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:
John McCall
2017-12-20 20:56:33 -05:00
parent 6c1f682af9
commit 9bbbe2c418
26 changed files with 316 additions and 302 deletions

View File

@@ -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
```

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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

View File

@@ -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,

View File

@@ -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(

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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);
}
};

View File

@@ -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.

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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.

View File

@@ -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()

View File

@@ -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);
}

View File

@@ -193,6 +193,8 @@ namespace swift {
#endif
}
void *allocateMetadata(size_t size, size_t align);
} // end namespace swift
#endif /* SWIFT_RUNTIME_PRIVATE_H */

View File

@@ -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.

View File

@@ -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]])

View File

@@ -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*** {{.*}})

View File

@@ -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: }

View File

@@ -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

View File

@@ -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(){}