Skip to content

Commit e2d3f53

Browse files
committed
IRGen: Intialize single case enum extrainhabitant value witness in generated code
Older Swift runtimes miss this initialization in the swift_initEnumMetadataSingleCase runtime call. rdar://49786768
1 parent 9850150 commit e2d3f53

File tree

6 files changed

+53
-5
lines changed

6 files changed

+53
-5
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,18 @@ namespace {
630630
IGF.Builder.CreateCall(
631631
IGF.IGM.getInitEnumMetadataSingleCaseFn(),
632632
{metadata, flags, payloadLayout});
633+
634+
// Pre swift-5.1 runtimes were missing the initialization of the
635+
// the extraInhabitantCount field. Do it here instead.
636+
auto payloadRef = IGF.Builder.CreateBitOrPointerCast(
637+
payloadLayout, IGF.IGM.TypeLayoutTy->getPointerTo());
638+
auto payloadExtraInhabitantCount =
639+
IGF.Builder.CreateLoad(IGF.Builder.CreateStructGEP(
640+
Address(payloadRef, Alignment(1)), 3,
641+
Size(IGF.IGM.DataLayout.getTypeAllocSize(IGF.IGM.SizeTy) * 2 +
642+
IGF.IGM.DataLayout.getTypeAllocSize(IGF.IGM.Int32Ty))));
643+
emitStoreOfExtraInhabitantCount(IGF, payloadExtraInhabitantCount,
644+
metadata);
633645
}
634646

635647
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {

lib/IRGen/GenOpaque.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,9 @@ llvm::Value *irgen::emitInvariantLoadOfOpaqueWitness(IRGenFunction &IGF,
343343
return witness;
344344
}
345345

346-
/// Given a value witness table, load one of the value witnesses.
347-
/// The result has the appropriate type for the witness.
348-
static llvm::Value *emitLoadOfValueWitnessValue(IRGenFunction &IGF,
349-
llvm::Value *table,
350-
ValueWitness witness) {
346+
static Address emitAddressOfValueWitnessTableValue(IRGenFunction &IGF,
347+
llvm::Value *table,
348+
ValueWitness witness) {
351349
assert(!isValueWitnessFunction(witness));
352350
assert(unsigned(witness) <= unsigned(ValueWitness::ExtraInhabitantCount) &&
353351
"extraInhabitantCount not the last non-function value witness");
@@ -368,7 +366,15 @@ static llvm::Value *emitLoadOfValueWitnessValue(IRGenFunction &IGF,
368366
Address addr = Address(table, IGF.IGM.getPointerAlignment());
369367
addr = IGF.Builder.CreateBitCast(addr, IGF.IGM.getValueWitnessTablePtrTy());
370368
addr = IGF.Builder.CreateStructGEP(addr, unsigned(witness), offset);
369+
return addr;
370+
}
371371

372+
/// Given a value witness table, load one of the value witnesses.
373+
/// The result has the appropriate type for the witness.
374+
static llvm::Value *emitLoadOfValueWitnessValue(IRGenFunction &IGF,
375+
llvm::Value *table,
376+
ValueWitness witness) {
377+
auto addr = emitAddressOfValueWitnessTableValue(IGF, table, witness);
372378
auto load = IGF.Builder.CreateLoad(addr, getValueWitnessLabel(witness));
373379
IGF.setInvariantLoad(load);
374380
return load;
@@ -912,6 +918,15 @@ llvm::Value *irgen::emitLoadOfExtraInhabitantCount(IRGenFunction &IGF,
912918
return IGF.emitValueWitnessValue(T, ValueWitness::ExtraInhabitantCount);
913919
}
914920

921+
void irgen::emitStoreOfExtraInhabitantCount(IRGenFunction &IGF,
922+
llvm::Value *value,
923+
llvm::Value *metadata) {
924+
auto vwTable = IGF.emitValueWitnessTableRefForMetadata(metadata);
925+
auto addr = emitAddressOfValueWitnessTableValue(
926+
IGF, vwTable, ValueWitness::ExtraInhabitantCount);
927+
IGF.Builder.CreateStore(value, addr);
928+
}
929+
915930
std::pair<llvm::Value *, llvm::Value *>
916931
irgen::emitLoadOfIsInline(IRGenFunction &IGF, llvm::Value *metadata) {
917932
auto *flags = emitLoadOfValueWitnessValueFromMetadata(IGF, metadata,

lib/IRGen/GenOpaque.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ namespace irgen {
215215
/// Emit a load of the 'extraInhabitantCount' value witness.
216216
llvm::Value *emitLoadOfExtraInhabitantCount(IRGenFunction &IGF, SILType T);
217217

218+
/// Emit a stored to the 'extraInhabitantCount' value witness.
219+
void emitStoreOfExtraInhabitantCount(IRGenFunction &IGF, llvm::Value *val,
220+
llvm::Value *metadata);
221+
218222
/// Returns the IsInline flag and the loaded flags value.
219223
std::pair<llvm::Value *, llvm::Value *>
220224
emitLoadOfIsInline(IRGenFunction &IGF, llvm::Value *metadata);

lib/IRGen/IRGenModule.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
228228
SizeTy // extra inhabitant flags (optional)
229229
});
230230

231+
TypeLayoutTy = createStructType(*this, "swift.type_layout", {
232+
SizeTy, // size
233+
SizeTy, // stride
234+
Int32Ty, // flags
235+
Int32Ty // extra inhabitant count
236+
});
237+
231238
// A protocol descriptor describes a protocol. It is not type metadata in
232239
// and of itself, but is referenced in the structure of existential type
233240
// metadata records.

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ class IRGenModule {
579579
};
580580
llvm::StructType *OffsetPairTy; /// { iSize, iSize }
581581
llvm::StructType *FullTypeLayoutTy; /// %swift.full_type_layout = { ... }
582+
llvm::StructType *TypeLayoutTy; /// %swift.type_layout = { ... }
582583
llvm::PointerType *TupleTypeMetadataPtrTy; /// %swift.tuple_type*
583584
llvm::StructType *FullHeapMetadataStructTy; /// %swift.full_heapmetadata = type { ... }
584585
llvm::PointerType *FullHeapMetadataPtrTy;/// %swift.full_heapmetadata*

test/IRGen/enum.sil

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2683,6 +2683,15 @@ entry(%x : $*MyOptional):
26832683
// CHECK: [[T_VWT:%.*]] = load i8**, i8*** [[T_VWT_ADDR]]
26842684
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VWT]], i32 8
26852685
// CHECK: call void @swift_initEnumMetadataSingleCase(%swift.type* [[METADATA]], [[WORD]] 0, i8** [[T_LAYOUT]])
2686+
// CHECK: [[PAYLOAD_TYPELAYOUT:%.*]] = bitcast i8** [[T_LAYOUT]] to %swift.type_layout*
2687+
// CHECK: [[PAYLOAD_EXTRAINHABITANTCNT:%.*]] = getelementptr inbounds %swift.type_layout, %swift.type_layout* [[PAYLOAD_TYPELAYOUT]], i32 0, i32 3
2688+
// CHECK: [[CNT:%.*]] = load i32, i32* [[PAYLOAD_EXTRAINHABITANTCNT]]
2689+
// CHECK: [[METADATA2:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
2690+
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA2]], i64 -1
2691+
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
2692+
// CHECK: [[VWT2:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
2693+
// CHECK: [[XIC_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT2]], i32 0, i32 11
2694+
// CHECK: store i32 [[CNT]], i32* [[XIC_ADDR]]
26862695
// CHECK: ret %swift.metadata_response
26872696

26882697
// -- Fill function for dynamic single-payload. Call into the runtime to

0 commit comments

Comments
 (0)