aboutsummaryrefslogtreecommitdiff
path: root/mlir
diff options
context:
space:
mode:
authorJustin Wilson <justin.wilson@omibyte.io>2023-12-04 08:52:02 -0600
committerGitHub <noreply@github.com>2023-12-04 15:52:02 +0100
commit6da578cec1395ee54f82b51f912fb85fdb6cdce3 (patch)
treede16414042e3131b911093ae7a6370cd04a29ce5 /mlir
parent8f40ef3479fb16b9b754a29e56bac91c6377e7b7 (diff)
downloadllvm-6da578cec1395ee54f82b51f912fb85fdb6cdce3.zip
llvm-6da578cec1395ee54f82b51f912fb85fdb6cdce3.tar.gz
llvm-6da578cec1395ee54f82b51f912fb85fdb6cdce3.tar.bz2
[mlir] Add support for DIGlobalVariable and DIGlobalVariableExpression (#73367)
This PR introduces DIGlobalVariableAttr and DIGlobalVariableExpressionAttr so that ModuleTranslation can emit the required metadata needed for debug information about global variable. The translator implementation for debug metadata needed to be refactored in order to allow translation of nodes based on MDNode (DIGlobalVariableExpressionAttr and DIExpression) in addition to DINode-based nodes. A DIGlobalVariableExpressionAttr can now be passed to the GlobalOp operation directly and ModuleTranslation will create the respective DIGlobalVariable and DIGlobalVariableExpression nodes. The compile unit that DIGlobalVariable is expected to be configured with will be updated with the created DIGlobalVariableExpression.
Diffstat (limited to 'mlir')
-rw-r--r--mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td63
-rw-r--r--mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h3
-rw-r--r--mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td6
-rw-r--r--mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td4
-rw-r--r--mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h7
-rw-r--r--mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp79
-rw-r--r--mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp10
-rw-r--r--mlir/lib/Target/LLVMIR/DebugImporter.cpp34
-rw-r--r--mlir/lib/Target/LLVMIR/DebugImporter.h8
-rw-r--r--mlir/lib/Target/LLVMIR/DebugTranslation.cpp38
-rw-r--r--mlir/lib/Target/LLVMIR/DebugTranslation.h8
-rw-r--r--mlir/lib/Target/LLVMIR/ModuleImport.cpp16
-rw-r--r--mlir/lib/Target/LLVMIR/ModuleTranslation.cpp37
-rw-r--r--mlir/test/Dialect/LLVMIR/debuginfo.mlir4
-rw-r--r--mlir/test/Dialect/LLVMIR/global.mlir26
-rw-r--r--mlir/test/Target/LLVMIR/Import/debug-info.ll6
-rw-r--r--mlir/test/Target/LLVMIR/Import/global-variables.ll26
-rw-r--r--mlir/test/Target/LLVMIR/llvmir-debug.mlir31
18 files changed, 379 insertions, 27 deletions
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 9e35bf1..5a65293 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -11,6 +11,7 @@
include "mlir/Dialect/LLVMIR/LLVMDialect.td"
include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/CommonAttrConstraints.td"
// All of the attributes will extend this class.
class LLVM_Attr<string name, string attrMnemonic,
@@ -261,15 +262,34 @@ def LLVM_DITagParameter : LLVM_DIParameter<
"tag", /*default=*/"", "Tag"
>;
+def LLVM_DIOperationEncodingParameter : LLVM_DIParameter<
+ "operation encoding", /*default=*/"", "OperationEncoding"
+>;
+
//===----------------------------------------------------------------------===//
// DIExpressionAttr
//===----------------------------------------------------------------------===//
-// TODO: Implement custom printer/parser for elements so that operators are
-// dumped in textual form.
-def LLVM_DIExpressionAttr : ArrayOfAttr<LLVM_Dialect, "DIExpression",
- "di_expr", "uint64_t"> {
- let assemblyFormat = "`<` `[` (`]` `>`) : ($value^ `]` `>`)?";
+def LLVM_DIExpressionElemAttr : LLVM_Attr<"DIExpressionElem",
+ "di_expression_elem"> {
+ let parameters = (ins
+ LLVM_DIOperationEncodingParameter:$opcode,
+ OptionalArrayRefParameter<"uint64_t">:$arguments);
+ let assemblyFormat = [{
+ `` $opcode ( `(` custom<ExpressionArg>(ref($opcode), $arguments)^ `)` ) : (``)?
+ }];
+}
+
+def LLVM_DIExpressionAttr : LLVM_Attr<"DIExpression", "di_expression"> {
+ let parameters = (ins
+ OptionalArrayRefParameter<"DIExpressionElemAttr">:$operations
+ );
+ let builders = [
+ AttrBuilder<(ins)>
+ ];
+ let constBuilderCall =
+ "::mlir::LLVM::DIExpressionAttr::get($_builder.getContext(), $0)";
+ let assemblyFormat = "`<` ( `[` $operations^ `]` ) : (``)? `>`";
}
//===----------------------------------------------------------------------===//
@@ -375,6 +395,39 @@ def LLVM_DIFileAttr : LLVM_Attr<"DIFile", "di_file", /*traits=*/[], "DIScopeAttr
}
//===----------------------------------------------------------------------===//
+// DIGlobalVariableExpressionAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DIGlobalVariableExpressionAttr
+ : LLVM_Attr<"DIGlobalVariableExpression", "di_global_variable_expression"> {
+ let parameters = (ins
+ "DIGlobalVariableAttr":$var,
+ OptionalParameter<"DIExpressionAttr">:$expr
+ );
+ let assemblyFormat = "`<` struct(params) `>`";
+ let constBuilderCall = "$0";
+}
+
+//===----------------------------------------------------------------------===//
+// DIGlobalVariableAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DIGlobalVariable : LLVM_Attr<"DIGlobalVariable", "di_global_variable",
+ /*traits=*/[], "DINodeAttr"> {
+ let parameters = (ins
+ "DIScopeAttr":$scope,
+ "StringAttr":$name,
+ "StringAttr":$linkageName,
+ "DIFileAttr":$file,
+ "unsigned":$line,
+ "DITypeAttr":$type,
+ OptionalParameter<"bool">:$isLocalToUnit,
+ OptionalParameter<"bool">:$isDefined,
+ OptionalParameter<"unsigned">:$alignInBits);
+ let assemblyFormat = "`<` struct(params) `>`";
+}
+
+//===----------------------------------------------------------------------===//
// DILexicalBlockAttr
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index c370bfa..dd88c3f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -16,6 +16,9 @@
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/OpImplementation.h"
+#include "mlir/TableGen/Constraint.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/TableGen/Record.h"
#include <optional>
#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc"
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index fc088ea..f886204 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -434,7 +434,7 @@ class LLVM_DbgIntrOp<string name, string argName, list<Trait> traits = []>
llvm::MetadataAsValue::get(ctx,
llvm::ValueAsMetadata::get(moduleTranslation.lookupValue(opInst.getOperand(0)))),
llvm::MetadataAsValue::get(ctx, moduleTranslation.translateDebugInfo($varInfo)),
- llvm::MetadataAsValue::get(ctx, llvm::DIExpression::get(ctx, $locationExpr)),
+ llvm::MetadataAsValue::get(ctx, moduleTranslation.translateExpression($locationExpr)),
});
}];
let mlirBuilder = [{
@@ -455,7 +455,7 @@ def LLVM_DbgDeclareOp : LLVM_DbgIntrOp<"dbg.declare", "addr",
let arguments = (ins
LLVM_AnyPointer:$addr,
LLVM_DILocalVariableAttr:$varInfo,
- DefaultValuedAttr<LLVM_DIExpressionAttr, "std::nullopt">:$locationExpr
+ DefaultValuedAttr<LLVM_DIExpressionAttr, "{}">:$locationExpr
);
}
@@ -465,7 +465,7 @@ def LLVM_DbgValueOp : LLVM_DbgIntrOp<"dbg.value", "value",
let arguments = (ins
LLVM_Type:$value,
LLVM_DILocalVariableAttr:$varInfo,
- DefaultValuedAttr<LLVM_DIExpressionAttr, "std::nullopt">:$locationExpr
+ DefaultValuedAttr<LLVM_DIExpressionAttr, "{}">:$locationExpr
);
}
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 88f4f81..8f166f0 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1087,6 +1087,7 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global",
OptionalAttr<UnnamedAddr>:$unnamed_addr,
OptionalAttr<StrAttr>:$section,
OptionalAttr<SymbolRefAttr>:$comdat,
+ DefaultValuedAttr<LLVM_DIGlobalVariableExpressionAttr, "{}">:$dbg_expr,
DefaultValuedAttr<Visibility, "mlir::LLVM::Visibility::Default">:$visibility_
);
let summary = "LLVM dialect global.";
@@ -1196,7 +1197,8 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global",
CArg<"bool", "false">:$dsoLocal,
CArg<"bool", "false">:$thread_local_,
CArg<"SymbolRefAttr", "{}">:$comdat,
- CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs)>
+ CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs,
+ CArg<"DIGlobalVariableExpressionAttr", "{}">:$dbgExpr)>
];
let extraClassDeclaration = [{
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index 4820e82..3f797f4 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -191,6 +191,13 @@ public:
/// Translates the given location.
llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope);
+ /// Translates the given LLVM DWARF expression metadata.
+ llvm::DIExpression *translateExpression(LLVM::DIExpressionAttr attr);
+
+ /// Translates the given LLVM global variable expression metadata.
+ llvm::DIGlobalVariableExpression *
+ translateGlobalVariableExpression(LLVM::DIGlobalVariableExpressionAttr attr);
+
/// Translates the given LLVM debug info metadata.
llvm::Metadata *translateDebugInfo(LLVM::DINodeAttr attr);
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 3d45ab8..0535246 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -17,11 +17,23 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include <optional>
using namespace mlir;
using namespace mlir::LLVM;
+/// Parses DWARF expression arguments with respect to the DWARF operation
+/// opcode. Some DWARF expression operations have a specific number of operands
+/// and may appear in a textual form.
+static LogicalResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
+ SmallVector<uint64_t> &args);
+
+/// Prints DWARF expression arguments with respect to the specific DWARF
+/// operation. Some operands are printed in their textual form.
+static LogicalResult printExpressionArg(AsmPrinter &printer, uint64_t opcode,
+ ArrayRef<uint64_t> args);
+
#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc"
#define GET_ATTRDEF_CLASSES
#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
@@ -43,8 +55,8 @@ void LLVMDialect::registerAttributes() {
bool DINodeAttr::classof(Attribute attr) {
return llvm::isa<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
- DIDerivedTypeAttr, DIFileAttr, DILabelAttr,
- DILexicalBlockAttr, DILexicalBlockFileAttr,
+ DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
+ DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr,
DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
DINullTypeAttr, DISubprogramAttr, DISubrangeAttr,
DISubroutineTypeAttr>(attr);
@@ -109,3 +121,66 @@ bool MemoryEffectsAttr::isReadWrite() {
return false;
return true;
}
+
+//===----------------------------------------------------------------------===//
+// DIExpression
+//===----------------------------------------------------------------------===//
+
+DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
+ return get(context, ArrayRef<DIExpressionElemAttr>({}));
+}
+
+LogicalResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
+ SmallVector<uint64_t> &args) {
+ auto operandParser = [&]() -> LogicalResult {
+ uint64_t operand = 0;
+ if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
+ // Attempt to parse a keyword.
+ StringRef keyword;
+ if (succeeded(parser.parseOptionalKeyword(&keyword))) {
+ operand = llvm::dwarf::getAttributeEncoding(keyword);
+ if (operand == 0) {
+ // The keyword is invalid.
+ return parser.emitError(parser.getCurrentLocation())
+ << "encountered unknown attribute encoding \"" << keyword
+ << "\"";
+ }
+ }
+ }
+
+ // operand should be non-zero if a keyword was parsed. Otherwise, the
+ // operand MUST be an integer.
+ if (operand == 0) {
+ // Parse the next operand as an integer.
+ if (parser.parseInteger(operand)) {
+ return parser.emitError(parser.getCurrentLocation())
+ << "expected integer operand";
+ }
+ }
+
+ args.push_back(operand);
+ return success();
+ };
+
+ // Parse operands as a comma-separated list.
+ return parser.parseCommaSeparatedList(operandParser);
+}
+
+LogicalResult printExpressionArg(AsmPrinter &printer, uint64_t opcode,
+ ArrayRef<uint64_t> args) {
+ size_t i = 0;
+ llvm::interleaveComma(args, printer, [&](uint64_t operand) {
+ if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
+ if (const StringRef keyword =
+ llvm::dwarf::AttributeEncodingString(operand);
+ !keyword.empty()) {
+ printer << keyword;
+ return;
+ }
+ }
+ // All operands are expected to be printed as integers.
+ printer << operand;
+ i++;
+ });
+ return success();
+}
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 7186036..2844594 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -1781,7 +1781,8 @@ void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type,
bool isConstant, Linkage linkage, StringRef name,
Attribute value, uint64_t alignment, unsigned addrSpace,
bool dsoLocal, bool threadLocal, SymbolRefAttr comdat,
- ArrayRef<NamedAttribute> attrs) {
+ ArrayRef<NamedAttribute> attrs,
+ DIGlobalVariableExpressionAttr dbgExpr) {
result.addAttribute(getSymNameAttrName(result.name),
builder.getStringAttr(name));
result.addAttribute(getGlobalTypeAttrName(result.name), TypeAttr::get(type));
@@ -1812,6 +1813,10 @@ void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type,
result.addAttribute(getAddrSpaceAttrName(result.name),
builder.getI32IntegerAttr(addrSpace));
result.attributes.append(attrs.begin(), attrs.end());
+
+ if (dbgExpr)
+ result.addAttribute(getDbgExprAttrName(result.name), dbgExpr);
+
result.addRegion();
}
@@ -2910,7 +2915,8 @@ struct LLVMOpAsmDialectInterface : public OpAsmDialectInterface {
return TypeSwitch<Attribute, AliasResult>(attr)
.Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
- DIDerivedTypeAttr, DIFileAttr, DILabelAttr, DILexicalBlockAttr,
+ DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
+ DIGlobalVariableExpressionAttr, DILabelAttr, DILexicalBlockAttr,
DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
DINamespaceAttr, DINullTypeAttr, DISubprogramAttr,
DISubroutineTypeAttr, LoopAnnotationAttr, LoopVectorizeAttr,
diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp
index 36a03ec..89d34e4 100644
--- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp
@@ -116,6 +116,16 @@ DebugImporter::translateImpl(llvm::DILexicalBlockFile *node) {
node->getDiscriminator());
}
+DIGlobalVariableAttr
+DebugImporter::translateImpl(llvm::DIGlobalVariable *node) {
+ return DIGlobalVariableAttr::get(
+ context, translate(node->getScope()),
+ StringAttr::get(context, node->getName()),
+ StringAttr::get(context, node->getLinkageName()),
+ translate(node->getFile()), node->getLine(), translate(node->getType()),
+ node->isLocalToUnit(), node->isDefinition(), node->getAlignInBits());
+}
+
DILocalVariableAttr DebugImporter::translateImpl(llvm::DILocalVariable *node) {
return DILocalVariableAttr::get(context, translate(node->getScope()),
getStringAttrOrNull(node->getRawName()),
@@ -231,6 +241,8 @@ DINodeAttr DebugImporter::translate(llvm::DINode *node) {
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DIFile>(node))
return translateImpl(casted);
+ if (auto *casted = dyn_cast<llvm::DIGlobalVariable>(node))
+ return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DILabel>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DILexicalBlock>(node))
@@ -281,6 +293,28 @@ Location DebugImporter::translateLoc(llvm::DILocation *loc) {
return result;
}
+DIExpressionAttr DebugImporter::translateExpression(llvm::DIExpression *node) {
+ SmallVector<DIExpressionElemAttr> ops;
+
+ // Begin processing the operations.
+ for (const llvm::DIExpression::ExprOperand &op : node->expr_ops()) {
+ SmallVector<uint64_t> operands;
+ operands.reserve(op.getNumArgs());
+ for (const auto &i : llvm::seq(op.getNumArgs()))
+ operands.push_back(op.getArg(i));
+ const auto attr = DIExpressionElemAttr::get(context, op.getOp(), operands);
+ ops.push_back(attr);
+ }
+ return DIExpressionAttr::get(context, ops);
+}
+
+DIGlobalVariableExpressionAttr DebugImporter::translateGlobalVariableExpression(
+ llvm::DIGlobalVariableExpression *node) {
+ return DIGlobalVariableExpressionAttr::get(
+ context, translate(node->getVariable()),
+ translateExpression(node->getExpression()));
+}
+
StringAttr DebugImporter::getStringAttrOrNull(llvm::MDString *stringNode) {
if (!stringNode)
return StringAttr();
diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.h b/mlir/lib/Target/LLVMIR/DebugImporter.h
index 5c07ec8..7d4a371 100644
--- a/mlir/lib/Target/LLVMIR/DebugImporter.h
+++ b/mlir/lib/Target/LLVMIR/DebugImporter.h
@@ -35,6 +35,13 @@ public:
/// Translates the given LLVM debug location to an MLIR location.
Location translateLoc(llvm::DILocation *loc);
+ /// Translates the LLVM DWARF expression metadata to MLIR.
+ DIExpressionAttr translateExpression(llvm::DIExpression *node);
+
+ /// Translates the LLVM DWARF global variable expression metadata to MLIR.
+ DIGlobalVariableExpressionAttr
+ translateGlobalVariableExpression(llvm::DIGlobalVariableExpression *node);
+
/// Translates the debug information for the given function into a Location.
/// Returns UnknownLoc if `func` has no debug information attached to it.
Location translateFuncLocation(llvm::Function *func);
@@ -61,6 +68,7 @@ private:
DILabelAttr translateImpl(llvm::DILabel *node);
DILexicalBlockAttr translateImpl(llvm::DILexicalBlock *node);
DILexicalBlockFileAttr translateImpl(llvm::DILexicalBlockFile *node);
+ DIGlobalVariableAttr translateImpl(llvm::DIGlobalVariable *node);
DILocalVariableAttr translateImpl(llvm::DILocalVariable *node);
DIModuleAttr translateImpl(llvm::DIModule *node);
DINamespaceAttr translateImpl(llvm::DINamespace *node);
diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
index a15ffb40..6d845e2 100644
--- a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
@@ -189,6 +189,15 @@ DebugTranslation::translateImpl(DILocalVariableAttr attr) {
/*Annotations=*/nullptr);
}
+llvm::DIGlobalVariable *
+DebugTranslation::translateImpl(DIGlobalVariableAttr attr) {
+ return llvm::DIGlobalVariable::getDistinct(
+ llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()),
+ getMDStringOrNull(attr.getLinkageName()), translate(attr.getFile()),
+ attr.getLine(), translate(attr.getType()), attr.getIsLocalToUnit(),
+ attr.getIsDefined(), nullptr, nullptr, attr.getAlignInBits(), nullptr);
+}
+
llvm::DIScope *DebugTranslation::translateImpl(DIScopeAttr attr) {
return cast<llvm::DIScope>(translate(DINodeAttr(attr)));
}
@@ -260,10 +269,11 @@ llvm::DINode *DebugTranslation::translate(DINodeAttr attr) {
llvm::DINode *node =
TypeSwitch<DINodeAttr, llvm::DINode *>(attr)
.Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
- DIDerivedTypeAttr, DIFileAttr, DILabelAttr, DILexicalBlockAttr,
- DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
- DINamespaceAttr, DINullTypeAttr, DISubprogramAttr,
- DISubrangeAttr, DISubroutineTypeAttr>(
+ DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
+ DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr,
+ DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
+ DINullTypeAttr, DISubprogramAttr, DISubrangeAttr,
+ DISubroutineTypeAttr>(
[&](auto attr) { return translateImpl(attr); });
attrToNode.insert({attr, node});
return node;
@@ -281,6 +291,26 @@ llvm::DILocation *DebugTranslation::translateLoc(Location loc,
return translateLoc(loc, scope, /*inlinedAt=*/nullptr);
}
+llvm::DIExpression *
+DebugTranslation::translateExpression(LLVM::DIExpressionAttr attr) {
+ SmallVector<uint64_t, 1> ops;
+ if (attr) {
+ // Append operations their operands to the list.
+ for (const DIExpressionElemAttr &op : attr.getOperations()) {
+ ops.push_back(op.getOpcode());
+ append_range(ops, op.getArguments());
+ }
+ }
+ return llvm::DIExpression::get(llvmCtx, ops);
+}
+
+llvm::DIGlobalVariableExpression *
+DebugTranslation::translateGlobalVariableExpression(
+ LLVM::DIGlobalVariableExpressionAttr attr) {
+ return llvm::DIGlobalVariableExpression::get(
+ llvmCtx, translate(attr.getVar()), translateExpression(attr.getExpr()));
+}
+
/// Translate the given location to an llvm DebugLoc.
llvm::DILocation *DebugTranslation::translateLoc(Location loc,
llvm::DILocalScope *scope,
diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.h b/mlir/lib/Target/LLVMIR/DebugTranslation.h
index d22c3d8..627c684 100644
--- a/mlir/lib/Target/LLVMIR/DebugTranslation.h
+++ b/mlir/lib/Target/LLVMIR/DebugTranslation.h
@@ -37,6 +37,13 @@ public:
/// Translate the given location to an llvm debug location.
llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope);
+ /// Translates the given DWARF expression metadata to to LLVM.
+ llvm::DIExpression *translateExpression(LLVM::DIExpressionAttr attr);
+
+ /// Translates the given DWARF global variable expression to LLVM.
+ llvm::DIGlobalVariableExpression *
+ translateGlobalVariableExpression(LLVM::DIGlobalVariableExpressionAttr attr);
+
/// Translate the debug information for the given function.
void translate(LLVMFuncOp func, llvm::Function &llvmFunc);
@@ -72,6 +79,7 @@ private:
llvm::DILexicalBlockFile *translateImpl(DILexicalBlockFileAttr attr);
llvm::DILocalScope *translateImpl(DILocalScopeAttr attr);
llvm::DILocalVariable *translateImpl(DILocalVariableAttr attr);
+ llvm::DIGlobalVariable *translateImpl(DIGlobalVariableAttr attr);
llvm::DIModule *translateImpl(DIModuleAttr attr);
llvm::DINamespace *translateImpl(DINamespaceAttr attr);
llvm::DIScope *translateImpl(DIScopeAttr attr);
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 9cdc1f4..2d1aaa9 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -853,12 +853,24 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
alignment = align.value();
}
+ // Get the global expression associated with this global variable and convert
+ // it.
+ DIGlobalVariableExpressionAttr globalExpressionAttr;
+ SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
+ globalVar->getDebugInfo(globalExpressions);
+
+ // There should only be a single global expression.
+ if (!globalExpressions.empty())
+ globalExpressionAttr =
+ debugImporter->translateGlobalVariableExpression(globalExpressions[0]);
+
GlobalOp globalOp = builder.create<GlobalOp>(
mlirModule.getLoc(), type, globalVar->isConstant(),
convertLinkageFromLLVM(globalVar->getLinkage()), globalVar->getName(),
valueAttr, alignment, /*addr_space=*/globalVar->getAddressSpace(),
/*dso_local=*/globalVar->isDSOLocal(),
- /*thread_local=*/globalVar->isThreadLocal());
+ /*thread_local=*/globalVar->isThreadLocal(), /*comdat=*/SymbolRefAttr(),
+ /*attrs=*/ArrayRef<NamedAttribute>(), /*dbgExpr=*/globalExpressionAttr);
globalInsertionOp = globalOp;
if (globalVar->hasInitializer() && !valueAttr) {
@@ -1890,7 +1902,7 @@ ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
DILocalVariableAttr localVariableAttr =
matchLocalVariableAttr(dbgIntr->getArgOperand(1));
auto locationExprAttr =
- DIExpressionAttr::get(context, dbgIntr->getExpression()->getElements());
+ debugImporter->translateExpression(dbgIntr->getExpression());
Operation *op =
llvm::TypeSwitch<llvm::DbgVariableIntrinsic *, Operation *>(dbgIntr)
.Case([&](llvm::DbgDeclareInst *) {
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 322843e..836f23b 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -726,6 +726,9 @@ static void addRuntimePreemptionSpecifier(bool dsoLocalRequested,
/// Create named global variables that correspond to llvm.mlir.global
/// definitions. Convert llvm.global_ctors and global_dtors ops.
LogicalResult ModuleTranslation::convertGlobals() {
+ // Mapping from compile unit to its respective set of global variables.
+ DenseMap<llvm::DICompileUnit *, SmallVector<llvm::Metadata *>> allGVars;
+
for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
llvm::Type *type = convertType(op.getType());
llvm::Constant *cst = nullptr;
@@ -782,6 +785,22 @@ LogicalResult ModuleTranslation::convertGlobals() {
var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
globalsMapping.try_emplace(op, var);
+
+ // Add debug information if present.
+ if (op.getDbgExpr()) {
+ llvm::DIGlobalVariableExpression *diGlobalExpr =
+ debugTranslation->translateGlobalVariableExpression(op.getDbgExpr());
+ llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
+ var->addDebugInfo(diGlobalExpr);
+
+ // Get the compile unit (scope) of the the global variable.
+ if (llvm::DICompileUnit *compileUnit =
+ dyn_cast<llvm::DICompileUnit>(diGlobalVar->getScope())) {
+ // Update the compile unit with this incoming global variable expression
+ // during the finalizing step later.
+ allGVars[compileUnit].push_back(diGlobalExpr);
+ }
+ }
}
// Convert global variable bodies. This is done after all global variables
@@ -827,6 +846,13 @@ LogicalResult ModuleTranslation::convertGlobals() {
if (failed(convertDialectAttributes(op)))
return failure();
+ // Finally, update the compile units their respective sets of global variables
+ // created earlier.
+ for (const auto &[compileUnit, globals] : allGVars) {
+ compileUnit->replaceGlobalVariables(
+ llvm::MDTuple::get(getLLVMContext(), globals));
+ }
+
return success();
}
@@ -1329,6 +1355,17 @@ llvm::DILocation *ModuleTranslation::translateLoc(Location loc,
return debugTranslation->translateLoc(loc, scope);
}
+llvm::DIExpression *
+ModuleTranslation::translateExpression(LLVM::DIExpressionAttr attr) {
+ return debugTranslation->translateExpression(attr);
+}
+
+llvm::DIGlobalVariableExpression *
+ModuleTranslation::translateGlobalVariableExpression(
+ LLVM::DIGlobalVariableExpressionAttr attr) {
+ return debugTranslation->translateGlobalVariableExpression(attr);
+}
+
llvm::Metadata *ModuleTranslation::translateDebugInfo(LLVM::DINodeAttr attr) {
return debugTranslation->translate(attr);
}
diff --git a/mlir/test/Dialect/LLVMIR/debuginfo.mlir b/mlir/test/Dialect/LLVMIR/debuginfo.mlir
index cdfcb7f..53c38b4 100644
--- a/mlir/test/Dialect/LLVMIR/debuginfo.mlir
+++ b/mlir/test/Dialect/LLVMIR/debuginfo.mlir
@@ -162,8 +162,8 @@ llvm.func @addr(%arg: i64) {
// CHECK: llvm.func @value(%[[ARG1:.*]]: i32, %[[ARG2:.*]]: i32)
llvm.func @value(%arg1: i32, %arg2: i32) {
- // CHECK: llvm.intr.dbg.value #[[VAR1]] #llvm.di_expr<[2, 4096, 0, 4]> = %[[ARG1]]
- llvm.intr.dbg.value #var1 #llvm.di_expr<[2, 4096, 0, 4]> = %arg1 : i32
+ // CHECK: llvm.intr.dbg.value #[[VAR1]] #llvm.di_expression<[DW_OP_LLVM_fragment(16, 8), DW_OP_plus_uconst(2), DW_OP_deref]> = %[[ARG1]]
+ llvm.intr.dbg.value #var1 #llvm.di_expression<[DW_OP_LLVM_fragment(16, 8), DW_OP_plus_uconst(2), DW_OP_deref]> = %arg1 : i32
// CHECK: llvm.intr.dbg.value #[[VAR2]] = %[[ARG2]]
llvm.intr.dbg.value #var2 = %arg2 : i32
// CHECK: llvm.intr.dbg.label #[[LABEL1]]
diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir
index 81178b2..8133aa8 100644
--- a/mlir/test/Dialect/LLVMIR/global.mlir
+++ b/mlir/test/Dialect/LLVMIR/global.mlir
@@ -258,3 +258,29 @@ llvm.mlir.global @target_ext_init() : !llvm.target<"spirv.Image", i32, 0> {
// expected-error @+1 {{global with target extension type can only be initialized with zero-initializer}}
llvm.mlir.global @target_fail(0 : i64) : !llvm.target<"spirv.Image", i32, 0>
+
+// -----
+
+// CHECK-DAG: #[[TYPE:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "uint64_t", sizeInBits = 64, encoding = DW_ATE_unsigned>
+// CHECK-DAG: #[[FILE:.*]] = #llvm.di_file<"not" in "existence">
+// CHECK-DAG: #[[CU:.*]] = #llvm.di_compile_unit<sourceLanguage = DW_LANG_C, file = #[[FILE]], producer = "MLIR", isOptimized = true, emissionKind = Full>
+// CHECK-DAG: #[[GVAR0:.*]] = #llvm.di_global_variable<scope = #[[CU]], name = "global_with_expr_1", linkageName = "global_with_expr_1", file = #[[FILE]], line = 370, type = #[[TYPE]], isLocalToUnit = true, isDefined = true, alignInBits = 8>
+// CHECK-DAG: #[[GVAR1:.*]] = #llvm.di_global_variable<scope = #[[CU]], name = "global_with_expr_2", linkageName = "global_with_expr_2", file = #[[FILE]], line = 371, type = #[[TYPE]], isLocalToUnit = true, isDefined = true, alignInBits = 8>
+// CHECK-DAG: #[[GVAR2:.*]] = #llvm.di_global_variable<scope = #[[CU]], name = "global_with_expr_3", linkageName = "global_with_expr_3", file = #[[FILE]], line = 372, type = #[[TYPE]], isLocalToUnit = true, isDefined = true, alignInBits = 8>
+// CHECK-DAG: #[[GVAR3:.*]] = #llvm.di_global_variable<scope = #[[CU]], name = "global_with_expr_4", linkageName = "global_with_expr_4", file = #[[FILE]], line = 373, type = #[[TYPE]], isLocalToUnit = true, isDefined = true, alignInBits = 8>
+// CHECK-DAG: #[[EXPR0:.*]] = #llvm.di_global_variable_expression<var = #[[GVAR0]], expr = <>>
+// CHECK-DAG: #[[EXPR1:.*]] = #llvm.di_global_variable_expression<var = #[[GVAR1]], expr = <[DW_OP_push_object_address, DW_OP_deref]>>
+// CHECK-DAG: #[[EXPR2:.*]] = #llvm.di_global_variable_expression<var = #[[GVAR2]], expr = <[DW_OP_LLVM_arg(0), DW_OP_LLVM_arg(1), DW_OP_plus]>>
+// CHECK-DAG: #[[EXPR3:.*]] = #llvm.di_global_variable_expression<var = #[[GVAR3]], expr = <[DW_OP_LLVM_convert(16, DW_ATE_signed)]>>
+// CHECK-DAG: llvm.mlir.global external @global_with_expr1() {addr_space = 0 : i32, dbg_expr = #[[EXPR0]]} : i64
+// CHECK-DAG: llvm.mlir.global external @global_with_expr2() {addr_space = 0 : i32, dbg_expr = #[[EXPR1]]} : i64
+// CHECK-DAG: llvm.mlir.global external @global_with_expr3() {addr_space = 0 : i32, dbg_expr = #[[EXPR2]]} : i64
+// CHECK-DAG: llvm.mlir.global external @global_with_expr4() {addr_space = 0 : i32, dbg_expr = #[[EXPR3]]} : i64
+
+#di_file = #llvm.di_file<"not" in "existence">
+#di_compile_unit = #llvm.di_compile_unit<sourceLanguage = DW_LANG_C, file = #di_file, producer = "MLIR", isOptimized = true, emissionKind = Full>
+#di_basic_type = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "uint64_t", sizeInBits = 64, encoding = DW_ATE_unsigned>
+llvm.mlir.global external @global_with_expr1() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression<var = <scope = #di_compile_unit, name = "global_with_expr_1", linkageName = "global_with_expr_1", file = #di_file, line = 370, type = #di_basic_type, isLocalToUnit = true, isDefined = true, alignInBits = 8>, expr = <>>} : i64
+llvm.mlir.global external @global_with_expr2() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression<var = <scope = #di_compile_unit, name = "global_with_expr_2", linkageName = "global_with_expr_2", file = #di_file, line = 371, type = #di_basic_type, isLocalToUnit = true, isDefined = true, alignInBits = 8>, expr = <[DW_OP_push_object_address, DW_OP_deref]>>} : i64
+llvm.mlir.global external @global_with_expr3() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression<var = <scope = #di_compile_unit, name = "global_with_expr_3", linkageName = "global_with_expr_3", file = #di_file, line = 372, type = #di_basic_type, isLocalToUnit = true, isDefined = true, alignInBits = 8>, expr = <[DW_OP_LLVM_arg(0), DW_OP_LLVM_arg(1), DW_OP_plus]>>} : i64
+llvm.mlir.global external @global_with_expr4() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression<var = <scope = #di_compile_unit, name = "global_with_expr_4", linkageName = "global_with_expr_4", file = #di_file, line = 373, type = #di_basic_type, isLocalToUnit = true, isDefined = true, alignInBits = 8>, expr = <[DW_OP_LLVM_convert(16, DW_ATE_signed)]>>} : i64
diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll
index 51445f2..c8f40cf 100644
--- a/mlir/test/Target/LLVMIR/Import/debug-info.ll
+++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll
@@ -257,8 +257,10 @@ source_filename = "debug-info.ll"
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
define void @intrinsic(i64 %0, ptr %1) {
; CHECK: llvm.intr.dbg.declare #[[$VAR1]] = %[[ARG1]] : !llvm.ptr loc(#[[LOC1:.+]])
- ; CHECK: llvm.intr.dbg.value #[[$VAR0]] #llvm.di_expr<[4096, 0, 8]> = %[[ARG0]] : i64 loc(#[[LOC0:.+]])
- call void @llvm.dbg.value(metadata i64 %0, metadata !5, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 8)), !dbg !7
+ ; CHECK: llvm.intr.dbg.value #[[$VAR0]] #llvm.di_expression<[DW_OP_deref, DW_OP_constu(3), DW_OP_plus, DW_OP_LLVM_convert(4, DW_ATE_signed)]> = %[[ARG0]] : i64 loc(#[[LOC0:.+]])
+ ; CHECK: llvm.intr.dbg.value #[[$VAR0]] #llvm.di_expression<[DW_OP_deref, DW_OP_constu(3), DW_OP_plus, DW_OP_LLVM_fragment(3, 7)]> = %[[ARG0]] : i64 loc(#[[LOC0:.+]])
+ call void @llvm.dbg.value(metadata i64 %0, metadata !5, metadata !DIExpression(DW_OP_deref, DW_OP_constu, 3, DW_OP_plus, DW_OP_LLVM_fragment, 3, 7)), !dbg !7
+ call void @llvm.dbg.value(metadata i64 %0, metadata !5, metadata !DIExpression(DW_OP_deref, DW_OP_constu, 3, DW_OP_plus, DW_OP_LLVM_convert, 4, DW_ATE_signed)), !dbg !7
call void @llvm.dbg.declare(metadata ptr %1, metadata !6, metadata !DIExpression()), !dbg !9
; CHECK: llvm.intr.dbg.label #[[$LABEL]] loc(#[[LOC1:.+]])
call void @llvm.dbg.label(metadata !10), !dbg !9
diff --git a/mlir/test/Target/LLVMIR/Import/global-variables.ll b/mlir/test/Target/LLVMIR/Import/global-variables.ll
index daf20ea..56045d1 100644
--- a/mlir/test/Target/LLVMIR/Import/global-variables.ll
+++ b/mlir/test/Target/LLVMIR/Import/global-variables.ll
@@ -244,3 +244,29 @@ define void @bar() {
; CHECK: llvm.mlir.global external protected constant @protected(42 : i64)
@protected = protected constant i64 42
+
+; // -----
+
+; CHECK-DAG: #[[TYPE:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int", sizeInBits = 32, encoding = DW_ATE_signed>
+; CHECK-DAG: #[[FILE:.*]] = #llvm.di_file<"source.c" in "/path/to/file">
+; CHECK-DAG: #[[CU:.*]] = #llvm.di_compile_unit<sourceLanguage = DW_LANG_C99, file = #[[FILE]], isOptimized = false, emissionKind = None>
+; CHECK-DAG: #[[SPROG:.*]] = #llvm.di_subprogram<scope = #[[CU]], name = "foo", file = #[[FILE]], line = 5, subprogramFlags = Definition>
+; CHECK-DAG: #[[GVAR0:.*]] = #llvm.di_global_variable<scope = #[[SPROG]], name = "foo", linkageName = "foo", file = #[[FILE]], line = 7, type = #[[TYPE]], isLocalToUnit = true>
+; CHECK-DAG: #[[GVAR1:.*]] = #llvm.di_global_variable<scope = #[[SPROG]], name = "bar", linkageName = "bar", file = #[[FILE]], line = 8, type = #[[TYPE]], isLocalToUnit = true>
+; CHECK-DAG: #[[EXPR0:.*]] = #llvm.di_global_variable_expression<var = #[[GVAR0]], expr = <[DW_OP_LLVM_fragment(0, 16)]>>
+; CHECK-DAG: #[[EXPR1:.*]] = #llvm.di_global_variable_expression<var = #[[GVAR1]], expr = <[DW_OP_constu(3), DW_OP_plus]>>
+; CHECK-DAG: llvm.mlir.global external @foo() {addr_space = 0 : i32, alignment = 8 : i64, dbg_expr = #[[EXPR0]]} : i32
+; CHECK-DAG: llvm.mlir.global external @bar() {addr_space = 0 : i32, alignment = 8 : i64, dbg_expr = #[[EXPR1]]} : i32
+
+@foo = external global i32, align 8, !dbg !5
+@bar = external global i32, align 8, !dbg !7
+!0 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!1 = !DIFile(filename: "source.c", directory: "/path/to/file")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
+!3 = distinct !DISubprogram(name: "foo", scope: !2, file: !1, line: 5)
+!4 = !DIGlobalVariable(name: "foo", linkageName: "foo", scope: !3, file: !1, line: 7, type: !0, isLocal: true, isDefinition: false)
+!5 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression(DW_OP_LLVM_fragment, 0, 16))
+!6 = !DIGlobalVariable(name: "bar", linkageName: "bar", scope: !3, file: !1, line: 8, type: !0, isLocal: true, isDefinition: false)
+!7 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression(DW_OP_constu, 3, DW_OP_plus))
+!100 = !{i32 2, !"Debug Info Version", i32 3}
+!llvm.module.flags = !{!100}
diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir
index e088374..e62ee35 100644
--- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir
@@ -91,11 +91,13 @@ llvm.func @func_with_debug(%arg: i64) {
%allocCount = llvm.mlir.constant(1 : i32) : i32
%alloc = llvm.alloca %allocCount x i64 : (i32) -> !llvm.ptr
- // CHECK: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[VAR_LOC:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 8, 8))
- // CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOC]], metadata ![[ADDR_LOC:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 8))
+ // CHECK: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[VAR_LOC:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 1))
+ llvm.intr.dbg.value #variable #llvm.di_expression<[DW_OP_LLVM_fragment(0, 1)]> = %arg : i64
+
+ // CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOC]], metadata ![[ADDR_LOC:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_LLVM_convert, 4, DW_ATE_signed))
+ llvm.intr.dbg.declare #variableAddr #llvm.di_expression<[DW_OP_deref, DW_OP_LLVM_convert(4, DW_ATE_signed)]> = %alloc : !llvm.ptr
+
// CHECK: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[NO_NAME_VAR:[0-9]+]], metadata !DIExpression())
- llvm.intr.dbg.value #variable #llvm.di_expr<[4096, 8, 8]> = %arg : i64
- llvm.intr.dbg.declare #variableAddr #llvm.di_expr<[4096, 0, 8]> = %alloc : !llvm.ptr
llvm.intr.dbg.value #noNameVariable = %arg : i64
// CHECK: call void @func_no_debug(), !dbg ![[CALLSITE_LOC:[0-9]+]]
@@ -263,3 +265,24 @@ llvm.func @dbg_intrinsics_with_no_location(%arg0: i32) -> (i32) {
llvm.intr.dbg.label #di_label
llvm.return %arg0 : i32
}
+
+// -----
+
+// CHECK: @global_with_expr_1 = external global i64, !dbg {{.*}}
+// CHECK: @global_with_expr_2 = external global i64, !dbg {{.*}}
+// CHECK: !llvm.module.flags = !{{{.*}}}
+// CHECK: !llvm.dbg.cu = !{{{.*}}}
+// CHECK-DAG: ![[FILE:.*]] = !DIFile(filename: "not", directory: "existence")
+// CHECK-DAG: ![[TYPE:.*]] = !DIBasicType(name: "uint64_t", size: 64, encoding: DW_ATE_unsigned)
+// CHECK-DAG: ![[SCOPE:.*]] = distinct !DICompileUnit(language: DW_LANG_C, file: ![[FILE]], producer: "MLIR", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: ![[GVALS:.*]])
+// CHECK-DAG: ![[GVAR0:.*]] = distinct !DIGlobalVariable(name: "global_with_expr_1", linkageName: "global_with_expr_1", scope: ![[SCOPE]], file: ![[FILE]], line: 370, type: ![[TYPE]], isLocal: false, isDefinition: false)
+// CHECK-DAG: ![[GVAR1:.*]] = distinct !DIGlobalVariable(name: "global_with_expr_2", linkageName: "global_with_expr_2", scope: ![[SCOPE]], file: ![[FILE]], line: 371, type: ![[TYPE]], isLocal: true, isDefinition: true, align: 8)
+// CHECK-DAG: ![[GEXPR0:.*]] = !DIGlobalVariableExpression(var: ![[GVAR0]], expr: !DIExpression())
+// CHECK-DAG: ![[GEXPR1:.*]] = !DIGlobalVariableExpression(var: ![[GVAR1]], expr: !DIExpression())
+// CHECK-DAG: ![[GVALS]] = !{![[GEXPR0]], ![[GEXPR1]]}
+
+#di_file_2 = #llvm.di_file<"not" in "existence">
+#di_compile_unit_2 = #llvm.di_compile_unit<sourceLanguage = DW_LANG_C, file = #di_file_2, producer = "MLIR", isOptimized = true, emissionKind = Full>
+#di_basic_type_2 = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "uint64_t", sizeInBits = 64, encoding = DW_ATE_unsigned>
+llvm.mlir.global external @global_with_expr_1() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression<var = <scope = #di_compile_unit_2, name = "global_with_expr_1", linkageName = "global_with_expr_1", file = #di_file_2, line = 370, type = #di_basic_type_2>, expr = <>>} : i64
+llvm.mlir.global external @global_with_expr_2() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression<var = <scope = #di_compile_unit_2, name = "global_with_expr_2", linkageName = "global_with_expr_2", file = #di_file_2, line = 371, type = #di_basic_type_2, isLocalToUnit = true, isDefined = true, alignInBits = 8>, expr = <>>} : i64