https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/162445
>From 7fe58f8007537445a7cb2922bfbe35781c26ff5a Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 6 Oct 2025 18:40:10 +0100 Subject: [PATCH 1/6] [llvm][DebugInfo] Abstract DICompileUnit::SourceLanguage to allow alternate DWARF SourceLanguage encoding --- 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 | 2 +- 29 files changed, 199 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<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage()); + auto RuntimeLang = static_cast<llvm::dwarf::SourceLanguage>( + 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<uint32_t> 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<bool> 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<Metadata *> 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<Metadata *> 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<DICompileUnit>(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<llvm::dwarf::SourceLanguage>( + 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 <optional> #include <string> @@ -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<DIFile>(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<DICompileUnit::DebugEmissionKind>(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<Metadata *> 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<StringRef, 4> SeenLanguages; for (size_t I = 0, E = Debug->getNumOperands(); I < E; ++I) { const auto *CU = cast<DICompileUnit>(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<llvm::dwarf::SourceLanguage>( + 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<StringRef>("/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..4d115f0d1c6f5 100644 --- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp +++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp @@ -59,7 +59,7 @@ DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) { std::underlying_type_t<llvm::DICompileUnit::DebugNameTableKind>>( 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 c20fdc32ced5db8520b50de9d75e6e4866076d3e Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 7 Oct 2025 14:36:40 +0100 Subject: [PATCH 2/6] fixup! clang-format --- mlir/lib/Target/LLVMIR/DebugImporter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp index 4d115f0d1c6f5..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<llvm::DICompileUnit::DebugNameTableKind>>( node->getNameTableKind())); return DICompileUnitAttr::get( - context, getOrCreateDistinctID(node), node->getSourceLanguage().getUnversionedName(), + context, getOrCreateDistinctID(node), + node->getSourceLanguage().getUnversionedName(), translate(node->getFile()), getStringAttrOrNull(node->getRawProducer()), node->isOptimized(), emissionKind.value(), nameTableKind.value(), getStringAttrOrNull(node->getRawSplitDebugFilename())); >From fa22b4033c272822c851a4dec02f7a79382d2dcc Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 7 Oct 2025 18:47:30 +0100 Subject: [PATCH 3/6] fixup! doxygen comment; make structure more compact --- llvm/include/llvm/IR/DebugInfoMetadata.h | 29 ++++++++++++++---------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 80c9ea38016b6..251936687a69a 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -73,35 +73,40 @@ enum Tag : uint16_t; /// DISourceLanguageName may hold either of these. /// class DISourceLanguageName { + /// Language version. The version scheme is language + /// dependent. + uint32_t Version = 0; + /// Language name. - /// If \ref Version is not std::nullopt, then this name + /// If \ref HasVersion is \c true, 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<uint32_t> Version; + /// If \c true, then \ref Version is interpretable and \ref Name + /// is a version independent name. + bool HasVersion; public: - bool hasVersionedName() const { return Version.has_value(); } + bool hasVersionedName() const { return HasVersion; } /// 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. + /// 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) {}; + : Version(Version), Name(Lang), HasVersion(true) {}; + DISourceLanguageName(uint16_t Lang) + : Version(0), Name(Lang), HasVersion(false) {}; }; class DbgVariableRecord; >From 769c4bf18f0e34d6f647ae04da70436c3846459e Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 7 Oct 2025 18:49:06 +0100 Subject: [PATCH 4/6] fixup! add getVersion --- llvm/include/llvm/IR/DebugInfoMetadata.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 251936687a69a..d9d3340aebe9b 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -103,6 +103,12 @@ class DISourceLanguageName { return Name; } + /// Returns language version. Only valid for versioned language names. + uint32_t getVersion() const { + assert(hasVersionedName()); + return Version; + } + DISourceLanguageName(uint16_t Lang, uint32_t Version) : Version(Version), Name(Lang), HasVersion(true) {}; DISourceLanguageName(uint16_t Lang) >From a52934e3370f369146ba91366ec9ede2ac951333 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Wed, 8 Oct 2025 08:34:55 +0100 Subject: [PATCH 5/6] [llvm][Dwarf] Add DW_LNAME_ string/enum getters These are going to be used in a follow-up patch. And they are generally useful for consumers (we have these for most other attributes). (cherry picked from commit ddb4a2d3c6ac1909fd9fc93fbc3a706bd1af7833) --- llvm/include/llvm/BinaryFormat/Dwarf.h | 2 ++ llvm/lib/BinaryFormat/Dwarf.cpp | 20 +++++++++++++ llvm/unittests/BinaryFormat/DwarfTest.cpp | 35 +++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h index 2c5012510a5c3..ba74ab9515a75 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -997,6 +997,7 @@ LLVM_ABI StringRef VisibilityString(unsigned Visibility); LLVM_ABI StringRef VirtualityString(unsigned Virtuality); LLVM_ABI StringRef EnumKindString(unsigned EnumKind); LLVM_ABI StringRef LanguageString(unsigned Language); +LLVM_ABI StringRef SourceLanguageNameString(SourceLanguageName Lang); LLVM_ABI StringRef CaseString(unsigned Case); LLVM_ABI StringRef ConventionString(unsigned Convention); LLVM_ABI StringRef InlineCodeString(unsigned Code); @@ -1038,6 +1039,7 @@ LLVM_ABI unsigned getSubOperationEncoding(unsigned OpEncoding, LLVM_ABI unsigned getVirtuality(StringRef VirtualityString); LLVM_ABI unsigned getEnumKind(StringRef EnumKindString); LLVM_ABI unsigned getLanguage(StringRef LanguageString); +LLVM_ABI unsigned getSourceLanguageName(StringRef SourceLanguageNameString); LLVM_ABI unsigned getCallingConvention(StringRef LanguageString); LLVM_ABI unsigned getAttributeEncoding(StringRef EncodingString); LLVM_ABI unsigned getMacinfo(StringRef MacinfoString); diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp index 8b24044e19e50..9690ff9107df8 100644 --- a/llvm/lib/BinaryFormat/Dwarf.cpp +++ b/llvm/lib/BinaryFormat/Dwarf.cpp @@ -472,6 +472,26 @@ StringRef llvm::dwarf::LanguageDescription(dwarf::SourceLanguageName lname) { return "Unknown"; } +llvm::StringRef llvm::dwarf::SourceLanguageNameString(SourceLanguageName Lang) { + switch (Lang) { +#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \ + case DW_LNAME_##NAME: \ + return "DW_LNAME_" #NAME; +#include "llvm/BinaryFormat/Dwarf.def" + } + + return {}; +} + +unsigned +llvm::dwarf::getSourceLanguageName(StringRef SourceLanguageNameString) { + return StringSwitch<unsigned>(SourceLanguageNameString) +#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \ + .Case("DW_LNAME_" #NAME, DW_LNAME_##NAME) +#include "llvm/BinaryFormat/Dwarf.def" + .Default(0); +} + StringRef llvm::dwarf::CaseString(unsigned Case) { switch (Case) { case DW_ID_case_sensitive: diff --git a/llvm/unittests/BinaryFormat/DwarfTest.cpp b/llvm/unittests/BinaryFormat/DwarfTest.cpp index 684e59fa2785c..1162eb709aa83 100644 --- a/llvm/unittests/BinaryFormat/DwarfTest.cpp +++ b/llvm/unittests/BinaryFormat/DwarfTest.cpp @@ -219,4 +219,39 @@ TEST(DwarfTest, lname) { EXPECT_EQ(roundtrip(DW_LANG_##NAME), DW_LANG_##NAME); #include "llvm/BinaryFormat/Dwarf.def" } + +TEST(DwarfTest, lname_getSourceLanguageName) { + // Some basics. + EXPECT_EQ(getSourceLanguageName("DW_LNAME_Ada"), DW_LNAME_Ada); + EXPECT_EQ(getSourceLanguageName("DW_LNAME_Metal"), DW_LNAME_Metal); + + // Test invalid input. + EXPECT_EQ(getSourceLanguageName(""), 0U); + EXPECT_EQ(getSourceLanguageName("blah"), 0U); + EXPECT_EQ(getSourceLanguageName("DW_LNAME__something_unlikely"), 0U); + EXPECT_EQ(getSourceLanguageName("DW_LANG_C"), 0U); + + // Test that we cover all DW_LNAME_ names. +#define xstr(X) #X +#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \ + EXPECT_EQ(getSourceLanguageName(xstr(DW_LNAME_##NAME)), DW_LNAME_##NAME); +#include "llvm/BinaryFormat/Dwarf.def" +} + +TEST(DwarfTest, lname_SourceLanguageNameString) { + // Some basics. + EXPECT_EQ(SourceLanguageNameString(DW_LNAME_C_plus_plus), + "DW_LNAME_C_plus_plus"); + EXPECT_EQ(SourceLanguageNameString(DW_LNAME_CPP_for_OpenCL), + "DW_LNAME_CPP_for_OpenCL"); + + // Test invalid input. + EXPECT_EQ(SourceLanguageNameString(static_cast<SourceLanguageName>(0)), ""); + + // Test that we cover all DW_LNAME_ names. +#define xstr(X) #X +#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \ + EXPECT_EQ(SourceLanguageNameString(DW_LNAME_##NAME), xstr(DW_LNAME_##NAME)); +#include "llvm/BinaryFormat/Dwarf.def" +} } // end namespace >From 7affded0804bce810d0fc5deba8b9b5cf765a611 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 7 Oct 2025 09:51:52 +0100 Subject: [PATCH 6/6] [llvm][DebugInfo] Support for versioned DISourceLanguageName --- llvm/include/llvm/AsmParser/LLToken.h | 43 ++++++++-------- llvm/lib/AsmParser/LLLexer.cpp | 1 + llvm/lib/AsmParser/LLParser.cpp | 49 ++++++++++++++++--- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 16 ++++-- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 8 ++- llvm/lib/IR/AsmWriter.cpp | 14 ++++-- ...compileunit-conflicting-language-fields.ll | 4 ++ .../dicompileunit-invalid-language.ll | 22 +++++++++ .../invalid-dicompileunit-missing-language.ll | 2 +- .../Bitcode/dwarf-source-language-name.ll | 15 ++++++ 10 files changed, 136 insertions(+), 38 deletions(-) create mode 100644 llvm/test/Assembler/dicompileunit-conflicting-language-fields.ll create mode 100644 llvm/test/Assembler/dicompileunit-invalid-language.ll create mode 100644 llvm/test/Bitcode/dwarf-source-language-name.ll diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index d976d40e5e956..6de99fe182ad9 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -488,27 +488,28 @@ enum Kind { SummaryID, // ^42 // String valued tokens (StrVal). - LabelStr, // foo: - GlobalVar, // @foo @"foo" - ComdatVar, // $foo - LocalVar, // %foo %"foo" - MetadataVar, // !foo - StringConstant, // "foo" - DwarfTag, // DW_TAG_foo - DwarfAttEncoding, // DW_ATE_foo - DwarfVirtuality, // DW_VIRTUALITY_foo - DwarfLang, // DW_LANG_foo - DwarfCC, // DW_CC_foo - EmissionKind, // lineTablesOnly - NameTableKind, // GNU - FixedPointKind, // Fixed point - DwarfOp, // DW_OP_foo - DIFlag, // DIFlagFoo - DISPFlag, // DISPFlagFoo - DwarfMacinfo, // DW_MACINFO_foo - ChecksumKind, // CSK_foo - DbgRecordType, // dbg_foo - DwarfEnumKind, // DW_APPLE_ENUM_KIND_foo + LabelStr, // foo: + GlobalVar, // @foo @"foo" + ComdatVar, // $foo + LocalVar, // %foo %"foo" + MetadataVar, // !foo + StringConstant, // "foo" + DwarfTag, // DW_TAG_foo + DwarfAttEncoding, // DW_ATE_foo + DwarfVirtuality, // DW_VIRTUALITY_foo + DwarfLang, // DW_LANG_foo + DwarfSourceLangName, // DW_LNAME_foo + DwarfCC, // DW_CC_foo + EmissionKind, // lineTablesOnly + NameTableKind, // GNU + FixedPointKind, // Fixed point + DwarfOp, // DW_OP_foo + DIFlag, // DIFlagFoo + DISPFlag, // DISPFlagFoo + DwarfMacinfo, // DW_MACINFO_foo + ChecksumKind, // CSK_foo + DbgRecordType, // dbg_foo + DwarfEnumKind, // DW_APPLE_ENUM_KIND_foo // Type valued tokens (TyVal). Type, diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index f6937d38eb38c..50d1d4730007a 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -982,6 +982,7 @@ lltok::Kind LLLexer::LexIdentifier() { DWKEYWORD(ATE, DwarfAttEncoding); DWKEYWORD(VIRTUALITY, DwarfVirtuality); DWKEYWORD(LANG, DwarfLang); + DWKEYWORD(LNAME, DwarfSourceLangName); DWKEYWORD(CC, DwarfCC); DWKEYWORD(OP, DwarfOp); DWKEYWORD(MACINFO, DwarfMacinfo); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 55899660fa84a..380b19296a3c4 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4740,6 +4740,10 @@ struct DwarfLangField : public MDUnsignedField { DwarfLangField() : MDUnsignedField(0, dwarf::DW_LANG_hi_user) {} }; +struct DwarfSourceLangNameField : public MDUnsignedField { + DwarfSourceLangNameField() : MDUnsignedField(0, UINT32_MAX) {} +}; + struct DwarfCCField : public MDUnsignedField { DwarfCCField() : MDUnsignedField(0, dwarf::DW_CC_hi_user) {} }; @@ -4997,6 +5001,25 @@ bool LLParser::parseMDField(LocTy Loc, StringRef Name, DwarfLangField &Result) { return false; } +template <> +bool LLParser::parseMDField(LocTy Loc, StringRef Name, + DwarfSourceLangNameField &Result) { + if (Lex.getKind() == lltok::APSInt) + return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); + + if (Lex.getKind() != lltok::DwarfSourceLangName) + return tokError("expected DWARF source language name"); + + unsigned Lang = dwarf::getSourceLanguageName(Lex.getStrVal()); + if (!Lang) + return tokError("invalid DWARF source language name" + Twine(" '") + + Lex.getStrVal() + "'"); + assert(Lang <= Result.Max && "Expected valid DWARF source language name"); + Result.assign(Lang); + Lex.Lex(); + return false; +} + template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, DwarfCCField &Result) { if (Lex.getKind() == lltok::APSInt) @@ -5836,9 +5859,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, DwarfSourceLangNameField, ); \ OPTIONAL(producer, MDStringField, ); \ OPTIONAL(isOptimized, MDBoolField, ); \ OPTIONAL(flags, MDStringField, ); \ @@ -5860,12 +5886,23 @@ 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"); + + if (language.Seen && sourceLanguageName.Seen) + return error(Loc, "can only specify one of 'language' and " + "'sourceLanguageName' on !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/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index ae086bcd3902d..0bc877d1c4471 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<llvm::dwarf::SourceLanguageName>(Lang.getName()), + dwarf::SourceLanguageNameString, + /* 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/dicompileunit-conflicting-language-fields.ll b/llvm/test/Assembler/dicompileunit-conflicting-language-fields.ll new file mode 100644 index 0000000000000..3aad27ba8a87a --- /dev/null +++ b/llvm/test/Assembler/dicompileunit-conflicting-language-fields.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: <stdin>:[[@LINE+1]]:15: error: can only specify one of 'language' and 'sourceLanguageName' on !DICompileUnit +!0 = distinct !DICompileUnit(language: DW_LANG_C, sourceLanguageName: DW_LNAME_C, file: !DIFile(filename: "a", directory: "b")) diff --git a/llvm/test/Assembler/dicompileunit-invalid-language.ll b/llvm/test/Assembler/dicompileunit-invalid-language.ll new file mode 100644 index 0000000000000..da93c4f20e333 --- /dev/null +++ b/llvm/test/Assembler/dicompileunit-invalid-language.ll @@ -0,0 +1,22 @@ +; RUN: split-file %s %t +; RUN: not llvm-as < %t/invalid_dw_lang.ll -disable-output 2>&1 | FileCheck %s --check-prefix=INVALID_DW_LANG +; RUN: not llvm-as < %t/invalid_dw_lang_2.ll -disable-output 2>&1 | FileCheck %s --check-prefix=INVALID_DW_LANG_2 +; RUN: not llvm-as < %t/invalid_dw_lname.ll -disable-output 2>&1 | FileCheck %s --check-prefix=INVALID_DW_LNAME +; RUN: not llvm-as < %t/invalid_dw_lname_2.ll -disable-output 2>&1 | FileCheck %s --check-prefix=INVALID_DW_LNAME_2 + +; INVALID_DW_LANG: invalid DWARF language 'DW_LANG_blah' +; INVALID_DW_LANG_2: expected DWARF language +; INVALID_DW_LNAME: invalid DWARF source language name 'DW_LNAME_blah' +; INVALID_DW_LNAME_2: expected DWARF source language name + +;--- invalid_dw_lang.ll +!0 = distinct !DICompileUnit(language: DW_LANG_blah) + +;--- invalid_dw_lang_2.ll +!0 = distinct !DICompileUnit(language: DW_LNAME_C) + +;--- invalid_dw_lname.ll +!0 = distinct !DICompileUnit(sourceLanguageName: DW_LNAME_blah) + +;--- invalid_dw_lname_2.ll +!0 = distinct !DICompileUnit(sourceLanguageName: DW_LANG_C) 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: <stdin>:[[@LINE+1]]:74: error: missing required field 'language' +; CHECK: <stdin>:[[@LINE+1]]:15: error: missing one of 'language' or 'sourceLanguageName', required for !DICompileUnit !0 = distinct !DICompileUnit(file: !DIFile(filename: "a", directory: "b")) diff --git a/llvm/test/Bitcode/dwarf-source-language-name.ll b/llvm/test/Bitcode/dwarf-source-language-name.ll new file mode 100644 index 0000000000000..e9893638f61b5 --- /dev/null +++ b/llvm/test/Bitcode/dwarf-source-language-name.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s + +; CHECK: sourceLanguageName: DW_LNAME_ObjC_plus_plus + +source_filename = "cu.cpp" +target triple = "arm64-apple-macosx" + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(sourceLanguageName: DW_LNAME_ObjC_plus_plus, file: !1, producer: "handwritten", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/") +!1 = !DIFile(filename: "cu.cpp", directory: "/tmp") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
