[llvm-mc] Add --show-source-loc option to emit source locations#199298
Conversation
Created using spr 1.3.8-beta.1
|
This is a stacked pull request managed by spr. The following pull requests must be merged before this one: |
|
@llvm/pr-subscribers-llvm-support Author: Alexander Richardson (arichardson) ChangesThis adds a new --show-source-loc flag (and -asm-show-source-loc The main motivation for this feature is improving Assisted-By: Gemini Full diff: https://github.com/llvm/llvm-project/pull/199298.diff 12 Files Affected:
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;
|
|
@llvm/pr-subscribers-llvm-mc Author: Alexander Richardson (arichardson) ChangesThis adds a new --show-source-loc flag (and -asm-show-source-loc The main motivation for this feature is improving Assisted-By: Gemini Full diff: https://github.com/llvm/llvm-project/pull/199298.diff 12 Files Affected:
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;
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
|
How does this work with |
This is only emitted as part of the instruction emission, so it will emit source locations for the ones that are a active branches. I will extend the test to show this behaviour. |
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 Pull Request: llvm#199298
Created using spr 1.3.8-beta.1
🐧 Linux x64 Test Results
Failed Tests(click on a test name to see its output) LLVMLLVM.tools/llvm-symbolizer/wasm-basic.s (Likely Already Failing)This test is already failing at the base commit.If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
🪟 Windows x64 Test Results
Failed Tests(click on a test name to see its output) LLVMLLVM.tools/llvm-symbolizer/wasm-basic.sIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
Created using spr 1.3.8-beta.1
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-levelmacro 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