Files
clang-p2996/mlir/lib/Target/LLVMIR/DebugImporter.cpp
Tobias Gysi 3f63889d58 [mlir][llvm] Import additional debug info from LLVMIR.
Add a DebugImporter to convert LLVMIR debug metadata into
MLIR debug attributes. It is the counterpart to the
DebugTranslation class and supports the same attributes.
The revision only supports the translation of instruction,
function, and module debug information. The import of
intrinsics is left to a later revision.

Depends on D138206

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D138209
2022-11-18 09:44:40 +01:00

210 lines
8.5 KiB
C++

//===- DebugImporter.cpp - LLVM to MLIR Debug conversion ------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DebugImporter.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Location.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
using namespace mlir;
using namespace mlir::LLVM;
using namespace mlir::LLVM::detail;
void DebugImporter::translate(llvm::Function *func, LLVMFuncOp funcOp) {
if (!func->getSubprogram())
return;
// Add a fused location to link the subprogram information.
StringAttr name = StringAttr::get(context, func->getSubprogram()->getName());
funcOp->setLoc(FusedLocWith<DISubprogramAttr>::get(
{NameLoc::get(name)}, translate(func->getSubprogram()), context));
}
//===----------------------------------------------------------------------===//
// Attributes
//===----------------------------------------------------------------------===//
DIBasicTypeAttr DebugImporter::translateImpl(llvm::DIBasicType *node) {
return DIBasicTypeAttr::get(context, node->getTag(), node->getName(),
node->getSizeInBits(), node->getEncoding());
}
DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) {
Optional<DIEmissionKind> emissionKind =
symbolizeDIEmissionKind(node->getEmissionKind());
return DICompileUnitAttr::get(context, node->getSourceLanguage(),
translate(node->getFile()),
StringAttr::get(context, node->getProducer()),
node->isOptimized(), emissionKind.value());
}
DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) {
Optional<DIFlags> flags = symbolizeDIFlags(node->getFlags());
SmallVector<DINodeAttr> elements;
for (llvm::DINode *element : node->getElements()) {
assert(element && "expected a non-null element type");
elements.push_back(translate(element));
}
return DICompositeTypeAttr::get(
context, node->getTag(), StringAttr::get(context, node->getName()),
translate(node->getFile()), node->getLine(), translate(node->getScope()),
translate(node->getBaseType()), flags.value_or(DIFlags::Zero),
node->getSizeInBits(), node->getAlignInBits(), elements);
}
DIDerivedTypeAttr DebugImporter::translateImpl(llvm::DIDerivedType *node) {
return DIDerivedTypeAttr::get(
context, node->getTag(),
node->getRawName() ? StringAttr::get(context, node->getName()) : nullptr,
translate(node->getBaseType()), node->getSizeInBits(),
node->getAlignInBits(), node->getOffsetInBits());
}
DIFileAttr DebugImporter::translateImpl(llvm::DIFile *node) {
return DIFileAttr::get(context, node->getFilename(), node->getDirectory());
}
DILexicalBlockAttr DebugImporter::translateImpl(llvm::DILexicalBlock *node) {
return DILexicalBlockAttr::get(context, translate(node->getScope()),
translate(node->getFile()), node->getLine(),
node->getColumn());
}
DILexicalBlockFileAttr
DebugImporter::translateImpl(llvm::DILexicalBlockFile *node) {
return DILexicalBlockFileAttr::get(context, translate(node->getScope()),
translate(node->getFile()),
node->getDiscriminator());
}
DILocalVariableAttr DebugImporter::translateImpl(llvm::DILocalVariable *node) {
return DILocalVariableAttr::get(context, translate(node->getScope()),
StringAttr::get(context, node->getName()),
translate(node->getFile()), node->getLine(),
node->getArg(), node->getAlignInBits(),
translate(node->getType()));
}
DIScopeAttr DebugImporter::translateImpl(llvm::DIScope *node) {
return cast<DIScopeAttr>(translate(static_cast<llvm::DINode *>(node)));
}
DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
Optional<DISubprogramFlags> subprogramFlags =
symbolizeDISubprogramFlags(node->getSubprogram()->getSPFlags());
return DISubprogramAttr::get(
context, translate(node->getUnit()), translate(node->getScope()),
StringAttr::get(context, node->getName()),
node->getRawLinkageName()
? StringAttr::get(context, node->getLinkageName())
: nullptr,
translate(node->getFile()), node->getLine(), node->getScopeLine(),
subprogramFlags.value(), translate(node->getType()));
}
DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
auto getIntegerAttrOrNull = [&](llvm::DISubrange::BoundType data) {
if (auto *constInt = llvm::dyn_cast_or_null<llvm::ConstantInt *>(data))
return IntegerAttr::get(IntegerType::get(context, 64),
constInt->getSExtValue());
return IntegerAttr();
};
return DISubrangeAttr::get(context, getIntegerAttrOrNull(node->getCount()),
getIntegerAttrOrNull(node->getLowerBound()),
getIntegerAttrOrNull(node->getUpperBound()),
getIntegerAttrOrNull(node->getStride()));
}
DISubroutineTypeAttr
DebugImporter::translateImpl(llvm::DISubroutineType *node) {
// Separate the result type since it is null for void functions.
DITypeAttr resultType = translate(*node->getTypeArray().begin());
SmallVector<DITypeAttr> argumentTypes;
for (llvm::DIType *type : llvm::drop_begin(node->getTypeArray())) {
assert(type && "expected a non-null argument type");
argumentTypes.push_back(translate(type));
}
return DISubroutineTypeAttr::get(context, node->getCC(), resultType,
argumentTypes);
}
DITypeAttr DebugImporter::translateImpl(llvm::DIType *node) {
return cast<DITypeAttr>(translate(static_cast<llvm::DINode *>(node)));
}
DINodeAttr DebugImporter::translate(llvm::DINode *node) {
if (!node)
return nullptr;
// Check for a cached instance.
if (DINodeAttr attr = nodeToAttr.lookup(node))
return attr;
// Convert the debug metadata if possible.
auto translateNode = [this](llvm::DINode *node) -> DINodeAttr {
if (auto *casted = dyn_cast<llvm::DIBasicType>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DICompileUnit>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DICompositeType>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DIDerivedType>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DIFile>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DILexicalBlock>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DILexicalBlockFile>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DILocalVariable>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DISubprogram>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DISubrange>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DISubroutineType>(node))
return translateImpl(casted);
return nullptr;
};
if (DINodeAttr attr = translateNode(node)) {
nodeToAttr.insert({node, attr});
return attr;
}
return nullptr;
}
//===----------------------------------------------------------------------===//
// Locations
//===----------------------------------------------------------------------===//
Location DebugImporter::translateLoc(llvm::DILocation *loc) {
if (!loc)
return UnknownLoc::get(context);
// Get the file location of the instruction.
Location result = FileLineColLoc::get(context, loc->getFilename(),
loc->getLine(), loc->getColumn());
// Add call site information, if available.
if (llvm::DILocation *inlinedAt = loc->getInlinedAt())
result = CallSiteLoc::get(result, translateLoc(inlinedAt));
// Add scope information.
assert(loc->getScope() && "expected non-null scope");
result = FusedLocWith<DIScopeAttr>::get({result}, translate(loc->getScope()),
context);
return result;
}