Skip to content

Commit a566ad5

Browse files
author
Joe Shajrawi
committed
Merge pull request #16515 from shajrawi/resilient_in_struct
[IRGen] Fix offset calculation when having a struct with a resilient type as its first field
1 parent 66e1bdb commit a566ad5

File tree

2 files changed

+75
-27
lines changed

2 files changed

+75
-27
lines changed

lib/IRGen/GenHeap.cpp

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,34 @@ HeapLayout::HeapLayout(IRGenModule &IGM, LayoutStrategy strategy,
8181
#endif
8282
}
8383

84+
static llvm::Value *calcInitOffset(swift::irgen::IRGenFunction &IGF,
85+
unsigned int i,
86+
const swift::irgen::HeapLayout &layout) {
87+
llvm::Value *offset = nullptr;
88+
if (i == 0) {
89+
auto startoffset = layout.getSize();
90+
offset = llvm::ConstantInt::get(IGF.IGM.SizeTy, startoffset.getValue());
91+
return offset;
92+
}
93+
auto &prevElt = layout.getElement(i - 1);
94+
auto prevType = layout.getElementTypes()[i - 1];
95+
// Start calculating offsets from the last fixed-offset field.
96+
Size lastFixedOffset = layout.getElement(i - 1).getByteOffset();
97+
if (auto *fixedType = dyn_cast<FixedTypeInfo>(&prevElt.getTypeForLayout())) {
98+
// If the last fixed-offset field is also fixed-size, we can
99+
// statically compute the end of the fixed-offset fields.
100+
auto fixedEnd = lastFixedOffset + fixedType->getFixedSize();
101+
offset = llvm::ConstantInt::get(IGF.IGM.SizeTy, fixedEnd.getValue());
102+
} else {
103+
// Otherwise, we need to add the dynamic size to the fixed start
104+
// offset.
105+
offset = llvm::ConstantInt::get(IGF.IGM.SizeTy, lastFixedOffset.getValue());
106+
offset = IGF.Builder.CreateAdd(
107+
offset, prevElt.getTypeForLayout().getSize(IGF, prevType));
108+
}
109+
return offset;
110+
}
111+
84112
HeapNonFixedOffsets::HeapNonFixedOffsets(IRGenFunction &IGF,
85113
const HeapLayout &layout) {
86114
if (!layout.isFixedLayout()) {
@@ -107,34 +135,8 @@ HeapNonFixedOffsets::HeapNonFixedOffsets(IRGenFunction &IGF,
107135
case ElementLayout::Kind::NonFixed:
108136
// Start calculating non-fixed offsets from the end of the first fixed
109137
// field.
110-
if (i == 0) {
111-
totalAlign = elt.getTypeForLayout().getAlignmentMask(IGF, eltTy);
112-
offset = totalAlign;
113-
Offsets.push_back(totalAlign);
114-
break;
115-
}
116-
117-
assert(i > 0 && "shouldn't begin with a non-fixed field");
118-
auto &prevElt = layout.getElement(i-1);
119-
auto prevType = layout.getElementTypes()[i-1];
120-
// Start calculating offsets from the last fixed-offset field.
121138
if (!offset) {
122-
Size lastFixedOffset = layout.getElement(i-1).getByteOffset();
123-
if (auto *fixedType = dyn_cast<FixedTypeInfo>(&prevElt.getTypeForLayout())) {
124-
// If the last fixed-offset field is also fixed-size, we can
125-
// statically compute the end of the fixed-offset fields.
126-
auto fixedEnd = lastFixedOffset + fixedType->getFixedSize();
127-
offset
128-
= llvm::ConstantInt::get(IGF.IGM.SizeTy, fixedEnd.getValue());
129-
} else {
130-
// Otherwise, we need to add the dynamic size to the fixed start
131-
// offset.
132-
offset
133-
= llvm::ConstantInt::get(IGF.IGM.SizeTy,
134-
lastFixedOffset.getValue());
135-
offset = IGF.Builder.CreateAdd(offset,
136-
prevElt.getTypeForLayout().getSize(IGF, prevType));
137-
}
139+
offset = calcInitOffset(IGF, i, layout);
138140
}
139141

140142
// Round up to alignment to get the offset.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
3+
// RUN: %target-swift-frontend -I %t -emit-ir %s | %FileCheck %s
4+
5+
// REQUIRES: CPU=x86_64
6+
7+
import resilient_struct
8+
9+
struct StructWithFunc {
10+
func foo(ptr: @escaping () -> Void) {
11+
}
12+
}
13+
14+
struct ProtAndResilStruct {
15+
let foundationType: ResilientBool
16+
17+
let fooImp: StructWithFunc
18+
19+
init(fType: ResilientBool, fooImp: StructWithFunc) {
20+
self.foundationType = fType
21+
self.fooImp = fooImp
22+
}
23+
24+
func bar() {
25+
}
26+
27+
func crash() {
28+
fooImp.foo(ptr: bar)
29+
}
30+
// CHECK-LABEL: define{{.*}} @"$S26struct_with_resilient_type18ProtAndResilStructV3baryyFTc"(%T26struct_with_resilient_type18ProtAndResilStructV* noalias nocapture)
31+
// CHECK: %flags.alignmentMask = and i64 %flags, 65535
32+
// CHECK: [[XOR_ALIGN:%.*]] = xor i64 %flags.alignmentMask, -1
33+
// CHECK: [[INIT_OFFSET:%.*]] = add i64 16, %flags.alignmentMask
34+
// CHECK: [[T0:%.*]] = and i64 [[INIT_OFFSET]], [[XOR_ALIGN]]
35+
// CHECK: [[T1:%.*]] = add i64 [[T0]], %size
36+
// CHECK: [[ALIGN:%.*]] = or i64 7, %flags.alignmentMask
37+
}
38+
39+
func crashCaller() {
40+
let fType = ResilientBool(b: false)
41+
let fooImp = StructWithFunc()
42+
let badStruct = ProtAndResilStruct(fType: fType, fooImp: fooImp)
43+
badStruct.crash()
44+
}
45+
46+
crashCaller()

0 commit comments

Comments
 (0)