[llvm] 030d8e6 - [llvm][Dwarf] Add LanguageDescription API that accounts for version (#162048)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 8 10:33:29 PDT 2025
Author: Michael Buch
Date: 2025-10-08T17:33:25Z
New Revision: 030d8e66498d6818300b1a8678861a016bd37e10
URL: https://github.com/llvm/llvm-project/commit/030d8e66498d6818300b1a8678861a016bd37e10
DIFF: https://github.com/llvm/llvm-project/commit/030d8e66498d6818300b1a8678861a016bd37e10.diff
LOG: [llvm][Dwarf] Add LanguageDescription API that accounts for version (#162048)
Currently `llvm::dwarf::LanguageDescription` returns a stringified
`DW_LNAME`. It would be useful to have an API that returns the language
name for a particular `DW_LNAME_`/version pair. LLDB's use case is that
it wants to emit diagnostics with human readable descriptions of the
language we got from debug-info (see
https://github.com/llvm/llvm-project/pull/161688). We could maintain a
side-table in LLDB but thought this might be generally useful and should
live next to the existing `LanguageDescription` API.
Added:
Modified:
llvm/include/llvm/BinaryFormat/Dwarf.h
llvm/lib/BinaryFormat/Dwarf.cpp
llvm/unittests/BinaryFormat/DwarfTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h
index ba74ab9515a75..815e85ddd7a92 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -500,8 +500,15 @@ toDW_LNAME(SourceLanguage language) {
return {};
}
+/// Returns a version-independent language name.
LLVM_ABI llvm::StringRef LanguageDescription(SourceLanguageName name);
+/// Returns a language name corresponding to the specified version.
+/// If the version is not recognized for the specified language, returns
+/// the version-independent name.
+LLVM_ABI llvm::StringRef LanguageDescription(SourceLanguageName Name,
+ uint32_t Version);
+
inline bool isCPlusPlus(SourceLanguage S) {
bool result = false;
// Deliberately enumerate all the language options so we get a warning when
diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp
index 9690ff9107df8..969047a8e5b5c 100644
--- a/llvm/lib/BinaryFormat/Dwarf.cpp
+++ b/llvm/lib/BinaryFormat/Dwarf.cpp
@@ -472,6 +472,117 @@ StringRef llvm::dwarf::LanguageDescription(dwarf::SourceLanguageName lname) {
return "Unknown";
}
+StringRef llvm::dwarf::LanguageDescription(dwarf::SourceLanguageName Name,
+ uint32_t Version) {
+ switch (Name) {
+ // YYYY
+ case DW_LNAME_Ada: {
+ if (Version <= 1983)
+ return "Ada 83";
+ if (Version <= 1995)
+ return "Ada 95";
+ if (Version <= 2005)
+ return "Ada 2005";
+ if (Version <= 2012)
+ return "Ada 2012";
+ } break;
+
+ case DW_LNAME_Cobol: {
+ if (Version <= 1974)
+ return "COBOL-74";
+ if (Version <= 1985)
+ return "COBOL-85";
+ } break;
+
+ case DW_LNAME_Fortran: {
+ if (Version <= 1977)
+ return "FORTRAN 77";
+ if (Version <= 1990)
+ return "FORTRAN 90";
+ if (Version <= 1995)
+ return "Fortran 95";
+ if (Version <= 2003)
+ return "Fortran 2003";
+ if (Version <= 2008)
+ return "Fortran 2008";
+ if (Version <= 2018)
+ return "Fortran 2018";
+ } break;
+
+ // YYYYMM
+ case DW_LNAME_C: {
+ if (Version == 0)
+ break;
+ if (Version <= 198912)
+ return "C89";
+ if (Version <= 199901)
+ return "C99";
+ if (Version <= 201112)
+ return "C11";
+ if (Version <= 201710)
+ return "C17";
+ } break;
+
+ case DW_LNAME_C_plus_plus: {
+ if (Version == 0)
+ break;
+ if (Version <= 199711)
+ return "C++98";
+ if (Version <= 200310)
+ return "C++03";
+ if (Version <= 201103)
+ return "C++11";
+ if (Version <= 201402)
+ return "C++14";
+ if (Version <= 201703)
+ return "C++17";
+ if (Version <= 202002)
+ return "C++20";
+ } break;
+
+ case DW_LNAME_ObjC_plus_plus:
+ case DW_LNAME_ObjC:
+ case DW_LNAME_Move:
+ case DW_LNAME_SYCL:
+ case DW_LNAME_BLISS:
+ case DW_LNAME_Crystal:
+ case DW_LNAME_D:
+ case DW_LNAME_Dylan:
+ case DW_LNAME_Go:
+ case DW_LNAME_Haskell:
+ case DW_LNAME_HLSL:
+ case DW_LNAME_Java:
+ case DW_LNAME_Julia:
+ case DW_LNAME_Kotlin:
+ case DW_LNAME_Modula2:
+ case DW_LNAME_Modula3:
+ case DW_LNAME_OCaml:
+ case DW_LNAME_OpenCL_C:
+ case DW_LNAME_Pascal:
+ case DW_LNAME_PLI:
+ case DW_LNAME_Python:
+ case DW_LNAME_RenderScript:
+ case DW_LNAME_Rust:
+ case DW_LNAME_Swift:
+ case DW_LNAME_UPC:
+ case DW_LNAME_Zig:
+ case DW_LNAME_Assembly:
+ case DW_LNAME_C_sharp:
+ case DW_LNAME_Mojo:
+ case DW_LNAME_GLSL:
+ case DW_LNAME_GLSL_ES:
+ case DW_LNAME_OpenCL_CPP:
+ case DW_LNAME_CPP_for_OpenCL:
+ case DW_LNAME_Ruby:
+ case DW_LNAME_Hylo:
+ case DW_LNAME_Metal:
+ break;
+ }
+
+ // Fallback to un-versioned name.
+ return LanguageDescription(Name);
+}
+
llvm::StringRef llvm::dwarf::SourceLanguageNameString(SourceLanguageName Lang) {
switch (Lang) {
#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
diff --git a/llvm/unittests/BinaryFormat/DwarfTest.cpp b/llvm/unittests/BinaryFormat/DwarfTest.cpp
index 1162eb709aa83..f4519f61adf85 100644
--- a/llvm/unittests/BinaryFormat/DwarfTest.cpp
+++ b/llvm/unittests/BinaryFormat/DwarfTest.cpp
@@ -254,4 +254,42 @@ TEST(DwarfTest, lname_SourceLanguageNameString) {
EXPECT_EQ(SourceLanguageNameString(DW_LNAME_##NAME), xstr(DW_LNAME_##NAME));
#include "llvm/BinaryFormat/Dwarf.def"
}
+
+TEST(DWARFDebugInfo, TestLanguageDescription_Versioned) {
+ // Tests for the llvm::dwarf::LanguageDescription API that
+ // takes a name *and* a version.
+
+ // Unknown language.
+ EXPECT_EQ(
+ llvm::dwarf::LanguageDescription(static_cast<SourceLanguageName>(0)),
+ "Unknown");
+
+ EXPECT_EQ(
+ llvm::dwarf::LanguageDescription(static_cast<SourceLanguageName>(0), 0),
+ "Unknown");
+
+ // Test that specifying an invalid version falls back to a valid language name
+ // regardless.
+ EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_ObjC, 0), "Objective C");
+ EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_Julia, 0), "Julia");
+
+ // Check some versions.
+ EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C_plus_plus, 199711),
+ "C++98");
+ EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C_plus_plus, 201402),
+ "C++14");
+
+ // Versions round up.
+ EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C_plus_plus, 201400),
+ "C++14");
+
+ // Version 0 for C and C++ is an unversioned name.
+ EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C, 0), "C (K&R and ISO)");
+ EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C_plus_plus, 0),
+ "ISO C++");
+
+ // Version 0 for other versioned languages may not be the unversioned name.
+ EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_Fortran, 0),
+ "FORTRAN 77");
+}
} // end namespace
More information about the llvm-commits
mailing list