diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -518,6 +518,31 @@ let assemblyFormat = "`<` struct(params) `>`"; } +//===----------------------------------------------------------------------===// +// DILabelAttr +//===----------------------------------------------------------------------===// + +def LLVM_DILabelAttr : LLVM_Attr<"DILabel", "di_label", + /*traits=*/[], "DINodeAttr"> { + let parameters = (ins + "DIScopeAttr":$scope, + OptionalParameter<"StringAttr">:$name, + OptionalParameter<"DIFileAttr">:$file, + OptionalParameter<"unsigned">:$line + ); + let builders = [ + AttrBuilderWithInferredContext<(ins + "DIScopeAttr":$scope, "StringRef":$name, "DIFileAttr":$file, + "unsigned":$line + ), [{ + MLIRContext *ctx = scope.getContext(); + return $_get(ctx, scope, StringAttr::get(ctx, name), file, line); + }]> + ]; + + let assemblyFormat = "`<` struct(params) `>`"; +} + //===----------------------------------------------------------------------===// // MemoryEffectsAttr //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -287,7 +287,7 @@ # setAliasAnalysisMetadataCode; } -def LLVM_MemsetOp : LLVM_ZeroResultIntrOp<"memset", [0, 2], +def LLVM_MemsetOp : LLVM_ZeroResultIntrOp<"memset", [0, 2], [DeclareOpInterfaceMethods, DeclareOpInterfaceMethods, DeclareOpInterfaceMethods], @@ -557,17 +557,35 @@ }]; } -def LLVM_DbgDeclareOp : LLVM_DbgIntrOp< "dbg.declare", "addr", +def LLVM_DbgDeclareOp : LLVM_DbgIntrOp<"dbg.declare", "addr", [DeclareOpInterfaceMethods]> { - let summary = "Declare the address of a local debug info variable."; + let summary = "Describes how the address relates to a source language variable."; let arguments = (ins LLVM_AnyPointer:$addr, LLVM_DILocalVariableAttr:$varInfo); } def LLVM_DbgValueOp : LLVM_DbgIntrOp<"dbg.value", "value"> { - let summary = "Describe the current value of a local debug info variable."; + let summary = "Describes how the value relates to a source language variable."; let arguments = (ins LLVM_Type:$value, LLVM_DILocalVariableAttr:$varInfo); } +def LLVM_DbgLabelOp : LLVM_IntrOp<"dbg.label", [], [], [], 0> { + let summary = "Relates the program to a debug information label."; + let arguments = (ins LLVM_DILabelAttr:$label); + let llvmBuilder = [{ + llvm::Module *module = builder.GetInsertBlock()->getModule(); + llvm::LLVMContext &ctx = module->getContext(); + llvm::Function *fn = + llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::dbg_label); + builder.CreateCall(fn, { + llvm::MetadataAsValue::get(ctx, moduleTranslation.translateDebugInfo($label)) + }); + }]; + let mlirBuilder = [{ + $_op = $_builder.create<$_qualCppClassName>($_location, $_label_attr($label)); + }]; + let assemblyFormat = "$label attr-dict"; +} + // // Variadic function intrinsics. // diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -91,12 +91,12 @@ // Type constraint accepting LLVM target extension types with no support for // memory operations such as alloca, load and store. def LLVM_NonLoadableTargetExtType : Type< - And<[LLVM_AnyTargetExt.predicate, + And<[LLVM_AnyTargetExt.predicate, CPred<"!::llvm::cast<::mlir::LLVM::LLVMTargetExtType>($_self).supportsMemOps()">] >>; // Type constraint accepting any LLVM type that can be loaded or stored, i.e. a -// type that has size (not void, function, opaque struct type or target +// type that has size (not void, function, opaque struct type or target // extension type which does not support memory operations). def LLVM_LoadableType : Type< Or<[And<[LLVM_PrimitiveType.predicate, Neg, @@ -174,6 +174,7 @@ // - $_int_attr - substituted by a call to an integer attribute matcher; // - $_float_attr - substituted by a call to a float attribute matcher; // - $_var_attr - substituted by a call to a variable attribute matcher; + // - $_label_attr - substituted by a call to a label attribute matcher; // - $_resultType - substituted with the MLIR result type; // - $_location - substituted with the MLIR location; // - $_builder - substituted with the MLIR builder; diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -148,6 +148,9 @@ /// fails. DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value); + /// Converts `value` to a label attribute. Asserts if the matching fails. + DILabelAttr matchLabelAttr(llvm::Value *value); + /// Converts `value` to an array of symbol references pointing to alias scope /// operations, or returns failure if the conversion fails. FailureOr> diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -43,10 +43,11 @@ bool DINodeAttr::classof(Attribute attr) { return llvm::isa(attr); + DIDerivedTypeAttr, DIFileAttr, DILabelAttr, + DILexicalBlockAttr, DILexicalBlockFileAttr, + DILocalVariableAttr, DINamespaceAttr, DINullTypeAttr, + DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>( + attr); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -3063,7 +3063,7 @@ AliasResult getAlias(Attribute attr, raw_ostream &os) const override { return TypeSwitch(attr) .CasegetFilename(), node->getDirectory()); } +DILabelAttr DebugImporter::translateImpl(llvm::DILabel *node) { + return DILabelAttr::get(context, translate(node->getScope()), + getStringAttrOrNull(node->getRawName()), + translate(node->getFile()), node->getLine()); +} + DILexicalBlockAttr DebugImporter::translateImpl(llvm::DILexicalBlock *node) { return DILexicalBlockAttr::get(context, translate(node->getScope()), translate(node->getFile()), node->getLine(), @@ -200,6 +206,8 @@ return translateImpl(casted); if (auto *casted = dyn_cast(node)) return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); if (auto *casted = dyn_cast(node)) return translateImpl(casted); if (auto *casted = dyn_cast(node)) diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.h b/mlir/lib/Target/LLVMIR/DebugTranslation.h --- a/mlir/lib/Target/LLVMIR/DebugTranslation.h +++ b/mlir/lib/Target/LLVMIR/DebugTranslation.h @@ -67,6 +67,7 @@ llvm::DICompositeType *translateImpl(DICompositeTypeAttr attr); llvm::DIDerivedType *translateImpl(DIDerivedTypeAttr attr); llvm::DIFile *translateImpl(DIFileAttr attr); + llvm::DILabel *translateImpl(DILabelAttr attr); llvm::DILexicalBlock *translateImpl(DILexicalBlockAttr attr); llvm::DILexicalBlockFile *translateImpl(DILexicalBlockFileAttr attr); llvm::DILocalScope *translateImpl(DILocalScopeAttr attr); diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp --- a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp @@ -149,6 +149,12 @@ getMDStringOrNull(attr.getDirectory())); } +llvm::DILabel *DebugTranslation::translateImpl(DILabelAttr attr) { + return llvm::DILabel::get(llvmCtx, translate(attr.getScope()), + getMDStringOrNull(attr.getName()), + translate(attr.getFile()), attr.getLine()); +} + llvm::DILexicalBlock *DebugTranslation::translateImpl(DILexicalBlockAttr attr) { return llvm::DILexicalBlock::getDistinct(llvmCtx, translate(attr.getScope()), translate(attr.getFile()), @@ -247,7 +253,7 @@ llvm::DINode *node = TypeSwitch(attr) .Case( diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -1255,6 +1255,12 @@ return debugImporter->translate(node); } +DILabelAttr ModuleImport::matchLabelAttr(llvm::Value *value) { + auto *nodeAsVal = cast(value); + auto *node = cast(nodeAsVal->getMetadata()); + return debugImporter->translate(node); +} + FailureOr> ModuleImport::matchAliasScopeAttrs(llvm::Value *value) { auto *nodeAsVal = cast(value); diff --git a/mlir/test/Dialect/LLVMIR/debuginfo.mlir b/mlir/test/Dialect/LLVMIR/debuginfo.mlir --- a/mlir/test/Dialect/LLVMIR/debuginfo.mlir +++ b/mlir/test/Dialect/LLVMIR/debuginfo.mlir @@ -136,6 +136,12 @@ scope = #block2, name = "arg2" > +// CHECK-DAG: #[[LABEL1:.*]] = #llvm.di_label +#label1 = #llvm.di_label + +// CHECK-DAG: #[[LABEL2:.*]] = #llvm.di_label +#label2 = #llvm.di_label + // CHECK: llvm.func @addr(%[[ARG:.*]]: i64) llvm.func @addr(%arg: i64) { // CHECK: %[[ALLOC:.*]] = llvm.alloca @@ -153,5 +159,9 @@ llvm.intr.dbg.value #var1 = %arg1 : i32 // CHECK: llvm.intr.dbg.value #[[VAR2]] = %[[ARG2]] llvm.intr.dbg.value #var2 = %arg2 : i32 + // CHECK: llvm.intr.dbg.label #[[LABEL1]] + llvm.intr.dbg.label #label1 + // CHECK: llvm.intr.dbg.label #[[LABEL2]] + llvm.intr.dbg.label #label2 llvm.return } diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll --- a/mlir/test/Target/LLVMIR/Import/debug-info.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll @@ -233,8 +233,10 @@ ; // ----- +; CHECK: #[[FILE:.+]] = #llvm.di_file< ; CHECK: #[[$SP:.+]] = #llvm.di_subprogram< -; CHECK: #[[$VAR0:.+]] = #llvm.di_local_variable +; CHECK: #[[$LABEL:.+]] = #llvm.di_label +; CHECK: #[[$VAR0:.+]] = #llvm.di_local_variable ; CHECK: #[[$VAR1:.+]] = #llvm.di_local_variable ; CHECK-LABEL: @intrinsic @@ -245,6 +247,8 @@ call void @llvm.dbg.value(metadata i64 %0, metadata !5, metadata !DIExpression()), !dbg !7 ; CHECK: llvm.intr.dbg.declare #[[$VAR1]] = %[[ARG1]] : !llvm.ptr loc(#[[LOC1:.+]]) 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 ret void } @@ -253,6 +257,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @llvm.dbg.label(metadata) !llvm.dbg.cu = !{!1} !llvm.module.flags = !{!0} @@ -266,6 +271,8 @@ !7 = !DILocation(line: 1, column: 2, scope: !3) !8 = !DILocation(line: 2, column: 2, scope: !3) !9 = !DILocation(line: 3, column: 2, scope: !3) +!10 = !DILabel(scope: !3, name: "label", file: !2, line: 42) + ; // ----- diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir --- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir @@ -176,6 +176,7 @@ #di_local_variable0 = #llvm.di_local_variable #di_lexical_block_file = #llvm.di_lexical_block_file #di_local_variable1 = #llvm.di_local_variable +#di_label = #llvm.di_label #loc0 = loc("foo.mlir":0:0) #loc1 = loc(callsite(#loc0 at fused<#di_subprogram>["foo.mlir":4:2])) @@ -187,6 +188,8 @@ llvm.intr.dbg.value #di_local_variable0 = %arg0 : i32 loc(fused<#di_subprogram>[#loc0]) // CHECK: call void @llvm.dbg.value(metadata i32 %[[ARG]], metadata ![[VAR_LOC1:[0-9]+]], metadata !DIExpression()), !dbg ![[DBG_LOC1:.*]] llvm.intr.dbg.value #di_local_variable1 = %arg0 : i32 loc(fused<#di_lexical_block_file>[#loc1]) + // CHECK: call void @llvm.dbg.label(metadata ![[LABEL:[0-9]+]]), !dbg ![[DBG_LOC1:.*]] + llvm.intr.dbg.label #di_label loc(fused<#di_lexical_block_file>[#loc1]) llvm.return %arg0 : i32 } loc(fused<#di_subprogram>["caller"]) @@ -196,3 +199,4 @@ // CHECK-DAG: ![[LEXICAL_BLOCK_FILE:.*]] = distinct !DILexicalBlockFile(scope: ![[INNER_FUNC]], file: ![[FILE]], discriminator: 0) // CHECK-DAG: ![[VAR_LOC0]] = !DILocalVariable(name: "a", scope: ![[OUTER_FUNC]], file: ![[FILE]] // CHECK-DAG: ![[VAR_LOC1]] = !DILocalVariable(name: "b", scope: ![[LEXICAL_BLOCK_FILE]], file: ![[FILE]] +// CHECK-DAG ![[LABEL]] = !DILabel(scope: ![[LEXICAL_BLOCK_FILE]], name: "label", file: ![[FILE]], line: 42) diff --git a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp --- a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp +++ b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp @@ -270,6 +270,8 @@ bs << "moduleImport.matchFloatAttr"; } else if (name == "_var_attr") { bs << "moduleImport.matchLocalVariableAttr"; + } else if (name == "_label_attr") { + bs << "moduleImport.matchLabelAttr"; } else if (name == "_resultType") { bs << "moduleImport.convertType(inst->getType())"; } else if (name == "_location") {