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_DISCOPEFORLLVMFUNCOPPASS
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=*/{}, /*annotations=*/{});
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 DIScopeForLLVMFuncOpPass
88  : public LLVM::impl::DIScopeForLLVMFuncOpPassBase<
89  DIScopeForLLVMFuncOpPass> {
90  using Base::Base;
91 
92  void runOnOperation() override {
93  ModuleOp module = getOperation();
94  Location loc = module.getLoc();
95 
96  MLIRContext *context = &getContext();
97  if (!context->getLoadedDialect<LLVM::LLVMDialect>()) {
98  emitError(loc, "LLVM dialect is not loaded.");
99  return signalPassFailure();
100  }
101 
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.
106  LLVM::DICompileUnitAttr compileUnitAttr;
107  auto fusedCompileUnitAttr =
108  module->getLoc()
110  if (fusedCompileUnitAttr) {
111  compileUnitAttr = fusedCompileUnitAttr.getMetadata();
112  } else {
113  LLVM::DIFileAttr fileAttr;
114  if (FileLineColLoc fileLoc = extractFileLoc(loc)) {
115  StringRef inputFilePath = fileLoc.getFilename().getValue();
116  fileAttr = LLVM::DIFileAttr::get(
117  context, llvm::sys::path::filename(inputFilePath),
118  llvm::sys::path::parent_path(inputFilePath));
119  } else {
120  fileAttr = LLVM::DIFileAttr::get(context, "<unknown>", "");
121  }
122 
123  compileUnitAttr = LLVM::DICompileUnitAttr::get(
124  DistinctAttr::create(UnitAttr::get(context)), llvm::dwarf::DW_LANG_C,
125  fileAttr, StringAttr::get(context, "MLIR"),
126  /*isOptimized=*/true, emissionKind);
127  }
128 
129  // Create subprograms for each function with the same distinct compile unit.
130  module.walk([&](LLVM::LLVMFuncOp func) {
131  addScopeToFunction(func, compileUnitAttr);
132  });
133  }
134 };
135 
136 } // end anonymous namespace
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:151
MetadataT getMetadata() const
Return the metadata associated with this fused location.
Definition: Location.h:156
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
Definition: Location.h:44
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:66
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...