@@ -31,6 +31,14 @@ static FileLineColLoc extractFileLoc(Location loc) {
3131 return extractFileLoc (nameLoc.getChildLoc ());
3232 if (auto opaqueLoc = dyn_cast<OpaqueLoc>(loc))
3333 return extractFileLoc (opaqueLoc.getFallbackLocation ());
34+ if (auto fusedLoc = dyn_cast<FusedLoc>(loc)) {
35+ for (auto loc : fusedLoc.getLocations ()) {
36+ if (auto fileLoc = extractFileLoc (loc))
37+ return fileLoc;
38+ }
39+ }
40+ if (auto callerLoc = dyn_cast<CallSiteLoc>(loc))
41+ return extractFileLoc (callerLoc.getCaller ());
3442 return FileLineColLoc ();
3543}
3644
@@ -41,47 +49,84 @@ static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,
4149 LLVM::DICompileUnitAttr compileUnitAttr) {
4250
4351 Location loc = llvmFunc.getLoc ();
44- if (loc->findInstanceOf <mlir:: FusedLocWith<LLVM::DISubprogramAttr>>())
52+ if (loc->findInstanceOf <FusedLocWith<LLVM::DISubprogramAttr>>())
4553 return ;
4654
4755 MLIRContext *context = llvmFunc->getContext ();
4856
49- // Filename, line and colmun to associate to the function.
57+ // Filename and line associate to the function.
5058 LLVM::DIFileAttr fileAttr;
51- int64_t line = 1 , col = 1 ;
52- FileLineColLoc fileLoc = extractFileLoc (loc);
53- if (!fileLoc && compileUnitAttr) {
54- fileAttr = compileUnitAttr.getFile ();
55- } else if (!fileLoc) {
56- fileAttr = LLVM::DIFileAttr::get (context, " <unknown>" , " " );
57- } else {
59+ int64_t line = 1 ;
60+ if (FileLineColLoc fileLoc = extractFileLoc (loc)) {
5861 line = fileLoc.getLine ();
59- col = fileLoc.getColumn ();
6062 StringRef inputFilePath = fileLoc.getFilename ().getValue ();
6163 fileAttr =
6264 LLVM::DIFileAttr::get (context, llvm::sys::path::filename (inputFilePath),
6365 llvm::sys::path::parent_path (inputFilePath));
66+ } else {
67+ fileAttr = compileUnitAttr
68+ ? compileUnitAttr.getFile ()
69+ : LLVM::DIFileAttr::get (context, " <unknown>" , " " );
6470 }
6571 auto subroutineTypeAttr =
6672 LLVM::DISubroutineTypeAttr::get (context, llvm::dwarf::DW_CC_normal, {});
6773
68- // Only definitions need a distinct identifier and a compilation unit.
74+ // Figure out debug information (`subprogramFlags` and `compileUnitAttr`) to
75+ // attach to the function definition / declaration. External functions are
76+ // declarations only and are defined in a different compile unit, so mark
77+ // them appropriately in `subprogramFlags` and set an empty `compileUnitAttr`.
6978 DistinctAttr id;
7079 auto subprogramFlags = LLVM::DISubprogramFlags::Optimized;
7180 if (!llvmFunc.isExternal ()) {
72- id = mlir:: DistinctAttr::create (mlir:: UnitAttr::get (context));
81+ id = DistinctAttr::create (UnitAttr::get (context));
7382 subprogramFlags = subprogramFlags | LLVM::DISubprogramFlags::Definition;
7483 } else {
7584 compileUnitAttr = {};
7685 }
77- auto funcName = StringAttr::get (context, llvmFunc.getName () );
86+ auto funcNameAttr = llvmFunc.getNameAttr ( );
7887 auto subprogramAttr = LLVM::DISubprogramAttr::get (
79- context, id, compileUnitAttr, fileAttr, funcName, funcName, fileAttr,
80- /* line=*/ line, /* scopeline=*/ col, subprogramFlags, subroutineTypeAttr,
88+ context, id, compileUnitAttr, fileAttr, funcNameAttr, funcNameAttr,
89+ fileAttr,
90+ /* line=*/ line, /* scopeLine=*/ line, subprogramFlags, subroutineTypeAttr,
8191 /* retainedNodes=*/ {}, /* annotations=*/ {});
8292 llvmFunc->setLoc (FusedLoc::get (context, {loc}, subprogramAttr));
8393}
8494
95+ // Get a nested loc for inlined functions.
96+ static Location getNestedLoc (Operation *op, LLVM::DIScopeAttr scopeAttr,
97+ Location calleeLoc) {
98+ auto calleeFileName = extractFileLoc (calleeLoc).getFilename ();
99+ auto *context = op->getContext ();
100+ LLVM::DIFileAttr calleeFileAttr =
101+ LLVM::DIFileAttr::get (context, llvm::sys::path::filename (calleeFileName),
102+ llvm::sys::path::parent_path (calleeFileName));
103+ auto lexicalBlockFileAttr = LLVM::DILexicalBlockFileAttr::get (
104+ context, scopeAttr, calleeFileAttr, /* discriminator=*/ 0 );
105+ Location loc = calleeLoc;
106+ // Recurse if the callee location is again a call site.
107+ if (auto callSiteLoc = dyn_cast<CallSiteLoc>(calleeLoc)) {
108+ auto nestedLoc = callSiteLoc.getCallee ();
109+ loc = getNestedLoc (op, lexicalBlockFileAttr, nestedLoc);
110+ }
111+ return FusedLoc::get (context, {loc}, lexicalBlockFileAttr);
112+ }
113+
114+ static void setLexicalBlockFileAttr (Operation *op) {
115+ if (auto callSiteLoc = dyn_cast<CallSiteLoc>(op->getLoc ())) {
116+ auto callerLoc = callSiteLoc.getCaller ();
117+ auto calleeLoc = callSiteLoc.getCallee ();
118+ LLVM::DIScopeAttr scopeAttr;
119+ // We assemble the full inline stack so the parent of this loc must be a
120+ // function
121+ auto funcOp = op->getParentOfType <LLVM::LLVMFuncOp>();
122+ if (auto funcOpLoc = llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc ())) {
123+ scopeAttr = cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata ());
124+ op->setLoc (
125+ CallSiteLoc::get (getNestedLoc (op, scopeAttr, calleeLoc), callerLoc));
126+ }
127+ }
128+ }
129+
85130namespace {
86131// / Add a debug info scope to LLVMFuncOp that are missing it.
87132struct DIScopeForLLVMFuncOpPass
@@ -99,15 +144,12 @@ struct DIScopeForLLVMFuncOpPass
99144 return signalPassFailure ();
100145 }
101146
102- // To find a DICompileUnitAttr attached to a parent (the module for
103- // example), otherwise create a default one.
104- // Find a DICompileUnitAttr attached to the module, otherwise create a
105- // default one.
147+ // Find a DICompileUnitAttr attached to a parent (the module for example),
148+ // otherwise create a default one.
106149 LLVM::DICompileUnitAttr compileUnitAttr;
107- auto fusedCompileUnitAttr =
108- module ->getLoc ()
109- ->findInstanceOf <mlir::FusedLocWith<LLVM::DICompileUnitAttr>>();
110- if (fusedCompileUnitAttr) {
150+ if (auto fusedCompileUnitAttr =
151+ module ->getLoc ()
152+ ->findInstanceOf <FusedLocWith<LLVM::DICompileUnitAttr>>()) {
111153 compileUnitAttr = fusedCompileUnitAttr.getMetadata ();
112154 } else {
113155 LLVM::DIFileAttr fileAttr;
@@ -126,9 +168,14 @@ struct DIScopeForLLVMFuncOpPass
126168 /* isOptimized=*/ true , emissionKind);
127169 }
128170
129- // Create subprograms for each function with the same distinct compile unit.
130- module .walk ([&](LLVM::LLVMFuncOp func) {
131- addScopeToFunction (func, compileUnitAttr);
171+ module .walk <WalkOrder::PreOrder>([&](Operation *op) -> void {
172+ if (auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(op)) {
173+ // Create subprograms for each function with the same distinct compile
174+ // unit.
175+ addScopeToFunction (funcOp, compileUnitAttr);
176+ } else {
177+ setLexicalBlockFileAttr (op);
178+ }
132179 });
133180 }
134181};
0 commit comments