[llvm] [Sframe] Support cfi_escape directives compatibly with gnu-gas (PR #161927)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 8 13:10:42 PDT 2025
================
@@ -211,8 +213,155 @@ class SFrameEmitterImpl {
return true;
}
+ // Technically, the escape data could be anything, but it is commonly a dwarf
+ // CFI program. Even then, it could contain an arbitrarily complicated Dwarf
+ // expression. Following gnu-gas, look for certain common cases that could
+ // invalidate an FDE, emit a warning for those sequences, and don't generate
+ // an FDE in those cases. Allow any that are known safe. It is likely that
+ // more thorough test cases could refine this code, but it handles the most
+ // important ones compatibly with gas.
+ // Returns true if the CFI escape sequence is safe for sframes.
+ bool isCFIEscapeSafe(SFrameFDE &FDE, const SFrameFRE &FRE,
+ const MCCFIInstruction &CFI) {
+ const MCAsmInfo *AI = Streamer.getContext().getAsmInfo();
+ DWARFDataExtractorSimple data(CFI.getValues(), AI->isLittleEndian(),
+ AI->getCodePointerSize());
+
+ // Normally, both alignment factors are extracted from the enclosing Dwarf
+ // FDE or CIE. We don't have one here. Alignments are used for scaling
+ // factors for ops like CFA_def_cfa_offset_sf. But this particular function
+ // is only interested in registers.
+ dwarf::CFIProgram P(/* CodeAlignmentFactor */ 1,
+ /* DataAlignmentFactor*/ 1,
+ Streamer.getContext().getTargetTriple().getArch());
+ uint64_t Offset = 0;
+ if (P.parse(data, &Offset, CFI.getValues().size())) {
+ // Not a parsable dwarf expression. Assume the worst.
+ Streamer.getContext().reportWarning(
+ CFI.getLoc(),
+ "skipping SFrame FDE; .cfi_escape with unknown effects");
+ return false;
+ }
+
+ // This loop deals with dwarf::CFIProgram::Instructions. Everywhere else
+ // this file deals with MCCFIInstructions.
+ for (const dwarf::CFIProgram::Instruction &I : P) {
+ switch (I.Opcode) {
+ case dwarf::DW_CFA_nop:
+ break;
+ case dwarf::DW_CFA_val_offset: {
+ // First argument is a register. Anything that touches CFA, FP, or RA is
+ // a problem, but allow others through. As an even more special case,
+ // allow SP + 0.
+ auto Reg = I.getOperandAsUnsigned(P, 0);
+ if (!Reg) {
+ Streamer.getContext().reportWarning(
+ CFI.getLoc(),
+ "skipping SFrame FDE; .cfi_escape with unknown effects");
----------------
Sterling-Augustine wrote:
Good catch.
Thinking about this even more, if the std::optional is empty, then the parser should have failed. So I think it should be switched to an assertion. Doing that instead.
https://github.com/llvm/llvm-project/pull/161927
More information about the llvm-commits
mailing list