llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-mc Author: Alexander Richardson (arichardson) <details> <summary>Changes</summary> This adds a new --show-source-loc flag (and -asm-show-source-loc MCTargetOption) to llvm-mc, which emits source location comments (`# <SourceLoc: filename:line:col>`). When instructions originate from macro expansions, llvm-mc unwinds the instantiation stack, emitting intermediate expansion layers as `# <MacroLoc: filename:line:col>` and reporting the top-level macro invocation in `SourceLoc`. For .include directives, it also emits `# <IncludeLoc: filename:line:col>` to report the include stack. The main motivation for this feature is improving update_mc_test_checks.py to cleanly map output instructions back to input lines, enabling automated test updates for assembly files that include directives like .ifdef or macros. Assisted-By: Gemini --- Full diff: https://github.com/llvm/llvm-project/pull/199298.diff 12 Files Affected: - (modified) llvm/include/llvm/MC/MCTargetOptions.h (+1) - (modified) llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h (+1) - (modified) llvm/include/llvm/Support/SourceMgr.h (+1-1) - (modified) llvm/lib/MC/MCAsmStreamer.cpp (+38) - (modified) llvm/lib/MC/MCTargetOptions.cpp (+3-3) - (modified) llvm/lib/MC/MCTargetOptionsCommandFlags.cpp (+7) - (modified) llvm/lib/Support/SourceMgr.cpp (+1-1) - (added) llvm/test/tools/llvm-mc/Inputs/show-source-loc.inc (+5) - (added) llvm/test/tools/llvm-mc/disassemble-show-source-loc.s (+9) - (added) llvm/test/tools/llvm-mc/show-source-loc.s (+52) - (modified) llvm/tools/llvm-mc/Disassembler.cpp (+1) - (modified) llvm/tools/llvm-mc/llvm-mc.cpp (+6) ``````````diff diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h index 2f24608b5f6ba..52ae464a8b91d 100644 --- a/llvm/include/llvm/MC/MCTargetOptions.h +++ b/llvm/include/llvm/MC/MCTargetOptions.h @@ -52,6 +52,7 @@ class MCTargetOptions { bool FDPIC : 1; bool ShowMCEncoding : 1; bool ShowMCInst : 1; + bool ShowMCInstSourceLoc : 1; bool AsmVerbose : 1; /// Preserve Comments in Assembly. diff --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h index ae80887900349..b9ddeeec4f537 100644 --- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -45,6 +45,7 @@ LLVM_ABI bool getEmitCompactUnwindNonCanonical(); LLVM_ABI bool getEmitSFrameUnwind(); LLVM_ABI bool getShowMCInst(); +LLVM_ABI bool getShowMCInstSourceLoc(); LLVM_ABI bool getFatalWarnings(); diff --git a/llvm/include/llvm/Support/SourceMgr.h b/llvm/include/llvm/Support/SourceMgr.h index 83cb3de26453a..6157213c4b870 100644 --- a/llvm/include/llvm/Support/SourceMgr.h +++ b/llvm/include/llvm/Support/SourceMgr.h @@ -263,7 +263,7 @@ class SourceMgr { /// Given a line and column number in a mapped buffer, turn it into an SMLoc. /// This will return a null SMLoc if the line/column location is invalid. LLVM_ABI SMLoc FindLocForLineAndColumn(unsigned BufferID, unsigned LineNo, - unsigned ColNo); + unsigned ColNo) const; /// Emit a message about the specified location with the specified string. /// diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 05e3dc28a502b..c279dab35d0a5 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -37,6 +37,7 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" +#include "llvm/Support/SourceMgr.h" #include <algorithm> #include <optional> @@ -60,6 +61,7 @@ class MCAsmStreamer final : public MCAsmBaseStreamer { bool IsVerboseAsm = false; bool ShowInst = false; + bool ShowInstSourceLoc = false; bool UseDwarfDirectory = false; void EmitRegisterName(int64_t Register); @@ -107,6 +109,7 @@ class MCAsmStreamer final : public MCAsmBaseStreamer { if (IsVerboseAsm) InstPrinter->setCommentStream(CommentStream); ShowInst = TO.ShowMCInst; + ShowInstSourceLoc = TO.ShowMCInstSourceLoc; switch (TO.MCUseDwarfDirectory) { case MCTargetOptions::DisableDwarfDirectory: UseDwarfDirectory = false; @@ -2624,6 +2627,41 @@ void MCAsmStreamer::emitInstruction(const MCInst &Inst, getCommentOS() << "\n"; EmitEOL(); + + if (ShowInstSourceLoc && Inst.getLoc().isValid()) { + if (const SourceMgr *SM = getContext().getSourceManager()) { + SMLoc Loc = Inst.getLoc(); + unsigned BufID = SM->FindBufferContainingLoc(Loc); + bool PrintedSourceLoc = false; + + auto PrintLoc = [&](StringRef Type, SMLoc L, unsigned Buf) { + StringRef Filename = SM->getMemoryBuffer(Buf)->getBufferIdentifier(); + std::pair<unsigned, unsigned> LineCol = SM->getLineAndColumn(L, Buf); + OS << MAI->getCommentString() << " <" << Type << ": " << Filename + << ":" << LineCol.first << ":" << LineCol.second << ">\n"; + }; + + // Unwind the macro expansion and inclusion stacks. + while (BufID) { + SMLoc ParentLoc = SM->getParentIncludeLoc(BufID); + if (SMLoc DefLoc = SM->getMacroDefLoc(BufID); DefLoc.isValid()) { + PrintLoc("MacroLoc", DefLoc, SM->FindBufferContainingLoc(DefLoc)); + } else { + // First location is the SourceLoc, all others are include stack + if (!PrintedSourceLoc) { + PrintLoc("SourceLoc", Loc, BufID); + PrintedSourceLoc = true; + } else { + PrintLoc("IncludeLoc", Loc, BufID); + } + } + // Move up to the parent context (the macro call site or the include site) + // for the next iteration of the stack unwinding. + Loc = ParentLoc; + BufID = Loc.isValid() ? SM->FindBufferContainingLoc(Loc) : 0; + } + } + } } void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index, diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp index be6d19d111620..daf7ccece36c7 100644 --- a/llvm/lib/MC/MCTargetOptions.cpp +++ b/llvm/lib/MC/MCTargetOptions.cpp @@ -15,9 +15,9 @@ MCTargetOptions::MCTargetOptions() : MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false), MCNoWarn(false), MCNoDeprecatedWarn(false), MCNoTypeCheck(false), MCSaveTempLabels(false), MCIncrementalLinkerCompatible(false), - FDPIC(false), ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false), - PreserveAsmComments(true), Dwarf64(false), - EmitDwarfUnwind(EmitDwarfUnwindType::Default), + FDPIC(false), ShowMCEncoding(false), ShowMCInst(false), + ShowMCInstSourceLoc(false), AsmVerbose(false), PreserveAsmComments(true), + Dwarf64(false), EmitDwarfUnwind(EmitDwarfUnwindType::Default), MCUseDwarfDirectory(DefaultDwarfDirectory), EmitCompactUnwindNonCanonical(false), EmitSFrameUnwind(false), PPCUseFullRegisterNames(false) {} diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp index 359c1bceb25b1..a80af06837b06 100644 --- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp +++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp @@ -50,6 +50,7 @@ MCOPT(EmitDwarfUnwindType, EmitDwarfUnwind) MCOPT(bool, EmitCompactUnwindNonCanonical) MCOPT(bool, EmitSFrameUnwind) MCOPT(bool, ShowMCInst) +MCOPT(bool, ShowMCInstSourceLoc) MCOPT(bool, FatalWarnings) MCOPT(bool, NoWarn) MCOPT(bool, NoDeprecatedWarn) @@ -124,6 +125,11 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() { cl::desc("Emit internal instruction representation to assembly file")); MCBINDOPT(ShowMCInst); + static cl::opt<bool> ShowMCInstSourceLoc( + "asm-show-source-loc", + cl::desc("Emit source locations of instructions to assembly file")); + MCBINDOPT(ShowMCInstSourceLoc); + static cl::opt<bool> FatalWarnings("fatal-warnings", cl::desc("Treat warnings as errors")); MCBINDOPT(FatalWarnings); @@ -203,6 +209,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() { Options.Dwarf64 = getDwarf64(); Options.DwarfVersion = getDwarfVersion(); Options.ShowMCInst = getShowMCInst(); + Options.ShowMCInstSourceLoc = getShowMCInstSourceLoc(); Options.ABIName = getABIName(); Options.MCFatalWarnings = getFatalWarnings(); Options.MCNoWarn = getNoWarn(); diff --git a/llvm/lib/Support/SourceMgr.cpp b/llvm/lib/Support/SourceMgr.cpp index 62fce28486d4a..66cee9ac28f03 100644 --- a/llvm/lib/Support/SourceMgr.cpp +++ b/llvm/lib/Support/SourceMgr.cpp @@ -259,7 +259,7 @@ std::string SourceMgr::getFormattedLocationNoOffset(SMLoc Loc, /// Given a line and column number in a mapped buffer, turn it into an SMLoc. /// This will return a null SMLoc if the line/column location is invalid. SMLoc SourceMgr::FindLocForLineAndColumn(unsigned BufferID, unsigned LineNo, - unsigned ColNo) { + unsigned ColNo) const { auto &SB = getBufferInfo(BufferID); const char *Ptr = SB.getPointerForLineNumber(LineNo); if (!Ptr) diff --git a/llvm/test/tools/llvm-mc/Inputs/show-source-loc.inc b/llvm/test/tools/llvm-mc/Inputs/show-source-loc.inc new file mode 100644 index 0000000000000..58e7a9628156d --- /dev/null +++ b/llvm/test/tools/llvm-mc/Inputs/show-source-loc.inc @@ -0,0 +1,5 @@ +xorl %ecx, %ecx + +.macro inc_macro reg + incl \reg +.endm diff --git a/llvm/test/tools/llvm-mc/disassemble-show-source-loc.s b/llvm/test/tools/llvm-mc/disassemble-show-source-loc.s new file mode 100644 index 0000000000000..31c9fc8a5bd59 --- /dev/null +++ b/llvm/test/tools/llvm-mc/disassemble-show-source-loc.s @@ -0,0 +1,9 @@ +# RUN: llvm-mc -triple=x86_64 -disassemble -show-source-loc %s | FileCheck %s + +# CHECK: nop +# CHECK-NEXT: # <SourceLoc: {{.*}}disassemble-show-source-loc.s:5:1> +0x90 + +# CHECK: xorl %ecx, %ecx +# CHECK-NEXT: # <SourceLoc: {{.*}}disassemble-show-source-loc.s:9:1> +0x31 0xc9 diff --git a/llvm/test/tools/llvm-mc/show-source-loc.s b/llvm/test/tools/llvm-mc/show-source-loc.s new file mode 100644 index 0000000000000..1fe06f2b87ed6 --- /dev/null +++ b/llvm/test/tools/llvm-mc/show-source-loc.s @@ -0,0 +1,52 @@ +# RUN: llvm-mc -triple=x86_64 -show-source-loc %s -I %S/Inputs +# RUN: llvm-mc -triple=x86_64 -show-source-loc %s -I %S/Inputs | FileCheck %s + +## Check that -show-source-loc emits <SourceLoc: ...> comments after instructions. + +.macro inner_macro reg1, reg2 + addl \reg1, \reg2 + subl \reg2, \reg1 +.endm + +.macro outer_macro r1, r2 + inner_macro \r1, \r2 +.endm + +## Standard instructions report their exact line number. +nop +# CHECK: nop +# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-2]]:1> + +## Nested macro expansion reports the full expansion stack. +outer_macro %eax, %ebx +# CHECK: addl %eax, %ebx +# CHECK-NEXT: # <MacroLoc: {{.*}}show-source-loc.s:6:1> +# CHECK-NEXT: # <MacroLoc: {{.*}}show-source-loc.s:11:1> +# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-4]]:1> +# CHECK: subl %ebx, %eax +# CHECK-NEXT: # <MacroLoc: {{.*}}show-source-loc.s:6:1> +# CHECK-NEXT: # <MacroLoc: {{.*}}show-source-loc.s:11:1> +# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-8]]:1> + +## .include reports the include file location and the .include directive location. +.include "show-source-loc.inc" +# CHECK: xorl %ecx, %ecx +# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.inc:1:1> +# CHECK-NEXT: # <IncludeLoc: {{.*}}show-source-loc.s:[[#@LINE-3]]:31> + +## Macro defined in an include file. +inc_macro %edx +# CHECK: incl %edx +# CHECK-NEXT: # <MacroLoc: {{.*}}show-source-loc.inc:3:1> +# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-3]]:1> + +## Indefinite repeat block (.irp). +.irp reg, %esi, %edi + incl \reg +.endr +# CHECK: incl %esi +# CHECK-NEXT: # <MacroLoc: {{.*}}show-source-loc.s:44:1> +# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-5]]:1> +# CHECK: incl %edi +# CHECK-NEXT: # <MacroLoc: {{.*}}show-source-loc.s:44:1> +# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-8]]:1> diff --git a/llvm/tools/llvm-mc/Disassembler.cpp b/llvm/tools/llvm-mc/Disassembler.cpp index 9a61f68b12d31..55ab78ddefe42 100644 --- a/llvm/tools/llvm-mc/Disassembler.cpp +++ b/llvm/tools/llvm-mc/Disassembler.cpp @@ -77,6 +77,7 @@ static bool printInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes, [[fallthrough]]; case MCDisassembler::Success: + Inst.setLoc(SMLoc::getFromPointer(Bytes.second[Index])); Streamer.emitInstruction(Inst, STI); break; } diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index 903f82e6855ba..afbd861b91b81 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -86,6 +86,11 @@ static cl::opt<bool> ShowInst("show-inst", cl::desc("Show internal instruction representation"), cl::cat(MCCategory)); +static cl::opt<bool> + ShowSourceLoc("show-source-loc", + cl::desc("Show source location of instructions"), + cl::cat(MCCategory)); + static cl::opt<bool> ShowInstOperands("show-inst-operands", cl::desc("Show instructions operands as parsed"), @@ -409,6 +414,7 @@ int main(int argc, char **argv) { MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags(); MCOptions.CompressDebugSections = CompressDebugSections.getValue(); MCOptions.ShowMCInst = ShowInst; + MCOptions.ShowMCInstSourceLoc = ShowSourceLoc; MCOptions.AsmVerbose = true; MCOptions.MCNoExecStack = NoExecStack; MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory; `````````` </details> https://github.com/llvm/llvm-project/pull/199298 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
