Skip to content

Commit 525001f

Browse files
committed
Support key paths on 32-bit platforms.
I had optimistically written the code here optimistically hoping swiftlang#7837 would land in time for me to merge, but that didn't happen, so adjust some things to match the current 12-byte object header size on 32-bit, and introduce some ABI constants for the expected 32- and 64-bit object header sizes we can assert against so that we have some robustness when it eventually changes again. Implements rdar://problem/31768303.
1 parent e2fdea9 commit 525001f

File tree

10 files changed

+206
-140
lines changed

10 files changed

+206
-140
lines changed

include/swift/ABI/HeapObject.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===--- HeapObject.h - ABI constants for heap objects -----------*- C++ *-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Constants used in the layout of heap objects.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef __SWIFT_ABI_HEAPOBJECT_H__
18+
#define __SWIFT_ABI_HEAPOBJECT_H__
19+
20+
#include "../../../stdlib/public/SwiftShims/HeapObject.h"
21+
22+
#endif // __SWIFT_ABI_HEAPOBJECT_H__

lib/IRGen/GenKeyPath.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/SIL/SILLocation.h"
3131
#include "swift/SIL/TypeLowering.h"
3232
#include "swift/ABI/KeyPath.h"
33+
#include "swift/ABI/HeapObject.h"
3334
#include "swift/AST/ASTContext.h"
3435
#include "swift/AST/DiagnosticEngine.h"
3536
#include "swift/AST/DiagnosticsIRGen.h"
@@ -42,15 +43,6 @@ using namespace irgen;
4243
llvm::Constant *
4344
IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
4445
SILLocation diagLoc) {
45-
// TODO: Landing 32-bit key paths requires some runtime changes to get the
46-
// 8-byte object header.
47-
if (getPointerSize() != Size(8)) {
48-
Context.Diags.diagnose(diagLoc.getSourceLoc(),
49-
diag::not_implemented,
50-
"32-bit key paths");
51-
return llvm::UndefValue::get(Int8PtrTy);
52-
}
53-
5446
// See if we already emitted this.
5547
auto found = KeyPathPatterns.find(pattern);
5648
if (found != KeyPathPatterns.end())
@@ -119,13 +111,36 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
119111
fields.setPacked(true);
120112
// Add a zero-initialized header we can use for lazy initialization.
121113
fields.add(llvm::ConstantInt::get(SizeTy, 0));
122-
114+
115+
#ifndef NDEBUG
116+
auto startOfObject = fields.getNextOffsetFromGlobal();
117+
#endif
118+
123119
// Store references to metadata generator functions to generate the metadata
124120
// for the root and leaf. These sit in the "isa" and object header parts of
125121
// the final object.
126122
fields.add(emitMetadataGenerator(rootTy));
127123
fields.add(emitMetadataGenerator(valueTy));
128124

125+
// TODO: 32-bit still has a padding word
126+
if (SizeTy == Int32Ty) {
127+
fields.addInt32(0);
128+
}
129+
130+
#ifndef NDEBUG
131+
auto endOfObjectHeader = fields.getNextOffsetFromGlobal();
132+
unsigned expectedObjectHeaderSize;
133+
if (SizeTy == Int64Ty)
134+
expectedObjectHeaderSize = SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64;
135+
else if (SizeTy == Int32Ty)
136+
expectedObjectHeaderSize = SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32;
137+
else
138+
llvm_unreachable("unexpected pointer size");
139+
assert((endOfObjectHeader - startOfObject).getValue()
140+
== expectedObjectHeaderSize
141+
&& "key path pattern header size doesn't match heap object header size");
142+
#endif
143+
129144
// Add a pointer to the ObjC KVC compatibility string, if there is one, or
130145
// null otherwise.
131146
llvm::Constant *objcString;

stdlib/public/SwiftShims/GlobalObjects.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ SWIFT_RUNTIME_STDLIB_INTERFACE
8989
__swift_uint64_t _swift_stdlib_HashingDetail_fixedSeedOverride;
9090

9191
#ifdef __cplusplus
92+
93+
static_assert(std::is_pod<_SwiftEmptyArrayStorage>::value,
94+
"empty array type should be POD");
95+
static_assert(std::is_pod<_SwiftEmptyDictionaryStorage>::value,
96+
"empty dictionary type should be POD");
97+
static_assert(std::is_pod<_SwiftEmptySetStorage>::value,
98+
"empty set type should be POD");
99+
92100
}} // extern "C", namespace swift
93101
#endif
94102

stdlib/public/SwiftShims/HeapObject.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
#include "RefCount.h"
1616

17+
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 16
18+
// TODO: Should be 8
19+
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 12
20+
1721
#ifdef __cplusplus
1822
#include <type_traits>
1923
#include "swift/Basic/type_traits.h"
@@ -69,9 +73,17 @@ static_assert(swift::IsTriviallyConstructible<HeapObject>::value,
6973
"HeapObject must be trivially initializable");
7074
static_assert(std::is_trivially_destructible<HeapObject>::value,
7175
"HeapObject must be trivially destructible");
76+
7277
// FIXME: small header for 32-bit
7378
//static_assert(sizeof(HeapObject) == 2*sizeof(void*),
7479
// "HeapObject must be two pointers long");
80+
//
81+
static_assert(sizeof(HeapObject) ==
82+
(sizeof(void*) == 8 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 :
83+
sizeof(void*) == 4 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 :
84+
0 && "unexpected pointer size"),
85+
"HeapObject must match ABI heap object header size");
86+
7587
static_assert(alignof(HeapObject) == alignof(void*),
7688
"HeapObject must be pointer-aligned");
7789

stdlib/public/core/KeyPath.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,8 @@ public func _appendingKeyPaths<
14141414
}
14151415

14161416
// The distance in bytes from the address point of a KeyPath object to its
1417-
// buffer header. Includes the size of the Swift heap object header and
1417+
// buffer header. Includes the size of the Swift heap object header and the
1418+
// pointer to the KVC string.
14181419

14191420
internal var keyPathObjectHeaderSize: Int {
14201421
return MemoryLayout<HeapObject>.size + MemoryLayout<Int>.size
@@ -1437,7 +1438,7 @@ public func swift_getKeyPath(pattern: UnsafeMutableRawPointer,
14371438
// global object will itself always have the "trivial" bit set, since it
14381439
// never needs to be destroyed.)
14391440
// - Components may have unresolved forms that require instantiation.
1440-
// - The component type metadata pointers are unresolved, and instead
1441+
// - Type metadata pointers are unresolved, and instead
14411442
// point to accessor functions that instantiate the metadata.
14421443
//
14431444
// The pattern never precomputes the capabilities of the key path (readonly/
@@ -1649,7 +1650,7 @@ internal func _instantiateKeyPathBuffer(
16491650
) {
16501651
// NB: patternBuffer and destData alias when the pattern is instantiable
16511652
// in-line. Therefore, do not read from patternBuffer after the same position
1652-
// in destBuffer has been written to.
1653+
// in destData has been written to.
16531654

16541655
var patternBuffer = origPatternBuffer
16551656
let destHeaderPtr = origDestData.baseAddress.unsafelyUnwrapped

test/IRGen/keypaths.sil

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
2-
// TODO: 32-bit support
3-
// REQUIRES: PTRSIZE=64
42

53
sil_stage canonical
64
import Swift
@@ -64,7 +62,7 @@ sil_vtable C {}
6462
// -- 0x8000_0018 - instantiable in-line, size 4
6563
// CHECK-SAME: i32 -2147483644,
6664
// -- 0x4000_0000 (class) + offset of C.x
67-
// CHECK-32-SAME: i32 1073741832 }>
65+
// CHECK-32-SAME: i32 1073741836 }>
6866
// CHECK-64-SAME: i32 1073741840 }>
6967

7068
// -- %e: C.y
@@ -75,7 +73,7 @@ sil_vtable C {}
7573
// -- 0x8000_0018 - instantiable in-line, size 4
7674
// CHECK-SAME: i32 -2147483644,
7775
// -- 0x4000_0000 (class) + offset of C.y
78-
// CHECK-32-SAME: i32 1073741836 }>
76+
// CHECK-32-SAME: i32 1073741840 }>
7977
// CHECK-64-SAME: i32 1073741848 }>
8078

8179
// -- %f: C.z
@@ -86,7 +84,7 @@ sil_vtable C {}
8684
// -- 0x8000_0018 - instantiable in-line, size 4
8785
// CHECK-SAME: i32 -2147483644,
8886
// -- 0x4000_0000 (class) + offset of C.z
89-
// CHECK-32-SAME: i32 1073741848 }>
87+
// CHECK-32-SAME: i32 1073741852 }>
9088
// CHECK-64-SAME: i32 1073741872 }>
9189

9290
// -- %g: S.z.x
@@ -103,7 +101,7 @@ sil_vtable C {}
103101
// CHECK-64-SAME: i32 32,
104102
// CHECK: %swift.type* (i8*)*
105103
// -- 0x4000_0000 (class) + offset of C.x
106-
// CHECK-32-SAME: i32 1073741832 }>
104+
// CHECK-32-SAME: i32 1073741836 }>
107105
// CHECK-64-SAME: i32 1073741840 }>
108106

109107
// -- %h: C.z.x
@@ -116,7 +114,7 @@ sil_vtable C {}
116114
// -- 0x8000_0018 - instantiable in-line, size 16
117115
// CHECK-64-SAME: i32 -2147483632,
118116
// -- 0x4000_0000 (class) + offset of C.z
119-
// CHECK-32-SAME: i32 1073741848,
117+
// CHECK-32-SAME: i32 1073741852,
120118
// CHECK-64-SAME: i32 1073741872,
121119
// CHECK: %swift.type* (i8*)*
122120
// -- offset of S.x
@@ -130,7 +128,7 @@ sil_vtable C {}
130128
// -- 0x8000_0014 - instantiable in-line, size 20
131129
// CHECK-64-SAME: i32 -2147483628,
132130
// -- 0x8000_000c - instantiable in-line, size 12
133-
// CHECK-32-SAME: i32 -2147483640,
131+
// CHECK-32-SAME: i32 -2147483636,
134132
// -- 0x2000_0000 - computed, get-only, identified by function pointer, no args
135133
// CHECK-SAME: i32 536870912,
136134
// CHECK-SAME: void ()* @k_id,
@@ -144,7 +142,7 @@ sil_vtable C {}
144142
// -- 0x8000_001c - instantiable in-line, size 28
145143
// CHECK-64-SAME: i32 -2147483620,
146144
// -- 0x8000_0010 - instantiable in-line, size 16
147-
// CHECK-32-SAME: i32 -2147483636,
145+
// CHECK-32-SAME: i32 -2147483632,
148146
// -- 0x2a00_0000 - computed, settable, nonmutating, identified by vtable, no args
149147
// CHECK-SAME: i32 704643072,
150148
// CHECK-SAME: [[WORD]]
@@ -159,7 +157,7 @@ sil_vtable C {}
159157
// -- 0x8000_001c - instantiable in-line, size 28
160158
// CHECK-64-SAME: i32 -2147483620,
161159
// -- 0x8000_0010 - instantiable in-line, size 16
162-
// CHECK-32-SAME: i32 -2147483636,
160+
// CHECK-32-SAME: i32 -2147483632,
163161
// -- 0x3c00_0000 - computed, settable, nonmutating, identified by property offset, no args
164162
// CHECK-SAME: i32 1006632960,
165163
// CHECK-SAME: [[WORD]]

test/SILGen/keypaths.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// RUN: %target-swift-frontend -enable-experimental-keypaths -emit-silgen %s | %FileCheck %s
2-
// REQUIRES: PTRSIZE=64
32

43
struct S<T> {
54
var x: T

test/stdlib/KeyPath.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// RUN: %target-build-swift %s -Xfrontend -enable-experimental-keypaths -o %t/a.out
33
// RUN: %target-run %t/a.out
44
// REQUIRES: executable_test
5-
// REQUIRES: PTRSIZE=64
65

76
import StdlibUnittest
87

0 commit comments

Comments
 (0)