aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCSFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCSFrame.cpp')
-rw-r--r--llvm/lib/MC/MCSFrame.cpp29
1 files changed, 24 insertions, 5 deletions
diff --git a/llvm/lib/MC/MCSFrame.cpp b/llvm/lib/MC/MCSFrame.cpp
index 066d1a3..910fcab 100644
--- a/llvm/lib/MC/MCSFrame.cpp
+++ b/llvm/lib/MC/MCSFrame.cpp
@@ -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) {}
@@ -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.
@@ -394,8 +413,8 @@ public:
// 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() {