Skip to content

Commit 74d49f2

Browse files
[SFrames] Implement .cfi_restore, remember_state, and restore_state (#159832)
As in the description. Very straightforward.
1 parent 9379922 commit 74d49f2

File tree

2 files changed

+114
-25
lines changed

2 files changed

+114
-25
lines changed

llvm/lib/MC/MCSFrame.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ struct SFrameFDE {
111111
MCFragment *Frag;
112112
// Unwinding fres
113113
SmallVector<SFrameFRE> FREs;
114+
// .cfi_remember_state stack
115+
SmallVector<SFrameFRE> SaveState;
114116

115117
SFrameFDE(const MCDwarfFrameInfo &DF, MCSymbol *FRES)
116118
: DFrame(DF), FREStart(FRES), Frag(nullptr) {}
@@ -237,13 +239,30 @@ class SFrameEmitterImpl {
237239
case MCCFIInstruction::OpAdjustCfaOffset:
238240
return setCFAOffset(FRE, CFI.getLoc(), FRE.CFAOffset + CFI.getOffset());
239241
case MCCFIInstruction::OpRememberState:
240-
// TODO: Implement. Will use FDE.
242+
if (FDE.FREs.size() == 1) {
243+
// Error for gas compatibility: If the initial FRE isn't complete,
244+
// then any state is incomplete. FIXME: Dwarf doesn't error here.
245+
// Why should sframe?
246+
Streamer.getContext().reportWarning(
247+
CFI.getLoc(), "skipping SFrame FDE; .cfi_remember_state without "
248+
"prior SFrame FRE state");
249+
return false;
250+
}
251+
FDE.SaveState.push_back(FRE);
241252
return true;
242253
case MCCFIInstruction::OpRestore:
243-
// TODO: Implement. Will use FDE.
254+
// The first FRE generated has the original state.
255+
if (CFI.getRegister() == FPReg)
256+
FRE.FPOffset = FDE.FREs.front().FPOffset;
257+
else if (CFI.getRegister() == RAReg)
258+
FRE.RAOffset = FDE.FREs.front().RAOffset;
244259
return true;
245260
case MCCFIInstruction::OpRestoreState:
246-
// TODO: Implement. Will use FDE.
261+
// The cfi parser will have caught unbalanced directives earlier, so a
262+
// mismatch here is an implementation error.
263+
assert(!FDE.SaveState.empty() &&
264+
"cfi_restore_state without cfi_save_state");
265+
FRE = FDE.SaveState.pop_back_val();
247266
return true;
248267
case MCCFIInstruction::OpEscape:
249268
// TODO: Implement. Will use FDE.
@@ -394,8 +413,8 @@ class SFrameEmitterImpl {
394413
// shf_fdeoff. With no sfh_auxhdr, these immediately follow this header.
395414
Streamer.emitInt32(0);
396415
// shf_freoff
397-
Streamer.emitAbsoluteSymbolDiff(FRESubSectionStart, FDESubSectionStart,
398-
sizeof(uint32_t));
416+
Streamer.emitInt32(FDEs.size() *
417+
sizeof(sframe::FuncDescEntry<endianness::native>));
399418
}
400419

401420
void emitFDEs() {

llvm/test/MC/ELF/cfi-sframe-fre-cases.s

Lines changed: 90 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fde4_fre_offset_sizes:
1717
# CHECK: FuncDescEntry [0] {
1818
# CHECK: Start FRE Offset: 0
1919
# CHECK: FRE Type: Addr1 (0x0)
20-
.cfi_startproc
20+
.cfi_startproc
2121
# CHECK: Frame Row Entry {
2222
# CHECK-NEXT: Start Address: 0x0
2323
# CHECK-NEXT: Return Address Signed: No
@@ -27,80 +27,80 @@ fde4_fre_offset_sizes:
2727
# CHECK-NEXT: RA Offset: -8
2828
.long 0
2929
# Uninteresting register no new fre, no effect on cfa
30-
.cfi_offset 0, 8
30+
.cfi_offset 0, 8
3131
.long 0
32-
.cfi_def_cfa_offset 0x78
32+
.cfi_def_cfa_offset 0x78
3333
# CHECK: Frame Row Entry {
3434
# CHECK-NEXT: Start Address: 0x8
3535
# CHECK-NEXT: Return Address Signed: No
3636
# CHECK-NEXT: Offset Size: B1 (0x0)
3737
# CHECK-NEXT: Base Register: SP (0x1)
3838
# CHECK-NEXT: CFA Offset: 120
3939
# CHECK-NEXT: RA Offset: -8
40-
.long 0
40+
.long 0
4141
# Uninteresting register no new fre, no effect on cfa
4242
.cfi_rel_offset 1, 8
4343
.long 0
44-
.cfi_def_cfa_offset 0x80
44+
.cfi_def_cfa_offset 0x80
4545
# CHECK: Frame Row Entry {
4646
# CHECK-NEXT: Start Address: 0x10
4747
# CHECK-NEXT: Return Address Signed: No
4848
# CHECK-NEXT: Offset Size: B2 (0x1)
4949
# CHECK-NEXT: Base Register: SP (0x1)
5050
# CHECK-NEXT: CFA Offset: 128
5151
# CHECK-NEXT: RA Offset: -8
52-
.long 0
52+
.long 0
5353
# Uninteresting register no new fre, no effect on cfa
5454
.cfi_val_offset 1, 8
5555
.long 0
56-
.cfi_def_cfa_offset 0x7FFF
56+
.cfi_def_cfa_offset 0x7FFF
5757
# CHECK: Frame Row Entry {
5858
# CHECK-NEXT: Start Address: 0x18
5959
# CHECK-NEXT: Return Address Signed: No
6060
# CHECK-NEXT: Offset Size: B2 (0x1)
6161
# CHECK-NEXT: Base Register: SP (0x1)
6262
# CHECK-NEXT: CFA Offset: 32767
6363
# CHECK-NEXT: RA Offset: -8
64-
.long 0
65-
.cfi_def_cfa_offset 0x8000
64+
.long 0
65+
.cfi_def_cfa_offset 0x8000
6666
# CHECK: Frame Row Entry {
6767
# CHECK-NEXT: Start Address: 0x1C
6868
# CHECK-NEXT: Return Address Signed: No
6969
# CHECK-NEXT: Offset Size: B4 (0x2)
7070
# CHECK-NEXT: Base Register: SP (0x1)
7171
# CHECK-NEXT: CFA Offset: 32768
7272
# CHECK-NEXT: RA Offset: -8
73-
.long 0
74-
.cfi_def_cfa_offset 0x8
73+
.long 0
74+
.cfi_def_cfa_offset 0x8
7575
# CHECK: Frame Row Entry {
7676
# CHECK-NEXT: Start Address: 0x20
7777
# CHECK-NEXT: Return Address Signed: No
7878
# CHECK-NEXT: Offset Size: B1 (0x0)
7979
# CHECK-NEXT: Base Register: SP (0x1)
8080
# CHECK-NEXT: CFA Offset: 8
8181
# CHECK-NEXT: RA Offset: -8
82-
.long 0
83-
.cfi_adjust_cfa_offset 0x8
82+
.long 0
83+
.cfi_adjust_cfa_offset 0x8
8484
# CHECK: Frame Row Entry {
8585
# CHECK-NEXT: Start Address: 0x24
8686
# CHECK-NEXT: Return Address Signed: No
8787
# CHECK-NEXT: Offset Size: B1 (0x0)
8888
# CHECK-NEXT: Base Register: SP (0x1)
8989
# CHECK-NEXT: CFA Offset: 16
9090
# CHECK-NEXT: RA Offset: -8
91-
.long 0
92-
.cfi_def_cfa_register 6 # switch to fp
91+
.long 0
92+
.cfi_def_cfa_register 6 # switch to fp
9393
# CHECK: Frame Row Entry {
9494
# CHECK-NEXT: Start Address: 0x28
9595
# CHECK-NEXT: Return Address Signed: No
9696
# CHECK-NEXT: Offset Size: B1 (0x0)
9797
# CHECK-NEXT: Base Register: FP (0x0)
9898
# CHECK-NEXT: CFA Offset: 16
9999
# CHECK-NEXT: RA Offset: -8
100-
.long 0
101-
.cfi_offset 7, 32
102-
# sp not the cfa but with large offset still changes encoding.
103-
.cfi_offset 6, 0x7FF8
100+
.long 0
101+
.cfi_offset 7, 32
102+
# sp not the cfa but with large offset still changes encoding.
103+
.cfi_offset 6, 0x7FF8
104104
# CHECK: Frame Row Entry {
105105
# CHECK-NEXT: Start Address: 0x2C
106106
# CHECK-NEXT: Return Address Signed: No
@@ -109,5 +109,75 @@ fde4_fre_offset_sizes:
109109
# CHECK-NEXT: CFA Offset: 16
110110
# CHECK-NEXT: RA Offset: -8
111111
# CHECK-NEXT: FP Offset: 32760
112-
.long 0
112+
.long 0
113+
.cfi_endproc
114+
115+
.align 1024
116+
restore_reg:
117+
# CHECK: FuncDescEntry [1] {
118+
# CHECK: Start FRE Offset: 0x23
119+
# CHECK-NEXT: Num FREs: 3
120+
.cfi_startproc
121+
# CHECK: Frame Row Entry {
122+
# CHECK-NEXT: Start Address: 0x400
123+
# CHECK-NOT FP Offset{{.*}}
124+
# CHECK: }
125+
.long 0
126+
.cfi_offset 6, 32
127+
# CHECK Frame Row Entry {
128+
# CHECK-NEXT Start Address: 0x404
129+
# CHECK: FP Offset: 32
130+
.long 0
131+
.cfi_restore 6
132+
# CHECK: Frame Row Entry {
133+
# CHECK-NEXT: Start Address: 0x408
134+
# CHECK-NOT FP Offset{{.*}}
135+
# CHECK: }
136+
.long 0
137+
.cfi_endproc
138+
139+
.align 1024
140+
remember_restore_state:
141+
# CHECK: FuncDescEntry [2] {
142+
# CHECK: Start FRE Offset: 0x2D
143+
# CHECK-NEXT: Num FREs: 4
144+
.cfi_startproc
145+
# CHECK: Frame Row Entry {
146+
# CHECK-NEXT: Start Address: 0x800
147+
# CHECK-NOT FP Offset{{.*}}
148+
# CHECK: }
149+
.long 0
150+
.cfi_offset 6, 8
151+
.cfi_offset 7, 16
152+
.cfi_offset 8, 24
153+
# CHECK: Frame Row Entry {
154+
# CHECK-NEXT: Start Address: 0x804
155+
# CHECK: Base Register: SP (0x1)
156+
# CHECK-NEXT: CFA Offset: 8
157+
# CHECK-NEXT: RA Offset: -8
158+
# CHECK-NEXT: FP Offset: 8
159+
# CHECK-NEXT: }
160+
.long 0
161+
.cfi_remember_state
162+
# CHECK: Frame Row Entry {
163+
# CHECK-NEXT: Start Address: 0x808
164+
# CHECK: Base Register: SP (0x1)
165+
# CHECK-NEXT: CFA Offset: 8
166+
# CHECK-NEXT: RA Offset: -8
167+
# CHECK-NEXT: FP Offset: 32
168+
# CHECK-NEXT: }
169+
.cfi_offset 6, 32
170+
.cfi_offset 7, 40
171+
.cfi_offset 8, 48
172+
.long 0
173+
# CHECK: Frame Row Entry {
174+
# CHECK-NEXT: Start Address: 0x80C
175+
# CHECK: Base Register: SP (0x1)
176+
# CHECK-NEXT: CFA Offset: 8
177+
# CHECK-NEXT: RA Offset: -8
178+
# CHECK-NEXT: FP Offset: 8
179+
# CHECK-NEXT: }
180+
.cfi_restore_state
181+
.long 0
182+
113183
.cfi_endproc

0 commit comments

Comments
 (0)