MLIR  19.0.0git
DIScopeForLLVMFuncOp.cpp
Go to the documentation of this file.
1 //===- DILineTableFromLocations.cpp - -------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
12 #include "mlir/Pass/Pass.h"
13 #include "llvm/BinaryFormat/Dwarf.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Path.h"
16 
17 namespace mlir {
18 namespace LLVM {
19 #define GEN_PASS_DEF_DISCOPEFORLLVMFUNCOP
20 #include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
21 } // namespace LLVM
22 } // namespace mlir
23 
24 using namespace mlir;
25 
26 /// Attempt to extract a filename for the given loc.
27 static FileLineColLoc extractFileLoc(Location loc) {
28  if (auto fileLoc = dyn_cast<FileLineColLoc>(loc))
29  return fileLoc;
30  if (auto nameLoc = dyn_cast<NameLoc>(loc))
31  return extractFileLoc(nameLoc.getChildLoc());
32  if (auto opaqueLoc = dyn_cast<OpaqueLoc>(loc))
33  return extractFileLoc(opaqueLoc.getFallbackLocation());
34  return FileLineColLoc();
35 }
36 
37 /// Creates a DISubprogramAttr with the provided compile unit and attaches it
38 /// to the function. Does nothing when the function already has an attached
39 /// subprogram.
40 static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,
41  LLVM::DICompileUnitAttr compileUnitAttr) {
42 
43  Location loc = llvmFunc.getLoc();
45  return;
46 
47  MLIRContext *context = llvmFunc->getContext();
48 
49  // Filename, line and colmun to associate to the function.
50  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 {
58  line = fileLoc.getLine();
59  col = fileLoc.getColumn();
60  StringRef inputFilePath = fileLoc.getFilename().getValue();
61  fileAttr =
62  LLVM::DIFileAttr::get(context, llvm::sys::path::filename(inputFilePath),
63  llvm::sys::path::parent_path(inputFilePath));
64  }
65  auto subroutineTypeAttr =
66  LLVM::DISubroutineTypeAttr::get(context, llvm::dwarf::DW_CC_normal, {});
67 
68  StringAttr funcNameAttr = llvmFunc.getNameAttr();
69  // Only definitions need a distinct identifier and a compilation unit.
70  DistinctAttr id;
71  auto subprogramFlags = LLVM::DISubprogramFlags::Optimized;
72  if (!llvmFunc.isExternal()) {
74  subprogramFlags = subprogramFlags | LLVM::DISubprogramFlags::Definition;
75  } else {
76  compileUnitAttr = {};
77  }
78  auto subprogramAttr = LLVM::DISubprogramAttr::get(
79  context, id, compileUnitAttr, fileAttr, funcNameAttr, funcNameAttr,
80  fileAttr,
81  /*line=*/line,
82  /*scopeline=*/col, subprogramFlags, subroutineTypeAttr);
83  llvmFunc->setLoc(FusedLoc::get(context, {loc}, subprogramAttr));
84 }
85 
86 namespace {
87 /// Add a debug info scope to LLVMFuncOp that are missing it.
88 struct DIScopeForLLVMFuncOp
89  : public LLVM::impl::DIScopeForLLVMFuncOpBase<DIScopeForLLVMFuncOp> {
90  void runOnOperation() override {
91  ModuleOp module = getOperation();
92  Location loc = module.getLoc();
93 
94  MLIRContext *context = &getContext();
95 
96  // To find a DICompileUnitAttr attached to a parent (the module for
97  // example), otherwise create a default one.
98  // Find a DICompileUnitAttr attached to the module, otherwise create a
99  // default one.
100  LLVM::DICompileUnitAttr compileUnitAttr;
101  auto fusedCompileUnitAttr =
102  module->getLoc()
104  if (fusedCompileUnitAttr) {
105  compileUnitAttr = fusedCompileUnitAttr.getMetadata();
106  } else {
107  LLVM::DIFileAttr fileAttr;
108  if (FileLineColLoc fileLoc = extractFileLoc(loc)) {
109  StringRef inputFilePath = fileLoc.getFilename().getValue();
110  fileAttr = LLVM::DIFileAttr::get(
111  context, llvm::sys::path::filename(inputFilePath),
112  llvm::sys::path::parent_path(inputFilePath));
113  } else {
114  fileAttr = LLVM::DIFileAttr::get(context, "<unknown>", "");
115  }
116 
117  compileUnitAttr = LLVM::DICompileUnitAttr::get(
118  DistinctAttr::create(UnitAttr::get(context)), llvm::dwarf::DW_LANG_C,
119  fileAttr, StringAttr::get(context, "MLIR"),
120  /*isOptimized=*/true, LLVM::DIEmissionKind::LineTablesOnly);
121  }
122 
123  // Create subprograms for each function with the same distinct compile unit.
124  module.walk([&](LLVM::LLVMFuncOp func) {
125  addScopeToFunction(func, compileUnitAttr);
126  });
127  }
128 };
129 
130 } // end anonymous namespace
131 
133  return std::make_unique<DIScopeForLLVMFuncOp>();
134 }
static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc, LLVM::DICompileUnitAttr compileUnitAttr)
Creates a DISubprogramAttr with the provided compile unit and attaches it to the function.
static FileLineColLoc extractFileLoc(Location loc)
Attempt to extract a filename for the given loc.
static MLIRContext * getContext(OpFoldResult val)
An attribute that associates a referenced attribute with a unique identifier.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
This class represents a fused location whose metadata is known to be an instance of the given type.
Definition: Location.h:145
MetadataT getMetadata() const
Return the metadata associated with this fused location.
Definition: Location.h:150
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
Definition: Location.h:41
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
std::unique_ptr< Pass > createDIScopeForLLVMFuncOpPass()
Create a pass to add DIScope to LLVMFuncOp that are missing it.
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...