@@ -31,6 +31,14 @@ static FileLineColLoc extractFileLoc(Location loc) {
31
31
return extractFileLoc (nameLoc.getChildLoc ());
32
32
if (auto opaqueLoc = dyn_cast<OpaqueLoc>(loc))
33
33
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 ());
34
42
return FileLineColLoc ();
35
43
}
36
44
@@ -41,47 +49,84 @@ static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,
41
49
LLVM::DICompileUnitAttr compileUnitAttr) {
42
50
43
51
Location loc = llvmFunc.getLoc ();
44
- if (loc->findInstanceOf <mlir:: FusedLocWith<LLVM::DISubprogramAttr>>())
52
+ if (loc->findInstanceOf <FusedLocWith<LLVM::DISubprogramAttr>>())
45
53
return ;
46
54
47
55
MLIRContext *context = llvmFunc->getContext ();
48
56
49
- // Filename, line and colmun to associate to the function.
57
+ // Filename and line associate to the function.
50
58
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)) {
58
61
line = fileLoc.getLine ();
59
- col = fileLoc.getColumn ();
60
62
StringRef inputFilePath = fileLoc.getFilename ().getValue ();
61
63
fileAttr =
62
64
LLVM::DIFileAttr::get (context, llvm::sys::path::filename (inputFilePath),
63
65
llvm::sys::path::parent_path (inputFilePath));
66
+ } else {
67
+ fileAttr = compileUnitAttr
68
+ ? compileUnitAttr.getFile ()
69
+ : LLVM::DIFileAttr::get (context, " <unknown>" , " " );
64
70
}
65
71
auto subroutineTypeAttr =
66
72
LLVM::DISubroutineTypeAttr::get (context, llvm::dwarf::DW_CC_normal, {});
67
73
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`.
69
78
DistinctAttr id;
70
79
auto subprogramFlags = LLVM::DISubprogramFlags::Optimized;
71
80
if (!llvmFunc.isExternal ()) {
72
- id = mlir:: DistinctAttr::create (mlir:: UnitAttr::get (context));
81
+ id = DistinctAttr::create (UnitAttr::get (context));
73
82
subprogramFlags = subprogramFlags | LLVM::DISubprogramFlags::Definition;
74
83
} else {
75
84
compileUnitAttr = {};
76
85
}
77
- auto funcName = StringAttr::get (context, llvmFunc.getName () );
86
+ auto funcNameAttr = llvmFunc.getNameAttr ( );
78
87
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,
81
91
/* retainedNodes=*/ {}, /* annotations=*/ {});
82
92
llvmFunc->setLoc (FusedLoc::get (context, {loc}, subprogramAttr));
83
93
}
84
94
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
+
85
130
namespace {
86
131
// / Add a debug info scope to LLVMFuncOp that are missing it.
87
132
struct DIScopeForLLVMFuncOpPass
@@ -99,15 +144,12 @@ struct DIScopeForLLVMFuncOpPass
99
144
return signalPassFailure ();
100
145
}
101
146
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.
106
149
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>>()) {
111
153
compileUnitAttr = fusedCompileUnitAttr.getMetadata ();
112
154
} else {
113
155
LLVM::DIFileAttr fileAttr;
@@ -126,9 +168,14 @@ struct DIScopeForLLVMFuncOpPass
126
168
/* isOptimized=*/ true , emissionKind);
127
169
}
128
170
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
+ }
132
179
});
133
180
}
134
181
};
0 commit comments