|
17 | 17 | import org.swift.swiftkit.SwiftHeapObject;
|
18 | 18 |
|
19 | 19 | import java.lang.foreign.*;
|
| 20 | +import java.lang.foreign.MemoryLayout.PathElement; |
20 | 21 | import java.lang.invoke.MethodHandle;
|
21 | 22 | import java.util.Arrays;
|
22 | 23 | import java.util.stream.Collectors;
|
@@ -200,7 +201,7 @@ public static MemorySegment getTypeByName(String string) {
|
200 | 201 | */
|
201 | 202 | private static class swift_getTypeByMangledNameInEnvironment {
|
202 | 203 | public static final FunctionDescriptor DESC = FunctionDescriptor.of(
|
203 |
| - /*returns=*/ValueLayout.ADDRESS, |
| 204 | + /*returns=*/SWIFT_POINTER, |
204 | 205 | ValueLayout.ADDRESS,
|
205 | 206 | ValueLayout.JAVA_INT,
|
206 | 207 | ValueLayout.ADDRESS,
|
@@ -230,4 +231,121 @@ public static MemorySegment getTypeByMangledNameInEnvironment(String string) {
|
230 | 231 | throw new AssertionError("should not reach here", ex$);
|
231 | 232 | }
|
232 | 233 | }
|
| 234 | + |
| 235 | + /** |
| 236 | + * The value layout for Swift's Int type, which is a signed type that follows |
| 237 | + * the size of a pointer (aka C's ptrdiff_t). |
| 238 | + */ |
| 239 | + public static ValueLayout SWIFT_INT = (ValueLayout.ADDRESS.byteSize() == 4) ? |
| 240 | + ValueLayout.JAVA_INT : ValueLayout.JAVA_LONG; |
| 241 | + |
| 242 | + /** |
| 243 | + * The value layout for Swift's UInt type, which is an unsigned type that follows |
| 244 | + * the size of a pointer (aka C's size_t). Java does not have unsigned integer |
| 245 | + * types in general, so we use the layout for Swift's Int. |
| 246 | + */ |
| 247 | + public static ValueLayout SWIFT_UINT = SWIFT_INT; |
| 248 | + |
| 249 | + /** |
| 250 | + * Read a Swift.Int value from memory at the given offset and translate it into a Java long. |
| 251 | + * |
| 252 | + * This function copes with the fact that a Swift.Int might be 32 or 64 bits. |
| 253 | + */ |
| 254 | + public static final long getSwiftInt(MemorySegment memorySegment, long offset) { |
| 255 | + if (SWIFT_INT == ValueLayout.JAVA_LONG) { |
| 256 | + return memorySegment.get(ValueLayout.JAVA_LONG, offset); |
| 257 | + } else { |
| 258 | + return memorySegment.get(ValueLayout.JAVA_INT, offset); |
| 259 | + } |
| 260 | + } |
| 261 | + |
| 262 | + /** |
| 263 | + * Value witness table layout. |
| 264 | + */ |
| 265 | + public static final MemoryLayout valueWitnessTableLayout = MemoryLayout.structLayout( |
| 266 | + ValueLayout.ADDRESS.withName("initializeBufferWithCopyOfBuffer"), |
| 267 | + ValueLayout.ADDRESS.withName("destroy"), |
| 268 | + ValueLayout.ADDRESS.withName("initializeWithCopy"), |
| 269 | + ValueLayout.ADDRESS.withName("assignWithCopy"), |
| 270 | + ValueLayout.ADDRESS.withName("initializeWithTake"), |
| 271 | + ValueLayout.ADDRESS.withName("assignWithTake"), |
| 272 | + ValueLayout.ADDRESS.withName("getEnumTagSinglePayload"), |
| 273 | + ValueLayout.ADDRESS.withName("storeEnumTagSinglePayload"), |
| 274 | + SwiftKit.SWIFT_INT.withName("size"), |
| 275 | + SwiftKit.SWIFT_INT.withName("stride"), |
| 276 | + SwiftKit.SWIFT_UINT.withName("flags"), |
| 277 | + SwiftKit.SWIFT_UINT.withName("extraInhabitantCount") |
| 278 | + ).withName("SwiftValueWitnessTable"); |
| 279 | + |
| 280 | + /** |
| 281 | + * Offset for the "size" field within the value witness table. |
| 282 | + */ |
| 283 | + static final long valueWitnessTable$size$offset = |
| 284 | + valueWitnessTableLayout.byteOffset(PathElement.groupElement("size")); |
| 285 | + |
| 286 | + /** |
| 287 | + * Offset for the "stride" field within the value witness table. |
| 288 | + */ |
| 289 | + static final long valueWitnessTable$stride$offset = |
| 290 | + valueWitnessTableLayout.byteOffset(PathElement.groupElement("stride")); |
| 291 | + |
| 292 | + /** |
| 293 | + * Offset for the "flags" field within the value witness table. |
| 294 | + */ |
| 295 | + static final long valueWitnessTable$flags$offset = |
| 296 | + valueWitnessTableLayout.byteOffset(PathElement.groupElement("flags")); |
| 297 | + |
| 298 | + /** |
| 299 | + * Type metadata pointer. |
| 300 | + */ |
| 301 | + public static final StructLayout fullTypeMetadataLayout = MemoryLayout.structLayout( |
| 302 | + SWIFT_POINTER.withName("vwt") |
| 303 | + ).withName("SwiftFullTypeMetadata"); |
| 304 | + |
| 305 | + /** |
| 306 | + * Offset for the "vwt" field within the full type metadata. |
| 307 | + */ |
| 308 | + static final long fullTypeMetadata$vwt$offset = |
| 309 | + fullTypeMetadataLayout.byteOffset(PathElement.groupElement("vwt")); |
| 310 | + |
| 311 | + /** |
| 312 | + * Given the address of Swift type metadata for a type, return the addres |
| 313 | + * of the "full" type metadata that can be accessed via fullTypeMetadataLayout. |
| 314 | + */ |
| 315 | + public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { |
| 316 | + return MemorySegment.ofAddress(typeMetadata.address() - SWIFT_POINTER.byteSize()) |
| 317 | + .reinterpret(fullTypeMetadataLayout.byteSize()); |
| 318 | + } |
| 319 | + |
| 320 | + /** |
| 321 | + * Given the address of Swift type's metadata, return the address that |
| 322 | + * references the value witness table for the type. |
| 323 | + */ |
| 324 | + public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { |
| 325 | + return fullTypeMetadata(typeMetadata).get(SWIFT_POINTER, fullTypeMetadata$vwt$offset); |
| 326 | + } |
| 327 | + |
| 328 | + /** |
| 329 | + * Determine the size of a Swift type given its type metadata. |
| 330 | + */ |
| 331 | + public static long sizeOfSwiftType(MemorySegment typeMetadata) { |
| 332 | + return getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$size$offset); |
| 333 | + } |
| 334 | + |
| 335 | + /** |
| 336 | + * Determine the stride of a Swift type given its type metadata, which is |
| 337 | + * how many bytes are between successive elements of this type within an |
| 338 | + * array. It is >= the size. |
| 339 | + */ |
| 340 | + public static long strideOfSwiftType(MemorySegment typeMetadata) { |
| 341 | + return getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$stride$offset); |
| 342 | + } |
| 343 | + |
| 344 | + /** |
| 345 | + * Determine the alignment of the given Swift type. |
| 346 | + */ |
| 347 | + public static long alignmentOfSwiftType(MemorySegment typeMetadata) { |
| 348 | + long flags = getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$flags$offset); |
| 349 | + return (flags & 0xFF) + 1; |
| 350 | + } |
233 | 351 | }
|
0 commit comments