[Mlir-commits] [clang] [llvm] [mlir] DRAFT: Support for DWARFv6 DW_AT_language_name (PR #162261)
Michael Buch
llvmlistbot at llvm.org
Tue Oct 7 06:46:33 PDT 2025
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/162261
>From a8242765e2ce94cd2fd36d73d233915f91908580 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
(cherry picked from commit 7fe58f8007537445a7cb2922bfbe35781c26ff5a)
---
clang/lib/CodeGen/CGDebugInfo.cpp | 12 ++--
llvm/include/llvm/IR/DIBuilder.h | 6 +-
llvm/include/llvm/IR/DebugInfoMetadata.h | 65 +++++++++++++++----
llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp | 6 +-
llvm/lib/AsmParser/LLParser.cpp | 10 +--
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 10 +--
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 +-
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 4 +-
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 12 ++--
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 16 +++--
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 7 +-
llvm/lib/IR/AsmWriter.cpp | 8 ++-
llvm/lib/IR/DIBuilder.cpp | 8 +--
llvm/lib/IR/DebugInfo.cpp | 2 +-
llvm/lib/IR/DebugInfoMetadata.cpp | 9 +--
.../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 3 +-
.../WebAssembly/WebAssemblyAsmPrinter.cpp | 4 +-
llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 12 ++--
llvm/lib/Transforms/Utils/Debugify.cpp | 5 +-
llvm/unittests/CodeGen/InstrRefLDVTest.cpp | 4 +-
llvm/unittests/CodeGen/LexicalScopesTest.cpp | 4 +-
.../CodeGen/MachineBasicBlockTest.cpp | 4 +-
.../Frontend/OpenMPIRBuilderTest.cpp | 5 +-
llvm/unittests/IR/DebugInfoTest.cpp | 11 ++--
llvm/unittests/IR/IRBuilderTest.cpp | 35 +++++-----
llvm/unittests/IR/MetadataTest.cpp | 25 +++----
llvm/unittests/IR/VerifierTest.cpp | 8 ++-
.../Transforms/Utils/CloningTest.cpp | 24 +++----
mlir/lib/Target/LLVMIR/DebugImporter.cpp | 3 +-
29 files changed, 200 insertions(+), 125 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index fee6bc0cbb64b..b91cb36483d72 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -787,7 +787,8 @@ void CGDebugInfo::CreateCompileUnit() {
// Create new compile unit.
TheCU = DBuilder.createCompileUnit(
- LangTag, CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "",
+ llvm::DISourceLanguageName(LangTag), CUFile,
+ CGOpts.EmitVersionIdentMetadata ? Producer : "",
CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
CGOpts.PrepareForThinLTO,
CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.SplitDwarfFile, EmissionKind,
@@ -1232,7 +1233,7 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
/// \return whether a C++ mangling exists for the type defined by TD.
static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
- switch (TheCU->getSourceLanguage()) {
+ switch (TheCU->getSourceLanguage().getUnversionedName()) {
case llvm::dwarf::DW_LANG_C_plus_plus:
case llvm::dwarf::DW_LANG_C_plus_plus_11:
case llvm::dwarf::DW_LANG_C_plus_plus_14:
@@ -3211,8 +3212,8 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
if (!ID)
return nullptr;
- auto RuntimeLang =
- static_cast<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..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(),
+ context, getOrCreateDistinctID(node),
+ node->getSourceLanguage().getUnversionedName(),
translate(node->getFile()), getStringAttrOrNull(node->getRawProducer()),
node->isOptimized(), emissionKind.value(), nameTableKind.value(),
getStringAttrOrNull(node->getRawSplitDebugFilename()));
>From d519d8845a9a98448ca92fe87c864422f595aac0 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 | 20 ++++++++++++++------
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 16 +++++++++++-----
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 8 +++++++-
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 12 ++++++++++--
llvm/lib/IR/AsmWriter.cpp | 14 ++++++++++----
6 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 80c9ea38016b6..1ab8a4c7e79d5 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -88,6 +88,10 @@ class DISourceLanguageName {
/// Returns a versioned or unversioned language name.
uint16_t getName() const { return Name; }
+ uint32_t getVersion() const {
+ assert(hasVersionedName() && "Tried getting version on unversioned name");
+ return *Version;
+ }
// Transitional API for cases where we do not yet support
// versioned source language names. Use \ref getName instead.
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 55899660fa84a..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,12 +5861,19 @@ 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(language.Val), file.Val, producer.Val,
- isOptimized.Val, flags.Val, runtimeVersion.Val, splitDebugFilename.Val,
- emissionKind.Val, enums.Val, retainedTypes.Val, globals.Val, imports.Val,
- macros.Val, dwoId.Val, splitDebugInlining.Val, debugInfoForProfiling.Val,
- nameTableKind.Val, rangesBaseAddress.Val, sysroot.Val, sdk.Val);
+ Context,
+ language.Seen ? DISourceLanguageName(language.Val)
+ : DISourceLanguageName(sourceLanguageName.Val, 0),
+ file.Val, producer.Val, isOptimized.Val, flags.Val, runtimeVersion.Val,
+ splitDebugFilename.Val, emissionKind.Val, enums.Val, retainedTypes.Val,
+ globals.Val, imports.Val, macros.Val, dwoId.Val, splitDebugInlining.Val,
+ debugInfoForProfiling.Val, nameTableKind.Val, rangesBaseAddress.Val,
+ sysroot.Val, sdk.Val);
return false;
}
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index a4d1b8372dfac..cdcf7a80ffac7 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1867,12 +1867,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
// distinct. It's always distinct.
IsDistinct = true;
+ const auto LangVersionMask = (uint64_t(1) << 63);
+ const bool HasVersionedLanguage = Record[1] & LangVersionMask;
+
auto *CU = DICompileUnit::getDistinct(
- Context, DISourceLanguageName(Record[1]), getMDOrNull(Record[2]),
- getMDString(Record[3]), Record[4], getMDString(Record[5]), Record[6],
- getMDString(Record[7]), Record[8], getMDOrNull(Record[9]),
- getMDOrNull(Record[10]), getMDOrNull(Record[12]),
- getMDOrNull(Record[13]),
+ Context,
+ HasVersionedLanguage
+ ? DISourceLanguageName(Record[1] & ~LangVersionMask, 0)
+ : DISourceLanguageName(Record[1]),
+ getMDOrNull(Record[2]), getMDString(Record[3]), Record[4],
+ getMDString(Record[5]), Record[6], getMDString(Record[7]), Record[8],
+ getMDOrNull(Record[9]), getMDOrNull(Record[10]),
+ getMDOrNull(Record[12]), getMDOrNull(Record[13]),
Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]),
Record.size() <= 14 ? 0 : Record[14],
Record.size() <= 16 ? true : Record[16],
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index bae05dc43a0fd..775481701204b 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2106,7 +2106,13 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
assert(N->isDistinct() && "Expected distinct compile units");
Record.push_back(/* IsDistinct */ true);
- Record.push_back(N->getSourceLanguage().getUnversionedName());
+ auto Lang = N->getSourceLanguage();
+ Record.push_back(Lang.getName());
+ // Set bit so the MetadataLoader can distniguish between versioned and
+ // unversioned names.
+ if (Lang.hasVersionedName())
+ Record.back() ^= (uint64_t(1) << 63);
+
Record.push_back(VE.getMetadataOrNullID(N->getFile()));
Record.push_back(VE.getMetadataOrNullID(N->getRawProducer()));
Record.push_back(N->isOptimized());
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index aa078f3f81d49..8427d361a3461 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -16,6 +16,7 @@
#include "DwarfExpression.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
@@ -705,8 +706,15 @@ void DwarfUnit::addType(DIE &Entity, const DIType *Ty,
}
llvm::dwarf::SourceLanguage DwarfUnit::getSourceLanguage() const {
- return static_cast<llvm::dwarf::SourceLanguage>(
- getLanguage().getUnversionedName());
+ const auto &Lang = getLanguage();
+
+ if (!Lang.hasVersionedName())
+ return static_cast<llvm::dwarf::SourceLanguage>(Lang.getName());
+
+ return llvm::dwarf::toDW_LANG(
+ static_cast<llvm::dwarf::SourceLanguageName>(Lang.getName()),
+ Lang.getVersion())
+ .value_or(llvm::dwarf::DW_LANG_hi_user);
}
std::string DwarfUnit::getParentContextString(const DIScope *Context) const {
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index ae086bcd3902d..abfef949ac7ae 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2370,10 +2370,16 @@ static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N,
Out << "!DICompileUnit(";
MDFieldPrinter Printer(Out, WriterCtx);
- Printer.printDwarfEnum("language",
- N->getSourceLanguage().getUnversionedName(),
- dwarf::LanguageString,
- /* ShouldSkipZero */ false);
+ auto Lang = N->getSourceLanguage();
+ if (Lang.hasVersionedName())
+ Printer.printDwarfEnum(
+ "sourceLanguageName",
+ static_cast<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 c4672a131411dfb11a2473fd2b358d646019fa41 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 33d3c8e12ceef325485b93c74fd11a3a50266812 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 | 102 +++++++++++++++++++++---------
1 file changed, 72 insertions(+), 30 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index b91cb36483d72..a4f418f4f2858 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -41,8 +41,10 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
@@ -647,6 +649,45 @@ StringRef CGDebugInfo::getCurrentDirname() {
return CGM.getCodeGenOpts().DebugCompilationDir;
}
+static llvm::DISourceLanguageName
+GetDISourceLanguageName(const CodeGenModule &CGM) {
+ const CodeGenOptions &CGO = CGM.getCodeGenOpts();
+ const LangOptions &LO = CGM.getLangOpts();
+
+ llvm::dwarf::SourceLanguage LangTag;
+ if (LO.CPlusPlus) {
+ if (LO.ObjC)
+ LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
+ else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)
+ LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
+ else if (LO.CPlusPlus14)
+ LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14;
+ else if (LO.CPlusPlus11)
+ LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11;
+ else
+ LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
+ } else if (LO.ObjC) {
+ LangTag = llvm::dwarf::DW_LANG_ObjC;
+ } else if (LO.OpenCL && (!CGO.DebugStrictDwarf || CGO.DwarfVersion >= 5)) {
+ LangTag = llvm::dwarf::DW_LANG_OpenCL;
+ } else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) {
+ LangTag = llvm::dwarf::DW_LANG_C11;
+ } else if (LO.C99) {
+ LangTag = llvm::dwarf::DW_LANG_C99;
+ } else {
+ LangTag = llvm::dwarf::DW_LANG_C89;
+ }
+
+ // FIXME: for some languages that don't have a DW_LNAME_* we would fall back
+ // to emitting a DW_LANG_. Which is technically obsolete starting with
+ // DWARFv6.
+ if (CGO.DwarfVersion >= 6)
+ if (auto LName = llvm::dwarf::toDW_LNAME(LangTag))
+ return llvm::DISourceLanguageName(LName->first, LName->second);
+
+ return llvm::DISourceLanguageName(LangTag);
+}
+
void CGDebugInfo::CreateCompileUnit() {
SmallString<64> Checksum;
std::optional<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(LangTag), CUFile,
+ GetDISourceLanguageName(CGM), CUFile,
CGOpts.EmitVersionIdentMetadata ? Producer : "",
CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
CGOpts.PrepareForThinLTO,
@@ -1231,20 +1247,46 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
Ty->getPointeeType(), Unit);
}
-/// \return whether a C++ mangling exists for the type defined by TD.
-static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
- switch (TheCU->getSourceLanguage().getUnversionedName()) {
+static bool hasCXXMangling(llvm::dwarf::SourceLanguage Lang, bool IsTagDecl) {
+ switch (Lang) {
case llvm::dwarf::DW_LANG_C_plus_plus:
case llvm::dwarf::DW_LANG_C_plus_plus_11:
case llvm::dwarf::DW_LANG_C_plus_plus_14:
return true;
case llvm::dwarf::DW_LANG_ObjC_plus_plus:
- return isa<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 9db9dd1bc9e57ffb5039efd964e0189add008888 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 | 8 ++++++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 2c9a3c0f6fb04..5977569a19f5c 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -424,6 +424,8 @@ HANDLE_DW_AT(0x89, export_symbols, 5, DWARF)
HANDLE_DW_AT(0x8a, deleted, 5, DWARF)
HANDLE_DW_AT(0x8b, defaulted, 5, DWARF)
HANDLE_DW_AT(0x8c, loclists_base, 5, DWARF)
+// New in Dwarf v6:
+HANDLE_DW_AT(0x90, language_name, 6, DWARF)
// Vendor extensions:
HANDLE_DW_AT(0x806, GHS_namespace_alias, 0, GHS)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index d751a7f9f01ef..433877f3a8b98 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1039,8 +1039,12 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit,
} else
NewCU.addString(Die, dwarf::DW_AT_producer, Producer);
- NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
- DIUnit->getSourceLanguage().getUnversionedName());
+ if (auto Lang = DIUnit->getSourceLanguage(); Lang.hasVersionedName())
+ NewCU.addUInt(Die, dwarf::DW_AT_language_name, dwarf::DW_FORM_data2,
+ Lang.getName());
+ else
+ NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ Lang.getName());
NewCU.addString(Die, dwarf::DW_AT_name, FN);
StringRef SysRoot = DIUnit->getSysRoot();
>From eaf7fa98ddac158878a6f91501f9987b219cd930 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 Mlir-commits
mailing list