Skip to content

Commit 1c75d3b

Browse files
authored
Merge pull request #82323 from jckarter/addressable-for-dependencies-vw-flag
Add an "addressable for dependencies" flag to value witness flags.
2 parents beb2b58 + 7e99e84 commit 1c75d3b

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

@@ -1439,7 +1450,7 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type,
14391450

14401451
auto &ti = IGM.getTypeInfoForUnlowered(AbstractionPattern::getOpaque(), type);
14411452

1442-
// We only have known value witness tables for copyable types currently.
1453+
// We only have known value witness tables for copyable types currently.
14431454
if (!ti.isCopyable(ResilienceExpansion::Maximal)) {
14441455
return {};
14451456
}
@@ -1452,6 +1463,17 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type,
14521463
CanType witnessSurrogate;
14531464
ReferenceCounting refCounting;
14541465

1466+
// All of our standard value witness tables are bitwise-borrowable and not
1467+
// addressable for dependencies.
1468+
if (!ti.isBitwiseBorrowable(ResilienceExpansion::Maximal)
1469+
|| IGM.getSILModule().Types
1470+
.getTypeLowering(AbstractionPattern::getOpaque(), type,
1471+
TypeExpansionContext::minimal())
1472+
.getRecursiveProperties()
1473+
.isAddressableForDependencies()) {
1474+
return {};
1475+
}
1476+
14551477
// Empty types can use empty tuple witnesses.
14561478
if (ti.isKnownEmpty(ResilienceExpansion::Maximal)) {
14571479
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)