xref: /llvm-project/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp (revision afa4681ce443e88a5f196b808300fe3c133e96fd)
17740e933Sabidh //===-------------- AddDebugInfo.cpp -- add debug info -------------------===//
27740e933Sabidh //
37740e933Sabidh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47740e933Sabidh // See https://llvm.org/LICENSE.txt for license information.
57740e933Sabidh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67740e933Sabidh //
77740e933Sabidh //===----------------------------------------------------------------------===//
87740e933Sabidh 
97740e933Sabidh //===----------------------------------------------------------------------===//
107740e933Sabidh /// \file
117740e933Sabidh /// This pass populates some debug information for the module and functions.
127740e933Sabidh //===----------------------------------------------------------------------===//
137740e933Sabidh 
1491a8cb78SAbid Qadeer #include "DebugTypeGenerator.h"
155f3f9d1aSAbid Qadeer #include "flang/Common/Version.h"
167740e933Sabidh #include "flang/Optimizer/Builder/FIRBuilder.h"
177740e933Sabidh #include "flang/Optimizer/Builder/Todo.h"
18cd5ee271SAbid Qadeer #include "flang/Optimizer/CodeGen/CGOps.h"
197740e933Sabidh #include "flang/Optimizer/Dialect/FIRDialect.h"
207740e933Sabidh #include "flang/Optimizer/Dialect/FIROps.h"
21f6f4c177STom Eccles #include "flang/Optimizer/Dialect/FIROpsSupport.h"
227740e933Sabidh #include "flang/Optimizer/Dialect/FIRType.h"
237740e933Sabidh #include "flang/Optimizer/Dialect/Support/FIRContext.h"
245f3f9d1aSAbid Qadeer #include "flang/Optimizer/Support/InternalNames.h"
257740e933Sabidh #include "flang/Optimizer/Transforms/Passes.h"
267740e933Sabidh #include "mlir/Dialect/Func/IR/FuncOps.h"
277740e933Sabidh #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
287740e933Sabidh #include "mlir/IR/Matchers.h"
297740e933Sabidh #include "mlir/IR/TypeUtilities.h"
307740e933Sabidh #include "mlir/Pass/Pass.h"
317740e933Sabidh #include "mlir/Transforms/DialectConversion.h"
327740e933Sabidh #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
337740e933Sabidh #include "mlir/Transforms/RegionUtils.h"
347740e933Sabidh #include "llvm/BinaryFormat/Dwarf.h"
357740e933Sabidh #include "llvm/Support/Debug.h"
365f3f9d1aSAbid Qadeer #include "llvm/Support/FileSystem.h"
377740e933Sabidh #include "llvm/Support/Path.h"
387740e933Sabidh #include "llvm/Support/raw_ostream.h"
397740e933Sabidh 
407740e933Sabidh namespace fir {
417740e933Sabidh #define GEN_PASS_DEF_ADDDEBUGINFO
427740e933Sabidh #include "flang/Optimizer/Transforms/Passes.h.inc"
437740e933Sabidh } // namespace fir
447740e933Sabidh 
456d9ee885Sabidh #define DEBUG_TYPE "flang-add-debug-info"
467740e933Sabidh 
477740e933Sabidh namespace {
487740e933Sabidh 
497740e933Sabidh class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {
50cd5ee271SAbid Qadeer   void handleDeclareOp(fir::cg::XDeclareOp declOp,
51cd5ee271SAbid Qadeer                        mlir::LLVM::DIFileAttr fileAttr,
52cd5ee271SAbid Qadeer                        mlir::LLVM::DIScopeAttr scopeAttr,
5320c6b9fbSAbid Qadeer                        fir::DebugTypeGenerator &typeGen,
5420c6b9fbSAbid Qadeer                        mlir::SymbolTable *symbolTable);
55cd5ee271SAbid Qadeer 
567740e933Sabidh public:
575f3f9d1aSAbid Qadeer   AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {}
587740e933Sabidh   void runOnOperation() override;
59f156b9ceSAbid Qadeer 
60f156b9ceSAbid Qadeer private:
61f156b9ceSAbid Qadeer   llvm::StringMap<mlir::LLVM::DIModuleAttr> moduleMap;
62*afa4681cSAbid Qadeer   llvm::StringMap<mlir::LLVM::DICommonBlockAttr> commonBlockMap;
63*afa4681cSAbid Qadeer   // List of GlobalVariableExpressionAttr that are attached to a given global
64*afa4681cSAbid Qadeer   // that represents the storage for common block.
65*afa4681cSAbid Qadeer   llvm::DenseMap<fir::GlobalOp, llvm::SmallVector<mlir::Attribute>>
66*afa4681cSAbid Qadeer       globalToGlobalExprsMap;
67f156b9ceSAbid Qadeer 
68f156b9ceSAbid Qadeer   mlir::LLVM::DIModuleAttr getOrCreateModuleAttr(
69f156b9ceSAbid Qadeer       const std::string &name, mlir::LLVM::DIFileAttr fileAttr,
70f156b9ceSAbid Qadeer       mlir::LLVM::DIScopeAttr scope, unsigned line, bool decl);
71*afa4681cSAbid Qadeer   mlir::LLVM::DICommonBlockAttr
72*afa4681cSAbid Qadeer   getOrCreateCommonBlockAttr(llvm::StringRef name,
73*afa4681cSAbid Qadeer                              mlir::LLVM::DIFileAttr fileAttr,
74*afa4681cSAbid Qadeer                              mlir::LLVM::DIScopeAttr scope, unsigned line);
75f156b9ceSAbid Qadeer 
76f156b9ceSAbid Qadeer   void handleGlobalOp(fir::GlobalOp glocalOp, mlir::LLVM::DIFileAttr fileAttr,
7720c6b9fbSAbid Qadeer                       mlir::LLVM::DIScopeAttr scope,
78d07dc73bSAbid Qadeer                       fir::DebugTypeGenerator &typeGen,
796fd46089SAbid Qadeer                       mlir::SymbolTable *symbolTable,
806fd46089SAbid Qadeer                       fir::cg::XDeclareOp declOp);
81bf76290dSAbid Qadeer   void handleFuncOp(mlir::func::FuncOp funcOp, mlir::LLVM::DIFileAttr fileAttr,
82bf76290dSAbid Qadeer                     mlir::LLVM::DICompileUnitAttr cuAttr,
83d07dc73bSAbid Qadeer                     fir::DebugTypeGenerator &typeGen,
84bf76290dSAbid Qadeer                     mlir::SymbolTable *symbolTable);
85*afa4681cSAbid Qadeer   bool createCommonBlockGlobal(fir::cg::XDeclareOp declOp,
86*afa4681cSAbid Qadeer                                const std::string &name,
87*afa4681cSAbid Qadeer                                mlir::LLVM::DIFileAttr fileAttr,
88*afa4681cSAbid Qadeer                                mlir::LLVM::DIScopeAttr scopeAttr,
89*afa4681cSAbid Qadeer                                fir::DebugTypeGenerator &typeGen,
90*afa4681cSAbid Qadeer                                mlir::SymbolTable *symbolTable);
91db64e69fSAbid Qadeer   std::optional<mlir::LLVM::DIModuleAttr>
92db64e69fSAbid Qadeer   getModuleAttrFromGlobalOp(fir::GlobalOp globalOp,
93db64e69fSAbid Qadeer                             mlir::LLVM::DIFileAttr fileAttr,
94db64e69fSAbid Qadeer                             mlir::LLVM::DIScopeAttr scope);
957740e933Sabidh };
967740e933Sabidh 
9720c6b9fbSAbid Qadeer bool debugInfoIsAlreadySet(mlir::Location loc) {
980ee0eeb4SValentin Clement (バレンタイン クレメン)   if (mlir::isa<mlir::FusedLoc>(loc)) {
990ee0eeb4SValentin Clement (バレンタイン クレメン)     if (loc->findInstanceOf<mlir::FusedLocWith<fir::LocationKindAttr>>())
1000ee0eeb4SValentin Clement (バレンタイン クレメン)       return false;
10120c6b9fbSAbid Qadeer     return true;
1020ee0eeb4SValentin Clement (バレンタイン クレメン)   }
10320c6b9fbSAbid Qadeer   return false;
10420c6b9fbSAbid Qadeer }
10520c6b9fbSAbid Qadeer 
1067740e933Sabidh } // namespace
1077740e933Sabidh 
108*afa4681cSAbid Qadeer bool AddDebugInfoPass::createCommonBlockGlobal(
109*afa4681cSAbid Qadeer     fir::cg::XDeclareOp declOp, const std::string &name,
110*afa4681cSAbid Qadeer     mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scopeAttr,
111*afa4681cSAbid Qadeer     fir::DebugTypeGenerator &typeGen, mlir::SymbolTable *symbolTable) {
112*afa4681cSAbid Qadeer   mlir::MLIRContext *context = &getContext();
113*afa4681cSAbid Qadeer   mlir::OpBuilder builder(context);
114*afa4681cSAbid Qadeer   std::optional<std::int64_t> optint;
115*afa4681cSAbid Qadeer   mlir::Operation *op = declOp.getMemref().getDefiningOp();
116*afa4681cSAbid Qadeer 
117*afa4681cSAbid Qadeer   if (auto conOp = mlir::dyn_cast_if_present<fir::ConvertOp>(op))
118*afa4681cSAbid Qadeer     op = conOp.getValue().getDefiningOp();
119*afa4681cSAbid Qadeer 
120*afa4681cSAbid Qadeer   if (auto cordOp = mlir::dyn_cast_if_present<fir::CoordinateOp>(op)) {
121*afa4681cSAbid Qadeer     optint = fir::getIntIfConstant(cordOp.getOperand(1));
122*afa4681cSAbid Qadeer     if (!optint)
123*afa4681cSAbid Qadeer       return false;
124*afa4681cSAbid Qadeer     op = cordOp.getRef().getDefiningOp();
125*afa4681cSAbid Qadeer     if (auto conOp2 = mlir::dyn_cast_if_present<fir::ConvertOp>(op))
126*afa4681cSAbid Qadeer       op = conOp2.getValue().getDefiningOp();
127*afa4681cSAbid Qadeer 
128*afa4681cSAbid Qadeer     if (auto addrOfOp = mlir::dyn_cast_if_present<fir::AddrOfOp>(op)) {
129*afa4681cSAbid Qadeer       mlir::SymbolRefAttr sym = addrOfOp.getSymbol();
130*afa4681cSAbid Qadeer       if (auto global =
131*afa4681cSAbid Qadeer               symbolTable->lookup<fir::GlobalOp>(sym.getRootReference())) {
132*afa4681cSAbid Qadeer 
133*afa4681cSAbid Qadeer         unsigned line = getLineFromLoc(global.getLoc());
134*afa4681cSAbid Qadeer         llvm::StringRef commonName(sym.getRootReference());
135*afa4681cSAbid Qadeer         // FIXME: We are trying to extract the name of the common block from the
136*afa4681cSAbid Qadeer         // name of the global. As part of mangling, GetCommonBlockObjectName can
137*afa4681cSAbid Qadeer         // add a trailing _ in the name of that global. The demangle function
138*afa4681cSAbid Qadeer         // does not seem to handle such cases. So the following hack is used to
139*afa4681cSAbid Qadeer         // remove the trailing '_'.
140*afa4681cSAbid Qadeer         if (commonName != Fortran::common::blankCommonObjectName &&
141*afa4681cSAbid Qadeer             commonName.back() == '_')
142*afa4681cSAbid Qadeer           commonName = commonName.drop_back();
143*afa4681cSAbid Qadeer         mlir::LLVM::DICommonBlockAttr commonBlock =
144*afa4681cSAbid Qadeer             getOrCreateCommonBlockAttr(commonName, fileAttr, scopeAttr, line);
145*afa4681cSAbid Qadeer         mlir::LLVM::DITypeAttr diType = typeGen.convertType(
146*afa4681cSAbid Qadeer             fir::unwrapRefType(declOp.getType()), fileAttr, scopeAttr, declOp);
147*afa4681cSAbid Qadeer         line = getLineFromLoc(declOp.getLoc());
148*afa4681cSAbid Qadeer         auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get(
149*afa4681cSAbid Qadeer             context, commonBlock, mlir::StringAttr::get(context, name),
150*afa4681cSAbid Qadeer             declOp.getUniqName(), fileAttr, line, diType,
151*afa4681cSAbid Qadeer             /*isLocalToUnit*/ false, /*isDefinition*/ true, /* alignInBits*/ 0);
152*afa4681cSAbid Qadeer         mlir::LLVM::DIExpressionAttr expr;
153*afa4681cSAbid Qadeer         if (*optint != 0) {
154*afa4681cSAbid Qadeer           llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops;
155*afa4681cSAbid Qadeer           ops.push_back(mlir::LLVM::DIExpressionElemAttr::get(
156*afa4681cSAbid Qadeer               context, llvm::dwarf::DW_OP_plus_uconst, *optint));
157*afa4681cSAbid Qadeer           expr = mlir::LLVM::DIExpressionAttr::get(context, ops);
158*afa4681cSAbid Qadeer         }
159*afa4681cSAbid Qadeer         auto dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get(
160*afa4681cSAbid Qadeer             global.getContext(), gvAttr, expr);
161*afa4681cSAbid Qadeer         globalToGlobalExprsMap[global].push_back(dbgExpr);
162*afa4681cSAbid Qadeer         return true;
163*afa4681cSAbid Qadeer       }
164*afa4681cSAbid Qadeer     }
165*afa4681cSAbid Qadeer   }
166*afa4681cSAbid Qadeer   return false;
167*afa4681cSAbid Qadeer }
168*afa4681cSAbid Qadeer 
169cd5ee271SAbid Qadeer void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
170cd5ee271SAbid Qadeer                                        mlir::LLVM::DIFileAttr fileAttr,
171cd5ee271SAbid Qadeer                                        mlir::LLVM::DIScopeAttr scopeAttr,
17220c6b9fbSAbid Qadeer                                        fir::DebugTypeGenerator &typeGen,
17320c6b9fbSAbid Qadeer                                        mlir::SymbolTable *symbolTable) {
174cd5ee271SAbid Qadeer   mlir::MLIRContext *context = &getContext();
175cd5ee271SAbid Qadeer   mlir::OpBuilder builder(context);
176cd5ee271SAbid Qadeer   auto result = fir::NameUniquer::deconstruct(declOp.getUniqName());
177cd5ee271SAbid Qadeer 
178cd5ee271SAbid Qadeer   if (result.first != fir::NameUniquer::NameKind::VARIABLE)
179cd5ee271SAbid Qadeer     return;
180*afa4681cSAbid Qadeer 
181*afa4681cSAbid Qadeer   if (createCommonBlockGlobal(declOp, result.second.name, fileAttr, scopeAttr,
182*afa4681cSAbid Qadeer                               typeGen, symbolTable))
183*afa4681cSAbid Qadeer     return;
184*afa4681cSAbid Qadeer 
18520c6b9fbSAbid Qadeer   // If this DeclareOp actually represents a global then treat it as such.
18620c6b9fbSAbid Qadeer   if (auto global = symbolTable->lookup<fir::GlobalOp>(declOp.getUniqName())) {
187d07dc73bSAbid Qadeer     handleGlobalOp(global, fileAttr, scopeAttr, typeGen, symbolTable, declOp);
18820c6b9fbSAbid Qadeer     return;
18920c6b9fbSAbid Qadeer   }
19020c6b9fbSAbid Qadeer 
191cd5ee271SAbid Qadeer   // Only accept local variables.
192cd5ee271SAbid Qadeer   if (result.second.procs.empty())
193cd5ee271SAbid Qadeer     return;
194cd5ee271SAbid Qadeer 
195cd5ee271SAbid Qadeer   // FIXME: There may be cases where an argument is processed a bit before
196cd5ee271SAbid Qadeer   // DeclareOp is generated. In that case, DeclareOp may point to an
1976cd86d0fSSlava Zakharin   // intermediate op and not to BlockArgument.
1986cd86d0fSSlava Zakharin   // Moreover, with MLIR inlining we cannot use the BlockArgument
1996cd86d0fSSlava Zakharin   // position to identify the original number of the dummy argument.
2006cd86d0fSSlava Zakharin   // If we want to keep running AddDebugInfoPass late, the dummy argument
2016cd86d0fSSlava Zakharin   // position in the argument list has to be expressed in FIR (e.g. as a
2026cd86d0fSSlava Zakharin   // constant attribute of [hl]fir.declare/fircg.ext_declare operation that has
2036cd86d0fSSlava Zakharin   // a dummy_scope operand).
204cd5ee271SAbid Qadeer   unsigned argNo = 0;
205f7420a9dSAbid Qadeer   if (declOp.getDummyScope()) {
206f7420a9dSAbid Qadeer     if (auto arg = llvm::dyn_cast<mlir::BlockArgument>(declOp.getMemref()))
2075bfc4445SKareem Ergawy       argNo = arg.getArgNumber() + 1;
2085bfc4445SKareem Ergawy   }
209cd5ee271SAbid Qadeer 
210cd5ee271SAbid Qadeer   auto tyAttr = typeGen.convertType(fir::unwrapRefType(declOp.getType()),
2116fd46089SAbid Qadeer                                     fileAttr, scopeAttr, declOp);
212cd5ee271SAbid Qadeer 
213cd5ee271SAbid Qadeer   auto localVarAttr = mlir::LLVM::DILocalVariableAttr::get(
214cd5ee271SAbid Qadeer       context, scopeAttr, mlir::StringAttr::get(context, result.second.name),
215cd5ee271SAbid Qadeer       fileAttr, getLineFromLoc(declOp.getLoc()), argNo, /* alignInBits*/ 0,
216ef8de68fSWalter Erquinigo       tyAttr, mlir::LLVM::DIFlags::Zero);
217cd5ee271SAbid Qadeer   declOp->setLoc(builder.getFusedLoc({declOp->getLoc()}, localVarAttr));
218cd5ee271SAbid Qadeer }
219cd5ee271SAbid Qadeer 
220*afa4681cSAbid Qadeer mlir::LLVM::DICommonBlockAttr AddDebugInfoPass::getOrCreateCommonBlockAttr(
221*afa4681cSAbid Qadeer     llvm::StringRef name, mlir::LLVM::DIFileAttr fileAttr,
222*afa4681cSAbid Qadeer     mlir::LLVM::DIScopeAttr scope, unsigned line) {
223*afa4681cSAbid Qadeer   mlir::MLIRContext *context = &getContext();
224*afa4681cSAbid Qadeer   mlir::LLVM::DICommonBlockAttr cbAttr;
225*afa4681cSAbid Qadeer   if (auto iter{commonBlockMap.find(name)}; iter != commonBlockMap.end()) {
226*afa4681cSAbid Qadeer     cbAttr = iter->getValue();
227*afa4681cSAbid Qadeer   } else {
228*afa4681cSAbid Qadeer     cbAttr = mlir::LLVM::DICommonBlockAttr::get(
229*afa4681cSAbid Qadeer         context, scope, nullptr, mlir::StringAttr::get(context, name), fileAttr,
230*afa4681cSAbid Qadeer         line);
231*afa4681cSAbid Qadeer     commonBlockMap[name] = cbAttr;
232*afa4681cSAbid Qadeer   }
233*afa4681cSAbid Qadeer   return cbAttr;
234*afa4681cSAbid Qadeer }
235*afa4681cSAbid Qadeer 
236f156b9ceSAbid Qadeer // The `module` does not have a first class representation in the `FIR`. We
237f156b9ceSAbid Qadeer // extract information about it from the name of the identifiers and keep a
238f156b9ceSAbid Qadeer // map to avoid duplication.
239f156b9ceSAbid Qadeer mlir::LLVM::DIModuleAttr AddDebugInfoPass::getOrCreateModuleAttr(
240f156b9ceSAbid Qadeer     const std::string &name, mlir::LLVM::DIFileAttr fileAttr,
241f156b9ceSAbid Qadeer     mlir::LLVM::DIScopeAttr scope, unsigned line, bool decl) {
242f156b9ceSAbid Qadeer   mlir::MLIRContext *context = &getContext();
243f156b9ceSAbid Qadeer   mlir::LLVM::DIModuleAttr modAttr;
244f156b9ceSAbid Qadeer   if (auto iter{moduleMap.find(name)}; iter != moduleMap.end()) {
245f156b9ceSAbid Qadeer     modAttr = iter->getValue();
246f156b9ceSAbid Qadeer   } else {
247f156b9ceSAbid Qadeer     modAttr = mlir::LLVM::DIModuleAttr::get(
248f156b9ceSAbid Qadeer         context, fileAttr, scope, mlir::StringAttr::get(context, name),
249f156b9ceSAbid Qadeer         /* configMacros */ mlir::StringAttr(),
250f156b9ceSAbid Qadeer         /* includePath */ mlir::StringAttr(),
251f156b9ceSAbid Qadeer         /* apinotes */ mlir::StringAttr(), line, decl);
252f156b9ceSAbid Qadeer     moduleMap[name] = modAttr;
253f156b9ceSAbid Qadeer   }
254f156b9ceSAbid Qadeer   return modAttr;
255f156b9ceSAbid Qadeer }
256f156b9ceSAbid Qadeer 
257db64e69fSAbid Qadeer /// If globalOp represents a module variable, return a ModuleAttr that
258db64e69fSAbid Qadeer /// represents that module.
259db64e69fSAbid Qadeer std::optional<mlir::LLVM::DIModuleAttr>
260db64e69fSAbid Qadeer AddDebugInfoPass::getModuleAttrFromGlobalOp(fir::GlobalOp globalOp,
261db64e69fSAbid Qadeer                                             mlir::LLVM::DIFileAttr fileAttr,
262db64e69fSAbid Qadeer                                             mlir::LLVM::DIScopeAttr scope) {
263db64e69fSAbid Qadeer   mlir::MLIRContext *context = &getContext();
264db64e69fSAbid Qadeer   mlir::OpBuilder builder(context);
265db64e69fSAbid Qadeer 
266db64e69fSAbid Qadeer   std::pair result = fir::NameUniquer::deconstruct(globalOp.getSymName());
267db64e69fSAbid Qadeer   // Only look for module if this variable is not part of a function.
268db64e69fSAbid Qadeer   if (!result.second.procs.empty() || result.second.modules.empty())
269db64e69fSAbid Qadeer     return std::nullopt;
270db64e69fSAbid Qadeer 
271db64e69fSAbid Qadeer   // DWARF5 says following about the fortran modules:
272db64e69fSAbid Qadeer   // A Fortran 90 module may also be represented by a module entry
273db64e69fSAbid Qadeer   // (but no declaration attribute is warranted because Fortran has no concept
274db64e69fSAbid Qadeer   // of a corresponding module body).
275db64e69fSAbid Qadeer   // But in practice, compilers use declaration attribute with a module in cases
276db64e69fSAbid Qadeer   // where module was defined in another source file (only being used in this
277db64e69fSAbid Qadeer   // one). The isInitialized() seems to provide the right information
278db64e69fSAbid Qadeer   // but inverted. It is true where module is actually defined but false where
279db64e69fSAbid Qadeer   // it is used.
280db64e69fSAbid Qadeer   // FIXME: Currently we don't have the line number on which a module was
281db64e69fSAbid Qadeer   // declared. We are using a best guess of line - 1 where line is the source
282db64e69fSAbid Qadeer   // line of the first member of the module that we encounter.
283db64e69fSAbid Qadeer   unsigned line = getLineFromLoc(globalOp.getLoc());
284db64e69fSAbid Qadeer 
285db64e69fSAbid Qadeer   mlir::LLVM::DISubprogramAttr sp =
286db64e69fSAbid Qadeer       mlir::dyn_cast_if_present<mlir::LLVM::DISubprogramAttr>(scope);
287db64e69fSAbid Qadeer   // Modules are generated at compile unit scope
288db64e69fSAbid Qadeer   if (sp)
289db64e69fSAbid Qadeer     scope = sp.getCompileUnit();
290db64e69fSAbid Qadeer 
291db64e69fSAbid Qadeer   return getOrCreateModuleAttr(result.second.modules[0], fileAttr, scope,
292db64e69fSAbid Qadeer                                std::max(line - 1, (unsigned)1),
293db64e69fSAbid Qadeer                                !globalOp.isInitialized());
294db64e69fSAbid Qadeer }
295db64e69fSAbid Qadeer 
296f156b9ceSAbid Qadeer void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp,
297f156b9ceSAbid Qadeer                                       mlir::LLVM::DIFileAttr fileAttr,
29820c6b9fbSAbid Qadeer                                       mlir::LLVM::DIScopeAttr scope,
299d07dc73bSAbid Qadeer                                       fir::DebugTypeGenerator &typeGen,
3006fd46089SAbid Qadeer                                       mlir::SymbolTable *symbolTable,
3016fd46089SAbid Qadeer                                       fir::cg::XDeclareOp declOp) {
30220c6b9fbSAbid Qadeer   if (debugInfoIsAlreadySet(globalOp.getLoc()))
30320c6b9fbSAbid Qadeer     return;
304f156b9ceSAbid Qadeer   mlir::MLIRContext *context = &getContext();
305f156b9ceSAbid Qadeer   mlir::OpBuilder builder(context);
306f156b9ceSAbid Qadeer 
307f156b9ceSAbid Qadeer   std::pair result = fir::NameUniquer::deconstruct(globalOp.getSymName());
308f156b9ceSAbid Qadeer   if (result.first != fir::NameUniquer::NameKind::VARIABLE)
309f156b9ceSAbid Qadeer     return;
310f156b9ceSAbid Qadeer 
31195b4128cSAbid Qadeer   if (fir::NameUniquer::isSpecialSymbol(result.second.name))
312d07dc73bSAbid Qadeer     return;
313d07dc73bSAbid Qadeer 
314f156b9ceSAbid Qadeer   unsigned line = getLineFromLoc(globalOp.getLoc());
315db64e69fSAbid Qadeer   std::optional<mlir::LLVM::DIModuleAttr> modOpt =
316db64e69fSAbid Qadeer       getModuleAttrFromGlobalOp(globalOp, fileAttr, scope);
317db64e69fSAbid Qadeer   if (modOpt)
318db64e69fSAbid Qadeer     scope = *modOpt;
319f156b9ceSAbid Qadeer 
3206fd46089SAbid Qadeer   mlir::LLVM::DITypeAttr diType =
3216fd46089SAbid Qadeer       typeGen.convertType(globalOp.getType(), fileAttr, scope, declOp);
322f156b9ceSAbid Qadeer   auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get(
323f156b9ceSAbid Qadeer       context, scope, mlir::StringAttr::get(context, result.second.name),
324f156b9ceSAbid Qadeer       mlir::StringAttr::get(context, globalOp.getName()), fileAttr, line,
325f156b9ceSAbid Qadeer       diType, /*isLocalToUnit*/ false,
326f156b9ceSAbid Qadeer       /*isDefinition*/ globalOp.isInitialized(), /* alignInBits*/ 0);
327*afa4681cSAbid Qadeer   auto dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get(
328*afa4681cSAbid Qadeer       globalOp.getContext(), gvAttr, nullptr);
329*afa4681cSAbid Qadeer   auto arrayAttr = mlir::ArrayAttr::get(context, {dbgExpr});
330*afa4681cSAbid Qadeer   globalOp->setLoc(builder.getFusedLoc({globalOp.getLoc()}, arrayAttr));
331f156b9ceSAbid Qadeer }
332f156b9ceSAbid Qadeer 
333bf76290dSAbid Qadeer void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
334bf76290dSAbid Qadeer                                     mlir::LLVM::DIFileAttr fileAttr,
335bf76290dSAbid Qadeer                                     mlir::LLVM::DICompileUnitAttr cuAttr,
336d07dc73bSAbid Qadeer                                     fir::DebugTypeGenerator &typeGen,
337bf76290dSAbid Qadeer                                     mlir::SymbolTable *symbolTable) {
338bf76290dSAbid Qadeer   mlir::Location l = funcOp->getLoc();
339bf76290dSAbid Qadeer   // If fused location has already been created then nothing to do
340bf76290dSAbid Qadeer   // Otherwise, create a fused location.
341bf76290dSAbid Qadeer   if (debugInfoIsAlreadySet(l))
342bf76290dSAbid Qadeer     return;
343bf76290dSAbid Qadeer 
344bf76290dSAbid Qadeer   mlir::MLIRContext *context = &getContext();
345bf76290dSAbid Qadeer   mlir::OpBuilder builder(context);
346bf76290dSAbid Qadeer   llvm::StringRef fileName(fileAttr.getName());
347bf76290dSAbid Qadeer   llvm::StringRef filePath(fileAttr.getDirectory());
348bf76290dSAbid Qadeer   unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry())
349bf76290dSAbid Qadeer                         ? llvm::dwarf::getCallingConvention("DW_CC_program")
350bf76290dSAbid Qadeer                         : llvm::dwarf::getCallingConvention("DW_CC_normal");
351bf76290dSAbid Qadeer 
352bf76290dSAbid Qadeer   if (auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l)) {
353bf76290dSAbid Qadeer     fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue());
354bf76290dSAbid Qadeer     filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue());
355bf76290dSAbid Qadeer   }
356bf76290dSAbid Qadeer 
357bf76290dSAbid Qadeer   mlir::StringAttr fullName = mlir::StringAttr::get(context, funcOp.getName());
358bf76290dSAbid Qadeer   mlir::Attribute attr = funcOp->getAttr(fir::getInternalFuncNameAttrName());
359bf76290dSAbid Qadeer   mlir::StringAttr funcName =
360bf76290dSAbid Qadeer       (attr) ? mlir::cast<mlir::StringAttr>(attr)
361bf76290dSAbid Qadeer              : mlir::StringAttr::get(context, funcOp.getName());
362bf76290dSAbid Qadeer 
363bf76290dSAbid Qadeer   auto result = fir::NameUniquer::deconstruct(funcName);
364bf76290dSAbid Qadeer   funcName = mlir::StringAttr::get(context, result.second.name);
365bf76290dSAbid Qadeer 
366f6f4c177STom Eccles   // try to use a better function name than _QQmain for the program statement
36791d6e77dSTom Eccles   bool isMain = false;
368f6f4c177STom Eccles   if (funcName == fir::NameUniquer::doProgramEntry()) {
36991d6e77dSTom Eccles     isMain = true;
370f6f4c177STom Eccles     mlir::StringAttr bindcName =
371f6f4c177STom Eccles         funcOp->getAttrOfType<mlir::StringAttr>(fir::getSymbolAttrName());
372f6f4c177STom Eccles     if (bindcName)
373f6f4c177STom Eccles       funcName = bindcName;
374f6f4c177STom Eccles   }
375f6f4c177STom Eccles 
376bf76290dSAbid Qadeer   llvm::SmallVector<mlir::LLVM::DITypeAttr> types;
377bf76290dSAbid Qadeer   for (auto resTy : funcOp.getResultTypes()) {
3786fd46089SAbid Qadeer     auto tyAttr =
3796fd46089SAbid Qadeer         typeGen.convertType(resTy, fileAttr, cuAttr, /*declOp=*/nullptr);
380bf76290dSAbid Qadeer     types.push_back(tyAttr);
381bf76290dSAbid Qadeer   }
382b6f72fc1SAbid Qadeer   // If no return type then add a null type as a place holder for that.
383b6f72fc1SAbid Qadeer   if (types.empty())
384b6f72fc1SAbid Qadeer     types.push_back(mlir::LLVM::DINullTypeAttr::get(context));
385bf76290dSAbid Qadeer   for (auto inTy : funcOp.getArgumentTypes()) {
386bf76290dSAbid Qadeer     auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr,
3876fd46089SAbid Qadeer                                       cuAttr, /*declOp=*/nullptr);
388bf76290dSAbid Qadeer     types.push_back(tyAttr);
389bf76290dSAbid Qadeer   }
390bf76290dSAbid Qadeer 
391bf76290dSAbid Qadeer   mlir::LLVM::DISubroutineTypeAttr subTypeAttr =
392bf76290dSAbid Qadeer       mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types);
393bf76290dSAbid Qadeer   mlir::LLVM::DIFileAttr funcFileAttr =
394bf76290dSAbid Qadeer       mlir::LLVM::DIFileAttr::get(context, fileName, filePath);
395bf76290dSAbid Qadeer 
396bf76290dSAbid Qadeer   // Only definitions need a distinct identifier and a compilation unit.
397db64e69fSAbid Qadeer   mlir::DistinctAttr id, id2;
398bf76290dSAbid Qadeer   mlir::LLVM::DIScopeAttr Scope = fileAttr;
399bf76290dSAbid Qadeer   mlir::LLVM::DICompileUnitAttr compilationUnit;
400bf76290dSAbid Qadeer   mlir::LLVM::DISubprogramFlags subprogramFlags =
401bf76290dSAbid Qadeer       mlir::LLVM::DISubprogramFlags{};
402bf76290dSAbid Qadeer   if (isOptimized)
403bf76290dSAbid Qadeer     subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized;
40491d6e77dSTom Eccles   if (isMain)
40591d6e77dSTom Eccles     subprogramFlags =
40691d6e77dSTom Eccles         subprogramFlags | mlir::LLVM::DISubprogramFlags::MainSubprogram;
407bf76290dSAbid Qadeer   if (!funcOp.isExternal()) {
408db64e69fSAbid Qadeer     // Place holder and final function have to have different IDs, otherwise
409db64e69fSAbid Qadeer     // translation code will reject one of them.
410bf76290dSAbid Qadeer     id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context));
411db64e69fSAbid Qadeer     id2 = mlir::DistinctAttr::create(mlir::UnitAttr::get(context));
412bf76290dSAbid Qadeer     compilationUnit = cuAttr;
413bf76290dSAbid Qadeer     subprogramFlags =
414bf76290dSAbid Qadeer         subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
415bf76290dSAbid Qadeer   }
416bf76290dSAbid Qadeer   unsigned line = getLineFromLoc(l);
417bf76290dSAbid Qadeer   if (fir::isInternalProcedure(funcOp)) {
418bf76290dSAbid Qadeer     // For contained functions, the scope is the parent subroutine.
419bf76290dSAbid Qadeer     mlir::SymbolRefAttr sym = mlir::cast<mlir::SymbolRefAttr>(
420bf76290dSAbid Qadeer         funcOp->getAttr(fir::getHostSymbolAttrName()));
421bf76290dSAbid Qadeer     if (sym) {
422bf76290dSAbid Qadeer       if (auto func =
423bf76290dSAbid Qadeer               symbolTable->lookup<mlir::func::FuncOp>(sym.getLeafReference())) {
424bf76290dSAbid Qadeer         // Make sure that parent is processed.
425d07dc73bSAbid Qadeer         handleFuncOp(func, fileAttr, cuAttr, typeGen, symbolTable);
426bf76290dSAbid Qadeer         if (auto fusedLoc =
427bf76290dSAbid Qadeer                 mlir::dyn_cast_if_present<mlir::FusedLoc>(func.getLoc())) {
428bf76290dSAbid Qadeer           if (auto spAttr =
429bf76290dSAbid Qadeer                   mlir::dyn_cast_if_present<mlir::LLVM::DISubprogramAttr>(
430bf76290dSAbid Qadeer                       fusedLoc.getMetadata()))
431bf76290dSAbid Qadeer             Scope = spAttr;
432bf76290dSAbid Qadeer         }
433bf76290dSAbid Qadeer       }
434bf76290dSAbid Qadeer     }
435bf76290dSAbid Qadeer   } else if (!result.second.modules.empty()) {
436bf76290dSAbid Qadeer     Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr,
437bf76290dSAbid Qadeer                                   line - 1, false);
438bf76290dSAbid Qadeer   }
439bf76290dSAbid Qadeer 
440db64e69fSAbid Qadeer   // Don't process variables if user asked for line tables only.
441db64e69fSAbid Qadeer   if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly) {
442bf76290dSAbid Qadeer     auto spAttr = mlir::LLVM::DISubprogramAttr::get(
443bf76290dSAbid Qadeer         context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr,
4442918e779SWalter Erquinigo         line, line, subprogramFlags, subTypeAttr, /*retainedNodes=*/{},
4452918e779SWalter Erquinigo         /*annotations=*/{});
446db64e69fSAbid Qadeer     funcOp->setLoc(builder.getFusedLoc({l}, spAttr));
447bf76290dSAbid Qadeer     return;
448db64e69fSAbid Qadeer   }
449db64e69fSAbid Qadeer 
450db64e69fSAbid Qadeer   mlir::DistinctAttr recId =
451db64e69fSAbid Qadeer       mlir::DistinctAttr::create(mlir::UnitAttr::get(context));
452db64e69fSAbid Qadeer 
453db64e69fSAbid Qadeer   // The debug attribute in MLIR are readonly once created. But in case of
454db64e69fSAbid Qadeer   // imported entities, we have a circular dependency. The
455db64e69fSAbid Qadeer   // DIImportedEntityAttr requires scope information (DISubprogramAttr in this
456db64e69fSAbid Qadeer   // case) and DISubprogramAttr requires the list of imported entities. The
457db64e69fSAbid Qadeer   // MLIR provides a way where a DISubprogramAttr an be created with a certain
458db64e69fSAbid Qadeer   // recID and be used in places like DIImportedEntityAttr. After that another
459db64e69fSAbid Qadeer   // DISubprogramAttr can be created with same recID but with list of entities
460db64e69fSAbid Qadeer   // now available. The MLIR translation code takes care of updating the
461db64e69fSAbid Qadeer   // references. Note that references will be updated only in the things that
462db64e69fSAbid Qadeer   // are part of DISubprogramAttr (like DIImportedEntityAttr) so we have to
463db64e69fSAbid Qadeer   // create the final DISubprogramAttr before we process local variables.
464db64e69fSAbid Qadeer   // Look at DIRecursiveTypeAttrInterface for more details.
465db64e69fSAbid Qadeer 
466db64e69fSAbid Qadeer   auto spAttr = mlir::LLVM::DISubprogramAttr::get(
467db64e69fSAbid Qadeer       context, recId, /*isRecSelf=*/true, id, compilationUnit, Scope, funcName,
468db64e69fSAbid Qadeer       fullName, funcFileAttr, line, line, subprogramFlags, subTypeAttr,
4692918e779SWalter Erquinigo       /*retainedNodes=*/{}, /*annotations=*/{});
470db64e69fSAbid Qadeer 
471db64e69fSAbid Qadeer   // There is no direct information in the IR for any 'use' statement in the
472db64e69fSAbid Qadeer   // function. We have to extract that information from the DeclareOp. We do
473db64e69fSAbid Qadeer   // a pass on the DeclareOp and generate ModuleAttr and corresponding
474db64e69fSAbid Qadeer   // DIImportedEntityAttr for that module.
475db64e69fSAbid Qadeer   // FIXME: As we are depending on the variables to see which module is being
476db64e69fSAbid Qadeer   // 'used' in the function, there are certain limitations.
477db64e69fSAbid Qadeer   // For things like 'use mod1, only: v1', whole module will be brought into the
478db64e69fSAbid Qadeer   // namespace in the debug info. It is not a problem as such unless there is a
479db64e69fSAbid Qadeer   // clash of names.
480db64e69fSAbid Qadeer   // There is no information about module variable renaming
481db64e69fSAbid Qadeer   llvm::DenseSet<mlir::LLVM::DIImportedEntityAttr> importedModules;
482db64e69fSAbid Qadeer   funcOp.walk([&](fir::cg::XDeclareOp declOp) {
483db64e69fSAbid Qadeer     if (&funcOp.front() == declOp->getBlock())
484db64e69fSAbid Qadeer       if (auto global =
485db64e69fSAbid Qadeer               symbolTable->lookup<fir::GlobalOp>(declOp.getUniqName())) {
486db64e69fSAbid Qadeer         std::optional<mlir::LLVM::DIModuleAttr> modOpt =
487db64e69fSAbid Qadeer             getModuleAttrFromGlobalOp(global, fileAttr, cuAttr);
488db64e69fSAbid Qadeer         if (modOpt) {
489db64e69fSAbid Qadeer           auto importedEntity = mlir::LLVM::DIImportedEntityAttr::get(
490db64e69fSAbid Qadeer               context, llvm::dwarf::DW_TAG_imported_module, spAttr, *modOpt,
491db64e69fSAbid Qadeer               fileAttr, /*line=*/1, /*name=*/nullptr, /*elements*/ {});
492db64e69fSAbid Qadeer           importedModules.insert(importedEntity);
493db64e69fSAbid Qadeer         }
494db64e69fSAbid Qadeer       }
495db64e69fSAbid Qadeer   });
496db64e69fSAbid Qadeer   llvm::SmallVector<mlir::LLVM::DINodeAttr> entities(importedModules.begin(),
497db64e69fSAbid Qadeer                                                      importedModules.end());
498db64e69fSAbid Qadeer   // We have the imported entities now. Generate the final DISubprogramAttr.
499db64e69fSAbid Qadeer   spAttr = mlir::LLVM::DISubprogramAttr::get(
500db64e69fSAbid Qadeer       context, recId, /*isRecSelf=*/false, id2, compilationUnit, Scope,
501db64e69fSAbid Qadeer       funcName, fullName, funcFileAttr, line, line, subprogramFlags,
5022918e779SWalter Erquinigo       subTypeAttr, entities, /*annotations=*/{});
503db64e69fSAbid Qadeer   funcOp->setLoc(builder.getFusedLoc({l}, spAttr));
504bf76290dSAbid Qadeer 
505bf76290dSAbid Qadeer   funcOp.walk([&](fir::cg::XDeclareOp declOp) {
5069e08db79SAbid Qadeer     // FIXME: We currently dont handle variables that are not in the entry
5079e08db79SAbid Qadeer     // blocks of the fuctions. These may be variable or arguments used in the
5089e08db79SAbid Qadeer     // OpenMP target regions.
5099e08db79SAbid Qadeer     if (&funcOp.front() == declOp->getBlock())
510bf76290dSAbid Qadeer       handleDeclareOp(declOp, fileAttr, spAttr, typeGen, symbolTable);
511bf76290dSAbid Qadeer   });
512*afa4681cSAbid Qadeer   // commonBlockMap ensures that we don't create multiple DICommonBlockAttr of
513*afa4681cSAbid Qadeer   // the same name in one function. But it is ok (rather required) to create
514*afa4681cSAbid Qadeer   // them in different functions if common block of the same name has been used
515*afa4681cSAbid Qadeer   // there.
516*afa4681cSAbid Qadeer   commonBlockMap.clear();
517bf76290dSAbid Qadeer }
518bf76290dSAbid Qadeer 
5197740e933Sabidh void AddDebugInfoPass::runOnOperation() {
5207740e933Sabidh   mlir::ModuleOp module = getOperation();
5217740e933Sabidh   mlir::MLIRContext *context = &getContext();
52220c6b9fbSAbid Qadeer   mlir::SymbolTable symbolTable(module);
5235f3f9d1aSAbid Qadeer   llvm::StringRef fileName;
5245f3f9d1aSAbid Qadeer   std::string filePath;
525d07dc73bSAbid Qadeer   std::optional<mlir::DataLayout> dl =
526d07dc73bSAbid Qadeer       fir::support::getOrSetDataLayout(module, /*allowDefaultLayout=*/true);
527d07dc73bSAbid Qadeer   if (!dl) {
528d07dc73bSAbid Qadeer     mlir::emitError(module.getLoc(), "Missing data layout attribute in module");
529d07dc73bSAbid Qadeer     signalPassFailure();
530d07dc73bSAbid Qadeer     return;
531d07dc73bSAbid Qadeer   }
532d07dc73bSAbid Qadeer   fir::DebugTypeGenerator typeGen(module, &symbolTable, *dl);
5335f3f9d1aSAbid Qadeer   // We need 2 type of file paths here.
5345f3f9d1aSAbid Qadeer   // 1. Name of the file as was presented to compiler. This can be absolute
5355f3f9d1aSAbid Qadeer   // or relative to 2.
5365f3f9d1aSAbid Qadeer   // 2. Current working directory
5375f3f9d1aSAbid Qadeer   //
5385f3f9d1aSAbid Qadeer   // We are also dealing with 2 different situations below. One is normal
5395f3f9d1aSAbid Qadeer   // compilation where we will have a value in 'inputFilename' and we can
5405f3f9d1aSAbid Qadeer   // obtain the current directory using 'current_path'.
5415f3f9d1aSAbid Qadeer   // The 2nd case is when this pass is invoked directly from 'fir-opt' tool.
5425f3f9d1aSAbid Qadeer   // In that case, 'inputFilename' may be empty. Location embedded in the
5435f3f9d1aSAbid Qadeer   // module will be used to get file name and its directory.
5445f3f9d1aSAbid Qadeer   if (inputFilename.empty()) {
545fac349a1SChristian Sigg     if (auto fileLoc = mlir::dyn_cast<mlir::FileLineColLoc>(module.getLoc())) {
5465f3f9d1aSAbid Qadeer       fileName = llvm::sys::path::filename(fileLoc.getFilename().getValue());
5475f3f9d1aSAbid Qadeer       filePath = llvm::sys::path::parent_path(fileLoc.getFilename().getValue());
5485f3f9d1aSAbid Qadeer     } else
5495f3f9d1aSAbid Qadeer       fileName = "-";
5505f3f9d1aSAbid Qadeer   } else {
5515f3f9d1aSAbid Qadeer     fileName = inputFilename;
5525f3f9d1aSAbid Qadeer     llvm::SmallString<256> cwd;
5535f3f9d1aSAbid Qadeer     if (!llvm::sys::fs::current_path(cwd))
5545f3f9d1aSAbid Qadeer       filePath = cwd.str();
5555f3f9d1aSAbid Qadeer   }
5567740e933Sabidh 
5575f3f9d1aSAbid Qadeer   mlir::LLVM::DIFileAttr fileAttr =
5585f3f9d1aSAbid Qadeer       mlir::LLVM::DIFileAttr::get(context, fileName, filePath);
5595f3f9d1aSAbid Qadeer   mlir::StringAttr producer =
5605f3f9d1aSAbid Qadeer       mlir::StringAttr::get(context, Fortran::common::getFlangFullVersion());
5617740e933Sabidh   mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get(
5627740e933Sabidh       mlir::DistinctAttr::create(mlir::UnitAttr::get(context)),
5637740e933Sabidh       llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer,
5645f3f9d1aSAbid Qadeer       isOptimized, debugLevel);
5657740e933Sabidh 
5667740e933Sabidh   module.walk([&](mlir::func::FuncOp funcOp) {
567d07dc73bSAbid Qadeer     handleFuncOp(funcOp, fileAttr, cuAttr, typeGen, &symbolTable);
5687740e933Sabidh   });
569*afa4681cSAbid Qadeer   mlir::OpBuilder builder(context);
570*afa4681cSAbid Qadeer   // We have processed all function. Attach common block variables to the
571*afa4681cSAbid Qadeer   // global that represent the storage.
572*afa4681cSAbid Qadeer   for (auto [global, exprs] : globalToGlobalExprsMap) {
573*afa4681cSAbid Qadeer     auto arrayAttr = mlir::ArrayAttr::get(context, exprs);
574*afa4681cSAbid Qadeer     global->setLoc(builder.getFusedLoc({global.getLoc()}, arrayAttr));
575*afa4681cSAbid Qadeer   }
57620c6b9fbSAbid Qadeer   // Process any global which was not processed through DeclareOp.
57720c6b9fbSAbid Qadeer   if (debugLevel == mlir::LLVM::DIEmissionKind::Full) {
57820c6b9fbSAbid Qadeer     // Process 'GlobalOp' only if full debug info is requested.
57920c6b9fbSAbid Qadeer     for (auto globalOp : module.getOps<fir::GlobalOp>())
580d07dc73bSAbid Qadeer       handleGlobalOp(globalOp, fileAttr, cuAttr, typeGen, &symbolTable,
5816fd46089SAbid Qadeer                      /*declOp=*/nullptr);
58220c6b9fbSAbid Qadeer   }
5837740e933Sabidh }
5847740e933Sabidh 
5855f3f9d1aSAbid Qadeer std::unique_ptr<mlir::Pass>
5865f3f9d1aSAbid Qadeer fir::createAddDebugInfoPass(fir::AddDebugInfoOptions options) {
5875f3f9d1aSAbid Qadeer   return std::make_unique<AddDebugInfoPass>(options);
5887740e933Sabidh }
589