Skip to content

Commit

Permalink
[mlir][debug] Support DICommonBlock. (llvm#111706)
Browse files Browse the repository at this point in the history
A COMMON block is a named area of memory that holds a collection of
variables. Fortran subprograms may map the COMMON block memory area to a
list of variables. A common block is represented in LLVM debug by
DICommonBlock.

This PR adds support for this in MLIR. The changes are mostly mechanical
apart from small change to access the DICompileUnit when the scope of
the variable is DICommonBlock.

---------

Co-authored-by: Tobias Gysi <[email protected]>
  • Loading branch information
2 people authored and ericastor committed Oct 10, 2024
1 parent 842314f commit 00095b5
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 30 deletions.
16 changes: 16 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,22 @@ def LLVM_DISubrangeAttr : LLVM_Attr<"DISubrange", "di_subrange", /*traits=*/[],
let assemblyFormat = "`<` struct(params) `>`";
}

//===----------------------------------------------------------------------===//
// DICommonBlockAttr
//===----------------------------------------------------------------------===//

def LLVM_DICommonBlockAttr : LLVM_Attr<"DICommonBlock", "di_common_block",
/*traits=*/[], "DIScopeAttr"> {
let parameters = (ins
"DIScopeAttr":$scope,
OptionalParameter<"DIGlobalVariableAttr">:$decl,
"StringAttr":$name,
OptionalParameter<"DIFileAttr">:$file,
OptionalParameter<"unsigned">:$line
);
let assemblyFormat = "`<` struct(params) `>`";
}

//===----------------------------------------------------------------------===//
// DISubroutineTypeAttr
//===----------------------------------------------------------------------===//
Expand Down
20 changes: 11 additions & 9 deletions mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,24 @@ void LLVMDialect::registerAttributes() {
//===----------------------------------------------------------------------===//

bool DINodeAttr::classof(Attribute attr) {
return llvm::isa<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
DINamespaceAttr, DINullTypeAttr, DIAnnotationAttr,
DIStringTypeAttr, DISubprogramAttr, DISubrangeAttr,
DISubroutineTypeAttr>(attr);
return llvm::isa<DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
DIGlobalVariableAttr, DIImportedEntityAttr, DILabelAttr,
DILexicalBlockAttr, DILexicalBlockFileAttr,
DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
DINullTypeAttr, DIAnnotationAttr, DIStringTypeAttr,
DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
attr);
}

//===----------------------------------------------------------------------===//
// DIScopeAttr
//===----------------------------------------------------------------------===//

bool DIScopeAttr::classof(Attribute attr) {
return llvm::isa<DICompileUnitAttr, DICompositeTypeAttr, DIFileAttr,
DILocalScopeAttr, DIModuleAttr, DINamespaceAttr>(attr);
return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
DIFileAttr, DILocalScopeAttr, DIModuleAttr, DINamespaceAttr>(
attr);
}

//===----------------------------------------------------------------------===//
Expand Down
11 changes: 6 additions & 5 deletions mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3369,11 +3369,12 @@ struct LLVMOpAsmDialectInterface : public OpAsmDialectInterface {
AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
return TypeSwitch<Attribute, AliasResult>(attr)
.Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
DIGlobalVariableExpressionAttr, DIImportedEntityAttr, DILabelAttr,
DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
DIModuleAttr, DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
DIGlobalVariableAttr, DIGlobalVariableExpressionAttr,
DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
Expand Down
9 changes: 9 additions & 0 deletions mlir/lib/Target/LLVMIR/DebugImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,13 @@ DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
getAttrOrNull(node->getStride()));
}

DICommonBlockAttr DebugImporter::translateImpl(llvm::DICommonBlock *node) {
return DICommonBlockAttr::get(context, translate(node->getScope()),
translate(node->getDecl()),
getStringAttrOrNull(node->getRawName()),
translate(node->getFile()), node->getLineNo());
}

DISubroutineTypeAttr
DebugImporter::translateImpl(llvm::DISubroutineType *node) {
SmallVector<DITypeAttr> types;
Expand Down Expand Up @@ -339,6 +346,8 @@ DINodeAttr DebugImporter::translate(llvm::DINode *node) {
auto translateNode = [this](llvm::DINode *node) -> DINodeAttr {
if (auto *casted = dyn_cast<llvm::DIBasicType>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DICommonBlock>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DICompileUnit>(node))
return translateImpl(casted);
if (auto *casted = dyn_cast<llvm::DICompositeType>(node))
Expand Down
1 change: 1 addition & 0 deletions mlir/lib/Target/LLVMIR/DebugImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class DebugImporter {
DIScopeAttr translateImpl(llvm::DIScope *node);
DISubprogramAttr translateImpl(llvm::DISubprogram *node);
DISubrangeAttr translateImpl(llvm::DISubrange *node);
DICommonBlockAttr translateImpl(llvm::DICommonBlock *node);
DISubroutineTypeAttr translateImpl(llvm::DISubroutineType *node);
DITypeAttr translateImpl(llvm::DIType *node);

Expand Down
20 changes: 14 additions & 6 deletions mlir/lib/Target/LLVMIR/DebugTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,13 @@ llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) {
getMetadataOrNull(attr.getStride()));
}

llvm::DICommonBlock *DebugTranslation::translateImpl(DICommonBlockAttr attr) {
return llvm::DICommonBlock::get(llvmCtx, translate(attr.getScope()),
translate(attr.getDecl()),
getMDStringOrNull(attr.getName()),
translate(attr.getFile()), attr.getLine());
}

llvm::DISubroutineType *
DebugTranslation::translateImpl(DISubroutineTypeAttr attr) {
// Concatenate the result and argument types into a single array.
Expand Down Expand Up @@ -428,12 +435,13 @@ llvm::DINode *DebugTranslation::translate(DINodeAttr attr) {

if (!node)
node = TypeSwitch<DINodeAttr, llvm::DINode *>(attr)
.Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
.Case<DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
DIGlobalVariableAttr, DIImportedEntityAttr, DILabelAttr,
DILexicalBlockAttr, DILexicalBlockFileAttr,
DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
DINullTypeAttr, DIStringTypeAttr, DISubprogramAttr,
DISubrangeAttr, DISubroutineTypeAttr>(
[&](auto attr) { return translateImpl(attr); });

if (node && !node->isTemporary())
Expand Down
1 change: 1 addition & 0 deletions mlir/lib/Target/LLVMIR/DebugTranslation.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class DebugTranslation {
llvm::DIScope *translateImpl(DIScopeAttr attr);
llvm::DISubprogram *translateImpl(DISubprogramAttr attr);
llvm::DISubrange *translateImpl(DISubrangeAttr attr);
llvm::DICommonBlock *translateImpl(DICommonBlockAttr attr);
llvm::DISubroutineType *translateImpl(DISubroutineTypeAttr attr);
llvm::DIType *translateImpl(DITypeAttr attr);

Expand Down
28 changes: 18 additions & 10 deletions mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1064,19 +1064,27 @@ LogicalResult ModuleTranslation::convertGlobals() {
// There is no `globals` field in DICompileUnitAttr which can be directly
// assigned to DICompileUnit. We have to build the list by looking at the
// dbgExpr of all the GlobalOps. The scope of the variable is used to get
// the DICompileUnit in which to add it. But for the languages that
// support modules, the scope hierarchy can be
// variable -> module -> compile unit
// If a variable scope points to the module then we use the scope of the
// module to get the compile unit.
// Global variables are also used for things like static local variables
// in C and local variables with the save attribute in Fortran. The scope
// of the variable is the parent function. We use the compile unit of the
// parent function in this case.
// the DICompileUnit in which to add it.
// But there are cases where the scope of a global does not
// directly point to the DICompileUnit and we have to do a bit more work
// to get to it. Some of those cases are:
//
// 1. For the languages that support modules, the scope hierarchy can be
// variable -> DIModule -> DICompileUnit
//
// 2. For the Fortran common block variable, the scope hierarchy can be
// variable -> DICommonBlock -> DISubprogram -> DICompileUnit
//
// 3. For entities like static local variables in C or variable with
// SAVE attribute in Fortran, the scope hierarchy can be
// variable -> DISubprogram -> DICompileUnit
llvm::DIScope *scope = diGlobalVar->getScope();
if (auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
scope = mod->getScope();
else if (auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
else if (auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
if (auto *sp = dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
scope = sp->getUnit();
} else if (auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
scope = sp->getUnit();

// Get the compile unit (scope) of the the global variable.
Expand Down
8 changes: 8 additions & 0 deletions mlir/test/Dialect/LLVMIR/debuginfo.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@
// CHECK-DAG: #[[LABEL2:.*]] = #llvm.di_label<scope = #[[BLOCK2]]>
#label2 = #llvm.di_label<scope = #block2>

// CHECK-DAG: #llvm.di_common_block<scope = #[[SP1]], name = "block", file = #[[FILE]], line = 3>
#di_common_block = #llvm.di_common_block<scope = #sp1, name = "block", file = #file, line = 3>
#global_var = #llvm.di_global_variable<scope = #di_common_block, name = "a",
file = #file, line = 2, type = #int0>
#var_expression = #llvm.di_global_variable_expression<var = #global_var,
expr = <>>
llvm.mlir.global common @block_() {dbg_expr = #var_expression} : i64

// CHECK: llvm.func @addr(%[[ARG:.*]]: i64)
llvm.func @addr(%arg: i64) {
// CHECK: %[[ALLOC:.*]] = llvm.alloca
Expand Down
24 changes: 24 additions & 0 deletions mlir/test/Target/LLVMIR/Import/debug-info.ll
Original file line number Diff line number Diff line change
Expand Up @@ -843,3 +843,27 @@ define void @fn_with_annotations() !dbg !12 {


; CHECK-DAG: #llvm.di_subprogram<{{.*}}name = "fn_with_annotations"{{.*}}annotations = #llvm.di_annotation<name = "foo", value = "bar">>

; // -----

@block = common global [4 x i8] zeroinitializer, !dbg !0

define void @test() !dbg !3 {
ret void
}

!llvm.module.flags = !{!10}
!llvm.dbg.cu = !{!7}

!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "alpha", scope: !2, file: !4, type: !9)
!2 = !DICommonBlock(scope: !3, declaration: null, name: "block", file: !4, line: 3)
!3 = distinct !DISubprogram(name: "test", scope: !4, file: !4, spFlags: DISPFlagDefinition, unit: !7)
!4 = !DIFile(filename: "test.f90", directory: "")
!7 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !4)
!9 = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed)
!10 = !{i32 2, !"Debug Info Version", i32 3}

; CHECK: #[[FILE:.+]] = #llvm.di_file<"test.f90" in "">
; CHECK: #[[SP:.+]] = #llvm.di_subprogram<{{.*}}name = "test"{{.*}}>
; CHECK: #llvm.di_common_block<scope = #[[SP]], name = "block", file = #[[FILE]], line = 3>
30 changes: 30 additions & 0 deletions mlir/test/Target/LLVMIR/llvmir-debug.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -660,3 +660,33 @@ llvm.func @string_ty(%arg0: !llvm.ptr) {

// CHECK-DAG: !DIStringType(name: "character(*)", stringLength: ![[VAR:[0-9]+]], stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref), size: 32, align: 8)
// CHECK-DAG: ![[VAR]] = !DILocalVariable(name: "string_size"{{.*}} flags: DIFlagArtificial)

// -----

// Test translation of DICommonBlockAttr.
#bt = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int", sizeInBits = 32>
#file = #llvm.di_file<"test.f90" in "">
#cu = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_C,
file = #file, isOptimized = false, emissionKind = Full>
#sp = #llvm.di_subprogram<compileUnit = #cu, scope = #file, name = "test",
file = #file, subprogramFlags = Definition>
#di_common_block = #llvm.di_common_block<scope = #sp, name = "block",
file = #file, line = 3>
#global_var = #llvm.di_global_variable<scope = #di_common_block, name = "a",
file = #file, line = 2, type = #bt>
#var_expression = #llvm.di_global_variable_expression<var = #global_var,
expr = <>>

llvm.mlir.global common @block_(dense<0> : tensor<8xi8>)
{dbg_expr = #var_expression} : !llvm.array<8 x i8>

llvm.func @test() {
llvm.return
} loc(#loc2)

#loc1 = loc("test.f90":1:0)
#loc2 = loc(fused<#sp>[#loc1])

// CHECK: !DICommonBlock(scope: ![[SCOPE:[0-9]+]], declaration: null, name: "block", file: ![[FILE:[0-9]+]], line: 3)
// CHECK: ![[SCOPE]] = {{.*}}!DISubprogram(name: "test"{{.*}})
// CHECK: ![[FILE]] = !DIFile(filename: "test.f90"{{.*}})

0 comments on commit 00095b5

Please sign in to comment.