mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
This commit is contained in:
@@ -165,18 +165,19 @@ public:
|
||||
// flags for the struct. (The "non-inline" and "has-extra-inhabitants" bits
|
||||
// still require additional fixup.)
|
||||
enum : uint32_t {
|
||||
AlignmentMask = 0x000000FF,
|
||||
// unused 0x0000FF00,
|
||||
IsNonPOD = 0x00010000,
|
||||
IsNonInline = 0x00020000,
|
||||
// unused 0x00040000,
|
||||
HasSpareBits = 0x00080000,
|
||||
IsNonBitwiseTakable = 0x00100000,
|
||||
HasEnumWitnesses = 0x00200000,
|
||||
Incomplete = 0x00400000,
|
||||
IsNonCopyable = 0x00800000,
|
||||
IsNonBitwiseBorrowable = 0x01000000,
|
||||
// unused 0xFE000000,
|
||||
AlignmentMask = 0x000000FF,
|
||||
// unused 0x0000FF00,
|
||||
IsNonPOD = 0x00010000,
|
||||
IsNonInline = 0x00020000,
|
||||
// unused 0x00040000,
|
||||
HasSpareBits = 0x00080000,
|
||||
IsNonBitwiseTakable = 0x00100000,
|
||||
HasEnumWitnesses = 0x00200000,
|
||||
Incomplete = 0x00400000,
|
||||
IsNonCopyable = 0x00800000,
|
||||
IsNonBitwiseBorrowable = 0x01000000,
|
||||
IsAddressableForDependencies = 0x02000000,
|
||||
// unused 0xFC000000,
|
||||
};
|
||||
|
||||
static constexpr const uint32_t MaxNumExtraInhabitants = 0x7FFFFFFF;
|
||||
@@ -268,6 +269,19 @@ public:
|
||||
return TargetValueWitnessFlags((Data & ~IsNonCopyable) |
|
||||
(isCopyable ? 0 : IsNonCopyable));
|
||||
}
|
||||
|
||||
/// True if values of this type are addressable-for-dependencies, meaning
|
||||
/// that values of this type should be passed indirectly to functions that
|
||||
/// produce lifetime-dependent values that could possibly contain pointers
|
||||
/// to the inline storage of this type.
|
||||
bool isAddressableForDependencies() const {
|
||||
return Data & IsAddressableForDependencies;
|
||||
}
|
||||
constexpr TargetValueWitnessFlags withAddressableForDependencies(bool afd) const {
|
||||
return TargetValueWitnessFlags((Data & ~IsAddressableForDependencies) |
|
||||
(afd ? IsAddressableForDependencies : 0));
|
||||
}
|
||||
|
||||
|
||||
/// True if this type's binary representation is that of an enum, and the
|
||||
/// enum value witness table entries are available in this type's value
|
||||
|
||||
@@ -837,7 +837,9 @@ struct BoundGenericTypeCharacteristics {
|
||||
FixedPacking packing;
|
||||
};
|
||||
|
||||
ValueWitnessFlags getValueWitnessFlags(const TypeInfo *TI, SILType concreteType,
|
||||
ValueWitnessFlags getValueWitnessFlags(IRGenModule &IGM,
|
||||
const TypeInfo *TI,
|
||||
SILType concreteType,
|
||||
FixedPacking packing) {
|
||||
ValueWitnessFlags flags;
|
||||
|
||||
@@ -852,6 +854,12 @@ ValueWitnessFlags getValueWitnessFlags(const TypeInfo *TI, SILType concreteType,
|
||||
bool isBitwiseBorrowable =
|
||||
fixedTI->isBitwiseBorrowable(ResilienceExpansion::Maximal);
|
||||
assert(isBitwiseTakable || !isInline);
|
||||
bool isAddressableForDependencies =
|
||||
IGM.getSILModule().Types.getTypeLowering(concreteType,
|
||||
TypeExpansionContext::minimal())
|
||||
.getRecursiveProperties()
|
||||
.isAddressableForDependencies();
|
||||
|
||||
flags = flags.withAlignment(fixedTI->getFixedAlignment().getValue())
|
||||
.withPOD(fixedTI->isTriviallyDestroyable(ResilienceExpansion::Maximal))
|
||||
.withCopyable(fixedTI->isCopyable(ResilienceExpansion::Maximal))
|
||||
@@ -864,7 +872,8 @@ ValueWitnessFlags getValueWitnessFlags(const TypeInfo *TI, SILType concreteType,
|
||||
// Swift prior to version 6 didn't have the
|
||||
// IsNotBitwiseBorrowable bit, so to avoid unnecessary variation
|
||||
// in metadata output, we only set the bit when needed.
|
||||
.withBitwiseBorrowable(!isBitwiseTakable || isBitwiseBorrowable);
|
||||
.withBitwiseBorrowable(!isBitwiseTakable || isBitwiseBorrowable)
|
||||
.withAddressableForDependencies(isAddressableForDependencies);
|
||||
} else {
|
||||
flags = flags.withIncomplete(true);
|
||||
}
|
||||
@@ -1226,11 +1235,13 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
|
||||
case ValueWitness::Flags: {
|
||||
if (boundGenericCharacteristics)
|
||||
return B.addInt32(
|
||||
getValueWitnessFlags(boundGenericCharacteristics->TI,
|
||||
getValueWitnessFlags(IGM,
|
||||
boundGenericCharacteristics->TI,
|
||||
boundGenericCharacteristics->concreteType,
|
||||
boundGenericCharacteristics->packing)
|
||||
.getOpaqueValue());
|
||||
return B.addInt32(getValueWitnessFlags(&concreteTI, concreteType, packing)
|
||||
return B.addInt32(getValueWitnessFlags(IGM, &concreteTI,
|
||||
concreteType, packing)
|
||||
.getOpaqueValue());
|
||||
}
|
||||
|
||||
@@ -1441,7 +1452,7 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type,
|
||||
|
||||
auto &ti = IGM.getTypeInfoForUnlowered(AbstractionPattern::getOpaque(), type);
|
||||
|
||||
// We only have known value witness tables for copyable types currently.
|
||||
// We only have known value witness tables for copyable types currently.
|
||||
if (!ti.isCopyable(ResilienceExpansion::Maximal)) {
|
||||
return {};
|
||||
}
|
||||
@@ -1454,6 +1465,17 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type,
|
||||
CanType witnessSurrogate;
|
||||
ReferenceCounting refCounting;
|
||||
|
||||
// All of our standard value witness tables are bitwise-borrowable and not
|
||||
// addressable for dependencies.
|
||||
if (!ti.isBitwiseBorrowable(ResilienceExpansion::Maximal)
|
||||
|| IGM.getSILModule().Types
|
||||
.getTypeLowering(AbstractionPattern::getOpaque(), type,
|
||||
TypeExpansionContext::minimal())
|
||||
.getRecursiveProperties()
|
||||
.isAddressableForDependencies()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Empty types can use empty tuple witnesses.
|
||||
if (ti.isKnownEmpty(ResilienceExpansion::Maximal)) {
|
||||
witnessSurrogate = TupleType::getEmpty(C);
|
||||
|
||||
19
test/IRGen/addressable_for_dependencies_metadata.swift
Normal file
19
test/IRGen/addressable_for_dependencies_metadata.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %{python} %utils/chex.py < %s > %t/test.swift
|
||||
// RUN: %target-swift-frontend -enable-experimental-feature AddressableTypes -emit-ir %s | %FileCheck %t/test.swift
|
||||
|
||||
// REQUIRES: swift_feature_AddressableTypes
|
||||
|
||||
@_addressableForDependencies
|
||||
struct DirectlyAFD {
|
||||
var x: Int32
|
||||
}
|
||||
// CHECK-LABEL: @"$s{{.*}}11DirectlyAFDVWV" =
|
||||
// -- 0x0200_0000: addressable for dependencies
|
||||
// CHECK-SAME: , [[WORD:i(64|32)]] 4, [[WORD]] 4, <i32 0x0200_0003>, i32 0 }
|
||||
|
||||
struct IndirectlyAFD {
|
||||
var directly: DirectlyAFD
|
||||
}
|
||||
// CHECK-LABEL: @"$s{{.*}}13IndirectlyAFDVWV" =
|
||||
// CHECK-SAME: , [[WORD:i(64|32)]] 4, [[WORD]] 4, <i32 0x0200_0003>, i32 0 }
|
||||
@@ -13,8 +13,8 @@ import RawLayoutCXX
|
||||
// CHECK-SAME: , {{i64|i32}} 4
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 4
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800003>
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800003>
|
||||
|
||||
@_rawLayout(size: 4, alignment: 4)
|
||||
struct Lock: ~Copyable { }
|
||||
@@ -29,8 +29,8 @@ struct PaddedStride {
|
||||
// CHECK-SAME: , {{i64|i32}} 5
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800003>
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800003>
|
||||
@_rawLayout(like: PaddedStride)
|
||||
struct LikePaddedStride: ~Copyable {}
|
||||
|
||||
@@ -39,8 +39,8 @@ struct LikePaddedStride: ~Copyable {}
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800003>
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800003>
|
||||
@_rawLayout(likeArrayOf: PaddedStride, count: 1)
|
||||
struct LikePaddedStrideArray1: ~Copyable {}
|
||||
|
||||
@@ -49,9 +49,9 @@ struct LikePaddedStrideArray1: ~Copyable {}
|
||||
// CHECK-SAME: , {{i64|i32}} 16
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 16
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable, (on 32-bit platforms) not storable inline
|
||||
// CHECK-64-SAME: , <i32 0x1800003>
|
||||
// CHECK-32-SAME: , <i32 0x1820003>
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies (on 32-bit platforms) not storable inline
|
||||
// CHECK-64-SAME: , <i32 0x3800003>
|
||||
// CHECK-32-SAME: , <i32 0x3820003>
|
||||
@_rawLayout(likeArrayOf: PaddedStride, count: 2)
|
||||
struct LikePaddedStrideArray2: ~Copyable {}
|
||||
|
||||
@@ -60,8 +60,8 @@ struct LikePaddedStrideArray2: ~Copyable {}
|
||||
// CHECK-SAME: , {{i64|i32}} 12
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 12
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800003>
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800003>
|
||||
struct Keymaster: ~Copyable {
|
||||
let lock1: Lock
|
||||
let lock2: Lock
|
||||
@@ -127,8 +127,8 @@ struct Vector<T, let N: Int>: ~Copyable {}
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800003>
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800003>
|
||||
struct UsesCell: ~Copyable {
|
||||
let someCondition: Bool
|
||||
let specialInt: Cell<Int32>
|
||||
@@ -139,8 +139,8 @@ struct UsesCell: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 3
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 3
|
||||
// flags: alignment 0, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800000>
|
||||
// flags: alignment 0, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800000>
|
||||
struct BufferOf3Bool: ~Copyable {
|
||||
let buffer: SmallVectorOf3<Bool>
|
||||
}
|
||||
@@ -150,8 +150,8 @@ struct BufferOf3Bool: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 48
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 48
|
||||
// flags: alignment 7, noncopyable, non-bitwise-borrowable, is not inline
|
||||
// CHECK-SAME: , <i32 0x1820007>
|
||||
// flags: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies, is not inline
|
||||
// CHECK-SAME: , <i32 0x3820007>
|
||||
struct BadBuffer: ~Copyable {
|
||||
let buffer: SmallVectorOf3<Int64?>
|
||||
}
|
||||
@@ -161,8 +161,8 @@ struct BadBuffer: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 2
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 2
|
||||
// flags: alignment 0, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800000>
|
||||
// flags: alignment 0, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800000>
|
||||
struct UsesVector: ~Copyable {
|
||||
let buffer: Vector<UInt8, 2>
|
||||
}
|
||||
@@ -172,8 +172,8 @@ struct UsesVector: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 48
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 48
|
||||
// flags: alignment 7, noncopyable, non-bitwise-borrowable, is not inline
|
||||
// CHECK-SAME: , <i32 0x1820007>
|
||||
// flags: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies, is not inline
|
||||
// CHECK-SAME: , <i32 0x3820007>
|
||||
struct BadBuffer2: ~Copyable {
|
||||
let buffer: Vector<Int64?, 3>
|
||||
}
|
||||
@@ -207,8 +207,8 @@ struct CellThatMovesAsLike<T>: ~Copyable {}
|
||||
// CHECK-SAME: , {{i64|i32}} 1
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 1
|
||||
// flags: not copyable, not bitwise takable, not pod, not inline
|
||||
// CHECK-SAME: , <i32 0x930000>
|
||||
// flags: not copyable, not bitwise takable, not pod, not inline, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x2930000>
|
||||
struct ConcreteMoveAsLike: ~Copyable {
|
||||
let cell: CellThatMovesAsLike<NonBitwiseTakableCXXType>
|
||||
}
|
||||
@@ -224,8 +224,8 @@ struct ConcreteMoveAsLike: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 4
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 4
|
||||
// flags: alignment 3, not copyable, not bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800003>
|
||||
// flags: alignment 3, not copyable, not bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800003>
|
||||
struct ConcreteIntMoveAsLike: ~Copyable {
|
||||
let cell: CellThatMovesAsLike<Int32>
|
||||
}
|
||||
@@ -257,8 +257,8 @@ struct SmallVectorOf2MovesAsLike<T: ~Copyable>: ~Copyable {}
|
||||
// CHECK-SAME: , {{i64|i32}} 2
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 2
|
||||
// flags: not copyable, not bitwise takable, not pod, not inline
|
||||
// CHECK-SAME: , <i32 0x930000>
|
||||
// flags: not copyable, not bitwise takable, not pod, not inline, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x2930000>
|
||||
struct ConcreteSmallVectorMovesAsLike: ~Copyable {
|
||||
let vector: SmallVectorOf2MovesAsLike<NonBitwiseTakableCXXType>
|
||||
}
|
||||
@@ -274,8 +274,8 @@ struct ConcreteSmallVectorMovesAsLike: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// flags: alignment 3, not copyable, not bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800003>
|
||||
// flags: alignment 3, not copyable, not bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x3800003>
|
||||
struct ConcreteSmallVectorIntMovesAsLike: ~Copyable {
|
||||
let vector: SmallVectorOf2MovesAsLike<Int32>
|
||||
}
|
||||
@@ -307,8 +307,8 @@ struct VectorMovesAsLike<T: ~Copyable, let N: Int>: ~Copyable {}
|
||||
// CHECK-SAME: , {{i64|i32}} 4
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 4
|
||||
// flags: not copyable, not bitwise takable, not pod, not inline
|
||||
// CHECK-SAME: , <i32 0x930000>
|
||||
// flags: not copyable, not bitwise takable, not pod, not inline, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x2930000>
|
||||
struct ConcreteVectorMovesAsLike: ~Copyable {
|
||||
let vector: VectorMovesAsLike<NonBitwiseTakableCXXType, 4>
|
||||
}
|
||||
@@ -324,9 +324,9 @@ struct ConcreteVectorMovesAsLike: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 16
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 16
|
||||
// flags: alignment 3, not copyable, not bitwise-borrowable, (on 32-bit platforms) not storable inline
|
||||
// CHECK-64-SAME: , <i32 0x1800003>
|
||||
// CHECK-32-SAME: , <i32 0x1820003>
|
||||
// flags: alignment 3, not copyable, not bitwise-borrowable, addressable for dependencies, (on 32-bit platforms) not storable inline
|
||||
// CHECK-64-SAME: , <i32 0x3800003>
|
||||
// CHECK-32-SAME: , <i32 0x3820003>
|
||||
struct ConcreteVectorIntMovesAsLike: ~Copyable {
|
||||
let vector: VectorMovesAsLike<Int32, 4>
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ public struct Foo<T>: ~Copyable {}
|
||||
// CHECK-SAME: , {{i64|i32}} 4
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 4
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME: , <i32 0x1800003>
|
||||
// flags: alignment 3, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME: , <i32 0x380_0003>
|
||||
struct MyInt: ~Copyable {
|
||||
let x: Int32Fake
|
||||
}
|
||||
@@ -24,8 +24,8 @@ struct MyInt: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 48
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 48
|
||||
// flags: alignment 7, noncopyable, non-bitwise-borrowable, is not inline
|
||||
// CHECK-SAME: , <i32 0x1820007>
|
||||
// flags: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies, is not inline
|
||||
// CHECK-SAME: , <i32 0x382_0007>
|
||||
struct BadBuffer: ~Copyable {
|
||||
let buf = SmallVectorOf3<Int64?>()
|
||||
}
|
||||
@@ -35,10 +35,10 @@ struct BadBuffer: ~Copyable {
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 8
|
||||
// flags-32: alignment 7, noncopyable, non-bitwise-borrowable, is not inline
|
||||
// CHECK-SAME-32: , <i32 0x1820007>
|
||||
// flags-64: alignment 7, noncopyable, non-bitwise-borrowable
|
||||
// CHECK-SAME-64: , <i32 0x1800007>
|
||||
// flags-32: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies, is not inline
|
||||
// CHECK-SAME-32: , <i32 0x3820007>
|
||||
// flags-64: alignment 7, noncopyable, non-bitwise-borrowable, addressable for dependencies
|
||||
// CHECK-SAME-64: , <i32 0x3800007>
|
||||
struct Weird: ~Copyable {
|
||||
let value = UnsafeCell<Int64>()
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ import RawLayoutCXX
|
||||
// CHECK-SAME: , {{i64|i32}} 1
|
||||
// stride
|
||||
// CHECK-SAME: , {{i64|i32}} 1
|
||||
// flags: not copyable, not bitwise takable, not pod, not inline
|
||||
// CHECK-SAME: , i32 9633792
|
||||
// flags: addressable for dependencies, not copyable, not bitwise takable, not pod, not inline
|
||||
// CHECK-SAME: , i32 43188224
|
||||
struct WeirdCXXTypeCell: ~Copyable {
|
||||
let cell: CellThatMovesLike<NonBitwiseTakableCXXType>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user