[llvm] Parse CFI instructions to create SFrame FREs (PR #155496)

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 28 10:16:48 PDT 2025


================
@@ -88,13 +202,91 @@ class SFrameEmitterImpl {
                .has_value());
     FDEs.reserve(Streamer.getDwarfFrameInfos().size());
     SFrameABI = *Streamer.getContext().getObjectFileInfo()->getSFrameABIArch();
+    switch (SFrameABI) {
+    case ABI::AArch64EndianBig:
+    case ABI::AArch64EndianLittle:
+      SPReg = 31;
+      RAReg = 29;
+      FPReg = 30;
+      break;
+    case ABI::AMD64EndianLittle:
+      SPReg = 7;
+      // RARegister untracked in this abi. Value chosen to match
+      // MCDwarfFrameInfo constructor.
+      RAReg = static_cast<unsigned>(INT_MAX);
+      FPReg = 6;
+      break;
+    }
+
     FDESubSectionStart = Streamer.getContext().createTempSymbol();
     FRESubSectionStart = Streamer.getContext().createTempSymbol();
     FRESubSectionEnd = Streamer.getContext().createTempSymbol();
   }
 
-  void BuildSFDE(const MCDwarfFrameInfo &DF) {
-    FDEs.emplace_back(DF, Streamer.getContext().createTempSymbol());
+  bool atSameLocation(const MCSymbol *Left, const MCSymbol *Right) {
+    return Left != nullptr && Right != nullptr &&
+           Left->getFragment() == Right->getFragment() &&
+           Left->getOffset() == Right->getOffset();
+  }
+
+  bool equalIgnoringLocation(const SFrameFRE &Left, const SFrameFRE &Right) {
+    return Left.CfaOffset == Right.CfaOffset &&
+           Left.FPOffset == Right.FPOffset && Left.RAOffset == Right.RAOffset &&
+           Left.FromFP == Right.FromFP && Left.CfaRegSet == Right.CfaRegSet;
+  }
+
+  void buildSFDE(const MCDwarfFrameInfo &DF) {
+    auto &FDE = FDEs.emplace_back(DF, Streamer.getContext().createTempSymbol());
+    // This would have been set via ".cfi_return_column", but
+    // MCObjectStreamer doesn't emit an MCCFIInstruction for that. It just
+    // sets the DF.RAReg.
+    // FIXME: This also prevents providing a proper location for the error.
+    // LLVM doesn't change the return column itself, so this was
+    // hand-written assembly.
+    if (DF.RAReg != RAReg) {
+      Streamer.getContext().reportWarning(
+          SMLoc(), "Non-default RA register " + Twine(DF.RAReg) +
+                       ". Omitting SFrame unwind info for this function.");
+      // Continue with the FDE to find any addtional errors. Discard it at
+      // the end.
+      FDE.Invalid = true;
+    }
+    MCSymbol *BaseLabel = DF.Begin;
+    SFrameFRE BaseFRE(BaseLabel);
+    if (!DF.IsSimple) {
+      for (const auto &CFI :
+           Streamer.getContext().getAsmInfo()->getInitialFrameState())
+        handleCFI(FDE, BaseFRE, CFI);
+    }
+    FDE.FREs.push_back(BaseFRE);
+
+    for (const auto &CFI : DF.Instructions) {
+      // Instructions from InitialFrameState may not have a label, but if
+      // these instructions don't, then they are in dead code or otherwise
+      // unused.
+      auto *L = CFI.getLabel();
+      if (L && !L->isDefined())
+        continue;
+
+      SFrameFRE FRE = FDE.FREs.back();
+      handleCFI(FDE, FRE, CFI);
+
+      // If nothing relevant but the location changed, don't add the FRE.
+      if (equalIgnoringLocation(FRE, FDE.FREs.back()))
+        continue;
+
+      // If the location stayed the same, then update the current
+      // row. Otherwise, add a new one.
+      if (atSameLocation(BaseLabel, L))
+        FDE.FREs.back() = FRE;
+      else {
+        FDE.FREs.push_back(FRE);
+        FDE.FREs.back().Label = L;
+        BaseLabel = L;
+      }
+    }
+    if (FDE.Invalid)
----------------
labath wrote:

Sounds good.

https://github.com/llvm/llvm-project/pull/155496


More information about the llvm-commits mailing list