IRGen: Record start of field offset vector in StructMetadataLayout

This commit is contained in:
Slava Pestov
2017-08-08 21:47:00 -07:00
parent f7152c0979
commit ea5a99a3f7
5 changed files with 56 additions and 67 deletions

View File

@@ -40,6 +40,7 @@
#include "NonFixedTypeInfo.h"
#include "ResilientTypeInfo.h"
#include "StructMetadataVisitor.h"
#include "MetadataLayout.h"
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
@@ -367,44 +368,6 @@ namespace {
}
};
struct GetStartOfFieldOffsets
: StructMetadataScanner<GetStartOfFieldOffsets>
{
GetStartOfFieldOffsets(IRGenModule &IGM, StructDecl *target)
: StructMetadataScanner(IGM, target) {}
Size StartOfFieldOffsets = Size::invalid();
void noteAddressPoint() {
assert(StartOfFieldOffsets == Size::invalid()
&& "found field offsets before address point?");
NextOffset = Size(0);
}
void noteStartOfFieldOffsets() { StartOfFieldOffsets = NextOffset; }
};
/// Find the beginning of the field offset vector in a struct's metadata.
static Address
emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
StructDecl *S,
llvm::Value *metadata) {
// Find where the field offsets begin.
GetStartOfFieldOffsets scanner(IGF.IGM, S);
scanner.layout();
assert(scanner.StartOfFieldOffsets != Size::invalid()
&& "did not find start of field offsets?!");
Size StartOfFieldOffsets = scanner.StartOfFieldOffsets;
// Find that offset into the metadata.
llvm::Value *fieldVector
= IGF.Builder.CreateBitCast(metadata, IGF.IGM.SizeTy->getPointerTo());
return IGF.Builder.CreateConstArrayGEP(
Address(fieldVector, IGF.IGM.getPointerAlignment()),
StartOfFieldOffsets / IGF.IGM.getPointerSize(),
StartOfFieldOffsets);
}
/// Accessor for the non-fixed offsets of a struct type.
class StructNonFixedOffsets : public NonFixedOffsetsImpl {
SILType TheStruct;
@@ -418,9 +381,8 @@ namespace {
// Get the field offset vector from the struct metadata.
llvm::Value *metadata = IGF.emitTypeMetadataRefForLayout(TheStruct);
Address fieldVector = emitAddressOfFieldOffsetVector(IGF,
TheStruct.getStructOrBoundGenericStruct(),
metadata);
Address fieldVector = emitAddressOfFieldOffsetVector(IGF, metadata,
TheStruct.getStructOrBoundGenericStruct());
// Grab the indexed offset.
fieldVector = IGF.Builder.CreateConstArrayGEP(fieldVector, index,
@@ -430,12 +392,13 @@ namespace {
MemberAccessStrategy getFieldAccessStrategy(IRGenModule &IGM,
unsigned nonFixedIndex) {
GetStartOfFieldOffsets scanner(IGM,
TheStruct.getStructOrBoundGenericStruct());
scanner.layout();
auto start =
IGM.getMetadataLayout(TheStruct.getStructOrBoundGenericStruct())
.getFieldOffsetVectorOffset();
Size indirectOffset =
scanner.StartOfFieldOffsets + IGM.getPointerSize() * nonFixedIndex;
// FIXME: Handle resilience
auto indirectOffset = start.getStatic() +
(IGM.getPointerSize() * nonFixedIndex);
return MemberAccessStrategy::getIndirectFixed(indirectOffset,
MemberAccessStrategy::OffsetKind::Bytes_Word);
@@ -478,9 +441,9 @@ namespace {
llvm::Value *vwtable,
SILType T) const override {
// Get the field offset vector.
llvm::Value *fieldVector = emitAddressOfFieldOffsetVector(IGF,
T.getStructOrBoundGenericStruct(),
metadata).getAddress();
llvm::Value *fieldVector = emitAddressOfFieldOffsetVector(IGF, metadata,
T.getStructOrBoundGenericStruct())
.getAddress();
// Collect the stored properties of the type.
llvm::SmallVector<VarDecl*, 4> storedProperties;

View File

@@ -186,6 +186,25 @@ llvm::Value *irgen::emitArgumentWitnessTableRef(IRGenFunction &IGF,
IGF.IGM.WitnessTablePtrTy);
}
Address irgen::emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
llvm::Value *metadata,
NominalTypeDecl *decl) {
auto &layout = IGF.IGM.getMetadataLayout(decl);
auto offset = [&]() {
if (isa<ClassDecl>(decl)) {
return cast<ClassMetadataLayout>(layout)
.getFieldOffsetVectorOffset(IGF);
} else {
assert(isa<StructDecl>(decl));
return cast<StructMetadataLayout>(layout)
.getFieldOffsetVectorOffset();
}
}();
return IGF.emitAddressAtOffset(metadata, offset, IGF.IGM.SizeTy,
IGF.IGM.getPointerAlignment());
}
/********************************** CLASSES ***********************************/
ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
@@ -295,16 +314,6 @@ Address irgen::emitAddressOfClassFieldOffset(IRGenFunction &IGF,
return slot;
}
Address irgen::emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
llvm::Value *metadata,
ClassDecl *theClass) {
auto offset =
IGF.IGM.getMetadataLayout(theClass).getFieldOffsetVectorOffset(IGF);
return IGF.emitAddressAtOffset(metadata, offset, IGF.IGM.SizeTy,
IGF.IGM.getPointerAlignment());
}
/*********************************** ENUMS ************************************/
EnumMetadataLayout::EnumMetadataLayout(IRGenModule &IGM, EnumDecl *decl)
@@ -353,6 +362,11 @@ StructMetadataLayout::StructMetadataLayout(IRGenModule &IGM, StructDecl *decl)
super::noteStartOfGenericRequirements();
}
void noteStartOfFieldOffsets() {
Layout.FieldOffsetVector = getNextOffset();
super::noteStartOfFieldOffsets();
}
void addFieldOffset(VarDecl *field) {
Layout.FieldOffsets.try_emplace(field, getNextOffset());
super::addFieldOffset(field);
@@ -372,3 +386,9 @@ Size StructMetadataLayout::getStaticFieldOffset(VarDecl *field) const {
assert(stored.isStatic() && "resilient struct metadata layout unsupported!");
return stored.getStaticOffset();
}
Offset
StructMetadataLayout::getFieldOffsetVectorOffset() const {
assert(FieldOffsetVector.isStatic());
return Offset(FieldOffsetVector.getStaticOffset());
}

View File

@@ -204,6 +204,9 @@ public:
class StructMetadataLayout : public NominalMetadataLayout {
llvm::DenseMap<VarDecl*, StoredOffset> FieldOffsets;
/// The start of the field-offset vector.
StoredOffset FieldOffsetVector;
const StoredOffset &getStoredFieldOffset(VarDecl *field) const {
auto it = FieldOffsets.find(field);
assert(it != FieldOffsets.end());
@@ -224,6 +227,8 @@ public:
/// more arbitrary fashion.
Size getStaticFieldOffset(VarDecl *field) const;
Offset getFieldOffsetVectorOffset() const;
static bool classof(const MetadataLayout *layout) {
return layout->getKind() == Kind::Struct;
}
@@ -248,10 +253,11 @@ Size getClassFieldOffsetOffset(IRGenModule &IGM,
ClassDecl *theClass,
VarDecl *field);
/// Emit the address of the field-offset vector in the given class metadata.
/// Emit the address of the field-offset vector in the given class or struct
/// metadata.
Address emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
llvm::Value *metadata,
ClassDecl *theClass);
NominalTypeDecl *theDecl);
} // end namespace irgen
} // end namespace swift

View File

@@ -134,7 +134,7 @@ entry(%0 : $*ComplexDynamic<A, B>, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Ch
%a = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.a2
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i32 3
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -143,7 +143,7 @@ entry(%0 : $*ComplexDynamic<A, B>, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Ch
%b = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.b
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i32 3
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 3
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -153,7 +153,7 @@ entry(%0 : $*ComplexDynamic<A, B>, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Ch
%c = struct_element_addr %5 : $*SingleDynamic<B>, #SingleDynamic.x
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i32 3
// CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 4
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -214,7 +214,7 @@ entry(%0 : $*ComplexDynamic<A, B>, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Ch
// CHECK: store i8* [[VWTABLE_VAL]], i8** [[VWTABLE_SLOT_ADDR]], align 8
// Lay out fields.
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
// CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i32 3
// CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i64 3
// CHECK: [[T2:%.*]] = getelementptr inbounds i8**, i8*** [[TYPES:%.*]], i32 0
// CHECK: call void @swift_initStructMetadata_UniversalStrategy(i64 1, i8*** [[TYPES]], i64* [[T1]], i8** [[VWTABLE_ADDR]])
// CHECK: ret %swift.type* [[METADATA]]

View File

@@ -59,7 +59,7 @@ public func functionWithResilientTypes(_ r: Rectangle) {
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T016resilient_struct9RectangleVMa()
// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], i32 3
// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 3
// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %T16resilient_struct9RectangleV* %0 to i8*
@@ -116,7 +116,7 @@ public struct StructWithResilientStorage {
// CHECK-LABEL: define{{( protected)?}} swiftcc {{i32|i64}} @_T017struct_resilience26StructWithResilientStorageV1nSifg(%T17struct_resilience26StructWithResilientStorageV* {{.*}})
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T017struct_resilience26StructWithResilientStorageVMa()
// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], i32 3
// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 3
// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %T17struct_resilience26StructWithResilientStorageV* %0 to i8*