[clang] [llvm] DRAFT: Support for DWARFv6 DW_AT_language_name (PR #162261)
Michael Buch via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 7 03:50:28 PDT 2025
https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/162261
Depends on https://github.com/llvm/llvm-project/pull/162255
Adds support for DWARFv6 `DW_AT_language_name`. In DWARFv5 we still generate a `DW_AT_language`.
Main changes are to correctly interpret the contents of `DISourceLanguageName`.
>From fa90ba97f1da568d1df2035708eae09b67c7ece7 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
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 | 22 ++++++--
llvm/include/llvm/IR/DIBuilder.h | 6 +--
llvm/include/llvm/IR/DebugInfoMetadata.h | 54 ++++++++++++++-----
llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp | 7 ++-
llvm/lib/AsmParser/LLParser.cpp | 11 ++--
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 8 +--
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 7 ++-
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 5 +-
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 16 +++---
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 20 ++++---
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 7 ++-
llvm/lib/IR/AsmWriter.cpp | 9 +++-
llvm/lib/IR/DIBuilder.cpp | 8 +--
llvm/lib/IR/DebugInfo.cpp | 2 +-
llvm/lib/IR/DebugInfoMetadata.cpp | 9 ++--
llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 16 ++++--
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 | 27 +++++-----
llvm/unittests/IR/VerifierTest.cpp | 8 +--
.../Transforms/Utils/CloningTest.cpp | 24 +++++----
26 files changed, 214 insertions(+), 120 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index fee6bc0cbb64b..bb49adaa9f858 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::NoVersion(LangTag), CUFile,
+ CGOpts.EmitVersionIdentMetadata ? Producer : "",
CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
CGOpts.PrepareForThinLTO,
CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.SplitDwarfFile, EmissionKind,
@@ -1232,7 +1233,11 @@ 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()) {
+ auto Lang = TheCU->getSourceLanguage();
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
+
+ switch (Lang.getName()) {
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 +3216,11 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
if (!ID)
return nullptr;
- auto RuntimeLang =
- static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage());
+ auto Lang = TheCU->getSourceLanguage();
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
+
+ auto RuntimeLang = static_cast<llvm::dwarf::SourceLanguage>(Lang.getName());
// 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 +3356,11 @@ 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();
+
+ auto Lang = TheCU->getSourceLanguage();
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
+ unsigned RuntimeLang = Lang.getName();
// 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..f7821873e4128 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -66,6 +66,33 @@ 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<uint16_t> Version;
+
+public:
+ bool hasVersionedName() const { return Version.has_value(); }
+
+ uint16_t getName() const { return Name; }
+
+ DISourceLanguageName(uint16_t Lang, uint16_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 +2030,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 +2040,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 +2070,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 +2096,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 +2112,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 +2127,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..d53ef6d02c72d 100644
--- a/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp
+++ b/llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp
@@ -43,11 +43,14 @@ 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 LangVerPair = CU->getSourceLanguage();
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!LangVerPair.hasVersionedName());
+ auto Lang = dwarf::LanguageString(LangVerPair.getName());
if (!Lang.empty())
O << Lang;
else
- O << "unknown-language(" << CU->getSourceLanguage() << ")";
+ O << "unknown-language(" << LangVerPair.getName() << ")";
printFile(O, CU->getFilename(), CU->getDirectory());
O << '\n';
}
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 897e679095906..17de69c3fb0ba 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5861,11 +5861,12 @@ 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::NoVersion(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..4706261b4d6d5 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1866,10 +1866,12 @@ 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]),
+ Context, DISourceLanguageName::NoVersion(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],
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index c4070e1f44688..50960f7f6e7f1 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2105,7 +2105,12 @@ 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());
+
+ auto Lang = N->getSourceLanguage();
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
+ Record.push_back(Lang.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..35c8368c7cfaa 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -633,8 +633,11 @@ void CodeViewDebug::beginModule(Module *M) {
Node = *CUs->operands().begin();
}
const auto *CU = cast<DICompileUnit>(Node);
+ auto Lang = CU->getSourceLanguage();
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
- CurrentSourceLanguage = MapDWLangToCVLang(CU->getSourceLanguage());
+ CurrentSourceLanguage = MapDWLangToCVLang(Lang.getName());
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..05c3c4c02f730 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1039,8 +1039,13 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit,
} else
NewCU.addString(Die, dwarf::DW_AT_producer, Producer);
+ auto Lang = DIUnit->getSourceLanguage();
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
+
NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
- DIUnit->getSourceLanguage());
+ Lang.getName());
+
NewCU.addString(Die, dwarf::DW_AT_name, FN);
StringRef SysRoot = DIUnit->getSysRoot();
if (!SysRoot.empty())
@@ -2930,10 +2935,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 +3930,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..b7aed24f54106 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,21 @@ void DwarfUnit::addType(DIE &Entity, const DIType *Ty,
addDIEEntry(Entity, Attribute, DIEEntry(*getOrCreateTypeDIE(Ty)));
}
+llvm::dwarf::SourceLanguage DwarfUnit::getSourceLanguage() const {
+ const auto &Lang = getLanguage();
+
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
+
+ return static_cast<llvm::dwarf::SourceLanguage>(Lang.getName());
+}
+
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 +949,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 +1457,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 +1709,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..8cd7d25de2332 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2369,8 +2369,13 @@ 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);
+ auto Lang = N->getSourceLanguage();
+
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
+ Printer.printDwarfEnum("language", Lang.getName(), 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/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 0accb225122be..4cc6ff396e75d 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -689,10 +689,18 @@ 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;
+
+ auto Lang = DIS->getUnit()->getSourceLanguage();
+ // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
+ assert(!Lang.hasVersionedName());
+
+ if (!dwarf::isCPlusPlus(
+ static_cast<llvm::dwarf::SourceLanguage>(Lang.getName())) ||
+ 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..95593f843b095 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,15 @@ 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());
+ ASSERT_FALSE(N->getSourceLanguage().hasVersionedName());
+ EXPECT_EQ(SourceLanguage, N->getSourceLanguage().getName());
EXPECT_EQ(File, N->getFile());
EXPECT_EQ(Producer, N->getProducer());
EXPECT_EQ(IsOptimized, N->isOptimized());
@@ -2921,7 +2923,8 @@ TEST_F(DICompileUnitTest, get) {
TempDICompileUnit Temp = N->clone();
EXPECT_EQ(dwarf::DW_TAG_compile_unit, Temp->getTag());
- EXPECT_EQ(SourceLanguage, Temp->getSourceLanguage());
+ ASSERT_FALSE(Temp->getSourceLanguage().hasVersionedName());
+ EXPECT_EQ(SourceLanguage, Temp->getSourceLanguage().getName());
EXPECT_EQ(File, Temp->getFile());
EXPECT_EQ(Producer, Temp->getProducer());
EXPECT_EQ(IsOptimized, Temp->isOptimized());
@@ -2959,10 +2962,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,
>From 3bbe032d63950d669113115cab47ccc9ab7f56fb Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
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/AsmParser/LLParser.cpp | 13 ++++++++++---
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 10 ++++++++--
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 8 +++++---
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 13 ++++++++++---
llvm/lib/IR/AsmWriter.cpp | 13 +++++++++----
6 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index f7821873e4128..6ff6be16ac60d 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -87,6 +87,10 @@ class DISourceLanguageName {
bool hasVersionedName() const { return Version.has_value(); }
uint16_t getName() const { return Name; }
+ uint16_t getVersion() const {
+ assert(hasVersionedName() && "Tried getting version on unversioned name");
+ return *Version;
+ }
DISourceLanguageName(uint16_t Lang, uint16_t Version)
: Name(Lang), Version(Version) {};
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 17de69c3fb0ba..c229efa8f1ef2 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5837,8 +5837,9 @@ bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) {
return tokError("missing 'distinct', required for !DICompileUnit");
#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,9 +5861,15 @@ bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) {
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
+ if (!language.Seen && !sourceLanguageName.Seen)
+ return tokError("missing one of 'language' or 'sourceLanguageName', "
+ "required for !DICompileUnit");
+
Result = DICompileUnit::getDistinct(
- Context, DISourceLanguageName::NoVersion(language.Val), file.Val,
- producer.Val, isOptimized.Val, flags.Val, runtimeVersion.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,
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 4706261b4d6d5..79450f8b7193a 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1860,15 +1860,21 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
break;
}
case bitc::METADATA_COMPILE_UNIT: {
- if (Record.size() < 14 || Record.size() > 22)
+ if (Record.size() < 14 || Record.size() > 23)
return error("Invalid record");
// Ignore Record[0], which indicates whether this compile unit is
// 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::NoVersion(Record[1]),
+ 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]),
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 50960f7f6e7f1..775481701204b 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2107,9 +2107,11 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
Record.push_back(/* IsDistinct */ true);
auto Lang = N->getSourceLanguage();
- // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
- assert(!Lang.hasVersionedName());
- Record.push_back(Lang.getUnversionedName());
+ 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()));
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index b7aed24f54106..14e899c6e4375 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"
@@ -707,10 +708,16 @@ void DwarfUnit::addType(DIE &Entity, const DIType *Ty,
llvm::dwarf::SourceLanguage DwarfUnit::getSourceLanguage() const {
const auto &Lang = getLanguage();
- // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
- assert(!Lang.hasVersionedName());
+ llvm::dwarf::SourceLanguage SLang;
+ if (Lang.hasVersionedName())
+ SLang = llvm::dwarf::toDW_LANG(
+ static_cast<llvm::dwarf::SourceLanguageName>(Lang.getName()),
+ Lang.getVersion())
+ .value_or(llvm::dwarf::DW_LANG_hi_user);
+ else
+ SLang = static_cast<llvm::dwarf::SourceLanguage>(Lang.getName());
- return static_cast<llvm::dwarf::SourceLanguage>(Lang.getName());
+ return SLang;
}
std::string DwarfUnit::getParentContextString(const DIScope *Context) const {
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 8cd7d25de2332..b658fbec60e38 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2371,10 +2371,15 @@ static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N,
MDFieldPrinter Printer(Out, WriterCtx);
auto Lang = N->getSourceLanguage();
- // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
- assert(!Lang.hasVersionedName());
- Printer.printDwarfEnum("language", Lang.getName(), dwarf::LanguageString,
- /* ShouldSkipZero */ false);
+ if (Lang.hasVersionedName())
+ Printer.printDwarfEnum(
+ "sourceLanguageName",
+ static_cast<llvm::dwarf::SourceLanguageName>(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());
>From 0cfd98977974eda46422cc82354bc82ff1d0cfcd Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
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 +-
4 files changed, 9 insertions(+), 4 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<g_Group>,
HelpText<"Generate source-level debug information with dwarf version 4">;
def gdwarf_5 : Flag<["-"], "gdwarf-5">, Group<g_Group>,
HelpText<"Generate source-level debug information with dwarf version 5">;
+def gdwarf_6
+ : Flag<["-"], "gdwarf-6">,
+ Group<g_Group>,
+ HelpText<"Generate source-level debug information with dwarf version 6">;
}
def gdwarf64 : Flag<["-"], "gdwarf64">, Group<g_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,
>From 6ccb9f27c15d0f5aa163235fe10417ec87c12e0e Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
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 | 106 ++++++++++++++++++++----------
1 file changed, 72 insertions(+), 34 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index bb49adaa9f858..7ec7b38dfa9f1 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<llvm::DIFile::ChecksumKind> 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::NoVersion(LangTag), CUFile,
+ GetDISourceLanguageName(CGM), CUFile,
CGOpts.EmitVersionIdentMetadata ? Producer : "",
CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
CGOpts.PrepareForThinLTO,
@@ -1231,24 +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) {
- auto Lang = TheCU->getSourceLanguage();
- // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
- assert(!Lang.hasVersionedName());
-
- switch (Lang.getName()) {
+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<CXXRecordDecl>(TD) || isa<EnumDecl>(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<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
+
+ if (llvm::DISourceLanguageName SourceLang = TheCU->getSourceLanguage();
+ SourceLang.hasVersionedName())
+ return hasCXXMangling(
+ static_cast<llvm::dwarf::SourceLanguageName>(SourceLang.getName()),
+ IsTagDecl);
+ else
+ return hasCXXMangling(
+ static_cast<llvm::dwarf::SourceLanguage>(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 323792d340a785b4833cb8fc9011f5a85358b8db Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
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 | 12 ++++++------
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 2c9a3c0f6fb04..7b0573e9080bf 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, 5, 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 05c3c4c02f730..32eef217053d7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1039,12 +1039,12 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit,
} else
NewCU.addString(Die, dwarf::DW_AT_producer, Producer);
- auto Lang = DIUnit->getSourceLanguage();
- // Versioned names (aka DWARFv6 DW_LNAME_) not yet supported.
- assert(!Lang.hasVersionedName());
-
- NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
- Lang.getName());
+ 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, /*Form=*/std::nullopt,
+ Lang.getName());
NewCU.addString(Die, dwarf::DW_AT_name, FN);
StringRef SysRoot = DIUnit->getSysRoot();
>From 26952b4218ccdee76f355376ede82cfba836622e Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
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<llvm::dwarf::SourceLanguageName>(Val));
case DW_AT_encoding:
return AttributeEncodingString(Val);
case DW_AT_decimal_sign:
More information about the llvm-commits
mailing list