[PATCH] D147506: [DebugLine] save one debug line entry for empty prologue
ChenZheng via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 26 07:53:33 PDT 2023
shchenz added a comment.
Like maybe recordSourceLine raises a flag and beginInstruction checks the flag, and if the flag is raised, it calls Asm.OutStreamer->emitDwarfLocDirective and lowers the flag. Then any redundant line directives aren't emitted, they are just overwritten.
Hi @dblaikie Sorry, I don't quite understand the method you suggested. Could you please share more details? And I am also sorry for the long comment...
I also tried a way in `recordSourceLine()` (See the code snippet at last), it can handle empty prologue case, but it can not handle non-empty prologue case now and I can not find a better way to fix this.
The truncated input for non-empty prologue case:
; Function Attrs: noinline nounwind optnone uwtable
define dso_local signext i32 @main() #0 !dbg !10 {
entry:
%retval = alloca i32, align 4 ;; prologue
store i32 0, ptr %retval, align 4 ;;prologue
ret i32 0, !dbg !15
}
main: # @main
.Lfunc_begin0:
.file 0 "empty_prologue" "1.c" md5 0xd1035b543709f23158df094b6d49742b
.cfi_startproc
# %bb.0: # %entry
li 3, 0
stw 3, -12(1)
.Ltmp0:
.loc 0 2 0 # 1.c:2:0 ######now the first line entry of the file is put after prologue instructions.
.loc 0 3 3 prologue_end # 1.c:3:3
li 3, 0
blr
The issue is for assembly code generation, we must emit the `.loc` once the `recordSourceLine()` is called, we can not delay it otherwise the `.loc` will be emitted in the wrong place like above case shows. `AsmPrinter::emitFunctionBody()` emits one instruction in each iteration while it iterates the instructions in a BB. The debug handler `DwarfDebug::beginInstruction()` must keep pace with `AsmPrinter::emitFunctionBody()`. Otherwise the `.loc` can not be emitted in the right place. I thought we can not change how we write the assembly file, it has to be written line by line, right?
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 98f24599970d..cd4dd504e1e8 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -2048,7 +2048,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
if ((LastAsmLine == 0 && DL.getLine() != 0) || Flags) {
// Reinstate the source location but not marked as a statement.
const MDNode *Scope = DL.getScope();
- recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
+ recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags, MI);
}
return;
}
@@ -2079,7 +2079,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
Scope = PrevInstLoc.getScope();
Column = PrevInstLoc.getCol();
}
- recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0);
+ recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0, MI);
}
return;
}
@@ -2091,7 +2091,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
return;
if (DL == PrologEndLoc) {
Flags |= DWARF2_FLAG_PROLOGUE_END | DWARF2_FLAG_IS_STMT;
- PrologEndLoc = DebugLoc();
+ //PrologEndLoc = DebugLoc();
}
// If the line changed, we call that a new statement; unless we went to
// line 0 and came back, in which case it is not a new statement.
@@ -2100,7 +2100,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
Flags |= DWARF2_FLAG_IS_STMT;
const MDNode *Scope = DL.getScope();
- recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
+ recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags, MI);
// If we're not at line 0, remember this location.
if (DL.getLine())
@@ -2128,28 +2128,6 @@ static DebugLoc findPrologueEndLoc(const MachineFunction *MF) {
return LineZeroLoc;
}
-/// Register a source line with debug info. Returns the unique label that was
-/// emitted and which provides correspondence to the source line list.
-static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col,
- const MDNode *S, unsigned Flags, unsigned CUID,
- uint16_t DwarfVersion,
- ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs) {
- StringRef Fn;
- unsigned FileNo = 1;
- unsigned Discriminator = 0;
- if (auto *Scope = cast_or_null<DIScope>(S)) {
- Fn = Scope->getFilename();
- if (Line != 0 && DwarfVersion >= 4)
- if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope))
- Discriminator = LBF->getDiscriminator();
-
- FileNo = static_cast<DwarfCompileUnit &>(*DCUs[CUID])
- .getOrCreateSourceID(Scope->getFile());
- }
- Asm.OutStreamer->emitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
- Discriminator, Fn);
-}
-
DebugLoc DwarfDebug::emitInitialLocDirective(const MachineFunction &MF,
unsigned CUID) {
// Get beginning of function.
@@ -2161,8 +2139,7 @@ DebugLoc DwarfDebug::emitInitialLocDirective(const MachineFunction &MF,
// We'd like to list the prologue as "not statements" but GDB behaves
// poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
const DISubprogram *SP = PrologEndLoc->getInlinedAtScope()->getSubprogram();
- ::recordSourceLine(*Asm, SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT,
- CUID, getDwarfVersion(), getUnits());
+ recordSourceLine(SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT);
return PrologEndLoc;
}
return DebugLoc();
@@ -2308,13 +2285,64 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
CurFn = nullptr;
}
-// Register a source line with debug info. Returns the unique label that was
+// Register a source line with debug info. Returns the unique label that was
// emitted and which provides correspondence to the source line list.
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
- unsigned Flags) {
- ::recordSourceLine(*Asm, Line, Col, S, Flags,
- Asm->OutStreamer->getContext().getDwarfCompileUnitID(),
- getDwarfVersion(), getUnits());
+ unsigned Flags, const MachineInstr *MI) {
+
+ auto EmitLoc = [&](unsigned Line, unsigned Col, const MDNode *S,
+ unsigned Flags) {
+ StringRef Fn;
+ unsigned FileNo = 1;
+ unsigned Discriminator = 0;
+ ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs = getUnits();
+ unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
+
+ if (auto *Scope = cast_or_null<DIScope>(S)) {
+ Fn = Scope->getFilename();
+ if (Line != 0 && getDwarfVersion() >= 4)
+ if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope))
+ Discriminator = LBF->getDiscriminator();
+
+ FileNo = static_cast<DwarfCompileUnit &>(*DCUs[CUID])
+ .getOrCreateSourceID(Scope->getFile());
+ }
+ Asm->OutStreamer->emitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
+ Discriminator, Fn);
+ };
+
+ // Before handling instructions, multiple debug lines may be recorded and
+ // these debug lines may have same addresses, for example the prologue is
+ // empty. Ignore these lines for now until we know what the prologue looks
+ // like.
+ if (!PrevInstLoc && !MI)
+ return;
+
+ // If the function's first instruction does not have debug loc info, prologue
+ // is not empty. Generate the line for the function start first before
+ // generating prologue end line.
+ if (!PrevInstLoc && MI && PrologEndLoc) {
+ const MachineInstr *FirstInstr =
+ [](const MachineInstr *MI) -> const MachineInstr * {
+ for (auto &BB : *MI->getParent()->getParent()) {
+ for (auto &I : BB) {
+ if (!I.isMetaInstruction())
+ return &I;
+ }
+ }
+ return nullptr;
+ }(MI);
+
+ if (FirstInstr && FirstInstr != MI) {
+ // FirstInstr must be in prologue.
+ const DISubprogram *SP =
+ PrologEndLoc->getInlinedAtScope()->getSubprogram();
+ EmitLoc(SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT);
+ }
+ PrologEndLoc = DebugLoc();
+ }
+
+ EmitLoc(Line, Col, S, Flags);
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 0e71c216e958..fdac1134abe7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -606,7 +606,7 @@ private:
/// label that was emitted and which provides correspondence to the
/// source line list.
void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope,
- unsigned Flags);
+ unsigned Flags, const MachineInstr *MI = nullptr);
/// Populate LexicalScope entries with variables' info.
void collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP,
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D147506/new/
https://reviews.llvm.org/D147506
More information about the llvm-commits
mailing list