Skip to content

Commit be4b494

Browse files
committed
[mlir][llvm] Import debug intrinsics from LLVMIR.
Currently, the import of LLVMIR fails if the program contains debug intrinsics. The revision adds support to import debug intrinsics that have no debug expression attached and drops all debug intrinsics with a non-empty debug expression. It also moves the existing debug intrinsics into the "intr" namespace by deriving from LLVM_IntrOp. Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D138405
1 parent 6335deb commit be4b494

File tree

8 files changed

+112
-41
lines changed

8 files changed

+112
-41
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,11 @@ def LLVM_DILocalVariableAttr : LLVM_Attr<"DILocalVariable", "di_local_variable",
274274
let parameters = (ins
275275
"DIScopeAttr":$scope,
276276
"StringAttr":$name,
277-
"DIFileAttr":$file,
278-
"unsigned":$line,
279-
"unsigned":$arg,
280-
"unsigned":$alignInBits,
281-
"DITypeAttr":$type
277+
OptionalParameter<"DIFileAttr">:$file,
278+
OptionalParameter<"unsigned">:$line,
279+
OptionalParameter<"unsigned">:$arg,
280+
OptionalParameter<"unsigned">:$alignInBits,
281+
OptionalParameter<"DITypeAttr">:$type
282282
);
283283
let builders = [
284284
AttrBuilderWithInferredContext<(ins

mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def LLVM_CoroResumeOp : LLVM_IntrOp<"coro.resume", [], [], [], 0> {
262262
// Debug function intrinsics.
263263
//
264264

265-
class LLVM_DbgIntrOp<string name> : LLVM_Op<name> {
265+
class LLVM_DbgIntrOp<string name, string argName> : LLVM_IntrOp<name, [], [], [], 0> {
266266
let llvmBuilder = [{
267267
llvm::Module *module = builder.GetInsertBlock()->getModule();
268268
llvm::LLVMContext &ctx = module->getContext();
@@ -276,27 +276,34 @@ class LLVM_DbgIntrOp<string name> : LLVM_Op<name> {
276276
llvm::MetadataAsValue::get(ctx, llvm::DIExpression::get(ctx, llvm::None)),
277277
});
278278
}];
279+
let mlirBuilder = [{
280+
// Drop all debug intrinsics with a non-empty debug expression.
281+
// TODO: Stop dropping debug intrinsics once debug expressions are
282+
// convertible to MLIR.
283+
auto *dbgIntr = cast<llvm::DbgVariableIntrinsic>(inst);
284+
if (dbgIntr->getExpression()->getNumElements() == 0)
285+
$_builder.create<$_qualCppClassName>($_location,
286+
$}] # argName # [{, $_var_attr($varInfo));
287+
}];
288+
let assemblyFormat = [{
289+
qualified($varInfo) `=` $}] # argName #
290+
[{ `:` qualified(type($}] # argName # [{)) attr-dict
291+
}];
279292
}
280293

281-
def LLVM_DbgAddrOp : LLVM_DbgIntrOp<"dbg.addr"> {
294+
def LLVM_DbgAddrOp : LLVM_DbgIntrOp<"dbg.addr", "addr"> {
282295
let summary = "Describe the current address of a local debug info variable.";
283296
let arguments = (ins LLVM_AnyPointer:$addr, LLVM_DILocalVariableAttr:$varInfo);
284-
285-
let assemblyFormat = "qualified($varInfo) `=` $addr `:` type($addr) attr-dict";
286297
}
287298

288-
def LLVM_DbgDeclareOp : LLVM_DbgIntrOp<"dbg.declare"> {
299+
def LLVM_DbgDeclareOp : LLVM_DbgIntrOp<"dbg.declare", "addr"> {
289300
let summary = "Declare the address of a local debug info variable.";
290301
let arguments = (ins LLVM_AnyPointer:$addr, LLVM_DILocalVariableAttr:$varInfo);
291-
292-
let assemblyFormat = "qualified($varInfo) `=` $addr `:` type($addr) attr-dict";
293302
}
294303

295-
def LLVM_DbgValueOp : LLVM_DbgIntrOp<"dbg.value"> {
304+
def LLVM_DbgValueOp : LLVM_DbgIntrOp<"dbg.value", "value"> {
296305
let summary = "Describe the current value of a local debug info variable.";
297306
let arguments = (ins LLVM_Type:$value, LLVM_DILocalVariableAttr:$varInfo);
298-
299-
let assemblyFormat = "qualified($varInfo) `=` $value `:` type($value) attr-dict";
300307
}
301308

302309
//

mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ class LLVM_OpBase<Dialect dialect, string mnemonic, list<Trait> traits = []> :
234234
// name matches the result name, by a reference to store the
235235
// result of the newly created MLIR operation to;
236236
// - $_int_attr - substituted by a call to an integer attribute matcher;
237+
// - $_var_attr - substituted by a call to a variable attribute matcher;
237238
// - $_resultType - substituted with the MLIR result type;
238239
// - $_location - substituted with the MLIR location;
239240
// - $_builder - substituted with the MLIR builder;

mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,10 @@ class Importer {
372372
SmallVector<Value> convertValues(ArrayRef<llvm::Value *> values);
373373

374374
/// Converts `value` to an integer attribute. Asserts if the conversion fails.
375-
IntegerAttr matchIntegerAttr(Value value);
375+
IntegerAttr matchIntegerAttr(llvm::Value *value);
376+
377+
/// Converts `value` to a local variable attribute.
378+
DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value);
376379

377380
/// Translates the debug location.
378381
Location translateLoc(llvm::DILocation *loc) {
@@ -852,6 +855,12 @@ Value Importer::convertConstantExpr(llvm::Constant *constant) {
852855
}
853856

854857
Value Importer::convertValue(llvm::Value *value) {
858+
// A value may be wrapped as metadata, for example, when passed to a debug
859+
// intrinsic. Unwrap these values before the conversion.
860+
if (auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value))
861+
if (auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata()))
862+
value = node->getValue();
863+
855864
// Return the mapped value if it has been converted before.
856865
if (valueMapping.count(value))
857866
return lookupValue(value);
@@ -872,14 +881,20 @@ SmallVector<Value> Importer::convertValues(ArrayRef<llvm::Value *> values) {
872881
return remapped;
873882
}
874883

875-
IntegerAttr Importer::matchIntegerAttr(Value value) {
884+
IntegerAttr Importer::matchIntegerAttr(llvm::Value *value) {
876885
IntegerAttr integerAttr;
877-
bool success = matchPattern(value, m_Constant(&integerAttr));
886+
bool success = matchPattern(convertValue(value), m_Constant(&integerAttr));
878887
assert(success && "expected a constant value");
879888
(void)success;
880889
return integerAttr;
881890
}
882891

892+
DILocalVariableAttr Importer::matchLocalVariableAttr(llvm::Value *value) {
893+
auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
894+
auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
895+
return debugImporter.translate(node);
896+
}
897+
883898
LogicalResult
884899
Importer::convertBranchArgs(llvm::Instruction *branch, llvm::BasicBlock *target,
885900
SmallVectorImpl<Value> &blockArguments) {

mlir/test/Dialect/LLVMIR/debuginfo.mlir

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,16 @@
8181
file = #file, line = 4, scopeLine = 4, subprogramFlags = "Definition", type = #spType1
8282
>
8383

84-
// CHECK-DAG: #[[VAR0:.*]] = #llvm.di_local_variable<scope = #[[SP0]], name = "arg", file = #[[FILE]], line = 6, arg = 1, alignInBits = 0, type = #[[INT0]]>
84+
// CHECK-DAG: #[[VAR0:.*]] = #llvm.di_local_variable<scope = #[[SP0]], name = "alloc", file = #[[FILE]], line = 6, arg = 1, alignInBits = 32, type = #[[INT0]]>
8585
#var0 = #llvm.di_local_variable<
86-
scope = #sp0, name = "arg", file = #file,
87-
line = 6, arg = 1, alignInBits = 0, type = #int0
86+
scope = #sp0, name = "alloc", file = #file,
87+
line = 6, arg = 1, alignInBits = 32, type = #int0
8888
>
8989

90-
// CHECK-DAG: #[[VAR1:.*]] = #llvm.di_local_variable<scope = #[[SP1]], name = "arg", file = #[[FILE]], line = 7, arg = 2, alignInBits = 0, type = #[[INT1]]>
90+
// CHECK-DAG: #[[VAR1:.*]] = #llvm.di_local_variable<scope = #[[SP1]], name = "arg">
9191
#var1 = #llvm.di_local_variable<
92-
scope = #sp1, name = "arg", file = #file,
93-
line = 7, arg = 2, alignInBits = 0, type = #int1
92+
// Omit the optional parameters.
93+
scope = #sp1, name = "arg"
9494
>
9595

9696
// CHECK: llvm.func @addr(%[[ARG:.*]]: i64)
@@ -99,16 +99,16 @@ llvm.func @addr(%arg: i64) {
9999
%allocCount = llvm.mlir.constant(1 : i32) : i32
100100
%alloc = llvm.alloca %allocCount x i64 : (i32) -> !llvm.ptr<i64>
101101

102-
// CHECK: llvm.dbg.addr #[[VAR0]] = %[[ALLOC]]
103-
// CHECK: llvm.dbg.declare #[[VAR0]] = %[[ALLOC]]
104-
llvm.dbg.addr #var0 = %alloc : !llvm.ptr<i64>
105-
llvm.dbg.declare #var0 = %alloc : !llvm.ptr<i64>
102+
// CHECK: llvm.intr.dbg.addr #[[VAR0]] = %[[ALLOC]]
103+
// CHECK: llvm.intr.dbg.declare #[[VAR0]] = %[[ALLOC]]
104+
llvm.intr.dbg.addr #var0 = %alloc : !llvm.ptr<i64>
105+
llvm.intr.dbg.declare #var0 = %alloc : !llvm.ptr<i64>
106106
llvm.return
107107
}
108108

109109
// CHECK: llvm.func @value(%[[ARG:.*]]: i32)
110110
llvm.func @value(%arg: i32) -> i32 {
111-
// CHECK: llvm.dbg.value #[[VAR1]] = %[[ARG]]
112-
llvm.dbg.value #var1 = %arg : i32
111+
// CHECK: llvm.intr.dbg.value #[[VAR1]] = %[[ARG]]
112+
llvm.intr.dbg.value #var1 = %arg : i32
113113
llvm.return %arg : i32
114114
}

mlir/test/Target/LLVMIR/Import/debug-info.ll

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,43 @@ define void @func_loc() !dbg !3 {
226226
; Verify the module location is set to the source filename.
227227
; CHECK: loc("debug-info.ll":0:0)
228228
source_filename = "debug-info.ll"
229+
230+
; // -----
231+
232+
; CHECK: #[[$SP:.+]] = #llvm.di_subprogram<
233+
; CHECK: #[[$VAR0:.+]] = #llvm.di_local_variable<scope = #[[$SP]], name = "arg", file = #{{.*}}, line = 1, arg = 1, alignInBits = 32, type = #{{.*}}>
234+
; CHECK: #[[$VAR1:.+]] = #llvm.di_local_variable<scope = #[[$SP]], name = "arg">
235+
236+
; CHECK-LABEL: @intrinsic
237+
; CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]
238+
; CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]
239+
define void @intrinsic(i64 %0, ptr %1) {
240+
; CHECK: llvm.intr.dbg.value #[[$VAR0]] = %[[ARG0]] : i64 loc(#[[LOC0:.+]])
241+
call void @llvm.dbg.value(metadata i64 %0, metadata !5, metadata !DIExpression()), !dbg !7
242+
; CHECK: llvm.intr.dbg.addr #[[$VAR1]] = %[[ARG1]] : !llvm.ptr loc(#[[LOC1:.+]])
243+
call void @llvm.dbg.addr(metadata ptr %1, metadata !6, metadata !DIExpression()), !dbg !8
244+
; CHECK: llvm.intr.dbg.declare #[[$VAR1]] = %[[ARG1]] : !llvm.ptr loc(#[[LOC2:.+]])
245+
call void @llvm.dbg.declare(metadata ptr %1, metadata !6, metadata !DIExpression()), !dbg !9
246+
ret void
247+
}
248+
249+
; CHECK: #[[LOC0]] = loc(fused<#[[$SP]]>["debug-info.ll":1:2])
250+
; CHECK: #[[LOC1]] = loc(fused<#[[$SP]]>["debug-info.ll":2:2])
251+
; CHECK: #[[LOC2]] = loc(fused<#[[$SP]]>["debug-info.ll":3:2])
252+
253+
declare void @llvm.dbg.value(metadata, metadata, metadata)
254+
declare void @llvm.dbg.addr(metadata, metadata, metadata)
255+
declare void @llvm.dbg.declare(metadata, metadata, metadata)
256+
257+
!llvm.dbg.cu = !{!1}
258+
!llvm.module.flags = !{!0}
259+
!0 = !{i32 2, !"Debug Info Version", i32 3}
260+
!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2)
261+
!2 = !DIFile(filename: "debug-info.ll", directory: "/")
262+
!3 = distinct !DISubprogram(name: "intrinsic", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1)
263+
!4 = !DIBasicType(name: "int")
264+
!5 = !DILocalVariable(scope: !3, name: "arg", file: !2, line: 1, arg: 1, align: 32, type: !4);
265+
!6 = !DILocalVariable(scope: !3, name: "arg")
266+
!7 = !DILocation(line: 1, column: 2, scope: !3)
267+
!8 = !DILocation(line: 2, column: 2, scope: !3)
268+
!9 = !DILocation(line: 3, column: 2, scope: !3)

mlir/test/Target/LLVMIR/llvmir-debug.mlir

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ llvm.func @func_no_debug() {
6464
>
6565
#fileScope = #llvm.di_lexical_block_file<scope = #sp, file = #file, discriminator = 0>
6666
#variable = #llvm.di_local_variable<scope = #fileScope, name = "arg", file = #file, line = 6, arg = 1, alignInBits = 0, type = #si64>
67+
#variableAddr = #llvm.di_local_variable<scope = #fileScope, name = "alloc">
6768

6869
// CHECK-LABEL: define void @func_with_debug(
6970
// CHECK-SAME: i64 %[[ARG:.*]]) !dbg ![[FUNC_LOC:[0-9]+]]
@@ -73,11 +74,11 @@ llvm.func @func_with_debug(%arg: i64) {
7374
%alloc = llvm.alloca %allocCount x i64 : (i32) -> !llvm.ptr<i64>
7475

7576
// CHECK: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[VAR_LOC:[0-9]+]], metadata !DIExpression())
76-
// CHECK: call void @llvm.dbg.addr(metadata ptr %[[ALLOC]], metadata ![[VAR_LOC]], metadata !DIExpression())
77-
// CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOC]], metadata ![[VAR_LOC]], metadata !DIExpression())
78-
llvm.dbg.value #variable = %arg : i64
79-
llvm.dbg.addr #variable = %alloc : !llvm.ptr<i64>
80-
llvm.dbg.declare #variable = %alloc : !llvm.ptr<i64>
77+
// CHECK: call void @llvm.dbg.addr(metadata ptr %[[ALLOC]], metadata ![[ADDR_LOC:[0-9]+]], metadata !DIExpression())
78+
// CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOC]], metadata ![[ADDR_LOC]], metadata !DIExpression())
79+
llvm.intr.dbg.value #variable = %arg : i64
80+
llvm.intr.dbg.addr #variableAddr = %alloc : !llvm.ptr<i64>
81+
llvm.intr.dbg.declare #variableAddr = %alloc : !llvm.ptr<i64>
8182

8283
// CHECK: call void @func_no_debug(), !dbg ![[CALLSITE_LOC:[0-9]+]]
8384
llvm.call @func_no_debug() : () -> () loc(callsite("mysource.cc":3:4 at "mysource.cc":5:6))
@@ -116,6 +117,7 @@ llvm.func @func_with_debug(%arg: i64) {
116117

117118
// CHECK: ![[VAR_LOC]] = !DILocalVariable(name: "arg", arg: 1, scope: ![[VAR_SCOPE:.*]], file: ![[CU_FILE_LOC]], line: 6, type: ![[ARG_TYPE]])
118119
// CHECK: ![[VAR_SCOPE]] = distinct !DILexicalBlockFile(scope: ![[FUNC_LOC]], file: ![[CU_FILE_LOC]], discriminator: 0)
120+
// CHECK: ![[ADDR_LOC]] = !DILocalVariable(name: "alloc", scope: ![[VAR_SCOPE:.*]])
119121

120122
// CHECK-DAG: ![[CALLSITE_LOC]] = !DILocation(line: 3, column: 4,
121123
// CHECK-DAG: ![[FILE_LOC]] = !DILocation(line: 1, column: 2,

mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,18 +237,24 @@ static LogicalResult emitOneMLIRBuilder(const Record &record, raw_ostream &os,
237237
return emitError(
238238
record, "expected non-negative operand index for argument " + name);
239239
}
240-
bool isVariadicOperand = isVariadicOperandName(op, name);
241-
auto result =
242-
isVariadicOperand
243-
? formatv("convertValues(llvmOperands.drop_front({0}))", idx)
244-
: formatv("convertValue(llvmOperands[{0}])", idx);
245-
bs << result;
240+
if (isAttributeName(op, name)) {
241+
bs << formatv("llvmOperands[{0}]", idx);
242+
} else {
243+
bool isVariadicOperand = isVariadicOperandName(op, name);
244+
auto result =
245+
isVariadicOperand
246+
? formatv("convertValues(llvmOperands.drop_front({0}))", idx)
247+
: formatv("convertValue(llvmOperands[{0}])", idx);
248+
bs << result;
249+
}
246250
} else if (isResultName(op, name)) {
247251
if (op.getNumResults() != 1)
248252
return emitError(record, "expected op to have one result");
249253
bs << formatv("mapValue(inst)");
250254
} else if (name == "_int_attr") {
251255
bs << "matchIntegerAttr";
256+
} else if (name == "_var_attr") {
257+
bs << "matchLocalVariableAttr";
252258
} else if (name == "_resultType") {
253259
bs << "convertType(inst->getType())";
254260
} else if (name == "_location") {

0 commit comments

Comments
 (0)