MLIR  20.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  // Only definitions need a distinct identifier and a compilation unit.
69  DistinctAttr id;
70  auto subprogramFlags = LLVM::DISubprogramFlags::Optimized;
71  if (!llvmFunc.isExternal()) {
73  subprogramFlags = subprogramFlags | LLVM::DISubprogramFlags::Definition;
74  } else {
75  compileUnitAttr = {};
76  }
77  auto funcName = StringAttr::get(context, llvmFunc.getName());
78  auto subprogramAttr = LLVM::DISubprogramAttr::get(
79  context, id, compileUnitAttr, fileAttr, funcName, funcName, fileAttr,
80  /*line=*/line, /*scopeline=*/col, subprogramFlags, subroutineTypeAttr,
81  /*retainedNodes=*/{});
82  llvmFunc->setLoc(FusedLoc::get(context, {loc}, subprogramAttr));
83 }
84 
85 namespace {
86 /// Add a debug info scope to LLVMFuncOp that are missing it.
87 struct DIScopeForLLVMFuncOp
88  : public LLVM::impl::DIScopeForLLVMFuncOpBase<DIScopeForLLVMFuncOp> {
89  void runOnOperation() override {
90  ModuleOp module = getOperation();
91  Location loc = module.getLoc();
92 
93  MLIRContext *context = &getContext();
94 
95  // To find a DICompileUnitAttr attached to a parent (the module for
96  // example), otherwise create a default one.
97  // Find a DICompileUnitAttr attached to the module, otherwise create a
98  // default one.
99  LLVM::DICompileUnitAttr compileUnitAttr;
100  auto fusedCompileUnitAttr =
101  module->getLoc()
103  if (fusedCompileUnitAttr) {
104  compileUnitAttr = fusedCompileUnitAttr.getMetadata();
105  } else {
106  LLVM::DIFileAttr fileAttr;
107  if (FileLineColLoc fileLoc = extractFileLoc(loc)) {
108  StringRef inputFilePath = fileLoc.getFilename().getValue();
109  fileAttr = LLVM::DIFileAttr::get(
110  context, llvm::sys::path::filename(inputFilePath),
111  llvm::sys::path::parent_path(inputFilePath));
112  } else {
113  fileAttr = LLVM::DIFileAttr::get(context, "<unknown>", "");
114  }
115 
116  compileUnitAttr = LLVM::DICompileUnitAttr::get(
117  DistinctAttr::create(UnitAttr::get(context)), llvm::dwarf::DW_LANG_C,
118  fileAttr, StringAttr::get(context, "MLIR"),
119  /*isOptimized=*/true, emissionKind);
120  }
121 
122  // Create subprograms for each function with the same distinct compile unit.
123  module.walk([&](LLVM::LLVMFuncOp func) {
124  addScopeToFunction(func, compileUnitAttr);
125  });
126  }
127 };
128 
129 } // end anonymous namespace
130 
132  return std::make_unique<DIScopeForLLVMFuncOp>();
133 }
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:148
MetadataT getMetadata() const
Return the metadata associated with this fused location.
Definition: Location.h:153
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...