Skip to content

Commit 7a492b8

Browse files
committed
[clang][DebugInfo] Emit DW_AT_language_name for DWARFv6
1 parent 71681e9 commit 7a492b8

File tree

5 files changed

+183
-30
lines changed

5 files changed

+183
-30
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 124 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,97 @@ 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+
if (LO.CPlusPlus26)
700+
LangVersion = 202400; // No official language code yet.
701+
else if (LO.CPlusPlus23)
702+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C_plus_plus_23;
703+
else if (LO.CPlusPlus20)
704+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C_plus_plus_20;
705+
else if (LO.CPlusPlus17)
706+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C_plus_plus_17;
707+
else if (LO.CPlusPlus14)
708+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C_plus_plus_14;
709+
else if (LO.CPlusPlus11)
710+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C_plus_plus_11;
711+
}
712+
} else if (LO.ObjC) {
713+
LangTag = llvm::dwarf::DW_LNAME_ObjC;
714+
} else if (LO.OpenCL) {
715+
LangTag = llvm::dwarf::DW_LNAME_OpenCL_C;
716+
} else {
717+
LangTag = llvm::dwarf::DW_LNAME_C;
718+
if (LO.C2y)
719+
LangVersion = 202500; // No official language code yet.
720+
else if (LO.C23)
721+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C23;
722+
else if (LO.C17)
723+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C17;
724+
else if (LO.C11)
725+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C11;
726+
else if (LO.C99)
727+
LangVersion = llvm::dwarf::DW_LANG_VERSION_C99;
728+
}
729+
730+
return {LangTag, LangVersion};
731+
}
732+
733+
static llvm::DISourceLanguageName
734+
GetDISourceLanguageName(const CodeGenModule &CGM) {
735+
// Emit pre-DWARFv6 language codes.
736+
if (CGM.getCodeGenOpts().DwarfVersion < 6)
737+
return llvm::DISourceLanguageName(GetSourceLanguage(CGM));
738+
739+
auto [LName, LVersion] = GetSourceLanguageName(CGM);
740+
return llvm::DISourceLanguageName(LName, LVersion);
741+
}
742+
650743
void CGDebugInfo::CreateCompileUnit() {
651744
SmallString<64> Checksum;
652745
std::optional<llvm::DIFile::ChecksumKind> CSKind;
@@ -702,31 +795,6 @@ void CGDebugInfo::CreateCompileUnit() {
702795
}
703796
}
704797

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

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

788856
// Create new compile unit.
789857
TheCU = DBuilder.createCompileUnit(
790-
llvm::DISourceLanguageName(LangTag), CUFile,
858+
GetDISourceLanguageName(CGM), CUFile,
791859
CGOpts.EmitVersionIdentMetadata ? Producer : "",
792860
CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
793861
CGOpts.PrepareForThinLTO,
@@ -1234,20 +1302,46 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
12341302
Ty->getPointeeType(), Unit);
12351303
}
12361304

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()) {
1305+
static bool hasCXXMangling(llvm::dwarf::SourceLanguage Lang, bool IsTagDecl) {
1306+
switch (Lang) {
12401307
case llvm::dwarf::DW_LANG_C_plus_plus:
12411308
case llvm::dwarf::DW_LANG_C_plus_plus_11:
12421309
case llvm::dwarf::DW_LANG_C_plus_plus_14:
12431310
return true;
12441311
case llvm::dwarf::DW_LANG_ObjC_plus_plus:
1245-
return isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
1312+
return IsTagDecl;
12461313
default:
12471314
return false;
12481315
}
12491316
}
12501317

1318+
static bool hasCXXMangling(llvm::dwarf::SourceLanguageName Lang,
1319+
bool IsTagDecl) {
1320+
switch (Lang) {
1321+
case llvm::dwarf::DW_LNAME_C_plus_plus:
1322+
return true;
1323+
case llvm::dwarf::DW_LNAME_ObjC_plus_plus:
1324+
return IsTagDecl;
1325+
default:
1326+
return false;
1327+
}
1328+
}
1329+
1330+
/// \return whether a C++ mangling exists for the type defined by TD.
1331+
static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
1332+
const bool IsTagDecl = isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);
1333+
1334+
if (llvm::DISourceLanguageName SourceLang = TheCU->getSourceLanguage();
1335+
SourceLang.hasVersionedName())
1336+
return hasCXXMangling(
1337+
static_cast<llvm::dwarf::SourceLanguageName>(SourceLang.getName()),
1338+
IsTagDecl);
1339+
else
1340+
return hasCXXMangling(
1341+
static_cast<llvm::dwarf::SourceLanguage>(SourceLang.getName()),
1342+
IsTagDecl);
1343+
}
1344+
12511345
// Determines if the debug info for this tag declaration needs a type
12521346
// identifier. The purpose of the unique identifier is to deduplicate type
12531347
// information for identical types across TUs. Because of the C++ one definition
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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 --implicit-check-not "sourceLanguageVersion"
5+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++03 | FileCheck %s --check-prefix=CHECK-CPP03 --implicit-check-not "sourceLanguageVersion"
6+
//
7+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++11 | FileCheck %s --check-prefix=CHECK-CPP11
8+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++14 | FileCheck %s --check-prefix=CHECK-CPP14
9+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++17 | FileCheck %s --check-prefix=CHECK-CPP17
10+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++20 | FileCheck %s --check-prefix=CHECK-CPP20
11+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++23 | FileCheck %s --check-prefix=CHECK-CPP23
12+
// RUN: %clang_cc1 -emit-llvm %s -o - -debug-info-kind=limited -dwarf-version=6 -std=c++2c | FileCheck %s --check-prefix=CHECK-CPP2C
13+
14+
int globalVar = 10;
15+
16+
// CHECK-CPP98: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus,
17+
// CHECK-CPP03: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus,
18+
//
19+
// CHECK-CPP11: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201103
20+
// CHECK-CPP14: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201402
21+
// CHECK-CPP17: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 201703
22+
// CHECK-CPP20: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202002
23+
// CHECK-CPP23: !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202302
24+
// 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: 202500
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)