diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc index a5acbffc83..e5d7ec9be0 100644 --- a/include/LLVMSPIRVExtensions.inc +++ b/include/LLVMSPIRVExtensions.inc @@ -30,3 +30,4 @@ EXT(SPV_INTEL_optnone) EXT(SPV_INTEL_arbitrary_precision_integers) EXT(SPV_INTEL_variable_length_array) EXT(SPV_INTEL_memory_access_aliasing) +EXT(SPV_INTEL_debug_module) diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp index 835470d591..3d2ddbb872 100644 --- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp @@ -330,6 +330,12 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { case dwarf::DW_TAG_imported_declaration: return transDbgImportedEntry(cast(DIEntry)); + case dwarf::DW_TAG_module: { + if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_debug_module)) + return transDbgModule(cast(DIEntry)); + return getDebugInfoNone(); + } + default: return getDebugInfoNone(); } @@ -785,7 +791,8 @@ LLVMToSPIRVDbgTran::transDbgGlobalVariable(const DIGlobalVariable *GV) { SPIRVEntry *Parent = SPIRVCU; // Global variable may be declared in scope of a namespace or it may be a // static variable declared in scope of a function - if (Context && (isa(Context) || isa(Context))) + if (Context && (isa(Context) || isa(Context) || + isa(Context))) Parent = transDbgEntry(Context); Ops[ParentIdx] = Parent->getId(); @@ -998,3 +1005,34 @@ LLVMToSPIRVDbgTran::transDbgImportedEntry(const DIImportedEntity *IE) { Ops[ParentIdx] = getScope(IE->getScope())->getId(); return BM->addDebugInfo(SPIRVDebug::ImportedEntity, getVoidTy(), Ops); } + +SPIRVEntry *LLVMToSPIRVDbgTran::transDbgModule(const DIModule *Module) { + using namespace SPIRVDebug::Operand::ModuleINTEL; + SPIRVWordVec Ops(OperandCount); + Ops[NameIdx] = BM->getString(Module->getName().str())->getId(); + Ops[ParentIdx] = getScope(Module->getScope())->getId(); + Ops[ConfigMacrosIdx] = + BM->getString(Module->getConfigurationMacros().str())->getId(); + Ops[IncludePathIdx] = BM->getString(Module->getIncludePath().str())->getId(); + + unsigned LineNo = 0; + std::string Source = ""; + + auto SysRoot = Module->getSysRoot(); + if (SysRoot != "") { + SmallVector SysRootParts; + SysRoot.split(SysRootParts, '?'); + if (SysRootParts.size() >= 1) { + LineNo = std::stoi(SysRootParts[0]); + } + if (SysRootParts.size() >= 3) { + Source = SysRootParts[1].str() + "/" + SysRootParts[2].str(); + } + } + Ops[LineIdx] = LineNo; + Ops[SourceIdx] = BM->getString(Source)->getId(); + + BM->addExtension(ExtensionID::SPV_INTEL_debug_module); + BM->addCapability(spv::internal::CapabilityDebugInfoModuleINTEL); + return BM->addDebugInfo(SPIRVDebug::ModuleINTEL, getVoidTy(), Ops); +} diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h index e114201b0a..3ee140fe4f 100644 --- a/lib/SPIRV/LLVMToSPIRVDbgTran.h +++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h @@ -145,6 +145,9 @@ class LLVMToSPIRVDbgTran { // Imported declarations and modules SPIRVEntry *transDbgImportedEntry(const DIImportedEntity *IE); + // A module in programming language. Example - Fortran module, clang module. + SPIRVEntry *transDbgModule(const DIModule *IE); + SPIRVModule *BM; Module *M; LLVMToSPIRV *SPIRVWriter; diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp index 76d8739be7..1f761cf24d 100644 --- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp @@ -760,6 +760,11 @@ DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) { DIFile *File = getFile(Ops[SourceIdx]); auto *Entity = transDebugInst(BM->get(Ops[EntityIdx])); if (Ops[TagIdx] == SPIRVDebug::ImportedModule) { + if (!Entity) + return Builder.createImportedModule( + Scope, static_cast(nullptr), File, Line); + if (DIModule *DM = dyn_cast(Entity)) + return Builder.createImportedModule(Scope, DM, File, Line); if (DIImportedEntity *IE = dyn_cast(Entity)) return Builder.createImportedModule(Scope, IE, File, Line); if (DINamespace *NS = dyn_cast(Entity)) @@ -776,6 +781,25 @@ DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) { llvm_unreachable("Unexpected kind of imported entity!"); } +DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::ModuleINTEL; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= OperandCount && "Invalid number of operands"); + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); + unsigned Line = Ops[LineIdx]; + DIFile *File = getDIFile(getString(Ops[SourceIdx])); + StringRef Name = getString(Ops[NameIdx]); + StringRef ConfigMacros = getString(Ops[ConfigMacrosIdx]); + StringRef IncludePath = getString(Ops[IncludePathIdx]); + + std::string SysRoot = std::to_string(Line) + "?"; + if (File) { + SysRoot += File->getDirectory().str() + "?" + File->getFilename().str(); + } + return Builder.createModule(Scope, Name, ConfigMacros, IncludePath, + StringRef(SysRoot)); +} + MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) { const SPIRVWordVec &Args = DebugInst->getArguments(); std::vector Ops; @@ -872,6 +896,9 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { case SPIRVDebug::ImportedEntity: return transImportedEntry(DebugInst); + case SPIRVDebug::ModuleINTEL: + return transModule(DebugInst); + case SPIRVDebug::Operation: // To be translated with transExpression case SPIRVDebug::Source: // To be used by other instructions return nullptr; diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h index a717af7e88..dd493067d2 100644 --- a/lib/SPIRV/SPIRVToLLVMDbgTran.h +++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h @@ -143,6 +143,8 @@ class SPIRVToLLVMDbgTran { DINode *transImportedEntry(const SPIRVExtInst *DebugInst); + DINode *transModule(const SPIRVExtInst *DebugInst); + MDNode *transExpression(const SPIRVExtInst *DebugInst); SPIRVModule *BM; diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h index c5613a00ce..6cf2dd5daf 100644 --- a/lib/SPIRV/libSPIRV/SPIRV.debug.h +++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h @@ -48,7 +48,8 @@ enum Instruction { MacroUndef = 33, ImportedEntity = 34, Source = 35, - InstCount = 36 + ModuleINTEL = 36, + InstCount = 37 }; enum Flag { @@ -770,6 +771,18 @@ enum { }; } +namespace ModuleINTEL { +enum { + NameIdx = 0, + SourceIdx = 1, + LineIdx = 2, + ParentIdx = 3, + ConfigMacrosIdx = 4, + IncludePathIdx = 5, + OperandCount = 6 +}; +} + } // namespace Operand } // namespace SPIRVDebug diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h index 89581f46ff..9f1aa91a96 100644 --- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h +++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h @@ -253,6 +253,7 @@ template <> inline void SPIRVMap::init() { add(SPIRVDebug::NoScope, "DebugNoScope"); add(SPIRVDebug::InlinedAt, "DebugInlinedAt"); add(SPIRVDebug::ImportedEntity, "DebugImportedEntity"); + add(SPIRVDebug::ModuleINTEL, "DebugModuleINTEL"); add(SPIRVDebug::Expression, "DebugExpression"); add(SPIRVDebug::Operation, "DebugOperation"); } diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h index ed9d944f80..561177a2eb 100644 --- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h @@ -576,7 +576,7 @@ template <> inline void SPIRVMap::init() { "ArbitraryPrecisionIntegersINTEL"); add(internal::CapabilityMemoryAccessAliasingINTEL, "MemoryAccessAliasingINTEL"); - + add(internal::CapabilityDebugInfoModuleINTEL, "DebugInfoModuleINTEL"); } SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp index 07b7ef6245..dcc797c8b5 100644 --- a/lib/SPIRV/libSPIRV/spirv_internal.hpp +++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp @@ -49,9 +49,9 @@ enum InternalDecoration { enum InternalCapability { ICapMemoryAccessAliasingINTEL = 5910, + ICapDebugInfoModuleINTEL = 6114 }; - enum InternalMemoryAccessMask { IMemAccessAliasScopeINTELMask = 0x10000, IMemAccessNoAliasINTELMask = 0x20000 @@ -73,7 +73,8 @@ constexpr Decoration DecorationNoAliasINTEL = constexpr Capability CapabilityMemoryAccessAliasingINTEL = static_cast(ICapMemoryAccessAliasingINTEL); - +constexpr Capability CapabilityDebugInfoModuleINTEL = + static_cast(ICapDebugInfoModuleINTEL); constexpr MemoryAccessMask MemoryAccessAliasScopeINTELMask = static_cast(IMemAccessAliasScopeINTELMask); diff --git a/test/DebugInfo/DebugInfoNoneEntity.ll b/test/DebugInfo/DebugInfoNoneEntity.ll new file mode 100644 index 0000000000..731d7c407a --- /dev/null +++ b/test/DebugInfo/DebugInfoNoneEntity.ll @@ -0,0 +1,29 @@ +; RUN: llvm-as %s -o %t.bc +; Translation shouldn't crash: +; RUN: llvm-spirv %t.bc -spirv-text +; RUN: llvm-spirv %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + +; RUN: llvm-spirv -spirv-ext=+SPV_INTEL_debug_module %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + +source_filename = "llvm-link" +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +target triple = "spir64" + +!llvm.module.flags = !{!1, !2, !3, !4} +!llvm.dbg.cu = !{!5} + +!0 = !{} +!1 = !{i32 1, !"wchar_size", i32 4} +!2 = !{i32 7, !"PIC Level", i32 2} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 2, !"Dwarf Version", i32 4} +!5 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !6, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !0, globals: !0, imports: !7, splitDebugInlining: false, nameTableKind: None) +!6 = !DIFile(filename: "declare_target_subroutine.F90", directory: "/test") +!7 = !{!8} +!8 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !9, entity: !12, file: !6, line: 24) +!9 = distinct !DISubprogram(name: "declare_target_subroutine", linkageName: "MAIN__", scope: !6, file: !6, line: 23, type: !10, scopeLine: 23, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !5, retainedNodes: !0) +!10 = !DISubroutineType(types: !11) +!11 = !{null} +!12 = !DIModule(scope: !9, name: "iso_fortran_env") diff --git a/test/DebugInfo/X86/DIModule.ll b/test/DebugInfo/X86/DIModule.ll new file mode 100644 index 0000000000..70ecc274d4 --- /dev/null +++ b/test/DebugInfo/X86/DIModule.ll @@ -0,0 +1,46 @@ +; ModuleID = '/Volumes/Data/apple-internal/llvm/tools/clang/test/Modules/debug-info-moduleimport.m' +; RUN: llvm-as < %s -o %t.bc +; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_debug_module %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll + +; RUN: llc -mtriple=x86_64-apple-macosx %t.ll -accel-tables=Dwarf -o %t -filetype=obj +; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s +; RUN: llvm-dwarfdump -verify %t + +; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_debug_module %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV + +; CHECK: DW_TAG_compile_unit +; CHECK-NOT: DW_TAG +; CHECK: DW_TAG_module +; CHECK-NEXT: DW_AT_name {{.*}}"DebugModule" +; CHECK-NEXT: DW_AT_LLVM_config_macros {{.*}}"-DMODULES=0" +; CHECK-NEXT: DW_AT_LLVM_include_path {{.*}}"/llvm/tools/clang/test/Modules/Inputs" + +; CHECK-SPIRV: Capability DebugInfoModuleINTEL +; CHECK-SPIRV: Extension "SPV_INTEL_debug_module" + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "spir64-unknown-unknown" + +; CHECK-SPIRV: String [[FileName:[0-9]+]] "/llvm/tools/clang/test/Modules/" +; CHECK-SPIRV: String [[EmptyStr:[0-9]+]] "" +; CHECK-SPIRV: String [[Name:[0-9]+]] "DebugModule" +; CHECK-SPIRV: String [[Defines:[0-9]+]] "-DMODULES=0" +; CHECK-SPIRV: String [[IncludePath:[0-9]+]] "/llvm/tools/clang/test/Modules/Inputs" + +; CHECK-SPIRV: ExtInst {{[0-9]+}} [[Module:[0-9]+]] {{[0-9]+}} DebugModuleINTEL [[Name]] {{[0-9]+}} 0 {{[0-9]+}} [[Defines]] [[IncludePath]] +; CHECK-SPIRV: ExtInst {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} DebugImportedEntity {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} [[Module]] + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !1, producer: "LLVM version 3.7.0", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !3) +!1 = !DIFile(filename: "/llvm/tools/clang/test/Modules/", directory: "/") +!2 = !{} +!3 = !{!4} +!4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !5, file: !1, line: 5) +!5 = !DIModule(scope: null, name: "DebugModule", configMacros: "-DMODULES=0", includePath: "/llvm/tools/clang/test/Modules/Inputs") +!6 = !{i32 2, !"Dwarf Version", i32 4} +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{!"LLVM version 3.7.0"} diff --git a/test/DebugInfo/X86/DIModuleContext.ll b/test/DebugInfo/X86/DIModuleContext.ll new file mode 100644 index 0000000000..71569a2769 --- /dev/null +++ b/test/DebugInfo/X86/DIModuleContext.ll @@ -0,0 +1,38 @@ +; RUN: llvm-as < %s -o %t.bc +; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_debug_module %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll + +; RUN: llc -mtriple=x86_64-apple-macosx %t.ll -o - -filetype=obj \ +; RUN: | llvm-dwarfdump -debug-info - | FileCheck %s +; CHECK: DW_TAG_module +; CHECK-NOT: NULL +; CHECK: DW_TAG_structure_type + +; Hand-crafted based on +; struct s; +; struct s *s; + +source_filename = "test/DebugInfo/X86/DIModuleContext.ll" +target triple = "spir64-unknown-unknown" + +%struct.s = type opaque + +@i = common addrspace(1) global %struct.s* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = !DIGlobalVariable(name: "s", scope: !2, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, imports: !6) +!3 = !DIFile(filename: "test.c", directory: "/") +!4 = !{} +!5 = !{!0} +!6 = !{!7} +!7 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !2, entity: !8, file: !3, line: 11) +!8 = !DIModule(scope: null, name: "Module", includePath: ".") +!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, align: 64) +!10 = !DICompositeType(tag: DW_TAG_structure_type, name: "s", scope: !8, file: !3, line: 1, flags: DIFlagFwdDecl) +!11 = !{i32 2, !"Dwarf Version", i32 2} +!12 = !{i32 2, !"Debug Info Version", i32 3} + diff --git a/test/DebugInfo/X86/Fortran-DIModule.ll b/test/DebugInfo/X86/Fortran-DIModule.ll new file mode 100644 index 0000000000..15b93ed6d6 --- /dev/null +++ b/test/DebugInfo/X86/Fortran-DIModule.ll @@ -0,0 +1,47 @@ +; This test checks attributes of a Fortran module. +; RUN: llvm-as < %s -o %t.bc +; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_debug_module %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll + +; RUN: llc -mtriple=x86_64-unknown-linux-gnu %t.ll -filetype=obj -o - | \ +; RUN: llvm-dwarfdump - | FileCheck %s + +; CHECK: DW_TAG_module +; CHECK-NEXT: DW_AT_name ("dummy") +; CHECK-NEXT: DW_AT_LLVM_sysroot ("2?/fortran?module.f90") + +; Generated from flang compiler, Fortran source to regenerate: +; module dummy +; integer :: foo +; end module dummy + +; ModuleID = '/tmp/module-b198fa.ll' +source_filename = "/tmp/module-b198fa.ll" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "spir64-unknown-unknown" + +%struct_dummy_0_ = type <{ [4 x i8] }> + +@_dummy_0_ = common addrspace(1) global %struct_dummy_0_ zeroinitializer, align 64, !dbg !0 + +; Function Attrs: noinline +define float @dummy_() #0 { +.L.entry: + ret float undef +} + +attributes #0 = { noinline "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" } + +!llvm.module.flags = !{!8, !9} +!llvm.dbg.cu = !{!3} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !4, type: !7, isLocal: false, isDefinition: true) +!2 = !DIModule(scope: !3, name: "dummy", sysroot: "2?/fortran?module.f90") +!3 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !4, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) +!4 = !DIFile(filename: "module.f90", directory: "/fortran") +!5 = !{} +!6 = !{!0} +!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/test/DebugInfo/X86/dimodule-external-fortran.ll b/test/DebugInfo/X86/dimodule-external-fortran.ll new file mode 100644 index 0000000000..c5ef4144cb --- /dev/null +++ b/test/DebugInfo/X86/dimodule-external-fortran.ll @@ -0,0 +1,94 @@ +; This test verifies that the debug info for an external Fortran module +; is correctly generated. +; +; To generate the test source, compile the following two files in order in +; the same directory (as the second compilation uses the .mod from the first): +; external_module.f90 (to compile: -g -c external_module.f90) +; module external_module +; real :: dummy +; end module external_module +; +; em.f90 (to compile: -g -llvm-emit -c -S em.f90) +; program use_external_module +; use external_module +; implicit none +; +; real :: x +; x = 2.0 + dummy +; +; end program use_external_module +; +; The test would be in em.ll. + +; RUN: llvm-as < %s -o %t.bc +; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_debug_module %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj %t.ll -o - | llvm-dwarfdump - | FileCheck %s + +; CHECK: [[DIE_ID:0x[0-9a-f]+]]: DW_TAG_module +; CHECK-NEXT: DW_AT_name ("external_module") +; CHECK-NEXT: DW_AT_LLVM_sysroot + +; CHECK: DW_TAG_imported_module +; CHECK-NEXT: DW_AT_decl_file +; CHECK-NEXT: DW_AT_decl_line +; CHECK-NEXT: DW_AT_import ([[DIE_ID]]) + +; When the debugger sees the module being imported is a declaration, +; it should go to the global scope to find the module's definition. + +; ModuleID = 'em.f90' +source_filename = "em.f90" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "spir64-unknown-unknown" + +@external_module_mp_dummy_ = available_externally global float 0.000000e+00, align 8, !dbg !0 +@0 = internal unnamed_addr constant i32 2 + +; Function Attrs: noinline nounwind uwtable +define void @MAIN__() #0 !dbg !2 { +alloca_0: + %"var$1" = alloca [8 x i64], align 8 + %"use_external_module_$X" = alloca float, align 8 + call void @llvm.dbg.declare(metadata float* %"use_external_module_$X", metadata !13, metadata !DIExpression()), !dbg !17 + %func_result = call i32 @for_set_reentrancy(i32* @0), !dbg !18 + %external_module_mp_dummy__fetch = load float, float* @external_module_mp_dummy_, align 1, !dbg !19 + %add = fadd reassoc ninf nsz arcp contract afn float 2.000000e+00, %external_module_mp_dummy__fetch, !dbg !20 + store float %add, float* %"use_external_module_$X", align 1, !dbg !19 + ret void, !dbg !21 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +declare i32 @for_set_reentrancy(i32*) + +attributes #0 = { noinline nounwind uwtable "intel-lang"="fortran" "min-legal-vector-width"="0" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } + +!llvm.module.flags = !{!15, !16} +!llvm.dbg.cu = !{!6} +!omp_offload.info = !{} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "dummy", linkageName: "external_module_mp_dummy_", scope: !2, file: !3, line: 1, type: !14, isLocal: false, isDefinition: true) +!2 = distinct !DISubprogram(name: "use_external_module", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !12) +!3 = !DIFile(filename: "em.f90", directory: "tests") +!4 = !DISubroutineType(types: !5) +!5 = !{null} +!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, imports: !9, splitDebugInlining: false, nameTableKind: None) +!7 = !{} +!8 = !{!0} +!9 = !{!10} +!10 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: !11, file: !3, line: 2) +!11 = !DIModule(scope: !2, name: "external_module") +!12 = !{!13} +!13 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14) +!14 = !DIBasicType(name: "REAL*4", size: 32, encoding: DW_ATE_float) +!15 = !{i32 2, !"Debug Info Version", i32 3} +!16 = !{i32 2, !"Dwarf Version", i32 4} +!17 = !DILocation(line: 5, column: 12, scope: !2) +!18 = !DILocation(line: 1, column: 9, scope: !2) +!19 = !DILocation(line: 6, column: 4, scope: !2) +!20 = !DILocation(line: 6, column: 12, scope: !2) +!21 = !DILocation(line: 8, column: 1, scope: !2)