11 #include "llvm/ADT/TypeSwitch.h"
12 #include "llvm/IR/Metadata.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/Path.h"
29 : debugEmissionIsEnabled(false), llvmModule(llvmModule),
34 debugEmissionIsEnabled =
true;
40 StringRef debugVersionKey =
"Debug Info Version";
41 if (!llvmModule.getModuleFlag(debugVersionKey))
42 llvmModule.addModuleFlag(llvm::Module::Warning, debugVersionKey,
43 llvm::DEBUG_METADATA_VERSION);
46 LLVM::LLVMDialect::getTargetTripleAttrName())) {
48 llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue());
49 if (targetTriple.isKnownWindowsMSVCEnvironment()) {
52 llvmModule.addModuleFlag(llvm::Module::Warning,
"CodeView", 1);
62 if (!debugEmissionIsEnabled)
70 llvmFunc.setSubprogram(
translate(spLoc.getMetadata()));
77 llvm::DIType *DebugTranslation::translateImpl(DINullTypeAttr attr) {
86 llvm::MDString *DebugTranslation::getMDStringOrNull(StringAttr stringAttr) {
87 if (!stringAttr || stringAttr.empty())
92 llvm::DIBasicType *DebugTranslation::translateImpl(DIBasicTypeAttr attr) {
94 llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
96 0, attr.getEncoding(), llvm::DINode::FlagZero);
99 llvm::DICompileUnit *DebugTranslation::translateImpl(DICompileUnitAttr attr) {
100 llvm::DIBuilder builder(llvmModule);
101 return builder.createCompileUnit(
102 attr.getSourceLanguage(),
translate(attr.getFile()),
103 attr.getProducer() ? attr.getProducer().getValue() :
"",
104 attr.getIsOptimized(),
110 template <
class DINodeT,
class... Ts>
113 return DINodeT::getDistinct(std::forward<Ts>(args)...);
117 llvm::DICompositeType *
118 DebugTranslation::translateImpl(DICompositeTypeAttr attr) {
120 for (
auto member : attr.getElements())
125 bool isDistinct =
false;
126 switch (attr.getTag()) {
127 case llvm::dwarf::DW_TAG_class_type:
128 case llvm::dwarf::DW_TAG_enumeration_type:
129 case llvm::dwarf::DW_TAG_structure_type:
130 case llvm::dwarf::DW_TAG_union_type:
134 return getDistinctOrUnique<llvm::DICompositeType>(
135 isDistinct, llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
137 translate(attr.getBaseType()), attr.getSizeInBits(),
138 attr.getAlignInBits(),
140 static_cast<llvm::DINode::DIFlags
>(attr.getFlags()),
145 llvm::DIDerivedType *DebugTranslation::translateImpl(DIDerivedTypeAttr attr) {
147 llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
149 nullptr,
translate(attr.getBaseType()), attr.getSizeInBits(),
150 attr.getAlignInBits(), attr.getOffsetInBits(),
151 std::nullopt, llvm::DINode::FlagZero);
154 llvm::DIFile *DebugTranslation::translateImpl(DIFileAttr attr) {
156 getMDStringOrNull(attr.getDirectory()));
159 llvm::DILabel *DebugTranslation::translateImpl(DILabelAttr attr) {
161 getMDStringOrNull(attr.getName()),
162 translate(attr.getFile()), attr.getLine());
165 llvm::DILexicalBlock *DebugTranslation::translateImpl(DILexicalBlockAttr attr) {
166 return llvm::DILexicalBlock::getDistinct(llvmCtx,
translate(attr.getScope()),
168 attr.getLine(), attr.getColumn());
171 llvm::DILexicalBlockFile *
172 DebugTranslation::translateImpl(DILexicalBlockFileAttr attr) {
173 return llvm::DILexicalBlockFile::getDistinct(
175 attr.getDiscriminator());
178 llvm::DILocalScope *DebugTranslation::translateImpl(
DILocalScopeAttr attr) {
182 llvm::DILocalVariable *
183 DebugTranslation::translateImpl(DILocalVariableAttr attr) {
185 llvmCtx,
translate(attr.getScope()), getMDStringOrNull(attr.getName()),
188 llvm::DINode::FlagZero, attr.getAlignInBits(),
192 llvm::DIScope *DebugTranslation::translateImpl(
DIScopeAttr attr) {
196 llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) {
197 bool isDefinition =
static_cast<bool>(attr.getSubprogramFlags() &
198 LLVM::DISubprogramFlags::Definition);
199 return getDistinctOrUnique<llvm::DISubprogram>(
200 isDefinition, llvmCtx,
translate(attr.getScope()),
201 getMDStringOrNull(attr.getName()),
202 getMDStringOrNull(attr.getLinkageName()),
translate(attr.getFile()),
203 attr.getLine(),
translate(attr.getType()), attr.getScopeLine(),
205 0, llvm::DINode::FlagZero,
206 static_cast<llvm::DISubprogram::DISPFlags
>(attr.getSubprogramFlags()),
210 llvm::DIModule *DebugTranslation::translateImpl(DIModuleAttr attr) {
213 getMDStringOrNull(attr.getName()),
214 getMDStringOrNull(attr.getConfigMacros()),
215 getMDStringOrNull(attr.getIncludePath()),
216 getMDStringOrNull(attr.getApinotes()), attr.getLine(), attr.getIsDecl());
219 llvm::DINamespace *DebugTranslation::translateImpl(DINamespaceAttr attr) {
221 getMDStringOrNull(attr.getName()),
222 attr.getExportSymbols());
225 llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) {
226 auto getMetadataOrNull = [&](IntegerAttr attr) -> llvm::Metadata * {
230 llvm::Type::getInt64Ty(llvmCtx), attr.getInt()));
233 getMetadataOrNull(attr.getLowerBound()),
234 getMetadataOrNull(attr.getUpperBound()),
235 getMetadataOrNull(attr.getStride()));
238 llvm::DISubroutineType *
239 DebugTranslation::translateImpl(DISubroutineTypeAttr attr) {
245 llvmCtx, llvm::DINode::FlagZero, attr.getCallingConvention(),
249 llvm::DIType *DebugTranslation::translateImpl(
DITypeAttr attr) {
257 if (llvm::DINode *node = attrToNode.lookup(attr))
262 .Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
263 DIDerivedTypeAttr, DIFileAttr, DILabelAttr, DILexicalBlockAttr,
264 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
265 DINamespaceAttr, DINullTypeAttr, DISubprogramAttr,
266 DISubrangeAttr, DISubroutineTypeAttr>(
267 [&](
auto attr) {
return translateImpl(attr); });
268 attrToNode.insert({attr, node});
278 llvm::DILocalScope *scope) {
279 if (!debugEmissionIsEnabled)
286 llvm::DILocalScope *scope,
287 llvm::DILocation *inlinedAt) {
289 if (isa<UnknownLoc>(loc))
293 auto existingIt = locationToLoc.find(std::make_tuple(loc, scope, inlinedAt));
294 if (existingIt != locationToLoc.end())
295 return existingIt->second;
297 llvm::DILocation *llvmLoc =
nullptr;
298 if (
auto callLoc = dyn_cast<CallSiteLoc>(loc)) {
300 auto *callerLoc =
translateLoc(callLoc.getCaller(), scope, inlinedAt);
301 llvmLoc =
translateLoc(callLoc.getCallee(), scope, callerLoc);
303 }
else if (
auto fileLoc = dyn_cast<FileLineColLoc>(loc)) {
309 scope,
const_cast<llvm::DILocation *
>(inlinedAt));
311 }
else if (
auto fusedLoc = dyn_cast<FusedLoc>(loc)) {
315 if (
auto scopedAttr =
316 dyn_cast_or_null<LLVM::DILocalScopeAttr>(fusedLoc.getMetadata()))
320 llvmLoc =
translateLoc(locations.front(), scope, inlinedAt);
321 for (
Location locIt : locations.drop_front()) {
322 llvmLoc = llvm::DILocation::getMergedLocation(
326 }
else if (
auto nameLoc = dyn_cast<NameLoc>(loc)) {
327 llvmLoc =
translateLoc(nameLoc.getChildLoc(), scope, inlinedAt);
329 }
else if (
auto opaqueLoc = dyn_cast<OpaqueLoc>(loc)) {
330 llvmLoc =
translateLoc(opaqueLoc.getFallbackLocation(), scope, inlinedAt);
332 llvm_unreachable(
"unknown location kind");
335 locationToLoc.try_emplace(std::make_tuple(loc, scope, inlinedAt), llvmLoc);
340 llvm::DIFile *DebugTranslation::translateFile(StringRef fileName) {
341 auto *&file = fileMap[fileName];
346 if (currentWorkingDir.empty())
347 llvm::sys::fs::current_path(currentWorkingDir);
349 StringRef directory = currentWorkingDir;
352 if (llvm::sys::path::is_absolute(fileName)) {
355 auto fileIt = llvm::sys::path::begin(fileName);
356 auto fileE = llvm::sys::path::end(fileName);
357 auto curDirIt = llvm::sys::path::begin(directory);
358 auto curDirE = llvm::sys::path::end(directory);
359 for (; curDirIt != curDirE && *curDirIt == *fileIt; ++curDirIt, ++fileIt)
360 llvm::sys::path::append(dirBuf, *curDirIt);
361 if (std::distance(llvm::sys::path::begin(directory), curDirIt) == 1) {
364 directory = StringRef();
366 for (; fileIt != fileE; ++fileIt)
367 llvm::sys::path::append(fileBuf, *fileIt);
static DINodeT * getDistinctOrUnique(bool isDistinct, Ts &&...args)
Returns a new DINodeT that is either distinct or not, depending on isDistinct.
static WalkResult interruptIfValidLocation(Operation *op)
A utility walker that interrupts if the operation has valid debug information.
static MLIRContext * getContext(OpFoldResult val)
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 local debug info scope.
This class represents the base attribute for all debug info attributes.
This class represents a LLVM attribute that describes a debug info scope.
This class represents a LLVM attribute that describes a debug info type.
void finalize()
Finalize the translation of debug information.
void translate(LLVMFuncOp func, llvm::Function &llvmFunc)
Translate the debug information for the given function.
DebugTranslation(Operation *module, llvm::Module &llvmModule)
llvm::DILocation * translateLoc(Location loc, llvm::DILocalScope *scope)
Translate the given location to an llvm debug location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Operation is the basic unit of execution within MLIR.
Attribute getDiscardableAttr(StringRef name)
Access a discardable attribute by name, returns an null Attribute if the discardable attribute does n...
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Location getLoc()
The source location the operation was defined or derived from.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
static WalkResult interrupt()
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...