Index: include/llvm-c/DebugInfo.h =================================================================== --- include/llvm-c/DebugInfo.h +++ include/llvm-c/DebugInfo.h @@ -160,7 +160,8 @@ LLVMDIObjCPropertyMetadataKind, LLVMDIImportedEntityMetadataKind, LLVMDIMacroMetadataKind, - LLVMDIMacroFileMetadataKind + LLVMDIMacroFileMetadataKind, + LLVMDICommonBlockMetadataKind }; typedef unsigned LLVMMetadataKind; Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -311,6 +311,7 @@ METADATA_INDEX_OFFSET = 38, // [offset] METADATA_INDEX = 39, // [bitpos] METADATA_LABEL = 40, // [distinct, scope, name, file, line] + METADATA_COMMON_BLOCK = 44, // [distinct, scope, name, variable,...] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -710,6 +710,17 @@ DITemplateParameterArray TParams = nullptr, DITypeArray ThrownTypes = nullptr); + /// Create common block entry for a Fortran common block + /// \param Scope Scope of this common block + /// \param Name The name of this common block + /// \param File The file this common block is defined + /// \param LineNo Line number + /// \param VarList List of variables that a located in common block + /// \param AlignInBits Common block alignment + DICommonBlock *createCommonBlock(DIScope *Scope, DIGlobalVariable *decl, + StringRef Name, DIFile *File, + unsigned LineNo, uint32_t AlignInBits = 0); + /// This creates new descriptor for a namespace with the specified /// parent scope. /// \param Scope Namespace scope Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -228,6 +228,7 @@ case DILexicalBlockKind: case DILexicalBlockFileKind: case DINamespaceKind: + case DICommonBlockKind: case DITemplateTypeParameterKind: case DITemplateValueParameterKind: case DIGlobalVariableKind: @@ -486,6 +487,7 @@ case DILexicalBlockKind: case DILexicalBlockFileKind: case DINamespaceKind: + case DICommonBlockKind: case DIModuleKind: return true; } @@ -2603,6 +2605,68 @@ } }; +class DICommonBlock : public DIScope { + unsigned LineNo; + uint32_t AlignInBits; + + friend class LLVMContextImpl; + friend class MDNode; + + DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo, + uint32_t AlignInBits, ArrayRef Ops) + : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block, + Ops), LineNo(LineNo), AlignInBits(AlignInBits) {} + ~DICommonBlock() = default; + + static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope, + DIGlobalVariable *Decl, StringRef Name, + DIFile *File, unsigned LineNo, + uint32_t AlignInBits, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name), + File, LineNo, AlignInBits, Storage, ShouldCreate); + } + static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *Decl, MDString *Name, Metadata *File, + unsigned LineNo, uint32_t AlignInBits, + StorageType Storage, bool ShouldCreate = true); + + TempDICommonBlock cloneImpl() const { + return getTemporary(getContext(), getScope(), getDecl(), getName(), + getFile(), getLineNo(), getAlignInBits()); + } + +public: + DEFINE_MDNODE_GET(DICommonBlock, + (DIScope *Scope, DIGlobalVariable *Decl, StringRef Name, + DIFile *File, unsigned LineNo, uint32_t AlignInBits), + (Scope, Decl, Name, File, LineNo, AlignInBits)) + DEFINE_MDNODE_GET(DICommonBlock, + (Metadata *Scope, Metadata *Decl, MDString *Name, + Metadata *File, unsigned LineNo, uint32_t AlignInBits), + (Scope, Decl, Name, File, LineNo, AlignInBits)) + + TempDICommonBlock clone() const { return cloneImpl(); } + + DIScope *getScope() const { return cast_or_null(getRawScope()); } + DIGlobalVariable *getDecl() const { + return cast_or_null(getRawDecl()); + } + StringRef getName() const { return getStringOperand(2); } + DIFile *getFile() const { return cast_or_null(getRawFile()); } + unsigned getLineNo() const { return LineNo; } + uint32_t getAlignInBits() const { return AlignInBits; } + + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawDecl() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs(2); } + Metadata *getRawFile() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICommonBlockKind; + } +}; + /// Local variable. /// /// TODO: Split up flags. Index: include/llvm/IR/Metadata.def =================================================================== --- include/llvm/IR/Metadata.def +++ include/llvm/IR/Metadata.def @@ -114,6 +114,7 @@ HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock) #undef HANDLE_METADATA #undef HANDLE_METADATA_LEAF Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -4565,6 +4565,25 @@ return false; } +/// ParseDICommonBlock: +/// ::= !DICommonBlock(scope: !0, file: !2, name: "COMMON name", line: 9) +bool LLParser::ParseDICommonBlock(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(declaration, MDField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DICommonBlock, + (Context, scope.Val, declaration.Val, name.Val, + file.Val, line.Val, align.Val)); + return false; +} + /// ParseDINamespace: /// ::= !DINamespace(scope: !0, file: !2, name: "SomeNamespace", line: 9) bool LLParser::ParseDINamespace(MDNode *&Result, bool IsDistinct) { Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -816,6 +816,7 @@ case bitc::METADATA_LEXICAL_BLOCK: case bitc::METADATA_LEXICAL_BLOCK_FILE: case bitc::METADATA_NAMESPACE: + case bitc::METADATA_COMMON_BLOCK: case bitc::METADATA_MACRO: case bitc::METADATA_MACRO_FILE: case bitc::METADATA_TEMPLATE_TYPE: @@ -1490,6 +1491,17 @@ NextMetadataNo++; break; } + case bitc::METADATA_COMMON_BLOCK: { + IsDistinct = Record[0] & 1; + MetadataList.assignValue( + GET_OR_DISTINCT(DICommonBlock, + (Context, getMDOrNull(Record[1]), + getMDOrNull(Record[2]), getMDString(Record[3]), + getMDOrNull(Record[4]), Record[5], Record[6])), + NextMetadataNo); + NextMetadataNo++; + break; + } case bitc::METADATA_NAMESPACE: { // Newer versions of DINamespace dropped file and line. MDString *Name; Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -316,6 +316,8 @@ void writeDILexicalBlockFile(const DILexicalBlockFile *N, SmallVectorImpl &Record, unsigned Abbrev); + void writeDICommonBlock(const DICommonBlock *N, + SmallVectorImpl &Record, unsigned Abbrev); void writeDINamespace(const DINamespace *N, SmallVectorImpl &Record, unsigned Abbrev); void writeDIMacro(const DIMacro *N, SmallVectorImpl &Record, @@ -1670,6 +1672,21 @@ Record.clear(); } +void ModuleBitcodeWriter::writeDICommonBlock(const DICommonBlock *N, + SmallVectorImpl &Record, + unsigned Abbrev) { + Record.push_back(N->isDistinct()); + Record.push_back(VE.getMetadataOrNullID(N->getScope())); + Record.push_back(VE.getMetadataOrNullID(N->getDecl())); + Record.push_back(VE.getMetadataOrNullID(N->getRawName())); + Record.push_back(VE.getMetadataOrNullID(N->getFile())); + Record.push_back(N->getLineNo()); + Record.push_back(N->getAlignInBits()); + + Stream.EmitRecord(bitc::METADATA_COMMON_BLOCK, Record, Abbrev); + Record.clear(); +} + void ModuleBitcodeWriter::writeDINamespace(const DINamespace *N, SmallVectorImpl &Record, unsigned Abbrev) { Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -130,6 +130,12 @@ getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV, ArrayRef GlobalExprs); + DIE *getOrCreateCommonBlock(const DICommonBlock *CB, + ArrayRef GlobalExprs); + + void addLocationAttribute(DIE *ToDIE, const DIGlobalVariable *GV, + ArrayRef GlobalExprs); + /// addLabelAddress - Add a dwarf label attribute data and value using /// either DW_FORM_addr or DW_FORM_GNU_addr_index. void addLabelAddress(DIE &Die, dwarf::Attribute Attribute, Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -110,62 +110,8 @@ File->getSource(), CUID); } -DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( - const DIGlobalVariable *GV, ArrayRef GlobalExprs) { - // Check for pre-existence. - if (DIE *Die = getDIE(GV)) - return Die; - - assert(GV); - - auto *GVContext = GV->getScope(); - auto *GTy = DD->resolve(GV->getType()); - - // Construct the context before querying for the existence of the DIE in - // case such construction creates the DIE. - DIE *ContextDIE = getOrCreateContextDIE(GVContext); - - // Add to map. - DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV); - DIScope *DeclContext; - if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) { - DeclContext = resolve(SDMDecl->getScope()); - assert(SDMDecl->isStaticMember() && "Expected static member decl"); - assert(GV->isDefinition()); - // We need the declaration DIE that is in the static member's class. - DIE *VariableSpecDIE = getOrCreateStaticMemberDIE(SDMDecl); - addDIEEntry(*VariableDIE, dwarf::DW_AT_specification, *VariableSpecDIE); - // If the global variable's type is different from the one in the class - // member type, assume that it's more specific and also emit it. - if (GTy != DD->resolve(SDMDecl->getBaseType())) - addType(*VariableDIE, GTy); - } else { - DeclContext = GV->getScope(); - // Add name and type. - addString(*VariableDIE, dwarf::DW_AT_name, GV->getDisplayName()); - addType(*VariableDIE, GTy); - - // Add scoping info. - if (!GV->isLocalToUnit()) - addFlag(*VariableDIE, dwarf::DW_AT_external); - - // Add line number info. - addSourceLine(*VariableDIE, GV); - } - - if (!GV->isDefinition()) - addFlag(*VariableDIE, dwarf::DW_AT_declaration); - else - addGlobalName(GV->getName(), *VariableDIE, DeclContext); - - if (uint32_t AlignInBytes = GV->getAlignInBytes()) - addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, - AlignInBytes); - - if (MDTuple *TP = GV->getTemplateParams()) - addTemplateParams(*VariableDIE, DINodeArray(TP)); - - // Add location. +void DwarfCompileUnit::addLocationAttribute( + DIE *ToDIE, const DIGlobalVariable *GV, ArrayRef GlobalExprs) { bool addToAccelTable = false; DIELoc *Loc = nullptr; std::unique_ptr DwarfExpr; @@ -178,7 +124,7 @@ // DW_AT_const_value(X). if (GlobalExprs.size() == 1 && Expr && Expr->isConstant()) { addToAccelTable = true; - addConstantValue(*VariableDIE, /*Unsigned=*/true, Expr->getElement(1)); + addConstantValue(*ToDIE, /*Unsigned=*/true, Expr->getElement(1)); break; } @@ -248,20 +194,101 @@ DwarfExpr->addExpression(Expr); } if (Loc) - addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize()); + addBlock(*ToDIE, dwarf::DW_AT_location, DwarfExpr->finalize()); if (DD->useAllLinkageNames()) - addLinkageName(*VariableDIE, GV->getLinkageName()); + addLinkageName(*ToDIE, GV->getLinkageName()); if (addToAccelTable) { - DD->addAccelName(*CUNode, GV->getName(), *VariableDIE); + DD->addAccelName(*CUNode, GV->getName(), *ToDIE); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() && DD->useAllLinkageNames()) - DD->addAccelName(*CUNode, GV->getLinkageName(), *VariableDIE); + DD->addAccelName(*CUNode, GV->getLinkageName(), *ToDIE); + } +} + +DIE *DwarfCompileUnit::getOrCreateCommonBlock( + const DICommonBlock *CB, ArrayRef GlobalExprs) { + // Construct the context before querying for the existence of the DIE in case + // such construction creates the DIE. + DIE *ContextDIE = getOrCreateContextDIE(CB->getScope()); + + if (DIE *NDie = getDIE(CB)) + return NDie; + DIE &NDie = createAndAddDIE(dwarf::DW_TAG_common_block, *ContextDIE, CB); + StringRef Name = CB->getName().empty() ? "_BLNK_" : CB->getName(); + addString(NDie, dwarf::DW_AT_name, Name); + addGlobalName(Name, NDie, CB->getScope()); + if (CB->getFile()) + addSourceLine(NDie, CB->getLineNo(), CB->getFile()); + if (DIGlobalVariable *V = CB->getDecl()) + getCU().addLocationAttribute(&NDie, V, GlobalExprs); + if (uint32_t AlignInBits = CB->getAlignInBits()) { + uint32_t AlignInBytes = AlignInBits >> 3; + addUInt(NDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, AlignInBytes); } + return &NDie; +} + +DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( + const DIGlobalVariable *GV, ArrayRef GlobalExprs) { + // Check for pre-existence. + if (DIE *Die = getDIE(GV)) + return Die; + + assert(GV); + + auto *GVContext = GV->getScope(); + auto *GTy = DD->resolve(GV->getType()); + + // Construct the context before querying for the existence of the DIE in + // case such construction creates the DIE. + auto *CB = dyn_cast(GVContext); + DIE *ContextDIE = CB ? getOrCreateCommonBlock(CB, GlobalExprs) + : getOrCreateContextDIE(GVContext); + + // Add to map. + DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV); + DIScope *DeclContext; + if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) { + DeclContext = resolve(SDMDecl->getScope()); + assert(SDMDecl->isStaticMember() && "Expected static member decl"); + assert(GV->isDefinition()); + // We need the declaration DIE that is in the static member's class. + DIE *VariableSpecDIE = getOrCreateStaticMemberDIE(SDMDecl); + addDIEEntry(*VariableDIE, dwarf::DW_AT_specification, *VariableSpecDIE); + // If the global variable's type is different from the one in the class + // member type, assume that it's more specific and also emit it. + if (GTy != DD->resolve(SDMDecl->getBaseType())) + addType(*VariableDIE, GTy); + } else { + DeclContext = GV->getScope(); + // Add name and type. + addString(*VariableDIE, dwarf::DW_AT_name, GV->getDisplayName()); + addType(*VariableDIE, GTy); + + // Add scoping info. + if (!GV->isLocalToUnit()) + addFlag(*VariableDIE, dwarf::DW_AT_external); + + // Add line number info. + addSourceLine(*VariableDIE, GV); + } + + if (!GV->isDefinition()) + addFlag(*VariableDIE, dwarf::DW_AT_declaration); + else + addGlobalName(GV->getName(), *VariableDIE, DeclContext); + + if (uint32_t AlignInBytes = GV->getAlignInBytes()) + addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, + AlignInBytes); + + // Add location. + addLocationAttribute(VariableDIE, GV, GlobalExprs); return VariableDIE; } Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -679,7 +679,7 @@ DD->addAccelType(*CUNode, Ty->getName(), TyDIE, Flags); if (!Context || isa(Context) || isa(Context) || - isa(Context)) + isa(Context) || isa(Context)) addGlobalType(Ty, TyDIE, Context); } } Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1981,6 +1981,20 @@ Out << ")"; } +static void writeDICommonBlock(raw_ostream &Out, const DICommonBlock *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DICommonBlock("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printMetadata("scope", N->getRawScope(), false); + Printer.printMetadata("declaration", N->getRawDecl(), false); + Printer.printString("name", N->getName()); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLineNo()); + Printer.printInt("align", N->getAlignInBits()); + Out << ")"; +} + static void writeDIMacro(raw_ostream &Out, const DIMacro *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -803,6 +803,13 @@ return SP; } +DICommonBlock *DIBuilder::createCommonBlock( + DIScope *Scope, DIGlobalVariable *Decl, StringRef Name, DIFile *File, + unsigned LineNo, uint32_t AlignInBits) { + return DICommonBlock::get( + VMContext, Scope, Decl, Name, File, LineNo, AlignInBits); +} + DINamespace *DIBuilder::createNameSpace(DIScope *Scope, StringRef Name, bool ExportSymbols) { Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -180,6 +180,9 @@ if (auto *NS = dyn_cast(this)) return NS->getScope(); + if (auto *CB = dyn_cast(this)) + return CB->getScope(); + if (auto *M = dyn_cast(this)) return M->getScope(); @@ -195,6 +198,8 @@ return SP->getName(); if (auto *NS = dyn_cast(this)) return NS->getName(); + if (auto *CB = dyn_cast(this)) + return CB->getName(); if (auto *M = dyn_cast(this)) return M->getName(); assert((isa(this) || isa(this) || @@ -617,6 +622,19 @@ DEFINE_GETIMPL_STORE(DINamespace, (ExportSymbols), Ops); } +DICommonBlock *DICommonBlock::getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *Decl, MDString *Name, + Metadata *File, unsigned LineNo, + uint32_t AlignInBits, + StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DICommonBlock, (Scope, Decl, Name, File, LineNo, + AlignInBits)); + // The nullptr is for DIScope's File operand. This should be refactored. + Metadata *Ops[] = {Scope, Decl, Name, File}; + DEFINE_GETIMPL_STORE(DICommonBlock, (LineNo, AlignInBits), Ops); +} + DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *ConfigurationMacros, MDString *IncludePath, MDString *ISysRoot, Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -796,6 +796,34 @@ } }; +template <> struct MDNodeKeyImpl { + Metadata *Scope; + Metadata *Decl; + MDString *Name; + Metadata *File; + unsigned LineNo; + uint32_t AlignInBits; + + MDNodeKeyImpl(Metadata *Scope, Metadata *Decl, MDString *Name, + Metadata *File, unsigned LineNo, uint32_t AlignInBits) + : Scope(Scope), Decl(Decl), Name(Name), File(File), LineNo(LineNo), + AlignInBits(AlignInBits) {} + MDNodeKeyImpl(const DICommonBlock *N) + : Scope(N->getRawScope()), Decl(N->getRawDecl()), Name(N->getRawName()), + File(N->getRawFile()), LineNo(N->getLineNo()), + AlignInBits(N->getAlignInBits()) {} + + bool isKeyOf(const DICommonBlock *RHS) const { + return Scope == RHS->getRawScope() && Decl == RHS->getRawDecl() && + Name == RHS->getRawName() && File == RHS->getRawFile() && + LineNo == RHS->getLineNo() && AlignInBits == RHS->getAlignInBits(); + } + + unsigned getHashValue() const { + return hash_combine(Scope, Decl, Name, File, LineNo, AlignInBits); + } +}; + template <> struct MDNodeKeyImpl { Metadata *Scope; MDString *Name; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -1145,6 +1145,14 @@ visitDILexicalBlockBase(N); } +void Verifier::visitDICommonBlock(const DICommonBlock &N) { + AssertDI(N.getTag() == dwarf::DW_TAG_common_block, "invalid tag", &N); + if (auto *S = N.getRawScope()) + AssertDI(isa(S), "invalid scope ref", &N, S); + if (auto *S = N.getRawDecl()) + AssertDI(isa(S), "invalid declaration", &N, S); +} + void Verifier::visitDINamespace(const DINamespace &N) { AssertDI(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N); if (auto *S = N.getRawScope()) Index: test/DebugInfo/DICommonBlock.ll =================================================================== --- /dev/null +++ test/DebugInfo/DICommonBlock.ll @@ -0,0 +1,36 @@ +; ModuleID = 'none.f90' +; RUN: llc %s -o %t -filetype=obj +; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s +; CHECK: DW_TAG_common_block + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx" + +@common_a = common global [32 x i8] zeroinitializer, align 8, !dbg !13 + +define i32 @subr() !dbg !9 { + %1 = getelementptr inbounds [32 x i8], [32 x i8]* @common_a, i64 0, i32 8 + %2 = bitcast i8* %1 to i32* + %3 = load i32, i32* %2 + ret i32 %3 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !1, producer: "PGI Fortran", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, retainedTypes: !14, globals: !2) +!1 = !DIFile(filename: "none.f90", directory: "/not/here/") +!2 = !{} +!3 = !{} +!4 = !DIGlobalVariable(name: "common /a/", scope: !5, file: !1, line: 4, isLocal: false, isDefinition: true, type: !12) +!5 = !DICommonBlock(scope: !9, declaration: !4, name: "a", file: !1, line: 4) +!6 = !{i32 2, !"Dwarf Version", i32 4} +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{!"PGI Fortran"} +!9 = distinct !DISubprogram(name: "subrtn", scope: !0, file: !1, line: 1, type: !10, isLocal: false, isDefinition: true, unit: !0) +!10 = !DISubroutineType(types: !11) +!11 = !{!12, !12} +!12 = !DIBasicType(name: "int", size: 32) +!13 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!14 = !{!12, !10}