mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge remote-tracking branch 'origin/master' into master-llvm-swift5-transition
This commit is contained in:
@@ -1021,6 +1021,10 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
|
|||||||
/// Only meaningful for class descriptors.
|
/// Only meaningful for class descriptors.
|
||||||
Class_SuperclassReferenceKind = 12,
|
Class_SuperclassReferenceKind = 12,
|
||||||
Class_SuperclassReferenceKind_width = 2,
|
Class_SuperclassReferenceKind_width = 2,
|
||||||
|
|
||||||
|
/// Whether the immediate class members in this metadata are allocated
|
||||||
|
/// at negative offsets. For now, we don't use this.
|
||||||
|
Class_AreImmediateMembersNegative = 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -1037,6 +1041,9 @@ public:
|
|||||||
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasResilientSuperclass,
|
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasResilientSuperclass,
|
||||||
class_hasResilientSuperclass,
|
class_hasResilientSuperclass,
|
||||||
class_setHasResilientSuperclass)
|
class_setHasResilientSuperclass)
|
||||||
|
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_AreImmediateMembersNegative,
|
||||||
|
class_areImmediateMembersNegative,
|
||||||
|
class_setAreImmediateMembersNegative)
|
||||||
|
|
||||||
FLAGSET_DEFINE_FIELD_ACCESSORS(Class_SuperclassReferenceKind,
|
FLAGSET_DEFINE_FIELD_ACCESSORS(Class_SuperclassReferenceKind,
|
||||||
Class_SuperclassReferenceKind_width,
|
Class_SuperclassReferenceKind_width,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ protected:
|
|||||||
if (value) {
|
if (value) {
|
||||||
Bits |= maskFor<Bit>();
|
Bits |= maskFor<Bit>();
|
||||||
} else {
|
} else {
|
||||||
Bits |= ~maskFor<Bit>();
|
Bits &= ~maskFor<Bit>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ public:
|
|||||||
return StoredPointer();
|
return StoredPointer();
|
||||||
|
|
||||||
auto classMeta = cast<TargetClassMetadata<Runtime>>(meta);
|
auto classMeta = cast<TargetClassMetadata<Runtime>>(meta);
|
||||||
return classMeta->SuperClass;
|
return classMeta->Superclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a remote pointer to class metadata, attempt to discover its class
|
/// Given a remote pointer to class metadata, attempt to discover its class
|
||||||
@@ -537,32 +537,24 @@ public:
|
|||||||
///
|
///
|
||||||
/// The offset is in units of words, from the start of the class's
|
/// The offset is in units of words, from the start of the class's
|
||||||
/// metadata.
|
/// metadata.
|
||||||
llvm::Optional<uint32_t>
|
llvm::Optional<int32_t>
|
||||||
readGenericArgsOffset(MetadataRef metadata,
|
readGenericArgsOffset(MetadataRef metadata,
|
||||||
ContextDescriptorRef descriptor) {
|
ContextDescriptorRef descriptor) {
|
||||||
switch (descriptor->getKind()) {
|
switch (descriptor->getKind()) {
|
||||||
case ContextDescriptorKind::Class: {
|
case ContextDescriptorKind::Class: {
|
||||||
auto type = cast<TargetClassDescriptor<Runtime>>(descriptor);
|
auto type = cast<TargetClassDescriptor<Runtime>>(descriptor);
|
||||||
|
|
||||||
auto *classMetadata = dyn_cast<TargetClassMetadata<Runtime>>(metadata);
|
if (!type->hasResilientSuperclass())
|
||||||
if (!classMetadata)
|
return type->getNonResilientGenericArgumentOffset();
|
||||||
|
|
||||||
|
auto bounds = readMetadataBoundsOfSuperclass(descriptor);
|
||||||
|
if (!bounds)
|
||||||
return llvm::None;
|
return llvm::None;
|
||||||
|
|
||||||
if (!classMetadata->SuperClass)
|
bounds->adjustForSubclass(type->areImmediateMembersNegative(),
|
||||||
return type->getGenericArgumentOffset(nullptr, nullptr);
|
type->NumImmediateMembers);
|
||||||
|
|
||||||
auto superMetadata = readMetadata(classMetadata->SuperClass);
|
return bounds->ImmediateMembersOffset / sizeof(StoredPointer);
|
||||||
if (!superMetadata)
|
|
||||||
return llvm::None;
|
|
||||||
|
|
||||||
auto superClassMetadata =
|
|
||||||
dyn_cast<TargetClassMetadata<Runtime>>(superMetadata);
|
|
||||||
if (!superClassMetadata)
|
|
||||||
return llvm::None;
|
|
||||||
|
|
||||||
auto result =
|
|
||||||
type->getGenericArgumentOffset(classMetadata, superClassMetadata);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case ContextDescriptorKind::Enum: {
|
case ContextDescriptorKind::Enum: {
|
||||||
@@ -580,6 +572,76 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using ClassMetadataBounds = TargetClassMetadataBounds<Runtime>;
|
||||||
|
|
||||||
|
// This follows computeMetadataBoundsForSuperclass.
|
||||||
|
llvm::Optional<ClassMetadataBounds>
|
||||||
|
readMetadataBoundsOfSuperclass(ContextDescriptorRef subclassRef) {
|
||||||
|
auto subclass = cast<TargetClassDescriptor<Runtime>>(subclassRef);
|
||||||
|
|
||||||
|
auto rawSuperclass =
|
||||||
|
resolveNullableRelativeField(subclassRef, subclass->Superclass);
|
||||||
|
if (!rawSuperclass) {
|
||||||
|
return ClassMetadataBounds::forSwiftRootClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return forTypeReference<ClassMetadataBounds>(
|
||||||
|
subclass->getSuperclassReferenceKind(), *rawSuperclass,
|
||||||
|
[&](ContextDescriptorRef superclass)
|
||||||
|
-> llvm::Optional<ClassMetadataBounds> {
|
||||||
|
if (!isa<TargetClassDescriptor<Runtime>>(superclass))
|
||||||
|
return llvm::None;
|
||||||
|
return readMetadataBoundsOfSuperclass(superclass);
|
||||||
|
},
|
||||||
|
[&](MetadataRef metadata) -> llvm::Optional<ClassMetadataBounds> {
|
||||||
|
auto cls = dyn_cast<TargetClassMetadata<Runtime>>(metadata);
|
||||||
|
if (!cls)
|
||||||
|
return llvm::None;
|
||||||
|
|
||||||
|
return cls->getClassBoundsAsSwiftSuperclass();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Result, class DescriptorFn, class MetadataFn>
|
||||||
|
llvm::Optional<Result>
|
||||||
|
forTypeReference(TypeMetadataRecordKind refKind, StoredPointer ref,
|
||||||
|
const DescriptorFn &descriptorFn,
|
||||||
|
const MetadataFn &metadataFn) {
|
||||||
|
switch (refKind) {
|
||||||
|
case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
|
||||||
|
StoredPointer descriptorAddress = 0;
|
||||||
|
if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress))
|
||||||
|
return llvm::None;
|
||||||
|
|
||||||
|
ref = descriptorAddress;
|
||||||
|
LLVM_FALLTHROUGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
|
||||||
|
auto descriptor = readContextDescriptor(ref);
|
||||||
|
if (!descriptor)
|
||||||
|
return llvm::None;
|
||||||
|
|
||||||
|
return descriptorFn(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
case TypeMetadataRecordKind::IndirectObjCClass: {
|
||||||
|
StoredPointer classRef = 0;
|
||||||
|
if (!Reader->readInteger(RemoteAddress(ref), &classRef))
|
||||||
|
return llvm::None;
|
||||||
|
|
||||||
|
auto metadata = readMetadata(classRef);
|
||||||
|
if (!metadata)
|
||||||
|
return llvm::None;
|
||||||
|
|
||||||
|
return metadataFn(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return llvm::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Read a single generic type argument from a bound generic type
|
/// Read a single generic type argument from a bound generic type
|
||||||
/// metadata.
|
/// metadata.
|
||||||
llvm::Optional<StoredPointer>
|
llvm::Optional<StoredPointer>
|
||||||
@@ -921,7 +983,7 @@ private:
|
|||||||
if (descriptorAddress || !skipArtificialSubclasses)
|
if (descriptorAddress || !skipArtificialSubclasses)
|
||||||
return static_cast<StoredPointer>(descriptorAddress);
|
return static_cast<StoredPointer>(descriptorAddress);
|
||||||
|
|
||||||
auto superclassMetadataAddress = classMeta->SuperClass;
|
auto superclassMetadataAddress = classMeta->Superclass;
|
||||||
if (!superclassMetadataAddress)
|
if (!superclassMetadataAddress)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -799,16 +799,11 @@ FUNCTION(GetGenericMetadata, swift_getGenericMetadata, C_CC,
|
|||||||
ATTRS(NoUnwind, ReadOnly))
|
ATTRS(NoUnwind, ReadOnly))
|
||||||
|
|
||||||
// Metadata *swift_allocateGenericClassMetadata(ClassDescriptor *type,
|
// Metadata *swift_allocateGenericClassMetadata(ClassDescriptor *type,
|
||||||
// const void *template,
|
|
||||||
// size_t templateSize,
|
|
||||||
// size_t templateAddressPoint,
|
|
||||||
// const void * const *arguments,
|
// const void * const *arguments,
|
||||||
// objc_class *superclass,
|
// const void *template);
|
||||||
// size_t numImmediateMembers);
|
|
||||||
FUNCTION(AllocateGenericClassMetadata, swift_allocateGenericClassMetadata,
|
FUNCTION(AllocateGenericClassMetadata, swift_allocateGenericClassMetadata,
|
||||||
C_CC, RETURNS(TypeMetadataPtrTy),
|
C_CC, RETURNS(TypeMetadataPtrTy),
|
||||||
ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, SizeTy, SizeTy,
|
ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, Int8PtrPtrTy),
|
||||||
Int8PtrPtrTy, ObjCClassPtrTy, SizeTy),
|
|
||||||
ATTRS(NoUnwind))
|
ATTRS(NoUnwind))
|
||||||
|
|
||||||
// Metadata *swift_allocateGenericValueMetadata(ValueTypeDescriptor *type,
|
// Metadata *swift_allocateGenericValueMetadata(ValueTypeDescriptor *type,
|
||||||
|
|||||||
@@ -113,8 +113,7 @@ private:
|
|||||||
asImpl().noteStartOfImmediateMembers(theClass);
|
asImpl().noteStartOfImmediateMembers(theClass);
|
||||||
|
|
||||||
// Add space for the generic parameters, if applicable.
|
// Add space for the generic parameters, if applicable.
|
||||||
// Note that we only add references for the immediate parameters;
|
// This must always be the first item in the immediate members.
|
||||||
// parameters for the parent context are handled by the parent.
|
|
||||||
asImpl().addGenericFields(theClass, type, theClass);
|
asImpl().addGenericFields(theClass, type, theClass);
|
||||||
|
|
||||||
// Add vtable entries.
|
// Add vtable entries.
|
||||||
|
|||||||
@@ -50,12 +50,10 @@ public:
|
|||||||
// EnumMetadata header.
|
// EnumMetadata header.
|
||||||
asImpl().addNominalTypeDescriptor();
|
asImpl().addNominalTypeDescriptor();
|
||||||
|
|
||||||
// If changing this layout, you must update the magic number in
|
|
||||||
// emitParentMetadataRef.
|
|
||||||
|
|
||||||
// Instantiation-specific.
|
// Instantiation-specific.
|
||||||
|
|
||||||
// Add fields for generic cases.
|
// Generic arguments.
|
||||||
|
// This must always be the first piece of trailing data.
|
||||||
asImpl().addGenericFields(Target, Target->getDeclaredTypeInContext());
|
asImpl().addGenericFields(Target, Target->getDeclaredTypeInContext());
|
||||||
|
|
||||||
// Reserve a word to cache the payload size if the type has dynamic layout.
|
// Reserve a word to cache the payload size if the type has dynamic layout.
|
||||||
|
|||||||
@@ -3342,11 +3342,18 @@ IRGenModule::getAddrOfTypeMetadataPattern(NominalTypeDecl *D,
|
|||||||
|
|
||||||
/// Returns the address of a class metadata base offset.
|
/// Returns the address of a class metadata base offset.
|
||||||
llvm::Constant *
|
llvm::Constant *
|
||||||
IRGenModule::getAddrOfClassMetadataBaseOffset(ClassDecl *D,
|
IRGenModule::getAddrOfClassMetadataBounds(ClassDecl *D,
|
||||||
ForDefinition_t forDefinition) {
|
ForDefinition_t forDefinition) {
|
||||||
|
// StoredClassMetadataBounds
|
||||||
|
auto layoutTy = llvm::StructType::get(getLLVMContext(), {
|
||||||
|
SizeTy, // Immediate members offset
|
||||||
|
Int32Ty, // Negative size in words
|
||||||
|
Int32Ty // Positive size in words
|
||||||
|
});
|
||||||
|
|
||||||
LinkEntity entity = LinkEntity::forClassMetadataBaseOffset(D);
|
LinkEntity entity = LinkEntity::forClassMetadataBaseOffset(D);
|
||||||
return getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
|
return getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
|
||||||
SizeTy, DebugTypeInfo());
|
layoutTy, DebugTypeInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the address of a generic type's metadata instantiation cache.
|
/// Return the address of a generic type's metadata instantiation cache.
|
||||||
|
|||||||
@@ -1113,8 +1113,7 @@ static Address emitAddressOfSuperclassRefInClassMetadata(IRGenFunction &IGF,
|
|||||||
unsigned index = 1;
|
unsigned index = 1;
|
||||||
|
|
||||||
Address addr(metadata, IGF.IGM.getPointerAlignment());
|
Address addr(metadata, IGF.IGM.getPointerAlignment());
|
||||||
addr = IGF.Builder.CreateBitCast(addr,
|
addr = IGF.Builder.CreateElementBitCast(addr, IGF.IGM.TypeMetadataPtrTy);
|
||||||
IGF.IGM.TypeMetadataPtrTy->getPointerTo());
|
|
||||||
return IGF.Builder.CreateConstArrayGEP(addr, index, IGF.IGM.getPointerSize());
|
return IGF.Builder.CreateConstArrayGEP(addr, index, IGF.IGM.getPointerSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2644,19 +2643,12 @@ namespace {
|
|||||||
|
|
||||||
/// Fill in the fields of a TypeGenericContextDescriptorHeader.
|
/// Fill in the fields of a TypeGenericContextDescriptorHeader.
|
||||||
void addGenericParametersHeader() {
|
void addGenericParametersHeader() {
|
||||||
asImpl().addGenericParamsOffset();
|
|
||||||
asImpl().addMetadataInstantiationFunction();
|
asImpl().addMetadataInstantiationFunction();
|
||||||
asImpl().addMetadataInstantiationCache();
|
asImpl().addMetadataInstantiationCache();
|
||||||
|
|
||||||
super::addGenericParametersHeader();
|
super::addGenericParametersHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addGenericParamsOffset() {
|
|
||||||
// Include the offset to the generic argument vector inside a metadata
|
|
||||||
// record for this type.
|
|
||||||
B.addInt32(asImpl().getGenericParamsOffset() / IGM.getPointerSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
void addMetadataInstantiationFunction() {
|
void addMetadataInstantiationFunction() {
|
||||||
if (!HasMetadata) {
|
if (!HasMetadata) {
|
||||||
B.addInt32(0);
|
B.addInt32(0);
|
||||||
@@ -2716,7 +2708,6 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Subclasses should provide:
|
// Subclasses should provide:
|
||||||
// Size getGenericParamsOffset();
|
|
||||||
// ContextDescriptorKind getContextKind();
|
// ContextDescriptorKind getContextKind();
|
||||||
// void addLayoutInfo(); // ABI TODO: should be superseded
|
// void addLayoutInfo(); // ABI TODO: should be superseded
|
||||||
};
|
};
|
||||||
@@ -2797,7 +2788,7 @@ namespace {
|
|||||||
return cast<StructDecl>(Type);
|
return cast<StructDecl>(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Size FieldVectorOffset, GenericParamsOffset;
|
Size FieldVectorOffset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StructContextDescriptorBuilder(IRGenModule &IGM, StructDecl *Type,
|
StructContextDescriptorBuilder(IRGenModule &IGM, StructDecl *Type,
|
||||||
@@ -2805,14 +2796,9 @@ namespace {
|
|||||||
: super(IGM, Type, requireMetadata)
|
: super(IGM, Type, requireMetadata)
|
||||||
{
|
{
|
||||||
auto &layout = IGM.getMetadataLayout(getType());
|
auto &layout = IGM.getMetadataLayout(getType());
|
||||||
GenericParamsOffset = layout.getStaticGenericRequirementsOffset();
|
|
||||||
FieldVectorOffset = layout.getFieldOffsetVectorOffset().getStatic();
|
FieldVectorOffset = layout.getFieldOffsetVectorOffset().getStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
Size getGenericParamsOffset() {
|
|
||||||
return GenericParamsOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextDescriptorKind getContextKind() {
|
ContextDescriptorKind getContextKind() {
|
||||||
return ContextDescriptorKind::Struct;
|
return ContextDescriptorKind::Struct;
|
||||||
}
|
}
|
||||||
@@ -2848,7 +2834,6 @@ namespace {
|
|||||||
return cast<EnumDecl>(Type);
|
return cast<EnumDecl>(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Size GenericParamsOffset;
|
|
||||||
Size PayloadSizeOffset;
|
Size PayloadSizeOffset;
|
||||||
const EnumImplStrategy &Strategy;
|
const EnumImplStrategy &Strategy;
|
||||||
|
|
||||||
@@ -2860,15 +2845,10 @@ namespace {
|
|||||||
getType()->getDeclaredTypeInContext()->getCanonicalType()))
|
getType()->getDeclaredTypeInContext()->getCanonicalType()))
|
||||||
{
|
{
|
||||||
auto &layout = IGM.getMetadataLayout(getType());
|
auto &layout = IGM.getMetadataLayout(getType());
|
||||||
GenericParamsOffset = layout.getStaticGenericRequirementsOffset();
|
|
||||||
if (layout.hasPayloadSizeOffset())
|
if (layout.hasPayloadSizeOffset())
|
||||||
PayloadSizeOffset = layout.getPayloadSizeOffset().getStatic();
|
PayloadSizeOffset = layout.getPayloadSizeOffset().getStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
Size getGenericParamsOffset() {
|
|
||||||
return GenericParamsOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextDescriptorKind getContextKind() {
|
ContextDescriptorKind getContextKind() {
|
||||||
return ContextDescriptorKind::Enum;
|
return ContextDescriptorKind::Enum;
|
||||||
}
|
}
|
||||||
@@ -2913,44 +2893,30 @@ namespace {
|
|||||||
return cast<ClassDecl>(Type);
|
return cast<ClassDecl>(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Non-null unless the type is foreign.
|
||||||
|
ClassMetadataLayout *MetadataLayout = nullptr;
|
||||||
|
|
||||||
Optional<TypeEntityReference> SuperClassRef;
|
Optional<TypeEntityReference> SuperClassRef;
|
||||||
|
|
||||||
// Offsets of key fields in the metadata records.
|
SILVTable *VTable = nullptr;
|
||||||
Size FieldVectorOffset, GenericParamsOffset;
|
unsigned VTableSize = 0;
|
||||||
|
|
||||||
SILVTable *VTable;
|
|
||||||
|
|
||||||
Size VTableOffset;
|
|
||||||
unsigned VTableSize;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ClassContextDescriptorBuilder(IRGenModule &IGM, ClassDecl *Type,
|
ClassContextDescriptorBuilder(IRGenModule &IGM, ClassDecl *Type,
|
||||||
RequireMetadata_t requireMetadata)
|
RequireMetadata_t requireMetadata)
|
||||||
: super(IGM, Type, requireMetadata)
|
: super(IGM, Type, requireMetadata)
|
||||||
{
|
{
|
||||||
if (getType()->isForeign()) {
|
if (getType()->isForeign()) return;
|
||||||
VTable = nullptr;
|
|
||||||
VTableSize = 0;
|
MetadataLayout = &IGM.getClassMetadataLayout(Type);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto superclassDecl = getType()->getSuperclassDecl()) {
|
if (auto superclassDecl = getType()->getSuperclassDecl()) {
|
||||||
SuperClassRef = IGM.getTypeEntityReference(superclassDecl);
|
SuperClassRef = IGM.getTypeEntityReference(superclassDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &layout = IGM.getClassMetadataLayout(getType());
|
VTableSize = MetadataLayout->getVTableSize();
|
||||||
|
if (VTableSize) {
|
||||||
VTable = IGM.getSILModule().lookUpVTable(getType());
|
VTable = IGM.getSILModule().lookUpVTable(getType());
|
||||||
VTableSize = layout.getVTableSize();
|
|
||||||
|
|
||||||
if (layout.hasResilientSuperclass()) {
|
|
||||||
FieldVectorOffset = layout.getRelativeFieldOffsetVectorOffset();
|
|
||||||
GenericParamsOffset = layout.getRelativeGenericRequirementsOffset();
|
|
||||||
VTableOffset = layout.getRelativeVTableOffset();
|
|
||||||
} else {
|
|
||||||
FieldVectorOffset = layout.getStaticFieldOffsetVectorOffset();
|
|
||||||
GenericParamsOffset = layout.getStaticGenericRequirementsOffset();
|
|
||||||
VTableOffset = layout.getStaticVTableOffset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2966,14 +2932,17 @@ namespace {
|
|||||||
uint16_t getKindSpecificFlags() {
|
uint16_t getKindSpecificFlags() {
|
||||||
TypeContextDescriptorFlags flags;
|
TypeContextDescriptorFlags flags;
|
||||||
|
|
||||||
flags.setIsReflectable(true); // class is always reflectable
|
// Classes are always reflectable.
|
||||||
|
flags.setIsReflectable(true);
|
||||||
|
|
||||||
if (!getType()->isForeign()) {
|
if (!getType()->isForeign()) {
|
||||||
|
if (MetadataLayout->areImmediateMembersNegative())
|
||||||
|
flags.class_setAreImmediateMembersNegative(true);
|
||||||
|
|
||||||
if (VTableSize != 0)
|
if (VTableSize != 0)
|
||||||
flags.class_setHasVTable(true);
|
flags.class_setHasVTable(true);
|
||||||
|
|
||||||
auto &layout = IGM.getClassMetadataLayout(getType());
|
if (MetadataLayout->hasResilientSuperclass())
|
||||||
if (layout.hasResilientSuperclass())
|
|
||||||
flags.class_setHasResilientSuperclass(true);
|
flags.class_setHasResilientSuperclass(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2986,15 +2955,21 @@ namespace {
|
|||||||
return flags.getOpaqueValue();
|
return flags.getOpaqueValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
Size getGenericParamsOffset() {
|
Size getFieldVectorOffset() {
|
||||||
return GenericParamsOffset;
|
if (!MetadataLayout) return Size(0);
|
||||||
|
return (MetadataLayout->hasResilientSuperclass()
|
||||||
|
? MetadataLayout->getRelativeFieldOffsetVectorOffset()
|
||||||
|
: MetadataLayout->getStaticFieldOffsetVectorOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addVTable() {
|
void addVTable() {
|
||||||
if (VTableSize == 0)
|
if (VTableSize == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
B.addInt32(VTableOffset / IGM.getPointerSize());
|
auto offset = MetadataLayout->hasResilientSuperclass()
|
||||||
|
? MetadataLayout->getRelativeVTableOffset()
|
||||||
|
: MetadataLayout->getStaticVTableOffset();
|
||||||
|
B.addInt32(offset / IGM.getPointerSize());
|
||||||
B.addInt32(VTableSize);
|
B.addInt32(VTableSize);
|
||||||
|
|
||||||
addVTableEntries(getType());
|
addVTableEntries(getType());
|
||||||
@@ -3052,11 +3027,45 @@ namespace {
|
|||||||
B.addInt32(0);
|
B.addInt32(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// union {
|
||||||
|
// uint32_t MetadataNegativeSizeInWords;
|
||||||
|
// RelativeDirectPointer<StoredClassMetadataBounds>
|
||||||
|
// ResilientMetadataBounds;
|
||||||
|
// };
|
||||||
|
if (!MetadataLayout) {
|
||||||
|
// FIXME: do something meaningful for foreign classes?
|
||||||
|
B.addInt32(0);
|
||||||
|
} else if (!MetadataLayout->hasResilientSuperclass()) {
|
||||||
|
B.addInt32(MetadataLayout->getSize().AddressPoint
|
||||||
|
/ IGM.getPointerSize());
|
||||||
|
} else {
|
||||||
|
B.addRelativeAddress(
|
||||||
|
IGM.getAddrOfClassMetadataBounds(getType(), NotForDefinition));
|
||||||
|
}
|
||||||
|
|
||||||
|
// union {
|
||||||
|
// uint32_t MetadataPositiveSizeInWords;
|
||||||
|
// };
|
||||||
|
if (!MetadataLayout) {
|
||||||
|
// FIXME: do something meaningful for foreign classes?
|
||||||
|
B.addInt32(0);
|
||||||
|
} else if (!MetadataLayout->hasResilientSuperclass()) {
|
||||||
|
B.addInt32(MetadataLayout->getSize().getOffsetToEnd()
|
||||||
|
/ IGM.getPointerSize());
|
||||||
|
} else {
|
||||||
|
B.addInt32(0); // currently unused
|
||||||
|
}
|
||||||
|
|
||||||
|
// uint32_t NumImmediateMembers;
|
||||||
|
auto numImmediateMembers =
|
||||||
|
(MetadataLayout ? MetadataLayout->getNumImmediateMembers() : 0);
|
||||||
|
B.addInt32(numImmediateMembers);
|
||||||
|
|
||||||
// uint32_t NumFields;
|
// uint32_t NumFields;
|
||||||
B.addInt32(std::distance(properties.begin(), properties.end()));
|
B.addInt32(std::distance(properties.begin(), properties.end()));
|
||||||
|
|
||||||
// uint32_t FieldOffsetVectorOffset;
|
// uint32_t FieldOffsetVectorOffset;
|
||||||
B.addInt32(FieldVectorOffset / IGM.getPointerSize());
|
B.addInt32(getFieldVectorOffset() / IGM.getPointerSize());
|
||||||
|
|
||||||
addFieldTypes(IGM, getType(), properties);
|
addFieldTypes(IGM, getType(), properties);
|
||||||
}
|
}
|
||||||
@@ -3193,7 +3202,11 @@ void IRGenModule::addFieldTypes(ArrayRef<CanType> fieldTypes) {
|
|||||||
namespace {
|
namespace {
|
||||||
/// An adapter class which turns a metadata layout class into a
|
/// An adapter class which turns a metadata layout class into a
|
||||||
/// generic metadata layout class.
|
/// generic metadata layout class.
|
||||||
template <class Impl, class Base>
|
///
|
||||||
|
/// If AddGenericArguments is false, fill ops will be added for the
|
||||||
|
/// arguments, but space for them won't actually be built into the
|
||||||
|
/// pattern.
|
||||||
|
template <class Impl, class Base, bool AddGenericArguments = true>
|
||||||
class GenericMetadataBuilderBase : public Base {
|
class GenericMetadataBuilderBase : public Base {
|
||||||
typedef Base super;
|
typedef Base super;
|
||||||
|
|
||||||
@@ -3319,6 +3332,10 @@ namespace {
|
|||||||
|
|
||||||
TemplateSize = getNextOffsetFromTemplateHeader();
|
TemplateSize = getNextOffsetFromTemplateHeader();
|
||||||
|
|
||||||
|
asImpl().emitInstantiationDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void emitInstantiationDefinitions() {
|
||||||
asImpl().emitCreateFunction();
|
asImpl().emitCreateFunction();
|
||||||
asImpl().emitInstantiationCache();
|
asImpl().emitInstantiationCache();
|
||||||
}
|
}
|
||||||
@@ -3337,14 +3354,16 @@ namespace {
|
|||||||
template <class... T>
|
template <class... T>
|
||||||
void addGenericArgument(CanType type, T &&...args) {
|
void addGenericArgument(CanType type, T &&...args) {
|
||||||
FillOps.push_back({type, None});
|
FillOps.push_back({type, None});
|
||||||
super::addGenericArgument(type, std::forward<T>(args)...);
|
if (AddGenericArguments)
|
||||||
|
super::addGenericArgument(type, std::forward<T>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class... T>
|
template <class... T>
|
||||||
void addGenericWitnessTable(CanType type, ProtocolConformanceRef conf,
|
void addGenericWitnessTable(CanType type, ProtocolConformanceRef conf,
|
||||||
T &&...args) {
|
T &&...args) {
|
||||||
FillOps.push_back({type, conf});
|
FillOps.push_back({type, conf});
|
||||||
super::addGenericWitnessTable(type, conf, std::forward<T>(args)...);
|
if (AddGenericArguments)
|
||||||
|
super::addGenericWitnessTable(type, conf, std::forward<T>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can be overridden by subclassers to emit other dependent metadata.
|
// Can be overridden by subclassers to emit other dependent metadata.
|
||||||
@@ -3544,11 +3563,10 @@ namespace {
|
|||||||
using super::Target;
|
using super::Target;
|
||||||
using super::asImpl;
|
using super::asImpl;
|
||||||
|
|
||||||
bool HasResilientSuperclass = false;
|
|
||||||
|
|
||||||
ConstantStructBuilder &B;
|
ConstantStructBuilder &B;
|
||||||
const StructLayout &Layout;
|
const StructLayout &Layout;
|
||||||
const ClassLayout &FieldLayout;
|
const ClassLayout &FieldLayout;
|
||||||
|
ClassMetadataLayout &MetadataLayout;
|
||||||
|
|
||||||
MemberBuilder Members;
|
MemberBuilder Members;
|
||||||
|
|
||||||
@@ -3558,47 +3576,59 @@ namespace {
|
|||||||
const ClassLayout &fieldLayout)
|
const ClassLayout &fieldLayout)
|
||||||
: super(IGM, theClass), B(builder),
|
: super(IGM, theClass), B(builder),
|
||||||
Layout(layout), FieldLayout(fieldLayout),
|
Layout(layout), FieldLayout(fieldLayout),
|
||||||
|
MetadataLayout(IGM.getClassMetadataLayout(theClass)),
|
||||||
Members(IGM, theClass, builder, layout, fieldLayout) {}
|
Members(IGM, theClass, builder, layout, fieldLayout) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void noteResilientSuperclass() {
|
void noteResilientSuperclass() {}
|
||||||
HasResilientSuperclass = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void noteStartOfImmediateMembers(ClassDecl *theClass) {
|
void noteStartOfImmediateMembers(ClassDecl *theClass) {
|
||||||
|
if (theClass == Target) {
|
||||||
|
emitClassMetadataBaseOffset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Emit the base-offset variable for the class.
|
||||||
|
void emitClassMetadataBaseOffset() {
|
||||||
// Only classes defined in resilient modules, or those that have
|
// Only classes defined in resilient modules, or those that have
|
||||||
// a resilient superclass need this.
|
// a resilient superclass need this.
|
||||||
if (!HasResilientSuperclass &&
|
if (!MetadataLayout.hasResilientSuperclass() &&
|
||||||
!IGM.isResilient(theClass, ResilienceExpansion::Minimal)) {
|
!IGM.isResilient(Target, ResilienceExpansion::Minimal)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theClass == Target) {
|
auto *offsetAddr =
|
||||||
auto *offsetAddr =
|
IGM.getAddrOfClassMetadataBounds(Target, ForDefinition);
|
||||||
IGM.getAddrOfClassMetadataBaseOffset(theClass,
|
auto *offsetVar = cast<llvm::GlobalVariable>(offsetAddr);
|
||||||
ForDefinition);
|
|
||||||
auto *offsetVar = cast<llvm::GlobalVariable>(offsetAddr);
|
|
||||||
|
|
||||||
if (HasResilientSuperclass) {
|
if (MetadataLayout.hasResilientSuperclass()) {
|
||||||
// If the superclass is resilient to us, we have to compute and
|
// If the superclass is resilient to us, we have to compute and
|
||||||
// initialize the global when we initialize the metadata.
|
// initialize the global when we initialize the metadata.
|
||||||
auto *init = llvm::ConstantInt::get(IGM.SizeTy, 0);
|
auto init = llvm::ConstantAggregateZero::get(offsetVar->getValueType());
|
||||||
|
|
||||||
offsetVar->setInitializer(init);
|
|
||||||
offsetVar->setConstant(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we know the offset at compile time, even if our
|
|
||||||
// clients do not, so just emit a constant.
|
|
||||||
auto &layout = IGM.getClassMetadataLayout(theClass);
|
|
||||||
|
|
||||||
auto value = layout.getStartOfImmediateMembers();
|
|
||||||
auto *init = llvm::ConstantInt::get(IGM.SizeTy, value.getValue());
|
|
||||||
|
|
||||||
offsetVar->setInitializer(init);
|
offsetVar->setInitializer(init);
|
||||||
offsetVar->setConstant(true);
|
offsetVar->setConstant(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, we know the offset at compile time, even if our
|
||||||
|
// clients do not, so just emit a constant.
|
||||||
|
auto &layout = IGM.getClassMetadataLayout(Target);
|
||||||
|
|
||||||
|
auto immediateMembersOffset = layout.getStartOfImmediateMembers();
|
||||||
|
auto size = layout.getSize();
|
||||||
|
auto negativeSizeInWords = size.AddressPoint / IGM.getPointerSize();
|
||||||
|
auto positiveSizeInWords = size.getOffsetToEnd() / IGM.getPointerSize();
|
||||||
|
|
||||||
|
auto initTy = cast<llvm::StructType>(offsetVar->getValueType());
|
||||||
|
auto *init = llvm::ConstantStruct::get(initTy, {
|
||||||
|
llvm::ConstantInt::get(IGM.SizeTy, immediateMembersOffset.getValue()),
|
||||||
|
llvm::ConstantInt::get(IGM.Int32Ty, negativeSizeInWords),
|
||||||
|
llvm::ConstantInt::get(IGM.Int32Ty, positiveSizeInWords)
|
||||||
|
});
|
||||||
|
|
||||||
|
offsetVar->setInitializer(init);
|
||||||
|
offsetVar->setConstant(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The 'metadata flags' field in a class is actually a pointer to
|
/// The 'metadata flags' field in a class is actually a pointer to
|
||||||
@@ -3744,13 +3774,13 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addClassSize() {
|
void addClassSize() {
|
||||||
auto size = IGM.getMetadataLayout(Target).getSize();
|
auto size = MetadataLayout.getSize();
|
||||||
B.addInt32(size.FullSize.getValue());
|
B.addInt32(size.FullSize.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addClassAddressPoint() {
|
void addClassAddressPoint() {
|
||||||
// FIXME: Wrong
|
// FIXME: Wrong
|
||||||
auto size = IGM.getMetadataLayout(Target).getSize();
|
auto size = MetadataLayout.getSize();
|
||||||
B.addInt32(size.AddressPoint.getValue());
|
B.addInt32(size.AddressPoint.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3857,52 +3887,20 @@ namespace {
|
|||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the runtime-computed metadata size of our superclass into the
|
/// Materialize type metadata for the given type and store it into the
|
||||||
// target class's metadata base offset global variable.
|
/// superclass field of the given metadata.
|
||||||
//
|
void emitStoreOfSuperclass(IRGenFunction &IGF, CanType superclassType,
|
||||||
// Note that this code will run for each generic instantiation of the
|
llvm::Value *metadata) {
|
||||||
// class, if the class is generic. This should be OK because the
|
llvm::Value *superMetadata =
|
||||||
// metadata size does not change between generic instantiations, so
|
emitClassHeapMetadataRef(IGF, superclassType,
|
||||||
// all stores after the first should be idempotent.
|
MetadataValueType::TypeMetadata,
|
||||||
void emitInitializeClassMetadataBaseOffset(IRGenFunction &IGF,
|
/*allowUninit*/ false);
|
||||||
llvm::Value *superMetadata) {
|
|
||||||
if (!HasResilientSuperclass)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto &layout = IGM.getClassMetadataLayout(Target);
|
Address superField =
|
||||||
|
emitAddressOfSuperclassRefInClassMetadata(IGF, metadata);
|
||||||
// Load the size of the superclass metadata.
|
superField = IGF.Builder.CreateElementBitCast(superField,
|
||||||
Address metadataAsBytes(
|
IGM.TypeMetadataPtrTy);
|
||||||
IGF.Builder.CreateBitCast(superMetadata, IGF.IGM.Int8PtrTy),
|
IGF.Builder.CreateStore(superMetadata, superField);
|
||||||
IGM.getPointerAlignment());
|
|
||||||
|
|
||||||
Address sizeSlot = IGF.Builder.CreateConstByteArrayGEP(
|
|
||||||
metadataAsBytes,
|
|
||||||
layout.getMetadataSizeOffset());
|
|
||||||
sizeSlot = IGF.Builder.CreateBitCast(sizeSlot,
|
|
||||||
IGM.Int32Ty->getPointerTo());
|
|
||||||
llvm::Value *size = IGF.Builder.CreateLoad(sizeSlot);
|
|
||||||
|
|
||||||
Address addressPointSlot = IGF.Builder.CreateConstByteArrayGEP(
|
|
||||||
metadataAsBytes,
|
|
||||||
layout.getMetadataAddressPointOffset());
|
|
||||||
addressPointSlot = IGF.Builder.CreateBitCast(addressPointSlot,
|
|
||||||
IGM.Int32Ty->getPointerTo());
|
|
||||||
llvm::Value *addressPoint = IGF.Builder.CreateLoad(addressPointSlot);
|
|
||||||
|
|
||||||
size = IGF.Builder.CreateSub(size, addressPoint);
|
|
||||||
|
|
||||||
if (IGM.SizeTy != IGM.Int32Ty)
|
|
||||||
size = IGF.Builder.CreateZExt(size, IGM.SizeTy);
|
|
||||||
|
|
||||||
Address offsetAddr(
|
|
||||||
IGM.getAddrOfClassMetadataBaseOffset(Target,
|
|
||||||
NotForDefinition),
|
|
||||||
IGM.getPointerAlignment());
|
|
||||||
|
|
||||||
// FIXME: Do we need to worry about memory barriers here, and when we
|
|
||||||
// load from the global?
|
|
||||||
IGF.Builder.CreateStore(size, offsetAddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update vtable entries for method overrides. The runtime copies in
|
// Update vtable entries for method overrides. The runtime copies in
|
||||||
@@ -3989,7 +3987,6 @@ namespace {
|
|||||||
using super::Target;
|
using super::Target;
|
||||||
using super::B;
|
using super::B;
|
||||||
using super::addReferenceToHeapMetadata;
|
using super::addReferenceToHeapMetadata;
|
||||||
using super::emitInitializeClassMetadataBaseOffset;
|
|
||||||
using super::emitFinishInitializationOfClassMetadata;
|
using super::emitFinishInitializationOfClassMetadata;
|
||||||
using super::emitFinishIdempotentInitialization;
|
using super::emitFinishIdempotentInitialization;
|
||||||
using super::emitFieldOffsetGlobals;
|
using super::emitFieldOffsetGlobals;
|
||||||
@@ -4080,18 +4077,7 @@ namespace {
|
|||||||
// Initialize the superclass if we didn't do so as a constant.
|
// Initialize the superclass if we didn't do so as a constant.
|
||||||
if (HasUnfilledSuperclass) {
|
if (HasUnfilledSuperclass) {
|
||||||
auto superclass = type->getSuperclass()->getCanonicalType();
|
auto superclass = type->getSuperclass()->getCanonicalType();
|
||||||
llvm::Value *superMetadata =
|
this->emitStoreOfSuperclass(IGF, superclass, metadata);
|
||||||
emitClassHeapMetadataRef(IGF, superclass,
|
|
||||||
MetadataValueType::TypeMetadata,
|
|
||||||
/*allowUninit*/ false);
|
|
||||||
|
|
||||||
emitInitializeClassMetadataBaseOffset(IGF, superMetadata);
|
|
||||||
|
|
||||||
Address superField =
|
|
||||||
emitAddressOfSuperclassRefInClassMetadata(IGF, metadata);
|
|
||||||
superField = IGF.Builder.CreateElementBitCast(superField,
|
|
||||||
IGM.TypeMetadataPtrTy);
|
|
||||||
IGF.Builder.CreateStore(superMetadata, superField);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relocate the metadata if it has a superclass that is resilient
|
// Relocate the metadata if it has a superclass that is resilient
|
||||||
@@ -4139,20 +4125,18 @@ namespace {
|
|||||||
: super(IGM, theClass, builder, layout, fieldLayout) {}
|
: super(IGM, theClass, builder, layout, fieldLayout) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A builder for generic class metadata.
|
/// A builder for GenericClassMetadataPattern objects.
|
||||||
class GenericClassMetadataBuilder :
|
class GenericClassMetadataBuilder :
|
||||||
public GenericMetadataBuilderBase<GenericClassMetadataBuilder,
|
public GenericMetadataBuilderBase<GenericClassMetadataBuilder,
|
||||||
ClassMetadataBuilderBase<GenericClassMetadataBuilder,
|
ClassMetadataBuilderBase<GenericClassMetadataBuilder,
|
||||||
ResilientClassMemberBuilder>>
|
ResilientClassMemberBuilder>,
|
||||||
|
/*add generic arguments*/ false>
|
||||||
{
|
{
|
||||||
typedef GenericMetadataBuilderBase super;
|
typedef GenericMetadataBuilderBase super;
|
||||||
|
|
||||||
Size MetaclassPtrOffset = Size::invalid();
|
Optional<ConstantAggregateBuilderBase::PlaceholderPosition>
|
||||||
Size ClassRODataPtrOffset = Size::invalid();
|
NumExtraDataWords, ClassRODataOffset, MetaclassObjectOffset,
|
||||||
Size MetaclassRODataPtrOffset = Size::invalid();
|
MetaclassRODataOffset;
|
||||||
Size DependentMetaclassPoint = Size::invalid();
|
|
||||||
Size DependentClassRODataPoint = Size::invalid();
|
|
||||||
Size DependentMetaclassRODataPoint = Size::invalid();
|
|
||||||
public:
|
public:
|
||||||
GenericClassMetadataBuilder(IRGenModule &IGM, ClassDecl *theClass,
|
GenericClassMetadataBuilder(IRGenModule &IGM, ClassDecl *theClass,
|
||||||
ConstantStructBuilder &B,
|
ConstantStructBuilder &B,
|
||||||
@@ -4165,70 +4149,107 @@ namespace {
|
|||||||
HasDependentMetadata = true;
|
HasDependentMetadata = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addSuperClass() {
|
void layout() {
|
||||||
// Filled in by the runtime.
|
// HeapObjectDestroyer *Destroy;
|
||||||
B.addNullPointer(IGM.TypeMetadataPtrTy);
|
addDestructorFunction();
|
||||||
|
|
||||||
|
// ClassIVarDestroyer *IVarDestroyer;
|
||||||
|
addIVarDestroyer();
|
||||||
|
|
||||||
|
// ClassFlags Flags;
|
||||||
|
addClassFlags();
|
||||||
|
|
||||||
|
// TODO: consider using this to initialize the field offsets (and then
|
||||||
|
// suppress dynamic layout for them).
|
||||||
|
// uint16_t ImmediateMembersPattern_Size;
|
||||||
|
// uint16_t ImmediateMembersPattern_TargetOffset;
|
||||||
|
B.addInt16(0);
|
||||||
|
B.addInt16(0);
|
||||||
|
|
||||||
|
// uint16_t NumExtraDataWords;
|
||||||
|
NumExtraDataWords = B.addPlaceholderWithSize(IGM.Int16Ty);
|
||||||
|
|
||||||
|
// uint16_t ClassRODataOffset;
|
||||||
|
ClassRODataOffset = B.addPlaceholderWithSize(IGM.Int16Ty);
|
||||||
|
|
||||||
|
// uint16_t MetaclassObjectOffset;
|
||||||
|
MetaclassObjectOffset = B.addPlaceholderWithSize(IGM.Int16Ty);
|
||||||
|
|
||||||
|
// uint16_t MetadataRODataOffset;
|
||||||
|
MetaclassRODataOffset = B.addPlaceholderWithSize(IGM.Int16Ty);
|
||||||
|
|
||||||
|
// Immediate members pattern:
|
||||||
|
// (currently we don't take advantage of this)
|
||||||
|
|
||||||
|
// Extra data pattern:
|
||||||
|
addExtraDataPattern();
|
||||||
|
|
||||||
|
// We're done with the pattern now.
|
||||||
|
#ifndef NDEBUG
|
||||||
|
auto finalOffset = getNextOffsetFromTemplateHeader();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Emit the base-offset variable.
|
||||||
|
emitClassMetadataBaseOffset();
|
||||||
|
|
||||||
|
// Emit the nominal type descriptor.
|
||||||
|
(void) ClassContextDescriptorBuilder(IGM, Target, RequireMetadata).emit();
|
||||||
|
|
||||||
|
// Register fill ops for all the immediate type arguments.
|
||||||
|
addGenericFields(Target, Target->getDeclaredTypeInContext(), Target);
|
||||||
|
|
||||||
|
// Emit instantiation information.
|
||||||
|
emitInstantiationDefinitions();
|
||||||
|
|
||||||
|
assert(finalOffset == getNextOffsetFromTemplateHeader() &&
|
||||||
|
"shouldn't have added anything to the pattern");
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value *emitAllocateMetadata(IRGenFunction &IGF,
|
uint16_t getOffsetInWords(Size begin, Size offset) {
|
||||||
llvm::Value *descriptor,
|
// Subtract the offset from the initial offset and divide by the
|
||||||
llvm::Value *arguments) {
|
// pointer size, rounding up.
|
||||||
llvm::Value *superMetadata;
|
auto result =
|
||||||
if (Target->hasSuperclass()) {
|
(offset - begin + IGM.getPointerSize() - Size(1))
|
||||||
Type superclass = Target->getSuperclass();
|
/ IGM.getPointerSize();
|
||||||
superclass = Target->mapTypeIntoContext(superclass);
|
assert(result < (1 << 16));
|
||||||
superMetadata =
|
return uint16_t(result);
|
||||||
emitClassHeapMetadataRef(IGF, superclass->getCanonicalType(),
|
};
|
||||||
MetadataValueType::ObjCClass);
|
|
||||||
|
|
||||||
emitInitializeClassMetadataBaseOffset(IGF, superMetadata);
|
void addExtraDataPattern() {
|
||||||
} else if (IGM.ObjCInterop) {
|
Size extraDataBegin = getNextOffsetFromTemplateHeader();
|
||||||
superMetadata = emitObjCHeapMetadataRef(IGF,
|
|
||||||
IGM.getObjCRuntimeBaseForSwiftRootClass(Target));
|
uint16_t classRODataOffsetWords = 0;
|
||||||
} else {
|
uint16_t metaclassObjectOffsetWords = 0;
|
||||||
superMetadata = llvm::ConstantPointerNull::get(IGM.ObjCClassPtrTy);
|
uint16_t metaclassRODataOffsetWords = 0;
|
||||||
|
if (IGM.ObjCInterop) {
|
||||||
|
// Add the metaclass object.
|
||||||
|
metaclassObjectOffsetWords =
|
||||||
|
getOffsetInWords(extraDataBegin, getNextOffsetFromTemplateHeader());
|
||||||
|
addMetaclassObject();
|
||||||
|
|
||||||
|
// Add the RO-data objects.
|
||||||
|
auto roDataPoints =
|
||||||
|
emitClassPrivateDataFields(IGM, B, Target);
|
||||||
|
classRODataOffsetWords =
|
||||||
|
getOffsetInWords(extraDataBegin, roDataPoints.first);
|
||||||
|
metaclassRODataOffsetWords =
|
||||||
|
getOffsetInWords(extraDataBegin, roDataPoints.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto templatePointer = IGM.getAddrOfTypeMetadataPattern(Target);
|
auto extraDataEnd = getNextOffsetFromTemplateHeader();
|
||||||
auto templateSize = IGM.getSize(TemplateSize);
|
auto numExtraDataWords = getOffsetInWords(extraDataBegin, extraDataEnd);
|
||||||
auto templateAddressPoint = IGM.getSize(AddressPoint);
|
|
||||||
|
|
||||||
auto numImmediateMembers =
|
B.fillPlaceholderWithInt(*NumExtraDataWords, IGM.Int16Ty,
|
||||||
IGM.getSize(Size(IGM.getClassMetadataLayout(Target).getNumImmediateMembers()));
|
numExtraDataWords);
|
||||||
|
B.fillPlaceholderWithInt(*ClassRODataOffset, IGM.Int16Ty,
|
||||||
return IGF.Builder.CreateCall(IGM.getAllocateGenericClassMetadataFn(),
|
classRODataOffsetWords);
|
||||||
{descriptor, templatePointer, templateSize,
|
B.fillPlaceholderWithInt(*MetaclassObjectOffset, IGM.Int16Ty,
|
||||||
templateAddressPoint, arguments,
|
metaclassObjectOffsetWords);
|
||||||
superMetadata, numImmediateMembers});
|
B.fillPlaceholderWithInt(*MetaclassRODataOffset, IGM.Int16Ty,
|
||||||
|
metaclassRODataOffsetWords);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMetadataFlags() {
|
void addMetaclassObject() {
|
||||||
// The metaclass pointer will be instantiated here.
|
|
||||||
MetaclassPtrOffset = getNextOffsetFromTemplateHeader();
|
|
||||||
B.addInt(IGM.MetadataKindTy, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addClassDataPointer() {
|
|
||||||
// The rodata pointer will be instantiated here.
|
|
||||||
// Make sure we at least set the 'is Swift class' bit, though.
|
|
||||||
ClassRODataPtrOffset = getNextOffsetFromTemplateHeader();
|
|
||||||
if (!IGM.ObjCInterop) {
|
|
||||||
// FIXME: Remove null data altogether rdar://problem/18801263
|
|
||||||
B.addInt(IGM.MetadataKindTy, 1);
|
|
||||||
} else {
|
|
||||||
B.addInt(IGM.MetadataKindTy, IGM.UseDarwinPreStableABIBit ? 1 : 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDependentData() {
|
|
||||||
if (!IGM.ObjCInterop) {
|
|
||||||
// Every piece of data in the dependent data appears to be related to
|
|
||||||
// Objective-C information. If we're not doing Objective-C interop, we
|
|
||||||
// can just skip adding it to the class.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Emit space for the dependent metaclass.
|
|
||||||
DependentMetaclassPoint = getNextOffsetFromTemplateHeader();
|
|
||||||
// isa
|
// isa
|
||||||
ClassDecl *rootClass = getRootClassForMetaclass(IGM, Target);
|
ClassDecl *rootClass = getRootClassForMetaclass(IGM, Target);
|
||||||
auto isa = IGM.getAddrOfMetaclassObject(rootClass, NotForDefinition);
|
auto isa = IGM.getAddrOfMetaclassObject(rootClass, NotForDefinition);
|
||||||
@@ -4240,17 +4261,9 @@ namespace {
|
|||||||
// vtable
|
// vtable
|
||||||
B.add(IGM.getObjCEmptyVTablePtr());
|
B.add(IGM.getObjCEmptyVTablePtr());
|
||||||
// rodata, which is always dependent
|
// rodata, which is always dependent
|
||||||
MetaclassRODataPtrOffset = getNextOffsetFromTemplateHeader();
|
|
||||||
B.addInt(IGM.IntPtrTy, 0);
|
B.addInt(IGM.IntPtrTy, 0);
|
||||||
|
|
||||||
std::tie(DependentClassRODataPoint, DependentMetaclassRODataPoint)
|
|
||||||
= emitClassPrivateDataFields(IGM, B, Target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void noteStartOfFieldOffsets(ClassDecl *whichClass) {}
|
|
||||||
|
|
||||||
void noteEndOfFieldOffsets(ClassDecl *whichClass) {}
|
|
||||||
|
|
||||||
// Suppress GenericMetadataBuilderBase's default behavior of introducing
|
// Suppress GenericMetadataBuilderBase's default behavior of introducing
|
||||||
// fill ops for generic arguments unless they belong directly to the target
|
// fill ops for generic arguments unless they belong directly to the target
|
||||||
// class and not its ancestors.
|
// class and not its ancestors.
|
||||||
@@ -4278,91 +4291,29 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Value *emitAllocateMetadata(IRGenFunction &IGF,
|
||||||
|
llvm::Value *descriptor,
|
||||||
|
llvm::Value *arguments) {
|
||||||
|
auto templatePointer = IGM.getAddrOfTypeMetadataPattern(Target);
|
||||||
|
auto metadata =
|
||||||
|
IGF.Builder.CreateCall(IGM.getAllocateGenericClassMetadataFn(),
|
||||||
|
{descriptor, arguments, templatePointer});
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
void emitInitializeMetadata(IRGenFunction &IGF,
|
void emitInitializeMetadata(IRGenFunction &IGF,
|
||||||
llvm::Value *metadata,
|
llvm::Value *metadata,
|
||||||
bool isVWTMutable) {
|
bool isVWTMutable) {
|
||||||
assert(!HasDependentVWT && "class should never have dependent VWT");
|
assert(!HasDependentVWT && "class should never have dependent VWT");
|
||||||
|
|
||||||
// Fill in the metaclass pointer.
|
// Install the superclass. The runtime takes care of installing
|
||||||
Address metadataPtr(IGF.Builder.CreateBitCast(metadata, IGF.IGM.Int8PtrPtrTy),
|
// SwiftObject if we're building with ObjC interop and don't have
|
||||||
IGF.IGM.getPointerAlignment());
|
// a formal superclass.
|
||||||
|
if (Target->hasSuperclass()) {
|
||||||
llvm::Value *metaclass;
|
CanType superclass = Target->mapTypeIntoContext(Target->getSuperclass())
|
||||||
if (IGF.IGM.ObjCInterop) {
|
->getCanonicalType();
|
||||||
assert(!DependentMetaclassPoint.isInvalid());
|
emitStoreOfSuperclass(IGF, superclass, metadata);
|
||||||
assert(!MetaclassPtrOffset.isInvalid());
|
|
||||||
|
|
||||||
Address metaclassPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
|
|
||||||
MetaclassPtrOffset - AddressPoint);
|
|
||||||
metaclassPtrSlot = IGF.Builder.CreateBitCast(metaclassPtrSlot,
|
|
||||||
IGF.IGM.ObjCClassPtrTy->getPointerTo());
|
|
||||||
Address metaclassRawPtr = createPointerSizedGEP(IGF, metadataPtr,
|
|
||||||
DependentMetaclassPoint - AddressPoint);
|
|
||||||
metaclass = IGF.Builder.CreateBitCast(metaclassRawPtr,
|
|
||||||
IGF.IGM.ObjCClassPtrTy)
|
|
||||||
.getAddress();
|
|
||||||
IGF.Builder.CreateStore(metaclass, metaclassPtrSlot);
|
|
||||||
} else {
|
|
||||||
// FIXME: Remove altogether rather than injecting a NULL value.
|
|
||||||
// rdar://problem/18801263
|
|
||||||
assert(!MetaclassPtrOffset.isInvalid());
|
|
||||||
Address metaclassPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
|
|
||||||
MetaclassPtrOffset - AddressPoint);
|
|
||||||
metaclassPtrSlot = IGF.Builder.CreateBitCast(metaclassPtrSlot,
|
|
||||||
IGF.IGM.ObjCClassPtrTy->getPointerTo());
|
|
||||||
IGF.Builder.CreateStore(
|
|
||||||
llvm::ConstantPointerNull::get(IGF.IGM.ObjCClassPtrTy),
|
|
||||||
metaclassPtrSlot);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in the rodata reference in the class.
|
|
||||||
Address classRODataPtr;
|
|
||||||
if (IGF.IGM.ObjCInterop) {
|
|
||||||
assert(!DependentClassRODataPoint.isInvalid());
|
|
||||||
assert(!ClassRODataPtrOffset.isInvalid());
|
|
||||||
Address rodataPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
|
|
||||||
ClassRODataPtrOffset - AddressPoint);
|
|
||||||
rodataPtrSlot = IGF.Builder.CreateBitCast(rodataPtrSlot,
|
|
||||||
IGF.IGM.IntPtrTy->getPointerTo());
|
|
||||||
|
|
||||||
classRODataPtr = createPointerSizedGEP(IGF, metadataPtr,
|
|
||||||
DependentClassRODataPoint - AddressPoint);
|
|
||||||
// Set the low bit of the value to indicate "compiled by Swift".
|
|
||||||
llvm::Value *rodata = IGF.Builder.CreatePtrToInt(
|
|
||||||
classRODataPtr.getAddress(), IGF.IGM.IntPtrTy);
|
|
||||||
rodata = IGF.Builder.CreateOr(rodata, 1);
|
|
||||||
IGF.Builder.CreateStore(rodata, rodataPtrSlot);
|
|
||||||
} else {
|
|
||||||
// NOTE: Unlike other bits of the metadata that should later be removed,
|
|
||||||
// this one is important because things check this value's flags to
|
|
||||||
// determine what kind of object it is. That said, if those checks
|
|
||||||
// are determined to be removable, we can remove this as well per
|
|
||||||
// rdar://problem/18801263
|
|
||||||
assert(!ClassRODataPtrOffset.isInvalid());
|
|
||||||
Address rodataPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
|
|
||||||
ClassRODataPtrOffset - AddressPoint);
|
|
||||||
rodataPtrSlot = IGF.Builder.CreateBitCast(rodataPtrSlot,
|
|
||||||
IGF.IGM.IntPtrTy->getPointerTo());
|
|
||||||
|
|
||||||
IGF.Builder.CreateStore(llvm::ConstantInt::get(IGF.IGM.IntPtrTy, 1),
|
|
||||||
rodataPtrSlot);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in the rodata reference in the metaclass.
|
|
||||||
Address metaclassRODataPtr;
|
|
||||||
if (IGF.IGM.ObjCInterop) {
|
|
||||||
assert(!DependentMetaclassRODataPoint.isInvalid());
|
|
||||||
assert(!MetaclassRODataPtrOffset.isInvalid());
|
|
||||||
Address rodataPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
|
|
||||||
MetaclassRODataPtrOffset - AddressPoint);
|
|
||||||
rodataPtrSlot = IGF.Builder.CreateBitCast(rodataPtrSlot,
|
|
||||||
IGF.IGM.IntPtrTy->getPointerTo());
|
|
||||||
|
|
||||||
metaclassRODataPtr = createPointerSizedGEP(IGF, metadataPtr,
|
|
||||||
DependentMetaclassRODataPoint - AddressPoint);
|
|
||||||
llvm::Value *rodata = IGF.Builder.CreatePtrToInt(
|
|
||||||
metaclassRODataPtr.getAddress(), IGF.IGM.IntPtrTy);
|
|
||||||
IGF.Builder.CreateStore(rodata, rodataPtrSlot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can assume that this never relocates the metadata because
|
// We can assume that this never relocates the metadata because
|
||||||
|
|||||||
@@ -150,13 +150,6 @@ namespace irgen {
|
|||||||
NominalTypeDecl *decl,
|
NominalTypeDecl *decl,
|
||||||
ArchetypeType *archetype);
|
ArchetypeType *archetype);
|
||||||
|
|
||||||
/// Given a reference to nominal type metadata of the given type,
|
|
||||||
/// derive a reference to the parent type metadata. There must be a
|
|
||||||
/// parent type.
|
|
||||||
llvm::Value *emitParentMetadataRef(IRGenFunction &IGF,
|
|
||||||
NominalTypeDecl *theDecl,
|
|
||||||
llvm::Value *metadata);
|
|
||||||
|
|
||||||
/// Given a reference to nominal type metadata of the given type,
|
/// Given a reference to nominal type metadata of the given type,
|
||||||
/// derive a reference to the type metadata stored in the nth
|
/// derive a reference to the type metadata stored in the nth
|
||||||
/// requirement slot. The type must have generic arguments.
|
/// requirement slot. The type must have generic arguments.
|
||||||
|
|||||||
@@ -1150,8 +1150,8 @@ public:
|
|||||||
/// Determine whether the given type requires foreign type metadata.
|
/// Determine whether the given type requires foreign type metadata.
|
||||||
bool requiresForeignTypeMetadata(CanType type);
|
bool requiresForeignTypeMetadata(CanType type);
|
||||||
|
|
||||||
llvm::Constant *getAddrOfClassMetadataBaseOffset(ClassDecl *D,
|
llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D,
|
||||||
ForDefinition_t forDefinition);
|
ForDefinition_t forDefinition);
|
||||||
llvm::Constant *getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
|
llvm::Constant *getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
|
||||||
RequireMetadata_t requireMetadata,
|
RequireMetadata_t requireMetadata,
|
||||||
ConstantInit definition = ConstantInit());
|
ConstantInit definition = ConstantInit());
|
||||||
|
|||||||
@@ -162,11 +162,13 @@ Offset NominalMetadataLayout::emitOffset(IRGenFunction &IGF,
|
|||||||
if (offset.isStatic())
|
if (offset.isStatic())
|
||||||
return Offset(offset.getStaticOffset());
|
return Offset(offset.getStaticOffset());
|
||||||
|
|
||||||
Address offsetBaseAddr(
|
Address layoutAddr(
|
||||||
IGF.IGM.getAddrOfClassMetadataBaseOffset(cast<ClassDecl>(getDecl()),
|
IGF.IGM.getAddrOfClassMetadataBounds(cast<ClassDecl>(getDecl()),
|
||||||
NotForDefinition),
|
NotForDefinition),
|
||||||
IGF.IGM.getPointerAlignment());
|
IGF.IGM.getPointerAlignment());
|
||||||
|
|
||||||
|
auto offsetBaseAddr = IGF.Builder.CreateStructGEP(layoutAddr, 0, Size(0));
|
||||||
|
|
||||||
// FIXME: Should this be an invariant load?
|
// FIXME: Should this be an invariant load?
|
||||||
llvm::Value *offsetVal = IGF.Builder.CreateLoad(offsetBaseAddr, "base");
|
llvm::Value *offsetVal = IGF.Builder.CreateLoad(offsetBaseAddr, "base");
|
||||||
|
|
||||||
|
|||||||
@@ -227,6 +227,10 @@ public:
|
|||||||
return HasResilientSuperclass;
|
return HasResilientSuperclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr static bool areImmediateMembersNegative() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Size getMetadataSizeOffset() const;
|
Size getMetadataSizeOffset() const;
|
||||||
|
|
||||||
Size getMetadataAddressPointOffset() const;
|
Size getMetadataAddressPointOffset() const;
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ public:
|
|||||||
// StructMetadata header.
|
// StructMetadata header.
|
||||||
asImpl().addNominalTypeDescriptor();
|
asImpl().addNominalTypeDescriptor();
|
||||||
|
|
||||||
// If changing this layout, you must update the magic number in
|
|
||||||
// emitParentMetadataRef.
|
|
||||||
|
|
||||||
// Instantiation-specific.
|
// Instantiation-specific.
|
||||||
|
|
||||||
|
// Generic arguments.
|
||||||
|
// This must always be the first piece of trailing data.
|
||||||
asImpl().addGenericFields(Target, Target->getDeclaredTypeInContext());
|
asImpl().addGenericFields(Target, Target->getDeclaredTypeInContext());
|
||||||
|
|
||||||
// Struct field offsets.
|
// Struct field offsets.
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ static void _buildNameForMetadata(const Metadata *type,
|
|||||||
auto classType = static_cast<const ClassMetadata *>(type);
|
auto classType = static_cast<const ClassMetadata *>(type);
|
||||||
// Look through artificial subclasses.
|
// Look through artificial subclasses.
|
||||||
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
|
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
|
||||||
classType = classType->SuperClass;
|
classType = classType->Superclass;
|
||||||
|
|
||||||
// Ask the Objective-C runtime to name ObjC classes.
|
// Ask the Objective-C runtime to name ObjC classes.
|
||||||
if (!classType->isTypeMetadata()) {
|
if (!classType->isTypeMetadata()) {
|
||||||
@@ -262,7 +262,7 @@ _dynamicCastClassMetatype(const ClassMetadata *sourceType,
|
|||||||
if (sourceType == targetType) {
|
if (sourceType == targetType) {
|
||||||
return sourceType;
|
return sourceType;
|
||||||
}
|
}
|
||||||
sourceType = sourceType->SuperClass;
|
sourceType = sourceType->Superclass;
|
||||||
} while (sourceType);
|
} while (sourceType);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -3228,7 +3228,7 @@ SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
|
|||||||
const Metadata *swift::_swift_class_getSuperclass(const Metadata *theClass) {
|
const Metadata *swift::_swift_class_getSuperclass(const Metadata *theClass) {
|
||||||
if (const ClassMetadata *classType = theClass->getClassObject())
|
if (const ClassMetadata *classType = theClass->getClassObject())
|
||||||
if (classHasSuperclass(classType))
|
if (classHasSuperclass(classType))
|
||||||
return getMetadataForClass(classType->SuperClass);
|
return getMetadataForClass(classType->Superclass);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
|
|||||||
#if SWIFT_OBJC_INTEROP
|
#if SWIFT_OBJC_INTEROP
|
||||||
// Peek through artificial subclasses.
|
// Peek through artificial subclasses.
|
||||||
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
|
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
|
||||||
classType = classType->SuperClass;
|
classType = classType->Superclass;
|
||||||
#endif
|
#endif
|
||||||
description = classType->getDescription();
|
description = classType->getDescription();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ static SWIFT_CC(swift) void _destroyErrorObject(SWIFT_CONTEXT HeapObject *obj) {
|
|||||||
/// Heap metadata for Error boxes.
|
/// Heap metadata for Error boxes.
|
||||||
static const FullMetadata<HeapMetadata> ErrorMetadata{
|
static const FullMetadata<HeapMetadata> ErrorMetadata{
|
||||||
HeapMetadataHeader{{_destroyErrorObject}, {&VALUE_WITNESS_SYM(Bo)}},
|
HeapMetadataHeader{{_destroyErrorObject}, {&VALUE_WITNESS_SYM(Bo)}},
|
||||||
Metadata{MetadataKind::ErrorObject},
|
HeapMetadata(MetadataKind::ErrorObject),
|
||||||
};
|
};
|
||||||
|
|
||||||
BoxPair
|
BoxPair
|
||||||
|
|||||||
@@ -658,10 +658,10 @@ void swift::swift_deallocPartialClassInstance(HeapObject *object,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (auto fn = classMetadata->getIVarDestroyer())
|
if (classMetadata->IVarDestroyer)
|
||||||
fn(object);
|
classMetadata->IVarDestroyer(object);
|
||||||
|
|
||||||
classMetadata = classMetadata->SuperClass->getClassObject();
|
classMetadata = classMetadata->Superclass->getClassObject();
|
||||||
assert(classMetadata && "Given metatype not a superclass of object type?");
|
assert(classMetadata && "Given metatype not a superclass of object type?");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,7 +671,7 @@ void swift::swift_deallocPartialClassInstance(HeapObject *object,
|
|||||||
if (!usesNativeSwiftReferenceCounting(classMetadata)) {
|
if (!usesNativeSwiftReferenceCounting(classMetadata)) {
|
||||||
// Find the pure Objective-C superclass.
|
// Find the pure Objective-C superclass.
|
||||||
while (!classMetadata->isPureObjC())
|
while (!classMetadata->isPureObjC())
|
||||||
classMetadata = classMetadata->SuperClass->getClassObject();
|
classMetadata = classMetadata->Superclass->getClassObject();
|
||||||
|
|
||||||
// Set the class to the pure Objective-C superclass, so that when dealloc
|
// Set the class to the pure Objective-C superclass, so that when dealloc
|
||||||
// runs, it starts at that superclass.
|
// runs, it starts at that superclass.
|
||||||
|
|||||||
@@ -74,6 +74,92 @@ static int compareIntegers(T left, T right) {
|
|||||||
|
|
||||||
static const size_t ValueTypeMetadataAddressPoint = sizeof(TypeMetadataHeader);
|
static const size_t ValueTypeMetadataAddressPoint = sizeof(TypeMetadataHeader);
|
||||||
|
|
||||||
|
static ClassMetadataBounds
|
||||||
|
computeMetadataBoundsForSuperclass(const void *ref,
|
||||||
|
TypeMetadataRecordKind refKind) {
|
||||||
|
switch (refKind) {
|
||||||
|
case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
|
||||||
|
auto description = *reinterpret_cast<const ClassDescriptor * const *>(ref);
|
||||||
|
if (!description) {
|
||||||
|
swift::fatalError(0, "instantiating class metadata for class with "
|
||||||
|
"missing weak-linked ancestor");
|
||||||
|
}
|
||||||
|
return description->getMetadataBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
|
||||||
|
auto description = reinterpret_cast<const ClassDescriptor *>(ref);
|
||||||
|
return description->getMetadataBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
case TypeMetadataRecordKind::IndirectObjCClass:
|
||||||
|
#if SWIFT_OBJC_INTEROP
|
||||||
|
{
|
||||||
|
auto cls = *reinterpret_cast<const Class *>(ref);
|
||||||
|
cls = swift_getInitializedObjCClass(cls);
|
||||||
|
auto metadata = reinterpret_cast<const ClassMetadata *>(cls);
|
||||||
|
return metadata->getClassBoundsAsSwiftSuperclass();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// fallthrough
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case TypeMetadataRecordKind::Reserved:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
swift_runtime_unreachable("unsupported superclass reference kind");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClassMetadataBounds computeMetadataBoundsFromSuperclass(
|
||||||
|
const ClassDescriptor *description,
|
||||||
|
StoredClassMetadataBounds &storedBounds) {
|
||||||
|
ClassMetadataBounds bounds;
|
||||||
|
|
||||||
|
// Compute the bounds for the superclass, extending it to the minimum
|
||||||
|
// bounds of a Swift class.
|
||||||
|
if (const void *superRef = description->Superclass.get()) {
|
||||||
|
bounds = computeMetadataBoundsForSuperclass(superRef,
|
||||||
|
description->getSuperclassReferenceKind());
|
||||||
|
} else {
|
||||||
|
bounds = ClassMetadataBounds::forSwiftRootClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the subclass's immediate members.
|
||||||
|
bounds.adjustForSubclass(description->areImmediateMembersNegative(),
|
||||||
|
description->NumImmediateMembers);
|
||||||
|
|
||||||
|
// Cache before returning.
|
||||||
|
storedBounds.initialize(bounds);
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassMetadataBounds
|
||||||
|
swift::getResilientMetadataBounds(const ClassDescriptor *description) {
|
||||||
|
assert(description->hasResilientSuperclass());
|
||||||
|
auto &storedBounds = *description->ResilientMetadataBounds.get();
|
||||||
|
|
||||||
|
ClassMetadataBounds bounds;
|
||||||
|
if (storedBounds.tryGet(bounds)) {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return computeMetadataBoundsFromSuperclass(description, storedBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
swift::getResilientImmediateMembersOffset(const ClassDescriptor *description) {
|
||||||
|
assert(description->hasResilientSuperclass());
|
||||||
|
auto &storedBounds = *description->ResilientMetadataBounds.get();
|
||||||
|
|
||||||
|
ptrdiff_t result;
|
||||||
|
if (storedBounds.tryGetImmediateMembersOffset(result)) {
|
||||||
|
return result / sizeof(void*);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bounds = computeMetadataBoundsFromSuperclass(description, storedBounds);
|
||||||
|
return bounds.ImmediateMembersOffset / sizeof(void*);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct GenericCacheEntry;
|
struct GenericCacheEntry;
|
||||||
|
|
||||||
@@ -94,9 +180,7 @@ namespace {
|
|||||||
|
|
||||||
size_t getNumArguments() const { return NumArguments; }
|
size_t getNumArguments() const { return NumArguments; }
|
||||||
|
|
||||||
static GenericCacheEntry *getFromMetadata(
|
static GenericCacheEntry *getFromMetadata(Metadata *metadata) {
|
||||||
const TypeGenericContextDescriptorHeader &generics,
|
|
||||||
Metadata *metadata) {
|
|
||||||
char *bytes = (char*) metadata;
|
char *bytes = (char*) metadata;
|
||||||
if (auto classType = dyn_cast<ClassMetadata>(metadata)) {
|
if (auto classType = dyn_cast<ClassMetadata>(metadata)) {
|
||||||
assert(classType->isTypeMetadata());
|
assert(classType->isTypeMetadata());
|
||||||
@@ -142,65 +226,148 @@ static GenericMetadataCache &unsafeGetInitializedCache(
|
|||||||
return lazyCache->unsafeGetAlreadyInitialized();
|
return lazyCache->unsafeGetAlreadyInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
extern "C" void *_objc_empty_cache;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
initializeClassMetadataFromPattern(ClassMetadata *metadata,
|
||||||
|
ClassMetadataBounds bounds,
|
||||||
|
const ClassDescriptor *description,
|
||||||
|
const GenericClassMetadataPattern *pattern) {
|
||||||
|
auto fullMetadata = asFullMetadata(metadata);
|
||||||
|
char *rawMetadata = reinterpret_cast<char*>(metadata);
|
||||||
|
|
||||||
|
// Install the extra-data pattern.
|
||||||
|
void **metadataExtraData =
|
||||||
|
reinterpret_cast<void**>(rawMetadata) + bounds.PositiveSizeInWords;
|
||||||
|
memcpy(metadataExtraData, pattern->getExtraDataPattern(),
|
||||||
|
size_t(pattern->NumExtraDataWords) * sizeof(void*));
|
||||||
|
|
||||||
|
// Install the immediate members pattern:
|
||||||
|
void **immediateMembers =
|
||||||
|
reinterpret_cast<void**>(rawMetadata + bounds.ImmediateMembersOffset);
|
||||||
|
|
||||||
|
// Zero out the entire immediate-members section.
|
||||||
|
// TODO: only memset the parts that aren't covered by the pattern.
|
||||||
|
memset(immediateMembers, 0, description->getImmediateMembersSize());
|
||||||
|
|
||||||
|
// Copy the immediate-members pattern.
|
||||||
|
if (auto immediateSize = pattern->ImmediateMembersPattern_Size) {
|
||||||
|
memcpy(immediateMembers + pattern->ImmediateMembersPattern_TargetOffset,
|
||||||
|
pattern->getImmediateMembersPattern(),
|
||||||
|
size_t(immediateSize) * sizeof(void*));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the header:
|
||||||
|
|
||||||
|
// Heap destructor.
|
||||||
|
fullMetadata->destroy = pattern->Destroy;
|
||||||
|
|
||||||
|
// Value witness table.
|
||||||
|
#if SWIFT_OBJC_INTEROP
|
||||||
|
fullMetadata->ValueWitnesses =
|
||||||
|
(pattern->Flags & ClassFlags::UsesSwiftRefcounting)
|
||||||
|
? &VALUE_WITNESS_SYM(Bo)
|
||||||
|
: &VALUE_WITNESS_SYM(BO);
|
||||||
|
#else
|
||||||
|
fullMetadata->ValueWitnesses = &VALUE_WITNESS_SYM(Bo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SWIFT_OBJC_INTEROP
|
||||||
|
// Install the metaclass's RO-data pointer.
|
||||||
|
auto metaclass = reinterpret_cast<AnyClassMetadata *>(
|
||||||
|
metadataExtraData + pattern->MetaclassObjectOffset);
|
||||||
|
auto metaclassRO = metadataExtraData + pattern->MetaclassRODataOffset;
|
||||||
|
metaclass->Data = reinterpret_cast<uintptr_t>(metaclassRO);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// MetadataKind / isa.
|
||||||
|
#if SWIFT_OBJC_INTEROP
|
||||||
|
metadata->setClassISA(metaclass);
|
||||||
|
#else
|
||||||
|
metadata->setKind(MetadataKind::Class);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Superclass.
|
||||||
|
metadata->Superclass = nullptr;
|
||||||
|
#if SWIFT_OBJC_INTEROP
|
||||||
|
// If the class doesn't have a formal superclass, automatically set
|
||||||
|
// it to SwiftObject.
|
||||||
|
if (!description->hasSuperclass()) {
|
||||||
|
metadata->Superclass = getRootSuperclass();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SWIFT_OBJC_INTEROP
|
||||||
|
// Cache data. Install the same initializer that the compiler is
|
||||||
|
// required to use. We don't need to do this in non-ObjC-interop modes.
|
||||||
|
metadata->CacheData[0] = &_objc_empty_cache;
|
||||||
|
metadata->CacheData[1] = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// RO-data pointer.
|
||||||
|
#if SWIFT_OBJC_INTEROP
|
||||||
|
auto classRO = metadataExtraData + pattern->ClassRODataOffset;
|
||||||
|
metadata->Data =
|
||||||
|
reinterpret_cast<uintptr_t>(classRO) | SWIFT_CLASS_IS_SWIFT_MASK;
|
||||||
|
#else
|
||||||
|
metadata->Data = SWIFT_CLASS_IS_SWIFT_MASK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Class flags.
|
||||||
|
metadata->Flags = pattern->Flags;
|
||||||
|
|
||||||
|
// Instance layout.
|
||||||
|
metadata->InstanceAddressPoint = 0;
|
||||||
|
metadata->InstanceSize = 0;
|
||||||
|
metadata->InstanceAlignMask = 0;
|
||||||
|
|
||||||
|
// Reserved.
|
||||||
|
metadata->Reserved = 0;
|
||||||
|
|
||||||
|
// Class metadata layout.
|
||||||
|
metadata->ClassSize = bounds.getTotalSizeInBytes();
|
||||||
|
metadata->ClassAddressPoint = bounds.getAddressPointInBytes();
|
||||||
|
|
||||||
|
// Class descriptor.
|
||||||
|
metadata->setDescription(description);
|
||||||
|
|
||||||
|
// I-var destroyer.
|
||||||
|
metadata->IVarDestroyer = pattern->IVarDestroyer;
|
||||||
|
}
|
||||||
|
|
||||||
ClassMetadata *
|
ClassMetadata *
|
||||||
swift::swift_allocateGenericClassMetadata(const ClassDescriptor *description,
|
swift::swift_allocateGenericClassMetadata(const ClassDescriptor *description,
|
||||||
const void *metadataTemplate,
|
|
||||||
size_t templateSize,
|
|
||||||
size_t templateAddressPoint,
|
|
||||||
const void *arguments,
|
const void *arguments,
|
||||||
ClassMetadata *superclass,
|
const GenericClassMetadataPattern *pattern){
|
||||||
size_t numImmediateMembers) {
|
|
||||||
void * const *argumentsAsArray = reinterpret_cast<void * const *>(arguments);
|
void * const *argumentsAsArray = reinterpret_cast<void * const *>(arguments);
|
||||||
auto &generics = description->getFullGenericContextHeader();
|
auto &generics = description->getFullGenericContextHeader();
|
||||||
|
auto &cache = unsafeGetInitializedCache(generics);
|
||||||
|
|
||||||
size_t numGenericArguments = generics.Base.NumKeyArguments;
|
size_t numGenericArguments = generics.Base.NumKeyArguments;
|
||||||
|
|
||||||
size_t metadataSize;
|
// Compute the formal bounds of the metadata.
|
||||||
if (superclass && superclass->isTypeMetadata()) {
|
auto bounds = description->getMetadataBounds();
|
||||||
assert(superclass->getClassAddressPoint() <= templateAddressPoint);
|
|
||||||
|
|
||||||
metadataSize = (superclass->getClassSize() -
|
// Augment that with any required extra data from the pattern.
|
||||||
superclass->getClassAddressPoint() +
|
auto allocationBounds = bounds;
|
||||||
templateAddressPoint +
|
allocationBounds.PositiveSizeInWords += pattern->NumExtraDataWords;
|
||||||
numImmediateMembers * sizeof(void *));
|
|
||||||
assert(templateSize <= metadataSize);
|
|
||||||
} else {
|
|
||||||
metadataSize = (templateSize +
|
|
||||||
numImmediateMembers * sizeof(void *));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &cache = unsafeGetInitializedCache(generics);
|
auto entry = GenericCacheEntry::allocate(cache.getAllocator(),
|
||||||
char *bytes = GenericCacheEntry::allocate(cache.getAllocator(),
|
argumentsAsArray,
|
||||||
argumentsAsArray,
|
numGenericArguments,
|
||||||
numGenericArguments,
|
allocationBounds.getTotalSizeInBytes());
|
||||||
metadataSize)->getData<char>();
|
|
||||||
|
|
||||||
// Copy in the metadata template.
|
auto bytes = entry->getData<char>();
|
||||||
memcpy(bytes, metadataTemplate, templateSize);
|
auto addressPoint = bytes + allocationBounds.getAddressPointInBytes();
|
||||||
|
auto metadata = reinterpret_cast<ClassMetadata *>(addressPoint);
|
||||||
|
|
||||||
// Zero out the rest of the metadata.
|
initializeClassMetadataFromPattern(metadata, bounds, description, pattern);
|
||||||
memset(bytes + templateSize, 0, metadataSize - templateSize);
|
|
||||||
|
|
||||||
// Okay, move to the address point.
|
assert(GenericCacheEntry::getFromMetadata(metadata) == entry);
|
||||||
ClassMetadata *metadata =
|
|
||||||
reinterpret_cast<ClassMetadata *>(bytes + templateAddressPoint);
|
|
||||||
auto patternBytes =
|
|
||||||
reinterpret_cast<const char*>(metadataTemplate) +
|
|
||||||
templateAddressPoint;
|
|
||||||
auto patternMetadata = reinterpret_cast<const ClassMetadata*>(patternBytes);
|
|
||||||
assert(metadata->isTypeMetadata());
|
assert(metadata->isTypeMetadata());
|
||||||
|
|
||||||
// Overwrite the superclass field.
|
|
||||||
metadata->SuperClass = superclass;
|
|
||||||
// Adjust the relative reference to the nominal type descriptor.
|
|
||||||
if (!metadata->isArtificialSubclass()) {
|
|
||||||
metadata->setDescription(patternMetadata->getDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
// The pattern might have private prefix matter prior to the start
|
|
||||||
// of metadata.
|
|
||||||
assert(metadata->getClassAddressPoint() <= templateAddressPoint);
|
|
||||||
metadata->setClassSize(metadataSize);
|
|
||||||
|
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +408,7 @@ swift::swift_getGenericMetadata(const TypeContextDescriptor *description,
|
|||||||
[&]() -> GenericCacheEntry* {
|
[&]() -> GenericCacheEntry* {
|
||||||
// Create new metadata to cache.
|
// Create new metadata to cache.
|
||||||
auto metadata = generics.InstantiationFunction(description, arguments);
|
auto metadata = generics.InstantiationFunction(description, arguments);
|
||||||
auto entry = GenericCacheEntry::getFromMetadata(generics, metadata);
|
auto entry = GenericCacheEntry::getFromMetadata(metadata);
|
||||||
entry->Value = metadata;
|
entry->Value = metadata;
|
||||||
return entry;
|
return entry;
|
||||||
});
|
});
|
||||||
@@ -1475,7 +1642,7 @@ static void _swift_initializeSuperclass(ClassMetadata *theClass) {
|
|||||||
_swift_initGenericClassObjCName(theClass);
|
_swift_initGenericClassObjCName(theClass);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const ClassMetadata *theSuperclass = theClass->SuperClass;
|
const ClassMetadata *theSuperclass = theClass->Superclass;
|
||||||
|
|
||||||
// Copy the class's immediate methods from the nominal type descriptor
|
// Copy the class's immediate methods from the nominal type descriptor
|
||||||
// to the class metadata.
|
// to the class metadata.
|
||||||
@@ -1509,8 +1676,8 @@ static void _swift_initializeSuperclass(ClassMetadata *theClass) {
|
|||||||
// Copy the generic requirements.
|
// Copy the generic requirements.
|
||||||
if (description->isGeneric()
|
if (description->isGeneric()
|
||||||
&& description->getGenericContextHeader().hasArguments()) {
|
&& description->getGenericContextHeader().hasArguments()) {
|
||||||
memcpy(classWords + description->getGenericArgumentOffset(ancestor),
|
memcpy(classWords + description->getGenericArgumentOffset(),
|
||||||
superWords + description->getGenericArgumentOffset(ancestor),
|
superWords + description->getGenericArgumentOffset(),
|
||||||
description->getGenericContextHeader().getNumArguments() *
|
description->getGenericContextHeader().getNumArguments() *
|
||||||
sizeof(uintptr_t));
|
sizeof(uintptr_t));
|
||||||
}
|
}
|
||||||
@@ -1531,7 +1698,7 @@ static void _swift_initializeSuperclass(ClassMetadata *theClass) {
|
|||||||
superWords + fieldOffsetVector,
|
superWords + fieldOffsetVector,
|
||||||
description->NumFields * sizeof(uintptr_t));
|
description->NumFields * sizeof(uintptr_t));
|
||||||
}
|
}
|
||||||
ancestor = ancestor->SuperClass;
|
ancestor = ancestor->Superclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SWIFT_OBJC_INTEROP
|
#if SWIFT_OBJC_INTEROP
|
||||||
@@ -1540,7 +1707,7 @@ static void _swift_initializeSuperclass(ClassMetadata *theClass) {
|
|||||||
auto theMetaclass = (ClassMetadata *)object_getClass((id)theClass);
|
auto theMetaclass = (ClassMetadata *)object_getClass((id)theClass);
|
||||||
auto theSuperMetaclass
|
auto theSuperMetaclass
|
||||||
= (const ClassMetadata *)object_getClass(id_const_cast(theSuperclass));
|
= (const ClassMetadata *)object_getClass(id_const_cast(theSuperclass));
|
||||||
theMetaclass->SuperClass = theSuperMetaclass;
|
theMetaclass->Superclass = theSuperMetaclass;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1556,7 +1723,10 @@ ClassMetadata *
|
|||||||
swift::swift_relocateClassMetadata(ClassMetadata *self,
|
swift::swift_relocateClassMetadata(ClassMetadata *self,
|
||||||
size_t templateSize,
|
size_t templateSize,
|
||||||
size_t numImmediateMembers) {
|
size_t numImmediateMembers) {
|
||||||
const ClassMetadata *superclass = self->SuperClass;
|
// Force the initialization of the metadata layout.
|
||||||
|
(void) self->getDescription()->getMetadataBounds();
|
||||||
|
|
||||||
|
const ClassMetadata *superclass = self->Superclass;
|
||||||
|
|
||||||
size_t metadataSize;
|
size_t metadataSize;
|
||||||
if (superclass && superclass->isTypeMetadata()) {
|
if (superclass && superclass->isTypeMetadata()) {
|
||||||
@@ -1608,7 +1778,7 @@ swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
|
|||||||
|
|
||||||
// If we have a superclass, start from its size and alignment instead.
|
// If we have a superclass, start from its size and alignment instead.
|
||||||
if (classHasSuperclass(self)) {
|
if (classHasSuperclass(self)) {
|
||||||
const ClassMetadata *super = self->SuperClass;
|
const ClassMetadata *super = self->Superclass;
|
||||||
|
|
||||||
// This is straightforward if the superclass is Swift.
|
// This is straightforward if the superclass is Swift.
|
||||||
#if SWIFT_OBJC_INTEROP
|
#if SWIFT_OBJC_INTEROP
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ public:
|
|||||||
/// Check if a class has a formal superclass in the AST.
|
/// Check if a class has a formal superclass in the AST.
|
||||||
static inline
|
static inline
|
||||||
bool classHasSuperclass(const ClassMetadata *c) {
|
bool classHasSuperclass(const ClassMetadata *c) {
|
||||||
return (c->SuperClass && c->SuperClass != getRootSuperclass());
|
return (c->Superclass && c->Superclass != getRootSuperclass());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace entries of a freshly-instantiated value witness table with more
|
/// Replace entries of a freshly-instantiated value witness table with more
|
||||||
|
|||||||
@@ -470,7 +470,7 @@ recur:
|
|||||||
// If the type is a class, try its superclass.
|
// If the type is a class, try its superclass.
|
||||||
if (const ClassMetadata *classType = type->getClassObject()) {
|
if (const ClassMetadata *classType = type->getClassObject()) {
|
||||||
if (classHasSuperclass(classType)) {
|
if (classHasSuperclass(classType)) {
|
||||||
type = getMetadataForClass(classType->SuperClass);
|
type = getMetadataForClass(classType->Superclass);
|
||||||
goto recur;
|
goto recur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -513,7 +513,7 @@ bool isRelatedType(const Metadata *type, const void *candidate,
|
|||||||
// If the type is a class, try its superclass.
|
// If the type is a class, try its superclass.
|
||||||
if (const ClassMetadata *classType = type->getClassObject()) {
|
if (const ClassMetadata *classType = type->getClassObject()) {
|
||||||
if (classHasSuperclass(classType)) {
|
if (classHasSuperclass(classType)) {
|
||||||
type = getMetadataForClass(classType->SuperClass);
|
type = getMetadataForClass(classType->Superclass);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -563,7 +563,7 @@ auto call(OpaqueValue *passedValue, const Metadata *T, const Metadata *passedTyp
|
|||||||
|
|
||||||
// Look through artificial subclasses.
|
// Look through artificial subclasses.
|
||||||
while (isa->isTypeMetadata() && isa->isArtificialSubclass()) {
|
while (isa->isTypeMetadata() && isa->isArtificialSubclass()) {
|
||||||
isa = isa->SuperClass;
|
isa = isa->Superclass;
|
||||||
}
|
}
|
||||||
passedType = isa;
|
passedType = isa;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ const Metadata *swift::swift_getObjectType(HeapObject *object) {
|
|||||||
while (classAsMetadata && classAsMetadata->isTypeMetadata()) {
|
while (classAsMetadata && classAsMetadata->isTypeMetadata()) {
|
||||||
if (!classAsMetadata->isArtificialSubclass())
|
if (!classAsMetadata->isArtificialSubclass())
|
||||||
return classAsMetadata;
|
return classAsMetadata;
|
||||||
classAsMetadata = classAsMetadata->SuperClass;
|
classAsMetadata = classAsMetadata->Superclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
id objcObject = reinterpret_cast<id>(object);
|
id objcObject = reinterpret_cast<id>(object);
|
||||||
@@ -195,10 +195,10 @@ static NSString *_getClassDescription(Class cls) {
|
|||||||
return _swift_getObjCClassOfAllocated(self);
|
return _swift_getObjCClassOfAllocated(self);
|
||||||
}
|
}
|
||||||
+ (Class)superclass {
|
+ (Class)superclass {
|
||||||
return (Class)((const ClassMetadata*) self)->SuperClass;
|
return (Class)((const ClassMetadata*) self)->Superclass;
|
||||||
}
|
}
|
||||||
- (Class)superclass {
|
- (Class)superclass {
|
||||||
return (Class)_swift_getClassOfAllocated(self)->SuperClass;
|
return (Class)_swift_getClassOfAllocated(self)->Superclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (BOOL)isMemberOfClass:(Class)cls {
|
+ (BOOL)isMemberOfClass:(Class)cls {
|
||||||
@@ -289,7 +289,7 @@ static NSString *_getClassDescription(Class cls) {
|
|||||||
|
|
||||||
- (BOOL)isKindOfClass:(Class)someClass {
|
- (BOOL)isKindOfClass:(Class)someClass {
|
||||||
for (auto cls = _swift_getClassOfAllocated(self); cls != nullptr;
|
for (auto cls = _swift_getClassOfAllocated(self); cls != nullptr;
|
||||||
cls = cls->SuperClass)
|
cls = cls->Superclass)
|
||||||
if (cls == (const ClassMetadata*) someClass)
|
if (cls == (const ClassMetadata*) someClass)
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ static NSString *_getClassDescription(Class cls) {
|
|||||||
|
|
||||||
+ (BOOL)isSubclassOfClass:(Class)someClass {
|
+ (BOOL)isSubclassOfClass:(Class)someClass {
|
||||||
for (auto cls = (const ClassMetadata*) self; cls != nullptr;
|
for (auto cls = (const ClassMetadata*) self; cls != nullptr;
|
||||||
cls = cls->SuperClass)
|
cls = cls->Superclass)
|
||||||
if (cls == (const ClassMetadata*) someClass)
|
if (cls == (const ClassMetadata*) someClass)
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
|
|||||||
@@ -63,14 +63,18 @@ class C<T> : B {}
|
|||||||
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1CCMa"
|
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1CCMa"
|
||||||
// Superclass.
|
// Superclass.
|
||||||
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1BCMn"
|
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1BCMn"
|
||||||
|
// Negative size in words.
|
||||||
|
// CHECK-SAME: i32 2,
|
||||||
|
// Positive size in words.
|
||||||
|
// CHECK-32-SAME: i32 15,
|
||||||
|
// CHECK-64-SAME: i32 12,
|
||||||
|
// Num immediate members.
|
||||||
|
// CHECK-32-SAME: i32 1,
|
||||||
// Field count.
|
// Field count.
|
||||||
// CHECK-SAME: i32 0,
|
// CHECK-SAME: i32 0,
|
||||||
// Field offset vector offset.
|
// Field offset vector offset.
|
||||||
// CHECK-32-SAME: i32 15,
|
// CHECK-32-SAME: i32 15,
|
||||||
// CHECK-64-SAME: i32 12,
|
// CHECK-64-SAME: i32 12,
|
||||||
// Argument offset.
|
|
||||||
// CHECK-32-SAME: i32 14,
|
|
||||||
// CHECK-64-SAME: i32 11,
|
|
||||||
// Instantiation function.
|
// Instantiation function.
|
||||||
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1CCMi"
|
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1CCMi"
|
||||||
// Instantiation cache.
|
// Instantiation cache.
|
||||||
|
|||||||
@@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
// CHECK: @"$S16class_resilience14ResilientChildC5fields5Int32VvpWvd" = hidden global [[INT]] {{8|16}}
|
// CHECK: @"$S16class_resilience14ResilientChildC5fields5Int32VvpWvd" = hidden global [[INT]] {{8|16}}
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience21ResilientGenericChildCMo" = {{(protected )?}}global [[INT]] 0
|
// CHECK: @"$S16class_resilience21ResilientGenericChildCMo" = {{(protected )?}}global [[BOUNDS:{ (i32|i64), i32, i32 }]] zeroinitializer
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience26ClassWithResilientPropertyCMo" = {{(protected )?}}constant [[INT]] {{52|80}}
|
// CHECK: @"$S16class_resilience26ClassWithResilientPropertyCMo" = {{(protected )?}}constant [[BOUNDS]]
|
||||||
|
// CHECK-SAME-32: { [[INT]] 52, i32 2, i32 13 }
|
||||||
|
// CHECK-SAME-64: { [[INT]] 80, i32 2, i32 10 }
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd" = hidden constant [[INT]] {{8|16}}
|
// CHECK: @"$S16class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd" = hidden constant [[INT]] {{8|16}}
|
||||||
// CHECK: @"$S16class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd" = hidden constant [[INT]] {{12|20}}
|
// CHECK: @"$S16class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd" = hidden constant [[INT]] {{12|20}}
|
||||||
@@ -28,6 +30,8 @@
|
|||||||
|
|
||||||
// CHECK: [[RESILIENTCHILD_NAME:@.*]] = private constant [15 x i8] c"ResilientChild\00"
|
// CHECK: [[RESILIENTCHILD_NAME:@.*]] = private constant [15 x i8] c"ResilientChild\00"
|
||||||
|
|
||||||
|
// CHECK: @"$S16class_resilience14ResilientChildCMo" = {{(protected )?}}global [[BOUNDS]] zeroinitializer
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience14ResilientChildCMn" = {{(protected )?}}constant <{{.*}}> <{
|
// CHECK: @"$S16class_resilience14ResilientChildCMn" = {{(protected )?}}constant <{{.*}}> <{
|
||||||
// -- flags: class, unique, reflectable, has vtable, has resilient superclass
|
// -- flags: class, unique, reflectable, has vtable, has resilient superclass
|
||||||
// CHECK-SAME: <i32 0xD004_0050>
|
// CHECK-SAME: <i32 0xD004_0050>
|
||||||
@@ -39,17 +43,23 @@
|
|||||||
// CHECK-SAME: i32 3,
|
// CHECK-SAME: i32 3,
|
||||||
// CHECK-SAME: }>
|
// CHECK-SAME: }>
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience14ResilientChildCMo" = {{(protected )?}}global [[INT]] 0
|
// CHECK: @"$S16class_resilience16FixedLayoutChildCMo" = {{(protected )?}}global [[BOUNDS]] zeroinitializer
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience16FixedLayoutChildCMo" = {{(protected )?}}global [[INT]] 0
|
// CHECK: @"$S16class_resilience17MyResilientParentCMo" = {{(protected )?}}constant [[BOUNDS]]
|
||||||
|
// CHECK-SAME-32: { [[INT]] 52, i32 2, i32 13 }
|
||||||
|
// CHECK-SAME-64: { [[INT]] 80, i32 2, i32 10 }
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience17MyResilientParentCMo" = {{(protected )?}}constant [[INT]] {{52|80}}
|
// CHECK: @"$S16class_resilience16MyResilientChildCMo" = {{(protected )?}}constant [[BOUNDS]]
|
||||||
|
// CHECK-SAME-32: { [[INT]] 60, i32 2, i32 15 }
|
||||||
|
// CHECK-SAME-64: { [[INT]] 96, i32 2, i32 12 }
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience16MyResilientChildCMo" = {{(protected )?}}constant [[INT]] {{60|96}}
|
// CHECK: @"$S16class_resilience24MyResilientGenericParentCMo" = {{(protected )?}}constant [[BOUNDS]]
|
||||||
|
// CHECK-SAME-32: { [[INT]] 52, i32 2, i32 13 }
|
||||||
|
// CHECK-SAME-64: { [[INT]] 80, i32 2, i32 10 }
|
||||||
|
|
||||||
// CHECK: @"$S16class_resilience24MyResilientGenericParentCMo" = {{(protected )?}}constant [[INT]] {{52|80}}
|
// CHECK: @"$S16class_resilience24MyResilientConcreteChildCMo" = {{(protected )?}}constant [[BOUNDS]]
|
||||||
|
// CHECK-SAME-32: { [[INT]] 64, i32 2, i32 16 }
|
||||||
// CHECK: @"$S16class_resilience24MyResilientConcreteChildCMo" = {{(protected )?}}constant [[INT]] {{64|104}}
|
// CHECK-SAME-64: { [[INT]] 104, i32 2, i32 13 }
|
||||||
|
|
||||||
import resilient_class
|
import resilient_class
|
||||||
import resilient_struct
|
import resilient_struct
|
||||||
@@ -273,7 +283,7 @@ extension ResilientGenericOutsideParent {
|
|||||||
|
|
||||||
// CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds %T16class_resilience21ResilientGenericChildC, %T16class_resilience21ResilientGenericChildC* %0, i32 0, i32 0, i32 0
|
// CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds %T16class_resilience21ResilientGenericChildC, %T16class_resilience21ResilientGenericChildC* %0, i32 0, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ADDR]]
|
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ADDR]]
|
||||||
// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S16class_resilience21ResilientGenericChildCMo"
|
// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience21ResilientGenericChildCMo", i32 0, i32 0)
|
||||||
// CHECK-NEXT: [[METADATA_OFFSET:%.*]] = add [[INT]] [[BASE]], {{16|32}}
|
// CHECK-NEXT: [[METADATA_OFFSET:%.*]] = add [[INT]] [[BASE]], {{16|32}}
|
||||||
// CHECK-NEXT: [[ISA_ADDR:%.*]] = bitcast %swift.type* [[ISA]] to i8*
|
// CHECK-NEXT: [[ISA_ADDR:%.*]] = bitcast %swift.type* [[ISA]] to i8*
|
||||||
// CHECK-NEXT: [[FIELD_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[ISA_ADDR]], [[INT]] [[METADATA_OFFSET]]
|
// CHECK-NEXT: [[FIELD_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[ISA_ADDR]], [[INT]] [[METADATA_OFFSET]]
|
||||||
@@ -305,7 +315,7 @@ extension ResilientGenericOutsideParent {
|
|||||||
// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @"$S15resilient_class29ResilientGenericOutsideParentC0B11_resilienceE22genericExtensionMethodxmyF"(%T15resilient_class29ResilientGenericOutsideParentC* swiftself) #0 {
|
// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @"$S15resilient_class29ResilientGenericOutsideParentC0B11_resilienceE22genericExtensionMethodxmyF"(%T15resilient_class29ResilientGenericOutsideParentC* swiftself) #0 {
|
||||||
// CHECK: [[ISA_ADDR:%.*]] = bitcast %T15resilient_class29ResilientGenericOutsideParentC* %0 to %swift.type**
|
// CHECK: [[ISA_ADDR:%.*]] = bitcast %T15resilient_class29ResilientGenericOutsideParentC* %0 to %swift.type**
|
||||||
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
|
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
|
||||||
// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class29ResilientGenericOutsideParentCMo"
|
// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class29ResilientGenericOutsideParentCMo", i32 0, i32 0)
|
||||||
// CHECK-NEXT: [[GENERIC_PARAM_OFFSET:%.*]] = add [[INT]] [[BASE]], 0
|
// CHECK-NEXT: [[GENERIC_PARAM_OFFSET:%.*]] = add [[INT]] [[BASE]], 0
|
||||||
// CHECK-NEXT: [[ISA_TMP:%.*]] = bitcast %swift.type* [[ISA]] to i8*
|
// CHECK-NEXT: [[ISA_TMP:%.*]] = bitcast %swift.type* [[ISA]] to i8*
|
||||||
// CHECK-NEXT: [[GENERIC_PARAM_TMP:%.*]] = getelementptr inbounds i8, i8* [[ISA_TMP]], [[INT]] [[GENERIC_PARAM_OFFSET]]
|
// CHECK-NEXT: [[GENERIC_PARAM_TMP:%.*]] = getelementptr inbounds i8, i8* [[ISA_TMP]], [[INT]] [[GENERIC_PARAM_OFFSET]]
|
||||||
@@ -352,39 +362,21 @@ extension ResilientGenericOutsideParent {
|
|||||||
|
|
||||||
// CHECK-LABEL: define private void @initialize_metadata_ResilientChild(i8*)
|
// CHECK-LABEL: define private void @initialize_metadata_ResilientChild(i8*)
|
||||||
|
|
||||||
// Get the superclass size and address point...
|
|
||||||
|
|
||||||
// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
|
|
||||||
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER]] to i8*
|
|
||||||
// CHECK: [[SIZE_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{36|56}}
|
|
||||||
// CHECK: [[SIZE_ADDR:%.*]] = bitcast i8* [[SIZE_TMP]] to i32*
|
|
||||||
// CHECK: [[SIZE:%.*]] = load i32, i32* [[SIZE_ADDR]]
|
|
||||||
// CHECK: [[ADDRESS_POINT_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{40|60}}
|
|
||||||
// CHECK: [[ADDRESS_POINT_ADDR:%.*]] = bitcast i8* [[ADDRESS_POINT_TMP]] to i32*
|
|
||||||
// CHECK: [[ADDRESS_POINT:%.*]] = load i32, i32* [[ADDRESS_POINT_ADDR]]
|
|
||||||
|
|
||||||
// CHECK: [[OFFSET:%.*]] = sub i32 [[SIZE]], [[ADDRESS_POINT]]
|
|
||||||
|
|
||||||
// Initialize class metadata base offset...
|
|
||||||
// CHECK-32: store [[INT]] [[OFFSET]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
|
|
||||||
|
|
||||||
// CHECK-64: [[OFFSET_ZEXT:%.*]] = zext i32 [[OFFSET]] to i64
|
|
||||||
// CHECK-64: store [[INT]] [[OFFSET_ZEXT]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
|
|
||||||
|
|
||||||
// Initialize the superclass field...
|
// Initialize the superclass field...
|
||||||
|
// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
|
||||||
// CHECK: store %swift.type* [[SUPER]], %swift.type** getelementptr inbounds ({{.*}})
|
// CHECK: store %swift.type* [[SUPER]], %swift.type** getelementptr inbounds ({{.*}})
|
||||||
|
|
||||||
// Relocate metadata if necessary...
|
// Relocate metadata if necessary...
|
||||||
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata(%swift.type* {{.*}}, [[INT]] {{60|96}}, [[INT]] 4)
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata(%swift.type* {{.*}}, [[INT]] {{60|96}}, [[INT]] 4)
|
||||||
|
|
||||||
// Initialize field offset vector...
|
// Initialize field offset vector...
|
||||||
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
|
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience14ResilientChildCMo", i32 0, i32 0)
|
||||||
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{12|24}}
|
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{12|24}}
|
||||||
|
|
||||||
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 1, i8*** {{.*}}, [[INT]]* {{.*}})
|
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 1, i8*** {{.*}}, [[INT]]* {{.*}})
|
||||||
|
|
||||||
// Initialize constructor vtable override...
|
// Initialize constructor vtable override...
|
||||||
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
|
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
|
||||||
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{16|32}}
|
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{16|32}}
|
||||||
// CHECK: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
|
// CHECK: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
|
||||||
// CHECK: [[VTABLE_ENTRY_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[OFFSET]]
|
// CHECK: [[VTABLE_ENTRY_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[OFFSET]]
|
||||||
@@ -392,7 +384,7 @@ extension ResilientGenericOutsideParent {
|
|||||||
// CHECK: store i8* bitcast (%T16class_resilience14ResilientChildC* (%T16class_resilience14ResilientChildC*)* @"$S16class_resilience14ResilientChildCACycfc" to i8*), i8** [[VTABLE_ENTRY_TMP]]
|
// CHECK: store i8* bitcast (%T16class_resilience14ResilientChildC* (%T16class_resilience14ResilientChildC*)* @"$S16class_resilience14ResilientChildCACycfc" to i8*), i8** [[VTABLE_ENTRY_TMP]]
|
||||||
|
|
||||||
// Initialize getValue() vtable override...
|
// Initialize getValue() vtable override...
|
||||||
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
|
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
|
||||||
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{28|56}}
|
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{28|56}}
|
||||||
// CHECK: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
|
// CHECK: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
|
||||||
// CHECK: [[VTABLE_ENTRY_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[OFFSET]]
|
// CHECK: [[VTABLE_ENTRY_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[OFFSET]]
|
||||||
@@ -410,7 +402,7 @@ extension ResilientGenericOutsideParent {
|
|||||||
// CHECK-LABEL: define{{( protected)?}} swiftcc i32 @"$S16class_resilience14ResilientChildC5fields5Int32VvgTj"(%T16class_resilience14ResilientChildC* swiftself)
|
// CHECK-LABEL: define{{( protected)?}} swiftcc i32 @"$S16class_resilience14ResilientChildC5fields5Int32VvgTj"(%T16class_resilience14ResilientChildC* swiftself)
|
||||||
// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T16class_resilience14ResilientChildC, %T16class_resilience14ResilientChildC* %0, i32 0, i32 0, i32 0
|
// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T16class_resilience14ResilientChildC, %T16class_resilience14ResilientChildC* %0, i32 0, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
|
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
|
||||||
// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
|
// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience14ResilientChildCMo", i32 0, i32 0)
|
||||||
// CHECK-NEXT: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[ISA]] to i8*
|
// CHECK-NEXT: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[ISA]] to i8*
|
||||||
// CHECK-NEXT: [[VTABLE_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[BASE]]
|
// CHECK-NEXT: [[VTABLE_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[BASE]]
|
||||||
// CHECK-NEXT: [[VTABLE_OFFSET_ADDR:%.*]] = bitcast i8* [[VTABLE_OFFSET_TMP]] to i32 (%T16class_resilience14ResilientChildC*)**
|
// CHECK-NEXT: [[VTABLE_OFFSET_ADDR:%.*]] = bitcast i8* [[VTABLE_OFFSET_TMP]] to i32 (%T16class_resilience14ResilientChildC*)**
|
||||||
@@ -423,7 +415,7 @@ extension ResilientGenericOutsideParent {
|
|||||||
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S16class_resilience14ResilientChildC5fields5Int32VvsTj"(i32, %T16class_resilience14ResilientChildC* swiftself)
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S16class_resilience14ResilientChildC5fields5Int32VvsTj"(i32, %T16class_resilience14ResilientChildC* swiftself)
|
||||||
// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T16class_resilience14ResilientChildC, %T16class_resilience14ResilientChildC* %1, i32 0, i32 0, i32 0
|
// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T16class_resilience14ResilientChildC, %T16class_resilience14ResilientChildC* %1, i32 0, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
|
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
|
||||||
// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
|
// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience14ResilientChildCMo", i32 0, i32 0)
|
||||||
// CHECK-NEXT: [[METADATA_OFFSET:%.*]] = add [[INT]] [[BASE]], {{4|8}}
|
// CHECK-NEXT: [[METADATA_OFFSET:%.*]] = add [[INT]] [[BASE]], {{4|8}}
|
||||||
// CHECK-NEXT: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[ISA]] to i8*
|
// CHECK-NEXT: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[ISA]] to i8*
|
||||||
// CHECK-NEXT: [[VTABLE_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[METADATA_OFFSET]]
|
// CHECK-NEXT: [[VTABLE_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[METADATA_OFFSET]]
|
||||||
@@ -437,26 +429,8 @@ extension ResilientGenericOutsideParent {
|
|||||||
|
|
||||||
// CHECK-LABEL: define private void @initialize_metadata_FixedLayoutChild(i8*)
|
// CHECK-LABEL: define private void @initialize_metadata_FixedLayoutChild(i8*)
|
||||||
|
|
||||||
// Get the superclass size and address point...
|
|
||||||
|
|
||||||
// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
|
|
||||||
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER]] to i8*
|
|
||||||
// CHECK: [[SIZE_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{36|56}}
|
|
||||||
// CHECK: [[SIZE_ADDR:%.*]] = bitcast i8* [[SIZE_TMP]] to i32*
|
|
||||||
// CHECK: [[SIZE:%.*]] = load i32, i32* [[SIZE_ADDR]]
|
|
||||||
// CHECK: [[ADDRESS_POINT_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{40|60}}
|
|
||||||
// CHECK: [[ADDRESS_POINT_ADDR:%.*]] = bitcast i8* [[ADDRESS_POINT_TMP]] to i32*
|
|
||||||
// CHECK: [[ADDRESS_POINT:%.*]] = load i32, i32* [[ADDRESS_POINT_ADDR]]
|
|
||||||
|
|
||||||
// CHECK: [[OFFSET:%.*]] = sub i32 [[SIZE]], [[ADDRESS_POINT]]
|
|
||||||
|
|
||||||
// Initialize class metadata base offset...
|
|
||||||
// CHECK-32: store [[INT]] [[OFFSET]], [[INT]]* @"$S16class_resilience16FixedLayoutChildCMo"
|
|
||||||
|
|
||||||
// CHECK-64: [[OFFSET_ZEXT:%.*]] = zext i32 [[OFFSET]] to i64
|
|
||||||
// CHECK-64: store [[INT]] [[OFFSET_ZEXT]], [[INT]]* @"$S16class_resilience16FixedLayoutChildCMo"
|
|
||||||
|
|
||||||
// Initialize the superclass field...
|
// Initialize the superclass field...
|
||||||
|
// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
|
||||||
// CHECK: store %swift.type* [[SUPER]], %swift.type** getelementptr inbounds ({{.*}})
|
// CHECK: store %swift.type* [[SUPER]], %swift.type** getelementptr inbounds ({{.*}})
|
||||||
|
|
||||||
// Relocate metadata if necessary...
|
// Relocate metadata if necessary...
|
||||||
@@ -471,23 +445,14 @@ extension ResilientGenericOutsideParent {
|
|||||||
|
|
||||||
// Get the superclass size and address point...
|
// Get the superclass size and address point...
|
||||||
|
|
||||||
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8** bitcast ({{.*}} @"$S16class_resilience21ResilientGenericChildCMP" to i8**))
|
||||||
|
|
||||||
|
// Initialize the superclass pointer...
|
||||||
// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class29ResilientGenericOutsideParentCMa"(%swift.type* %T)
|
// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class29ResilientGenericOutsideParentCMa"(%swift.type* %T)
|
||||||
// CHECK: [[SUPER_TMP:%.*]] = bitcast %swift.type* [[SUPER]] to %objc_class*
|
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
|
||||||
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %objc_class* [[SUPER_TMP]] to i8*
|
// CHECK: [[SUPER_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
|
||||||
// CHECK: [[SIZE_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{36|56}}
|
// CHECK: store %swift.type* [[SUPER]], %swift.type** [[SUPER_ADDR]],
|
||||||
// CHECK: [[SIZE_ADDR:%.*]] = bitcast i8* [[SIZE_TMP]] to i32*
|
|
||||||
// CHECK: [[SIZE:%.*]] = load i32, i32* [[SIZE_ADDR]]
|
|
||||||
// CHECK: [[ADDRESS_POINT_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{40|60}}
|
|
||||||
// CHECK: [[ADDRESS_POINT_ADDR:%.*]] = bitcast i8* [[ADDRESS_POINT_TMP]] to i32*
|
|
||||||
// CHECK: [[ADDRESS_POINT:%.*]] = load i32, i32* [[ADDRESS_POINT_ADDR]]
|
|
||||||
|
|
||||||
// CHECK: [[OFFSET:%.*]] = sub i32 [[SIZE]], [[ADDRESS_POINT]]
|
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]],
|
||||||
|
|
||||||
// Initialize class metadata base offset...
|
|
||||||
// CHECK-32: store [[INT]] [[OFFSET]], [[INT]]* @"$S16class_resilience21ResilientGenericChildCMo"
|
|
||||||
|
|
||||||
// CHECK-64: [[OFFSET_ZEXT:%.*]] = zext i32 [[OFFSET]] to i64
|
|
||||||
// CHECK-64: store [[INT]] [[OFFSET_ZEXT]], [[INT]]* @"$S16class_resilience21ResilientGenericChildCMo"
|
|
||||||
|
|
||||||
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}} @"$S16class_resilience21ResilientGenericChildCMP" to i8**), [[INT]] {{[0-9]+}}, [[INT]] {{[0-9]+}}, i8** %1, %objc_class* [[SUPER_TMP]], [[INT]] 5)
|
|
||||||
// CHECK: ret %swift.type* [[METADATA]]
|
// CHECK: ret %swift.type* [[METADATA]]
|
||||||
|
|||||||
@@ -116,8 +116,6 @@ import Swift
|
|||||||
// CHECK-SAME: i32 1,
|
// CHECK-SAME: i32 1,
|
||||||
// -- No empty cases
|
// -- No empty cases
|
||||||
// CHECK-SAME: i32 0,
|
// CHECK-SAME: i32 0,
|
||||||
// -- Case type accessor
|
|
||||||
// CHECK-SAME: i32 2,
|
|
||||||
// -- generic instantiation function
|
// -- generic instantiation function
|
||||||
// CHECK-SAME: @"$S4enum16DynamicSingletonOMi"
|
// CHECK-SAME: @"$S4enum16DynamicSingletonOMi"
|
||||||
// -- generic parameters, requirements, key, extra
|
// -- generic parameters, requirements, key, extra
|
||||||
|
|||||||
@@ -19,12 +19,16 @@ import Swift
|
|||||||
// CHECK-SAME: <i32 0x8004_00D0>
|
// CHECK-SAME: <i32 0x8004_00D0>
|
||||||
// -- name
|
// -- name
|
||||||
// CHECK-SAME: [12 x i8]* [[ROOTGENERIC_NAME]]
|
// CHECK-SAME: [12 x i8]* [[ROOTGENERIC_NAME]]
|
||||||
|
// -- negative size in words
|
||||||
|
// CHECK-SAME: i32 2,
|
||||||
|
// -- positive size in words
|
||||||
|
// CHECK-SAME: i32 18,
|
||||||
|
// -- num immediate members
|
||||||
|
// CHECK-SAME: i32 8,
|
||||||
// -- num fields
|
// -- num fields
|
||||||
// CHECK-SAME: i32 3,
|
// CHECK-SAME: i32 3,
|
||||||
// -- field offset vector offset
|
// -- field offset vector offset
|
||||||
// CHECK-SAME: i32 15,
|
// CHECK-SAME: i32 15,
|
||||||
// -- generic parameter vector offset
|
|
||||||
// CHECK-SAME: i32 10,
|
|
||||||
// -- template instantiation function
|
// -- template instantiation function
|
||||||
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_classes11RootGenericCMi"
|
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_classes11RootGenericCMi"
|
||||||
// -- template instantiation cache
|
// -- template instantiation cache
|
||||||
@@ -38,10 +42,29 @@ import Swift
|
|||||||
// CHECK-SAME: }
|
// CHECK-SAME: }
|
||||||
|
|
||||||
// CHECK-LABEL: @"$S15generic_classes11RootGenericCMP" = internal constant
|
// CHECK-LABEL: @"$S15generic_classes11RootGenericCMP" = internal constant
|
||||||
// -- nominal type descriptor
|
// CHECK-SAME: <{
|
||||||
// CHECK-SAME: @"$S15generic_classes11RootGenericCMn"
|
// -- heap destructor
|
||||||
|
// CHECK-SAME: @"$S15generic_classes11RootGenericCfD"
|
||||||
// -- ivar destroyer
|
// -- ivar destroyer
|
||||||
// CHECK-SAME: i8* null
|
// CHECK-SAME: i8* null,
|
||||||
|
// -- flags
|
||||||
|
// CHECK_SAME: i32 3,
|
||||||
|
// -- immediate pattern size
|
||||||
|
// CHECK-SAME: i16 0,
|
||||||
|
// -- immediate pattern target offset
|
||||||
|
// CHECK-SAME: i16 0,
|
||||||
|
// -- extra data size
|
||||||
|
// CHECK-SAME-native: i16 0,
|
||||||
|
// CHECK-SAME-objc: i16 23,
|
||||||
|
// -- class ro-data offset
|
||||||
|
// CHECK-SAME-native: i16 0,
|
||||||
|
// CHECK-SAME-objc: i16 5,
|
||||||
|
// -- metaclass object offset
|
||||||
|
// CHECK-SAME-native: i16 0,
|
||||||
|
// CHECK-SAME-objc: i16 0,
|
||||||
|
// -- class ro-data offset
|
||||||
|
// CHECK-SAME-native: i16 0
|
||||||
|
// CHECK-SAME-objc: i16 14,
|
||||||
// CHECK-SAME: }>
|
// CHECK-SAME: }>
|
||||||
|
|
||||||
// -- Check that offset vars are emitted for fixed-layout generics
|
// -- Check that offset vars are emitted for fixed-layout generics
|
||||||
@@ -87,10 +110,28 @@ import Swift
|
|||||||
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_classes015GenericInheritsC0CMi"
|
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_classes015GenericInheritsC0CMi"
|
||||||
|
|
||||||
// CHECK: @"$S15generic_classes015GenericInheritsC0CMP" = internal constant
|
// CHECK: @"$S15generic_classes015GenericInheritsC0CMP" = internal constant
|
||||||
// -- nominal type descriptor
|
// -- heap destructor
|
||||||
// CHECK-SAME: @"$S15generic_classes015GenericInheritsC0CMn",
|
// CHECK-SAME: @"$S15generic_classes015GenericInheritsC0CfD"
|
||||||
// -- ivar destroyer
|
// -- ivar destroyer
|
||||||
// CHECK-SAME: i8* null
|
// CHECK-SAME: i8* null,
|
||||||
|
// -- flags
|
||||||
|
// CHECK_SAME: i32 3,
|
||||||
|
// -- immediate pattern size
|
||||||
|
// CHECK-SAME: i16 0,
|
||||||
|
// -- immediate pattern target offset
|
||||||
|
// CHECK-SAME: i16 0,
|
||||||
|
// -- extra data size
|
||||||
|
// CHECK-SAME-native: i16 0,
|
||||||
|
// CHECK-SAME-objc: i16 23,
|
||||||
|
// -- class ro-data offset
|
||||||
|
// CHECK-SAME-native: i16 0,
|
||||||
|
// CHECK-SAME-objc: i16 5,
|
||||||
|
// -- metaclass object offset
|
||||||
|
// CHECK-SAME-native: i16 0,
|
||||||
|
// CHECK-SAME-objc: i16 0,
|
||||||
|
// -- class ro-data offset
|
||||||
|
// CHECK-SAME-native: i16 0
|
||||||
|
// CHECK-SAME-objc: i16 14,
|
||||||
// CHECK-SAME: }
|
// CHECK-SAME: }
|
||||||
|
|
||||||
// CHECK: @"$S15generic_classes018GenericInheritsNonC0CMP"
|
// CHECK: @"$S15generic_classes018GenericInheritsNonC0CMP"
|
||||||
@@ -292,13 +333,13 @@ entry(%c : $RootGeneric<Int32>):
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S15generic_classes11RootGenericCMi"(%swift.type_descriptor*, i8**) {{.*}} {
|
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S15generic_classes11RootGenericCMi"(%swift.type_descriptor*, i8**) {{.*}} {
|
||||||
// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, {{.*}}, i64 8)
|
// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, {{.*}} @"$S15generic_classes11RootGenericCMP"{{.*}})
|
||||||
// -- initialize the dependent field offsets
|
// -- initialize the dependent field offsets
|
||||||
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
|
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
|
|
||||||
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S15generic_classes22RootGenericFixedLayoutCMi"(%swift.type_descriptor*, i8**) {{.*}} {
|
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S15generic_classes22RootGenericFixedLayoutCMi"(%swift.type_descriptor*, i8**) {{.*}} {
|
||||||
// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, {{.*}}, i64 5)
|
// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, {{.*}} @"$S15generic_classes22RootGenericFixedLayoutCMP"{{.*}})
|
||||||
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
|
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
|
||||||
// CHECK: }
|
// CHECK: }
|
||||||
|
|
||||||
@@ -309,10 +350,7 @@ entry(%c : $RootGeneric<Int32>):
|
|||||||
// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
|
// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
|
||||||
// CHECK: %B = load %swift.type*, %swift.type** [[T1]]
|
// CHECK: %B = load %swift.type*, %swift.type** [[T1]]
|
||||||
// Construct the superclass.
|
// Construct the superclass.
|
||||||
// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15generic_classes11RootGenericCMa"(%swift.type* %A)
|
// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, {{.*}} @"$S15generic_classes015GenericInheritsC0CMP"{{.*}})
|
||||||
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[SUPER]] to %objc_class*
|
|
||||||
// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** {{.*}}, i64 96, i64 16, i8** %1, %objc_class* [[T0]], i64 6)
|
|
||||||
// CHECK-objc: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** {{.*}}, i64 280, i64 200, i8** %1, %objc_class* [[T0]], i64 6)
|
|
||||||
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
||||||
// Put the generic arguments in their correct positions.
|
// Put the generic arguments in their correct positions.
|
||||||
// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i64 18
|
// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i64 18
|
||||||
@@ -321,26 +359,10 @@ entry(%c : $RootGeneric<Int32>):
|
|||||||
// CHECK: [[B_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i64 19
|
// CHECK: [[B_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i64 19
|
||||||
// CHECK: [[T0:%.*]] = bitcast %swift.type* %B to i8*
|
// CHECK: [[T0:%.*]] = bitcast %swift.type* %B to i8*
|
||||||
// CHECK: store i8* [[T0]], i8** [[B_ADDR]], align 8
|
// CHECK: store i8* [[T0]], i8** [[B_ADDR]], align 8
|
||||||
// Set up the isa.
|
// CHECK: [[SUPER:%.*]] ={{( tail)?}} call %swift.type* @"$S15generic_classes11RootGenericCMa"(%swift.type* %A)
|
||||||
// CHECK-objc: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
|
||||||
// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 0
|
// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
|
||||||
// CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to %objc_class**
|
// CHECK: store %swift.type* [[SUPER]], %swift.type** [[T1]],
|
||||||
// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -25
|
|
||||||
// CHECK-objc: [[METACLASS:%.*]] = bitcast i8** [[T0]] to %objc_class*
|
|
||||||
// CHECK-objc: store %objc_class* [[METACLASS]], %objc_class** [[T1]], align 8
|
|
||||||
// Set up the instance rodata pointer.
|
|
||||||
// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 4
|
|
||||||
// CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to i64*
|
|
||||||
// CHECK-objc: [[RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -20
|
|
||||||
// CHECK-objc: [[T2:%.*]] = ptrtoint i8** [[RODATA]] to i64
|
|
||||||
// CHECK-objc: [[T3:%.*]] = or i64 [[T2]], 1
|
|
||||||
// CHECK-objc: store i64 [[T3]], i64* [[T1]], align 8
|
|
||||||
// Set up the class rodata pointer.
|
|
||||||
// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -21
|
|
||||||
// CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to i64*
|
|
||||||
// CHECK-objc: [[META_RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -11
|
|
||||||
// CHECK-objc: [[T2:%.*]] = ptrtoint i8** [[META_RODATA]] to i64
|
|
||||||
// CHECK-objc: store i64 [[T2]], i64* [[T1]], align 8
|
|
||||||
// Initialize our own dependent field offsets.
|
// Initialize our own dependent field offsets.
|
||||||
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
|
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
|
||||||
// CHECK: [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i64 23
|
// CHECK: [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i64 23
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ import Builtin
|
|||||||
// CHECK-SAME: i32 1,
|
// CHECK-SAME: i32 1,
|
||||||
// -- field offset vector offset
|
// -- field offset vector offset
|
||||||
// CHECK-SAME: i32 3,
|
// CHECK-SAME: i32 3,
|
||||||
// -- generic parameter vector offset
|
|
||||||
// CHECK-SAME: i32 2,
|
|
||||||
// -- generic instantiation info
|
// -- generic instantiation info
|
||||||
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_structs13SingleDynamicVMi"
|
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_structs13SingleDynamicVMi"
|
||||||
// CHECK-SAME: [{{[0-9]+}} x i8*]* @"$S15generic_structs13SingleDynamicVMI"
|
// CHECK-SAME: [{{[0-9]+}} x i8*]* @"$S15generic_structs13SingleDynamicVMI"
|
||||||
@@ -59,8 +57,6 @@ import Builtin
|
|||||||
// CHECK-SAME: i32 2,
|
// CHECK-SAME: i32 2,
|
||||||
// -- field offset vector offset
|
// -- field offset vector offset
|
||||||
// CHECK-SAME: i32 6,
|
// CHECK-SAME: i32 6,
|
||||||
// -- generic parameter vector offset
|
|
||||||
// CHECK-SAME: i32 2,
|
|
||||||
// -- generic params, requirements, key args, extra args
|
// -- generic params, requirements, key args, extra args
|
||||||
// CHECK-SAME: i32 2, i32 2, i32 2, i32 2,
|
// CHECK-SAME: i32 2, i32 2, i32 2, i32 2,
|
||||||
// -- generic parameters
|
// -- generic parameters
|
||||||
|
|||||||
@@ -11,30 +11,43 @@
|
|||||||
// CHECK-LABEL: @"$S13generic_types1ACMI" = internal global [16 x i8*] zeroinitializer, align 8
|
// CHECK-LABEL: @"$S13generic_types1ACMI" = internal global [16 x i8*] zeroinitializer, align 8
|
||||||
|
|
||||||
// CHECK-LABEL: @"$S13generic_types1ACMn" = hidden constant
|
// CHECK-LABEL: @"$S13generic_types1ACMn" = hidden constant
|
||||||
|
// CHECK-SAME: i32 -2147221296,
|
||||||
|
// CHECK-SAME: @"$S13generic_typesMXM"
|
||||||
|
// <name>
|
||||||
// CHECK-SAME: @"$S13generic_types1ACMa"
|
// CHECK-SAME: @"$S13generic_types1ACMa"
|
||||||
|
// -- superclass
|
||||||
|
// CHECK-SAME: i32 0,
|
||||||
|
// -- negative size in words
|
||||||
|
// CHECK-SAME: i32 2,
|
||||||
|
// -- positive size in words
|
||||||
|
// CHECK-SAME: i32 17,
|
||||||
|
// -- num immediate members
|
||||||
|
// CHECK-SAME: i32 7,
|
||||||
|
// -- num fields
|
||||||
|
// CHECK-SAME: i32 1,
|
||||||
|
// -- field offset vector offset
|
||||||
|
// CHECK-SAME: i32 16,
|
||||||
|
// -- instantiation function
|
||||||
// CHECK-SAME: @"$S13generic_types1ACMi"
|
// CHECK-SAME: @"$S13generic_types1ACMi"
|
||||||
|
// -- instantiation cache
|
||||||
// CHECK-SAME: @"$S13generic_types1ACMI"
|
// CHECK-SAME: @"$S13generic_types1ACMI"
|
||||||
|
// -- num generic params
|
||||||
|
// CHECK-SAME: i32 1,
|
||||||
|
// -- num generic requirement
|
||||||
|
// CHECK-SAME: i32 0,
|
||||||
|
// -- num key arguments
|
||||||
|
// CHECK-SAME: i32 1,
|
||||||
|
// -- num extra arguments
|
||||||
|
// CHECK-SAME: i32 0,
|
||||||
|
// -- parameter descriptor 1
|
||||||
|
// CHECK-SAME: i8 -128,
|
||||||
|
|
||||||
// CHECK-LABEL: @"$S13generic_types1ACMP" = internal constant
|
// CHECK-LABEL: @"$S13generic_types1ACMP" = internal constant
|
||||||
// CHECK-SAME: void ([[A]]*)* @"$S13generic_types1ACfD",
|
// CHECK-SAME: void ([[A]]*)* @"$S13generic_types1ACfD",
|
||||||
// CHECK-SAME: i8** @"$SBoWV",
|
|
||||||
// CHECK-SAME: i64 0,
|
|
||||||
// CHECK-SAME: %swift.type* null,
|
|
||||||
// CHECK-native-SAME: %swift.opaque* null,
|
|
||||||
// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
|
|
||||||
// CHECK-SAME: %swift.opaque* null,
|
|
||||||
// CHECK-SAME: i64 {{1|2}},
|
|
||||||
// CHECK-SAME: i32 {{3|2}},
|
|
||||||
// CHECK-SAME: i32 0,
|
|
||||||
// CHECK-SAME: i32 24,
|
|
||||||
// CHECK-SAME: i16 7,
|
|
||||||
// CHECK-SAME: i16 0,
|
|
||||||
// CHECK-SAME: i32 152,
|
|
||||||
// CHECK-SAME: i32 16,
|
|
||||||
// -- nominal type descriptor
|
|
||||||
// CHECK-SAME: @"$S13generic_types1ACMn",
|
|
||||||
// -- ivar destroyer
|
// -- ivar destroyer
|
||||||
// CHECK-SAME: i8* null
|
// CHECK-SAME: i8* null,
|
||||||
|
// -- flags
|
||||||
|
// CHECK-SAME: i32 {{3|2}},
|
||||||
// CHECK-SAME: }
|
// CHECK-SAME: }
|
||||||
|
|
||||||
// CHECK-LABEL: @"$S13generic_types1BCMI" = internal global [16 x i8*] zeroinitializer, align 8
|
// CHECK-LABEL: @"$S13generic_types1BCMI" = internal global [16 x i8*] zeroinitializer, align 8
|
||||||
@@ -46,77 +59,29 @@
|
|||||||
|
|
||||||
// CHECK-LABEL: @"$S13generic_types1BCMP" = internal constant
|
// CHECK-LABEL: @"$S13generic_types1BCMP" = internal constant
|
||||||
// CHECK-SAME: void ([[B]]*)* @"$S13generic_types1BCfD",
|
// CHECK-SAME: void ([[B]]*)* @"$S13generic_types1BCfD",
|
||||||
// CHECK-SAME: i8** @"$SBoWV",
|
|
||||||
// CHECK-SAME: i64 0,
|
|
||||||
// CHECK-SAME: %swift.type* null,
|
|
||||||
// CHECK-native-SAME: %swift.opaque* null,
|
|
||||||
// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
|
|
||||||
// CHECK-SAME: %swift.opaque* null,
|
|
||||||
// CHECK-SAME: i64 {{1|2}},
|
|
||||||
// CHECK-SAME: i32 {{3|2}},
|
|
||||||
// CHECK-SAME: i32 0,
|
|
||||||
// CHECK-SAME: i32 24,
|
|
||||||
// CHECK-SAME: i16 7,
|
|
||||||
// CHECK-SAME: i16 0,
|
|
||||||
// CHECK-SAME: i32 144,
|
|
||||||
// CHECK-SAME: i32 16,
|
|
||||||
// -- nominal type descriptor
|
|
||||||
// CHECK-SAME: @"$S13generic_types1BCMn",
|
|
||||||
// -- ivar destroyer
|
// -- ivar destroyer
|
||||||
// CHECK-SAME: i8* null
|
// CHECK-SAME: i8* null
|
||||||
|
// CHECK-SAME: i32 {{3|2}},
|
||||||
// CHECK-SAME: }
|
// CHECK-SAME: }
|
||||||
|
|
||||||
// CHECK-LABEL: @"$S13generic_types1CCMP" = internal constant
|
// CHECK-LABEL: @"$S13generic_types1CCMP" = internal constant
|
||||||
// CHECK-SAME: void ([[C]]*)* @"$S13generic_types1CCfD",
|
// CHECK-SAME: void ([[C]]*)* @"$S13generic_types1CCfD",
|
||||||
// CHECK-SAME: i8** @"$SBoWV",
|
|
||||||
// CHECK-SAME: i64 0,
|
|
||||||
// CHECK-SAME: %swift.type* null,
|
|
||||||
// CHECK-native-SAME: %swift.opaque* null,
|
|
||||||
// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
|
|
||||||
// CHECK-SAME: %swift.opaque* null,
|
|
||||||
// CHECK-SAME: i64 {{1|2}},
|
|
||||||
// CHECK-SAME: i32 {{3|2}},
|
|
||||||
// CHECK-SAME: i32 0,
|
|
||||||
// CHECK-SAME: i32 24,
|
|
||||||
// CHECK-SAME: i16 7,
|
|
||||||
// CHECK-SAME: i16 0,
|
|
||||||
// CHECK-SAME: i32 160,
|
|
||||||
// CHECK-SAME: i32 16,
|
|
||||||
// -- nominal type descriptor
|
|
||||||
// CHECK-SAME: @"$S13generic_types1CCMn",
|
|
||||||
// -- ivar destroyer
|
// -- ivar destroyer
|
||||||
// CHECK-SAME: i8* null
|
// CHECK-SAME: i8* null
|
||||||
|
// CHECK-SAME: i32 {{3|2}},
|
||||||
// CHECK-SAME: }
|
// CHECK-SAME: }
|
||||||
|
|
||||||
// CHECK-LABEL: @"$S13generic_types1DCMP" = internal constant
|
// CHECK-LABEL: @"$S13generic_types1DCMP" = internal constant
|
||||||
// CHECK-SAME: void ([[D]]*)* @"$S13generic_types1DCfD",
|
// CHECK-SAME: void ([[D]]*)* @"$S13generic_types1DCfD",
|
||||||
// CHECK-SAME: i8** @"$SBoWV",
|
|
||||||
// CHECK-SAME: i64 0,
|
|
||||||
// CHECK-SAME: %swift.type* null,
|
|
||||||
// CHECK-native-SAME: %swift.opaque* null,
|
|
||||||
// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
|
|
||||||
// CHECK-SAME: %swift.opaque* null,
|
|
||||||
// CHECK-SAME: i64 {{1|2}},
|
|
||||||
// CHECK-SAME: i32 {{3|2}},
|
|
||||||
// CHECK-SAME: i32 0,
|
|
||||||
// CHECK-SAME: i32 24,
|
|
||||||
// CHECK-SAME: i16 7,
|
|
||||||
// CHECK-SAME: i16 0,
|
|
||||||
// CHECK-SAME: i32 160,
|
|
||||||
// CHECK-SAME: i32 16,
|
|
||||||
// -- nominal type descriptor
|
|
||||||
// CHECK-SAME: @"$S13generic_types1DCMn",
|
|
||||||
// -- ivar destroyer
|
// -- ivar destroyer
|
||||||
// CHECK-SAME: i8* null
|
// CHECK-SAME: i8* null
|
||||||
|
// CHECK-SAME: i32 {{3|2}},
|
||||||
// CHECK-SAME: }
|
// CHECK-SAME: }
|
||||||
|
|
||||||
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S13generic_types1ACMi"(%swift.type_descriptor*, i8**) {{.*}} {
|
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S13generic_types1ACMi"(%swift.type_descriptor*, i8**) {{.*}} {
|
||||||
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
|
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
|
||||||
// CHECK: %T = load %swift.type*, %swift.type** [[T0]],
|
// CHECK: %T = load %swift.type*, %swift.type** [[T0]],
|
||||||
// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}}* @"$S13generic_types1ACMP" to i8**), i64 96, i64 16, i8** %1, %objc_class* null, i64 7)
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8** bitcast ({{.*}}* @"$S13generic_types1ACMP" to i8**))
|
||||||
// CHECK-objc: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$__TtCs12_SwiftObject"
|
|
||||||
// CHECK-objc: [[SUPER:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T0]])
|
|
||||||
// CHECK-objc: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}}* @"$S13generic_types1ACMP" to i8**), i64 280, i64 200, i8** %1, %objc_class* [[SUPER]], i64 7)
|
|
||||||
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
||||||
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i64 10
|
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i64 10
|
||||||
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
|
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
|
||||||
@@ -127,10 +92,7 @@
|
|||||||
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S13generic_types1BCMi"(%swift.type_descriptor*, i8**) {{.*}} {
|
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S13generic_types1BCMi"(%swift.type_descriptor*, i8**) {{.*}} {
|
||||||
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
|
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
|
||||||
// CHECK: %T = load %swift.type*, %swift.type** [[T0]],
|
// CHECK: %T = load %swift.type*, %swift.type** [[T0]],
|
||||||
// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}}* @"$S13generic_types1BCMP" to i8**), i64 96, i64 16, i8** %1, %objc_class* null, i64 6)
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8** bitcast ({{.*}}* @"$S13generic_types1BCMP" to i8**))
|
||||||
// CHECK-objc: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$__TtCs12_SwiftObject"
|
|
||||||
// CHECK-objc: [[SUPER:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T0]])
|
|
||||||
// CHECK-objc: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}}* @"$S13generic_types1BCMP" to i8**), i64 280, i64 200, i8** %1, %objc_class* [[SUPER]], i64 6)
|
|
||||||
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
||||||
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i64 10
|
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i64 10
|
||||||
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
|
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ public class Concrete : Derived<Int> {
|
|||||||
//// instantiation time.
|
//// instantiation time.
|
||||||
|
|
||||||
// CHECK-LABEL: @"$S14generic_vtable7DerivedCMP" = internal constant <{{.*}}> <{
|
// CHECK-LABEL: @"$S14generic_vtable7DerivedCMP" = internal constant <{{.*}}> <{
|
||||||
// -- nominal type descriptor
|
|
||||||
// CHECK-SAME: @"$S14generic_vtable7DerivedCMn",
|
|
||||||
// -- ivar destroyer
|
// -- ivar destroyer
|
||||||
// CHECK-SAME: i8* null
|
// CHECK-SAME: i8* null
|
||||||
// --
|
// --
|
||||||
@@ -105,7 +103,7 @@ public class Concrete : Derived<Int> {
|
|||||||
// - 2 immediate members:
|
// - 2 immediate members:
|
||||||
// - type metadata for generic parameter T,
|
// - type metadata for generic parameter T,
|
||||||
// - and vtable entry for 'm3()'
|
// - and vtable entry for 'm3()'
|
||||||
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}} @"$S14generic_vtable7DerivedCMP" to i8**), i64 {{[0-9]+}}, i64 {{[0-9]+}}, i8** %1, {{.*}}, i64 2)
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8** bitcast ({{.*}} @"$S14generic_vtable7DerivedCMP" to i8**))
|
||||||
|
|
||||||
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
|
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ bb0(%0 : $ChildToResilientParent):
|
|||||||
// ChildToResilientParent is in our resilience domain - can load the superclass's metadata directly.
|
// ChildToResilientParent is in our resilience domain - can load the superclass's metadata directly.
|
||||||
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S5super22ChildToResilientParentC6methodyyF"(%T5super22ChildToResilientParentC* swiftself)
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S5super22ChildToResilientParentC6methodyyF"(%T5super22ChildToResilientParentC* swiftself)
|
||||||
// CHECK: [[SUPER_METADATA:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
|
// CHECK: [[SUPER_METADATA:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
|
||||||
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
|
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS:{.*}]], {{.*}}* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
|
||||||
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{20|40}}
|
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{20|40}}
|
||||||
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
|
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
|
||||||
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
|
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
|
||||||
@@ -76,7 +76,7 @@ bb0(%0 : $@thick ChildToResilientParent.Type):
|
|||||||
// ChildToResilientParent is in our resilience domain - can load the superclass's metadata directly.
|
// ChildToResilientParent is in our resilience domain - can load the superclass's metadata directly.
|
||||||
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S5super22ChildToResilientParentC11classMethodyyFZ"(%swift.type* swiftself)
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S5super22ChildToResilientParentC11classMethodyyFZ"(%swift.type* swiftself)
|
||||||
// CHECK: [[SUPER_METADATA:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
|
// CHECK: [[SUPER_METADATA:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
|
||||||
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
|
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
|
||||||
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{24|48}}
|
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{24|48}}
|
||||||
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
|
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
|
||||||
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
|
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
|
||||||
@@ -151,7 +151,7 @@ bb0(%0 : $ResilientOutsideChild):
|
|||||||
// CHECK: [[OPAQUE_METADATA:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
|
// CHECK: [[OPAQUE_METADATA:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
|
||||||
// CHECK: [[SUPER_METADATA_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[OPAQUE_METADATA]], i32 1
|
// CHECK: [[SUPER_METADATA_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[OPAQUE_METADATA]], i32 1
|
||||||
// CHECK: [[SUPER_METADATA:%.*]] = load %swift.type*, %swift.type** [[SUPER_METADATA_PTR]]
|
// CHECK: [[SUPER_METADATA:%.*]] = load %swift.type*, %swift.type** [[SUPER_METADATA_PTR]]
|
||||||
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
|
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
|
||||||
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{20|40}}
|
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{20|40}}
|
||||||
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
|
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
|
||||||
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
|
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
|
||||||
@@ -177,7 +177,7 @@ bb0(%0 : $@thick ResilientOutsideChild.Type):
|
|||||||
// CHECK: [[OPAQUE_METADATA:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
|
// CHECK: [[OPAQUE_METADATA:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
|
||||||
// CHECK: [[SUPER_METADATA_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[OPAQUE_METADATA]], i32 1
|
// CHECK: [[SUPER_METADATA_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[OPAQUE_METADATA]], i32 1
|
||||||
// CHECK: [[SUPER_METADATA:%.*]] = load %swift.type*, %swift.type** [[SUPER_METADATA_PTR]]
|
// CHECK: [[SUPER_METADATA:%.*]] = load %swift.type*, %swift.type** [[SUPER_METADATA_PTR]]
|
||||||
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
|
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
|
||||||
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{24|48}}
|
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{24|48}}
|
||||||
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
|
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
|
||||||
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
|
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
|
||||||
|
|||||||
@@ -80,8 +80,7 @@ static SWIFT_CC(swift) void destroyTestObject(SWIFT_CONTEXT HeapObject *_object)
|
|||||||
|
|
||||||
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
||||||
{ { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
{ { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
||||||
{ { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
|
{ { nullptr }, ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
||||||
ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create an object that, when deallocated, stores the given value to
|
/// Create an object that, when deallocated, stores the given value to
|
||||||
|
|||||||
@@ -98,8 +98,7 @@ static SWIFT_CC(swift) void deinitTestObject(SWIFT_CONTEXT HeapObject *_object)
|
|||||||
|
|
||||||
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
||||||
{ { &deinitTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
{ { &deinitTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
||||||
{ { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
|
{ { nullptr }, ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
||||||
ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create an object that, when deinited, stores the given value to
|
/// Create an object that, when deinited, stores the given value to
|
||||||
|
|||||||
@@ -252,8 +252,7 @@ TEST(Concurrent, ConcurrentMap) {
|
|||||||
|
|
||||||
FullMetadata<ClassMetadata> MetadataTest2 = {
|
FullMetadata<ClassMetadata> MetadataTest2 = {
|
||||||
{ { nullptr }, { &VALUE_WITNESS_SYM(Bo) } },
|
{ { nullptr }, { &VALUE_WITNESS_SYM(Bo) } },
|
||||||
{ { { MetadataKind::Class } }, nullptr, /*rodata*/ 1,
|
{ { nullptr }, ClassFlags(), 0, 0, 0, 0, 0, 0 }
|
||||||
ClassFlags(), 0, 0, 0, 0, 0, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(MetadataTest, getMetatypeMetadata) {
|
TEST(MetadataTest, getMetatypeMetadata) {
|
||||||
|
|||||||
@@ -31,8 +31,7 @@ static SWIFT_CC(swift) void destroyTestObject(SWIFT_CONTEXT HeapObject *_object)
|
|||||||
|
|
||||||
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
|
||||||
{ { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
{ { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
|
||||||
{ { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
|
{ { nullptr }, ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
||||||
ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create an object that, when deallocated, stores the given value to
|
/// Create an object that, when deallocated, stores the given value to
|
||||||
|
|||||||
Reference in New Issue
Block a user