13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.foreign.abi.x64.sysv;
26
27 import jdk.incubator.foreign.CSupport;
28 import jdk.incubator.foreign.ForeignLinker;
29 import jdk.incubator.foreign.FunctionDescriptor;
30 import jdk.incubator.foreign.MemoryAddress;
31 import jdk.incubator.foreign.MemoryLayout;
32 import jdk.incubator.foreign.MemorySegment;
33 import jdk.internal.foreign.abi.UpcallStubs;
34
35 import java.lang.invoke.MethodHandle;
36 import java.lang.invoke.MethodHandles;
37 import java.lang.invoke.MethodType;
38 import java.util.Optional;
39 import java.util.function.Consumer;
40
41 import static jdk.incubator.foreign.CSupport.*;
42
43 /**
44 * ABI implementation based on System V ABI AMD64 supplement v.0.99.6
45 */
46 public class SysVx64Linker implements ForeignLinker {
47 public static final int MAX_INTEGER_ARGUMENT_REGISTERS = 6;
48 public static final int MAX_INTEGER_RETURN_REGISTERS = 2;
49 public static final int MAX_VECTOR_ARGUMENT_REGISTERS = 8;
50 public static final int MAX_VECTOR_RETURN_REGISTERS = 2;
51 public static final int MAX_X87_RETURN_REGISTERS = 2;
52
53 private static SysVx64Linker instance;
54
55 static final long ADDRESS_SIZE = 64; // bits
56
57 private static final MethodHandle MH_unboxVaList;
58 private static final MethodHandle MH_boxVaList;
59
60 static {
61 try {
62 MethodHandles.Lookup lookup = MethodHandles.lookup();
63 MH_unboxVaList = lookup.findStatic(SysVx64Linker.class, "unboxVaList",
64 MethodType.methodType(MemoryAddress.class, CSupport.VaList.class));
65 MH_boxVaList = lookup.findStatic(SysVx64Linker.class, "boxVaList",
66 MethodType.methodType(VaList.class, MemoryAddress.class));
67 } catch (ReflectiveOperationException e) {
68 throw new ExceptionInInitializerError(e);
69 }
70 }
71
72 public static SysVx64Linker getInstance() {
73 if (instance == null) {
74 instance = new SysVx64Linker();
75 }
76 return instance;
77 }
78
79 public static VaList newVaList(Consumer<VaList.Builder> actions) {
80 SysVVaList.Builder builder = SysVVaList.builder();
81 actions.accept(builder);
82 return builder.build();
83 }
84
85 private static MethodType convertVaListCarriers(MethodType mt) {
86 Class<?>[] params = new Class<?>[mt.parameterCount()];
87 for (int i = 0; i < params.length; i++) {
88 Class<?> pType = mt.parameterType(i);
89 params[i] = ((pType == CSupport.VaList.class) ? SysVVaList.CARRIER : pType);
90 }
91 return MethodType.methodType(mt.returnType(), params);
92 }
93
94 private static MethodHandle unxboxVaLists(MethodType type, MethodHandle handle) {
95 for (int i = 0; i < type.parameterCount(); i++) {
96 if (type.parameterType(i) == VaList.class) {
97 handle = MethodHandles.filterArguments(handle, i, MH_unboxVaList);
98 }
99 }
100 return handle;
101 }
102
103 @Override
104 public MethodHandle downcallHandle(MemoryAddress symbol, MethodType type, FunctionDescriptor function) {
105 MethodType llMt = convertVaListCarriers(type);
106 MethodHandle handle = CallArranger.arrangeDowncall(symbol, llMt, function);
107 handle = unxboxVaLists(type, handle);
108 return handle;
109 }
110
111 private static MethodHandle boxVaLists(MethodHandle handle) {
112 MethodType type = handle.type();
113 for (int i = 0; i < type.parameterCount(); i++) {
114 if (type.parameterType(i) == VaList.class) {
115 handle = MethodHandles.filterArguments(handle, i, MH_boxVaList);
116 }
117 }
118 return handle;
119 }
120
121 @Override
122 public MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function) {
123 target = boxVaLists(target);
124 return UpcallStubs.upcallAddress(CallArranger.arrangeUpcall(target, target.type(), function));
125 }
126
127 @Override
128 public String name() {
129 return SysV.NAME;
130 }
131
132 static Optional<ArgumentClassImpl> argumentClassFor(MemoryLayout layout) {
133 @SuppressWarnings({"unchecked", "rawtypes"})
134 Optional<SysV.ArgumentClass> argClassOpt =
135 (Optional<SysV.ArgumentClass>)(Optional)layout.attribute(SysV.CLASS_ATTRIBUTE_NAME);
136 return argClassOpt.map(argClass -> switch (argClass) {
137 case INTEGER -> ArgumentClassImpl.INTEGER;
138 case SSE -> ArgumentClassImpl.SSE;
139 case X87 -> ArgumentClassImpl.X87;
140 case COMPLEX_87 -> ArgumentClassImpl.COMPLEX_X87;
141 case POINTER -> ArgumentClassImpl.POINTER;
142 default -> null;
143 });
144 }
145
146 private static MemoryAddress unboxVaList(CSupport.VaList list) {
147 return ((SysVVaList) list).getSegment().baseAddress();
148 }
149
150 private static CSupport.VaList boxVaList(MemoryAddress ma) {
151 return SysVVaList.ofAddress(ma);
152 }
153
154 public static VaList newVaListOfAddress(MemoryAddress ma) {
155 return SysVVaList.ofAddress(ma);
156 }
157 }
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.foreign.abi.x64.sysv;
26
27 import jdk.incubator.foreign.CSupport;
28 import jdk.incubator.foreign.ForeignLinker;
29 import jdk.incubator.foreign.FunctionDescriptor;
30 import jdk.incubator.foreign.MemoryAddress;
31 import jdk.incubator.foreign.MemoryLayout;
32 import jdk.incubator.foreign.MemorySegment;
33 import jdk.internal.foreign.abi.SharedUtils;
34 import jdk.internal.foreign.abi.UpcallStubs;
35
36 import java.lang.invoke.MethodHandle;
37 import java.lang.invoke.MethodHandles;
38 import java.lang.invoke.MethodType;
39 import java.util.Optional;
40 import java.util.function.Consumer;
41
42 import static jdk.incubator.foreign.CSupport.*;
43
44 /**
45 * ABI implementation based on System V ABI AMD64 supplement v.0.99.6
46 */
47 public class SysVx64Linker implements ForeignLinker {
48 public static final int MAX_INTEGER_ARGUMENT_REGISTERS = 6;
49 public static final int MAX_INTEGER_RETURN_REGISTERS = 2;
50 public static final int MAX_VECTOR_ARGUMENT_REGISTERS = 8;
51 public static final int MAX_VECTOR_RETURN_REGISTERS = 2;
52 public static final int MAX_X87_RETURN_REGISTERS = 2;
53
54 private static SysVx64Linker instance;
55
56 static final long ADDRESS_SIZE = 64; // bits
57
58 private static final MethodHandle MH_unboxVaList;
59 private static final MethodHandle MH_boxVaList;
60
61 static {
62 try {
63 MethodHandles.Lookup lookup = MethodHandles.lookup();
64 MH_unboxVaList = lookup.findVirtual(CSupport.VaList.class, "address",
65 MethodType.methodType(MemoryAddress.class));
66 MH_boxVaList = lookup.findStatic(SysVx64Linker.class, "newVaListOfAddress",
67 MethodType.methodType(VaList.class, MemoryAddress.class));
68 } catch (ReflectiveOperationException e) {
69 throw new ExceptionInInitializerError(e);
70 }
71 }
72
73 public static SysVx64Linker getInstance() {
74 if (instance == null) {
75 instance = new SysVx64Linker();
76 }
77 return instance;
78 }
79
80 public static VaList newVaList(Consumer<VaList.Builder> actions) {
81 SysVVaList.Builder builder = SysVVaList.builder();
82 actions.accept(builder);
83 return builder.build();
84 }
85
86 @Override
87 public MethodHandle downcallHandle(MemoryAddress symbol, MethodType type, FunctionDescriptor function) {
88 MethodType llMt = SharedUtils.convertVaListCarriers(type, SysVVaList.CARRIER);
89 MethodHandle handle = CallArranger.arrangeDowncall(symbol, llMt, function);
90 handle = SharedUtils.unboxVaLists(type, handle, MH_unboxVaList);
91 return handle;
92 }
93
94 @Override
95 public MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function) {
96 target = SharedUtils.boxVaLists(target, MH_boxVaList);
97 return UpcallStubs.upcallAddress(CallArranger.arrangeUpcall(target, target.type(), function));
98 }
99
100 @Override
101 public String name() {
102 return SysV.NAME;
103 }
104
105 static Optional<ArgumentClassImpl> argumentClassFor(MemoryLayout layout) {
106 @SuppressWarnings({"unchecked", "rawtypes"})
107 Optional<SysV.ArgumentClass> argClassOpt =
108 (Optional<SysV.ArgumentClass>)(Optional)layout.attribute(SysV.CLASS_ATTRIBUTE_NAME);
109 return argClassOpt.map(argClass -> switch (argClass) {
110 case INTEGER -> ArgumentClassImpl.INTEGER;
111 case SSE -> ArgumentClassImpl.SSE;
112 case X87 -> ArgumentClassImpl.X87;
113 case COMPLEX_87 -> ArgumentClassImpl.COMPLEX_X87;
114 case POINTER -> ArgumentClassImpl.POINTER;
115 default -> null;
116 });
117 }
118
119 public static VaList newVaListOfAddress(MemoryAddress ma) {
120 return SysVVaList.ofAddress(ma);
121 }
122
123 public static VaList emptyVaList() {
124 return SysVVaList.empty();
125 }
126 }
|