From 0f8087dcb3e509614b9e2b49bed2f1ddefceda17 Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Mon, 1 Oct 2018 12:23:27 -0700 Subject: [PATCH] Changes to support the generation of DW_TAG_common_block (DWARF debug information) for Fortran's COMMON statement. --- include/llvm/Bitcode/LLVMBitCodes.h | 1 + include/llvm/IR/DIBuilder.h | 11 ++ include/llvm/IR/DebugInfoMetadata.h | 64 +++++++++ include/llvm/IR/Metadata.def | 1 + lib/AsmParser/LLParser.cpp | 19 +++ lib/Bitcode/Reader/MetadataLoader.cpp | 12 ++ lib/Bitcode/Writer/BitcodeWriter.cpp | 17 +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 147 ++++++++++++-------- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 6 + lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 2 +- lib/IR/AsmWriter.cpp | 14 ++ lib/IR/DIBuilder.cpp | 7 + lib/IR/DebugInfoMetadata.cpp | 18 +++ lib/IR/LLVMContextImpl.h | 28 ++++ lib/IR/Verifier.cpp | 8 ++ test/DebugInfo/X86/DICommonBlock.ll | 36 +++++ 16 files changed, 332 insertions(+), 59 deletions(-) create mode 100644 test/DebugInfo/X86/DICommonBlock.ll diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 5b3a7af632188..9e4d226bec9eb 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -301,6 +301,7 @@ enum MetadataCodes { METADATA_STRING_TYPE = 40, // [distinct, name, size, align, ...] METADATA_FORTRAN_ARRAY_TYPE = 41, // [distinct, name, [bounds ...], ...] METADATA_FORTRAN_SUBRANGE = 42, // [distinct, lbound, lbnde, ubound, ubnde] + METADATA_COMMON_BLOCK = 43, // [distinct, scope, name, variable,...] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 38c31824cb322..2d034b331a083 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -658,6 +658,17 @@ namespace llvm { 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 diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index d0757e8889f9f..16b2482bf1a71 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -229,6 +229,7 @@ class DINode : public MDNode { case DILexicalBlockKind: case DILexicalBlockFileKind: case DINamespaceKind: + case DICommonBlockKind: case DITemplateTypeParameterKind: case DITemplateValueParameterKind: case DIGlobalVariableKind: @@ -528,6 +529,7 @@ class DIScope : public DINode { case DILexicalBlockKind: case DILexicalBlockFileKind: case DINamespaceKind: + case DICommonBlockKind: case DIModuleKind: return true; } @@ -2653,6 +2655,68 @@ class DIGlobalVariable : public DIVariable { } }; +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. diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index 3fa30a56a2a33..dddca513c953f 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -116,6 +116,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFortranArrayType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFortranSubrange) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock) #undef HANDLE_METADATA #undef HANDLE_METADATA_LEAF diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 125edbb8ce43f..771b5a1386d9c 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -4310,6 +4310,25 @@ bool LLParser::ParseDILexicalBlockFile(MDNode *&Result, bool IsDistinct) { return false; } +/// ParseDICommonBlock: +/// ::= !DICommonBlock(scope: !0, file: !2, name: "SomeNamespace", 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) { diff --git a/lib/Bitcode/Reader/MetadataLoader.cpp b/lib/Bitcode/Reader/MetadataLoader.cpp index 0d2f38065ae88..6a2e6b98e2301 100644 --- a/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/lib/Bitcode/Reader/MetadataLoader.cpp @@ -819,6 +819,7 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() { 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: @@ -1524,6 +1525,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( 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; diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index c7c543029d701..c24f509bccca9 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -317,6 +317,8 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase { 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, @@ -1695,6 +1697,21 @@ void ModuleBitcodeWriter::writeDILexicalBlockFile( 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) { diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 208affa7b7f7f..ddbcba5fb2b04 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -106,59 +106,8 @@ unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID()); } -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); - - // Add location. +void DwarfCompileUnit::addLocationAttribute( + DIE *ToDIE, const DIGlobalVariable *GV, ArrayRef GlobalExprs) { bool addToAccelTable = false; DIELoc *Loc = nullptr; std::unique_ptr DwarfExpr; @@ -171,7 +120,7 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( // 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; } @@ -231,19 +180,101 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( } } 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(GV->getName(), *VariableDIE); + DD->addAccelName(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->addAccelName(GV->getLinkageName(), *VariableDIE); + DD->addAccelName(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()->getFilename(), + CB->getFile()->getDirectory()); + 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; } diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 08def4f8d3581..5630a978c42a1 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -129,6 +129,12 @@ class DwarfCompileUnit final : public DwarfUnit { 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, diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index cc9c99dec9ace..68158046058d3 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -758,7 +758,7 @@ void DwarfUnit::updateAcceleratorTables(const DIScope *Context, DD->addAccelType(Ty->getName(), TyDIE, Flags); if (!Context || isa(Context) || isa(Context) || - isa(Context)) + isa(Context) || isa(Context)) addGlobalType(Ty, TyDIE, Context); } } diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index d31a6b1bc239a..a58232fc94a61 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1874,6 +1874,20 @@ static void writeDINamespace(raw_ostream &Out, const DINamespace *N, 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) { diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 63c53bdbc394e..dcfb3137dff90 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -759,6 +759,13 @@ DISubprogram *DIBuilder::createMethod( 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) { diff --git a/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp index 84d892b602014..dc222be6b3fa1 100644 --- a/lib/IR/DebugInfoMetadata.cpp +++ b/lib/IR/DebugInfoMetadata.cpp @@ -160,6 +160,9 @@ DIScopeRef DIScope::getScope() const { 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(); @@ -175,6 +178,8 @@ StringRef DIScope::getName() const { 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) || @@ -584,6 +589,19 @@ DINamespace *DINamespace::getImpl(LLVMContext &Context, Metadata *Scope, 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, diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 10b137d00d3de..5cd4e25b0b25a 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -880,6 +880,34 @@ template <> struct MDNodeKeyImpl { } }; +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; diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index b20eaba9c72c2..626adf7663566 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -1118,6 +1118,14 @@ void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) { 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()) diff --git a/test/DebugInfo/X86/DICommonBlock.ll b/test/DebugInfo/X86/DICommonBlock.ll new file mode 100644 index 0000000000000..5492b94d3a695 --- /dev/null +++ b/test/DebugInfo/X86/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} \ No newline at end of file