Skip to content

Commit 66a5329

Browse files
authored
Merge pull request #74952 from drexin/wip-129627898
[IRGen] Always load extra tag bits as full bytes in CVW to avoid elem…
2 parents 427077b + 5dcd163 commit 66a5329

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,11 +1688,22 @@ namespace {
16881688
auto payload = EnumPayload::load(IGF, projectPayload(IGF, addr),
16891689
PayloadSchema);
16901690
if (ExtraTagBitCount > 0) {
1691-
extraTag = IGF.Builder.CreateLoad(projectExtraTagBits(IGF, addr));
16921691
if (maskExtraTagBits) {
1693-
auto maskBits = llvm::NextPowerOf2(NumExtraTagValues) - 1;
1692+
auto projectedBits = projectExtraTagBits(IGF, addr);
1693+
// LLVM assumes that loads of fractional byte sizes have been stored
1694+
// with the same type, so all unused bits would be 0. Since we are
1695+
// re-using spare bits for tag storage, that assumption is wrong here.
1696+
// In CVW we have to mask the extra bits, which requires us to make
1697+
// this cast here, otherwise LLVM would optimize away the bit mask.
1698+
if (projectedBits.getElementType()->getIntegerBitWidth() < 8) {
1699+
projectedBits = IGF.Builder.CreateElementBitCast(addr, IGM.Int8Ty);
1700+
}
1701+
extraTag = IGF.Builder.CreateLoad(projectedBits);
1702+
auto maskBits = llvm::PowerOf2Ceil(NumExtraTagValues) - 1;
16941703
auto mask = llvm::ConstantInt::get(extraTag->getType(), maskBits);
16951704
extraTag = IGF.Builder.CreateAnd(extraTag, mask);
1705+
} else {
1706+
extraTag = IGF.Builder.CreateLoad(projectExtraTagBits(IGF, addr));
16961707
}
16971708
}
16981709
return {std::move(payload), extraTag};

test/Interpreter/Inputs/layout_string_witnesses_types.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,16 @@ public enum MultiPayloadError {
619619
case error2(Int, Error)
620620
}
621621

622+
public enum TwoPayloadInner {
623+
case x(AnyObject)
624+
case y(Int)
625+
}
626+
627+
public enum TwoPayloadOuter {
628+
case x(Int)
629+
case y(TwoPayloadInner)
630+
}
631+
622632
@inline(never)
623633
public func consume<T>(_ x: T.Type) {
624634
withExtendedLifetime(x) {}

test/Interpreter/layout_string_witnesses_static.swift

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -I %S/Inputs/CTypes -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -parse-stdlib -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift
2+
// RUN: %target-swift-frontend -O -I %S/Inputs/CTypes -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -parse-stdlib -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift
33

44
// NOTE: We have to build this as dylib to turn private external symbols into local symbols, so we can observe potential issues with linkage
5-
// RUN: %target-build-swift-dylib(%t/%target-library-name(layout_string_witnesses_types)) -I %S/Inputs/CTypes -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -parse-stdlib -parse-as-library %S/Inputs/layout_string_witnesses_types.swift
5+
// RUN: %target-build-swift-dylib(%t/%target-library-name(layout_string_witnesses_types)) -O -I %S/Inputs/CTypes -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -parse-stdlib -parse-as-library %S/Inputs/layout_string_witnesses_types.swift
66
// RUN: %target-codesign %t/%target-library-name(layout_string_witnesses_types)
7-
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -enable-library-evolution -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift
8-
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift
9-
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -module-name layout_string_witnesses_static -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
7+
// RUN: %target-swift-frontend -O -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -enable-library-evolution -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift
8+
// RUN: %target-build-swift -O -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift
9+
// RUN: %target-build-swift -O -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -module-name layout_string_witnesses_static -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
1010
// RUN: %target-codesign %t/main
1111
// RUN: %target-run %t/main %t/%target-library-name(layout_string_witnesses_types) | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os
1212

@@ -1290,6 +1290,35 @@ func testCTypeUnderAligned() {
12901290

12911291
testCTypeUnderAligned()
12921292

1293+
func testNestedTwoPayload() {
1294+
let ptr = UnsafeMutablePointer<TwoPayloadOuter>.allocate(capacity: 1)
1295+
1296+
do {
1297+
let x = TwoPayloadOuter.y(TwoPayloadInner.x(SimpleClass(x: 23)))
1298+
testInit(ptr, to: x)
1299+
}
1300+
1301+
do {
1302+
let y = TwoPayloadOuter.y(TwoPayloadInner.x(SimpleClass(x: 1)))
1303+
1304+
// CHECK: Before deinit
1305+
print("Before deinit")
1306+
1307+
// CHECK-NEXT: SimpleClass deinitialized!
1308+
testAssign(ptr, from: y)
1309+
}
1310+
1311+
// CHECK-NEXT: Before deinit
1312+
print("Before deinit")
1313+
1314+
// CHECK-NEXT: SimpleClass deinitialized!
1315+
testDestroy(ptr)
1316+
1317+
ptr.deallocate()
1318+
}
1319+
1320+
testNestedTwoPayload()
1321+
12931322
#if os(macOS)
12941323
func testObjc() {
12951324
let ptr = UnsafeMutablePointer<ObjcWrapper>.allocate(capacity: 1)

0 commit comments

Comments
 (0)