[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