Skip to content

Commit 78822bc

Browse files
committed
[IRGen] Adjust element size of offset vector to 32-bit for structs
Type of elements contained by field offsets vector can be adjusted to 32-bit integers (from being pointer sized) to safe space in the binary since segment size is limited to 4 GB. Resolves: rdar://problem/36560486
1 parent 187ab0b commit 78822bc

File tree

10 files changed

+74
-24
lines changed

10 files changed

+74
-24
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,12 +1706,12 @@ struct TargetStructMetadata : public TargetValueMetadata<Runtime> {
17061706
// argument array.
17071707

17081708
/// Get a pointer to the field offset vector, if present, or null.
1709-
const StoredPointer *getFieldOffsets() const {
1709+
const uint32_t *getFieldOffsets() const {
17101710
auto offset = getDescription()->FieldOffsetVectorOffset;
17111711
if (offset == 0)
17121712
return nullptr;
17131713
auto asWords = reinterpret_cast<const void * const*>(this);
1714-
return reinterpret_cast<const StoredPointer *>(asWords + offset);
1714+
return reinterpret_cast<const uint32_t *>(asWords + offset);
17151715
}
17161716

17171717
static constexpr int32_t getGenericArgumentOffset() {
@@ -4212,7 +4212,7 @@ void swift_initStructMetadata(StructMetadata *self,
42124212
StructLayoutFlags flags,
42134213
size_t numFields,
42144214
const TypeLayout * const *fieldTypes,
4215-
size_t *fieldOffsets);
4215+
uint32_t *fieldOffsets);
42164216

42174217
/// Relocate the metadata for a class and copy fields from the given template.
42184218
/// The final size of the metadata is calculated at runtime from the size of

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -942,13 +942,13 @@ FUNCTION(InitClassMetadata,
942942
// StructLayoutFlags flags,
943943
// size_t numFields,
944944
// TypeLayout * const *fieldTypes,
945-
// size_t *fieldOffsets);
945+
// uint32_t *fieldOffsets);
946946
FUNCTION(InitStructMetadata,
947947
swift_initStructMetadata, C_CC,
948948
RETURNS(VoidTy),
949949
ARGS(TypeMetadataPtrTy, SizeTy, SizeTy,
950950
Int8PtrPtrTy->getPointerTo(0),
951-
SizeTy->getPointerTo()),
951+
Int32Ty->getPointerTo()),
952952
ATTRS(NoUnwind))
953953

954954
// void swift_initEnumMetadataSingleCase(Metadata *enumType,

lib/IRGen/ConstantBuilder.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class ConstantAggregateBuilderBase
106106
Size getNextOffsetFromGlobal() const {
107107
return Size(super::getNextOffsetFromGlobal().getQuantity());
108108
}
109-
109+
110110
void addAlignmentPadding(Alignment align) {
111111
auto misalignment = getNextOffsetFromGlobal() % IGM().getPointerAlignment();
112112
if (misalignment != Size(0))
@@ -119,10 +119,26 @@ class ConstantAggregateBuilderBase
119119
class ConstantArrayBuilder
120120
: public clang::CodeGen::ConstantArrayBuilderTemplateBase<
121121
ConstantInitBuilderTraits> {
122+
private:
123+
llvm::Type *EltTy;
124+
122125
public:
123-
template <class... As>
124-
ConstantArrayBuilder(As &&... args)
125-
: ConstantArrayBuilderTemplateBase(std::forward<As>(args)...) {}
126+
ConstantArrayBuilder(InitBuilder &builder,
127+
AggregateBuilderBase *parent,
128+
llvm::Type *eltTy)
129+
: ConstantArrayBuilderTemplateBase(builder, parent, eltTy), EltTy(eltTy) {}
130+
131+
void addAlignmentPadding(Alignment align) {
132+
auto misalignment = getNextOffsetFromGlobal() % align;
133+
if (misalignment == Size(0))
134+
return;
135+
136+
auto eltSize = IGM().DataLayout.getTypeStoreSize(EltTy);
137+
assert(misalignment.getValue() % eltSize == 0);
138+
139+
for (unsigned i = 0, n = misalignment.getValue() / eltSize; i != n; ++i)
140+
add(llvm::Constant::getNullValue(EltTy));
141+
}
126142
};
127143

128144
class ConstantStructBuilder

lib/IRGen/GenClass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ llvm::Value *IRGenFunction::emitByteOffsetGEP(llvm::Value *base,
461461
llvm::Value *offset,
462462
llvm::Type *objectType,
463463
const llvm::Twine &name) {
464-
assert(offset->getType() == IGM.SizeTy);
464+
assert(offset->getType() == IGM.SizeTy || offset->getType() == IGM.Int32Ty);
465465
auto addr = Builder.CreateBitCast(base, IGM.Int8PtrTy);
466466
addr = Builder.CreateInBoundsGEP(addr, offset);
467467
return Builder.CreateBitCast(addr, objectType->getPointerTo(), name);

lib/IRGen/GenMeta.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,10 +2629,14 @@ namespace {
26292629
B.add(offset);
26302630
} else {
26312631
asImpl().flagUnfilledFieldOffset();
2632-
B.addInt(IGM.IntPtrTy, 0);
2632+
B.addInt(IGM.Int32Ty, 0);
26332633
}
26342634
}
26352635

2636+
void noteEndOfFieldOffsets() {
2637+
B.addAlignmentPadding(super::IGM.getPointerAlignment());
2638+
}
2639+
26362640
void addGenericArgument(CanType type) {
26372641
B.addNullPointer(IGM.TypeMetadataPtrTy);
26382642
}
@@ -2727,7 +2731,7 @@ namespace {
27272731
/// Fill in a constant field offset vector if possible.
27282732
PartialPattern buildExtraDataPattern() {
27292733
ConstantInitBuilder builder(IGM);
2730-
auto init = builder.beginArray(IGM.SizeTy);
2734+
auto init = builder.beginArray(IGM.Int32Ty);
27312735

27322736
struct Scanner : StructMetadataScanner<Scanner> {
27332737
SILType Type;
@@ -2744,7 +2748,11 @@ namespace {
27442748
}
27452749
assert(IGM.isKnownEmpty(Type.getFieldType(field, IGM.getSILModule()),
27462750
ResilienceExpansion::Maximal));
2747-
B.addInt(IGM.SizeTy, 0);
2751+
B.addInt32(0);
2752+
}
2753+
2754+
void noteEndOfFieldOffsets() {
2755+
B.addAlignmentPadding(IGM.getPointerAlignment());
27482756
}
27492757
};
27502758
Scanner(IGM, Target, getLoweredType(), init).layout();

lib/IRGen/GenStruct.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,16 +158,16 @@ namespace {
158158
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
159159
return fieldInfo.projectAddress(IGF, addr, offsets);
160160
}
161-
162-
/// Return the constant offset of a field as a SizeTy, or nullptr if the
161+
162+
/// Return the constant offset of a field as a Int32Ty, or nullptr if the
163163
/// field is not at a fixed offset.
164164
llvm::Constant *getConstantFieldOffset(IRGenModule &IGM,
165165
VarDecl *field) const {
166166
auto &fieldInfo = getFieldInfo(field);
167167
if (fieldInfo.getKind() == ElementLayout::Kind::Fixed
168168
|| fieldInfo.getKind() == ElementLayout::Kind::Empty) {
169-
return llvm::ConstantInt::get(IGM.SizeTy,
170-
fieldInfo.getFixedByteOffset().getValue());
169+
return llvm::ConstantInt::get(
170+
IGM.Int32Ty, fieldInfo.getFixedByteOffset().getValue());
171171
}
172172
return nullptr;
173173
}

lib/IRGen/MetadataLayout.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,11 @@ Address irgen::emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
248248
}
249249
}();
250250

251-
return IGF.emitAddressAtOffset(metadata, offset, IGF.IGM.SizeTy,
251+
auto *elementSize = IGF.IGM.SizeTy;
252+
if (isa<StructDecl>(decl))
253+
elementSize = IGF.IGM.Int32Ty;
254+
255+
return IGF.emitAddressAtOffset(metadata, offset, elementSize,
252256
IGF.IGM.getPointerAlignment());
253257
}
254258

@@ -564,6 +568,10 @@ StructMetadataLayout::StructMetadataLayout(IRGenModule &IGM, StructDecl *decl)
564568
super::addFieldOffset(field);
565569
}
566570

571+
void noteEndOfFieldOffsets() {
572+
super::noteEndOfFieldOffsets();
573+
}
574+
567575
void layout() {
568576
super::layout();
569577
Layout.TheSize = getMetadataSize();

lib/IRGen/StructMetadataVisitor.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,15 @@ template <class Impl> class StructMetadataVisitor
5959
asImpl().noteStartOfFieldOffsets();
6060
for (VarDecl *prop : Target->getStoredProperties())
6161
asImpl().addFieldOffset(prop);
62+
63+
asImpl().noteEndOfFieldOffsets();
6264
}
6365

6466
// Note the start of the field offset vector.
6567
void noteStartOfFieldOffsets() {}
68+
69+
// Note the end of the field offset vector.
70+
void noteEndOfFieldOffsets() {}
6671
};
6772

6873
/// An "implementation" of StructMetadataVisitor that just scans through
@@ -81,17 +86,22 @@ class StructMetadataScanner : public StructMetadataVisitor<Impl> {
8186
void addMetadataFlags() { addPointer(); }
8287
void addValueWitnessTable() { addPointer(); }
8388
void addNominalTypeDescriptor() { addPointer(); }
84-
void addFieldOffset(VarDecl*) { addPointer(); }
89+
void addFieldOffset(VarDecl *) { addInt32(); }
8590
void addGenericArgument(CanType argument) { addPointer(); }
8691
void addGenericWitnessTable(CanType argument, ProtocolConformanceRef conf) {
8792
addPointer();
8893
}
8994
void noteStartOfTypeSpecificMembers() {}
9095

96+
void noteEndOfFieldOffsets() {
97+
NextOffset = NextOffset.roundUpToAlignment(super::IGM.getPointerAlignment());
98+
}
99+
91100
private:
92101
void addPointer() {
93102
NextOffset += super::IGM.getPointerSize();
94103
}
104+
void addInt32() { NextOffset += Size(4); }
95105
};
96106

97107
} // end namespace irgen

stdlib/public/core/KeyPath.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,8 +2404,16 @@ internal func _instantiateKeyPathBuffer(
24042404
// offset within the metadata object.
24052405
let metadataPtr = unsafeBitCast(base, to: UnsafeRawPointer.self)
24062406
let offsetOfOffset = patternBuffer.pop(UInt32.self)
2407-
let offset = UInt32(metadataPtr.load(fromByteOffset: Int(offsetOfOffset),
2408-
as: UInt.self))
2407+
2408+
let offset: UInt32
2409+
if (header.kind == .struct) {
2410+
offset = UInt32(metadataPtr.load(fromByteOffset: Int(offsetOfOffset),
2411+
as: UInt32.self))
2412+
} else {
2413+
offset = UInt32(metadataPtr.load(fromByteOffset: Int(offsetOfOffset),
2414+
as: UInt.self))
2415+
}
2416+
24092417
// Rewrite the header for a resolved offset.
24102418
var newHeader = header
24112419
newHeader.payload = RawKeyPathComponent.Header.outOfLineOffsetPayload

stdlib/public/runtime/Metadata.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,12 +1758,12 @@ static ValueWitnessTable *getMutableVWTableForInit(StructMetadata *self,
17581758
void swift::swift_initStructMetadata(StructMetadata *structType,
17591759
StructLayoutFlags layoutFlags,
17601760
size_t numFields,
1761-
const TypeLayout * const *fieldTypes,
1762-
size_t *fieldOffsets) {
1761+
const TypeLayout *const *fieldTypes,
1762+
uint32_t *fieldOffsets) {
17631763
auto layout = getInitialLayoutForValueType();
17641764
performBasicLayout(layout, fieldTypes, numFields,
17651765
[&](const TypeLayout *fieldType) { return fieldType; },
1766-
[&](size_t i, const TypeLayout *fieldType, size_t offset) {
1766+
[&](size_t i, const TypeLayout *fieldType, uint32_t offset) {
17671767
assignUnlessEqual(fieldOffsets[i], offset);
17681768
});
17691769

0 commit comments

Comments
 (0)