Skip to content

Commit 2bcc3da

Browse files
committed
[IRGen] Fix enum metadata instantiation for resilient payload
The metadata can't be constant when we generate a layout string at runtime.
1 parent e89de6e commit 2bcc3da

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2581,16 +2581,17 @@ void irgen::emitLazyTypeContextDescriptor(IRGenModule &IGM,
25812581
auto genericSig =
25822582
lowered.getNominalOrBoundGenericNominal()->getGenericSignature();
25832583
hasLayoutString = !!typeLayoutEntry->layoutString(IGM, genericSig);
2584-
}
25852584

2586-
if (auto sd = dyn_cast<StructDecl>(type)) {
2587-
if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnessesInstantiation) &&
2585+
if (!hasLayoutString &&
2586+
IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnessesInstantiation) &&
25882587
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation) {
25892588
hasLayoutString |= requiresForeignTypeMetadata(type) ||
2590-
needsSingletonMetadataInitialization(IGM, type) ||
2591-
(type->isGenericContext() && !isa<FixedTypeInfo>(ti));
2589+
needsSingletonMetadataInitialization(IGM, type) ||
2590+
(type->isGenericContext() && !isa<FixedTypeInfo>(ti));
25922591
}
2592+
}
25932593

2594+
if (auto sd = dyn_cast<StructDecl>(type)) {
25942595
StructContextDescriptorBuilder(IGM, sd, requireMetadata,
25952596
hasLayoutString).emit();
25962597
} else if (auto ed = dyn_cast<EnumDecl>(type)) {
@@ -5487,6 +5488,24 @@ namespace {
54875488
return emitValueWitnessTable(relativeReference);
54885489
}
54895490

5491+
bool hasInstantiatedLayoutString() {
5492+
if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnessesInstantiation) &&
5493+
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation) {
5494+
return needsSingletonMetadataInitialization(IGM, Target);
5495+
}
5496+
5497+
return false;
5498+
}
5499+
5500+
bool hasLayoutString() {
5501+
if (!IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) ||
5502+
!IGM.getOptions().EnableLayoutStringValueWitnesses) {
5503+
return false;
5504+
}
5505+
5506+
return hasInstantiatedLayoutString() || !!getLayoutString();
5507+
}
5508+
54905509
llvm::Constant *emitLayoutString() {
54915510
if (!IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) ||
54925511
!IGM.getOptions().EnableLayoutStringValueWitnesses)
@@ -5521,7 +5540,7 @@ namespace {
55215540

55225541
llvm::Constant *emitNominalTypeDescriptor() {
55235542
auto descriptor = EnumContextDescriptorBuilder(
5524-
IGM, Target, RequireMetadata, !!getLayoutString())
5543+
IGM, Target, RequireMetadata, hasLayoutString())
55255544
.emit();
55265545
return descriptor;
55275546
}
@@ -5570,7 +5589,7 @@ namespace {
55705589
}
55715590

55725591
bool canBeConstant() {
5573-
return !HasUnfilledPayloadSize;
5592+
return !HasUnfilledPayloadSize && !hasInstantiatedLayoutString();
55745593
}
55755594
};
55765595

stdlib/public/runtime/Enum.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ XIElement findXIElement(const Metadata *type) {
222222
void swift::swift_initEnumMetadataSinglePayloadWithLayoutString(
223223
EnumMetadata *self, EnumLayoutFlags layoutFlags,
224224
const Metadata *payloadType, unsigned emptyCases) {
225+
assert(self->hasLayoutString());
226+
225227
auto *payloadLayout = payloadType->getTypeLayout();
226228
size_t payloadSize = payloadLayout->size;
227229
unsigned payloadNumExtraInhabitants = payloadLayout->getNumExtraInhabitants();

test/Interpreter/Inputs/layout_string_witnesses_types_resilient.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,9 @@ public func getResilientSinglePayloadEnumSimpleEmpty0() -> ResilientSinglePayloa
7878
public func getResilientSingletonEnumNonEmpty(_ x: AnyObject) -> ResilientSingletonEnum {
7979
return .nonEmpty(x)
8080
}
81+
82+
public enum ResilientSinglePayloadEnum {
83+
case empty0
84+
case empty1
85+
case nonEmpty(AnyObject, Int)
86+
}

test/Interpreter/layout_string_witnesses_dynamic.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,22 @@ func testResilientSingletonEnumGenericInjectTag() {
686686

687687
testResilientSingletonEnumGenericInjectTag()
688688

689+
enum ResilientPayloadSinglePayloadEnum {
690+
case empty0
691+
case empty1
692+
case empty2
693+
case nonEmpty(ResilientSinglePayloadEnum, Int)
694+
}
695+
696+
func testResilientPayloadSinglePayloadEnum() {
697+
let xxx = ResilientPayloadSinglePayloadEnum.nonEmpty(.empty0, 1)
698+
699+
// CHECK: nonEmpty(layout_string_witnesses_types_resilient.ResilientSinglePayloadEnum.empty0, 1)
700+
print(xxx)
701+
}
702+
703+
testResilientPayloadSinglePayloadEnum()
704+
689705
#if os(macOS)
690706

691707
import Foundation

0 commit comments

Comments
 (0)