34
34
#include " llvm/Support/FileSystem.h"
35
35
#include " llvm/Support/Path.h"
36
36
#include " llvm/Support/raw_ostream.h"
37
+ #include < map>
37
38
38
39
namespace fir {
39
40
#define GEN_PASS_DEF_ADDDEBUGINFO
@@ -48,10 +49,87 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {
48
49
public:
49
50
AddDebugInfoPass (fir::AddDebugInfoOptions options) : Base(options) {}
50
51
void runOnOperation () override ;
52
+
53
+ private:
54
+ std::map<std::string, mlir::LLVM::DIModuleAttr> moduleMap;
55
+
56
+ mlir::LLVM::DIModuleAttr getOrCreateModuleAttr (
57
+ const std::string &name, mlir::LLVM::DIFileAttr fileAttr,
58
+ mlir::LLVM::DIScopeAttr scope, unsigned line, bool decl);
59
+
60
+ void handleGlobalOp (fir::GlobalOp glocalOp, mlir::LLVM::DIFileAttr fileAttr,
61
+ mlir::LLVM::DIScopeAttr scope);
51
62
};
52
63
64
+ static uint32_t getLineFromLoc (mlir::Location loc) {
65
+ uint32_t line = 1 ;
66
+ if (auto fileLoc = mlir::dyn_cast<mlir::FileLineColLoc>(loc))
67
+ line = fileLoc.getLine ();
68
+ return line;
69
+ }
70
+
53
71
} // namespace
54
72
73
+ // The `module` does not have a first class representation in the `FIR`. We
74
+ // extract information about it from the name of the identifiers and keep a
75
+ // map to avoid duplication.
76
+ mlir::LLVM::DIModuleAttr AddDebugInfoPass::getOrCreateModuleAttr (
77
+ const std::string &name, mlir::LLVM::DIFileAttr fileAttr,
78
+ mlir::LLVM::DIScopeAttr scope, unsigned line, bool decl) {
79
+ mlir::MLIRContext *context = &getContext ();
80
+ mlir::LLVM::DIModuleAttr modAttr;
81
+ if (auto iter{moduleMap.find (name)}; iter != moduleMap.end ())
82
+ modAttr = iter->second ;
83
+ else {
84
+ modAttr = mlir::LLVM::DIModuleAttr::get (
85
+ context, fileAttr, scope, mlir::StringAttr::get (context, name),
86
+ mlir::StringAttr (), mlir::StringAttr (), mlir::StringAttr (), line, decl);
87
+ moduleMap[name] = modAttr;
88
+ }
89
+ return modAttr;
90
+ }
91
+
92
+ void AddDebugInfoPass::handleGlobalOp (fir::GlobalOp globalOp,
93
+ mlir::LLVM::DIFileAttr fileAttr,
94
+ mlir::LLVM::DIScopeAttr scope) {
95
+ mlir::ModuleOp module = getOperation ();
96
+ mlir::MLIRContext *context = &getContext ();
97
+ fir::DebugTypeGenerator typeGen (module );
98
+ mlir::OpBuilder builder (context);
99
+
100
+ auto result = fir::NameUniquer::deconstruct (globalOp.getSymName ());
101
+ if (result.first != fir::NameUniquer::NameKind::VARIABLE)
102
+ return ;
103
+
104
+ unsigned line = getLineFromLoc (globalOp.getLoc ());
105
+
106
+ // DWARF5 says following about the fortran modules:
107
+ // A Fortran 90 module may also be represented by a module entry
108
+ // (but no declaration attribute is warranted because Fortran has no concept
109
+ // of a corresponding module body).
110
+ // But in practice, compilers use declaration attribute with a module in cases
111
+ // where module was defined in another source file (only being used in this
112
+ // one). The hasInitializationBody() seems to provide the right information
113
+ // but inverted. It is true where module is actually defined but false where
114
+ // it is used.
115
+ // FIXME: Currently we don't have the line number on which a module was
116
+ // declared. We are using a best guess of line - 1 where line is the source
117
+ // line of the first member of the module that we encounter.
118
+
119
+ if (!result.second .modules .empty ())
120
+ scope = getOrCreateModuleAttr (result.second .modules [0 ], fileAttr, scope,
121
+ line - 1 , !globalOp.hasInitializationBody ());
122
+
123
+ auto diType = typeGen.convertType (globalOp.getType (), fileAttr, scope,
124
+ globalOp.getLoc ());
125
+ auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get (
126
+ context, scope, mlir::StringAttr::get (context, result.second .name ),
127
+ mlir::StringAttr::get (context, globalOp.getName ()), fileAttr, line,
128
+ diType, /* isLocalToUnit*/ false ,
129
+ /* isDefinition*/ globalOp.hasInitializationBody (), /* alignInBits*/ 0 );
130
+ globalOp->setLoc (builder.getFusedLoc ({globalOp->getLoc ()}, gvAttr));
131
+ }
132
+
55
133
void AddDebugInfoPass::runOnOperation () {
56
134
mlir::ModuleOp module = getOperation ();
57
135
mlir::MLIRContext *context = &getContext ();
@@ -91,6 +169,10 @@ void AddDebugInfoPass::runOnOperation() {
91
169
llvm::dwarf::getLanguage (" DW_LANG_Fortran95" ), fileAttr, producer,
92
170
isOptimized, debugLevel);
93
171
172
+ module .walk ([&](fir::GlobalOp globalOp) {
173
+ handleGlobalOp (globalOp, fileAttr, cuAttr);
174
+ });
175
+
94
176
module .walk ([&](mlir::func::FuncOp funcOp) {
95
177
mlir::Location l = funcOp->getLoc ();
96
178
// If fused location has already been created then nothing to do
@@ -131,8 +213,12 @@ void AddDebugInfoPass::runOnOperation() {
131
213
mlir::LLVM::DIFileAttr funcFileAttr =
132
214
mlir::LLVM::DIFileAttr::get (context, fileName, filePath);
133
215
216
+ unsigned line = 1 ;
217
+ if (auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l))
218
+ line = funcLoc.getLine ();
134
219
// Only definitions need a distinct identifier and a compilation unit.
135
220
mlir::DistinctAttr id;
221
+ mlir::LLVM::DIScopeAttr Scope = fileAttr;
136
222
mlir::LLVM::DICompileUnitAttr compilationUnit;
137
223
mlir::LLVM::DISubprogramFlags subprogramFlags =
138
224
mlir::LLVM::DISubprogramFlags{};
@@ -144,13 +230,13 @@ void AddDebugInfoPass::runOnOperation() {
144
230
subprogramFlags =
145
231
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
146
232
}
147
- unsigned line = 1 ;
148
- if ( auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l))
149
- line = funcLoc. getLine ( );
233
+ if (!result. second . modules . empty ())
234
+ Scope = getOrCreateModuleAttr (result. second . modules [ 0 ], fileAttr, cuAttr,
235
+ line - 1 , false );
150
236
151
237
auto spAttr = mlir::LLVM::DISubprogramAttr::get (
152
- context, id, compilationUnit, fileAttr , funcName, fullName,
153
- funcFileAttr, line, line, subprogramFlags, subTypeAttr);
238
+ context, id, compilationUnit, Scope , funcName, fullName, funcFileAttr ,
239
+ line, line, subprogramFlags, subTypeAttr);
154
240
funcOp->setLoc (builder.getFusedLoc ({funcOp->getLoc ()}, spAttr));
155
241
});
156
242
}
0 commit comments