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));
98 LLVM::DIFileAttr calleeFileAttr =
99 LLVM::DIFileAttr::get(context, llvm::sys::path::filename(calleeFileName),
100 llvm::sys::path::parent_path(calleeFileName));
101 auto lexicalBlockFileAttr = LLVM::DILexicalBlockFileAttr::get(
102 context, scopeAttr, calleeFileAttr, 0);
105 if (
auto callSiteLoc = dyn_cast<CallSiteLoc>(calleeLoc)) {
106 auto nestedLoc = callSiteLoc.getCallee();
107 loc =
getNestedLoc(op, lexicalBlockFileAttr, nestedLoc);
109 return FusedLoc::get(context, {loc}, lexicalBlockFileAttr);
117 if (
auto callSiteLoc = dyn_cast<CallSiteLoc>(opLoc)) {
118 auto callerLoc = callSiteLoc.getCaller();
119 auto calleeLoc = callSiteLoc.getCallee();
124 if (
auto funcOpLoc = llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc())) {
125 scopeAttr = cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());
127 CallSiteLoc::get(
getNestedLoc(op, scopeAttr, calleeLoc), callerLoc));
145 StringRef opFile = opFileLoc.
getFilename().getValue();
146 StringRef funcFile = funcFileLoc.
getFilename().getValue();
150 if (opFile != funcFile) {
151 auto funcOpLoc = llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc());
154 auto scopeAttr = dyn_cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());
159 LLVM::DIFileAttr opFileAttr =
160 LLVM::DIFileAttr::get(context, llvm::sys::path::filename(opFile),
161 llvm::sys::path::parent_path(opFile));
163 LLVM::DILexicalBlockFileAttr lexicalBlockFileAttr =
164 LLVM::DILexicalBlockFileAttr::get(context, scopeAttr, opFileAttr, 0);
166 Location newLoc = FusedLoc::get(context, {opLoc}, lexicalBlockFileAttr);
173struct DIScopeForLLVMFuncOpPass
175 DIScopeForLLVMFuncOpPass> {
178 void runOnOperation()
override {
179 ModuleOp module = getOperation();
180 Location loc =
module.getLoc();
184 emitError(loc,
"LLVM dialect is not loaded.");
185 return signalPassFailure();
190 LLVM::DICompileUnitAttr compileUnitAttr;
191 if (
auto fusedCompileUnitAttr =
193 ->findInstanceOf<FusedLocWith<LLVM::DICompileUnitAttr>>()) {
194 compileUnitAttr = fusedCompileUnitAttr.getMetadata();
196 LLVM::DIFileAttr fileAttr;
198 StringRef inputFilePath = fileLoc.getFilename().getValue();
199 fileAttr = LLVM::DIFileAttr::get(
200 context, llvm::sys::path::filename(inputFilePath),
201 llvm::sys::path::parent_path(inputFilePath));
203 fileAttr = LLVM::DIFileAttr::get(context,
"<unknown>",
"");
206 compileUnitAttr = LLVM::DICompileUnitAttr::get(
208 fileAttr, StringAttr::get(context,
"MLIR"),
212 module.walk<WalkOrder::PreOrder>([&](Operation *op) -> void {
213 if (auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(op)) {
216 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.