Skip to content

Commit f12a321

Browse files
committed
[Runtime] Fixed multi-payload empty-case masking.
When storing a tag into a multi-payload enum for an empty case via swift_storeEnumTagMultiPayload, the tag is split between the storage for payloads (i.e. the associated values of the non-empty cases) and the storage for tags (i.e. the integers which refer to the non-empty cases). Typically, the number of non-empty cases (i.e. one beyond the tag that refers to the last non-empty case) is stored into the tag storage and the integer which distinguishes which among the empty cases the enum is in is stored into storage for payloads. When the enum is small, however--specifically, when the payload size is less than four bytes--that information is packaged differently via masking. Previously, there was a problem with that masking. While the value stored into the tag storage was correct (and correctly indicated that the enum was in some empty case), the value stored into the payload storage was not. The result was that which empty case an enum was in would be corrupted. Here, that is fixed by fixing the masking. rdar://87914343
1 parent b90d584 commit f12a321

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

stdlib/public/runtime/Enum.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ swift::swift_storeEnumTagMultiPayload(OpaqueValue *value,
325325
} else {
326326
unsigned numPayloadBits = layout.payloadSize * CHAR_BIT;
327327
whichTag = numPayloads + (whichEmptyCase >> numPayloadBits);
328-
whichPayloadValue = whichEmptyCase & ((1U << numPayloads) - 1U);
328+
whichPayloadValue = whichEmptyCase & ((1U << numPayloadBits) - 1U);
329329
}
330330
storeMultiPayloadTag(value, layout, whichTag);
331331
storeMultiPayloadValue(value, layout, whichPayloadValue);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
public enum ResilientEnum : Comparable {
2+
case a
3+
case b
4+
case c
5+
}
6+
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-build-swift \
4+
// RUN: -emit-module \
5+
// RUN: %S/Inputs/rdar87914343_Resilient.swift \
6+
// RUN: -parse-as-library \
7+
// RUN: -enable-library-evolution \
8+
// RUN: -module-name Resilient \
9+
// RUN: -emit-module-path %t/Resilient.swiftmodule
10+
11+
// RUN: %target-build-swift \
12+
// RUN: -c \
13+
// RUN: %S/Inputs/rdar87914343_Resilient.swift \
14+
// RUN: -parse-as-library \
15+
// RUN: -enable-library-evolution \
16+
// RUN: -module-name Resilient \
17+
// RUN: -o %t/Resilient.o
18+
19+
// RUN: %target-build-swift \
20+
// RUN: -c \
21+
// RUN: %s \
22+
// RUN: -o %t/main.o \
23+
// RUN: -I %t
24+
25+
// RUN: %target-swiftc_driver \
26+
// RUN: %t/Resilient.o \
27+
// RUN: %t/main.o \
28+
// RUN: -o %t/main
29+
30+
// RUN: %target-codesign %t/main
31+
// RUN: %target-run %t/main | %FileCheck %s
32+
33+
// REQUIRES: executable_test
34+
35+
import Resilient
36+
37+
func dump<T>(_ value: T) {
38+
print(value)
39+
}
40+
41+
enum ProblematicEnumeration {
42+
case zero(ResilientEnum)
43+
case one(Bool)
44+
case two
45+
case three
46+
case four
47+
case five
48+
case six
49+
}
50+
51+
func doit() {
52+
dump(ProblematicEnumeration.six)
53+
}
54+
55+
doit()
56+
// CHECK: six

0 commit comments

Comments
 (0)