Skip to content

Commit 0ede563

Browse files
authored
[clang][DebugInfo] Emit DW_AT_language_{name, version} for DWARFv6 (#163208)
Depends on: * llvm/llvm-project#163348 * llvm/llvm-project#162632 With this patch Clang will start emitting `DW_AT_language_{name, version}` for C++/C/Objective-C/Objective-C++ when using `-gdwarf-6`. We adjust the `DISourceLanguageName` (which we pass to `DICompileUnit`) to hold a `DW_AT_language_name_` and version code when in DWARFv6. Otherwise we continue using the `DW_LANG_` version of `DISourceLanguageName`. We didn't back-port emitting `DW_AT_language_name`/`DW_AT_language_version` to DWARFv5 (unlike GCC, which emits both the new and old language attributes in DWARFv5) because there wasn't a compelling reason to do so (yet).
1 parent 4c4c028 commit 0ede563

File tree

5 files changed

+151
-30
lines changed

5 files changed

+151
-30
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 93 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,68 @@ StringRef CGDebugInfo::getCurrentDirname() {
647647
return CGM.getCodeGenOpts().DebugCompilationDir;
648648
}
649649

650+
static llvm::dwarf::SourceLanguage GetSourceLanguage(const CodeGenModule &CGM) {
651+
const CodeGenOptions &CGO = CGM.getCodeGenOpts();
652+
const LangOptions &LO = CGM.getLangOpts();
653+
654+
assert(CGO.DwarfVersion <= 5);
655+
656+
llvm::dwarf::SourceLanguage LangTag;
657+
if (LO.CPlusPlus) {
658+
if (LO.ObjC)
659+
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
660+
else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)
661+
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
662+
else if (LO.CPlusPlus14)
663+
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14;
664+
else if (LO.CPlusPlus11)
665+
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11;
666+
else
667+
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
668+
} else if (LO.ObjC) {
669+
LangTag = llvm::dwarf::DW_LANG_ObjC;
670+
} else if (LO.OpenCL && (!CGO.DebugStrictDwarf || CGO.DwarfVersion >= 5)) {
671+
LangTag = llvm::dwarf::DW_LANG_OpenCL;
672+
} else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) {
673+
LangTag = llvm::dwarf::DW_LANG_C11;
674+
} else if (LO.C99) {
675+
LangTag = llvm::dwarf::DW_LANG_C99;
676+
} else {
677+
LangTag = llvm::dwarf::DW_LANG_C89;
678+
}
679+
680+
return LangTag;
681+
}
682+
683+
static llvm::DISourceLanguageName
684+
GetDISourceLanguageName(const CodeGenModule &CGM) {
685+
// Emit pre-DWARFv6 language codes.
686+
if (CGM.getCodeGenOpts().DwarfVersion < 6)
687+
return llvm::DISourceLanguageName(GetSourceLanguage(CGM));
688+
689+
const LangOptions &LO = CGM.getLangOpts();
690+
691+
uint32_t LangVersion = 0;
692+
llvm::dwarf::SourceLanguageName LangTag;
693+
if (LO.CPlusPlus) {
694+
if (LO.ObjC) {
695+
LangTag = llvm::dwarf::DW_LNAME_ObjC_plus_plus;
696+
} else {
697+
LangTag = llvm::dwarf::DW_LNAME_C_plus_plus;
698+
LangVersion = LO.getCPlusPlusLangStd().value_or(0);
699+
}
700+
} else if (LO.ObjC) {
701+
LangTag = llvm::dwarf::DW_LNAME_ObjC;
702+
} else if (LO.OpenCL) {
703+
LangTag = llvm::dwarf::DW_LNAME_OpenCL_C;
704+
} else {
705+
LangTag = llvm::dwarf::DW_LNAME_C;
706+
LangVersion = LO.getCLangStd().value_or(0);
707+
}
708+
709+
return llvm::DISourceLanguageName(LangTag, LangVersion);
710+
}
711+
650712
void CGDebugInfo::CreateCompileUnit() {
651713
SmallString<64> Checksum;
652714
std::optional<llvm::DIFile::ChecksumKind> CSKind;
@@ -702,31 +764,6 @@ void CGDebugInfo::CreateCompileUnit() {
702764
}
703765
}
704766

705-
llvm::dwarf::SourceLanguage LangTag;
706-
if (LO.CPlusPlus) {
707-
if (LO.ObjC)
708-
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
709-
else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)
710-
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
711-
else if (LO.CPlusPlus14)
712-
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14;
713-
else if (LO.CPlusPlus11)
714-
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11;
715-
else
716-
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
717-
} else if (LO.ObjC) {
718-
LangTag = llvm::dwarf::DW_LANG_ObjC;
719-
} else if (LO.OpenCL && (!CGM.getCodeGenOpts().DebugStrictDwarf ||
720-
CGM.getCodeGenOpts().DwarfVersion >= 5)) {
721-
LangTag = llvm::dwarf::DW_LANG_OpenCL;
722-
} else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) {
723-
LangTag = llvm::dwarf::DW_LANG_C11;
724-
} else if (LO.C99) {
725-
LangTag = llvm::dwarf::DW_LANG_C99;
726-
} else {
727-
LangTag = llvm::dwarf::DW_LANG_C89;
728-
}
729-
730767
std::string Producer = getClangFullVersion();
731768

732769
// Figure out which version of the ObjC runtime we have.
@@ -787,7 +824,7 @@ void CGDebugInfo::CreateCompileUnit() {
787824

788825
// Create new compile unit.
789826
TheCU = DBuilder.createCompileUnit(
790-
llvm::DISourceLanguageName(LangTag), CUFile,
827+
GetDISourceLanguageName(CGM), CUFile,
791828
CGOpts.EmitVersionIdentMetadata ? Producer : "",
792829
CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
793830
CGOpts.PrepareForThinLTO,
@@ -1234,20 +1271,46 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
12341271
Ty->getPointeeType(), Unit);
12351272
}
12361273

1237-
/// \return whether a C++ mangling exists for the type defined by TD.
1238-
static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
1239-
switch (TheCU->getSourceLanguage().getUnversionedName()) {
1274+
static bool hasCXXMangling(llvm::dwarf::SourceLanguage Lang, bool IsTagDecl) {
1275+
switch (Lang) {
12401276
case llvm::dwarf::DW_LANG_C_plus_plus:
12411277
case llvm::dwarf::DW_LANG_C_plus_plus_11:
12421278
case llvm::dwarf::DW_LANG_C_plus_plus_14:
12431279
return true;
12441280
case llvm::dwarf::DW_LANG_ObjC_plus_plus:
1245-
return isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
1281+
return IsTagDecl;
1282+
default:
1283+
return false;
1284+
}
1285+
}
1286+
1287+
static bool hasCXXMangling(llvm::dwarf::SourceLanguageName Lang,
1288+
bool IsTagDecl) {
1289+
switch (Lang) {
1290+
case llvm::dwarf::DW_LNAME_C_plus_plus:
1291+
return true;
1292+
case llvm::dwarf::DW_LNAME_ObjC_plus_plus:
1293+
return IsTagDecl;
12461294
default:
12471295
return false;
12481296
}
12491297
}
12501298

1299+
/// \return whether a C++ mangling exists for the type defined by TD.
1300+
static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
1301+
const bool IsTagDecl = isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
1302+
1303+
if (llvm::DISourceLanguageName SourceLang = TheCU->getSourceLanguage();
1304+
SourceLang.hasVersionedName())
1305+
return hasCXXMangling(
1306+
static_cast<llvm::dwarf::SourceLanguageName>(SourceLang.getName()),
1307+
IsTagDecl);
1308+
else
1309+
return hasCXXMangling(
1310+
static_cast<llvm::dwarf::SourceLanguage>(SourceLang.getName()),
1311+
IsTagDecl);
1312+
}
1313+
12511314
// Determines if the debug info for this tag declaration needs a type
12521315
// identifier. The purpose of the unique identifier is to deduplicate type
12531316
// information for identical types across TUs. Because of the C++ one definition
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=5 -std=c++98 \
2+
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageName" --implicit-check-not "sourceLanguageVersion"
3+
//
4+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++98 | FileCheck %s --check-prefix=CHECK-CPP98
5+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++03 | FileCheck %s --check-prefix=CHECK-CPP03
6+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++11 | FileCheck %s --check-prefix=CHECK-CPP11
7+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++14 | FileCheck %s --check-prefix=CHECK-CPP14
8+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++17 | FileCheck %s --check-prefix=CHECK-CPP17
9+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++20 | FileCheck %s --check-prefix=CHECK-CPP20
10+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++23 | FileCheck %s --check-prefix=CHECK-CPP23
11+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++2c | FileCheck %s --check-prefix=CHECK-CPP2C
12+
13+
struct Foo {} globalVar;
14+
15+
// CHECK-CPP98: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 199711
16+
// FIXME: C++03 technically has no official standard version code. From Clang's point of view C++03 and C++98 are interchangable.
17+
// CHECK-CPP03: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 199711
18+
// CHECK-CPP11: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201103
19+
// CHECK-CPP14: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201402
20+
// CHECK-CPP17: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201703
21+
// CHECK-CPP20: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202002
22+
// CHECK-CPP23: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202302
23+
// CHECK-CPP2C: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202400
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=5 -std=c99 \
2+
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageName" --implicit-check-not "sourceLanguageVersion"
3+
//
4+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c89 | FileCheck %s --check-prefix=CHECK-C89 --implicit-check-not "sourceLanguageVersion"
5+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c99 | FileCheck %s --check-prefix=CHECK-C99
6+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c17 | FileCheck %s --check-prefix=CHECK-C17
7+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c23 | FileCheck %s --check-prefix=CHECK-C23
8+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c2y | FileCheck %s --check-prefix=CHECK-C2Y
9+
10+
int globalVar = 10;
11+
12+
// CHECK-C89: !DICompileUnit(sourceLanguageName: DW_LNAME_C,
13+
// CHECK-C99: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 199901
14+
// CHECK-C11: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 201112
15+
// CHECK-C17: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 201710
16+
// CHECK-C23: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 202311
17+
// CHECK-C2Y: !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 202400
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=5 \
2+
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageName" --implicit-check-not "sourceLanguageVersion"
3+
//
4+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 \
5+
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageVersion" --check-prefix=CHECK-OBJC
6+
7+
int globalVar = 10;
8+
9+
// CHECK-OBJC: !DICompileUnit(sourceLanguageName: DW_LNAME_ObjC,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=5 \
2+
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageName" --implicit-check-not "sourceLanguageVersion"
3+
//
4+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 \
5+
// RUN: | FileCheck %s --implicit-check-not "sourceLanguageVersion" --check-prefix=CHECK-OBJCXX
6+
7+
int globalVar = 10;
8+
9+
// CHECK-OBJCXX: !DICompileUnit(sourceLanguageName: DW_LNAME_ObjC_plus_plus,

0 commit comments

Comments
 (0)