Skip to content

Commit cdafc1d

Browse files
committed
[clang][DebugInfo] Emit DW_AT_language_name for DWARFv6
1 parent 8e29980 commit cdafc1d

File tree

5 files changed

+162
-30
lines changed

5 files changed

+162
-30
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 104 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@
4141
#include "llvm/ADT/DenseSet.h"
4242
#include "llvm/ADT/SmallVector.h"
4343
#include "llvm/ADT/StringExtras.h"
44+
#include "llvm/BinaryFormat/Dwarf.h"
4445
#include "llvm/IR/Constants.h"
4546
#include "llvm/IR/DataLayout.h"
47+
#include "llvm/IR/DebugInfoMetadata.h"
4648
#include "llvm/IR/DerivedTypes.h"
4749
#include "llvm/IR/Instruction.h"
4850
#include "llvm/IR/Instructions.h"
@@ -647,6 +649,77 @@ StringRef CGDebugInfo::getCurrentDirname() {
647649
return CGM.getCodeGenOpts().DebugCompilationDir;
648650
}
649651

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

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-
730778
std::string Producer = getClangFullVersion();
731779

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

788836
// Create new compile unit.
789837
TheCU = DBuilder.createCompileUnit(
790-
llvm::DISourceLanguageName(LangTag), CUFile,
838+
GetDISourceLanguageName(CGM), CUFile,
791839
CGOpts.EmitVersionIdentMetadata ? Producer : "",
792840
CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
793841
CGOpts.PrepareForThinLTO,
@@ -1234,20 +1282,46 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
12341282
Ty->getPointeeType(), Unit);
12351283
}
12361284

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()) {
1285+
static bool hasCXXMangling(llvm::dwarf::SourceLanguage Lang, bool IsTagDecl) {
1286+
switch (Lang) {
12401287
case llvm::dwarf::DW_LANG_C_plus_plus:
12411288
case llvm::dwarf::DW_LANG_C_plus_plus_11:
12421289
case llvm::dwarf::DW_LANG_C_plus_plus_14:
12431290
return true;
12441291
case llvm::dwarf::DW_LANG_ObjC_plus_plus:
1245-
return isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
1292+
return IsTagDecl;
12461293
default:
12471294
return false;
12481295
}
12491296
}
12501297

1298+
static bool hasCXXMangling(llvm::dwarf::SourceLanguageName Lang,
1299+
bool IsTagDecl) {
1300+
switch (Lang) {
1301+
case llvm::dwarf::DW_LNAME_C_plus_plus:
1302+
return true;
1303+
case llvm::dwarf::DW_LNAME_ObjC_plus_plus:
1304+
return IsTagDecl;
1305+
default:
1306+
return false;
1307+
}
1308+
}
1309+
1310+
/// \return whether a C++ mangling exists for the type defined by TD.
1311+
static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
1312+
const bool IsTagDecl = isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
1313+
1314+
if (llvm::DISourceLanguageName SourceLang = TheCU->getSourceLanguage();
1315+
SourceLang.hasVersionedName())
1316+
return hasCXXMangling(
1317+
static_cast<llvm::dwarf::SourceLanguageName>(SourceLang.getName()),
1318+
IsTagDecl);
1319+
else
1320+
return hasCXXMangling(
1321+
static_cast<llvm::dwarf::SourceLanguage>(SourceLang.getName()),
1322+
IsTagDecl);
1323+
}
1324+
12511325
// Determines if the debug info for this tag declaration needs a type
12521326
// identifier. The purpose of the unique identifier is to deduplicate type
12531327
// 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+
int globalVar = 10;
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)