Skip to content

Conversation

@Michael137
Copy link
Member

Depends on:

In preparation to emit DWARFv6's DW_AT_language_version.

@Michael137 Michael137 force-pushed the llvm/dwarf-language-attrs-2-part-9 branch 2 times, most recently from 2cf20c8 to dc6391f Compare October 11, 2025 12:39
@Michael137 Michael137 force-pushed the llvm/dwarf-language-attrs-2-part-9 branch from dc6391f to 2a2bd98 Compare October 11, 2025 12:44
@Michael137 Michael137 marked this pull request as ready for review October 13, 2025 08:17
@llvmbot
Copy link
Member

llvmbot commented Oct 13, 2025

@llvm/pr-subscribers-llvm-ir

Author: Michael Buch (Michael137)

Changes

Depends on:

In preparation to emit DWARFv6's DW_AT_language_version.


Full diff: https://github.com/llvm/llvm-project/pull/162632.diff

6 Files Affected:

  • (modified) llvm/lib/AsmParser/LLParser.cpp (+7-1)
  • (modified) llvm/lib/Bitcode/Reader/MetadataLoader.cpp (+4-2)
  • (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+1)
  • (modified) llvm/lib/IR/AsmWriter.cpp (+8-3)
  • (added) llvm/test/Assembler/dicompileunit-invalid-language-version.ll (+25)
  • (added) llvm/test/Bitcode/dwarf-source-language-version.ll (+17)
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 380b19296a3c4..bb9f8442610d8 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5865,6 +5865,7 @@ bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) {
   REQUIRED(file, MDField, (/* AllowNull */ false));                            \
   OPTIONAL(language, DwarfLangField, );                                        \
   OPTIONAL(sourceLanguageName, DwarfSourceLangNameField, );                    \
+  OPTIONAL(sourceLanguageVersion, MDUnsignedField, (0, UINT32_MAX));           \
   OPTIONAL(producer, MDStringField, );                                         \
   OPTIONAL(isOptimized, MDBoolField, );                                        \
   OPTIONAL(flags, MDStringField, );                                            \
@@ -5894,10 +5895,15 @@ bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) {
     return error(Loc, "can only specify one of 'language' and "
                       "'sourceLanguageName' on !DICompileUnit");
 
+  if (sourceLanguageVersion.Seen && !sourceLanguageName.Seen)
+    return error(Loc, "'sourceLanguageVersion' requires an associated "
+                      "'sourceLanguageName' on !DICompileUnit");
+
   Result = DICompileUnit::getDistinct(
       Context,
       language.Seen ? DISourceLanguageName(language.Val)
-                    : DISourceLanguageName(sourceLanguageName.Val, 0),
+                    : DISourceLanguageName(sourceLanguageName.Val,
+                                           sourceLanguageVersion.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,
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index cdcf7a80ffac7..ed0443f599a44 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1860,7 +1860,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     break;
   }
   case bitc::METADATA_COMPILE_UNIT: {
-    if (Record.size() < 14 || Record.size() > 22)
+    if (Record.size() < 14 || Record.size() > 23)
       return error("Invalid record");
 
     // Ignore Record[0], which indicates whether this compile unit is
@@ -1869,11 +1869,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
 
     const auto LangVersionMask = (uint64_t(1) << 63);
     const bool HasVersionedLanguage = Record[1] & LangVersionMask;
+    const uint32_t LanguageVersion = Record.size() > 22 ? Record[22] : 0;
 
     auto *CU = DICompileUnit::getDistinct(
         Context,
         HasVersionedLanguage
-            ? DISourceLanguageName(Record[1] & ~LangVersionMask, 0)
+            ? DISourceLanguageName(Record[1] & ~LangVersionMask,
+                                   LanguageVersion)
             : DISourceLanguageName(Record[1]),
         getMDOrNull(Record[2]), getMDString(Record[3]), Record[4],
         getMDString(Record[5]), Record[6], getMDString(Record[7]), Record[8],
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 54e916e2dcfe1..8ff3aa9817571 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2142,6 +2142,7 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
   Record.push_back(N->getRangesBaseAddress());
   Record.push_back(VE.getMetadataOrNullID(N->getRawSysRoot()));
   Record.push_back(VE.getMetadataOrNullID(N->getRawSDK()));
+  Record.push_back(Lang.hasVersionedName() ? Lang.getVersion() : 0);
 
   Stream.EmitRecord(bitc::METADATA_COMPILE_UNIT, Record, Abbrev);
   Record.clear();
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 2430d988ddb04..3908a78f48412 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2374,16 +2374,21 @@ static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N,
   Out << "!DICompileUnit(";
   MDFieldPrinter Printer(Out, WriterCtx);
 
-  auto Lang = N->getSourceLanguage();
-  if (Lang.hasVersionedName())
+  DISourceLanguageName Lang = N->getSourceLanguage();
+
+  if (Lang.hasVersionedName()) {
     Printer.printDwarfEnum(
         "sourceLanguageName",
         static_cast<llvm::dwarf::SourceLanguageName>(Lang.getName()),
         dwarf::SourceLanguageNameString,
         /* ShouldSkipZero */ false);
-  else
+
+    Printer.printInt("sourceLanguageVersion", Lang.getVersion(),
+                     /*ShouldSkipZero=*/true);
+  } else {
     Printer.printDwarfEnum("language", Lang.getName(), dwarf::LanguageString,
                            /* ShouldSkipZero */ false);
+  }
 
   Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false);
   Printer.printString("producer", N->getProducer());
diff --git a/llvm/test/Assembler/dicompileunit-invalid-language-version.ll b/llvm/test/Assembler/dicompileunit-invalid-language-version.ll
new file mode 100644
index 0000000000000..b3794ac749f60
--- /dev/null
+++ b/llvm/test/Assembler/dicompileunit-invalid-language-version.ll
@@ -0,0 +1,25 @@
+; RUN: split-file %s %t
+; RUN: not llvm-as < %t/dw_lang_with_version.ll -disable-output 2>&1 | FileCheck %s --check-prefix=WRONG-ATTR
+; RUN: not llvm-as < %t/overflow.ll -disable-output 2>&1 | FileCheck %s --check-prefix=OVERFLOW
+; RUN: not llvm-as < %t/version_without_name.ll -disable-output 2>&1 | FileCheck %s --check-prefix=NO-NAME
+; RUN: not llvm-as < %t/negative.ll -disable-output 2>&1 | FileCheck %s --check-prefix=NEGATIVE
+
+; WRONG-ATTR: error: 'sourceLanguageVersion' requires an associated 'sourceLanguageName' on !DICompileUnit
+; OVERFLOW: error: value for 'sourceLanguageVersion' too large, limit is 4294967295
+; NEGATIVE: error: expected unsigned integer
+; NO-NAME: error: missing one of 'language' or 'sourceLanguageName', required for !DICompileUnit
+
+;--- dw_lang_with_version.ll
+!0 = distinct !DICompileUnit(language: DW_LANG_C, sourceLanguageVersion: 1,
+                             file: !DIFile(filename: "", directory: ""))
+
+;--- overflow.ll
+!0 = distinct !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: 4294967298)
+
+;--- negative.ll
+!0 = distinct !DICompileUnit(sourceLanguageName: DW_LNAME_C, sourceLanguageVersion: -1,
+                             file: !DIFile(filename: "", directory: ""))
+
+;--- version_without_name.ll
+!0 = distinct !DICompileUnit(sourceLanguageVersion: 1,
+                             file: !DIFile(filename: "", directory: ""))
diff --git a/llvm/test/Bitcode/dwarf-source-language-version.ll b/llvm/test/Bitcode/dwarf-source-language-version.ll
new file mode 100644
index 0000000000000..311afd5a99afe
--- /dev/null
+++ b/llvm/test/Bitcode/dwarf-source-language-version.ll
@@ -0,0 +1,17 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s --implicit-check-not "sourceLanguageVersion: 0"
+
+; CHECK: sourceLanguageVersion: 120
+
+source_filename = "cu.cpp"
+target triple = "arm64-apple-macosx"
+
+!llvm.dbg.cu = !{!0, !5}
+!llvm.module.flags = !{!3, !4}
+
+!0 = distinct !DICompileUnit(sourceLanguageName: DW_LNAME_ObjC_plus_plus, sourceLanguageVersion: 120, file: !1, producer: "handwritten", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
+!1 = !DIFile(filename: "cu.cpp", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 5}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = distinct !DICompileUnit(sourceLanguageName: DW_LNAME_ObjC_plus_plus, sourceLanguageVersion: 0, file: !6, producer: "handwritten", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
+!6 = !DIFile(filename: "cu2.cpp", directory: "/tmp")

Copy link
Collaborator

@adrian-prantl adrian-prantl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you confirm that there is a .bc file checked in with RecordSize == 22 that tests the upgrade code?

@Michael137
Copy link
Member Author

Can you confirm that there is a .bc file checked in with RecordSize == 22 that tests the upgrade code?

There probably isn't. Do we have raw bitcode files that test the upgrade code for other metadata? Happy to add one if checking in bitcode is fine

@adrian-prantl
Copy link
Collaborator

ls llvm/test/Bitcode/*upgrade*

@Michael137
Copy link
Member Author

ls llvm/test/Bitcode/*upgrade*

Added. Turns out there were a couple already there that exercise this upgrade codepath, but I added a dedicated test just in case.

@Michael137
Copy link
Member Author

Failing tests in CI is a LLDB-DAP test. Unrelated

@Michael137 Michael137 merged commit cf1cdde into llvm:main Oct 15, 2025
10 checks passed
@Michael137 Michael137 deleted the llvm/dwarf-language-attrs-2-part-9 branch October 15, 2025 15:52
@Michael137 Michael137 changed the title [llvm][DebugInfo] [llvm][DebugInfo] Add 'sourceLanguageVersion' field support to DICompileUnit [llvm][DebugInfo] Add 'sourceLanguageVersion' field support to DICompileUnit Oct 15, 2025
Michael137 added a commit that referenced this pull request Oct 16, 2025
…163208)

Depends on:
* #163348
* #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).
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Oct 16, 2025
… 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).
Michael137 added a commit that referenced this pull request Oct 17, 2025
…63147)

Depends on:
* #162632

Emit `DW_AT_language_version` (new in DWARFv6) if DICompileUnit has a
`sourceLanguageVersion` field. Omit it if it has the default value of
`0` (since it's the default lower bound of any language without a
version scheme).
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Oct 17, 2025
…version (#163147)

Depends on:
* llvm/llvm-project#162632

Emit `DW_AT_language_version` (new in DWARFv6) if DICompileUnit has a
`sourceLanguageVersion` field. Omit it if it has the default value of
`0` (since it's the default lower bound of any language without a
version scheme).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants