From a8242765e2ce94cd2fd36d73d233915f91908580 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 6 Oct 2025 18:40:10 +0100 Subject: [PATCH 1/6] [llvm][DebugInfo] Abstract DICompileUnit::SourceLanguage to allow alternate DWARF SourceLanguage encoding (cherry picked from commit 7fe58f8007537445a7cb2922bfbe35781c26ff5a) --- clang/lib/CodeGen/CGDebugInfo.cpp | 12 ++-- llvm/include/llvm/IR/DIBuilder.h | 6 +- llvm/include/llvm/IR/DebugInfoMetadata.h | 65 +++++++++++++++---- llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp | 6 +- llvm/lib/AsmParser/LLParser.cpp | 10 +-- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 10 +-- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 +- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 4 +- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 12 ++-- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 16 +++-- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 7 +- llvm/lib/IR/AsmWriter.cpp | 8 ++- llvm/lib/IR/DIBuilder.cpp | 8 +-- llvm/lib/IR/DebugInfo.cpp | 2 +- llvm/lib/IR/DebugInfoMetadata.cpp | 9 +-- .../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 3 +- .../WebAssembly/WebAssemblyAsmPrinter.cpp | 4 +- llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 12 ++-- llvm/lib/Transforms/Utils/Debugify.cpp | 5 +- llvm/unittests/CodeGen/InstrRefLDVTest.cpp | 4 +- llvm/unittests/CodeGen/LexicalScopesTest.cpp | 4 +- .../CodeGen/MachineBasicBlockTest.cpp | 4 +- .../Frontend/OpenMPIRBuilderTest.cpp | 5 +- llvm/unittests/IR/DebugInfoTest.cpp | 11 ++-- llvm/unittests/IR/IRBuilderTest.cpp | 35 +++++----- llvm/unittests/IR/MetadataTest.cpp | 25 +++---- llvm/unittests/IR/VerifierTest.cpp | 8 ++- .../Transforms/Utils/CloningTest.cpp | 24 +++---- mlir/lib/Target/LLVMIR/DebugImporter.cpp | 3 +- 29 files changed, 200 insertions(+), 125 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index fee6bc0cbb64b..b91cb36483d72 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -787,7 +787,8 @@ void CGDebugInfo::CreateCompileUnit() { // Create new compile unit. TheCU = DBuilder.createCompileUnit( - LangTag, CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "", + llvm::DISourceLanguageName(LangTag), CUFile, + CGOpts.EmitVersionIdentMetadata ? Producer : "", CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.SplitDwarfFile, EmissionKind, @@ -1232,7 +1233,7 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty, /// \return whether a C++ mangling exists for the type defined by TD. static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) { - switch (TheCU->getSourceLanguage()) { + switch (TheCU->getSourceLanguage().getUnversionedName()) { case llvm::dwarf::DW_LANG_C_plus_plus: case llvm::dwarf::DW_LANG_C_plus_plus_11: case llvm::dwarf::DW_LANG_C_plus_plus_14: @@ -3211,8 +3212,8 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, if (!ID) return nullptr; - auto RuntimeLang = - static_cast(TheCU->getSourceLanguage()); + auto RuntimeLang = static_cast( + TheCU->getSourceLanguage().getUnversionedName()); // Return a forward declaration if this type was imported from a clang module, // and this is not the compile unit with the implementation of the type (which @@ -3348,7 +3349,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, ObjCInterfaceDecl *ID = Ty->getDecl(); llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation()); unsigned Line = getLineNumber(ID->getLocation()); - unsigned RuntimeLang = TheCU->getSourceLanguage(); + + unsigned RuntimeLang = TheCU->getSourceLanguage().getUnversionedName(); // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(Ty); diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 25cbc38b61272..6529412abd252 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -146,9 +146,9 @@ namespace llvm { /// \param SDK The SDK name. On Darwin, this is the last component /// of the sysroot. LLVM_ABI DICompileUnit * - createCompileUnit(unsigned Lang, DIFile *File, StringRef Producer, - bool isOptimized, StringRef Flags, unsigned RV, - StringRef SplitName = StringRef(), + createCompileUnit(DISourceLanguageName Lang, DIFile *File, + StringRef Producer, bool isOptimized, StringRef Flags, + unsigned RV, StringRef SplitName = StringRef(), DICompileUnit::DebugEmissionKind Kind = DICompileUnit::DebugEmissionKind::FullDebug, uint64_t DWOId = 0, bool SplitDebugInlining = true, diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 6652e303a6648..80c9ea38016b6 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -66,6 +66,44 @@ namespace dwarf { enum Tag : uint16_t; } +/// Wrapper structure that holds a language name and its version. +/// +/// Some debug-info formats, particularly DWARF, distniguish between +/// language codes that include the version name and codes that don't. +/// DISourceLanguageName may hold either of these. +/// +class DISourceLanguageName { + /// Language name. + /// If \ref Version is not std::nullopt, then this name + /// is version independent (i.e., doesn't include the language + /// version in its name). + uint16_t Name; + + /// Language version. The version scheme is language + /// dependent. + std::optional Version; + +public: + bool hasVersionedName() const { return Version.has_value(); } + + /// Returns a versioned or unversioned language name. + uint16_t getName() const { return Name; } + + // Transitional API for cases where we do not yet support + // versioned source language names. Use \ref getName instead. + // + // FIXME: remove once all callers of this API account for versioned + // names. + uint16_t getUnversionedName() const { + assert(!hasVersionedName()); + return Name; + } + + DISourceLanguageName(uint16_t Lang, uint32_t Version) + : Name(Lang), Version(Version) {}; + DISourceLanguageName(uint16_t Lang) : Name(Lang), Version(std::nullopt) {}; +}; + class DbgVariableRecord; LLVM_ABI extern cl::opt EnableFSDiscriminator; @@ -2003,7 +2041,7 @@ class DICompileUnit : public DIScope { LLVM_ABI static const char *nameTableKindString(DebugNameTableKind PK); private: - unsigned SourceLanguage; + DISourceLanguageName SourceLanguage; unsigned RuntimeVersion; uint64_t DWOId; unsigned EmissionKind; @@ -2013,16 +2051,17 @@ class DICompileUnit : public DIScope { bool DebugInfoForProfiling; bool RangesBaseAddress; - DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, - bool IsOptimized, unsigned RuntimeVersion, - unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining, - bool DebugInfoForProfiling, unsigned NameTableKind, - bool RangesBaseAddress, ArrayRef Ops); + DICompileUnit(LLVMContext &C, StorageType Storage, + DISourceLanguageName SourceLanguage, bool IsOptimized, + unsigned RuntimeVersion, unsigned EmissionKind, uint64_t DWOId, + bool SplitDebugInlining, bool DebugInfoForProfiling, + unsigned NameTableKind, bool RangesBaseAddress, + ArrayRef Ops); ~DICompileUnit() = default; static DICompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, - StringRef Producer, bool IsOptimized, StringRef Flags, + getImpl(LLVMContext &Context, DISourceLanguageName SourceLanguage, + DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, unsigned EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, @@ -2042,8 +2081,8 @@ class DICompileUnit : public DIScope { getCanonicalMDString(Context, SDK), Storage, ShouldCreate); } LLVM_ABI static DICompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, - MDString *Producer, bool IsOptimized, MDString *Flags, + getImpl(LLVMContext &Context, DISourceLanguageName SourceLanguage, + Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables, Metadata *ImportedEntities, @@ -2068,7 +2107,7 @@ class DICompileUnit : public DIScope { DEFINE_MDNODE_GET_DISTINCT_TEMPORARY( DICompileUnit, - (unsigned SourceLanguage, DIFile *File, StringRef Producer, + (DISourceLanguageName SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, @@ -2084,7 +2123,7 @@ class DICompileUnit : public DIScope { SysRoot, SDK)) DEFINE_MDNODE_GET_DISTINCT_TEMPORARY( DICompileUnit, - (unsigned SourceLanguage, Metadata *File, MDString *Producer, + (DISourceLanguageName SourceLanguage, Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables, @@ -2099,7 +2138,7 @@ class DICompileUnit : public DIScope { TempDICompileUnit clone() const { return cloneImpl(); } - unsigned getSourceLanguage() const { return SourceLanguage; } + DISourceLanguageName getSourceLanguage() const { return SourceLanguage; } bool isOptimized() const { return IsOptimized; } unsigned getRuntimeVersion() const { return RuntimeVersion; } DebugEmissionKind getEmissionKind() const { diff --git a/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp b/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp index 0fbf082615af3..f31d625eca14c 100644 --- a/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp +++ b/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp @@ -43,11 +43,13 @@ static void printModuleDebugInfo(raw_ostream &O, const Module *M, // filenames), so just print a few useful things. for (DICompileUnit *CU : Finder.compile_units()) { O << "Compile unit: "; - auto Lang = dwarf::LanguageString(CU->getSourceLanguage()); + auto Lang = + dwarf::LanguageString(CU->getSourceLanguage().getUnversionedName()); if (!Lang.empty()) O << Lang; else - O << "unknown-language(" << CU->getSourceLanguage() << ")"; + O << "unknown-language(" << CU->getSourceLanguage().getUnversionedName() + << ")"; printFile(O, CU->getFilename(), CU->getDirectory()); O << '\n'; } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 897e679095906..55899660fa84a 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -5861,11 +5861,11 @@ bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) { #undef VISIT_MD_FIELDS Result = DICompileUnit::getDistinct( - Context, language.Val, file.Val, producer.Val, isOptimized.Val, flags.Val, - runtimeVersion.Val, splitDebugFilename.Val, emissionKind.Val, enums.Val, - retainedTypes.Val, globals.Val, imports.Val, macros.Val, dwoId.Val, - splitDebugInlining.Val, debugInfoForProfiling.Val, nameTableKind.Val, - rangesBaseAddress.Val, sysroot.Val, sdk.Val); + Context, DISourceLanguageName(language.Val), file.Val, producer.Val, + isOptimized.Val, flags.Val, runtimeVersion.Val, splitDebugFilename.Val, + emissionKind.Val, enums.Val, retainedTypes.Val, globals.Val, imports.Val, + macros.Val, dwoId.Val, splitDebugInlining.Val, debugInfoForProfiling.Val, + nameTableKind.Val, rangesBaseAddress.Val, sysroot.Val, sdk.Val); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 22c7fa5f515ee..a4d1b8372dfac 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1866,11 +1866,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( // Ignore Record[0], which indicates whether this compile unit is // distinct. It's always distinct. IsDistinct = true; + auto *CU = DICompileUnit::getDistinct( - Context, Record[1], getMDOrNull(Record[2]), getMDString(Record[3]), - Record[4], getMDString(Record[5]), Record[6], getMDString(Record[7]), - Record[8], getMDOrNull(Record[9]), getMDOrNull(Record[10]), - getMDOrNull(Record[12]), getMDOrNull(Record[13]), + Context, DISourceLanguageName(Record[1]), getMDOrNull(Record[2]), + getMDString(Record[3]), Record[4], getMDString(Record[5]), Record[6], + getMDString(Record[7]), Record[8], getMDOrNull(Record[9]), + getMDOrNull(Record[10]), getMDOrNull(Record[12]), + getMDOrNull(Record[13]), Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]), Record.size() <= 14 ? 0 : Record[14], Record.size() <= 16 ? true : Record[16], diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index c4070e1f44688..bae05dc43a0fd 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2105,7 +2105,8 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N, unsigned Abbrev) { assert(N->isDistinct() && "Expected distinct compile units"); Record.push_back(/* IsDistinct */ true); - Record.push_back(N->getSourceLanguage()); + + Record.push_back(N->getSourceLanguage().getUnversionedName()); Record.push_back(VE.getMetadataOrNullID(N->getFile())); Record.push_back(VE.getMetadataOrNullID(N->getRawProducer())); Record.push_back(N->isOptimized()); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index c5d6e40eb7c1e..12d749ce56f06 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -633,8 +633,8 @@ void CodeViewDebug::beginModule(Module *M) { Node = *CUs->operands().begin(); } const auto *CU = cast(Node); - - CurrentSourceLanguage = MapDWLangToCVLang(CU->getSourceLanguage()); + CurrentSourceLanguage = + MapDWLangToCVLang(CU->getSourceLanguage().getUnversionedName()); if (!M->getCodeViewFlag() || CU->getEmissionKind() == DICompileUnit::NoDebug) { Asm = nullptr; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 09d5f9c57a1a7..d751a7f9f01ef 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1040,7 +1040,8 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, NewCU.addString(Die, dwarf::DW_AT_producer, Producer); NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - DIUnit->getSourceLanguage()); + DIUnit->getSourceLanguage().getUnversionedName()); + NewCU.addString(Die, dwarf::DW_AT_name, FN); StringRef SysRoot = DIUnit->getSysRoot(); if (!SysRoot.empty()) @@ -2930,10 +2931,9 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU, case dwarf::DW_TAG_union_type: case dwarf::DW_TAG_enumeration_type: return dwarf::PubIndexEntryDescriptor( - dwarf::GIEK_TYPE, - dwarf::isCPlusPlus((dwarf::SourceLanguage)CU->getLanguage()) - ? dwarf::GIEL_EXTERNAL - : dwarf::GIEL_STATIC); + dwarf::GIEK_TYPE, dwarf::isCPlusPlus(CU->getSourceLanguage()) + ? dwarf::GIEL_EXTERNAL + : dwarf::GIEL_STATIC); case dwarf::DW_TAG_typedef: case dwarf::DW_TAG_base_type: case dwarf::DW_TAG_subrange_type: @@ -3926,7 +3926,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, TypeUnitsUnderConstruction.emplace_back(std::move(OwnedUnit), CTy); NewTU.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - CU.getLanguage()); + CU.getSourceLanguage()); uint64_t Signature = makeTypeSignature(Identifier); NewTU.setTypeSignature(Signature); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 3cfe7cc12d5b6..aa078f3f81d49 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -100,7 +100,7 @@ DwarfUnit::~DwarfUnit() { } int64_t DwarfUnit::getDefaultLowerBound() const { - switch (getLanguage()) { + switch (getSourceLanguage()) { default: break; @@ -704,12 +704,17 @@ void DwarfUnit::addType(DIE &Entity, const DIType *Ty, addDIEEntry(Entity, Attribute, DIEEntry(*getOrCreateTypeDIE(Ty))); } +llvm::dwarf::SourceLanguage DwarfUnit::getSourceLanguage() const { + return static_cast( + getLanguage().getUnversionedName()); +} + std::string DwarfUnit::getParentContextString(const DIScope *Context) const { if (!Context) return ""; // FIXME: Decide whether to implement this for non-C++ languages. - if (!dwarf::isCPlusPlus((dwarf::SourceLanguage)getLanguage())) + if (!dwarf::isCPlusPlus(getSourceLanguage())) return ""; std::string CS; @@ -940,7 +945,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy) { // Add prototype flag if we're dealing with a C language and the function has // been prototyped. - if (isPrototyped && dwarf::isC((dwarf::SourceLanguage)getLanguage())) + if (isPrototyped && dwarf::isC(getSourceLanguage())) addFlag(Buffer, dwarf::DW_AT_prototyped); // Add a DW_AT_calling_convention if this has an explicit convention. @@ -1448,7 +1453,7 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, // Add the prototype if we have a prototype and we have a C like // language. - if (SP->isPrototyped() && dwarf::isC((dwarf::SourceLanguage)getLanguage())) + if (SP->isPrototyped() && dwarf::isC(getSourceLanguage())) addFlag(SPDie, dwarf::DW_AT_prototyped); if (SP->isObjCDirect()) @@ -1700,8 +1705,7 @@ DIE *DwarfUnit::getIndexTyDie() { addString(*IndexTyDie, dwarf::DW_AT_name, Name); addUInt(*IndexTyDie, dwarf::DW_AT_byte_size, std::nullopt, sizeof(int64_t)); addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - dwarf::getArrayIndexTypeEncoding( - (dwarf::SourceLanguage)getLanguage())); + dwarf::getArrayIndexTypeEncoding(getSourceLanguage())); DD->addAccelType(*this, CUNode->getNameTableKind(), Name, *IndexTyDie, /*Flags*/ 0); return IndexTyDie; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h index bb00ec3af9782..9288d7edbf156 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DIE.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Target/TargetMachine.h" #include #include @@ -107,7 +108,7 @@ class DwarfUnit : public DIEUnit { return LabelBegin; } MCSymbol *getEndLabel() const { return EndLabel; } - uint16_t getLanguage() const { return CUNode->getSourceLanguage(); } + llvm::dwarf::SourceLanguage getSourceLanguage() const; const DICompileUnit *getCUNode() const { return CUNode; } DwarfDebug &getDwarfDebug() const { return *DD; } @@ -358,6 +359,10 @@ class DwarfUnit : public DIEUnit { } private: + DISourceLanguageName getLanguage() const { + return CUNode->getSourceLanguage(); + } + /// A helper to add a wide integer constant to a DIE using a block /// form. void addIntAsBlock(DIE &Die, dwarf::Attribute Attribute, const APInt &Val); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 245129f3f791f..ae086bcd3902d 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2369,8 +2369,12 @@ static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N, AsmWriterContext &WriterCtx) { Out << "!DICompileUnit("; MDFieldPrinter Printer(Out, WriterCtx); - Printer.printDwarfEnum("language", N->getSourceLanguage(), - dwarf::LanguageString, /* ShouldSkipZero */ false); + + Printer.printDwarfEnum("language", + N->getSourceLanguage().getUnversionedName(), + dwarf::LanguageString, + /* ShouldSkipZero */ false); + Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false); Printer.printString("producer", N->getProducer()); Printer.printBool("isOptimized", N->isOptimized()); diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 1344df9298c80..1ae20a9fca413 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -131,17 +131,13 @@ static DIScope *getNonCompileUnitScope(DIScope *N) { } DICompileUnit *DIBuilder::createCompileUnit( - unsigned Lang, DIFile *File, StringRef Producer, bool isOptimized, - StringRef Flags, unsigned RunTimeVer, StringRef SplitName, + DISourceLanguageName Lang, DIFile *File, StringRef Producer, + bool isOptimized, StringRef Flags, unsigned RunTimeVer, StringRef SplitName, DICompileUnit::DebugEmissionKind Kind, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, DICompileUnit::DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK) { - assert(((Lang <= dwarf::DW_LANG_Metal && Lang >= dwarf::DW_LANG_C89) || - (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && - "Invalid Language tag"); - assert(!CUNode && "Can only make one compile unit per DIBuilder instance"); CUNode = DICompileUnit::getDistinct( VMContext, Lang, File, Producer, isOptimized, Flags, RunTimeVer, diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index f9ded507f8328..9601a8ae33feb 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1078,7 +1078,7 @@ LLVMMetadataRef LLVMDIBuilderCreateCompileUnit( auto File = unwrapDI(FileRef); return wrap(unwrap(Builder)->createCompileUnit( - map_from_llvmDWARFsourcelanguage(Lang), File, + DISourceLanguageName(map_from_llvmDWARFsourcelanguage(Lang)), File, StringRef(Producer, ProducerLen), isOptimized, StringRef(Flags, FlagsLen), RuntimeVer, StringRef(SplitName, SplitNameLen), static_cast(Kind), DWOId, diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 77d044b55f7e0..e30df88e6b56b 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1184,9 +1184,10 @@ DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename, DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops); } DICompileUnit::DICompileUnit(LLVMContext &C, StorageType Storage, - unsigned SourceLanguage, bool IsOptimized, - unsigned RuntimeVersion, unsigned EmissionKind, - uint64_t DWOId, bool SplitDebugInlining, + DISourceLanguageName SourceLanguage, + bool IsOptimized, unsigned RuntimeVersion, + unsigned EmissionKind, uint64_t DWOId, + bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, ArrayRef Ops) : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), @@ -1199,7 +1200,7 @@ DICompileUnit::DICompileUnit(LLVMContext &C, StorageType Storage, } DICompileUnit *DICompileUnit::getImpl( - LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + LLVMContext &Context, DISourceLanguageName SourceLanguage, Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp index 275463ef4c527..318ef0679ba03 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp @@ -112,7 +112,8 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) { FilePaths.emplace_back(); sys::path::append(FilePaths.back(), File->getDirectory(), File->getFilename()); - LLVMSourceLanguages.push_back(CompileUnit->getSourceLanguage()); + LLVMSourceLanguages.push_back( + CompileUnit->getSourceLanguage().getUnversionedName()); } } const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags"); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index 6bb064a53eabd..526420bb2b294 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -441,7 +441,9 @@ void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) { llvm::SmallSet SeenLanguages; for (size_t I = 0, E = Debug->getNumOperands(); I < E; ++I) { const auto *CU = cast(Debug->getOperand(I)); - StringRef Language = dwarf::LanguageString(CU->getSourceLanguage()); + StringRef Language = + dwarf::LanguageString(CU->getSourceLanguage().getUnversionedName()); + Language.consume_front("DW_LANG_"); if (SeenLanguages.insert(Language).second) Languages.emplace_back(Language.str(), ""); diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 0accb225122be..c89af688a69ca 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -689,10 +689,14 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, DISubprogram *DIS = F.getSubprogram(); // If there is no DISubprogram for F, it implies the function is compiled // without debug info. So we also don't generate debug info for the frame. - if (!DIS || !DIS->getUnit() || - !dwarf::isCPlusPlus( - (dwarf::SourceLanguage)DIS->getUnit()->getSourceLanguage()) || - DIS->getUnit()->getEmissionKind() != DICompileUnit::DebugEmissionKind::FullDebug) + + if (!DIS || !DIS->getUnit()) + return; + + if (!dwarf::isCPlusPlus(static_cast( + DIS->getUnit()->getSourceLanguage().getUnversionedName())) || + DIS->getUnit()->getEmissionKind() != + DICompileUnit::DebugEmissionKind::FullDebug) return; assert(Shape.ABI == coro::ABI::Switch && diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index 5a09b7385f2be..2923633f29d7a 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -19,6 +19,7 @@ #include "llvm/Config/llvm-config.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" @@ -162,8 +163,8 @@ bool llvm::applyDebugifyMetadata( unsigned NextLine = 1; unsigned NextVar = 1; auto File = DIB.createFile(M.getName(), "/"); - auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify", - /*isOptimized=*/true, "", 0); + auto CU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C), File, + "debugify", /*isOptimized=*/true, "", 0); // Visit each instruction. for (Function &F : Functions) { diff --git a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp index 3a625b299a96f..ce2a38b785655 100644 --- a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp +++ b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp @@ -100,8 +100,8 @@ class InstrRefLDVTest : public testing::Test { // scope. DIBuilder DIB(*Mod); OurFile = DIB.createFile("xyzzy.c", "/cave"); - OurCU = - DIB.createCompileUnit(dwarf::DW_LANG_C99, OurFile, "nou", false, "", 0); + OurCU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C99), + OurFile, "nou", false, "", 0); auto OurSubT = DIB.createSubroutineType(DIB.getOrCreateTypeArray({})); OurFunc = DIB.createFunction(OurCU, "bees", "", OurFile, 1, OurSubT, 1, diff --git a/llvm/unittests/CodeGen/LexicalScopesTest.cpp b/llvm/unittests/CodeGen/LexicalScopesTest.cpp index 34bd37a4afdc2..0c6b9326bcfd4 100644 --- a/llvm/unittests/CodeGen/LexicalScopesTest.cpp +++ b/llvm/unittests/CodeGen/LexicalScopesTest.cpp @@ -102,8 +102,8 @@ class LexicalScopesTest : public testing::Test { // scope. DIBuilder DIB(Mod); OurFile = DIB.createFile("xyzzy.c", "/cave"); - OurCU = - DIB.createCompileUnit(dwarf::DW_LANG_C99, OurFile, "nou", false, "", 0); + OurCU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C99), + OurFile, "nou", false, "", 0); OurSubT = DIB.createSubroutineType(DIB.getOrCreateTypeArray({})); OurFunc = DIB.createFunction(OurCU, "bees", "", OurFile, 1, OurSubT, 1, diff --git a/llvm/unittests/CodeGen/MachineBasicBlockTest.cpp b/llvm/unittests/CodeGen/MachineBasicBlockTest.cpp index bcb5a18188a8b..ef0d40b8644f9 100644 --- a/llvm/unittests/CodeGen/MachineBasicBlockTest.cpp +++ b/llvm/unittests/CodeGen/MachineBasicBlockTest.cpp @@ -40,8 +40,8 @@ TEST(FindDebugLocTest, DifferentIterators) { // scope. DIBuilder DIB(Mod); DIFile *OurFile = DIB.createFile("foo.c", "/bar"); - DICompileUnit *OurCU = - DIB.createCompileUnit(dwarf::DW_LANG_C99, OurFile, "", false, "", 0); + DICompileUnit *OurCU = DIB.createCompileUnit( + DISourceLanguageName(dwarf::DW_LANG_C99), OurFile, "", false, "", 0); auto OurSubT = DIB.createSubroutineType(DIB.getOrCreateTypeArray({})); DISubprogram *OurFunc = DIB.createFunction(OurCU, "bees", "", OurFile, 1, OurSubT, 1, diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp index c13570dc803b3..e56872320b4ac 100644 --- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp +++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp @@ -11,6 +11,7 @@ #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" @@ -212,8 +213,8 @@ class OpenMPIRBuilderTest : public testing::Test { DIBuilder DIB(*M); auto File = DIB.createFile("test.dbg", "/src", std::nullopt, std::optional("/src/test.dbg")); - auto CU = - DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0); + auto CU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C), + File, "llvm-C", true, "", 0); auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray({})); auto SP = DIB.createFunction( CU, "foo", "", File, 1, Type, 1, DINode::FlagZero, diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp index 03333d5872d2f..9cc1149cf51c1 100644 --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -409,7 +409,8 @@ TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) { DIFile *F = DIB.createFile("main.c", "/"); DICompileUnit *CU = DIB.createCompileUnit( - dwarf::DW_LANG_C, DIB.createFile("main.c", "/"), "llvm-c", true, "", 0); + DISourceLanguageName(dwarf::DW_LANG_C), DIB.createFile("main.c", "/"), + "llvm-c", true, "", 0); DIVariable *DataLocation = DIB.createTempGlobalVariableFwdDecl(CU, "dl", "_dl", F, 1, nullptr, true); @@ -1259,8 +1260,8 @@ TEST(DIBuilder, HashingDISubprogram) { DIBuilder DIB(*M); DIFile *F = DIB.createFile("main.c", "/"); - DICompileUnit *CU = - DIB.createCompileUnit(dwarf::DW_LANG_C, F, "Test", false, "", 0); + DICompileUnit *CU = DIB.createCompileUnit( + DISourceLanguageName(dwarf::DW_LANG_C), F, "Test", false, "", 0); llvm::TempDIType ForwardDeclaredType = llvm::TempDIType(DIB.createReplaceableCompositeType( @@ -1305,8 +1306,8 @@ TEST(DIBuilder, CompositeTypes) { DIBuilder DIB(*M); DIFile *F = DIB.createFile("main.c", "/"); - DICompileUnit *CU = - DIB.createCompileUnit(dwarf::DW_LANG_C, F, "Test", false, "", 0); + DICompileUnit *CU = DIB.createCompileUnit( + DISourceLanguageName(dwarf::DW_LANG_C), F, "Test", false, "", 0); DICompositeType *Class = DIB.createClassType(CU, "MyClass", F, 0, 8, 8, 0, {}, nullptr, {}, 0, diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index 773c32e7d9b43..37826b2dbaecf 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -6,11 +6,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/InstSimplifyFolder.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/Analysis/InstSimplifyFolder.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicsAArch64.h" @@ -859,8 +860,8 @@ TEST_F(IRBuilderTest, createFunction) { IRBuilder<> Builder(BB); DIBuilder DIB(*M); auto File = DIB.createFile("error.swift", "/"); - auto CU = - DIB.createCompileUnit(dwarf::DW_LANG_Swift, File, "swiftc", true, "", 0); + auto CU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_Swift), + File, "swiftc", true, "", 0); auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray({})); auto NoErr = DIB.createFunction( CU, "noerr", "", File, 1, Type, 1, DINode::FlagZero, @@ -893,9 +894,9 @@ TEST_F(IRBuilderTest, DIBuilder) { IRBuilder<> Builder(BB); DIBuilder DIB(*M); auto File = DIB.createFile("F.CBL", "/"); - auto CU = DIB.createCompileUnit(dwarf::DW_LANG_Cobol74, - DIB.createFile("F.CBL", "/"), - "llvm-cobol74", true, "", 0); + auto CU = DIB.createCompileUnit( + DISourceLanguageName(dwarf::DW_LANG_Cobol74), + DIB.createFile("F.CBL", "/"), "llvm-cobol74", true, "", 0); auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray({})); auto SP = DIB.createFunction( CU, "foo", "", File, 1, Type, 1, DINode::FlagZero, @@ -1004,7 +1005,8 @@ TEST_F(IRBuilderTest, createArtificialSubprogram) { IRBuilder<> Builder(BB); DIBuilder DIB(*M); auto File = DIB.createFile("main.c", "/"); - auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "clang", + auto CU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C), File, + "clang", /*isOptimized=*/true, /*Flags=*/"", /*Runtime Version=*/0); auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray({})); @@ -1083,7 +1085,8 @@ TEST_F(IRBuilderTest, appendDebugInfo) { { DIBuilder DIB(*M); auto *File = DIB.createFile("main.c", "/"); - CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "clang", + CU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C), File, + "clang", /*isOptimized=*/true, /*Flags=*/"", /*Runtime Version=*/0); auto *ByteTy = DIB.createBasicType("byte0", 8, dwarf::DW_ATE_signed); @@ -1158,9 +1161,9 @@ TEST_F(IRBuilderTest, DebugLoc) { DIBuilder DIB(*M); auto File = DIB.createFile("tmp.cpp", "/"); - auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C_plus_plus_11, - DIB.createFile("tmp.cpp", "/"), "", true, "", - 0); + auto CU = + DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C_plus_plus_11), + DIB.createFile("tmp.cpp", "/"), "", true, "", 0); auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray({})); auto SP = DIB.createFunction(CU, "foo", "foo", File, 1, SPType, 1, DINode::FlagZero, @@ -1191,9 +1194,8 @@ TEST_F(IRBuilderTest, DIImportedEntity) { IRBuilder<> Builder(BB); DIBuilder DIB(*M); auto F = DIB.createFile("F.CBL", "/"); - auto CU = DIB.createCompileUnit(dwarf::DW_LANG_Cobol74, - F, "llvm-cobol74", - true, "", 0); + auto CU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_Cobol74), + F, "llvm-cobol74", true, "", 0); MDTuple *Elements = MDTuple::getDistinct(Ctx, {}); DIB.createImportedDeclaration(CU, nullptr, F, 1); @@ -1218,8 +1220,9 @@ TEST_F(IRBuilderTest, DIBuilderMacro) { DIBuilder DIB(*M); auto File1 = DIB.createFile("main.c", "/"); auto File2 = DIB.createFile("file.h", "/"); - auto CU = DIB.createCompileUnit( - dwarf::DW_LANG_C, DIB.createFile("main.c", "/"), "llvm-c", true, "", 0); + auto CU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C), + DIB.createFile("main.c", "/"), "llvm-c", true, + "", 0); auto MDef0 = DIB.createMacro(nullptr, 0, dwarf::DW_MACINFO_define, "M0", "V0"); auto TMF1 = DIB.createTempMacroFile(nullptr, 0, File1); diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index 7425703606381..85c79d13ae7ce 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -101,8 +101,8 @@ class MetadataTest : public testing::Test { } DICompileUnit *getUnit() { return DICompileUnit::getDistinct( - Context, 1, getFile(), "clang", false, "-g", 2, "", - DICompileUnit::FullDebug, getTuple(), getTuple(), getTuple(), + Context, DISourceLanguageName(1), getFile(), "clang", false, "-g", 2, + "", DICompileUnit::FullDebug, getTuple(), getTuple(), getTuple(), getTuple(), getTuple(), 0, true, false, DICompileUnit::DebugNameTableKind::Default, false, "/", ""); } @@ -2896,13 +2896,14 @@ TEST_F(DICompileUnitTest, get) { StringRef SysRoot = "/"; StringRef SDK = "MacOSX.sdk"; auto *N = DICompileUnit::getDistinct( - Context, SourceLanguage, File, Producer, IsOptimized, Flags, - RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, - RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, true, - false, DICompileUnit::DebugNameTableKind::Default, false, SysRoot, SDK); + Context, DISourceLanguageName(SourceLanguage), File, Producer, + IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, + DWOId, true, false, DICompileUnit::DebugNameTableKind::Default, false, + SysRoot, SDK); EXPECT_EQ(dwarf::DW_TAG_compile_unit, N->getTag()); - EXPECT_EQ(SourceLanguage, N->getSourceLanguage()); + EXPECT_EQ(SourceLanguage, N->getSourceLanguage().getUnversionedName()); EXPECT_EQ(File, N->getFile()); EXPECT_EQ(Producer, N->getProducer()); EXPECT_EQ(IsOptimized, N->isOptimized()); @@ -2921,7 +2922,7 @@ TEST_F(DICompileUnitTest, get) { TempDICompileUnit Temp = N->clone(); EXPECT_EQ(dwarf::DW_TAG_compile_unit, Temp->getTag()); - EXPECT_EQ(SourceLanguage, Temp->getSourceLanguage()); + EXPECT_EQ(SourceLanguage, Temp->getSourceLanguage().getUnversionedName()); EXPECT_EQ(File, Temp->getFile()); EXPECT_EQ(Producer, Temp->getProducer()); EXPECT_EQ(IsOptimized, Temp->isOptimized()); @@ -2959,10 +2960,10 @@ TEST_F(DICompileUnitTest, replaceArrays) { StringRef SysRoot = "/"; StringRef SDK = "MacOSX.sdk"; auto *N = DICompileUnit::getDistinct( - Context, SourceLanguage, File, Producer, IsOptimized, Flags, - RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, - RetainedTypes, nullptr, ImportedEntities, nullptr, DWOId, true, false, - DICompileUnit::DebugNameTableKind::Default, false, SysRoot, SDK); + Context, DISourceLanguageName(SourceLanguage), File, Producer, + IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, nullptr, ImportedEntities, nullptr, DWOId, true, + false, DICompileUnit::DebugNameTableKind::Default, false, SysRoot, SDK); auto *GlobalVariables = MDTuple::getDistinct(Context, {}); EXPECT_EQ(nullptr, N->getGlobalVariables().get()); diff --git a/llvm/unittests/IR/VerifierTest.cpp b/llvm/unittests/IR/VerifierTest.cpp index 7a136e6a382a7..440db1216edc9 100644 --- a/llvm/unittests/IR/VerifierTest.cpp +++ b/llvm/unittests/IR/VerifierTest.cpp @@ -9,6 +9,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" @@ -232,8 +233,9 @@ TEST(VerifierTest, DetectInvalidDebugInfo) { LLVMContext C; Module M("M", C); DIBuilder DIB(M); - DIB.createCompileUnit(dwarf::DW_LANG_C89, DIB.createFile("broken.c", "/"), - "unittest", false, "", 0); + DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C89), + DIB.createFile("broken.c", "/"), "unittest", false, + "", 0); DIB.finalize(); EXPECT_FALSE(verifyModule(M)); @@ -247,7 +249,7 @@ TEST(VerifierTest, DetectInvalidDebugInfo) { LLVMContext C; Module M("M", C); DIBuilder DIB(M); - auto *CU = DIB.createCompileUnit(dwarf::DW_LANG_C89, + auto *CU = DIB.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C89), DIB.createFile("broken.c", "/"), "unittest", false, "", 0); new GlobalVariable(M, Type::getInt8Ty(C), false, diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp index fe81986aee7b9..d990808d31fe2 100644 --- a/llvm/unittests/Transforms/Utils/CloningTest.cpp +++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" @@ -482,10 +483,10 @@ class CloneFunc : public ::testing::Test { DITypeRefArray ParamTypes = DBuilder.getOrCreateTypeArray({}); DISubroutineType *FuncType = DBuilder.createSubroutineType(ParamTypes); - auto *CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, - DBuilder.createFile("filename.c", - "/file/dir"), - "CloneFunc", false, "", 0); + auto *CU = DBuilder.createCompileUnit( + DISourceLanguageName(dwarf::DW_LANG_C99), + DBuilder.createFile("filename.c", "/file/dir"), "CloneFunc", false, "", + 0); auto *Subprogram = DBuilder.createFunction( CU, "f", "f", File, 4, FuncType, 3, DINode::FlagZero, @@ -540,7 +541,7 @@ class CloneFunc : public ::testing::Test { // Create another, empty, compile unit. DIBuilder DBuilder2(*M); - DBuilder2.createCompileUnit(dwarf::DW_LANG_C99, + DBuilder2.createCompileUnit(DISourceLanguageName(dwarf::DW_LANG_C99), DBuilder.createFile("extra.c", "/file/dir"), "CloneFunc", false, "", 0); DBuilder2.finalize(); @@ -953,8 +954,9 @@ class CloneModule : public ::testing::Test { // confirm that compile units get cloned in the correct order. DIBuilder EmptyBuilder(*OldM); auto *File = EmptyBuilder.createFile("empty.c", "/file/dir/"); - (void)EmptyBuilder.createCompileUnit(dwarf::DW_LANG_C99, File, - "EmptyUnit", false, "", 0); + (void)EmptyBuilder.createCompileUnit( + DISourceLanguageName(dwarf::DW_LANG_C99), File, "EmptyUnit", false, + "", 0); EmptyBuilder.finalize(); } @@ -973,10 +975,10 @@ class CloneModule : public ::testing::Test { auto *File = DBuilder.createFile("filename.c", "/file/dir/"); DITypeRefArray ParamTypes = DBuilder.getOrCreateTypeArray({}); DISubroutineType *DFuncType = DBuilder.createSubroutineType(ParamTypes); - auto *CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, - DBuilder.createFile("filename.c", - "/file/dir"), - "CloneModule", false, "", 0); + auto *CU = DBuilder.createCompileUnit( + DISourceLanguageName(dwarf::DW_LANG_C99), + DBuilder.createFile("filename.c", "/file/dir"), "CloneModule", false, + "", 0); // Function DI auto *Subprogram = DBuilder.createFunction( CU, "f", "f", File, 4, DFuncType, 3, DINode::FlagZero, diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp index 8b0326518770d..4bbcd8e2177f3 100644 --- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp +++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp @@ -59,7 +59,8 @@ DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) { std::underlying_type_t>( node->getNameTableKind())); return DICompileUnitAttr::get( - context, getOrCreateDistinctID(node), node->getSourceLanguage(), + context, getOrCreateDistinctID(node), + node->getSourceLanguage().getUnversionedName(), translate(node->getFile()), getStringAttrOrNull(node->getRawProducer()), node->isOptimized(), emissionKind.value(), nameTableKind.value(), getStringAttrOrNull(node->getRawSplitDebugFilename())); From bd38e497c15e3f66b77f13c0cac9816f9ee8efa4 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 7 Oct 2025 09:51:52 +0100 Subject: [PATCH 2/6] [llvm][DebugInfo] Support for versioned DISourceLanguageName --- llvm/include/llvm/IR/DebugInfoMetadata.h | 4 ++++ llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp | 17 +++++++++----- llvm/lib/AsmParser/LLParser.cpp | 22 ++++++++++++++----- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 16 +++++++++----- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 8 ++++++- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 12 ++++++++-- llvm/lib/IR/AsmWriter.cpp | 14 ++++++++---- .../invalid-dicompileunit-missing-language.ll | 2 +- 8 files changed, 70 insertions(+), 25 deletions(-) diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 80c9ea38016b6..1ab8a4c7e79d5 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -88,6 +88,10 @@ class DISourceLanguageName { /// Returns a versioned or unversioned language name. uint16_t getName() const { return Name; } + uint32_t getVersion() const { + assert(hasVersionedName() && "Tried getting version on unversioned name"); + return *Version; + } // Transitional API for cases where we do not yet support // versioned source language names. Use \ref getName instead. diff --git a/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp b/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp index f31d625eca14c..f7e2914a334cc 100644 --- a/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp +++ b/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp @@ -17,6 +17,7 @@ #include "llvm/Analysis/ModuleDebugInfoPrinter.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include "llvm/Support/ErrorHandling.h" @@ -43,13 +44,17 @@ static void printModuleDebugInfo(raw_ostream &O, const Module *M, // filenames), so just print a few useful things. for (DICompileUnit *CU : Finder.compile_units()) { O << "Compile unit: "; - auto Lang = - dwarf::LanguageString(CU->getSourceLanguage().getUnversionedName()); - if (!Lang.empty()) - O << Lang; + + DISourceLanguageName Lang = CU->getSourceLanguage().getUnversionedName(); + auto LangStr = + Lang.hasVersionedName() + ? dwarf::LanguageString(Lang.getName()) + : dwarf::LanguageDescription( + static_cast(Lang.getName())); + if (!LangStr.empty()) + O << LangStr; else - O << "unknown-language(" << CU->getSourceLanguage().getUnversionedName() - << ")"; + O << "unknown-language(" << CU->getSourceLanguage().getName() << ")"; printFile(O, CU->getFilename(), CU->getDirectory()); O << '\n'; } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 55899660fa84a..0c569f0c3db46 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -5836,9 +5836,12 @@ bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) { if (!IsDistinct) return tokError("missing 'distinct', required for !DICompileUnit"); + LocTy Loc = Lex.getLoc(); + #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(language, DwarfLangField, ); \ REQUIRED(file, MDField, (/* AllowNull */ false)); \ + OPTIONAL(language, DwarfLangField, ); \ + OPTIONAL(sourceLanguageName, MDUnsignedField, ); \ OPTIONAL(producer, MDStringField, ); \ OPTIONAL(isOptimized, MDBoolField, ); \ OPTIONAL(flags, MDStringField, ); \ @@ -5860,12 +5863,19 @@ bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) { PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS + if (!language.Seen && !sourceLanguageName.Seen) + return error(Loc, "missing one of 'language' or 'sourceLanguageName', " + "required for !DICompileUnit"); + Result = DICompileUnit::getDistinct( - Context, DISourceLanguageName(language.Val), file.Val, producer.Val, - isOptimized.Val, flags.Val, runtimeVersion.Val, splitDebugFilename.Val, - emissionKind.Val, enums.Val, retainedTypes.Val, globals.Val, imports.Val, - macros.Val, dwoId.Val, splitDebugInlining.Val, debugInfoForProfiling.Val, - nameTableKind.Val, rangesBaseAddress.Val, sysroot.Val, sdk.Val); + Context, + language.Seen ? DISourceLanguageName(language.Val) + : DISourceLanguageName(sourceLanguageName.Val, 0), + file.Val, producer.Val, isOptimized.Val, flags.Val, runtimeVersion.Val, + splitDebugFilename.Val, emissionKind.Val, enums.Val, retainedTypes.Val, + globals.Val, imports.Val, macros.Val, dwoId.Val, splitDebugInlining.Val, + debugInfoForProfiling.Val, nameTableKind.Val, rangesBaseAddress.Val, + sysroot.Val, sdk.Val); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index a4d1b8372dfac..cdcf7a80ffac7 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1867,12 +1867,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( // distinct. It's always distinct. IsDistinct = true; + const auto LangVersionMask = (uint64_t(1) << 63); + const bool HasVersionedLanguage = Record[1] & LangVersionMask; + auto *CU = DICompileUnit::getDistinct( - Context, DISourceLanguageName(Record[1]), getMDOrNull(Record[2]), - getMDString(Record[3]), Record[4], getMDString(Record[5]), Record[6], - getMDString(Record[7]), Record[8], getMDOrNull(Record[9]), - getMDOrNull(Record[10]), getMDOrNull(Record[12]), - getMDOrNull(Record[13]), + Context, + HasVersionedLanguage + ? DISourceLanguageName(Record[1] & ~LangVersionMask, 0) + : DISourceLanguageName(Record[1]), + getMDOrNull(Record[2]), getMDString(Record[3]), Record[4], + getMDString(Record[5]), Record[6], getMDString(Record[7]), Record[8], + getMDOrNull(Record[9]), getMDOrNull(Record[10]), + getMDOrNull(Record[12]), getMDOrNull(Record[13]), Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]), Record.size() <= 14 ? 0 : Record[14], Record.size() <= 16 ? true : Record[16], diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index bae05dc43a0fd..775481701204b 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2106,7 +2106,13 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N, assert(N->isDistinct() && "Expected distinct compile units"); Record.push_back(/* IsDistinct */ true); - Record.push_back(N->getSourceLanguage().getUnversionedName()); + auto Lang = N->getSourceLanguage(); + Record.push_back(Lang.getName()); + // Set bit so the MetadataLoader can distniguish between versioned and + // unversioned names. + if (Lang.hasVersionedName()) + Record.back() ^= (uint64_t(1) << 63); + Record.push_back(VE.getMetadataOrNullID(N->getFile())); Record.push_back(VE.getMetadataOrNullID(N->getRawProducer())); Record.push_back(N->isOptimized()); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index aa078f3f81d49..8427d361a3461 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -16,6 +16,7 @@ #include "DwarfExpression.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -705,8 +706,15 @@ void DwarfUnit::addType(DIE &Entity, const DIType *Ty, } llvm::dwarf::SourceLanguage DwarfUnit::getSourceLanguage() const { - return static_cast( - getLanguage().getUnversionedName()); + const auto &Lang = getLanguage(); + + if (!Lang.hasVersionedName()) + return static_cast(Lang.getName()); + + return llvm::dwarf::toDW_LANG( + static_cast(Lang.getName()), + Lang.getVersion()) + .value_or(llvm::dwarf::DW_LANG_hi_user); } std::string DwarfUnit::getParentContextString(const DIScope *Context) const { diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index ae086bcd3902d..abfef949ac7ae 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2370,10 +2370,16 @@ static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N, Out << "!DICompileUnit("; MDFieldPrinter Printer(Out, WriterCtx); - Printer.printDwarfEnum("language", - N->getSourceLanguage().getUnversionedName(), - dwarf::LanguageString, - /* ShouldSkipZero */ false); + auto Lang = N->getSourceLanguage(); + if (Lang.hasVersionedName()) + Printer.printDwarfEnum( + "sourceLanguageName", + static_cast(Lang.getName()), + dwarf::LanguageDescription, + /* ShouldSkipZero */ false); + else + Printer.printDwarfEnum("language", Lang.getName(), dwarf::LanguageString, + /* ShouldSkipZero */ false); Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false); Printer.printString("producer", N->getProducer()); diff --git a/llvm/test/Assembler/invalid-dicompileunit-missing-language.ll b/llvm/test/Assembler/invalid-dicompileunit-missing-language.ll index 8e4cb0261dbbf..ebc86e3410d66 100644 --- a/llvm/test/Assembler/invalid-dicompileunit-missing-language.ll +++ b/llvm/test/Assembler/invalid-dicompileunit-missing-language.ll @@ -1,4 +1,4 @@ ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s -; CHECK: :[[@LINE+1]]:74: error: missing required field 'language' +; CHECK: :[[@LINE+1]]:15: error: missing one of 'language' or 'sourceLanguageName', required for !DICompileUnit !0 = distinct !DICompileUnit(file: !DIFile(filename: "a", directory: "b")) From baade17fe83f20b152e123cad730bf9bf363fa23 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 7 Oct 2025 11:07:52 +0100 Subject: [PATCH 3/6] [clang][Driver] Basic -gdwarf-6 support --- clang/include/clang/Driver/Options.td | 4 ++++ clang/lib/Driver/ToolChains/CommonArgs.cpp | 5 +++-- llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h | 2 +- llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp | 2 +- llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 2 +- .../X86/debug_addr_unsupported_version.s | 12 +----------- .../llvm-dwarfdump/X86/verify_unit_header_chain.s | 2 +- .../llvm-dwp/X86/cu_tu_units_manual_v5_invalid.s | 10 +++++----- .../llvm-symbolizer/split-dwarf-dwp-invalid.test | 4 ++-- 9 files changed, 19 insertions(+), 24 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 9bfa1dd52effe..22cdc50d0608f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4715,6 +4715,10 @@ def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group, HelpText<"Generate source-level debug information with dwarf version 4">; def gdwarf_5 : Flag<["-"], "gdwarf-5">, Group, HelpText<"Generate source-level debug information with dwarf version 5">; +def gdwarf_6 + : Flag<["-"], "gdwarf-6">, + Group, + HelpText<"Generate source-level debug information with dwarf version 6">; } def gdwarf64 : Flag<["-"], "gdwarf64">, Group, Visibility<[ClangOption, CC1Option, CC1AsOption]>, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 49ee53f0ba3bf..16cc1db0a2235 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2231,7 +2231,7 @@ static unsigned ParseDebugDefaultVersion(const ToolChain &TC, return 0; unsigned Value = 0; - if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 5 || + if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 6 || Value < 2) TC.getDriver().Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << A->getValue(); @@ -2244,13 +2244,14 @@ unsigned tools::DwarfVersionNum(StringRef ArgValue) { .Case("-gdwarf-3", 3) .Case("-gdwarf-4", 4) .Case("-gdwarf-5", 5) + .Case("-gdwarf-6", 6) .Default(0); } const Arg *tools::getDwarfNArg(const ArgList &Args) { return Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3, options::OPT_gdwarf_4, options::OPT_gdwarf_5, - options::OPT_gdwarf); + options::OPT_gdwarf_6, options::OPT_gdwarf); } unsigned tools::getDwarfVersion(const ToolChain &TC, diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h index d0187e885a518..b4844343e8293 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -402,7 +402,7 @@ class LLVM_ABI DWARFContext : public DIContext { getLocalsForAddress(object::SectionedAddress Address) override; bool isLittleEndian() const { return DObj->isLittleEndian(); } - static unsigned getMaxSupportedVersion() { return 5; } + static unsigned getMaxSupportedVersion() { return 6; } static bool isSupportedVersion(unsigned version) { return version >= 2 && version <= getMaxSupportedVersion(); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp index 98eaf1a095d9f..064667582b1d5 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp @@ -80,7 +80,7 @@ Error DWARFDebugAddrTable::extractV5(const DWARFDataExtractor &Data, SegSize = Data.getU8(OffsetPtr); // Perform a basic validation of the header fields. - if (Version != 5) + if (Version < 5) return createStringError(errc::not_supported, "address table at offset 0x%" PRIx64 " has unsupported version %" PRIu16, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 08b58669b3eb3..4581b5fcd7479 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -42,7 +42,7 @@ using ContentDescriptors = SmallVector; } // end anonymous namespace static bool versionIsSupported(uint16_t Version) { - return Version >= 2 && Version <= 5; + return Version >= 2 && Version <= 6; } void DWARFDebugLine::ContentTypeTracker::trackContentType( diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s index 7398182fd8917..982eaaf675baf 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s @@ -2,8 +2,7 @@ # RUN: not llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s # RUN: FileCheck %s -input-file %t.err -check-prefix=ERR -# ERR: address table at offset 0x0 has unsupported version 6 -# ERR: address table at offset 0x20 has unsupported version 4 +# ERR: address table at offset 0x10 has unsupported version 4 # ERR-NOT: {{.}} # CHECK: .debug_addr contents @@ -24,15 +23,6 @@ .byte 4 # Address Size (in bytes) .long .debug_abbrev # Offset Into Abbrev. Section - .section .debug_addr,"",@progbits -.Ldebug_addr0: - .long 12 # unit_length = .short + .byte + .byte + .long + .long - .short 6 # version - .byte 4 # address_size - .byte 0 # segment_selector_size - .long 0x00000000 - .long 0x00000001 - .section .debug_addr,"",@progbits .Ldebug_addr1: .long 12 # unit_length = .short + .byte + .byte + .long + .long diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s b/llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s index 5921f75643273..c439a66afcd95 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s @@ -53,7 +53,7 @@ Ltu_begin0: .byte 0 Lcu_begin1: .long 10 ## Length of Unit - .short 6 ## DWARF version number -- Error: The 16 bit unit header version is not valid. + .short 7 ## DWARF version number -- Error: The 16 bit unit header version is not valid. .byte 1 ## DWARF Unit Type .byte 4 ## Address Size (in bytes) -- The offset into the .debug_abbrev section is not valid. .long Lline_table_start0 diff --git a/llvm/test/tools/llvm-dwp/X86/cu_tu_units_manual_v5_invalid.s b/llvm/test/tools/llvm-dwp/X86/cu_tu_units_manual_v5_invalid.s index b13177435d04d..8947472fdd80f 100644 --- a/llvm/test/tools/llvm-dwp/X86/cu_tu_units_manual_v5_invalid.s +++ b/llvm/test/tools/llvm-dwp/X86/cu_tu_units_manual_v5_invalid.s @@ -13,15 +13,15 @@ # CHECK-NOT: .debug_info.dwo contents: # CHECK-DAG: .debug_cu_index contents: -# CHECK: warning: Failed to parse CU header in DWP file: DWARF unit at offset 0x00000000 has unsupported version 6, supported are 2-5 +# CHECK: warning: Failed to parse CU header in DWP file: DWARF unit at offset 0x00000000 has unsupported version 7, supported are 2-6 # CHECK-DAG: .debug_tu_index contents: -# CHECK: warning: Failed to parse CU header in DWP file: DWARF unit at offset 0x00000000 has unsupported version 6, supported are 2-5 +# CHECK: warning: Failed to parse CU header in DWP file: DWARF unit at offset 0x00000000 has unsupported version 7, supported are 2-6 .section .debug_info.dwo,"e",@progbits .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit .Ldebug_info_dwo_start0: - .short 6 # DWARF version number + .short 7 # DWARF version number .byte 6 # DWARF Unit Type (DW_UT_split_type) .byte 8 # Address Size (in bytes) .long 0 # Offset Into Abbrev. Section @@ -34,7 +34,7 @@ .section .debug_info.dwo,"e",@progbits .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit .Ldebug_info_dwo_start1: - .short 6 # DWARF version number + .short 7 # DWARF version number .byte 6 # DWARF Unit Type (DW_UT_split_type) .byte 8 # Address Size (in bytes) .long 0 # Offset Into Abbrev. Section @@ -47,7 +47,7 @@ .section .debug_info.dwo,"e",@progbits .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit .Ldebug_info_dwo_start2: - .short 6 # DWARF version number + .short 7 # DWARF version number .byte 5 # DWARF Unit Type (DW_UT_split_compile) .byte 8 # Address Size (in bytes) .long 0 # Offset Into Abbrev. Section diff --git a/llvm/test/tools/llvm-symbolizer/split-dwarf-dwp-invalid.test b/llvm/test/tools/llvm-symbolizer/split-dwarf-dwp-invalid.test index 46b244b1315a5..62f86de5621fa 100644 --- a/llvm/test/tools/llvm-symbolizer/split-dwarf-dwp-invalid.test +++ b/llvm/test/tools/llvm-symbolizer/split-dwarf-dwp-invalid.test @@ -20,8 +20,8 @@ that skips the null entries, keeping those only as an implementation detail?) - or perhaps just have a separate list of offsets that have failed to parse previously? -CHECK: warning: DWARF unit at offset 0x00000000 has unsupported version 255, supported are 2-5 -CHECK: warning: DWARF unit at offset 0x00000000 has unsupported version 255, supported are 2-5 +CHECK: warning: DWARF unit at offset 0x00000000 has unsupported version 255, supported are 2-6 +CHECK: warning: DWARF unit at offset 0x00000000 has unsupported version 255, supported are 2-6 CHECK: other() CHECK: /usr/local/google/home/blaikie/dev/scratch{{[/\\]}}other.cpp:1:16 From f273e494b8b33851631c91198b3559ac86703674 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 7 Oct 2025 09:52:19 +0100 Subject: [PATCH 4/6] [clang][DebugInfo] Emit DW_AT_language_name for DWARFv6 --- clang/lib/CodeGen/CGDebugInfo.cpp | 102 +++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 30 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index b91cb36483d72..a4f418f4f2858 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -41,8 +41,10 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" @@ -647,6 +649,45 @@ StringRef CGDebugInfo::getCurrentDirname() { return CGM.getCodeGenOpts().DebugCompilationDir; } +static llvm::DISourceLanguageName +GetDISourceLanguageName(const CodeGenModule &CGM) { + const CodeGenOptions &CGO = CGM.getCodeGenOpts(); + const LangOptions &LO = CGM.getLangOpts(); + + llvm::dwarf::SourceLanguage LangTag; + if (LO.CPlusPlus) { + if (LO.ObjC) + LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; + else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5) + LangTag = llvm::dwarf::DW_LANG_C_plus_plus; + else if (LO.CPlusPlus14) + LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14; + else if (LO.CPlusPlus11) + LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11; + else + LangTag = llvm::dwarf::DW_LANG_C_plus_plus; + } else if (LO.ObjC) { + LangTag = llvm::dwarf::DW_LANG_ObjC; + } else if (LO.OpenCL && (!CGO.DebugStrictDwarf || CGO.DwarfVersion >= 5)) { + LangTag = llvm::dwarf::DW_LANG_OpenCL; + } else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) { + LangTag = llvm::dwarf::DW_LANG_C11; + } else if (LO.C99) { + LangTag = llvm::dwarf::DW_LANG_C99; + } else { + LangTag = llvm::dwarf::DW_LANG_C89; + } + + // FIXME: for some languages that don't have a DW_LNAME_* we would fall back + // to emitting a DW_LANG_. Which is technically obsolete starting with + // DWARFv6. + if (CGO.DwarfVersion >= 6) + if (auto LName = llvm::dwarf::toDW_LNAME(LangTag)) + return llvm::DISourceLanguageName(LName->first, LName->second); + + return llvm::DISourceLanguageName(LangTag); +} + void CGDebugInfo::CreateCompileUnit() { SmallString<64> Checksum; std::optional CSKind; @@ -702,31 +743,6 @@ void CGDebugInfo::CreateCompileUnit() { } } - llvm::dwarf::SourceLanguage LangTag; - if (LO.CPlusPlus) { - if (LO.ObjC) - LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; - else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5) - LangTag = llvm::dwarf::DW_LANG_C_plus_plus; - else if (LO.CPlusPlus14) - LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14; - else if (LO.CPlusPlus11) - LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11; - else - LangTag = llvm::dwarf::DW_LANG_C_plus_plus; - } else if (LO.ObjC) { - LangTag = llvm::dwarf::DW_LANG_ObjC; - } else if (LO.OpenCL && (!CGM.getCodeGenOpts().DebugStrictDwarf || - CGM.getCodeGenOpts().DwarfVersion >= 5)) { - LangTag = llvm::dwarf::DW_LANG_OpenCL; - } else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) { - LangTag = llvm::dwarf::DW_LANG_C11; - } else if (LO.C99) { - LangTag = llvm::dwarf::DW_LANG_C99; - } else { - LangTag = llvm::dwarf::DW_LANG_C89; - } - std::string Producer = getClangFullVersion(); // Figure out which version of the ObjC runtime we have. @@ -787,7 +803,7 @@ void CGDebugInfo::CreateCompileUnit() { // Create new compile unit. TheCU = DBuilder.createCompileUnit( - llvm::DISourceLanguageName(LangTag), CUFile, + GetDISourceLanguageName(CGM), CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "", CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, @@ -1231,20 +1247,46 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty, Ty->getPointeeType(), Unit); } -/// \return whether a C++ mangling exists for the type defined by TD. -static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) { - switch (TheCU->getSourceLanguage().getUnversionedName()) { +static bool hasCXXMangling(llvm::dwarf::SourceLanguage Lang, bool IsTagDecl) { + switch (Lang) { case llvm::dwarf::DW_LANG_C_plus_plus: case llvm::dwarf::DW_LANG_C_plus_plus_11: case llvm::dwarf::DW_LANG_C_plus_plus_14: return true; case llvm::dwarf::DW_LANG_ObjC_plus_plus: - return isa(TD) || isa(TD); + return IsTagDecl; default: return false; } } +static bool hasCXXMangling(llvm::dwarf::SourceLanguageName Lang, + bool IsTagDecl) { + switch (Lang) { + case llvm::dwarf::DW_LNAME_C_plus_plus: + return true; + case llvm::dwarf::DW_LNAME_ObjC_plus_plus: + return IsTagDecl; + default: + return false; + } +} + +/// \return whether a C++ mangling exists for the type defined by TD. +static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) { + const bool IsTagDecl = isa(TD) || isa(TD); + + if (llvm::DISourceLanguageName SourceLang = TheCU->getSourceLanguage(); + SourceLang.hasVersionedName()) + return hasCXXMangling( + static_cast(SourceLang.getName()), + IsTagDecl); + else + return hasCXXMangling( + static_cast(SourceLang.getName()), + IsTagDecl); +} + // Determines if the debug info for this tag declaration needs a type // identifier. The purpose of the unique identifier is to deduplicate type // information for identical types across TUs. Because of the C++ one definition From 774e1e04f615f3b8402c96111871111572416658 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 7 Oct 2025 10:03:45 +0100 Subject: [PATCH 5/6] [llvm][DebugInfo] Emit DW_AT_lanugage_name --- llvm/include/llvm/BinaryFormat/Dwarf.def | 2 ++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index 2c9a3c0f6fb04..5977569a19f5c 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -424,6 +424,8 @@ HANDLE_DW_AT(0x89, export_symbols, 5, DWARF) HANDLE_DW_AT(0x8a, deleted, 5, DWARF) HANDLE_DW_AT(0x8b, defaulted, 5, DWARF) HANDLE_DW_AT(0x8c, loclists_base, 5, DWARF) +// New in Dwarf v6: +HANDLE_DW_AT(0x90, language_name, 6, DWARF) // Vendor extensions: HANDLE_DW_AT(0x806, GHS_namespace_alias, 0, GHS) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index d751a7f9f01ef..433877f3a8b98 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1039,8 +1039,12 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, } else NewCU.addString(Die, dwarf::DW_AT_producer, Producer); - NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - DIUnit->getSourceLanguage().getUnversionedName()); + if (auto Lang = DIUnit->getSourceLanguage(); Lang.hasVersionedName()) + NewCU.addUInt(Die, dwarf::DW_AT_language_name, dwarf::DW_FORM_data2, + Lang.getName()); + else + NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + Lang.getName()); NewCU.addString(Die, dwarf::DW_AT_name, FN); StringRef SysRoot = DIUnit->getSysRoot(); From c9f369e1b5f08f2da7ca05d10bd96e07e8ac096e Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 7 Oct 2025 11:44:31 +0100 Subject: [PATCH 6/6] [llvm][dwarfdump] Print DW_AT_language_name as string --- llvm/lib/BinaryFormat/Dwarf.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp index 8b24044e19e50..00d9e6f6da306 100644 --- a/llvm/lib/BinaryFormat/Dwarf.cpp +++ b/llvm/lib/BinaryFormat/Dwarf.cpp @@ -740,6 +740,9 @@ StringRef llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) { return VirtualityString(Val); case DW_AT_language: return LanguageString(Val); + case DW_AT_language_name: + return LanguageDescription( + static_cast(Val)); case DW_AT_encoding: return AttributeEncodingString(Val); case DW_AT_decimal_sign: