Skip to content

Commit bc4bedd

Browse files
authored
[mlir][debug] Handle DIImportedEntity. (#103055)
The `DIImporedEntity` can be used to represent imported entities like C++'s namespace with using directive or fortran's moudule with use statement. This PR adds `DIImportedEntityAttr` and 2-way translation from `DIImportedEntity` to `DIImportedEntityAttr` and vice versa. When an entity is imported in a function, the `retainedNodes` field of the `DISubprogram` contains all the imported nodes. See the C++ code and the LLVM IR below. ``` void test() { using namespace n1; ... } !2 = !DINamespace(name: "n1", scope: null) !16 = distinct !DISubprogram(name: "test", ..., retainedNodes: !19) !19 = !{!20} !20 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !16, entity: !2 ...) ``` This PR makes sure that the translation from mlir to `retainedNodes` field happens correctly both ways. To side step the cyclic dependency between `DISubprogramAttr` and `DIImportedEntityAttr`, we have decided to not have `scope` field in the `DIImportedEntityAttr` and it is inferred from the entity which hold the list of `DIImportedEntityAttr`. A `retainedNodes` field has been added in the `DISubprogramAttr` which contains the list of `DIImportedEntityAttr` for that function. This PR currently does not handle entities imported in a global scope but that should be easy to handle in a subsequent PR.
1 parent ad468da commit bc4bedd

File tree

13 files changed

+184
-16
lines changed

13 files changed

+184
-16
lines changed

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
301301

302302
auto spAttr = mlir::LLVM::DISubprogramAttr::get(
303303
context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr,
304-
line, line, subprogramFlags, subTypeAttr);
304+
line, line, subprogramFlags, subTypeAttr, /*retainedNodes=*/{});
305305
funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));
306306

307307
// Don't process variables if user asked for line tables only.

mlir/include/mlir-c/Dialect/LLVM.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDISubprogramAttrGet(
316316
MlirContext ctx, MlirAttribute id, MlirAttribute compileUnit,
317317
MlirAttribute scope, MlirAttribute name, MlirAttribute linkageName,
318318
MlirAttribute file, unsigned int line, unsigned int scopeLine,
319-
uint64_t subprogramFlags, MlirAttribute type);
319+
uint64_t subprogramFlags, MlirAttribute type, intptr_t nRetainedNodes,
320+
MlirAttribute const *retainedNodes);
320321

321322
/// Gets the scope from this DISubprogramAttr.
322323
MLIR_CAPI_EXPORTED MlirAttribute
@@ -353,6 +354,12 @@ MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDIModuleAttrGet(
353354
MlirAttribute name, MlirAttribute configMacros, MlirAttribute includePath,
354355
MlirAttribute apinotes, unsigned int line, bool isDecl);
355356

357+
/// Creates a LLVM DIImportedEntityAttr attribute.
358+
MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDIImportedEntityAttrGet(
359+
MlirContext ctx, unsigned int tag, MlirAttribute entity, MlirAttribute file,
360+
unsigned int line, MlirAttribute name, intptr_t nElements,
361+
MlirAttribute const *elements);
362+
356363
/// Gets the scope of this DIModuleAttr.
357364
MLIR_CAPI_EXPORTED MlirAttribute
358365
mlirLLVMDIModuleAttrGetScope(MlirAttribute diModule);

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -565,19 +565,21 @@ def LLVM_DISubprogramAttr : LLVM_Attr<"DISubprogram", "di_subprogram",
565565
OptionalParameter<"unsigned">:$line,
566566
OptionalParameter<"unsigned">:$scopeLine,
567567
OptionalParameter<"DISubprogramFlags">:$subprogramFlags,
568-
OptionalParameter<"DISubroutineTypeAttr">:$type
568+
OptionalParameter<"DISubroutineTypeAttr">:$type,
569+
OptionalArrayRefParameter<"DINodeAttr">:$retainedNodes
569570
);
570571
let builders = [
571572
AttrBuilderWithInferredContext<(ins
572573
"DistinctAttr":$id, "DICompileUnitAttr":$compileUnit,
573574
"DIScopeAttr":$scope, "StringRef":$name, "StringRef":$linkageName,
574575
"DIFileAttr":$file, "unsigned":$line, "unsigned":$scopeLine,
575-
"DISubprogramFlags":$subprogramFlags, "DISubroutineTypeAttr":$type
576+
"DISubprogramFlags":$subprogramFlags, "DISubroutineTypeAttr":$type,
577+
"ArrayRef<DINodeAttr>":$retainedNodes
576578
), [{
577579
MLIRContext *ctx = file.getContext();
578580
return $_get(ctx, id, compileUnit, scope, StringAttr::get(ctx, name),
579581
StringAttr::get(ctx, linkageName), file, line,
580-
scopeLine, subprogramFlags, type);
582+
scopeLine, subprogramFlags, type, retainedNodes);
581583
}]>
582584
];
583585

@@ -619,6 +621,29 @@ def LLVM_DINamespaceAttr : LLVM_Attr<"DINamespace", "di_namespace",
619621
let assemblyFormat = "`<` struct(params) `>`";
620622
}
621623

624+
//===----------------------------------------------------------------------===//
625+
// DIImportedEntityAttr
626+
//===----------------------------------------------------------------------===//
627+
628+
def LLVM_DIImportedEntityAttr : LLVM_Attr<"DIImportedEntity", "di_imported_entity",
629+
/*traits=*/[], "DINodeAttr"> {
630+
/// TODO: DIImportedEntity has a 'scope' field which represents the scope where
631+
/// this entity is imported. Currently, we are not adding a 'scope' field in
632+
/// DIImportedEntityAttr to avoid cyclic dependency. As DIImportedEntityAttr
633+
/// entries will be contained inside a scope entity (e.g. DISubprogramAttr),
634+
/// the scope can easily be inferred.
635+
let parameters = (ins
636+
LLVM_DITagParameter:$tag,
637+
"DINodeAttr":$entity,
638+
OptionalParameter<"DIFileAttr">:$file,
639+
OptionalParameter<"unsigned">:$line,
640+
OptionalParameter<"StringAttr">:$name,
641+
OptionalArrayRefParameter<"DINodeAttr">:$elements
642+
);
643+
644+
let assemblyFormat = "`<` struct(params) `>`";
645+
}
646+
622647
//===----------------------------------------------------------------------===//
623648
// DISubrangeAttr
624649
//===----------------------------------------------------------------------===//

mlir/lib/CAPI/Dialect/LLVM.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,20 @@ MlirAttribute mlirLLVMDISubprogramAttrGet(
293293
MlirContext ctx, MlirAttribute id, MlirAttribute compileUnit,
294294
MlirAttribute scope, MlirAttribute name, MlirAttribute linkageName,
295295
MlirAttribute file, unsigned int line, unsigned int scopeLine,
296-
uint64_t subprogramFlags, MlirAttribute type) {
296+
uint64_t subprogramFlags, MlirAttribute type, intptr_t nRetainedNodes,
297+
MlirAttribute const *retainedNodes) {
298+
SmallVector<Attribute> nodesStorage;
299+
nodesStorage.reserve(nRetainedNodes);
297300
return wrap(DISubprogramAttr::get(
298301
unwrap(ctx), cast<DistinctAttr>(unwrap(id)),
299302
cast<DICompileUnitAttr>(unwrap(compileUnit)),
300303
cast<DIScopeAttr>(unwrap(scope)), cast<StringAttr>(unwrap(name)),
301304
cast<StringAttr>(unwrap(linkageName)), cast<DIFileAttr>(unwrap(file)),
302305
line, scopeLine, DISubprogramFlags(subprogramFlags),
303-
cast<DISubroutineTypeAttr>(unwrap(type))));
306+
cast<DISubroutineTypeAttr>(unwrap(type)),
307+
llvm::map_to_vector(
308+
unwrapList(nRetainedNodes, retainedNodes, nodesStorage),
309+
[](Attribute a) { return cast<DINodeAttr>(a); })));
304310
}
305311

306312
MlirAttribute mlirLLVMDISubprogramAttrGetScope(MlirAttribute diSubprogram) {
@@ -345,3 +351,16 @@ MlirAttribute mlirLLVMDIModuleAttrGet(MlirContext ctx, MlirAttribute file,
345351
MlirAttribute mlirLLVMDIModuleAttrGetScope(MlirAttribute diModule) {
346352
return wrap(cast<DIModuleAttr>(unwrap(diModule)).getScope());
347353
}
354+
355+
MlirAttribute mlirLLVMDIImportedEntityAttrGet(
356+
MlirContext ctx, unsigned int tag, MlirAttribute entity, MlirAttribute file,
357+
unsigned int line, MlirAttribute name, intptr_t nElements,
358+
MlirAttribute const *elements) {
359+
SmallVector<Attribute> elementsStorage;
360+
elementsStorage.reserve(nElements);
361+
return wrap(DIImportedEntityAttr::get(
362+
unwrap(ctx), tag, cast<DINodeAttr>(unwrap(entity)),
363+
cast<DIFileAttr>(unwrap(file)), line, cast<StringAttr>(unwrap(name)),
364+
llvm::map_to_vector(unwrapList(nElements, elements, elementsStorage),
365+
[](Attribute a) { return cast<DINodeAttr>(a); })));
366+
}

mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ void LLVMDialect::registerAttributes() {
5858
bool DINodeAttr::classof(Attribute attr) {
5959
return llvm::isa<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
6060
DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
61-
DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr,
62-
DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
63-
DINullTypeAttr, DIStringTypeAttr, DISubprogramAttr,
64-
DISubrangeAttr, DISubroutineTypeAttr>(attr);
61+
DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
62+
DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
63+
DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
64+
DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
65+
attr);
6566
}
6667

6768
//===----------------------------------------------------------------------===//

mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,
7979
context, id, compileUnitAttr, fileAttr, funcNameAttr, funcNameAttr,
8080
fileAttr,
8181
/*line=*/line,
82-
/*scopeline=*/col, subprogramFlags, subroutineTypeAttr);
82+
/*scopeline=*/col, subprogramFlags, subroutineTypeAttr,
83+
/*retainedNodes=*/{});
8384
llvmFunc->setLoc(FusedLoc::get(context, {loc}, subprogramAttr));
8485
}
8586

mlir/lib/Target/LLVMIR/DebugImporter.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,20 @@ DINamespaceAttr DebugImporter::translateImpl(llvm::DINamespace *node) {
208208
node->getExportSymbols());
209209
}
210210

211+
DIImportedEntityAttr
212+
DebugImporter::translateImpl(llvm::DIImportedEntity *node) {
213+
SmallVector<DINodeAttr> elements;
214+
for (llvm::DINode *element : node->getElements()) {
215+
assert(element && "expected a non-null element type");
216+
elements.push_back(translate(element));
217+
}
218+
219+
return DIImportedEntityAttr::get(
220+
context, node->getTag(), translate(node->getEntity()),
221+
translate(node->getFile()), node->getLine(),
222+
getStringAttrOrNull(node->getRawName()), elements);
223+
}
224+
211225
DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
212226
// Only definitions require a distinct identifier.
213227
mlir::DistinctAttr id;
@@ -223,11 +237,17 @@ DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
223237
DISubroutineTypeAttr type = translate(node->getType());
224238
if (node->getType() && !type)
225239
return nullptr;
240+
241+
SmallVector<DINodeAttr> retainedNodes;
242+
for (llvm::DINode *retainedNode : node->getRetainedNodes())
243+
retainedNodes.push_back(translate(retainedNode));
244+
226245
return DISubprogramAttr::get(context, id, translate(node->getUnit()), scope,
227246
getStringAttrOrNull(node->getRawName()),
228247
getStringAttrOrNull(node->getRawLinkageName()),
229248
translate(node->getFile()), node->getLine(),
230-
node->getScopeLine(), *subprogramFlags, type);
249+
node->getScopeLine(), *subprogramFlags, type,
250+
retainedNodes);
231251
}
232252

233253
DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
@@ -308,6 +328,8 @@ DINodeAttr DebugImporter::translate(llvm::DINode *node) {
308328
return translateImpl(casted);
309329
if (auto *casted = dyn_cast<llvm::DIGlobalVariable>(node))
310330
return translateImpl(casted);
331+
if (auto *casted = dyn_cast<llvm::DIImportedEntity>(node))
332+
return translateImpl(casted);
311333
if (auto *casted = dyn_cast<llvm::DILabel>(node))
312334
return translateImpl(casted);
313335
if (auto *casted = dyn_cast<llvm::DILexicalBlock>(node))

mlir/lib/Target/LLVMIR/DebugImporter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class DebugImporter {
7575
DIVariableAttr translateImpl(llvm::DIVariable *node);
7676
DIModuleAttr translateImpl(llvm::DIModule *node);
7777
DINamespaceAttr translateImpl(llvm::DINamespace *node);
78+
DIImportedEntityAttr translateImpl(llvm::DIImportedEntity *node);
7879
DIScopeAttr translateImpl(llvm::DIScope *node);
7980
DISubprogramAttr translateImpl(llvm::DISubprogram *node);
8081
DISubrangeAttr translateImpl(llvm::DISubrange *node);

mlir/lib/Target/LLVMIR/DebugTranslation.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,19 @@ llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) {
306306
static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()),
307307
compileUnit);
308308

309+
// DIImportedEntity requires scope information which DIImportedEntityAttr does
310+
// not have. This is why we translate DIImportedEntityAttr after we have
311+
// created DISubprogram as we can use it as the scope.
312+
SmallVector<llvm::Metadata *> retainedNodes;
313+
for (DINodeAttr nodeAttr : attr.getRetainedNodes()) {
314+
if (auto importedAttr = dyn_cast<DIImportedEntityAttr>(nodeAttr)) {
315+
llvm::DINode *dn = translate(importedAttr, node);
316+
retainedNodes.push_back(dn);
317+
}
318+
}
319+
if (!retainedNodes.empty())
320+
node->replaceRetainedNodes(llvm::MDTuple::get(llvmCtx, retainedNodes));
321+
309322
if (attr.getId())
310323
distinctAttrToNode.try_emplace(attr.getId(), node);
311324
return node;
@@ -326,6 +339,18 @@ llvm::DINamespace *DebugTranslation::translateImpl(DINamespaceAttr attr) {
326339
attr.getExportSymbols());
327340
}
328341

342+
llvm::DIImportedEntity *DebugTranslation::translate(DIImportedEntityAttr attr,
343+
llvm::DIScope *scope) {
344+
SmallVector<llvm::Metadata *> elements;
345+
for (DINodeAttr member : attr.getElements())
346+
elements.push_back(translate(member));
347+
348+
return llvm::DIImportedEntity::get(
349+
llvmCtx, attr.getTag(), scope, translate(attr.getEntity()),
350+
translate(attr.getFile()), attr.getLine(),
351+
getMDStringOrNull(attr.getName()), llvm::MDNode::get(llvmCtx, elements));
352+
}
353+
329354
llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) {
330355
auto getMetadataOrNull = [&](Attribute attr) -> llvm::Metadata * {
331356
if (!attr)

mlir/lib/Target/LLVMIR/DebugTranslation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ class DebugTranslation {
9090
llvm::DISubroutineType *translateImpl(DISubroutineTypeAttr attr);
9191
llvm::DIType *translateImpl(DITypeAttr attr);
9292

93+
/// Currently, DIImportedEntityAttr does not have a scope field to avoid a
94+
/// cyclic dependency. The scope information is obtained from the entity
95+
/// which holds the list of DIImportedEntityAttr. This requires that scope
96+
/// information be passed to translate function.
97+
llvm::DIImportedEntity *translate(DIImportedEntityAttr attr, llvm::DIScope *);
98+
9399
/// Attributes that support self recursion need to implement an additional
94100
/// method to hook into `translateRecursive`.
95101
/// - `<temp llvm type> translateTemporaryImpl(<mlir type>)`:

mlir/test/CAPI/llvm.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,9 +312,15 @@ static void testDebugInfoAttributes(MlirContext ctx) {
312312
// CHECK: #llvm.di_subroutine_type<{{.*}}>
313313
mlirAttributeDump(subroutine_type);
314314

315-
MlirAttribute di_subprogram =
316-
mlirLLVMDISubprogramAttrGet(ctx, id, compile_unit, compile_unit, foo, bar,
317-
file, 1, 2, 0, subroutine_type);
315+
MlirAttribute di_imported_entity = mlirLLVMDIImportedEntityAttrGet(
316+
ctx, 0, di_module, file, 1, foo, 1, &local_var);
317+
318+
mlirAttributeDump(di_imported_entity);
319+
// CHECK: #llvm.di_imported_entity<{{.*}}>
320+
321+
MlirAttribute di_subprogram = mlirLLVMDISubprogramAttrGet(
322+
ctx, id, compile_unit, compile_unit, foo, bar, file, 1, 2, 0,
323+
subroutine_type, 1, &di_imported_entity);
318324
// CHECK: #llvm.di_subprogram<{{.*}}>
319325
mlirAttributeDump(di_subprogram);
320326

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,3 +792,28 @@ define void @string_type(ptr %arg1) {
792792
; CHECK-SAME: stringLengthExp = <[DW_OP_push_object_address, DW_OP_plus_uconst(8)]>
793793
; CHECK-SAME: stringLocationExp = <[DW_OP_push_object_address, DW_OP_deref]>>
794794
; CHECK: #di_local_variable1 = #llvm.di_local_variable<scope = #di_subprogram, name = "str", file = #di_file, type = #di_string_type, flags = Artificial>
795+
796+
; // -----
797+
798+
; Test that imported entities for a functions are handled correctly.
799+
800+
define void @imp_fn() !dbg !12 {
801+
ret void
802+
}
803+
804+
!llvm.module.flags = !{!10}
805+
!llvm.dbg.cu = !{!4}
806+
807+
!2 = !DIModule(scope: !4, name: "mod1", file: !3, line: 1)
808+
!3 = !DIFile(filename: "test.f90", directory: "")
809+
!4 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3)
810+
!8 = !DIModule(scope: !4, name: "mod1", file: !3, line: 5)
811+
!10 = !{i32 2, !"Debug Info Version", i32 3}
812+
!12 = distinct !DISubprogram(name: "imp_fn", linkageName: "imp_fn", scope: !3, file: !3, line: 10, type: !14, scopeLine: 10, spFlags: DISPFlagDefinition, unit: !4, retainedNodes: !16)
813+
!14 = !DISubroutineType(cc: DW_CC_program, types: !15)
814+
!15 = !{}
815+
!16 = !{!17}
816+
!17 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !12, entity: !8, file: !3, line: 1, elements: !15)
817+
818+
; CHECK-DAG: #[[M:.+]] = #llvm.di_module<{{.*}}name = "mod1"{{.*}}>
819+
; CHECK-DAG: #[[SP:.+]] = #llvm.di_subprogram<{{.*}}name = "imp_fn"{{.*}}retainedNodes = #llvm.di_imported_entity<tag = DW_TAG_imported_module, entity = #[[M]]{{.*}}>>

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,36 @@ llvm.func @fn_with_gl() {
366366

367367
// -----
368368

369+
// Test that imported entries correctly generates 'retainedNodes' in the
370+
// subprogram.
371+
372+
llvm.func @imp_fn() {
373+
llvm.return
374+
} loc(#loc2)
375+
#file = #llvm.di_file<"test.f90" in "">
376+
#SP_TY = #llvm.di_subroutine_type<callingConvention = DW_CC_program>
377+
#CU = #llvm.di_compile_unit<id = distinct[0]<>,
378+
sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false,
379+
emissionKind = Full>
380+
#MOD = #llvm.di_module<file = #file, scope = #CU, name = "mod1">
381+
#MOD1 = #llvm.di_module<file = #file, scope = #CU, name = "mod2">
382+
#SP = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #CU, scope = #file,
383+
name = "imp_fn", file = #file, subprogramFlags = Definition, type = #SP_TY,
384+
retainedNodes = #llvm.di_imported_entity<tag = DW_TAG_imported_module,
385+
entity = #MOD1, file = #file, line = 1>, #llvm.di_imported_entity<tag
386+
= DW_TAG_imported_module, entity = #MOD, file = #file, line = 1>>
387+
#loc1 = loc("test.f90":12:14)
388+
#loc2 = loc(fused<#SP>[#loc1])
389+
390+
// CHECK-DAG: ![[SP:[0-9]+]] = {{.*}}!DISubprogram(name: "imp_fn"{{.*}}retainedNodes: ![[NODES:[0-9]+]])
391+
// CHECK-DAG: ![[NODES]] = !{![[NODE2:[0-9]+]], ![[NODE1:[0-9]+]]}
392+
// CHECK-DAG: ![[NODE1]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[SP]], entity: ![[MOD1:[0-9]+]]{{.*}})
393+
// CHECK-DAG: ![[NODE2]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[SP]], entity: ![[MOD2:[0-9]+]]{{.*}})
394+
// CHECK-DAG: ![[MOD1]] = !DIModule({{.*}}name: "mod1"{{.*}})
395+
// CHECK-DAG: ![[MOD2]] = !DIModule({{.*}}name: "mod2"{{.*}})
396+
397+
// -----
398+
369399
// Nameless and scopeless global constant.
370400

371401
// CHECK-LABEL: @.str.1 = external constant [10 x i8]

0 commit comments

Comments
 (0)