Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions llvm/lib/MC/MCSFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ struct SFrameFDE {
MCFragment *Frag;
// Unwinding fres
SmallVector<SFrameFRE> FREs;
// .cfi_remember_state stack
SmallVector<SFrameFRE> SaveState;

SFrameFDE(const MCDwarfFrameInfo &DF, MCSymbol *FRES)
: DFrame(DF), FREStart(FRES), Frag(nullptr) {}
Expand Down Expand Up @@ -237,13 +239,30 @@ class SFrameEmitterImpl {
case MCCFIInstruction::OpAdjustCfaOffset:
return setCFAOffset(FRE, CFI.getLoc(), FRE.CFAOffset + CFI.getOffset());
case MCCFIInstruction::OpRememberState:
// TODO: Implement. Will use FDE.
if (FDE.FREs.size() == 1) {
// Error for gas compatibility: If the initial FRE isn't complete,
// then any state is incomplete. FIXME: Dwarf doesn't error here.
// Why should sframe?
Streamer.getContext().reportWarning(
CFI.getLoc(), "skipping SFrame FDE; .cfi_remember_state without "
"prior SFrame FRE state");
return false;
}
FDE.SaveState.push_back(FRE);
return true;
case MCCFIInstruction::OpRestore:
// TODO: Implement. Will use FDE.
// The first FRE generated has the original state.
if (CFI.getRegister() == FPReg)
FRE.FPOffset = FDE.FREs.front().FPOffset;
else if (CFI.getRegister() == RAReg)
FRE.RAOffset = FDE.FREs.front().RAOffset;
return true;
case MCCFIInstruction::OpRestoreState:
// TODO: Implement. Will use FDE.
// The cfi parser will have caught unbalanced directives earlier, so a
// mismatch here is an implementation error.
assert(!FDE.SaveState.empty() &&
"cfi_restore_state without cfi_save_state");
FRE = FDE.SaveState.pop_back_val();
return true;
case MCCFIInstruction::OpEscape:
// TODO: Implement. Will use FDE.
Expand Down Expand Up @@ -394,8 +413,8 @@ class SFrameEmitterImpl {
// shf_fdeoff. With no sfh_auxhdr, these immediately follow this header.
Streamer.emitInt32(0);
// shf_freoff
Streamer.emitAbsoluteSymbolDiff(FRESubSectionStart, FDESubSectionStart,
sizeof(uint32_t));
Streamer.emitInt32(FDEs.size() *
sizeof(sframe::FuncDescEntry<endianness::native>));
}

void emitFDEs() {
Expand Down
110 changes: 90 additions & 20 deletions llvm/test/MC/ELF/cfi-sframe-fre-cases.s
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fde4_fre_offset_sizes:
# CHECK: FuncDescEntry [0] {
# CHECK: Start FRE Offset: 0
# CHECK: FRE Type: Addr1 (0x0)
.cfi_startproc
.cfi_startproc
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x0
# CHECK-NEXT: Return Address Signed: No
Expand All @@ -27,80 +27,80 @@ fde4_fre_offset_sizes:
# CHECK-NEXT: RA Offset: -8
.long 0
# Uninteresting register no new fre, no effect on cfa
.cfi_offset 0, 8
.cfi_offset 0, 8
.long 0
.cfi_def_cfa_offset 0x78
.cfi_def_cfa_offset 0x78
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x8
# CHECK-NEXT: Return Address Signed: No
# CHECK-NEXT: Offset Size: B1 (0x0)
# CHECK-NEXT: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 120
# CHECK-NEXT: RA Offset: -8
.long 0
.long 0
# Uninteresting register no new fre, no effect on cfa
.cfi_rel_offset 1, 8
.long 0
.cfi_def_cfa_offset 0x80
.cfi_def_cfa_offset 0x80
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x10
# CHECK-NEXT: Return Address Signed: No
# CHECK-NEXT: Offset Size: B2 (0x1)
# CHECK-NEXT: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 128
# CHECK-NEXT: RA Offset: -8
.long 0
.long 0
# Uninteresting register no new fre, no effect on cfa
.cfi_val_offset 1, 8
.long 0
.cfi_def_cfa_offset 0x7FFF
.cfi_def_cfa_offset 0x7FFF
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x18
# CHECK-NEXT: Return Address Signed: No
# CHECK-NEXT: Offset Size: B2 (0x1)
# CHECK-NEXT: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 32767
# CHECK-NEXT: RA Offset: -8
.long 0
.cfi_def_cfa_offset 0x8000
.long 0
.cfi_def_cfa_offset 0x8000
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x1C
# CHECK-NEXT: Return Address Signed: No
# CHECK-NEXT: Offset Size: B4 (0x2)
# CHECK-NEXT: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 32768
# CHECK-NEXT: RA Offset: -8
.long 0
.cfi_def_cfa_offset 0x8
.long 0
.cfi_def_cfa_offset 0x8
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x20
# CHECK-NEXT: Return Address Signed: No
# CHECK-NEXT: Offset Size: B1 (0x0)
# CHECK-NEXT: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 8
# CHECK-NEXT: RA Offset: -8
.long 0
.cfi_adjust_cfa_offset 0x8
.long 0
.cfi_adjust_cfa_offset 0x8
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x24
# CHECK-NEXT: Return Address Signed: No
# CHECK-NEXT: Offset Size: B1 (0x0)
# CHECK-NEXT: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 16
# CHECK-NEXT: RA Offset: -8
.long 0
.cfi_def_cfa_register 6 # switch to fp
.long 0
.cfi_def_cfa_register 6 # switch to fp
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x28
# CHECK-NEXT: Return Address Signed: No
# CHECK-NEXT: Offset Size: B1 (0x0)
# CHECK-NEXT: Base Register: FP (0x0)
# CHECK-NEXT: CFA Offset: 16
# CHECK-NEXT: RA Offset: -8
.long 0
.cfi_offset 7, 32
# sp not the cfa but with large offset still changes encoding.
.cfi_offset 6, 0x7FF8
.long 0
.cfi_offset 7, 32
# sp not the cfa but with large offset still changes encoding.
.cfi_offset 6, 0x7FF8
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x2C
# CHECK-NEXT: Return Address Signed: No
Expand All @@ -109,5 +109,75 @@ fde4_fre_offset_sizes:
# CHECK-NEXT: CFA Offset: 16
# CHECK-NEXT: RA Offset: -8
# CHECK-NEXT: FP Offset: 32760
.long 0
.long 0
.cfi_endproc

.align 1024
restore_reg:
# CHECK: FuncDescEntry [1] {
# CHECK: Start FRE Offset: 0x23
# CHECK-NEXT: Num FREs: 3
.cfi_startproc
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x400
# CHECK-NOT FP Offset{{.*}}
# CHECK: }
.long 0
.cfi_offset 6, 32
# CHECK Frame Row Entry {
# CHECK-NEXT Start Address: 0x404
# CHECK: FP Offset: 32
.long 0
.cfi_restore 6
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x408
# CHECK-NOT FP Offset{{.*}}
# CHECK: }
.long 0
.cfi_endproc

.align 1024
remember_restore_state:
# CHECK: FuncDescEntry [2] {
# CHECK: Start FRE Offset: 0x2D
# CHECK-NEXT: Num FREs: 4
.cfi_startproc
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x800
# CHECK-NOT FP Offset{{.*}}
# CHECK: }
.long 0
.cfi_offset 6, 8
.cfi_offset 7, 16
.cfi_offset 8, 24
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x804
# CHECK: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 8
# CHECK-NEXT: RA Offset: -8
# CHECK-NEXT: FP Offset: 8
# CHECK-NEXT: }
.long 0
.cfi_remember_state
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x808
# CHECK: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 8
# CHECK-NEXT: RA Offset: -8
# CHECK-NEXT: FP Offset: 32
# CHECK-NEXT: }
.cfi_offset 6, 32
.cfi_offset 7, 40
.cfi_offset 8, 48
.long 0
# CHECK: Frame Row Entry {
# CHECK-NEXT: Start Address: 0x80C
# CHECK: Base Register: SP (0x1)
# CHECK-NEXT: CFA Offset: 8
# CHECK-NEXT: RA Offset: -8
# CHECK-NEXT: FP Offset: 8
# CHECK-NEXT: }
.cfi_restore_state
.long 0

.cfi_endproc
Loading