[llvm-branch-commits] [llvm] [llvm-mc] Add --show-source-loc option to emit source locations (PR #198231)
Alexander Richardson via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri May 22 16:18:33 PDT 2026
https://github.com/arichardson updated https://github.com/llvm/llvm-project/pull/198231
>From c9a79d5943619dc537a4376ca96f4cac4d603611 Mon Sep 17 00:00:00 2001
From: Alex Richardson <alexrichardson at google.com>
Date: Sun, 17 May 2026 22:07:52 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.8-beta.1
---
llvm/include/llvm/MC/MCTargetOptions.h | 1 +
.../llvm/MC/MCTargetOptionsCommandFlags.h | 1 +
llvm/lib/MC/MCAsmStreamer.cpp | 40 +++++++++++++++
llvm/lib/MC/MCParser/AsmParser.cpp | 4 +-
llvm/lib/MC/MCTargetOptions.cpp | 6 +--
llvm/lib/MC/MCTargetOptionsCommandFlags.cpp | 7 +++
.../tools/llvm-mc/Inputs/show-source-loc.inc | 5 ++
llvm/test/tools/llvm-mc/show-source-loc.s | 51 +++++++++++++++++++
llvm/tools/llvm-mc/llvm-mc.cpp | 6 +++
9 files changed, 116 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/tools/llvm-mc/Inputs/show-source-loc.inc
create mode 100644 llvm/test/tools/llvm-mc/show-source-loc.s
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/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 05e3dc28a502b..d12da51065bb1 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,43 @@ 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;
+ // Walk the SourceMgr buffer stack to emit full source location
+ // information. When AsmParser instantiates a macro, it creates a buffer
+ // named "<instantiation>" and attaches the macro call location as its
+ // IncludeLoc. Therefore, walking IncludeLoc cleanly unwinds the macro
+ // expansion stack (emitted as ExpansionLoc) until it reaches the actual
+ // source file (emitted as SourceLoc). Any further IncludeLoc parents
+ // beyond that point represent actual .include directives (emitted as
+ // IncludeLoc).
+ while (BufID) {
+ StringRef Filename =
+ SM->getBufferInfo(BufID).Buffer->getBufferIdentifier();
+ std::pair<unsigned, unsigned> LineCol =
+ SM->getLineAndColumn(Loc, BufID);
+
+ if (Filename == "<instantiation>") {
+ OS << MAI->getCommentString() << " <ExpansionLoc: " << Filename << ":"
+ << LineCol.first << ":" << LineCol.second << ">\n";
+ } else if (!PrintedSourceLoc) {
+ OS << MAI->getCommentString() << " <SourceLoc: " << Filename << ":"
+ << LineCol.first << ":" << LineCol.second << ">\n";
+ PrintedSourceLoc = true;
+ } else {
+ OS << MAI->getCommentString() << " <IncludeLoc: " << Filename << ":"
+ << LineCol.first << ":" << LineCol.second << ">\n";
+ }
+
+ Loc = SM->getBufferInfo(BufID).IncludeLoc;
+ BufID = Loc.isValid() ? SM->FindBufferContainingLoc(Loc) : 0;
+ }
+ }
+ }
}
void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 80003c8331b82..74eaf2ae8a994 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -2864,7 +2864,7 @@ bool AsmParser::handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc) {
++NumOfMacroInstantiations;
// Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), NameLoc);
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
Lex();
@@ -5798,7 +5798,7 @@ void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
ActiveMacros.push_back(MI);
// Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), DirectiveLoc);
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
Lex();
}
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/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/show-source-loc.s b/llvm/test/tools/llvm-mc/show-source-loc.s
new file mode 100644
index 0000000000000..34da2b3039930
--- /dev/null
+++ b/llvm/test/tools/llvm-mc/show-source-loc.s
@@ -0,0 +1,51 @@
+# 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: # <ExpansionLoc: <instantiation>:1:1>
+# CHECK-NEXT: # <ExpansionLoc: <instantiation>:1:1>
+# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-4]]:1>
+# CHECK: subl %ebx, %eax
+# CHECK-NEXT: # <ExpansionLoc: <instantiation>:2:3>
+# CHECK-NEXT: # <ExpansionLoc: <instantiation>:1: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: # <ExpansionLoc: <instantiation>:1: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: # <ExpansionLoc: <instantiation>:1:1>
+# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-5]]:1>
+# CHECK: incl %edi
+# CHECK-NEXT: # <ExpansionLoc: <instantiation>:2:1>
+# CHECK-NEXT: # <SourceLoc: {{.*}}show-source-loc.s:[[#@LINE-8]]:1>
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;
More information about the llvm-branch-commits
mailing list