[mlir][llvm] Add an explicit void type debug info attribute.

Previously, the DISubroutineType attribute used an optional result
parameter and an optional argument types array to model the subroutine
signature. LLVM IR debug metadata, on the other hand, has one types
list whose first entry maps to the result type. That entry may be
null to model a void result type. The type list may also be entirely
empty not specifying any type information. The latter is problematic
since the current DISubroutineType attribute cannot express it.

The revision changes DISubroutineTypeAttr to closely follow the
LLVM metadata design. In particular, it uses a single types parameter
array to model the subroutine signature and introduces an explicit
DIVoidResultTypeAttr to model the null entries.

Reviewed By: Dinistro

Differential Revision: https://reviews.llvm.org/D141261
This commit is contained in:
Tobias Gysi
2023-01-12 17:32:22 +01:00
parent e866fb8606
commit a960547ea1
10 changed files with 150 additions and 63 deletions

View File

@@ -122,6 +122,15 @@ def LLVM_DITagParameter : LLVM_DIParameter<
"tag", /*default=*/"", "Tag"
>;
//===----------------------------------------------------------------------===//
// DIVoidResultTypeAttr
//===----------------------------------------------------------------------===//
def LLVM_DIVoidResultTypeAttr : LLVM_Attr<"DIVoidResultType", "di_void_result_type",
/*traits=*/[], "DITypeAttr"> {
let parameters = (ins);
}
//===----------------------------------------------------------------------===//
// DIBasicTypeAttr
//===----------------------------------------------------------------------===//
@@ -353,16 +362,15 @@ def LLVM_DISubroutineTypeAttr : LLVM_Attr<"DISubroutineType", "di_subroutine_typ
], "DITypeAttr"> {
let parameters = (ins
LLVM_DICallingConventionParameter:$callingConvention,
OptionalParameter<"DITypeAttr">:$resultType,
OptionalArrayRefParameter<"DITypeAttr">:$argumentTypes
OptionalArrayRefParameter<"DITypeAttr">:$types
);
let builders = [
TypeBuilder<(ins "DITypeAttr":$resultType,
"ArrayRef<DITypeAttr>":$argumentTypes), [{
return $_get($_ctxt, /*callingConvention=*/0, resultType, argumentTypes);
TypeBuilder<(ins "ArrayRef<DITypeAttr>":$types), [{
return $_get($_ctxt, /*callingConvention=*/0, types);
}]>
];
let assemblyFormat = "`<` struct(params) `>`";
let genVerifyDecl = 1;
}
#endif // LLVMIR_ATTRDEFS

View File

@@ -14,6 +14,7 @@
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/DialectImplementation.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/BinaryFormat/Dwarf.h"
@@ -41,11 +42,11 @@ void LLVMDialect::registerAttributes() {
//===----------------------------------------------------------------------===//
bool DINodeAttr::classof(Attribute attr) {
return llvm::isa<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
DIDerivedTypeAttr, DIFileAttr, DILexicalBlockAttr,
DILexicalBlockFileAttr, DILocalVariableAttr,
DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
attr);
return llvm::isa<DIVoidResultTypeAttr, DIBasicTypeAttr, DICompileUnitAttr,
DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
DILexicalBlockAttr, DILexicalBlockFileAttr,
DILocalVariableAttr, DISubprogramAttr, DISubrangeAttr,
DISubroutineTypeAttr>(attr);
}
//===----------------------------------------------------------------------===//
@@ -63,8 +64,23 @@ bool DIScopeAttr::classof(Attribute attr) {
//===----------------------------------------------------------------------===//
bool DITypeAttr::classof(Attribute attr) {
return llvm::isa<DIBasicTypeAttr, DICompositeTypeAttr, DIDerivedTypeAttr,
DISubroutineTypeAttr>(attr);
return llvm::isa<DIVoidResultTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
DIDerivedTypeAttr, DISubroutineTypeAttr>(attr);
}
//===----------------------------------------------------------------------===//
// DISubroutineTypeAttr
//===----------------------------------------------------------------------===//
LogicalResult
DISubroutineTypeAttr::verify(function_ref<InFlightDiagnostic()> emitError,
unsigned int callingConventions,
ArrayRef<DITypeAttr> types) {
if (llvm::any_of(llvm::drop_begin(types), [](DITypeAttr type) {
return type.isa<DIVoidResultTypeAttr>();
}))
return emitError() << "expected subroutine to have non-void argument types";
return success();
}
//===----------------------------------------------------------------------===//

View File

@@ -2810,10 +2810,10 @@ struct LLVMOpAsmDialectInterface : public OpAsmDialectInterface {
AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
return TypeSwitch<Attribute, AliasResult>(attr)
.Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
DIDerivedTypeAttr, DIFileAttr, DILexicalBlockAttr,
DILexicalBlockFileAttr, DILocalVariableAttr, DISubprogramAttr,
DISubroutineTypeAttr>([&](auto attr) {
.Case<DIVoidResultTypeAttr, DIBasicTypeAttr, DICompileUnitAttr,
DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
DISubprogramAttr, DISubroutineTypeAttr>([&](auto attr) {
os << decltype(attr)::getMnemonic();
return AliasResult::OverridableAlias;
})

View File

@@ -129,15 +129,19 @@ DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
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));
SmallVector<DITypeAttr> types;
for (llvm::DIType *type : node->getTypeArray()) {
if (!type) {
// A nullptr entry at the beginning of the subroutine types list models a
// void result type. Translate the nullptr to an explicit
// DIVoidResultTypeAttr since the attribute list cannot contain a nullptr
// entry.
types.push_back(DIVoidResultTypeAttr::get(context));
continue;
}
types.push_back(translate(type));
}
return DISubroutineTypeAttr::get(context, node->getCC(), resultType,
argumentTypes);
return DISubroutineTypeAttr::get(context, node->getCC(), types);
}
DITypeAttr DebugImporter::translateImpl(llvm::DIType *node) {

View File

@@ -88,6 +88,14 @@ void DebugTranslation::translate(LLVMFuncOp func, llvm::Function &llvmFunc) {
// Attributes
//===----------------------------------------------------------------------===//
llvm::DIType *DebugTranslation::translateImpl(DIVoidResultTypeAttr attr) {
// A DIVoidResultTypeAttr at the beginning of the subroutine types list models
// a void result type. Translate the explicit DIVoidResultTypeAttr to a
// nullptr since LLVM IR metadata does not have an explicit void result type
// representation.
return nullptr;
}
llvm::DIBasicType *DebugTranslation::translateImpl(DIBasicTypeAttr attr) {
return llvm::DIBasicType::get(
llvmCtx, attr.getTag(), attr.getName(), attr.getSizeInBits(),
@@ -201,8 +209,8 @@ llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) {
llvm::DISubroutineType *
DebugTranslation::translateImpl(DISubroutineTypeAttr attr) {
// Concatenate the result and argument types into a single array.
SmallVector<llvm::Metadata *> types = {translate(attr.getResultType())};
for (DITypeAttr type : attr.getArgumentTypes())
SmallVector<llvm::Metadata *> types;
for (DITypeAttr type : attr.getTypes())
types.push_back(translate(type));
return llvm::DISubroutineType::get(
llvmCtx, llvm::DINode::FlagZero, attr.getCallingConvention(),
@@ -222,10 +230,10 @@ llvm::DINode *DebugTranslation::translate(DINodeAttr attr) {
llvm::DINode *node =
TypeSwitch<DINodeAttr, llvm::DINode *>(attr)
.Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
DIDerivedTypeAttr, DIFileAttr, DILexicalBlockAttr,
DILexicalBlockFileAttr, DILocalVariableAttr, DISubprogramAttr,
DISubrangeAttr, DISubroutineTypeAttr>(
.Case<DIVoidResultTypeAttr, DIBasicTypeAttr, DICompileUnitAttr,
DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
[&](auto attr) { return translateImpl(attr); });
attrToNode.insert({attr, node});
return node;

View File

@@ -61,6 +61,7 @@ private:
llvm::DIFile *translateFile(StringRef fileName);
/// Translate the given attribute to the corresponding llvm debug metadata.
llvm::DIType *translateImpl(DIVoidResultTypeAttr attr);
llvm::DIBasicType *translateImpl(DIBasicTypeAttr attr);
llvm::DICompileUnit *translateImpl(DICompileUnitAttr attr);
llvm::DICompositeType *translateImpl(DICompositeTypeAttr attr);

View File

@@ -9,6 +9,9 @@
isOptimized = true, emissionKind = Full
>
// CHECK-DAG: #[[VOID:.*]] = #llvm.di_void_result_type
#void = #llvm.di_void_result_type
// CHECK-DAG: #[[INT0:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int0">
#int0 = #llvm.di_basic_type<
// Omit the optional sizeInBits and encoding parameters.
@@ -53,15 +56,21 @@
flags = "TypePassByReference|NonTrivial"
>
// CHECK-DAG: #[[SPTYPE0:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, argumentTypes = #[[INT0]], #[[PTR0]], #[[PTR1]], #[[COMP0:.*]], #[[COMP1:.*]], #[[COMP2:.*]]>
// CHECK-DAG: #[[SPTYPE0:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #[[VOID]], #[[INT0]], #[[PTR0]], #[[PTR1]], #[[COMP0:.*]], #[[COMP1:.*]], #[[COMP2:.*]]>
#spType0 = #llvm.di_subroutine_type<
callingConvention = DW_CC_normal, argumentTypes = #int0, #ptr0, #ptr1, #comp0, #comp1, #comp2
callingConvention = DW_CC_normal, types = #void, #int0, #ptr0, #ptr1, #comp0, #comp1, #comp2
>
// CHECK-DAG: #[[SPTYPE1:.*]] = #llvm.di_subroutine_type<resultType = #[[INT1]], argumentTypes = #[[INT1]]>
// CHECK-DAG: #[[SPTYPE1:.*]] = #llvm.di_subroutine_type<types = #[[INT1]], #[[INT1]]>
#spType1 = #llvm.di_subroutine_type<
// Omit the optional callingConvention parameter.
resultType = #int1, argumentTypes = #int1
types = #int1, #int1
>
// CHECK-DAG: #[[SPTYPE2:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
#spType2 = #llvm.di_subroutine_type<
// Omit the optional types parameter array.
callingConvention = DW_CC_normal
>
// CHECK-DAG: #[[SP0:.*]] = #llvm.di_subprogram<compileUnit = #[[CU]], scope = #[[FILE]], name = "addr", linkageName = "addr", file = #[[FILE]], line = 3, scopeLine = 3, subprogramFlags = "Definition|Optimized", type = #[[SPTYPE0]]>
@@ -77,22 +86,38 @@
file = #file, subprogramFlags = "Definition", type = #spType1
>
// CHECK-DAG: #[[SP2:.*]] = #llvm.di_subprogram<compileUnit = #[[CU]], scope = #[[FILE]], name = "value", file = #[[FILE]], subprogramFlags = Definition, type = #[[SPTYPE2]]>
#sp2 = #llvm.di_subprogram<
// Omit the optional linkageName parameter.
compileUnit = #cu, scope = #file, name = "value",
file = #file, subprogramFlags = "Definition", type = #spType2
>
// CHECK-DAG: #[[BLOCK0:.*]] = #llvm.di_lexical_block<scope = #[[SP0]], line = 1, column = 2>
#block0 = #llvm.di_lexical_block<scope = #sp0, line = 1, column = 2>
// CHECK-DAG: #[[BLOCK1:.*]] = #llvm.di_lexical_block<scope = #[[SP1]]>
#block1 = #llvm.di_lexical_block<scope = #sp1>
// CHECK-DAG: #[[BLOCK2:.*]] = #llvm.di_lexical_block<scope = #[[SP2]]>
#block2 = #llvm.di_lexical_block<scope = #sp2>
// CHECK-DAG: #[[VAR0:.*]] = #llvm.di_local_variable<scope = #[[BLOCK0]], name = "alloc", file = #[[FILE]], line = 6, arg = 1, alignInBits = 32, type = #[[INT0]]>
#var0 = #llvm.di_local_variable<
scope = #block0, name = "alloc", file = #file,
line = 6, arg = 1, alignInBits = 32, type = #int0
>
// CHECK-DAG: #[[VAR1:.*]] = #llvm.di_local_variable<scope = #[[BLOCK1]], name = "arg">
// CHECK-DAG: #[[VAR1:.*]] = #llvm.di_local_variable<scope = #[[BLOCK1]], name = "arg1">
#var1 = #llvm.di_local_variable<
// Omit the optional parameters.
scope = #block1, name = "arg"
scope = #block1, name = "arg1"
>
// CHECK-DAG: #[[VAR2:.*]] = #llvm.di_local_variable<scope = #[[BLOCK2]], name = "arg2">
#var2 = #llvm.di_local_variable<
// Omit the optional parameters.
scope = #block2, name = "arg2"
>
// CHECK: llvm.func @addr(%[[ARG:.*]]: i64)
@@ -108,9 +133,11 @@ llvm.func @addr(%arg: i64) {
llvm.return
}
// CHECK: llvm.func @value(%[[ARG:.*]]: i32)
llvm.func @value(%arg: i32) -> i32 {
// CHECK: llvm.intr.dbg.value #[[VAR1]] = %[[ARG]]
llvm.intr.dbg.value #var1 = %arg : i32
llvm.return %arg : i32
// CHECK: llvm.func @value(%[[ARG1:.*]]: i32, %[[ARG2:.*]]: i32)
llvm.func @value(%arg1: i32, %arg2: i32) {
// CHECK: llvm.intr.dbg.value #[[VAR1]] = %[[ARG1]]
llvm.intr.dbg.value #var1 = %arg1 : i32
// CHECK: llvm.intr.dbg.value #[[VAR2]] = %[[ARG2]]
llvm.intr.dbg.value #var2 = %arg2 : i32
llvm.return
}

View File

@@ -1392,3 +1392,9 @@ func.func @extract_scalable_from_fixed_length_vector(%arg0 : vector<16xf32>) {
// expected-error@+1 {{op failed to verify that it is not extracting scalable from fixed-length vectors.}}
%0 = llvm.intr.vector.extract %arg0[0] : vector<[8]xf32> from vector<16xf32>
}
// -----
#void = #llvm.di_void_result_type
// expected-error@below {{expected subroutine to have non-void argument types}}
#void_argument_type = #llvm.di_subroutine_type<types = #void, #void>

View File

@@ -112,9 +112,10 @@ define i32 @lexical_block_file(i32 %arg1) {
; // -----
; CHECK: #[[INT1:.+]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int1">
; CHECK: #[[INT2:.+]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int2", sizeInBits = 32, encoding = DW_ATE_signed>
; CHECK: #llvm.di_subroutine_type<argumentTypes = #[[INT1]], #[[INT2]]>
; CHECK-DAG: #[[VOID:.+]] = #llvm.di_void_result_type
; CHECK-DAG: #[[INT1:.+]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int1">
; CHECK-DAG: #[[INT2:.+]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int2", sizeInBits = 32, encoding = DW_ATE_signed>
; CHECK-DAG: #llvm.di_subroutine_type<types = #[[VOID]], #[[INT1]], #[[INT2]]>
define void @basic_type() !dbg !3 {
ret void
@@ -136,7 +137,7 @@ define void @basic_type() !dbg !3 {
; CHECK: #[[INT:.+]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int">
; CHECK: #[[PTR1:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[INT]]>
; CHECK: #[[PTR2:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, name = "mypointer", baseType = #[[INT]], sizeInBits = 64, alignInBits = 32, offsetInBits = 4>
; CHECK: #llvm.di_subroutine_type<argumentTypes = #[[PTR1]], #[[PTR2]]>
; CHECK: #llvm.di_subroutine_type<types = #[[PTR1]], #[[PTR2]]>
define void @derived_type() !dbg !3 {
ret void
@@ -149,7 +150,7 @@ define void @derived_type() !dbg !3 {
!2 = !DIFile(filename: "debug-info.ll", directory: "/")
!3 = distinct !DISubprogram(name: "derived_type", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1, type: !4)
!4 = !DISubroutineType(types: !5)
!5 = !{null, !7, !8}
!5 = !{!7, !8}
!6 = !DIBasicType(name: "int")
!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6)
!8 = !DIDerivedType(name: "mypointer", tag: DW_TAG_pointer_type, baseType: !6, size: 64, align: 32, offset: 4)
@@ -162,7 +163,7 @@ define void @derived_type() !dbg !3 {
; CHECK-DAG: #[[COMP2:.+]] = #llvm.di_composite_type<{{.*}}, file = #[[FILE]], scope = #[[FILE]], baseType = #[[INT]]>
; CHECK-DAG: #[[COMP3:.+]] = #llvm.di_composite_type<{{.*}}, flags = Vector, elements = #llvm.di_subrange<count = 4 : i64>>
; CHECK-DAG: #[[COMP4:.+]] = #llvm.di_composite_type<{{.*}}, flags = Vector, elements = #llvm.di_subrange<lowerBound = 0 : i64, upperBound = 4 : i64, stride = 1 : i64>>
; CHECK-DAG: #llvm.di_subroutine_type<argumentTypes = #[[COMP1]], #[[COMP2]], #[[COMP3]], #[[COMP4]]>
; CHECK-DAG: #llvm.di_subroutine_type<types = #[[COMP1]], #[[COMP2]], #[[COMP3]], #[[COMP4]]>
define void @composite_type() !dbg !3 {
ret void
@@ -175,7 +176,7 @@ define void @composite_type() !dbg !3 {
!2 = !DIFile(filename: "debug-info.ll", directory: "/")
!3 = distinct !DISubprogram(name: "composite_type", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1, type: !4)
!4 = !DISubroutineType(types: !5)
!5 = !{null, !7, !8, !9, !10}
!5 = !{!7, !8, !9, !10}
!6 = !DIBasicType(name: "int")
!7 = !DICompositeType(tag: DW_TAG_array_type, name: "array1", line: 10, size: 128, align: 32)
!8 = !DICompositeType(tag: DW_TAG_array_type, name: "array2", file: !2, scope: !2, baseType: !6)
@@ -188,11 +189,11 @@ define void @composite_type() !dbg !3 {
; // -----
; CHECK: #[[INT:.+]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int">
; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/">
; CHECK: #[[CU:.+]] = #llvm.di_compile_unit<sourceLanguage = DW_LANG_C, file = #[[FILE]], producer = "", isOptimized = false, emissionKind = None>
; CHECK: #[[SP_TYPE:.+]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, resultType = #[[INT]], argumentTypes = #[[INT]]>
; CHECK: #[[SP:.+]] = #llvm.di_subprogram<compileUnit = #[[CU]], scope = #[[FILE]], name = "subprogram", linkageName = "subprogram", file = #[[FILE]], line = 42, scopeLine = 42, subprogramFlags = Definition, type = #[[SP_TYPE]]>
; CHECK-DAG: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/">
; CHECK-DAG: #[[CU:.+]] = #llvm.di_compile_unit<sourceLanguage = DW_LANG_C, file = #[[FILE]], producer = "", isOptimized = false, emissionKind = None>
; Verify an empty subroutine types list is supported.
; CHECK-DAG: #[[SP_TYPE:.+]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
; CHECK-DAG: #[[SP:.+]] = #llvm.di_subprogram<compileUnit = #[[CU]], scope = #[[FILE]], name = "subprogram", linkageName = "subprogram", file = #[[FILE]], line = 42, scopeLine = 42, subprogramFlags = Definition, type = #[[SP_TYPE]]>
define void @subprogram() !dbg !3 {
ret void
@@ -205,7 +206,7 @@ define void @subprogram() !dbg !3 {
!2 = !DIFile(filename: "debug-info.ll", directory: "/")
!3 = distinct !DISubprogram(name: "subprogram", linkageName: "subprogram", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1, type: !4)
!4 = !DISubroutineType(cc: DW_CC_normal, types: !5)
!5 = !{!6, !6}
!5 = !{}
!6 = !DIBasicType(name: "int")
; // -----

View File

@@ -48,24 +48,31 @@ llvm.func @func_no_debug() {
baseType = #si64, flags = Vector,
elements = #llvm.di_subrange<lowerBound = 0, upperBound = 4, stride = 1>
>
#spType = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, argumentTypes = #si64, #ptr, #named, #composite, #vector>
#sp = #llvm.di_subprogram<
#void = #llvm.di_void_result_type
#spType0 = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #void, #si64, #ptr, #named, #composite, #vector>
#sp0 = #llvm.di_subprogram<
compileUnit = #cu, scope = #file, name = "func_with_debug", linkageName = "func_with_debug",
file = #file, line = 3, scopeLine = 3, subprogramFlags = "Definition|Optimized", type = #spType
file = #file, line = 3, scopeLine = 3, subprogramFlags = "Definition|Optimized", type = #spType0
>
#calleeType = #llvm.di_subroutine_type<
// Omit the optional callingConvention parameter but specify a result type.
resultType = #si64, argumentTypes = #si64>
// Omit the optional callingConvention parameter.
types = #si64, #si64>
#callee = #llvm.di_subprogram<
// Omit the optional linkageName, line, and scopeLine parameters.
compileUnit = #cu, scope = #composite, name = "callee",
file = #file, subprogramFlags = "Definition", type = #calleeType
>
#fileScope = #llvm.di_lexical_block_file<scope = #sp, file = #file, discriminator = 0>
#blockScope = #llvm.di_lexical_block<scope = #sp>
#fileScope = #llvm.di_lexical_block_file<scope = #sp0, file = #file, discriminator = 0>
#blockScope = #llvm.di_lexical_block<scope = #sp0>
#variable = #llvm.di_local_variable<scope = #fileScope, name = "arg", file = #file, line = 6, arg = 1, alignInBits = 32, type = #si64>
#variableAddr = #llvm.di_local_variable<scope = #blockScope, name = "alloc">
#spType1 = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
#sp1 = #llvm.di_subprogram<
compileUnit = #cu, scope = #file, name = "empty_types",
file = #file, subprogramFlags = "Definition", type = #spType1
>
// CHECK-LABEL: define void @func_with_debug(
// CHECK-SAME: i64 %[[ARG:.*]]) !dbg ![[FUNC_LOC:[0-9]+]]
llvm.func @func_with_debug(%arg: i64) {
@@ -93,10 +100,15 @@ llvm.func @func_with_debug(%arg: i64) {
llvm.call @func_no_debug() : () -> () loc(fused[callsite("mysource.cc":5:6 at "mysource.cc":1:1), "mysource.cc":1:1])
// CHECK: add i64 %[[ARG]], %[[ARG]], !dbg ![[FUSEDWITH_LOC:[0-9]+]]
%sum = llvm.add %arg, %arg : i64 loc(fused<#callee>[callsite("foo.mlir":2:4 at fused<#sp>["foo.mlir":28:5])])
%sum = llvm.add %arg, %arg : i64 loc(fused<#callee>[callsite("foo.mlir":2:4 at fused<#sp0>["foo.mlir":28:5])])
llvm.return
} loc(fused<#sp>["foo.mlir":1:1])
} loc(fused<#sp0>["foo.mlir":1:1])
// CHECK: define void @empty_types() !dbg ![[EMPTY_TYPES_LOC:[0-9]+]]
llvm.func @empty_types() {
llvm.return
} loc(fused<#sp1>["foo.mlir":2:1])
// CHECK: ![[CU_LOC:.*]] = distinct !DICompileUnit(language: DW_LANG_C, file: ![[CU_FILE_LOC:.*]], producer: "MLIR", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
// CHECK: ![[CU_FILE_LOC]] = !DIFile(filename: "foo.mlir", directory: "/test/")
@@ -131,3 +143,7 @@ llvm.func @func_with_debug(%arg: i64) {
// CHECK: ![[CALLEE_TYPE]] = !DISubroutineType(types: ![[CALLEE_ARGS:.*]])
// CHECK: ![[CALLEE_ARGS]] = !{![[ARG_TYPE:.*]], ![[ARG_TYPE:.*]]}
// CHECK: ![[INLINE_LOC]] = !DILocation(line: 28, column: 5,
// CHECK: ![[EMPTY_TYPES_LOC]] = distinct !DISubprogram(name: "empty_types", scope: ![[CU_FILE_LOC]], file: ![[CU_FILE_LOC]], type: ![[EMPTY_TYPES_TYPE:.*]], spFlags: DISPFlagDefinition
// CHECK: ![[EMPTY_TYPES_TYPE]] = !DISubroutineType(cc: DW_CC_normal, types: ![[EMPTY_TYPES_ARGS:.*]])
// CHECK: ![[EMPTY_TYPES_ARGS]] = !{}