Skip to content

Commit 95663e4

Browse files
authored
Merge pull request #11399 from slavapestov/struct-class-layout-common-logic
Refactor some duplication in class and struct layout
2 parents 8074124 + 2f65905 commit 95663e4

17 files changed

+265
-328
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3084,11 +3084,6 @@ void swift_initStructMetadata_UniversalStrategy(size_t numFields,
30843084
size_t *fieldOffsets,
30853085
ValueWitnessTable *vwtable);
30863086

3087-
struct ClassFieldLayout {
3088-
size_t Size;
3089-
size_t AlignMask;
3090-
};
3091-
30923087
/// Initialize the field offset vector for a dependent-layout class, using the
30933088
/// "Universal" layout strategy.
30943089
///
@@ -3099,7 +3094,7 @@ SWIFT_RUNTIME_EXPORT
30993094
ClassMetadata *
31003095
swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
31013096
size_t numFields,
3102-
const ClassFieldLayout *fieldLayouts,
3097+
const TypeLayout * const *fieldTypes,
31033098
size_t *fieldOffsets);
31043099

31053100
/// \brief Fetch a uniqued metadata for a metatype type.

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,13 +813,13 @@ FUNCTION(GetExistentialMetadata,
813813
// struct FieldInfo { size_t Size; size_t AlignMask; };
814814
// Metadata *swift_initClassMetadata_UniversalStrategy(Metadata *self,
815815
// size_t numFields,
816-
// const FieldInfo *fields,
816+
// TypeLayout * const *fieldTypes,
817817
// size_t *fieldOffsets);
818818
FUNCTION(InitClassMetadataUniversal,
819819
swift_initClassMetadata_UniversalStrategy, DefaultCC,
820820
RETURNS(TypeMetadataPtrTy),
821821
ARGS(TypeMetadataPtrTy, SizeTy,
822-
SizeTy->getPointerTo(),
822+
Int8PtrPtrTy->getPointerTo(),
823823
SizeTy->getPointerTo()),
824824
ATTRS(NoUnwind))
825825

lib/IRGen/FixedTypeInfo.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,6 @@ class FixedTypeInfo : public TypeInfo {
8686
void initializeWithTake(IRGenFunction &IGF, Address destAddr,
8787
Address srcAddr, SILType T) const override;
8888

89-
std::pair<llvm::Value*, llvm::Value*>
90-
getSizeAndAlignmentMask(IRGenFunction &IGF, SILType T) const override;
91-
std::tuple<llvm::Value*,llvm::Value*,llvm::Value*>
92-
getSizeAndAlignmentMaskAndStride(IRGenFunction &IGF, SILType T) const override;
9389
llvm::Value *getSize(IRGenFunction &IGF, SILType T) const override;
9490
llvm::Value *getAlignmentMask(IRGenFunction &IGF, SILType T) const override;
9591
llvm::Value *getStride(IRGenFunction &IGF, SILType T) const override;

lib/IRGen/GenMeta.cpp

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,10 +1831,8 @@ namespace {
18311831
return visit(singletonFieldTy.getSwiftRValueType());
18321832

18331833
// If the type is fixed-layout, emit a copy of its layout.
1834-
if (auto fixed = dyn_cast<FixedTypeInfo>(&ti)) {
1835-
1834+
if (auto fixed = dyn_cast<FixedTypeInfo>(&ti))
18361835
return IGF.IGM.emitFixedTypeLayout(t, *fixed);
1837-
}
18381836

18391837
return emitFromTypeMetadata(t);
18401838
}
@@ -3065,13 +3063,15 @@ namespace {
30653063
};
30663064
} // end anonymous namespace
30673065

3068-
// Classes
3069-
3070-
static llvm::Value *emitInitializeFieldOffsetVector(IRGenFunction &IGF,
3071-
ClassDecl *target,
3072-
llvm::Value *metadata) {
3066+
llvm::Value *
3067+
irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
3068+
SILType T,
3069+
llvm::Value *metadata,
3070+
llvm::Value *vwtable) {
3071+
auto *target = T.getNominalOrBoundGenericNominal();
30733072
llvm::Value *fieldVector
3074-
= emitAddressOfFieldOffsetVector(IGF, metadata, target).getAddress();
3073+
= emitAddressOfFieldOffsetVector(IGF, metadata, target)
3074+
.getAddress();
30753075

30763076
// Collect the stored properties of the type.
30773077
llvm::SmallVector<VarDecl*, 4> storedProperties;
@@ -3081,53 +3081,47 @@ static llvm::Value *emitInitializeFieldOffsetVector(IRGenFunction &IGF,
30813081

30823082
// Fill out an array with the field type metadata records.
30833083
Address fields = IGF.createAlloca(
3084-
llvm::ArrayType::get(IGF.IGM.SizeTy,
3085-
storedProperties.size() * 2),
3084+
llvm::ArrayType::get(IGF.IGM.Int8PtrPtrTy,
3085+
storedProperties.size()),
30863086
IGF.IGM.getPointerAlignment(), "classFields");
30873087
IGF.Builder.CreateLifetimeStart(fields,
3088-
IGF.IGM.getPointerSize() * storedProperties.size() * 2);
3089-
3090-
Address firstField;
3088+
IGF.IGM.getPointerSize() * storedProperties.size());
3089+
fields = IGF.Builder.CreateStructGEP(fields, 0, Size(0));
3090+
30913091
unsigned index = 0;
30923092
for (auto prop : storedProperties) {
3093-
auto propFormalTy = target->mapTypeIntoContext(prop->getInterfaceType())
3094-
->getCanonicalType();
3095-
SILType propLoweredTy = IGF.IGM.getLoweredType(propFormalTy);
3096-
auto &propTI = IGF.getTypeInfo(propLoweredTy);
3097-
auto sizeAndAlignMask
3098-
= propTI.getSizeAndAlignmentMask(IGF, propLoweredTy);
3099-
3100-
llvm::Value *size = sizeAndAlignMask.first;
3101-
Address sizeAddr =
3102-
IGF.Builder.CreateStructGEP(fields, index, IGF.IGM.getPointerSize());
3103-
IGF.Builder.CreateStore(size, sizeAddr);
3104-
if (index == 0) firstField = sizeAddr;
3105-
3106-
llvm::Value *alignMask = sizeAndAlignMask.second;
3107-
Address alignMaskAddr =
3108-
IGF.Builder.CreateStructGEP(fields, index + 1,
3109-
IGF.IGM.getPointerSize());
3110-
IGF.Builder.CreateStore(alignMask, alignMaskAddr);
3111-
3112-
index += 2;
3113-
}
3114-
3115-
if (storedProperties.empty()) {
3116-
firstField = IGF.Builder.CreateStructGEP(fields, 0, Size(0));
3093+
auto propTy = T.getFieldType(prop, IGF.getSILModule());
3094+
llvm::Value *metadata = IGF.emitTypeLayoutRef(propTy);
3095+
Address field = IGF.Builder.CreateConstArrayGEP(fields, index,
3096+
IGF.IGM.getPointerSize());
3097+
IGF.Builder.CreateStore(metadata, field);
3098+
++index;
31173099
}
31183100

31193101
// Ask the runtime to lay out the class. This can relocate it if it
31203102
// wasn't allocated with swift_allocateGenericClassMetadata.
31213103
auto numFields = IGF.IGM.getSize(Size(storedProperties.size()));
3122-
metadata = IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
3123-
{metadata, numFields,
3124-
firstField.getAddress(), fieldVector});
3104+
3105+
if (isa<ClassDecl>(target)) {
3106+
assert(vwtable == nullptr);
3107+
metadata = IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
3108+
{metadata, numFields,
3109+
fields.getAddress(), fieldVector});
3110+
} else {
3111+
assert(isa<StructDecl>(target));
3112+
IGF.Builder.CreateCall(IGF.IGM.getInitStructMetadataUniversalFn(),
3113+
{numFields, fields.getAddress(),
3114+
fieldVector, vwtable});
3115+
}
3116+
31253117
IGF.Builder.CreateLifetimeEnd(fields,
3126-
IGF.IGM.getPointerSize() * storedProperties.size() * 2);
3118+
IGF.IGM.getPointerSize() * storedProperties.size());
31273119

31283120
return metadata;
31293121
}
31303122

3123+
// Classes
3124+
31313125
namespace {
31323126
/// An adapter for laying out class metadata.
31333127
template <class Impl>
@@ -3469,7 +3463,11 @@ namespace {
34693463
//
34703464
// emitInitializeFieldOffsetVector will do everything in the full case.
34713465
if (doesClassMetadataRequireDynamicInitialization(IGF.IGM, Target)) {
3472-
metadata = emitInitializeFieldOffsetVector(IGF, Target, metadata);
3466+
auto classTy = Target->getDeclaredTypeInContext()->getCanonicalType();
3467+
auto loweredClassTy = IGF.IGM.getLoweredType(classTy);
3468+
metadata = emitInitializeFieldOffsetVector(IGF, loweredClassTy,
3469+
metadata,
3470+
/*vwtable=*/nullptr);
34733471

34743472
// TODO: do something intermediate when e.g. all we needed to do was
34753473
// set parent metadata pointers.

lib/IRGen/GenMeta.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,14 @@ namespace irgen {
252252
NominalTypeDecl *type,
253253
llvm::Function *fn,
254254
ArrayRef<FieldTypeInfo> fieldTypes);
255-
255+
256+
/// \brief Initialize the field offset vector within the given class or struct
257+
/// metadata.
258+
llvm::Value *emitInitializeFieldOffsetVector(IRGenFunction &IGF,
259+
SILType T,
260+
llvm::Value *metadata,
261+
llvm::Value *vwtable);
262+
256263
/// Adjustment indices for the address points of various metadata.
257264
/// Size is in words.
258265
namespace MetadataAdjustmentIndex {

lib/IRGen/GenStruct.cpp

Lines changed: 10 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "NonFixedTypeInfo.h"
4141
#include "ResilientTypeInfo.h"
4242
#include "StructMetadataVisitor.h"
43+
#include "MetadataLayout.h"
4344

4445
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
4546

@@ -366,44 +367,6 @@ namespace {
366367
llvm_unreachable("non-fixed field in fixed struct?");
367368
}
368369
};
369-
370-
struct GetStartOfFieldOffsets
371-
: StructMetadataScanner<GetStartOfFieldOffsets>
372-
{
373-
GetStartOfFieldOffsets(IRGenModule &IGM, StructDecl *target)
374-
: StructMetadataScanner(IGM, target) {}
375-
376-
Size StartOfFieldOffsets = Size::invalid();
377-
378-
void noteAddressPoint() {
379-
assert(StartOfFieldOffsets == Size::invalid()
380-
&& "found field offsets before address point?");
381-
NextOffset = Size(0);
382-
}
383-
void noteStartOfFieldOffsets() { StartOfFieldOffsets = NextOffset; }
384-
};
385-
386-
/// Find the beginning of the field offset vector in a struct's metadata.
387-
static Address
388-
emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
389-
StructDecl *S,
390-
llvm::Value *metadata) {
391-
// Find where the field offsets begin.
392-
GetStartOfFieldOffsets scanner(IGF.IGM, S);
393-
scanner.layout();
394-
assert(scanner.StartOfFieldOffsets != Size::invalid()
395-
&& "did not find start of field offsets?!");
396-
397-
Size StartOfFieldOffsets = scanner.StartOfFieldOffsets;
398-
399-
// Find that offset into the metadata.
400-
llvm::Value *fieldVector
401-
= IGF.Builder.CreateBitCast(metadata, IGF.IGM.SizeTy->getPointerTo());
402-
return IGF.Builder.CreateConstArrayGEP(
403-
Address(fieldVector, IGF.IGM.getPointerAlignment()),
404-
StartOfFieldOffsets / IGF.IGM.getPointerSize(),
405-
StartOfFieldOffsets);
406-
}
407370

408371
/// Accessor for the non-fixed offsets of a struct type.
409372
class StructNonFixedOffsets : public NonFixedOffsetsImpl {
@@ -418,9 +381,8 @@ namespace {
418381

419382
// Get the field offset vector from the struct metadata.
420383
llvm::Value *metadata = IGF.emitTypeMetadataRefForLayout(TheStruct);
421-
Address fieldVector = emitAddressOfFieldOffsetVector(IGF,
422-
TheStruct.getStructOrBoundGenericStruct(),
423-
metadata);
384+
Address fieldVector = emitAddressOfFieldOffsetVector(IGF, metadata,
385+
TheStruct.getStructOrBoundGenericStruct());
424386

425387
// Grab the indexed offset.
426388
fieldVector = IGF.Builder.CreateConstArrayGEP(fieldVector, index,
@@ -430,12 +392,13 @@ namespace {
430392

431393
MemberAccessStrategy getFieldAccessStrategy(IRGenModule &IGM,
432394
unsigned nonFixedIndex) {
433-
GetStartOfFieldOffsets scanner(IGM,
434-
TheStruct.getStructOrBoundGenericStruct());
435-
scanner.layout();
395+
auto start =
396+
IGM.getMetadataLayout(TheStruct.getStructOrBoundGenericStruct())
397+
.getFieldOffsetVectorOffset();
436398

437-
Size indirectOffset =
438-
scanner.StartOfFieldOffsets + IGM.getPointerSize() * nonFixedIndex;
399+
// FIXME: Handle resilience
400+
auto indirectOffset = start.getStatic() +
401+
(IGM.getPointerSize() * nonFixedIndex);
439402

440403
return MemberAccessStrategy::getIndirectFixed(indirectOffset,
441404
MemberAccessStrategy::OffsetKind::Bytes_Word);
@@ -477,44 +440,7 @@ namespace {
477440
llvm::Value *metadata,
478441
llvm::Value *vwtable,
479442
SILType T) const override {
480-
// Get the field offset vector.
481-
llvm::Value *fieldVector = emitAddressOfFieldOffsetVector(IGF,
482-
T.getStructOrBoundGenericStruct(),
483-
metadata).getAddress();
484-
485-
// Collect the stored properties of the type.
486-
llvm::SmallVector<VarDecl*, 4> storedProperties;
487-
for (auto prop : T.getStructOrBoundGenericStruct()
488-
->getStoredProperties()) {
489-
storedProperties.push_back(prop);
490-
}
491-
// Fill out an array with the field type layout records.
492-
Address fields = IGF.createAlloca(
493-
llvm::ArrayType::get(IGF.IGM.Int8PtrPtrTy,
494-
storedProperties.size()),
495-
IGF.IGM.getPointerAlignment(), "structFields");
496-
IGF.Builder.CreateLifetimeStart(fields,
497-
IGF.IGM.getPointerSize() * storedProperties.size());
498-
499-
fields = IGF.Builder.CreateStructGEP(fields, 0, Size(0));
500-
unsigned index = 0;
501-
for (auto prop : storedProperties) {
502-
auto propTy = T.getFieldType(prop, IGF.getSILModule());
503-
llvm::Value *metadata = IGF.emitTypeLayoutRef(propTy);
504-
Address field = IGF.Builder.CreateConstArrayGEP(fields, index,
505-
IGF.IGM.getPointerSize());
506-
IGF.Builder.CreateStore(metadata, field);
507-
++index;
508-
}
509-
510-
// Ask the runtime to lay out the struct.
511-
auto numFields = llvm::ConstantInt::get(IGF.IGM.SizeTy,
512-
storedProperties.size());
513-
IGF.Builder.CreateCall(IGF.IGM.getInitStructMetadataUniversalFn(),
514-
{numFields, fields.getAddress(),
515-
fieldVector, vwtable});
516-
IGF.Builder.CreateLifetimeEnd(fields,
517-
IGF.IGM.getPointerSize() * storedProperties.size());
443+
emitInitializeFieldOffsetVector(IGF, T, metadata, vwtable);
518444
}
519445
};
520446

lib/IRGen/GenType.cpp

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -183,21 +183,6 @@ static llvm::Constant *asSizeConstant(IRGenModule &IGM, Size size) {
183183
return llvm::ConstantInt::get(IGM.SizeTy, size.getValue());
184184
}
185185

186-
/// Return the size and alignment of this type.
187-
std::pair<llvm::Value*,llvm::Value*>
188-
FixedTypeInfo::getSizeAndAlignmentMask(IRGenFunction &IGF,
189-
SILType T) const {
190-
return {FixedTypeInfo::getSize(IGF, T),
191-
FixedTypeInfo::getAlignmentMask(IGF, T)};
192-
}
193-
std::tuple<llvm::Value*,llvm::Value*,llvm::Value*>
194-
FixedTypeInfo::getSizeAndAlignmentMaskAndStride(IRGenFunction &IGF,
195-
SILType T) const {
196-
return std::make_tuple(FixedTypeInfo::getSize(IGF, T),
197-
FixedTypeInfo::getAlignmentMask(IGF, T),
198-
FixedTypeInfo::getStride(IGF, T));
199-
}
200-
201186
llvm::Value *FixedTypeInfo::getSize(IRGenFunction &IGF, SILType T) const {
202187
return FixedTypeInfo::getStaticSize(IGF.IGM);
203188
}
@@ -1753,6 +1738,11 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t,
17531738
|| structDecl->hasClangNode())
17541739
return SILType();
17551740

1741+
// A single-field struct with custom alignment has different layout from its
1742+
// field.
1743+
if (structDecl->getAttrs().hasAttribute<AlignmentAttr>())
1744+
return SILType();
1745+
17561746
// If there's only one stored property, we have the layout of its field.
17571747
auto allFields = structDecl->getStoredProperties();
17581748

0 commit comments

Comments
 (0)