Skip to content

Commit c38db43

Browse files
authored
Merge pull request #83922 from drexin/wip-159143492
[IRGen] Fix computation of spare bits for fixed arrays
2 parents 29fcb5e + 81af291 commit c38db43

File tree

3 files changed

+83
-2
lines changed

3 files changed

+83
-2
lines changed

lib/IRGen/GenArray.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,15 @@ class FixedArrayTypeInfoBase : public ArrayTypeInfoBase<BaseTypeInfo> {
248248

249249
// Take spare bits from the first element only.
250250
SpareBitVector result = elementTI.getSpareBits();
251+
251252
// We can use the padding to the next element as spare bits too.
252-
result.appendSetBits(getArraySize(arraySize, elementTI).getValueInBits()
253-
- result.size());
253+
auto padding = elementTI.getFixedStride() - elementTI.getFixedSize();
254+
result.appendSetBits(padding.getValueInBits());
255+
256+
// spare bits of any other elements should not be considered
257+
result.appendClearBits(
258+
getArraySize(arraySize - 1, elementTI).getValueInBits());
259+
254260
return result;
255261
}
256262

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking -O -emit-ir %s | %FileCheck %s
2+
3+
public struct Foo {
4+
let x: UInt64
5+
let y: InlineArray<2, UInt64>
6+
}
7+
8+
public struct Bar {
9+
let x: UInt64
10+
let y: [UInt64]
11+
}
12+
13+
// CHECK: define {{.*}} i32 @"$s22inline_array_enum_tags3BazOwug"(ptr noalias nocapture readonly %value, ptr nocapture readnone %Baz)
14+
// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds i8, ptr %value, {{i64|i32}} 24
15+
// CHECK: [[TAG_VAL:%.*]] = load i8, ptr [[TAG_ADDR]], align 8
16+
// CHECK: [[TAG_EXT:%.*]] = zext i8 [[TAG_VAL]] to i32
17+
// CHECK: ret i32 [[TAG_EXT]]
18+
// CHECK: }
19+
public enum Baz {
20+
case foo(Foo)
21+
case bar(Bar)
22+
}
23+
24+
public struct Padded {
25+
let x: UInt64
26+
let y: InlineArray<2, (UInt16, UInt8)>
27+
}
28+
29+
30+
// CHECK: define {{.*}} i32 @"$s22inline_array_enum_tags17WithPaddedPayloadOwug"(ptr noalias nocapture readonly %value, ptr nocapture readnone %WithPaddedPayload)
31+
// CHECK: entry:
32+
// CHECK: [[ADDR:%.*]] = getelementptr inbounds i8, ptr %value, {{i64|i32}} 8
33+
// CHECK: [[VAL:%.*]] = load {{i64|i32}}, ptr [[ADDR]], align 8
34+
// CHECK: [[TAG:%.*]] = lshr i32 {{%.*}}, 31
35+
// CHECK: ret i32 [[TAG]]
36+
// CHECK: }
37+
public enum WithPaddedPayload {
38+
case a(Padded)
39+
case b(Padded)
40+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking) | %FileCheck %s
2+
// RUN: %target-run-simple-swift(-O -Xfrontend -disable-availability-checking) | %FileCheck %s
3+
4+
// REQUIRES: executable_test
5+
6+
// UNSUPPORTED: back_deployment_runtime || use_os_stdlib
7+
8+
struct Foo {
9+
let x: UInt64
10+
let y: InlineArray<2, UInt64>
11+
}
12+
13+
struct Bar {
14+
let x: UInt64
15+
let y: [UInt64]
16+
}
17+
18+
enum Baz {
19+
case foo(Foo)
20+
case bar(Bar)
21+
}
22+
23+
@inline(never)
24+
func createEnum() -> Baz {
25+
return .foo(Foo(x: 0, y: [0, 0xff00000000000000]))
26+
}
27+
28+
29+
let x = createEnum()
30+
31+
// CHECK: 0 - 18374686479671623680
32+
switch x {
33+
case .bar: fatalError("Expected .foo")
34+
case .foo(let x): print("\(x.y[0]) - \(x.y[1])")
35+
}

0 commit comments

Comments
 (0)