12#include "llvm/BinaryFormat/Dwarf.h"
13#include "llvm/Support/Path.h"
17#define GEN_PASS_DEF_DISCOPEFORLLVMFUNCOPPASS
18#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
26 if (
auto fileLoc = dyn_cast<FileLineColLoc>(loc))
28 if (
auto nameLoc = dyn_cast<NameLoc>(loc))
30 if (
auto opaqueLoc = dyn_cast<OpaqueLoc>(loc))
32 if (
auto fusedLoc = dyn_cast<FusedLoc>(loc)) {
33 for (
auto loc : fusedLoc.getLocations()) {
38 if (
auto callerLoc = dyn_cast<CallSiteLoc>(loc))
47 LLVM::DICompileUnitAttr compileUnitAttr) {
56 LLVM::DIFileAttr fileAttr;
59 line = fileLoc.getLine();
60 StringRef inputFilePath = fileLoc.getFilename().getValue();
62 LLVM::DIFileAttr::get(context, llvm::sys::path::filename(inputFilePath),
63 llvm::sys::path::parent_path(inputFilePath));
65 fileAttr = compileUnitAttr
66 ? compileUnitAttr.getFile()
67 : LLVM::DIFileAttr::get(context,
"<unknown>",
"");
69 auto subroutineTypeAttr =
70 LLVM::DISubroutineTypeAttr::get(context, llvm::dwarf::DW_CC_normal, {});
77 auto subprogramFlags = LLVM::DISubprogramFlags::Optimized;
78 if (!llvmFunc.isExternal()) {
80 subprogramFlags |= LLVM::DISubprogramFlags::Definition;
84 auto funcNameAttr = llvmFunc.getNameAttr();
85 auto subprogramAttr = LLVM::DISubprogramAttr::get(
86 context,
id, compileUnitAttr, fileAttr, funcNameAttr, funcNameAttr,
88 line, line, subprogramFlags, subroutineTypeAttr,
90 llvmFunc->setLoc(FusedLoc::get(context, {loc}, subprogramAttr));
97 LLVM::DIFileAttr calleeFileAttr;
99 auto calleeFileName = calleeFileLoc.getFilename();
100 calleeFileAttr = LLVM::DIFileAttr::get(
101 context, llvm::sys::path::filename(calleeFileName),
102 llvm::sys::path::parent_path(calleeFileName));
104 calleeFileAttr = LLVM::DIFileAttr::get(context,
"<unknown>",
"");
106 auto lexicalBlockFileAttr = LLVM::DILexicalBlockFileAttr::get(
107 context, scopeAttr, calleeFileAttr, 0);
110 if (
auto callSiteLoc = dyn_cast<CallSiteLoc>(calleeLoc)) {
111 auto nestedLoc = callSiteLoc.getCallee();
112 loc =
getNestedLoc(op, lexicalBlockFileAttr, nestedLoc);
114 return FusedLoc::get(context, {loc}, lexicalBlockFileAttr);
122 if (
auto callSiteLoc = dyn_cast<CallSiteLoc>(opLoc)) {
123 auto callerLoc = callSiteLoc.getCaller();
124 auto calleeLoc = callSiteLoc.getCallee();
130 llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc())) {
131 scopeAttr = cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());
152 StringRef opFile = opFileLoc.
getFilename().getValue();
153 StringRef funcFile = funcFileLoc.
getFilename().getValue();
157 if (opFile != funcFile) {
158 auto funcOpLoc = llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc());
161 auto scopeAttr = dyn_cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());
166 LLVM::DIFileAttr opFileAttr =
167 LLVM::DIFileAttr::get(context, llvm::sys::path::filename(opFile),
168 llvm::sys::path::parent_path(opFile));
170 LLVM::DILexicalBlockFileAttr lexicalBlockFileAttr =
171 LLVM::DILexicalBlockFileAttr::get(context, scopeAttr, opFileAttr, 0);
173 Location newLoc = FusedLoc::get(context, {opLoc}, lexicalBlockFileAttr);
180struct DIScopeForLLVMFuncOpPass
181 :
public LLVM::impl::DIScopeForLLVMFuncOpPassBase<
182 DIScopeForLLVMFuncOpPass> {
185 void runOnOperation()
override {
186 ModuleOp module = getOperation();
187 Location loc =
module.getLoc();
191 emitError(loc,
"LLVM dialect is not loaded.");
192 return signalPassFailure();
197 LLVM::DICompileUnitAttr compileUnitAttr;
198 if (
auto fusedCompileUnitAttr =
200 ->findInstanceOf<FusedLocWith<LLVM::DICompileUnitAttr>>()) {
201 compileUnitAttr = fusedCompileUnitAttr.getMetadata();
203 LLVM::DIFileAttr fileAttr;
205 StringRef inputFilePath = fileLoc.getFilename().getValue();
206 fileAttr = LLVM::DIFileAttr::get(
207 context, llvm::sys::path::filename(inputFilePath),
208 llvm::sys::path::parent_path(inputFilePath));
210 fileAttr = LLVM::DIFileAttr::get(context,
"<unknown>",
"");
213 compileUnitAttr = LLVM::DICompileUnitAttr::get(
215 fileAttr, StringAttr::get(context,
"MLIR"),
219 module.walk<WalkOrder::PreOrder>([&](Operation *op) -> void {
220 if (auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(op)) {
223 addScopeToFunction(funcOp, compileUnitAttr);
static Location getNestedLoc(Operation *op, LLVM::DIScopeAttr scopeAttr, Location calleeLoc)
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 void setLexicalBlockFileAttr(Operation *op)
Adds DILexicalBlockFileAttr for operations with CallSiteLoc and operations from different files than ...
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.
An instance of this location represents a tuple of file, line number, and column number.
StringAttr getFilename() const
This class represents a fused location whose metadata is known to be an instance of the given type.
This class represents a LLVM attribute that describes a debug info scope.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
Operation is the basic unit of execution within MLIR.
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
Location getLoc()
The source location the operation was defined or derived from.
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
MLIRContext * getContext()
Return the context this operation is associated with.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.