Skip to content

Commit f984f94

Browse files
committed
[IRGen] Don't store payload in destructiveInjectEnumTag when payload is empty type
rdar://142485229 In generic multi payload enums, if the payload was empty, we missed a check for that when storing the payload and always cleared out the extra tag byte.
1 parent fc16f3f commit f984f94

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

lib/IRGen/TypeLayout.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3262,13 +3262,29 @@ void EnumTypeLayoutEntry::storeMultiPayloadValue(IRGenFunction &IGF,
32623262
Address enumAddr) const {
32633263
auto &IGM = IGF.IGM;
32643264
auto &Builder = IGF.Builder;
3265+
3266+
auto emptyBB = IGF.createBasicBlock("empty-payload");
3267+
auto nonEmptyBB = IGF.createBasicBlock("non-empty-payload");
3268+
auto contBB = IGF.createBasicBlock("");
3269+
32653270
auto truncSize = Builder.CreateZExtOrTrunc(maxPayloadSize(IGF), IGM.Int32Ty);
3271+
auto empty =
3272+
Builder.CreateICmpEQ(truncSize, llvm::ConstantInt::get(IGM.Int32Ty, 0));
3273+
3274+
Builder.CreateCondBr(empty, emptyBB, nonEmptyBB);
3275+
3276+
Builder.emitBlock(nonEmptyBB);
32663277
auto four = IGM.getInt32(4);
32673278
auto sizeGTE4 = Builder.CreateICmpUGE(truncSize, four);
32683279
auto sizeClampedTo4 = Builder.CreateSelect(sizeGTE4, four, truncSize);
32693280
Builder.CreateMemSet(enumAddr, llvm::ConstantInt::get(IGF.IGM.Int8Ty, 0),
32703281
truncSize);
32713282
emitStore1to4Bytes(IGF, enumAddr, value, sizeClampedTo4);
3283+
Builder.CreateBr(contBB);
3284+
3285+
Builder.emitBlock(emptyBB);
3286+
Builder.CreateBr(contBB);
3287+
Builder.emitBlock(contBB);
32723288
}
32733289

32743290
void EnumTypeLayoutEntry::storeEnumTagSinglePayloadForMultiPayloadEnum(

test/IRGen/typelayout_based_value_witness.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ public enum ForwardEnum<T> {
127127
// OPT: ret void
128128
// CHECK: }
129129

130+
// OPT: define internal void @"$s30typelayout_based_value_witness2E3Owui"(ptr noalias nocapture writeonly %value, i32 %tag, ptr nocapture readonly %"E3<T>")
131+
// OPT: [[IS_EMPTY:%.*]] = icmp eq i32 {{%.*}}, 0
132+
// OPT: br i1 [[IS_EMPTY]], label %empty-payload, label %non-empty-payload
133+
// OPT: }
134+
130135
// Let's not crash on the following example.
131136
public protocol P {}
132137

@@ -145,3 +150,9 @@ public enum E2<T: P> {
145150
case first(Ref<T>)
146151
case second(String)
147152
}
153+
154+
public enum E3<T> {
155+
case empty
156+
case first(T)
157+
case second(T)
158+
}

0 commit comments

Comments
 (0)