8314949: linux PPC64 Big Endian: Implementation of Foreign Function & Memory API
Reviewed-by: mcimadamore, jvernee
This commit is contained in:
parent
a01b3fb8e9
commit
f6c203e616
@ -47,7 +47,7 @@ bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const {
|
||||
}
|
||||
|
||||
bool ForeignGlobals::is_foreign_linker_supported() {
|
||||
#ifdef ABI_ELFv2
|
||||
#ifdef LINUX
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
|
@ -39,6 +39,7 @@ public enum CABI {
|
||||
LINUX_AARCH_64,
|
||||
MAC_OS_AARCH_64,
|
||||
WIN_AARCH_64,
|
||||
LINUX_PPC_64,
|
||||
LINUX_PPC_64_LE,
|
||||
LINUX_RISCV_64,
|
||||
LINUX_S390,
|
||||
@ -74,6 +75,10 @@ public enum CABI {
|
||||
// The Linux ABI follows the standard AAPCS ABI
|
||||
return LINUX_AARCH_64;
|
||||
}
|
||||
} else if (arch.equals("ppc64")) {
|
||||
if (OperatingSystem.isLinux()) {
|
||||
return LINUX_PPC_64;
|
||||
}
|
||||
} else if (arch.equals("ppc64le")) {
|
||||
if (OperatingSystem.isLinux()) {
|
||||
return LINUX_PPC_64_LE;
|
||||
|
@ -30,6 +30,7 @@ import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
|
||||
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
|
||||
import jdk.internal.foreign.abi.aarch64.windows.WindowsAArch64Linker;
|
||||
import jdk.internal.foreign.abi.fallback.FallbackLinker;
|
||||
import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64Linker;
|
||||
import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64leLinker;
|
||||
import jdk.internal.foreign.abi.riscv64.linux.LinuxRISCV64Linker;
|
||||
import jdk.internal.foreign.abi.s390.linux.LinuxS390Linker;
|
||||
@ -60,7 +61,8 @@ import java.util.Set;
|
||||
|
||||
public abstract sealed class AbstractLinker implements Linker permits LinuxAArch64Linker, MacOsAArch64Linker,
|
||||
SysVx64Linker, WindowsAArch64Linker,
|
||||
Windowsx64Linker, LinuxPPC64leLinker,
|
||||
Windowsx64Linker,
|
||||
LinuxPPC64Linker, LinuxPPC64leLinker,
|
||||
LinuxRISCV64Linker, LinuxS390Linker,
|
||||
FallbackLinker {
|
||||
|
||||
|
@ -276,6 +276,18 @@ public sealed interface Binding {
|
||||
return Dup.INSTANCE;
|
||||
}
|
||||
|
||||
static ShiftLeft shiftLeft(int shiftAmount) {
|
||||
if (shiftAmount <= 0)
|
||||
throw new IllegalArgumentException("shiftAmount must be positive");
|
||||
return new ShiftLeft(shiftAmount);
|
||||
}
|
||||
|
||||
static ShiftRight shiftRight(int shiftAmount) {
|
||||
if (shiftAmount <= 0)
|
||||
throw new IllegalArgumentException("shiftAmount must be positive");
|
||||
return new ShiftRight(shiftAmount);
|
||||
}
|
||||
|
||||
static Binding cast(Class<?> fromType, Class<?> toType) {
|
||||
if (fromType == int.class) {
|
||||
if (toType == boolean.class) {
|
||||
@ -286,6 +298,8 @@ public sealed interface Binding {
|
||||
return Cast.INT_TO_SHORT;
|
||||
} else if (toType == char.class) {
|
||||
return Cast.INT_TO_CHAR;
|
||||
} else if (toType == long.class) {
|
||||
return Cast.INT_TO_LONG;
|
||||
}
|
||||
} else if (toType == int.class) {
|
||||
if (fromType == boolean.class) {
|
||||
@ -296,6 +310,24 @@ public sealed interface Binding {
|
||||
return Cast.SHORT_TO_INT;
|
||||
} else if (fromType == char.class) {
|
||||
return Cast.CHAR_TO_INT;
|
||||
} else if (fromType == long.class) {
|
||||
return Cast.LONG_TO_INT;
|
||||
}
|
||||
} else if (fromType == long.class) {
|
||||
if (toType == byte.class) {
|
||||
return Cast.LONG_TO_BYTE;
|
||||
} else if (toType == short.class) {
|
||||
return Cast.LONG_TO_SHORT;
|
||||
} else if (toType == char.class) {
|
||||
return Cast.LONG_TO_CHAR;
|
||||
}
|
||||
} else if (toType == long.class) {
|
||||
if (fromType == byte.class) {
|
||||
return Cast.BYTE_TO_LONG;
|
||||
} else if (fromType == short.class) {
|
||||
return Cast.SHORT_TO_LONG;
|
||||
} else if (fromType == char.class) {
|
||||
return Cast.CHAR_TO_LONG;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown conversion: " + fromType + " -> " + toType);
|
||||
@ -387,6 +419,24 @@ public sealed interface Binding {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Converts to long if needed then shifts left by the given number of Bytes.
|
||||
public Binding.Builder shiftLeft(int shiftAmount, Class<?> type) {
|
||||
if (type != long.class) {
|
||||
bindings.add(Binding.cast(type, long.class));
|
||||
}
|
||||
bindings.add(Binding.shiftLeft(shiftAmount));
|
||||
return this;
|
||||
}
|
||||
|
||||
// Shifts right by the given number of Bytes then converts from long if needed.
|
||||
public Binding.Builder shiftRight(int shiftAmount, Class<?> type) {
|
||||
bindings.add(Binding.shiftRight(shiftAmount));
|
||||
if (type != long.class) {
|
||||
bindings.add(Binding.cast(long.class, type));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<Binding> build() {
|
||||
return List.copyOf(bindings);
|
||||
}
|
||||
@ -670,6 +720,52 @@ public sealed interface Binding {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ShiftLeft([shiftAmount])
|
||||
* Shifts the Bytes on the top of the operand stack (64 bit unsigned).
|
||||
* Shifts left by the given number of Bytes.
|
||||
*/
|
||||
record ShiftLeft(int shiftAmount) implements Binding {
|
||||
|
||||
@Override
|
||||
public void verify(Deque<Class<?>> stack) {
|
||||
Class<?> last = stack.pop();
|
||||
SharedUtils.checkType(last, long.class);
|
||||
stack.push(long.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpret(Deque<Object> stack, StoreFunc storeFunc,
|
||||
LoadFunc loadFunc, SegmentAllocator allocator) {
|
||||
long l = (long) stack.pop();
|
||||
l <<= (shiftAmount * Byte.SIZE);
|
||||
stack.push(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ShiftRight([shiftAmount])
|
||||
* Shifts the Bytes on the top of the operand stack (64 bit unsigned).
|
||||
* Shifts right by the given number of Bytes.
|
||||
*/
|
||||
record ShiftRight(int shiftAmount) implements Binding {
|
||||
|
||||
@Override
|
||||
public void verify(Deque<Class<?>> stack) {
|
||||
Class<?> last = stack.pop();
|
||||
SharedUtils.checkType(last, long.class);
|
||||
stack.push(long.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpret(Deque<Object> stack, StoreFunc storeFunc,
|
||||
LoadFunc loadFunc, SegmentAllocator allocator) {
|
||||
long l = (long) stack.pop();
|
||||
l >>>= (shiftAmount * Byte.SIZE);
|
||||
stack.push(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CAST([fromType], [toType])
|
||||
* Pop a [fromType] from the stack, convert it to [toType], and push the resulting
|
||||
@ -690,10 +786,21 @@ public sealed interface Binding {
|
||||
INT_TO_BYTE(int.class, byte.class),
|
||||
INT_TO_CHAR(int.class, char.class),
|
||||
INT_TO_SHORT(int.class, short.class),
|
||||
INT_TO_LONG(int.class, long.class),
|
||||
|
||||
BOOLEAN_TO_INT(boolean.class, int.class),
|
||||
BYTE_TO_INT(byte.class, int.class),
|
||||
CHAR_TO_INT(char.class, int.class),
|
||||
SHORT_TO_INT(short.class, int.class);
|
||||
SHORT_TO_INT(short.class, int.class),
|
||||
LONG_TO_INT(long.class, int.class),
|
||||
|
||||
LONG_TO_BYTE(long.class, byte.class),
|
||||
LONG_TO_SHORT(long.class, short.class),
|
||||
LONG_TO_CHAR(long.class, char.class),
|
||||
|
||||
BYTE_TO_LONG(byte.class, long.class),
|
||||
SHORT_TO_LONG(short.class, long.class),
|
||||
CHAR_TO_LONG(char.class, long.class);
|
||||
|
||||
private final Class<?> fromType;
|
||||
private final Class<?> toType;
|
||||
|
@ -39,6 +39,8 @@ import jdk.internal.foreign.abi.Binding.BufferStore;
|
||||
import jdk.internal.foreign.abi.Binding.Cast;
|
||||
import jdk.internal.foreign.abi.Binding.Copy;
|
||||
import jdk.internal.foreign.abi.Binding.Dup;
|
||||
import jdk.internal.foreign.abi.Binding.ShiftLeft;
|
||||
import jdk.internal.foreign.abi.Binding.ShiftRight;
|
||||
import jdk.internal.foreign.abi.Binding.UnboxAddress;
|
||||
import jdk.internal.foreign.abi.Binding.VMLoad;
|
||||
import jdk.internal.foreign.abi.Binding.VMStore;
|
||||
@ -463,6 +465,8 @@ public class BindingSpecializer {
|
||||
case BoxAddress boxAddress -> emitBoxAddress(boxAddress);
|
||||
case UnboxAddress unused -> emitUnboxAddress();
|
||||
case Dup unused -> emitDupBinding();
|
||||
case ShiftLeft shiftLeft -> emitShiftLeft(shiftLeft);
|
||||
case ShiftRight shiftRight -> emitShiftRight(shiftRight);
|
||||
case Cast cast -> emitCast(cast);
|
||||
}
|
||||
}
|
||||
@ -725,6 +729,20 @@ public class BindingSpecializer {
|
||||
pushType(dupType);
|
||||
}
|
||||
|
||||
private void emitShiftLeft(ShiftLeft shiftLeft) {
|
||||
popType(long.class);
|
||||
cb.constantInstruction(shiftLeft.shiftAmount() * Byte.SIZE);
|
||||
cb.lshl();
|
||||
pushType(long.class);
|
||||
}
|
||||
|
||||
private void emitShiftRight(ShiftRight shiftRight) {
|
||||
popType(long.class);
|
||||
cb.constantInstruction(shiftRight.shiftAmount() * Byte.SIZE);
|
||||
cb.lushr();
|
||||
pushType(long.class);
|
||||
}
|
||||
|
||||
private void emitCast(Cast cast) {
|
||||
Class<?> fromType = cast.fromType();
|
||||
Class<?> toType = cast.toType();
|
||||
@ -744,6 +762,11 @@ public class BindingSpecializer {
|
||||
case INT_TO_BYTE -> cb.i2b();
|
||||
case INT_TO_CHAR -> cb.i2c();
|
||||
case INT_TO_SHORT -> cb.i2s();
|
||||
case BYTE_TO_LONG, CHAR_TO_LONG, SHORT_TO_LONG, INT_TO_LONG -> cb.i2l();
|
||||
case LONG_TO_BYTE -> { cb.l2i(); cb.i2b(); }
|
||||
case LONG_TO_SHORT -> { cb.l2i(); cb.i2s(); }
|
||||
case LONG_TO_CHAR -> { cb.l2i(); cb.i2c(); }
|
||||
case LONG_TO_INT -> cb.l2i();
|
||||
case BOOLEAN_TO_INT, BYTE_TO_INT, CHAR_TO_INT, SHORT_TO_INT -> {
|
||||
// no-op in bytecode
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ import jdk.internal.foreign.abi.Binding.BufferStore;
|
||||
import jdk.internal.foreign.abi.Binding.Cast;
|
||||
import jdk.internal.foreign.abi.Binding.Copy;
|
||||
import jdk.internal.foreign.abi.Binding.Dup;
|
||||
import jdk.internal.foreign.abi.Binding.ShiftLeft;
|
||||
import jdk.internal.foreign.abi.Binding.ShiftRight;
|
||||
import jdk.internal.foreign.abi.Binding.UnboxAddress;
|
||||
import jdk.internal.foreign.abi.Binding.VMLoad;
|
||||
import jdk.internal.foreign.abi.Binding.VMStore;
|
||||
@ -220,6 +222,8 @@ public class CallingSequenceBuilder {
|
||||
case Copy unused -> true;
|
||||
case UnboxAddress unused -> true;
|
||||
case Dup unused -> true;
|
||||
case ShiftLeft unused -> true;
|
||||
case ShiftRight unused -> true;
|
||||
case Cast unused -> true;
|
||||
|
||||
case VMLoad unused -> false;
|
||||
@ -254,6 +258,8 @@ public class CallingSequenceBuilder {
|
||||
case Allocate unused -> true;
|
||||
case BoxAddress unused -> true;
|
||||
case Dup unused -> true;
|
||||
case ShiftLeft unused -> true;
|
||||
case ShiftRight unused -> true;
|
||||
case Cast unused -> true;
|
||||
|
||||
case VMStore unused -> false;
|
||||
|
@ -33,6 +33,7 @@ import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
|
||||
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
|
||||
import jdk.internal.foreign.abi.aarch64.windows.WindowsAArch64Linker;
|
||||
import jdk.internal.foreign.abi.fallback.FallbackLinker;
|
||||
import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64Linker;
|
||||
import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64leLinker;
|
||||
import jdk.internal.foreign.abi.riscv64.linux.LinuxRISCV64Linker;
|
||||
import jdk.internal.foreign.abi.s390.linux.LinuxS390Linker;
|
||||
@ -241,6 +242,7 @@ public final class SharedUtils {
|
||||
case LINUX_AARCH_64 -> LinuxAArch64Linker.getInstance();
|
||||
case MAC_OS_AARCH_64 -> MacOsAArch64Linker.getInstance();
|
||||
case WIN_AARCH_64 -> WindowsAArch64Linker.getInstance();
|
||||
case LINUX_PPC_64 -> LinuxPPC64Linker.getInstance();
|
||||
case LINUX_PPC_64_LE -> LinuxPPC64leLinker.getInstance();
|
||||
case LINUX_RISCV_64 -> LinuxRISCV64Linker.getInstance();
|
||||
case LINUX_S390 -> LinuxS390Linker.getInstance();
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.internal.foreign.abi.ppc64;
|
||||
|
||||
/**
|
||||
* PPC64 CallArranger specialized for ABI v1.
|
||||
*/
|
||||
public class ABIv1CallArranger extends CallArranger {
|
||||
|
||||
@Override
|
||||
protected boolean useABIv2() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -25,11 +25,13 @@
|
||||
*/
|
||||
package jdk.internal.foreign.abi.ppc64;
|
||||
|
||||
import jdk.internal.foreign.abi.ppc64.CallArranger;
|
||||
|
||||
/**
|
||||
* PPC64 CallArranger specialized for ABI v2.
|
||||
*/
|
||||
public class ABIv2CallArranger extends CallArranger {
|
||||
// Currently no specific content, but CallArranger detects usage of ABIv2 for this class.
|
||||
|
||||
@Override
|
||||
protected boolean useABIv2() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ import jdk.internal.foreign.abi.DowncallLinker;
|
||||
import jdk.internal.foreign.abi.LinkerOptions;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.VMStorage;
|
||||
import jdk.internal.foreign.abi.ppc64.ABIv2CallArranger;
|
||||
|
||||
import java.lang.foreign.AddressLayout;
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
@ -62,7 +61,7 @@ import static jdk.internal.foreign.abi.ppc64.PPC64Architecture.Regs.*;
|
||||
* public constants CallArranger.ABIv1/2.
|
||||
*/
|
||||
public abstract class CallArranger {
|
||||
final boolean useABIv2 = (this instanceof ABIv2CallArranger);
|
||||
final boolean useABIv2 = useABIv2();
|
||||
|
||||
private static final int STACK_SLOT_SIZE = 8;
|
||||
private static final int MAX_COPY_SIZE = 8;
|
||||
@ -90,8 +89,14 @@ public abstract class CallArranger {
|
||||
|
||||
protected CallArranger() {}
|
||||
|
||||
public static final CallArranger ABIv1 = new ABIv1CallArranger();
|
||||
public static final CallArranger ABIv2 = new ABIv2CallArranger();
|
||||
|
||||
/**
|
||||
* Select ABI version
|
||||
*/
|
||||
protected abstract boolean useABIv2();
|
||||
|
||||
public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) {
|
||||
return getBindings(mt, cDesc, forUpcall, LinkerOptions.empty());
|
||||
}
|
||||
@ -214,11 +219,23 @@ public abstract class CallArranger {
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* The struct is split into 8-byte chunks, and those chunks are passed in registers or on the stack.
|
||||
ABIv1 requires shifting if the struct occupies more than one 8-byte chunk and the last one is not full.
|
||||
Here's an example for passing an 11 byte struct with ABIv1:
|
||||
offset : 0 .... 32 ..... 64 ..... 96 .... 128
|
||||
values : xxxxxxxx|yyyyyyyy|zzzzzz??|???????? (can't touch bits 96..128)
|
||||
Load into int : V +--------+
|
||||
| |
|
||||
+--------+ |
|
||||
V V
|
||||
In register : ????????|??zzzzzz (LSBs are zz...z)
|
||||
Shift left : zzzzzz00|00000000 (LSBs are 00...0)
|
||||
Write long : V V
|
||||
Result : xxxxxxxx|yyyyyyyy|zzzzzz00|00000000
|
||||
*/
|
||||
|
||||
// Regular struct, no HFA.
|
||||
VMStorage[] structAlloc(MemoryLayout layout) {
|
||||
// TODO: Big Endian can't pass partially used slots correctly in some cases with:
|
||||
// !useABIv2 && layout.byteSize() > 8 && layout.byteSize() % 8 != 0
|
||||
|
||||
// Allocate enough gp slots (regs and stack) such that the struct fits in them.
|
||||
int numChunks = (int) Utils.alignUp(layout.byteSize(), MAX_COPY_SIZE) / MAX_COPY_SIZE;
|
||||
VMStorage[] result = new VMStorage[numChunks];
|
||||
@ -332,16 +349,26 @@ public abstract class CallArranger {
|
||||
case STRUCT_REGISTER -> {
|
||||
assert carrier == MemorySegment.class;
|
||||
VMStorage[] regs = storageCalculator.structAlloc(layout);
|
||||
final boolean isLargeABIv1Struct = !useABIv2 && layout.byteSize() > MAX_COPY_SIZE;
|
||||
long offset = 0;
|
||||
for (VMStorage storage : regs) {
|
||||
// Last slot may be partly used.
|
||||
final long size = Math.min(layout.byteSize() - offset, MAX_COPY_SIZE);
|
||||
int shiftAmount = 0;
|
||||
Class<?> type = SharedUtils.primitiveCarrierForSize(size, false);
|
||||
if (offset + size < layout.byteSize()) {
|
||||
bindings.dup();
|
||||
} else if (isLargeABIv1Struct) {
|
||||
// Last slot requires shift.
|
||||
shiftAmount = MAX_COPY_SIZE - (int) size;
|
||||
}
|
||||
bindings.bufferLoad(offset, type, (int) size);
|
||||
if (shiftAmount != 0) {
|
||||
bindings.shiftLeft(shiftAmount, type)
|
||||
.vmStore(storage, long.class);
|
||||
} else {
|
||||
bindings.vmStore(storage, type);
|
||||
}
|
||||
bindings.bufferLoad(offset, type, (int) size)
|
||||
.vmStore(storage, type);
|
||||
offset += size;
|
||||
}
|
||||
}
|
||||
@ -410,14 +437,25 @@ public abstract class CallArranger {
|
||||
assert carrier == MemorySegment.class;
|
||||
bindings.allocate(layout);
|
||||
VMStorage[] regs = storageCalculator.structAlloc(layout);
|
||||
final boolean isLargeABIv1Struct = !useABIv2 && layout.byteSize() > MAX_COPY_SIZE;
|
||||
long offset = 0;
|
||||
for (VMStorage storage : regs) {
|
||||
// Last slot may be partly used.
|
||||
final long size = Math.min(layout.byteSize() - offset, MAX_COPY_SIZE);
|
||||
int shiftAmount = 0;
|
||||
Class<?> type = SharedUtils.primitiveCarrierForSize(size, false);
|
||||
bindings.dup()
|
||||
.vmLoad(storage, type)
|
||||
.bufferStore(offset, type, (int) size);
|
||||
if (isLargeABIv1Struct && offset + size >= layout.byteSize()) {
|
||||
// Last slot requires shift.
|
||||
shiftAmount = MAX_COPY_SIZE - (int) size;
|
||||
}
|
||||
bindings.dup();
|
||||
if (shiftAmount != 0) {
|
||||
bindings.vmLoad(storage, long.class)
|
||||
.shiftRight(shiftAmount, type);
|
||||
} else {
|
||||
bindings.vmLoad(storage, type);
|
||||
}
|
||||
bindings.bufferStore(offset, type, (int) size);
|
||||
offset += size;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.internal.foreign.abi.ppc64.linux;
|
||||
|
||||
import jdk.internal.foreign.abi.AbstractLinker;
|
||||
import jdk.internal.foreign.abi.LinkerOptions;
|
||||
import jdk.internal.foreign.abi.ppc64.CallArranger;
|
||||
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public final class LinuxPPC64Linker extends AbstractLinker {
|
||||
|
||||
public static LinuxPPC64Linker getInstance() {
|
||||
final class Holder {
|
||||
private static final LinuxPPC64Linker INSTANCE = new LinuxPPC64Linker();
|
||||
}
|
||||
|
||||
return Holder.INSTANCE;
|
||||
}
|
||||
|
||||
private LinuxPPC64Linker() {
|
||||
// Ensure there is only one instance
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options) {
|
||||
return CallArranger.ABIv1.arrangeDowncall(inferredMethodType, function, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function, LinkerOptions options) {
|
||||
return CallArranger.ABIv1.arrangeUpcall(targetType, function, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteOrder linkerByteOrder() {
|
||||
return ByteOrder.BIG_ENDIAN;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user