-
Notifications
You must be signed in to change notification settings - Fork 15.4k
Parse CFI instructions to create SFrame FREs #155496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
6ce089d
1b1eb72
67b9205
f5b9edd
d2b2503
c1a97b0
8b54030
3415154
8dd4b52
3ea761c
c9e9ee8
be4da9e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,17 +24,17 @@ namespace { | |||||||
| // High-level structure to track info needed to emit a | ||||||||
| // sframe_frame_row_entry_addrX. On disk these have both a fixed portion of type | ||||||||
| // sframe_frame_row_entry_addrX and trailing data of X * S bytes, where X is the | ||||||||
| // datum size, and S is 1, 2, or 3 depending on which of Cfa, SP, and FP are | ||||||||
| // datum size, and S is 1, 2, or 3 depending on which of CFA, SP, and FP are | ||||||||
| // being tracked. | ||||||||
| struct SFrameFRE { | ||||||||
| // An FRE describes how to find the registers when the PC is at this | ||||||||
| // Label from function start. | ||||||||
| const MCSymbol *Label = nullptr; | ||||||||
| size_t CfaOffset = 0; | ||||||||
| size_t CFAOffset = 0; | ||||||||
| size_t FPOffset = 0; | ||||||||
| size_t RAOffset = 0; | ||||||||
| bool FromFP = false; | ||||||||
| bool CfaRegSet = false; | ||||||||
| bool CFARegSet = false; | ||||||||
|
|
||||||||
| SFrameFRE(const MCSymbol *Start) : Label(Start) {} | ||||||||
| }; | ||||||||
|
|
@@ -46,13 +46,11 @@ struct SFrameFDE { | |||||||
| const MCDwarfFrameInfo &DFrame; | ||||||||
| // Label where this FDE's FREs start. | ||||||||
| MCSymbol *FREStart; | ||||||||
| // True when unwind info can't be described with an Sframe FDE. | ||||||||
| bool Invalid; | ||||||||
| // Unwinding fres | ||||||||
| SmallVector<SFrameFRE> FREs; | ||||||||
|
|
||||||||
| SFrameFDE(const MCDwarfFrameInfo &DF, MCSymbol *FRES) | ||||||||
| : DFrame(DF), FREStart(FRES), Invalid(false) {} | ||||||||
| : DFrame(DF), FREStart(FRES) {} | ||||||||
|
|
||||||||
| void emit(MCObjectStreamer &S, const MCSymbol *FRESubSectionStart) { | ||||||||
| MCContext &C = S.getContext(); | ||||||||
|
|
@@ -109,91 +107,81 @@ class SFrameEmitterImpl { | |||||||
| MCSymbol *FRESubSectionStart; | ||||||||
| MCSymbol *FRESubSectionEnd; | ||||||||
|
|
||||||||
|
|
||||||||
| bool setCfaRegister(SFrameFDE &FDE, SFrameFRE &FRE, const MCCFIInstruction &I) { | ||||||||
| bool setCFARegister(SFrameFRE &FRE, const MCCFIInstruction &I) { | ||||||||
| if (I.getRegister() == SPReg) { | ||||||||
| FRE.CfaRegSet = true; | ||||||||
| FRE.CFARegSet = true; | ||||||||
| FRE.FromFP = false; | ||||||||
| return true; | ||||||||
| } else if (I.getRegister() == FPReg) { | ||||||||
| FRE.CfaRegSet = true; | ||||||||
| } | ||||||||
| if (I.getRegister() == FPReg) { | ||||||||
| FRE.CFARegSet = true; | ||||||||
| FRE.FromFP = true; | ||||||||
| return true; | ||||||||
| } | ||||||||
| Streamer.getContext().reportWarning( | ||||||||
| I.getLoc(), "Canonical Frame Address not in stack- or frame-pointer. " | ||||||||
| "Omitting SFrame unwind info for this function."); | ||||||||
| FDE.Invalid = true; | ||||||||
| return false; | ||||||||
| } | ||||||||
|
|
||||||||
| bool isCfaRegisterSet(SFrameFDE &FDE, SFrameFRE &FRE, | ||||||||
| const MCCFIInstruction &I) { | ||||||||
| if (FRE.CfaRegSet) | ||||||||
| return true; | ||||||||
|
|
||||||||
| Streamer.getContext().reportWarning( | ||||||||
| I.getLoc(), "Adjusting CFA offset without a base register. " | ||||||||
| "Omitting SFrame unwind info for this function."); | ||||||||
| FDE.Invalid = true; | ||||||||
| return false; | ||||||||
| bool setCFAOffset(SFrameFRE &FRE, const SMLoc &Loc, size_t Offset) { | ||||||||
| if (!FRE.CFARegSet) { | ||||||||
| Streamer.getContext().reportWarning( | ||||||||
| Loc, "Adjusting CFA offset without a base register. " | ||||||||
| "Omitting SFrame unwind info for this function."); | ||||||||
| return false; | ||||||||
| } | ||||||||
| FRE.CFAOffset = Offset; | ||||||||
| return true; | ||||||||
| } | ||||||||
|
|
||||||||
| // Add the effects of CFI to the current FDE, creating a new FRE when | ||||||||
| // necessary. | ||||||||
| void handleCFI(SFrameFDE &FDE, SFrameFRE &FRE, const MCCFIInstruction &CFI) { | ||||||||
| bool handleCFI(SFrameFDE &FDE, SFrameFRE &FRE, const MCCFIInstruction &CFI) { | ||||||||
| switch (CFI.getOperation()) { | ||||||||
| case MCCFIInstruction::OpDefCfaRegister: | ||||||||
| setCfaRegister(FDE, FRE, CFI); | ||||||||
| return; | ||||||||
| return setCFARegister(FRE, CFI); | ||||||||
| case MCCFIInstruction::OpDefCfa: | ||||||||
| case MCCFIInstruction::OpLLVMDefAspaceCfa: | ||||||||
| if (!setCfaRegister(FDE, FRE, CFI)) | ||||||||
| return; | ||||||||
| FRE.CfaOffset = CFI.getOffset(); | ||||||||
| return; | ||||||||
| if (!setCFARegister(FRE, CFI)) | ||||||||
| return false; | ||||||||
| setCFAOffset(FRE, CFI.getLoc(), CFI.getOffset()); | ||||||||
| return true; | ||||||||
|
||||||||
| setCFAOffset(FRE, CFI.getLoc(), CFI.getOffset()); | |
| return true; | |
| return setCFAOffset(FRE, CFI.getLoc(), CFI.getOffset()); |
I guess the difference is that if this was the only error, the code would still go on to produce a (broken) FDE entry.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: non-default to conform with LLVM warning style guide.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,35 +1,31 @@ | ||
| // TODO: Add other architectures as they gain sframe support | ||
| // REQUIRES: x86-registered-target | ||
| // RUN: llvm-mc --assemble --filetype=obj --gsframe -triple x86_64 %s -o %t.o 2>&1 | FileCheck %s | ||
| // RUN: llvm-mc --assemble --filetype=obj -triple x86_64 %s -o %t.o 2>&1 | FileCheck %s | ||
| // RUN: llvm-readelf --sframe %t.o | FileCheck --check-prefix=CHECK-NOFDES %s | ||
|
|
||
|
|
||
| .cfi_sections .sframe | ||
labath marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| f1: | ||
| .cfi_startproc simple | ||
| // CHECK: Non-default RA register {{.*}} | ||
| .cfi_return_column 0 | ||
| nop | ||
| .cfi_def_cfa_offset 16 // No base register yet | ||
| nop | ||
| .cfi_adjust_cfa_offset 16 // No base register yet | ||
| // CHECK: {{.*}} Adjusting CFA offset without a base register.{{.*}} | ||
| .cfi_def_cfa_offset 16 // no line number reported here. | ||
| nop | ||
| .cfi_return_column 0 | ||
| // CHECK: [[@LINE+1]]:{{.*}} Adjusting CFA offset without a base register.{{.*}} | ||
| .cfi_adjust_cfa_offset 16 | ||
| nop | ||
| .cfi_endproc | ||
|
|
||
| f2: | ||
| .cfi_startproc | ||
| nop | ||
| // CHECK: Canonical Frame Address not in stack- or frame-pointer. {{.*}} | ||
| .cfi_def_cfa 0, 4 | ||
| nop | ||
|
|
||
| .cfi_endproc | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. something wrong with the indentation here. Tabs?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's still something wrong with the indentation on this line (.cfi_endproc), at least when I view it in github UI. (I would expect it to start at the same column as the other .cfi directives. |
||
|
|
||
| // CHECK: Non-default RA register {{.*}} | ||
| // asm parser doesn't give a location with .cfi_def_cfa_offset | ||
| // CHECK: :0:{{.*}} Adjusting CFA offset without a base register.{{.*}} | ||
| // .cfi_adjust_cfa_offset | ||
| // CHECK: :13:{{.*}} Adjusting CFA offset without a base register. {{.*}} | ||
| // CHECK: Canonical Frame Address not in stack- or frame-pointer. {{.*}} | ||
|
|
||
| // CHECK-NOFDES: Num FDEs: 0 | ||
| // CHECK-NOFDES: Num FREs: 0 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,7 +16,7 @@ f1: | |
| nop | ||
| .cfi_register 0, 1 // Uninteresting register. No new FRE. | ||
| nop | ||
|
|
||
| .cfi_endproc | ||
|
|
||
| f2: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.