mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Update the metadata-initialization ABI:
- Create the value witness table as a separate global object instead of concatenating it to the metadata pattern. - Always pass the metadata to the runtime and let the runtime handle instantiating or modifying the value witness table. - Pass the right layout algorithm version to the runtime; currently this is always "Swift 5". - Create a runtime function to instantiate single-case enums. Among other things, this makes the copying of the VWT, and any modifications of it, explicit and in the runtime, which is more future-proof.
This commit is contained in:
@@ -314,8 +314,9 @@ runtime.
|
||||
000000000001e620 T _swift_allocateGenericValueMetadata
|
||||
0000000000022be0 T _swift_initClassMetadata_UniversalStrategy
|
||||
000000000001c100 T _swift_initEnumMetadataMultiPayload
|
||||
000000000001bd60 T _swift_initEnumValueWitnessTableSinglePayload
|
||||
0000000000022a20 T _swift_initStructMetadata_UniversalStrategy
|
||||
000000000001bd60 T _swift_initEnumMetadataSingleCase
|
||||
000000000001bd60 T _swift_initEnumMetadataSinglePayload
|
||||
0000000000022a20 T _swift_initStructMetadata
|
||||
0000000000024230 T _swift_initializeSuperclass
|
||||
0000000000028b60 T _swift_instantiateObjCClass
|
||||
```
|
||||
|
||||
@@ -747,6 +747,62 @@ static inline bool isWarningOnly(ExclusivityFlags flags) {
|
||||
return uintptr_t(flags) & uintptr_t(ExclusivityFlags::WarningOnly);
|
||||
}
|
||||
|
||||
/// Flags for struct layout.
|
||||
enum class StructLayoutFlags : uintptr_t {
|
||||
/// Reserve space for 256 layout algorithms.
|
||||
AlgorithmMask = 0xff,
|
||||
|
||||
/// The ABI baseline algorithm, i.e. the algorithm implemented in Swift 5.
|
||||
Swift5Algorithm = 0x00,
|
||||
|
||||
/// Is the value-witness table mutable in place, or does layout need to
|
||||
/// clone it?
|
||||
IsVWTMutable = 0x100,
|
||||
};
|
||||
static inline StructLayoutFlags operator|(StructLayoutFlags lhs,
|
||||
StructLayoutFlags rhs) {
|
||||
return StructLayoutFlags(uintptr_t(lhs) | uintptr_t(rhs));
|
||||
}
|
||||
static inline StructLayoutFlags &operator|=(StructLayoutFlags &lhs,
|
||||
StructLayoutFlags rhs) {
|
||||
return (lhs = (lhs | rhs));
|
||||
}
|
||||
static inline StructLayoutFlags getLayoutAlgorithm(StructLayoutFlags flags) {
|
||||
return StructLayoutFlags(uintptr_t(flags)
|
||||
& uintptr_t(StructLayoutFlags::AlgorithmMask));
|
||||
}
|
||||
static inline bool isValueWitnessTableMutable(StructLayoutFlags flags) {
|
||||
return uintptr_t(flags) & uintptr_t(StructLayoutFlags::IsVWTMutable);
|
||||
}
|
||||
|
||||
/// Flags for enum layout.
|
||||
enum class EnumLayoutFlags : uintptr_t {
|
||||
/// Reserve space for 256 layout algorithms.
|
||||
AlgorithmMask = 0xff,
|
||||
|
||||
/// The ABI baseline algorithm, i.e. the algorithm implemented in Swift 5.
|
||||
Swift5Algorithm = 0x00,
|
||||
|
||||
/// Is the value-witness table mutable in place, or does layout need to
|
||||
/// clone it?
|
||||
IsVWTMutable = 0x100,
|
||||
};
|
||||
static inline EnumLayoutFlags operator|(EnumLayoutFlags lhs,
|
||||
EnumLayoutFlags rhs) {
|
||||
return EnumLayoutFlags(uintptr_t(lhs) | uintptr_t(rhs));
|
||||
}
|
||||
static inline EnumLayoutFlags &operator|=(EnumLayoutFlags &lhs,
|
||||
EnumLayoutFlags rhs) {
|
||||
return (lhs = (lhs | rhs));
|
||||
}
|
||||
static inline EnumLayoutFlags getLayoutAlgorithm(EnumLayoutFlags flags) {
|
||||
return EnumLayoutFlags(uintptr_t(flags)
|
||||
& uintptr_t(EnumLayoutFlags::AlgorithmMask));
|
||||
}
|
||||
static inline bool isValueWitnessTableMutable(EnumLayoutFlags flags) {
|
||||
return uintptr_t(flags) & uintptr_t(EnumLayoutFlags::IsVWTMutable);
|
||||
}
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif /* SWIFT_ABI_METADATAVALUES_H */
|
||||
|
||||
@@ -33,17 +33,29 @@ template <typename Runtime> struct TargetEnumMetadata;
|
||||
using EnumMetadata = TargetEnumMetadata<InProcess>;
|
||||
struct TypeLayout;
|
||||
|
||||
/// \brief Initialize the value witness table for a generic, single-payload
|
||||
/// enum instance.
|
||||
/// \brief Initialize the type metadata for a single-case enum type.
|
||||
///
|
||||
/// \param vwtable - pointer to the instantiated but uninitialized value
|
||||
/// witness table for the enum.
|
||||
/// \param enumType - pointer to the instantiated but uninitialized metadata
|
||||
/// for the enum.
|
||||
/// \param flags - flags controlling the layout
|
||||
/// \param payload - type metadata for the payload of the enum.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_initEnumMetadataSingleCase(EnumMetadata *enumType,
|
||||
EnumLayoutFlags flags,
|
||||
const TypeLayout *payload);
|
||||
|
||||
/// \brief Initialize the type metadata for a single-payload enum type.
|
||||
///
|
||||
/// \param enumType - pointer to the instantiated but uninitialized metadata
|
||||
/// for the enum.
|
||||
/// \param flags - flags controlling the layout
|
||||
/// \param payload - type metadata for the payload case of the enum.
|
||||
/// \param emptyCases - the number of empty cases in the enum.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_initEnumValueWitnessTableSinglePayload(ValueWitnessTable *vwtable,
|
||||
const TypeLayout *payload,
|
||||
unsigned emptyCases);
|
||||
void swift_initEnumMetadataSinglePayload(EnumMetadata *enumType,
|
||||
EnumLayoutFlags flags,
|
||||
const TypeLayout *payload,
|
||||
unsigned emptyCases);
|
||||
|
||||
/// \brief Faster variant of the above which avoids digging into the enum type
|
||||
/// metadata when the caller already has the payload information handy.
|
||||
@@ -81,11 +93,11 @@ void swift_storeEnumTagSinglePayload(OpaqueValue *value,
|
||||
unsigned emptyCases)
|
||||
SWIFT_CC(RegisterPreservingCC);
|
||||
|
||||
/// \brief Initialize the value witness table for a generic, multi-payload
|
||||
/// \brief Initialize the type metadata for a generic, multi-payload
|
||||
/// enum instance.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_initEnumMetadataMultiPayload(ValueWitnessTable *vwtable,
|
||||
EnumMetadata *enumType,
|
||||
void swift_initEnumMetadataMultiPayload(EnumMetadata *enumType,
|
||||
EnumLayoutFlags flags,
|
||||
unsigned numPayloads,
|
||||
const TypeLayout * const *payloadTypes);
|
||||
|
||||
|
||||
@@ -2901,10 +2901,11 @@ swift_getTupleTypeMetadata3(const Metadata *elt0, const Metadata *elt1,
|
||||
/// Initialize the value witness table and struct field offset vector for a
|
||||
/// struct, using the "Universal" layout strategy.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_initStructMetadata_UniversalStrategy(size_t numFields,
|
||||
const TypeLayout * const *fieldTypes,
|
||||
size_t *fieldOffsets,
|
||||
ValueWitnessTable *vwtable);
|
||||
void swift_initStructMetadata(StructMetadata *self,
|
||||
StructLayoutFlags flags,
|
||||
size_t numFields,
|
||||
const TypeLayout * const *fieldTypes,
|
||||
size_t *fieldOffsets);
|
||||
|
||||
/// Relocate the metadata for a class and copy fields from the given template.
|
||||
/// The final size of the metadata is calculated at runtime from the size of
|
||||
|
||||
@@ -968,37 +968,47 @@ FUNCTION(InitClassMetadataUniversal,
|
||||
SizeTy->getPointerTo()),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
// void swift_initStructMetadata_UniversalStrategy(size_t numFields,
|
||||
// TypeLayout * const *fieldTypes,
|
||||
// size_t *fieldOffsets,
|
||||
// value_witness_table_t *vwtable);
|
||||
FUNCTION(InitStructMetadataUniversal,
|
||||
swift_initStructMetadata_UniversalStrategy, DefaultCC,
|
||||
// void swift_initStructMetadata(Metadata *structType,
|
||||
// StructLayoutFlags flags,
|
||||
// size_t numFields,
|
||||
// TypeLayout * const *fieldTypes,
|
||||
// size_t *fieldOffsets);
|
||||
FUNCTION(InitStructMetadata,
|
||||
swift_initStructMetadata, DefaultCC,
|
||||
RETURNS(VoidTy),
|
||||
ARGS(SizeTy, Int8PtrPtrTy->getPointerTo(),
|
||||
SizeTy->getPointerTo(), WitnessTablePtrTy),
|
||||
ARGS(TypeMetadataPtrTy, SizeTy, SizeTy, Int8PtrPtrTy->getPointerTo(0),
|
||||
SizeTy->getPointerTo()),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
// void swift_initEnumValueWitnessTableSinglePayload(value_witness_table_t *vwt,
|
||||
// TypeLayout *payload,
|
||||
// unsigned num_empty_cases);
|
||||
FUNCTION(InitEnumValueWitnessTableSinglePayload,
|
||||
swift_initEnumValueWitnessTableSinglePayload,
|
||||
// void swift_initEnumMetadataSingleCase(Metadata *enumType,
|
||||
// EnumLayoutFlags flags,
|
||||
// TypeLayout *payload);
|
||||
FUNCTION(InitEnumMetadataSingleCase,
|
||||
swift_initEnumMetadataSingleCase,
|
||||
DefaultCC,
|
||||
RETURNS(VoidTy),
|
||||
ARGS(WitnessTablePtrTy, Int8PtrPtrTy, Int32Ty),
|
||||
ARGS(TypeMetadataPtrTy, SizeTy, Int8PtrPtrTy),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
// void swift_initEnumMetadataMultiPayload(value_witness_table_t *vwt,
|
||||
// Metadata *enumType,
|
||||
// void swift_initEnumMetadataSinglePayload(Metadata *enumType,
|
||||
// EnumLayoutFlags flags,
|
||||
// TypeLayout *payload,
|
||||
// unsigned num_empty_cases);
|
||||
FUNCTION(InitEnumMetadataSinglePayload,
|
||||
swift_initEnumMetadataSinglePayload,
|
||||
DefaultCC,
|
||||
RETURNS(VoidTy),
|
||||
ARGS(TypeMetadataPtrTy, SizeTy, Int8PtrPtrTy, Int32Ty),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
// void swift_initEnumMetadataMultiPayload(Metadata *enumType,
|
||||
// size_t numPayloads,
|
||||
// TypeLayout * const *payloadTypes);
|
||||
FUNCTION(InitEnumMetadataMultiPayload,
|
||||
swift_initEnumMetadataMultiPayload,
|
||||
DefaultCC,
|
||||
RETURNS(VoidTy),
|
||||
ARGS(WitnessTablePtrTy, TypeMetadataPtrTy, SizeTy,
|
||||
Int8PtrPtrTy->getPointerTo(0)),
|
||||
ARGS(TypeMetadataPtrTy, SizeTy, SizeTy, Int8PtrPtrTy->getPointerTo(0)),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
// int swift_getEnumCaseSinglePayload(opaque_t *obj, Metadata *payload,
|
||||
|
||||
@@ -226,7 +226,7 @@ public:
|
||||
/// Fixed-size types never need dynamic value witness table instantiation.
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {}
|
||||
|
||||
void collectArchetypeMetadata(
|
||||
|
||||
@@ -130,6 +130,14 @@
|
||||
using namespace swift;
|
||||
using namespace irgen;
|
||||
|
||||
static llvm::Constant *emitEnumLayoutFlags(IRGenModule &IGM, bool isVWTMutable){
|
||||
// For now, we always use the Swift 5 algorithm.
|
||||
auto flags = EnumLayoutFlags::Swift5Algorithm;
|
||||
if (isVWTMutable) flags |= EnumLayoutFlags::IsVWTMutable;
|
||||
|
||||
return IGM.getSize(Size(uintptr_t(flags)));
|
||||
}
|
||||
|
||||
SpareBitVector getBitVectorFromAPInt(const APInt &bits, unsigned startBit = 0) {
|
||||
if (startBit == 0) {
|
||||
return SpareBitVector::fromAPInt(bits);
|
||||
@@ -587,78 +595,21 @@ namespace {
|
||||
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
// Fixed-size enums don't need dynamic witness table initialization.
|
||||
if (TIK >= Fixed) return;
|
||||
|
||||
assert(!ElementsWithPayload.empty() &&
|
||||
assert(ElementsWithPayload.size() == 1 &&
|
||||
"empty singleton enum should not be dynamic!");
|
||||
|
||||
// Get the value witness table for the element.
|
||||
SILType eltTy = T.getEnumElementType(ElementsWithPayload[0].decl,
|
||||
IGM.getSILModule());
|
||||
llvm::Value *eltLayout = IGF.emitTypeLayoutRef(eltTy);
|
||||
|
||||
Address vwtAddr(vwtable, IGF.IGM.getPointerAlignment());
|
||||
Address eltLayoutAddr(eltLayout, IGF.IGM.getPointerAlignment());
|
||||
|
||||
auto getWitnessDestAndSrc = [&](ValueWitness witness,
|
||||
Address *dest,
|
||||
Address *src) {
|
||||
*dest = IGF.Builder.CreateConstArrayGEP(vwtAddr,
|
||||
unsigned(witness), IGF.IGM.getPointerSize());
|
||||
*src = IGF.Builder.CreateConstArrayGEP(eltLayoutAddr,
|
||||
unsigned(witness) - unsigned(ValueWitness::First_TypeLayoutWitness),
|
||||
IGF.IGM.getPointerSize());
|
||||
};
|
||||
|
||||
auto copyWitnessFromElt = [&](ValueWitness witness) {
|
||||
Address dest, src;
|
||||
getWitnessDestAndSrc(witness, &dest, &src);
|
||||
auto val = IGF.Builder.CreateLoad(src);
|
||||
IGF.Builder.CreateStore(val, dest);
|
||||
};
|
||||
|
||||
copyWitnessFromElt(ValueWitness::Size);
|
||||
copyWitnessFromElt(ValueWitness::Stride);
|
||||
|
||||
// Copy flags over, adding HasEnumWitnesses flag
|
||||
auto copyFlagsFromElt = [&](ValueWitness witness) -> llvm::Value* {
|
||||
Address dest, src;
|
||||
getWitnessDestAndSrc(witness, &dest, &src);
|
||||
auto val = IGF.Builder.CreateLoad(src);
|
||||
auto ewFlag = IGF.Builder.CreatePtrToInt(val, IGF.IGM.SizeTy);
|
||||
auto ewMask
|
||||
= IGF.IGM.getSize(Size(ValueWitnessFlags::HasEnumWitnesses));
|
||||
ewFlag = IGF.Builder.CreateOr(ewFlag, ewMask);
|
||||
auto flag = IGF.Builder.CreateIntToPtr(ewFlag,
|
||||
dest.getType()->getElementType());
|
||||
IGF.Builder.CreateStore(flag, dest);
|
||||
return val;
|
||||
};
|
||||
|
||||
auto flags = copyFlagsFromElt(ValueWitness::Flags);
|
||||
|
||||
// If the original type had extra inhabitants, carry over its
|
||||
// extra inhabitant flags.
|
||||
auto xiBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
|
||||
auto noXIBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
|
||||
|
||||
auto xiFlag = IGF.Builder.CreatePtrToInt(flags, IGF.IGM.SizeTy);
|
||||
auto xiMask
|
||||
= IGF.IGM.getSize(Size(ValueWitnessFlags::Enum_HasExtraInhabitants));
|
||||
xiFlag = IGF.Builder.CreateAnd(xiFlag, xiMask);
|
||||
auto xiBool = IGF.Builder.CreateICmpNE(xiFlag,
|
||||
IGF.IGM.getSize(Size(0)));
|
||||
IGF.Builder.CreateCondBr(xiBool, xiBB, noXIBB);
|
||||
|
||||
IGF.Builder.emitBlock(xiBB);
|
||||
ConditionalDominanceScope condition(IGF);
|
||||
copyWitnessFromElt(ValueWitness::ExtraInhabitantFlags);
|
||||
IGF.Builder.CreateBr(noXIBB);
|
||||
|
||||
IGF.Builder.emitBlock(noXIBB);
|
||||
auto payloadTy = T.getEnumElementType(ElementsWithPayload[0].decl,
|
||||
IGM.getSILModule());
|
||||
auto payloadLayout = IGF.emitTypeLayoutRef(payloadTy);
|
||||
auto flags = emitEnumLayoutFlags(IGF.IGM, isVWTMutable);
|
||||
IGF.Builder.CreateCall(
|
||||
IGF.IGM.getInitEnumMetadataSingleCaseFn(),
|
||||
{metadata, flags, payloadLayout});
|
||||
}
|
||||
|
||||
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
|
||||
@@ -904,7 +855,7 @@ namespace {
|
||||
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
// No-payload enums are always fixed-size so never need dynamic value
|
||||
// witness table initialization.
|
||||
@@ -2846,7 +2797,7 @@ namespace {
|
||||
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
// Fixed-size enums don't need dynamic witness table initialization.
|
||||
if (TIK >= Fixed) return;
|
||||
@@ -2858,10 +2809,10 @@ namespace {
|
||||
auto payloadLayout = IGF.emitTypeLayoutRef(payloadTy);
|
||||
auto emptyCasesVal = llvm::ConstantInt::get(IGF.IGM.Int32Ty,
|
||||
ElementsWithNoPayload.size());
|
||||
|
||||
auto flags = emitEnumLayoutFlags(IGF.IGM, isVWTMutable);
|
||||
IGF.Builder.CreateCall(
|
||||
IGF.IGM.getInitEnumValueWitnessTableSinglePayloadFn(),
|
||||
{vwtable, payloadLayout, emptyCasesVal});
|
||||
IGF.IGM.getInitEnumMetadataSinglePayloadFn(),
|
||||
{metadata, flags, payloadLayout, emptyCasesVal});
|
||||
}
|
||||
|
||||
/// \group Extra inhabitants
|
||||
@@ -4744,7 +4695,7 @@ namespace {
|
||||
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
// Fixed-size enums don't need dynamic metadata initialization.
|
||||
if (TIK >= Fixed) return;
|
||||
@@ -4754,8 +4705,9 @@ namespace {
|
||||
auto numPayloadsVal = llvm::ConstantInt::get(IGF.IGM.SizeTy,
|
||||
ElementsWithPayload.size());
|
||||
|
||||
auto flags = emitEnumLayoutFlags(IGF.IGM, isVWTMutable);
|
||||
IGF.Builder.CreateCall(IGF.IGM.getInitEnumMetadataMultiPayloadFn(),
|
||||
{vwtable, metadata, numPayloadsVal,
|
||||
{metadata, flags, numPayloadsVal,
|
||||
payloadLayoutArray});
|
||||
}
|
||||
|
||||
@@ -5139,7 +5091,7 @@ namespace {
|
||||
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
llvm_unreachable("resilient enums cannot be defined");
|
||||
}
|
||||
@@ -5392,9 +5344,9 @@ namespace {
|
||||
}
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
return Strategy.initializeMetadata(IGF, metadata, vwtable, T);
|
||||
return Strategy.initializeMetadata(IGF, metadata, isVWTMutable, T);
|
||||
}
|
||||
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
|
||||
return Strategy.mayHaveExtraInhabitants(IGM);
|
||||
|
||||
@@ -372,7 +372,7 @@ public:
|
||||
|
||||
virtual void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const = 0;
|
||||
|
||||
virtual bool mayHaveExtraInhabitants(IRGenModule &IGM) const = 0;
|
||||
|
||||
@@ -2779,14 +2779,9 @@ namespace {
|
||||
bool HasDependentMetadata = false;
|
||||
|
||||
/// Set to true if the value witness table for the generic type is dependent
|
||||
/// on its generic parameters. If true, the value witness will be
|
||||
/// tail-emplaced inside the metadata pattern and initialized by the fill
|
||||
/// function. Implies HasDependentMetadata.
|
||||
/// on its generic parameters. Implies HasDependentMetadata.
|
||||
bool HasDependentVWT = false;
|
||||
|
||||
/// The offset of the tail-allocated dependent VWT, if any.
|
||||
Size DependentVWTPoint = Size::invalid();
|
||||
|
||||
template <class... T>
|
||||
GenericMetadataBuilderBase(IRGenModule &IGM, T &&...args)
|
||||
: super(IGM, std::forward<T>(args)...) {}
|
||||
@@ -2852,31 +2847,13 @@ namespace {
|
||||
value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
|
||||
IGF.Builder.CreateStore(value, dest);
|
||||
}
|
||||
|
||||
// Initialize the instantiated dependent value witness table, if we have
|
||||
// one.
|
||||
llvm::Value *vwtableValue = nullptr;
|
||||
if (HasDependentVWT) {
|
||||
assert(!AddressPoint.isInvalid() && "did not set valid address point!");
|
||||
assert(!DependentVWTPoint.isInvalid() && "did not set dependent VWT point!");
|
||||
|
||||
// Fill in the pointer from the metadata to the VWT. The VWT pointer
|
||||
// always immediately precedes the address point.
|
||||
auto vwtAddr = createPointerSizedGEP(IGF, metadataWords,
|
||||
DependentVWTPoint - AddressPoint);
|
||||
vwtableValue = IGF.Builder.CreateBitCast(vwtAddr.getAddress(),
|
||||
IGF.IGM.WitnessTablePtrTy);
|
||||
|
||||
auto vwtAddrVal = IGF.Builder.CreateBitCast(vwtableValue, IGM.Int8PtrTy);
|
||||
auto vwtRefAddr = createPointerSizedGEP(IGF, metadataWords,
|
||||
Size(0) - IGM.getPointerSize());
|
||||
IGF.Builder.CreateStore(vwtAddrVal, vwtRefAddr);
|
||||
|
||||
// A dependent VWT means that we have dependent metadata.
|
||||
if (HasDependentVWT)
|
||||
HasDependentMetadata = true;
|
||||
}
|
||||
|
||||
if (HasDependentMetadata) {
|
||||
asImpl().emitInitializeMetadata(IGF, metadataValue, vwtableValue);
|
||||
asImpl().emitInitializeMetadata(IGF, metadataValue, false);
|
||||
}
|
||||
|
||||
// The metadata is now complete.
|
||||
@@ -2912,13 +2889,6 @@ namespace {
|
||||
// Lay out the template data.
|
||||
super::layout();
|
||||
|
||||
// If we have a dependent value witness table, emit its template.
|
||||
if (HasDependentVWT) {
|
||||
// Note the dependent VWT offset.
|
||||
DependentVWTPoint = getNextOffsetFromTemplateHeader();
|
||||
asImpl().addDependentValueWitnessTablePattern();
|
||||
}
|
||||
|
||||
// Fill in the header:
|
||||
|
||||
// Metadata *(*CreateFunction)(GenericMetadata *, const void*);
|
||||
@@ -3009,7 +2979,7 @@ namespace {
|
||||
void irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
|
||||
SILType T,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable) {
|
||||
bool isVWTMutable) {
|
||||
auto *target = T.getNominalOrBoundGenericNominal();
|
||||
llvm::Value *fieldVector
|
||||
= emitAddressOfFieldOffsetVector(IGF, metadata, target)
|
||||
@@ -3045,15 +3015,18 @@ void irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
|
||||
auto numFields = IGF.IGM.getSize(Size(storedProperties.size()));
|
||||
|
||||
if (isa<ClassDecl>(target)) {
|
||||
assert(vwtable == nullptr);
|
||||
IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
|
||||
{metadata, numFields,
|
||||
fields.getAddress(), fieldVector});
|
||||
} else {
|
||||
assert(isa<StructDecl>(target));
|
||||
IGF.Builder.CreateCall(IGF.IGM.getInitStructMetadataUniversalFn(),
|
||||
{numFields, fields.getAddress(),
|
||||
fieldVector, vwtable});
|
||||
StructLayoutFlags flags = StructLayoutFlags::Swift5Algorithm;
|
||||
if (isVWTMutable)
|
||||
flags |= StructLayoutFlags::IsVWTMutable;
|
||||
|
||||
IGF.Builder.CreateCall(IGF.IGM.getInitStructMetadataFn(),
|
||||
{metadata, IGF.IGM.getSize(Size(uintptr_t(flags))),
|
||||
numFields, fields.getAddress(), fieldVector});
|
||||
}
|
||||
|
||||
IGF.Builder.CreateLifetimeEnd(fields,
|
||||
@@ -3505,8 +3478,7 @@ namespace {
|
||||
auto classTy = Target->getDeclaredTypeInContext()->getCanonicalType();
|
||||
auto loweredClassTy = IGF.IGM.getLoweredType(classTy);
|
||||
emitInitializeFieldOffsetVector(IGF, loweredClassTy,
|
||||
metadata,
|
||||
/*vwtable=*/nullptr);
|
||||
metadata, /*VWT is mutable*/ false);
|
||||
|
||||
// Realizing the class with the ObjC runtime will copy back to the
|
||||
// field offset globals for us; but if ObjC interop is disabled, we
|
||||
@@ -3923,10 +3895,6 @@ namespace {
|
||||
DependentMetaclassRODataPoint -= TemplateHeaderSize;
|
||||
}
|
||||
|
||||
void addDependentValueWitnessTablePattern() {
|
||||
llvm_unreachable("classes should never have dependent vwtables");
|
||||
}
|
||||
|
||||
void noteStartOfFieldOffsets(ClassDecl *whichClass) {}
|
||||
|
||||
void noteEndOfFieldOffsets(ClassDecl *whichClass) {}
|
||||
@@ -3960,7 +3928,7 @@ namespace {
|
||||
|
||||
void emitInitializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable) {
|
||||
bool isVWTMutable) {
|
||||
assert(!HasDependentVWT && "class should never have dependent VWT");
|
||||
|
||||
// Fill in the metaclass pointer.
|
||||
@@ -4553,12 +4521,8 @@ emitInPlaceValueTypeMetadataInitialization(IRGenFunction &IGF,
|
||||
SILType loweredType = IGF.IGM.getLoweredType(AbstractionPattern(type), type);
|
||||
auto &ti = IGF.IGM.getTypeInfo(loweredType);
|
||||
if (!ti.isFixedSize()) {
|
||||
// We assume that that value witness table will already have been written
|
||||
// into the metadata; just load it.
|
||||
llvm::Value *vwtable = IGF.emitValueWitnessTableRefForMetadata(metadata);
|
||||
|
||||
// Initialize the metadata.
|
||||
ti.initializeMetadata(IGF, metadata, vwtable, loweredType.getAddressType());
|
||||
ti.initializeMetadata(IGF, metadata, true, loweredType.getAddressType());
|
||||
}
|
||||
|
||||
return metadata;
|
||||
@@ -4659,7 +4623,7 @@ namespace {
|
||||
|
||||
void addValueWitnessTable() {
|
||||
auto type = this->Target->getDeclaredType()->getCanonicalType();
|
||||
B.add(emitValueWitnessTable(IGM, type));
|
||||
B.add(emitValueWitnessTable(IGM, type, false));
|
||||
}
|
||||
|
||||
void createMetadataAccessFunction() {
|
||||
@@ -4677,11 +4641,8 @@ namespace {
|
||||
CanType unboundType
|
||||
= decl->getDeclaredType()->getCanonicalType();
|
||||
|
||||
dependent = hasDependentValueWitnessTable(IGM, unboundType);
|
||||
if (dependent)
|
||||
return llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
|
||||
else
|
||||
return emitValueWitnessTable(IGM, unboundType);
|
||||
dependent = hasDependentValueWitnessTable(IGM, unboundType);
|
||||
return emitValueWitnessTable(IGM, unboundType, dependent);
|
||||
}
|
||||
|
||||
/// A builder for metadata templates.
|
||||
@@ -4712,18 +4673,13 @@ namespace {
|
||||
HasDependentVWT));
|
||||
}
|
||||
|
||||
void addDependentValueWitnessTablePattern() {
|
||||
emitDependentValueWitnessTablePattern(IGM, B,
|
||||
Target->getDeclaredType()->getCanonicalType());
|
||||
}
|
||||
|
||||
void emitInitializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable) {
|
||||
bool isVWTMutable) {
|
||||
// Nominal types are always preserved through SIL lowering.
|
||||
auto structTy = Target->getDeclaredTypeInContext()->getCanonicalType();
|
||||
IGM.getTypeInfoForUnlowered(structTy)
|
||||
.initializeMetadata(IGF, metadata, vwtable,
|
||||
.initializeMetadata(IGF, metadata, isVWTMutable,
|
||||
IGF.IGM.getLoweredType(structTy));
|
||||
}
|
||||
};
|
||||
@@ -4814,7 +4770,7 @@ namespace {
|
||||
|
||||
void addValueWitnessTable() {
|
||||
auto type = Target->getDeclaredType()->getCanonicalType();
|
||||
B.add(emitValueWitnessTable(IGM, type));
|
||||
B.add(emitValueWitnessTable(IGM, type, false));
|
||||
}
|
||||
|
||||
void addPayloadSize() {
|
||||
@@ -4862,11 +4818,6 @@ namespace {
|
||||
HasDependentVWT));
|
||||
}
|
||||
|
||||
void addDependentValueWitnessTablePattern() {
|
||||
emitDependentValueWitnessTablePattern(IGM, B,
|
||||
Target->getDeclaredType()->getCanonicalType());
|
||||
}
|
||||
|
||||
void addPayloadSize() {
|
||||
// In all cases where a payload size is demanded in the metadata, it's
|
||||
// runtime-dependent, so fill in a zero here.
|
||||
@@ -4880,11 +4831,11 @@ namespace {
|
||||
|
||||
void emitInitializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable) {
|
||||
bool isVWTMutable) {
|
||||
// Nominal types are always preserved through SIL lowering.
|
||||
auto enumTy = Target->getDeclaredTypeInContext()->getCanonicalType();
|
||||
IGM.getTypeInfoForUnlowered(enumTy)
|
||||
.initializeMetadata(IGF, metadata, vwtable,
|
||||
.initializeMetadata(IGF, metadata, isVWTMutable,
|
||||
IGF.IGM.getLoweredType(enumTy));
|
||||
}
|
||||
};
|
||||
@@ -5127,7 +5078,7 @@ namespace {
|
||||
|
||||
void addValueWitnessTable() {
|
||||
auto type = this->Target->getDeclaredType()->getCanonicalType();
|
||||
B.add(emitValueWitnessTable(IGM, type));
|
||||
B.add(emitValueWitnessTable(IGM, type, false));
|
||||
}
|
||||
|
||||
void flagUnfilledFieldOffset() {
|
||||
@@ -5156,7 +5107,7 @@ namespace {
|
||||
|
||||
void addValueWitnessTable() {
|
||||
auto type = this->Target->getDeclaredType()->getCanonicalType();
|
||||
B.add(emitValueWitnessTable(IGM, type));
|
||||
B.add(emitValueWitnessTable(IGM, type, false));
|
||||
}
|
||||
|
||||
void addPayloadSize() const {
|
||||
|
||||
@@ -258,7 +258,7 @@ namespace irgen {
|
||||
void emitInitializeFieldOffsetVector(IRGenFunction &IGF,
|
||||
SILType T,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable);
|
||||
bool isVWTMutable);
|
||||
|
||||
/// Adjustment indices for the address points of various metadata.
|
||||
/// Size is in words.
|
||||
|
||||
@@ -512,9 +512,9 @@ namespace {
|
||||
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
emitInitializeFieldOffsetVector(IGF, T, metadata, vwtable);
|
||||
emitInitializeFieldOffsetVector(IGF, T, metadata, isVWTMutable);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -343,7 +343,7 @@ namespace {
|
||||
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
// Tuple value witness tables are instantiated by the runtime along with
|
||||
// their metadata. We should never try to initialize one in the compiler.
|
||||
|
||||
@@ -1063,17 +1063,28 @@ static void addValueWitnessesForAbstractType(IRGenModule &IGM,
|
||||
/// Emit a value-witness table for the given type, which is assumed to
|
||||
/// be non-dependent.
|
||||
llvm::Constant *irgen::emitValueWitnessTable(IRGenModule &IGM,
|
||||
CanType abstractType) {
|
||||
CanType abstractType,
|
||||
bool isPattern) {
|
||||
// We shouldn't emit global value witness tables for generic type instances.
|
||||
assert(!isa<BoundGenericType>(abstractType) &&
|
||||
"emitting VWT for generic instance");
|
||||
|
||||
// We should never be making a pattern if the layout isn't fixed.
|
||||
// The reverse can be true for types whose layout depends on
|
||||
// resilient types.
|
||||
assert((!isPattern || hasDependentValueWitnessTable(IGM, abstractType)) &&
|
||||
"emitting VWT pattern for fixed-layout type");
|
||||
|
||||
ConstantInitBuilder builder(IGM);
|
||||
auto witnesses = builder.beginArray(IGM.Int8PtrTy);
|
||||
|
||||
bool canBeConstant = false;
|
||||
addValueWitnessesForAbstractType(IGM, witnesses, abstractType, canBeConstant);
|
||||
|
||||
// If this is just an instantiation pattern, we should never be modifying
|
||||
// it in-place.
|
||||
if (isPattern) canBeConstant = true;
|
||||
|
||||
auto addr = IGM.getAddrOfValueWitnessTable(abstractType,
|
||||
witnesses.finishAndCreateFuture());
|
||||
auto global = cast<llvm::GlobalVariable>(addr);
|
||||
@@ -1163,25 +1174,6 @@ llvm::Constant *IRGenModule::emitFixedTypeLayout(CanType t,
|
||||
return layout;
|
||||
}
|
||||
|
||||
/// Emit the elements of a dependent value witness table template into a
|
||||
/// vector.
|
||||
void irgen::emitDependentValueWitnessTablePattern(IRGenModule &IGM,
|
||||
ConstantStructBuilder &B,
|
||||
CanType abstractType) {
|
||||
// We shouldn't emit global value witness tables for generic type instances.
|
||||
assert(!isa<BoundGenericType>(abstractType) &&
|
||||
"emitting VWT for generic instance");
|
||||
|
||||
// We shouldn't emit global value witness tables for fixed-layout types.
|
||||
assert(hasDependentValueWitnessTable(IGM, abstractType) &&
|
||||
"emitting VWT pattern for fixed-layout type");
|
||||
|
||||
bool canBeConstant = false;
|
||||
auto witnesses = B.beginArray(IGM.Int8PtrTy);
|
||||
addValueWitnessesForAbstractType(IGM, witnesses, abstractType, canBeConstant);
|
||||
witnesses.finishAndAddTo(B);
|
||||
}
|
||||
|
||||
FixedPacking TypeInfo::getFixedPacking(IRGenModule &IGM) const {
|
||||
auto fixedTI = dyn_cast<FixedTypeInfo>(this);
|
||||
|
||||
|
||||
@@ -37,16 +37,13 @@ namespace irgen {
|
||||
/// dependent on its generic parameters.
|
||||
bool hasDependentValueWitnessTable(IRGenModule &IGM, CanType ty);
|
||||
|
||||
/// Emit a value-witness table for the given type, which is assumed
|
||||
/// to be non-dependent.
|
||||
llvm::Constant *emitValueWitnessTable(IRGenModule &IGM, CanType type);
|
||||
|
||||
/// Emit the elements of a dependent value witness table template into a
|
||||
/// vector.
|
||||
void emitDependentValueWitnessTablePattern(IRGenModule &IGM,
|
||||
ConstantStructBuilder &B,
|
||||
CanType abstractType);
|
||||
|
||||
/// Emit a value-witness table for the given type.
|
||||
///
|
||||
/// \param isPattern - true if the table just serves as an instantiation
|
||||
/// pattern and does not need to be modifiable in-place (if the type
|
||||
/// does not have static layout for some reason)
|
||||
llvm::Constant *emitValueWitnessTable(IRGenModule &IGM, CanType type,
|
||||
bool isPattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
|
||||
void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const override {
|
||||
// Resilient value types and archetypes always refer to an existing type.
|
||||
// A witness table should never be independently initialized for one.
|
||||
|
||||
@@ -392,7 +392,7 @@ public:
|
||||
/// for fixed-size types.
|
||||
virtual void initializeMetadata(IRGenFunction &IGF,
|
||||
llvm::Value *metadata,
|
||||
llvm::Value *vwtable,
|
||||
bool isVWTMutable,
|
||||
SILType T) const = 0;
|
||||
|
||||
/// Get the tag of a single payload enum with a payload of this type (\p T) e.g
|
||||
|
||||
@@ -975,7 +975,7 @@ public:
|
||||
// further.
|
||||
if (CaseTI != nullptr) {
|
||||
// Below logic should match the runtime function
|
||||
// swift_initEnumValueWitnessTableSinglePayload().
|
||||
// swift_initEnumMetadataSinglePayload().
|
||||
NumExtraInhabitants = CaseTI->getNumExtraInhabitants();
|
||||
if (NumExtraInhabitants >= NoPayloadCases) {
|
||||
// Extra inhabitants can encode all no-payload cases.
|
||||
|
||||
@@ -26,10 +26,45 @@
|
||||
|
||||
using namespace swift;
|
||||
|
||||
static EnumValueWitnessTable *getMutableVWTableForInit(EnumMetadata *self,
|
||||
EnumLayoutFlags flags) {
|
||||
auto oldTable =
|
||||
static_cast<const EnumValueWitnessTable *>(self->getValueWitnesses());
|
||||
|
||||
// If we can alter the existing table in-place, do so.
|
||||
if (isValueWitnessTableMutable(flags))
|
||||
return const_cast<EnumValueWitnessTable*>(oldTable);
|
||||
|
||||
// Otherwise, allocate permanent memory for it and copy the existing table.
|
||||
void *memory = allocateMetadata(sizeof(EnumValueWitnessTable),
|
||||
alignof(EnumValueWitnessTable));
|
||||
auto newTable = new (memory) EnumValueWitnessTable(*oldTable);
|
||||
self->setValueWitnesses(newTable);
|
||||
|
||||
return newTable;
|
||||
}
|
||||
|
||||
void
|
||||
swift::swift_initEnumValueWitnessTableSinglePayload(ValueWitnessTable *vwtable,
|
||||
const TypeLayout *payloadLayout,
|
||||
unsigned emptyCases) {
|
||||
swift::swift_initEnumMetadataSingleCase(EnumMetadata *self,
|
||||
EnumLayoutFlags layoutFlags,
|
||||
const TypeLayout *payloadLayout) {
|
||||
auto vwtable = getMutableVWTableForInit(self, layoutFlags);
|
||||
|
||||
vwtable->size = payloadLayout->size;
|
||||
vwtable->stride = payloadLayout->stride;
|
||||
vwtable->flags = payloadLayout->flags.withEnumWitnesses(true);
|
||||
|
||||
if (payloadLayout->flags.hasExtraInhabitants()) {
|
||||
auto ew = static_cast<ExtraInhabitantsValueWitnessTable*>(vwtable);
|
||||
ew->extraInhabitantFlags = payloadLayout->getExtraInhabitantFlags();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
swift::swift_initEnumMetadataSinglePayload(EnumMetadata *self,
|
||||
EnumLayoutFlags layoutFlags,
|
||||
const TypeLayout *payloadLayout,
|
||||
unsigned emptyCases) {
|
||||
size_t payloadSize = payloadLayout->size;
|
||||
unsigned payloadNumExtraInhabitants
|
||||
= payloadLayout->getNumExtraInhabitants();
|
||||
@@ -47,6 +82,8 @@ swift::swift_initEnumValueWitnessTableSinglePayload(ValueWitnessTable *vwtable,
|
||||
emptyCases - payloadNumExtraInhabitants,
|
||||
1 /*payload case*/);
|
||||
}
|
||||
|
||||
auto vwtable = getMutableVWTableForInit(self, layoutFlags);
|
||||
|
||||
size_t align = payloadLayout->flags.getAlignment();
|
||||
vwtable->size = size;
|
||||
@@ -128,8 +165,8 @@ void swift::swift_storeEnumTagSinglePayload(OpaqueValue *value,
|
||||
}
|
||||
|
||||
void
|
||||
swift::swift_initEnumMetadataMultiPayload(ValueWitnessTable *vwtable,
|
||||
EnumMetadata *enumType,
|
||||
swift::swift_initEnumMetadataMultiPayload(EnumMetadata *enumType,
|
||||
EnumLayoutFlags layoutFlags,
|
||||
unsigned numPayloads,
|
||||
const TypeLayout * const *payloadLayouts) {
|
||||
// Accumulate the layout requirements of the payloads.
|
||||
@@ -151,7 +188,9 @@ swift::swift_initEnumMetadataMultiPayload(ValueWitnessTable *vwtable,
|
||||
unsigned totalSize = payloadSize + getNumTagBytes(payloadSize,
|
||||
enumType->Description->Enum.getNumEmptyCases(),
|
||||
numPayloads);
|
||||
|
||||
|
||||
auto vwtable = getMutableVWTableForInit(enumType, layoutFlags);
|
||||
|
||||
// Set up the layout info in the vwtable.
|
||||
vwtable->size = totalSize;
|
||||
vwtable->flags = ValueWitnessFlags()
|
||||
|
||||
@@ -1278,25 +1278,57 @@ void swift::installCommonValueWitnesses(ValueWitnessTable *vwtable) {
|
||||
/*** Structs ***************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
static ValueWitnessTable *getMutableVWTableForInit(StructMetadata *self,
|
||||
StructLayoutFlags flags,
|
||||
bool hasExtraInhabitants) {
|
||||
auto oldTable = self->getValueWitnesses();
|
||||
|
||||
// If we can alter the existing table in-place, do so.
|
||||
if (isValueWitnessTableMutable(flags))
|
||||
return const_cast<ValueWitnessTable*>(oldTable);
|
||||
|
||||
// Otherwise, allocate permanent memory for it and copy the existing table.
|
||||
ValueWitnessTable *newTable;
|
||||
if (hasExtraInhabitants) {
|
||||
void *memory = allocateMetadata(sizeof(ExtraInhabitantsValueWitnessTable),
|
||||
alignof(ExtraInhabitantsValueWitnessTable));
|
||||
newTable = new (memory) ExtraInhabitantsValueWitnessTable(
|
||||
*static_cast<const ExtraInhabitantsValueWitnessTable*>(oldTable));
|
||||
} else {
|
||||
void *memory = allocateMetadata(sizeof(ValueWitnessTable),
|
||||
alignof(ValueWitnessTable));
|
||||
newTable = new (memory) ValueWitnessTable(*oldTable);
|
||||
}
|
||||
self->setValueWitnesses(newTable);
|
||||
|
||||
return newTable;
|
||||
}
|
||||
|
||||
/// Initialize the value witness table and struct field offset vector for a
|
||||
/// struct, using the "Universal" layout strategy.
|
||||
void swift::swift_initStructMetadata_UniversalStrategy(size_t numFields,
|
||||
void swift::swift_initStructMetadata(StructMetadata *structType,
|
||||
StructLayoutFlags layoutFlags,
|
||||
size_t numFields,
|
||||
const TypeLayout * const *fieldTypes,
|
||||
size_t *fieldOffsets,
|
||||
ValueWitnessTable *vwtable) {
|
||||
size_t *fieldOffsets) {
|
||||
auto layout = BasicLayout::initialForValueType();
|
||||
performBasicLayout(layout, fieldTypes, numFields,
|
||||
[&](size_t i, const TypeLayout *fieldType, size_t offset) {
|
||||
assignUnlessEqual(fieldOffsets[i], offset);
|
||||
});
|
||||
|
||||
bool hasExtraInhabitants = fieldTypes[0]->flags.hasExtraInhabitants();
|
||||
|
||||
auto vwtable =
|
||||
getMutableVWTableForInit(structType, layoutFlags, hasExtraInhabitants);
|
||||
|
||||
vwtable->size = layout.size;
|
||||
vwtable->flags = layout.flags;
|
||||
vwtable->stride = layout.stride;
|
||||
|
||||
// We have extra inhabitants if the first element does.
|
||||
// FIXME: generalize this.
|
||||
if (fieldTypes[0]->flags.hasExtraInhabitants()) {
|
||||
if (hasExtraInhabitants) {
|
||||
vwtable->flags = vwtable->flags.withExtraInhabitants(true);
|
||||
auto xiVWT = cast<ExtraInhabitantsValueWitnessTable>(vwtable);
|
||||
xiVWT->extraInhabitantFlags = fieldTypes[0]->getExtraInhabitantFlags();
|
||||
@@ -2900,3 +2932,6 @@ void MetadataAllocator::Deallocate(const void *allocation, size_t size) {
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void *swift::allocateMetadata(size_t size, size_t alignment) {
|
||||
return MetadataAllocator().Allocate(size, alignment);
|
||||
}
|
||||
|
||||
@@ -193,6 +193,8 @@ namespace swift {
|
||||
#endif
|
||||
}
|
||||
|
||||
void *allocateMetadata(size_t size, size_t align);
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif /* SWIFT_RUNTIME_PRIVATE_H */
|
||||
|
||||
@@ -105,6 +105,11 @@ import Swift
|
||||
// implementations which are used if the instance has extra inhabitants.
|
||||
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
|
||||
// CHECK: [[DYNAMICSINGLETON_FIELD_NAMES:@.*]] = private constant [7 x i8] c"value\00\00"
|
||||
// CHECK: @_T04enum16DynamicSingletonOWV =
|
||||
// CHECK-SAME: i8* null
|
||||
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum16DynamicSingletonOwxs to i8*)
|
||||
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum16DynamicSingletonOwxg to i8*)
|
||||
|
||||
// CHECK: [[DYNAMICSINGLETON_NAME:@.*]] = private constant [25 x i8] c"4enum16DynamicSingletonO\00"
|
||||
// CHECK: @_T04enum16DynamicSingletonOMn = hidden constant <{ {{.*}} i32 }> <{
|
||||
// CHECK-SAME: [25 x i8]* [[DYNAMICSINGLETON_NAME]]
|
||||
@@ -128,12 +133,10 @@ import Swift
|
||||
// CHECK-SAME: i32 1
|
||||
// CHECK-SAME: }>
|
||||
|
||||
// CHECK: @_T04enum16DynamicSingletonOMP = internal global <{ {{.*}}, [18 x i8*] }> <{
|
||||
// CHECK: @_T04enum16DynamicSingletonOMP = internal global <{ {{.*}}, %swift.type* }> <{
|
||||
// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSingleton
|
||||
// CHECK-SAME: [18 x i8*]* @_T04enum16DynamicSingletonOWV
|
||||
// CHECK-SAME: @_T04enum16DynamicSingletonOMn
|
||||
// CHECK-SAME: i8* null
|
||||
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum16DynamicSingletonOwxs to i8*)
|
||||
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum16DynamicSingletonOwxg to i8*)
|
||||
|
||||
// -- No-payload enums have extra inhabitants in
|
||||
// their value witness table.
|
||||
@@ -171,13 +174,15 @@ import Swift
|
||||
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum19SinglePayloadNestedOwxg to i8*)
|
||||
// CHECK-SAME: ]
|
||||
|
||||
|
||||
// CHECK: @_T04enum20DynamicSinglePayloadOMP = internal global <{ {{.*}}, [18 x i8*] }> <{
|
||||
// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload
|
||||
// CHECK: @_T04enum20DynamicSinglePayloadOWV = internal constant [18 x i8*] [
|
||||
// CHECK-SAME: i8* null
|
||||
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxs to i8*)
|
||||
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxg to i8*)
|
||||
|
||||
// CHECK: @_T04enum20DynamicSinglePayloadOMP = internal global <{ {{.*}}, %swift.type* }> <{
|
||||
// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload
|
||||
// CHECK-SAME: [18 x i8*]* @_T04enum20DynamicSinglePayloadOWV
|
||||
|
||||
// CHECK: @_T04enum18MultiPayloadNestedOWV = internal constant [18 x i8*] [
|
||||
// -- size
|
||||
// CHECK-32-SAME: i8* inttoptr ([[WORD]] 5 to i8*),
|
||||
@@ -2682,8 +2687,7 @@ entry(%x : $*MyOptional):
|
||||
return %tuple : $()
|
||||
}
|
||||
|
||||
// -- Fill function for dynamic singleton. The value witness table flags just
|
||||
// get copied over from the element.
|
||||
// -- Fill function for dynamic singleton.
|
||||
// CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_DynamicSingleton(%swift.type_pattern*, i8**) {{.*}} {
|
||||
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
|
||||
// CHECK: [[T:%T]] = load %swift.type*, %swift.type** [[T0]],
|
||||
@@ -2692,48 +2696,17 @@ entry(%x : $*MyOptional):
|
||||
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 2
|
||||
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[T]] to i8*
|
||||
// CHECK: store i8* [[T0]], i8** [[T1]]
|
||||
// CHECK: [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 3
|
||||
// CHECK: [[T0:%.*]] = bitcast i8** [[VWT]] to i8*
|
||||
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -1
|
||||
// CHECK: store i8* [[T0]], i8** [[T1]]
|
||||
// CHECK: [[T_VWTS:%.*]] = bitcast %swift.type* [[T]] to i8***
|
||||
// CHECK: [[T_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[T_VWTS]], [[WORD]] -1
|
||||
// CHECK: [[T_VWT:%.*]] = load i8**, i8*** [[T_VWT_ADDR]]
|
||||
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VWT]], i32 9
|
||||
// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
|
||||
// CHECK: [[T_SIZE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[T_LAYOUT]], i32 0
|
||||
// CHECK: [[T_SIZE:%.*]] = load i8*, i8** [[T_SIZE_ADDR]]
|
||||
// CHECK: store i8* [[T_SIZE]], i8** [[SIZE_ADDR]]
|
||||
// CHECK: [[STRIDE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 11
|
||||
// CHECK: [[T_STRIDE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[T_LAYOUT]], i32 2
|
||||
// CHECK: [[T_STRIDE:%.*]] = load i8*, i8** [[T_STRIDE_ADDR]]
|
||||
// CHECK: store i8* [[T_STRIDE]], i8** [[STRIDE_ADDR]]
|
||||
// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
|
||||
// CHECK: [[T_FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[T_LAYOUT]], i32 1
|
||||
// CHECK: [[T_FLAGS:%.*]] = load i8*, i8** [[T_FLAGS_ADDR]]
|
||||
// CHECK: [[T_FLAGS_INT:%.*]] = ptrtoint i8* [[T_FLAGS]] to [[WORD]]
|
||||
// CHECK: [[T_FLAGS_INT_2:%.*]] = or [[WORD]] [[T_FLAGS_INT]], 2097152
|
||||
// CHECK: [[T_FLAGS_2:%.*]] = inttoptr [[WORD]] [[T_FLAGS_INT_2]] to i8*
|
||||
// CHECK: store i8* [[T_FLAGS_2]], i8** [[FLAGS_ADDR]]
|
||||
// -- Test the 'has extra inhabitants' bit and carry over the extra inhabitants
|
||||
// flag if set.
|
||||
// CHECK: [[T_FLAGS_VAL:%.*]] = ptrtoint i8* [[T_FLAGS]] to [[WORD]]
|
||||
// CHECK: [[XI_FLAG:%.*]] = and [[WORD]] [[T_FLAGS_VAL]], 262144
|
||||
// CHECK: [[XI_BIT:%.*]] = icmp ne [[WORD]] [[XI_FLAG]], 0
|
||||
// CHECK: br i1 [[XI_BIT]], label %[[HAS_XI:[0-9]+]], label %[[HAS_NO_XI:[0-9]+]]
|
||||
// CHECK: ; <label>:[[HAS_XI]]
|
||||
// CHECK: [[XI_FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 12
|
||||
// CHECK: [[T_XI_FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[T_LAYOUT]], i32 3
|
||||
// CHECK: [[T_XI_FLAGS:%.*]] = load i8*, i8** [[T_XI_FLAGS_ADDR]]
|
||||
// CHECK: store i8* [[T_XI_FLAGS]], i8** [[XI_FLAGS_ADDR]]
|
||||
// CHECK: br label %[[HAS_NO_XI]]
|
||||
// CHECK: ; <label>:[[HAS_NO_XI]]
|
||||
// CHECK: call void @swift_initEnumMetadataSingleCase(%swift.type* [[METADATA]], [[WORD]] 0, i8** [[T_LAYOUT]])
|
||||
// CHECK: ret %swift.type* [[METADATA]]
|
||||
|
||||
// -- Fill function for dynamic single-payload. Call into the runtime to
|
||||
// calculate the size.
|
||||
// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_DynamicSinglePayload(%swift.type_pattern*, i8**) {{.*}} {
|
||||
// CHECK: call void @swift_initEnumValueWitnessTableSinglePayload
|
||||
// CHECK: call void @swift_initEnumMetadataSinglePayload(%swift.type* [[METADATA]], [[WORD]] 0, i8** [[T_LAYOUT]], i32 3)
|
||||
|
||||
// CHECK-64-LABEL: define linkonce_odr hidden void @_T04enum17StructWithWeakVarVwxs(%swift.opaque* noalias %dest, i32 %index, %swift.type* %StructWithWeakVar)
|
||||
// -- TODO: some pointless masking here.
|
||||
|
||||
@@ -437,4 +437,4 @@ entry(%a : $*EitherOr<T, C>, %b : $*EitherOr<T, C>):
|
||||
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 9
|
||||
// CHECK-NEXT: store i8** [[LAYOUT]], {{.*}} [[BUF1]]
|
||||
|
||||
// CHECK: call void @swift_initEnumMetadataMultiPayload(i8** {{%.*}}, %swift.type* [[METADATA]], {{i(32|64)}} 2, i8*** [[BUF0]])
|
||||
// CHECK: call void @swift_initEnumMetadataMultiPayload(%swift.type* [[METADATA]], {{i(32|64)}} 0, {{i(32|64)}} 2, i8*** [[BUF0]])
|
||||
|
||||
@@ -262,3 +262,4 @@ extension ResilientMultiPayloadGenericEnum {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_EnumWithResilientPayload(i8*)
|
||||
// CHECK: call void @swift_initEnumMetadataMultiPayload(%swift.type* {{.*}}, [[INT]] 256, [[INT]] 2, i8*** {{.*}})
|
||||
|
||||
@@ -6,7 +6,16 @@ import Builtin
|
||||
|
||||
// -- Generic structs with dynamic layout contain the vwtable pattern as part
|
||||
// of the metadata pattern, and no independent vwtable symbol
|
||||
// CHECK-NOT: @_T015generic_structs13SingleDynamicVWV
|
||||
// CHECK: @_T015generic_structs13SingleDynamicVWV = internal constant
|
||||
// CHECK-SAME: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_T015generic_structs13SingleDynamicVwCP to i8*),
|
||||
// -- ...
|
||||
// -- placeholder for size, flags, stride
|
||||
// CHECK-SAME: i8* null, i8* null, i8* null
|
||||
// -- extra inhabitants
|
||||
// CHECK-SAME: i8* null,
|
||||
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T015generic_structs13SingleDynamicVwxs to i8*),
|
||||
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T015generic_structs13SingleDynamicVwxg to i8*)]
|
||||
|
||||
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
|
||||
// CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [34 x i8] c"15generic_structs13SingleDynamicV\00"
|
||||
// CHECK: [[SINGLEDYNAMIC_FIELDS:@.*]] = private constant [3 x i8] c"x\00\00"
|
||||
@@ -35,23 +44,13 @@ import Builtin
|
||||
// CHECK: @_T015generic_structs13SingleDynamicVMP = internal global <{ {{.*}} }> <{
|
||||
// -- template header
|
||||
// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_SingleDynamic,
|
||||
// CHECK-SAME: i32 168, i16 1, i16 16, [{{[0-9]+}} x i8*] zeroinitializer,
|
||||
// -- placeholder for vwtable pointer
|
||||
// CHECK-SAME: i8* null,
|
||||
// CHECK-SAME: i32 48, i16 1, i16 16, [{{[0-9]+}} x i8*] zeroinitializer,
|
||||
// -- vwtable pointer
|
||||
// CHECK-SAME: @_T015generic_structs13SingleDynamicVWV
|
||||
// -- address point
|
||||
// CHECK-SAME: i64 1, {{.*}}* @_T015generic_structs13SingleDynamicVMn
|
||||
// -- field offset vector; generic parameter vector
|
||||
// CHECK-SAME: i64 0, %swift.type* null,
|
||||
// -- tail-allocated vwtable pattern
|
||||
// CHECK-SAME: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_T015generic_structs13SingleDynamicVwCP to i8*),
|
||||
// -- ...
|
||||
// -- placeholder for size, flags, stride
|
||||
// CHECK-SAME: i8* null, i8* null, i8* null
|
||||
// -- extra inhabitants
|
||||
// CHECK-SAME: i8* null,
|
||||
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T015generic_structs13SingleDynamicVwxs to i8*),
|
||||
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T015generic_structs13SingleDynamicVwxg to i8*)] }>
|
||||
// CHECK-NOT: @_T015generic_structs13SingleDynamicVWV
|
||||
// CHECK-SAME: i64 0, %swift.type* null }>
|
||||
|
||||
// -- Nominal type descriptor for generic struct with protocol requirements
|
||||
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
|
||||
@@ -82,8 +81,7 @@ import Builtin
|
||||
|
||||
// CHECK: @_T015generic_structs23DynamicWithRequirementsVMP = internal global <{ {{.*}} }> <{
|
||||
// -- field offset vector; generic parameter vector
|
||||
// CHECK: i64 0, i64 0, %swift.type* null, %swift.type* null, i8** null, i8** null,
|
||||
// CHECK: }>
|
||||
// CHECK: i64 0, i64 0, %swift.type* null, %swift.type* null, i8** null, i8** null }>
|
||||
|
||||
// -- Fixed-layout struct metadata contains fixed field offsets
|
||||
// CHECK: @_T015generic_structs6IntishVMf = internal constant <{ {{.*}} i64 }> <{
|
||||
@@ -219,16 +217,11 @@ entry(%0 : $*ComplexDynamic<A, B>, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Ch
|
||||
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 3
|
||||
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
|
||||
// CHECK: store i8* [[T0]], i8** [[T1]], align 8
|
||||
// Fill vwtable reference.
|
||||
// CHECK: [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 4
|
||||
// CHECK: [[VWTABLE_VAL:%.*]] = bitcast i8** [[VWTABLE_ADDR]] to i8*
|
||||
// CHECK: [[VWTABLE_SLOT_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 -1
|
||||
// CHECK: store i8* [[VWTABLE_VAL]], i8** [[VWTABLE_SLOT_ADDR]], align 8
|
||||
// Lay out fields.
|
||||
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
|
||||
// CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i64 2
|
||||
// CHECK: [[T2:%.*]] = getelementptr inbounds i8**, i8*** [[TYPES:%.*]], i32 0
|
||||
// CHECK: call void @swift_initStructMetadata_UniversalStrategy(i64 1, i8*** [[TYPES]], i64* [[T1]], i8** [[VWTABLE_ADDR]])
|
||||
// CHECK: call void @swift_initStructMetadata(%swift.type* [[METADATA]], i64 0, i64 1, i8*** [[TYPES]], i64* [[T1]])
|
||||
// CHECK: ret %swift.type* [[METADATA]]
|
||||
// CHECK: }
|
||||
|
||||
|
||||
@@ -170,7 +170,6 @@ public func partialApplyOfResilientMethod(s: Size) {
|
||||
|
||||
// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_StructWithResilientStorage(i8*)
|
||||
// CHECK: [[FIELDS:%.*]] = alloca [4 x i8**]
|
||||
// CHECK: [[VWT:%.*]] = load i8**, i8*** getelementptr inbounds ({{.*}} @_T017struct_resilience26StructWithResilientStorageVMf{{.*}}, [[INT]] -1)
|
||||
|
||||
// CHECK: [[FIELDS_ADDR:%.*]] = getelementptr inbounds [4 x i8**], [4 x i8**]* [[FIELDS]], i32 0, i32 0
|
||||
|
||||
@@ -195,6 +194,6 @@ public func partialApplyOfResilientMethod(s: Size) {
|
||||
// CHECK: [[FIELD_4:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 3
|
||||
// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_4]]
|
||||
|
||||
// CHECK: call void @swift_initStructMetadata_UniversalStrategy([[INT]] 4, i8*** [[FIELDS_ADDR]], [[INT]]* {{.*}}, i8** [[VWT]])
|
||||
// CHECK: call void @swift_initStructMetadata(%swift.type* {{.*}}, [[INT]] 256, [[INT]] 4, i8*** [[FIELDS_ADDR]], [[INT]]* {{.*}})
|
||||
// CHECK: store atomic %swift.type* {{.*}} @_T017struct_resilience26StructWithResilientStorageVMf{{.*}}, %swift.type** @_T017struct_resilience26StructWithResilientStorageVML release,
|
||||
// CHECK: ret void
|
||||
|
||||
@@ -7,6 +7,6 @@ void _swift_slowAlloc(void) {}
|
||||
void _swift_slowDealloc(void) {}
|
||||
void _swift_storeEnumTagSinglePayload(void) {}
|
||||
void swift_allocateGenericValueMetadata(void) {}
|
||||
void swift_initEnumValueWitnessTableSinglePayload(void) {}
|
||||
void swift_initEnumMetadataSinglePayload(void) {}
|
||||
void _swift_retain(){}
|
||||
void swift_allocBox(){}
|
||||
|
||||
Reference in New Issue
Block a user