Skip to content

Commit 7e99e84

Browse files
committed
Add an "addressable for dependencies" flag to value witness flags.
This may be useful for type layout of borrow fields in the future, should we decide that addressable-for-dependencies borrows should always be represented by a pointer. rdar://153650278
1 parent 66b8f35 commit 7e99e84

File tree

6 files changed

+116
-61
lines changed

6 files changed

+116
-61
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -165,18 +165,19 @@ class TargetValueWitnessFlags {
165165
// flags for the struct. (The "non-inline" and "has-extra-inhabitants" bits
166166
// still require additional fixup.)
167167
enum : uint32_t {
168-
AlignmentMask = 0x000000FF,
169-
// unused 0x0000FF00,
170-
IsNonPOD = 0x00010000,
171-
IsNonInline = 0x00020000,
172-
// unused 0x00040000,
173-
HasSpareBits = 0x00080000,
174-
IsNonBitwiseTakable = 0x00100000,
175-
HasEnumWitnesses = 0x00200000,
176-
Incomplete = 0x00400000,
177-
IsNonCopyable = 0x00800000,
178-
IsNonBitwiseBorrowable = 0x01000000,
179-
// unused 0xFE000000,
168+
AlignmentMask = 0x000000FF,
169+
// unused 0x0000FF00,
170+
IsNonPOD = 0x00010000,
171+
IsNonInline = 0x00020000,
172+
// unused 0x00040000,
173+
HasSpareBits = 0x00080000,
174+
IsNonBitwiseTakable = 0x00100000,
175+
HasEnumWitnesses = 0x00200000,
176+
Incomplete = 0x00400000,
177+
IsNonCopyable = 0x00800000,
178+
IsNonBitwiseBorrowable = 0x01000000,
179+
IsAddressableForDependencies = 0x02000000,
180+
// unused 0xFC000000,
180181
};
181182

182183
static constexpr const uint32_t MaxNumExtraInhabitants = 0x7FFFFFFF;
@@ -268,6 +269,19 @@ class TargetValueWitnessFlags {
268269
return TargetValueWitnessFlags((Data & ~IsNonCopyable) |
269270
(isCopyable ? 0 : IsNonCopyable));
270271
}
272+
273+
/// True if values of this type are addressable-for-dependencies, meaning
274+
/// that values of this type should be passed indirectly to functions that
275+
/// produce lifetime-dependent values that could possibly contain pointers
276+
/// to the inline storage of this type.
277+
bool isAddressableForDependencies() const {
278+
return Data & IsAddressableForDependencies;
279+
}
280+
constexpr TargetValueWitnessFlags withAddressableForDependencies(bool afd) const {
281+
return TargetValueWitnessFlags((Data & ~IsAddressableForDependencies) |
282+
(afd ? IsAddressableForDependencies : 0));
283+
}
284+
271285

272286
/// True if this type's binary representation is that of an enum, and the
273287
/// enum value witness table entries are available in this type's value

lib/IRGen/GenValueWitness.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,9 @@ struct BoundGenericTypeCharacteristics {
837837
FixedPacking packing;
838838
};
839839

840-
ValueWitnessFlags getValueWitnessFlags(const TypeInfo *TI, SILType concreteType,
840+
ValueWitnessFlags getValueWitnessFlags(IRGenModule &IGM,
841+
const TypeInfo *TI,
842+
SILType concreteType,
841843
FixedPacking packing) {
842844
ValueWitnessFlags flags;
843845

@@ -852,6 +854,12 @@ ValueWitnessFlags getValueWitnessFlags(const TypeInfo *TI, SILType concreteType,
852854
bool isBitwiseBorrowable =
853855
fixedTI->isBitwiseBorrowable(ResilienceExpansion::Maximal);
854856
assert(isBitwiseTakable || !isInline);
857+
bool isAddressableForDependencies =
858+
IGM.getSILModule().Types.getTypeLowering(concreteType,
859+
TypeExpansionContext::minimal())
860+
.getRecursiveProperties()
861+
.isAddressableForDependencies();
862+
855863
flags = flags.withAlignment(fixedTI->getFixedAlignment().getValue())
856864
.withPOD(fixedTI->isTriviallyDestroyable(ResilienceExpansion::Maximal))
857865
.withCopyable(fixedTI->isCopyable(ResilienceExpansion::Maximal))
@@ -864,7 +872,8 @@ ValueWitnessFlags getValueWitnessFlags(const TypeInfo *TI, SILType concreteType,
864872
// Swift prior to version 6 didn't have the
865873
// IsNotBitwiseBorrowable bit, so to avoid unnecessary variation
866874
// in metadata output, we only set the bit when needed.
867-
.withBitwiseBorrowable(!isBitwiseTakable || isBitwiseBorrowable);
875+
.withBitwiseBorrowable(!isBitwiseTakable || isBitwiseBorrowable)
876+
.withAddressableForDependencies(isAddressableForDependencies);
868877
} else {
869878
flags = flags.withIncomplete(true);
870879
}
@@ -1226,11 +1235,13 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
12261235
case ValueWitness::Flags: {
12271236
if (boundGenericCharacteristics)
12281237
return B.addInt32(
1229-
getValueWitnessFlags(boundGenericCharacteristics->TI,
1238+
getValueWitnessFlags(IGM,
1239+
boundGenericCharacteristics->TI,
12301240
boundGenericCharacteristics->concreteType,
12311241
boundGenericCharacteristics->packing)
12321242
.getOpaqueValue());
1233-
return B.addInt32(getValueWitnessFlags(&concreteTI, concreteType, packing)
1243+
return B.addInt32(getValueWitnessFlags(IGM, &concreteTI,
1244+
concreteType, packing)
12341245
.getOpaqueValue());
12351246
}
12361247

@@ -1441,7 +1452,7 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type,
14411452

14421453
auto &ti = IGM.getTypeInfoForUnlowered(AbstractionPattern::getOpaque(), type);
14431454

1444-
// We only have known value witness tables for copyable types currently.
1455+
// We only have known value witness tables for copyable types currently.
14451456
if (!ti.isCopyable(ResilienceExpansion::Maximal)) {
14461457
return {};
14471458
}
@@ -1454,6 +1465,17 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type,
14541465
CanType witnessSurrogate;
14551466
ReferenceCounting refCounting;
14561467

1468+
// All of our standard value witness tables are bitwise-borrowable and not
1469+
// addressable for dependencies.
1470+
if (!ti.isBitwiseBorrowable(ResilienceExpansion::Maximal)
1471+
|| IGM.getSILModule().Types
1472+
.getTypeLowering(AbstractionPattern::getOpaque(), type,
1473+
TypeExpansionContext::minimal())
1474+
.getRecursiveProperties()
1475+
.isAddressableForDependencies()) {
1476+
return {};
1477+
}
1478+
14571479
// Empty types can use empty tuple witnesses.
14581480
if (ti.isKnownEmpty(ResilienceExpansion::Maximal)) {
14591481
witnessSurrogate = TupleType::getEmpty(C);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/chex.py < %s > %t/test.swift
3+
// RUN: %target-swift-frontend -enable-experimental-feature AddressableTypes -emit-ir %s | %FileCheck %t/test.swift
4+
5+
// REQUIRES: swift_feature_AddressableTypes
6+
7+
@_addressableForDependencies
8+
struct DirectlyAFD {
9+
var x: Int32
10+
}
11+
// CHECK-LABEL: @"$s{{.*}}11DirectlyAFDVWV" =
12+
// -- 0x0200_0000: addressable for dependencies
13+
// CHECK-SAME: , [[WORD:i(64|32)]] 4, [[WORD]] 4, <i32 0x0200_0003>, i32 0 }
14+
15+
struct IndirectlyAFD {
16+
var directly: DirectlyAFD
17+
}
18+
// CHECK-LABEL: @"$s{{.*}}13IndirectlyAFDVWV" =
19+
// CHECK-SAME: , [[WORD:i(64|32)]] 4, [[WORD]] 4, <i32 0x0200_0003>, i32 0 }

test/IRGen/raw_layout.swift

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import RawLayoutCXX
1313
// CHECK-SAME: , {{i64|i32}} 4
1414
// stride
1515
// CHECK-SAME: , {{i64|i32}} 4
16-
// flags: alignment 3, noncopyable, non-bitwise-borrowable
17-
// CHECK-SAME: , <i32 0x1800003>
16+
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
17+
// CHECK-SAME: , <i32 0x3800003>
1818

1919
@_rawLayout(size: 4, alignment: 4)
2020
struct Lock: ~Copyable { }
@@ -29,8 +29,8 @@ struct PaddedStride {
2929
// CHECK-SAME: , {{i64|i32}} 5
3030
// stride
3131
// CHECK-SAME: , {{i64|i32}} 8
32-
// flags: alignment 3, noncopyable, non-bitwise-borrowable
33-
// CHECK-SAME: , <i32 0x1800003>
32+
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
33+
// CHECK-SAME: , <i32 0x3800003>
3434
@_rawLayout(like: PaddedStride)
3535
struct LikePaddedStride: ~Copyable {}
3636

@@ -39,8 +39,8 @@ struct LikePaddedStride: ~Copyable {}
3939
// CHECK-SAME: , {{i64|i32}} 8
4040
// stride
4141
// CHECK-SAME: , {{i64|i32}} 8
42-
// flags: alignment 3, noncopyable, non-bitwise-borrowable
43-
// CHECK-SAME: , <i32 0x1800003>
42+
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
43+
// CHECK-SAME: , <i32 0x3800003>
4444
@_rawLayout(likeArrayOf: PaddedStride, count: 1)
4545
struct LikePaddedStrideArray1: ~Copyable {}
4646

@@ -49,9 +49,9 @@ struct LikePaddedStrideArray1: ~Copyable {}
4949
// CHECK-SAME: , {{i64|i32}} 16
5050
// stride
5151
// CHECK-SAME: , {{i64|i32}} 16
52-
// flags: alignment 3, noncopyable, non-bitwise-borrowable, (on 32-bit platforms) not storable inline
53-
// CHECK-64-SAME: , <i32 0x1800003>
54-
// CHECK-32-SAME: , <i32 0x1820003>
52+
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies (on 32-bit platforms) not storable inline
53+
// CHECK-64-SAME: , <i32 0x3800003>
54+
// CHECK-32-SAME: , <i32 0x3820003>
5555
@_rawLayout(likeArrayOf: PaddedStride, count: 2)
5656
struct LikePaddedStrideArray2: ~Copyable {}
5757

@@ -60,8 +60,8 @@ struct LikePaddedStrideArray2: ~Copyable {}
6060
// CHECK-SAME: , {{i64|i32}} 12
6161
// stride
6262
// CHECK-SAME: , {{i64|i32}} 12
63-
// flags: alignment 3, noncopyable, non-bitwise-borrowable
64-
// CHECK-SAME: , <i32 0x1800003>
63+
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
64+
// CHECK-SAME: , <i32 0x3800003>
6565
struct Keymaster: ~Copyable {
6666
let lock1: Lock
6767
let lock2: Lock
@@ -127,8 +127,8 @@ struct Vector<T, let N: Int>: ~Copyable {}
127127
// CHECK-SAME: , {{i64|i32}} 8
128128
// stride
129129
// CHECK-SAME: , {{i64|i32}} 8
130-
// flags: alignment 3, noncopyable, non-bitwise-borrowable
131-
// CHECK-SAME: , <i32 0x1800003>
130+
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
131+
// CHECK-SAME: , <i32 0x3800003>
132132
struct UsesCell: ~Copyable {
133133
let someCondition: Bool
134134
let specialInt: Cell<Int32>
@@ -139,8 +139,8 @@ struct UsesCell: ~Copyable {
139139
// CHECK-SAME: , {{i64|i32}} 3
140140
// stride
141141
// CHECK-SAME: , {{i64|i32}} 3
142-
// flags: alignment 0, noncopyable, non-bitwise-borrowable
143-
// CHECK-SAME: , <i32 0x1800000>
142+
// flags: alignment 0, noncopyable, non-bitwise-borrowable, addressable for dependencies
143+
// CHECK-SAME: , <i32 0x3800000>
144144
struct BufferOf3Bool: ~Copyable {
145145
let buffer: SmallVectorOf3<Bool>
146146
}
@@ -150,8 +150,8 @@ struct BufferOf3Bool: ~Copyable {
150150
// CHECK-SAME: , {{i64|i32}} 48
151151
// stride
152152
// CHECK-SAME: , {{i64|i32}} 48
153-
// flags: alignment 7, noncopyable, non-bitwise-borrowable, is not inline
154-
// CHECK-SAME: , <i32 0x1820007>
153+
// flags: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies, is not inline
154+
// CHECK-SAME: , <i32 0x3820007>
155155
struct BadBuffer: ~Copyable {
156156
let buffer: SmallVectorOf3<Int64?>
157157
}
@@ -161,8 +161,8 @@ struct BadBuffer: ~Copyable {
161161
// CHECK-SAME: , {{i64|i32}} 2
162162
// stride
163163
// CHECK-SAME: , {{i64|i32}} 2
164-
// flags: alignment 0, noncopyable, non-bitwise-borrowable
165-
// CHECK-SAME: , <i32 0x1800000>
164+
// flags: alignment 0, noncopyable, non-bitwise-borrowable, addressable for dependencies
165+
// CHECK-SAME: , <i32 0x3800000>
166166
struct UsesVector: ~Copyable {
167167
let buffer: Vector<UInt8, 2>
168168
}
@@ -172,8 +172,8 @@ struct UsesVector: ~Copyable {
172172
// CHECK-SAME: , {{i64|i32}} 48
173173
// stride
174174
// CHECK-SAME: , {{i64|i32}} 48
175-
// flags: alignment 7, noncopyable, non-bitwise-borrowable, is not inline
176-
// CHECK-SAME: , <i32 0x1820007>
175+
// flags: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies, is not inline
176+
// CHECK-SAME: , <i32 0x3820007>
177177
struct BadBuffer2: ~Copyable {
178178
let buffer: Vector<Int64?, 3>
179179
}
@@ -207,8 +207,8 @@ struct CellThatMovesAsLike<T>: ~Copyable {}
207207
// CHECK-SAME: , {{i64|i32}} 1
208208
// stride
209209
// CHECK-SAME: , {{i64|i32}} 1
210-
// flags: not copyable, not bitwise takable, not pod, not inline
211-
// CHECK-SAME: , <i32 0x930000>
210+
// flags: not copyable, not bitwise takable, not pod, not inline, addressable for dependencies
211+
// CHECK-SAME: , <i32 0x2930000>
212212
struct ConcreteMoveAsLike: ~Copyable {
213213
let cell: CellThatMovesAsLike<NonBitwiseTakableCXXType>
214214
}
@@ -224,8 +224,8 @@ struct ConcreteMoveAsLike: ~Copyable {
224224
// CHECK-SAME: , {{i64|i32}} 4
225225
// stride
226226
// CHECK-SAME: , {{i64|i32}} 4
227-
// flags: alignment 3, not copyable, not bitwise-borrowable
228-
// CHECK-SAME: , <i32 0x1800003>
227+
// flags: alignment 3, not copyable, not bitwise-borrowable, addressable for dependencies
228+
// CHECK-SAME: , <i32 0x3800003>
229229
struct ConcreteIntMoveAsLike: ~Copyable {
230230
let cell: CellThatMovesAsLike<Int32>
231231
}
@@ -257,8 +257,8 @@ struct SmallVectorOf2MovesAsLike<T: ~Copyable>: ~Copyable {}
257257
// CHECK-SAME: , {{i64|i32}} 2
258258
// stride
259259
// CHECK-SAME: , {{i64|i32}} 2
260-
// flags: not copyable, not bitwise takable, not pod, not inline
261-
// CHECK-SAME: , <i32 0x930000>
260+
// flags: not copyable, not bitwise takable, not pod, not inline, addressable for dependencies
261+
// CHECK-SAME: , <i32 0x2930000>
262262
struct ConcreteSmallVectorMovesAsLike: ~Copyable {
263263
let vector: SmallVectorOf2MovesAsLike<NonBitwiseTakableCXXType>
264264
}
@@ -274,8 +274,8 @@ struct ConcreteSmallVectorMovesAsLike: ~Copyable {
274274
// CHECK-SAME: , {{i64|i32}} 8
275275
// stride
276276
// CHECK-SAME: , {{i64|i32}} 8
277-
// flags: alignment 3, not copyable, not bitwise-borrowable
278-
// CHECK-SAME: , <i32 0x1800003>
277+
// flags: alignment 3, not copyable, not bitwise-borrowable, addressable for dependencies
278+
// CHECK-SAME: , <i32 0x3800003>
279279
struct ConcreteSmallVectorIntMovesAsLike: ~Copyable {
280280
let vector: SmallVectorOf2MovesAsLike<Int32>
281281
}
@@ -307,8 +307,8 @@ struct VectorMovesAsLike<T: ~Copyable, let N: Int>: ~Copyable {}
307307
// CHECK-SAME: , {{i64|i32}} 4
308308
// stride
309309
// CHECK-SAME: , {{i64|i32}} 4
310-
// flags: not copyable, not bitwise takable, not pod, not inline
311-
// CHECK-SAME: , <i32 0x930000>
310+
// flags: not copyable, not bitwise takable, not pod, not inline, addressable for dependencies
311+
// CHECK-SAME: , <i32 0x2930000>
312312
struct ConcreteVectorMovesAsLike: ~Copyable {
313313
let vector: VectorMovesAsLike<NonBitwiseTakableCXXType, 4>
314314
}
@@ -324,9 +324,9 @@ struct ConcreteVectorMovesAsLike: ~Copyable {
324324
// CHECK-SAME: , {{i64|i32}} 16
325325
// stride
326326
// CHECK-SAME: , {{i64|i32}} 16
327-
// flags: alignment 3, not copyable, not bitwise-borrowable, (on 32-bit platforms) not storable inline
328-
// CHECK-64-SAME: , <i32 0x1800003>
329-
// CHECK-32-SAME: , <i32 0x1820003>
327+
// flags: alignment 3, not copyable, not bitwise-borrowable, addressable for dependencies, (on 32-bit platforms) not storable inline
328+
// CHECK-64-SAME: , <i32 0x3800003>
329+
// CHECK-32-SAME: , <i32 0x3820003>
330330
struct ConcreteVectorIntMovesAsLike: ~Copyable {
331331
let vector: VectorMovesAsLike<Int32, 4>
332332
}

test/IRGen/raw_layout_multifile.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ public struct Foo<T>: ~Copyable {}
1313
// CHECK-SAME: , {{i64|i32}} 4
1414
// stride
1515
// CHECK-SAME: , {{i64|i32}} 4
16-
// flags: alignment 3, noncopyable, non-bitwise-borrowable
17-
// CHECK-SAME: , <i32 0x1800003>
16+
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
17+
// CHECK-SAME: , <i32 0x380_0003>
1818
struct MyInt: ~Copyable {
1919
let x: Int32Fake
2020
}
@@ -24,8 +24,8 @@ struct MyInt: ~Copyable {
2424
// CHECK-SAME: , {{i64|i32}} 48
2525
// stride
2626
// CHECK-SAME: , {{i64|i32}} 48
27-
// flags: alignment 7, noncopyable, non-bitwise-borrowable, is not inline
28-
// CHECK-SAME: , <i32 0x1820007>
27+
// flags: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies, is not inline
28+
// CHECK-SAME: , <i32 0x382_0007>
2929
struct BadBuffer: ~Copyable {
3030
let buf = SmallVectorOf3<Int64?>()
3131
}
@@ -35,10 +35,10 @@ struct BadBuffer: ~Copyable {
3535
// CHECK-SAME: , {{i64|i32}} 8
3636
// stride
3737
// CHECK-SAME: , {{i64|i32}} 8
38-
// flags-32: alignment 7, noncopyable, non-bitwise-borrowable, is not inline
39-
// CHECK-32-SAME: , <i32 0x1820007>
40-
// flags-64: alignment 7, noncopyable, non-bitwise-borrowable
41-
// CHECK-64-SAME: , <i32 0x1800007>
38+
// flags-32: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies, is not inline
39+
// CHECK-32-SAME: , <i32 0x3820007>
40+
// flags-64: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies
41+
// CHECK-64-SAME: , <i32 0x3800007>
4242
struct Weird: ~Copyable {
4343
let value = UnsafeCell<Int64>()
4444
}

test/Serialization/raw_layout.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import RawLayoutCXX
1818
// CHECK-SAME: , {{i64|i32}} 1
1919
// stride
2020
// CHECK-SAME: , {{i64|i32}} 1
21-
// flags: not copyable, not bitwise takable, not pod, not inline
22-
// CHECK-SAME: , i32 9633792
21+
// flags: addressable for dependencies, not copyable, not bitwise takable, not pod, not inline
22+
// CHECK-SAME: , i32 43188224
2323
struct WeirdCXXTypeCell: ~Copyable {
2424
let cell: CellThatMovesLike<NonBitwiseTakableCXXType>
2525
}

0 commit comments

Comments
 (0)