9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
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 */
26 package jdk.internal.foreign.abi.x64.windows;
27
28 import jdk.incubator.foreign.CSupport;
29 import jdk.incubator.foreign.MemoryAddress;
30 import jdk.incubator.foreign.MemoryHandles;
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.SharedUtils.SimpleVaArg;
35
36 import java.lang.invoke.VarHandle;
37 import java.util.ArrayList;
38 import java.util.List;
39
40 import static jdk.incubator.foreign.CSupport.Win64.C_POINTER;
41 import static jdk.incubator.foreign.MemorySegment.CLOSE;
42 import static jdk.incubator.foreign.MemorySegment.READ;
43
44 // see vadefs.h (VC header)
45 //
46 // in short
47 // -> va_list is just a pointer to a buffer with 64 bit entries.
48 // -> non-power-of-two-sized, or larger than 64 bit types passed by reference.
49 // -> other types passed in 64 bit slots by normal function calling convention.
50 //
51 // X64 va_arg impl:
52 //
53 // typedef char* va_list;
54 //
55 // #define __crt_va_arg(ap, t) \
56 // ((sizeof(t) > sizeof(__int64) || (sizeof(t) & (sizeof(t) - 1)) != 0) \
57 // ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64)) \
58 // : *(t* )((ap += sizeof(__int64)) - sizeof(__int64)))
59 //
60 class WinVaList implements CSupport.VaList {
61 public static final Class<?> CARRIER = MemoryAddress.class;
62 private static final long VA_SLOT_SIZE_BYTES = 8;
63 private static final VarHandle VH_address = MemoryHandles.asAddressVarHandle(C_POINTER.varHandle(long.class));
64
65 private final MemorySegment segment;
66 private MemoryAddress ptr;
67 private final List<MemorySegment> copies;
68
69 WinVaList(MemorySegment segment) {
70 this(segment, new ArrayList<>());
71 }
72
73 WinVaList(MemorySegment segment, List<MemorySegment> copies) {
74 this.segment = segment;
75 this.ptr = segment.baseAddress();
76 this.copies = copies;
77 }
78
79 @Override
80 public int vargAsInt(MemoryLayout layout) {
81 return (int) read(int.class, layout);
82 }
83
84 @Override
85 public long vargAsLong(MemoryLayout layout) {
86 return (long) read(long.class, layout);
87 }
88
89 @Override
90 public double vargAsDouble(MemoryLayout layout) {
91 return (double) read(double.class, layout);
92 }
93
94 @Override
95 public MemoryAddress vargAsAddress(MemoryLayout layout) {
96 return (MemoryAddress) read(MemoryAddress.class, layout);
97 }
98
127 VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
128 res = reader.get(ptr);
129 }
130 ptr = ptr.addOffset(VA_SLOT_SIZE_BYTES);
131 return res;
132 }
133
134 @Override
135 public void skip(MemoryLayout... layouts) {
136 ptr = ptr.addOffset(layouts.length * VA_SLOT_SIZE_BYTES);
137 }
138
139 static WinVaList ofAddress(MemoryAddress addr) {
140 return new WinVaList(MemorySegment.ofNativeRestricted(addr, Long.MAX_VALUE, Thread.currentThread(), null, null));
141 }
142
143 static Builder builder() {
144 return new Builder();
145 }
146
147 MemorySegment getSegment() {
148 return segment;
149 }
150
151 @Override
152 public void close() {
153 segment.close();
154 copies.forEach(MemorySegment::close);
155 }
156
157 @Override
158 public CSupport.VaList copy() {
159 return WinVaList.ofAddress(ptr);
160 }
161
162 @Override
163 public MemoryAddress address() {
164 return ptr;
165 }
166
167 @Override
168 public boolean isAlive() {
169 return segment.isAlive();
170 }
171
172 static class Builder implements CSupport.VaList.Builder {
173
174 private final List<SimpleVaArg> args = new ArrayList<>();
175
176 private Builder arg(Class<?> carrier, MemoryLayout layout, Object value) {
177 SharedUtils.checkCompatibleType(carrier, layout, Windowsx64Linker.ADDRESS_SIZE);
178 args.add(new SimpleVaArg(carrier, layout, value));
179 return this;
180 }
181
182 @Override
183 public Builder vargFromInt(MemoryLayout layout, int value) {
184 return arg(int.class, layout, value);
185 }
186
187 @Override
188 public Builder vargFromLong(MemoryLayout layout, long value) {
189 return arg(long.class, layout, value);
190 }
191
192 @Override
193 public Builder vargFromDouble(MemoryLayout layout, double value) {
194 return arg(double.class, layout, value);
195 }
196
197 @Override
198 public Builder vargFromAddress(MemoryLayout layout, MemoryAddress value) {
199 return arg(MemoryAddress.class, layout, value);
200 }
201
202 @Override
203 public Builder vargFromSegment(MemoryLayout layout, MemorySegment value) {
204 return arg(MemorySegment.class, layout, value);
205 }
206
207 public WinVaList build() {
208 MemorySegment ms = MemorySegment.allocateNative(VA_SLOT_SIZE_BYTES * args.size());
209 List<MemorySegment> copies = new ArrayList<>();
210
211 MemoryAddress addr = ms.baseAddress();
212 for (SimpleVaArg arg : args) {
213 if (arg.carrier == MemorySegment.class) {
214 MemorySegment msArg = ((MemorySegment) arg.value);
215 TypeClass typeClass = TypeClass.typeClassFor(arg.layout);
216 switch (typeClass) {
217 case STRUCT_REFERENCE -> {
218 MemorySegment copy = MemorySegment.allocateNative(arg.layout);
219 copy.copyFrom(msArg); // by-value
220 copies.add(copy);
221 VH_address.set(addr, copy.baseAddress());
222 }
223 case STRUCT_REGISTER -> {
224 MemorySegment slice = ms.asSlice(addr.segmentOffset(), VA_SLOT_SIZE_BYTES);
225 slice.copyFrom(msArg);
226 }
227 default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass);
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
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 */
26 package jdk.internal.foreign.abi.x64.windows;
27
28 import jdk.incubator.foreign.CSupport;
29 import jdk.incubator.foreign.CSupport.VaList;
30 import jdk.incubator.foreign.MemoryAddress;
31 import jdk.incubator.foreign.MemoryHandles;
32 import jdk.incubator.foreign.MemoryLayout;
33 import jdk.incubator.foreign.MemorySegment;
34 import jdk.internal.foreign.abi.SharedUtils;
35 import jdk.internal.foreign.abi.SharedUtils.SimpleVaArg;
36
37 import java.lang.invoke.VarHandle;
38 import java.util.ArrayList;
39 import java.util.List;
40
41 import static jdk.incubator.foreign.CSupport.Win64.C_POINTER;
42 import static jdk.incubator.foreign.MemorySegment.CLOSE;
43 import static jdk.incubator.foreign.MemorySegment.READ;
44
45 // see vadefs.h (VC header)
46 //
47 // in short
48 // -> va_list is just a pointer to a buffer with 64 bit entries.
49 // -> non-power-of-two-sized, or larger than 64 bit types passed by reference.
50 // -> other types passed in 64 bit slots by normal function calling convention.
51 //
52 // X64 va_arg impl:
53 //
54 // typedef char* va_list;
55 //
56 // #define __crt_va_arg(ap, t) \
57 // ((sizeof(t) > sizeof(__int64) || (sizeof(t) & (sizeof(t) - 1)) != 0) \
58 // ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64)) \
59 // : *(t* )((ap += sizeof(__int64)) - sizeof(__int64)))
60 //
61 class WinVaList implements VaList {
62 public static final Class<?> CARRIER = MemoryAddress.class;
63 private static final long VA_SLOT_SIZE_BYTES = 8;
64 private static final VarHandle VH_address = MemoryHandles.asAddressVarHandle(C_POINTER.varHandle(long.class));
65
66 private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemoryAddress.NULL);
67
68 private final MemorySegment segment;
69 private MemoryAddress ptr;
70 private final List<MemorySegment> copies;
71
72 WinVaList(MemorySegment segment) {
73 this(segment, new ArrayList<>());
74 }
75
76 WinVaList(MemorySegment segment, List<MemorySegment> copies) {
77 this.segment = segment;
78 this.ptr = segment.baseAddress();
79 this.copies = copies;
80 }
81
82 public static final VaList empty() {
83 return EMPTY;
84 }
85
86 @Override
87 public int vargAsInt(MemoryLayout layout) {
88 return (int) read(int.class, layout);
89 }
90
91 @Override
92 public long vargAsLong(MemoryLayout layout) {
93 return (long) read(long.class, layout);
94 }
95
96 @Override
97 public double vargAsDouble(MemoryLayout layout) {
98 return (double) read(double.class, layout);
99 }
100
101 @Override
102 public MemoryAddress vargAsAddress(MemoryLayout layout) {
103 return (MemoryAddress) read(MemoryAddress.class, layout);
104 }
105
134 VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
135 res = reader.get(ptr);
136 }
137 ptr = ptr.addOffset(VA_SLOT_SIZE_BYTES);
138 return res;
139 }
140
141 @Override
142 public void skip(MemoryLayout... layouts) {
143 ptr = ptr.addOffset(layouts.length * VA_SLOT_SIZE_BYTES);
144 }
145
146 static WinVaList ofAddress(MemoryAddress addr) {
147 return new WinVaList(MemorySegment.ofNativeRestricted(addr, Long.MAX_VALUE, Thread.currentThread(), null, null));
148 }
149
150 static Builder builder() {
151 return new Builder();
152 }
153
154 @Override
155 public void close() {
156 segment.close();
157 copies.forEach(MemorySegment::close);
158 }
159
160 @Override
161 public VaList copy() {
162 return WinVaList.ofAddress(ptr);
163 }
164
165 @Override
166 public MemoryAddress address() {
167 return ptr;
168 }
169
170 @Override
171 public boolean isAlive() {
172 return segment.isAlive();
173 }
174
175 static class Builder implements VaList.Builder {
176
177 private final List<SimpleVaArg> args = new ArrayList<>();
178
179 private Builder arg(Class<?> carrier, MemoryLayout layout, Object value) {
180 SharedUtils.checkCompatibleType(carrier, layout, Windowsx64Linker.ADDRESS_SIZE);
181 args.add(new SimpleVaArg(carrier, layout, value));
182 return this;
183 }
184
185 @Override
186 public Builder vargFromInt(MemoryLayout layout, int value) {
187 return arg(int.class, layout, value);
188 }
189
190 @Override
191 public Builder vargFromLong(MemoryLayout layout, long value) {
192 return arg(long.class, layout, value);
193 }
194
195 @Override
196 public Builder vargFromDouble(MemoryLayout layout, double value) {
197 return arg(double.class, layout, value);
198 }
199
200 @Override
201 public Builder vargFromAddress(MemoryLayout layout, MemoryAddress value) {
202 return arg(MemoryAddress.class, layout, value);
203 }
204
205 @Override
206 public Builder vargFromSegment(MemoryLayout layout, MemorySegment value) {
207 return arg(MemorySegment.class, layout, value);
208 }
209
210 public VaList build() {
211 if (args.isEmpty()) {
212 return EMPTY;
213 }
214 MemorySegment ms = MemorySegment.allocateNative(VA_SLOT_SIZE_BYTES * args.size());
215 List<MemorySegment> copies = new ArrayList<>();
216
217 MemoryAddress addr = ms.baseAddress();
218 for (SimpleVaArg arg : args) {
219 if (arg.carrier == MemorySegment.class) {
220 MemorySegment msArg = ((MemorySegment) arg.value);
221 TypeClass typeClass = TypeClass.typeClassFor(arg.layout);
222 switch (typeClass) {
223 case STRUCT_REFERENCE -> {
224 MemorySegment copy = MemorySegment.allocateNative(arg.layout);
225 copy.copyFrom(msArg); // by-value
226 copies.add(copy);
227 VH_address.set(addr, copy.baseAddress());
228 }
229 case STRUCT_REGISTER -> {
230 MemorySegment slice = ms.asSlice(addr.segmentOffset(), VA_SLOT_SIZE_BYTES);
231 slice.copyFrom(msArg);
232 }
233 default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass);
|