[Mlir-commits] [mlir] [MLIR][LLVM] Support DWARF v6 source language names in DICompileUnitAttr (PR #217432)

Gibran Essa llvmlistbot at llvm.org
Thu Aug 20 12:53:50 PDT 2026


https://github.com/gibwrong updated https://github.com/llvm/llvm-project/pull/217432

>From bfdf86ddbda7998c415ab6b5f3155f1664b72cf4 Mon Sep 17 00:00:00 2001
From: Gibran Essa <gessa at nvidia.com>
Date: Fri, 14 Aug 2026 17:14:10 +0000
Subject: [PATCH] support for new dwarf lang name and version

---
 mlir/include/mlir-c/Dialect/LLVM.h            | 12 +++
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       | 69 ++++++++++++--
 .../Dialect/LLVMIR/LLVMDialectBytecode.td     | 14 ++-
 mlir/lib/CAPI/Dialect/LLVM.cpp                | 30 ++++++-
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp      | 90 +++++++++++++++++--
 mlir/lib/Target/LLVMIR/DebugImporter.cpp      | 19 ++--
 mlir/lib/Target/LLVMIR/DebugTranslation.cpp   | 14 ++-
 mlir/test/CAPI/llvm.c                         | 21 ++++-
 mlir/test/Dialect/LLVMIR/bytecode.mlir        | 11 ++-
 mlir/test/Dialect/LLVMIR/debuginfo.mlir       |  6 +-
 .../di-compile-unit-source-language.mlir      | 24 +++++
 ...valid-di-compile-unit-source-language.mlir | 31 +++++++
 mlir/test/Target/LLVMIR/Import/debug-info.ll  | 21 ++++-
 mlir/test/Target/LLVMIR/llvmir-debug.mlir     | 26 +++++-
 14 files changed, 355 insertions(+), 33 deletions(-)
 create mode 100644 mlir/test/Dialect/LLVMIR/di-compile-unit-source-language.mlir
 create mode 100644 mlir/test/Dialect/LLVMIR/invalid-di-compile-unit-source-language.mlir

diff --git a/mlir/include/mlir-c/Dialect/LLVM.h b/mlir/include/mlir-c/Dialect/LLVM.h
index 30137faaaa8d8..5c8e24bef3798 100644
--- a/mlir/include/mlir-c/Dialect/LLVM.h
+++ b/mlir/include/mlir-c/Dialect/LLVM.h
@@ -386,6 +386,18 @@ mlirLLVMDICompileUnitAttrGetWithSourceLanguageDialect(
     MlirLLVMDINameTableKind nameTableKind, MlirAttribute splitDebugFilename,
     intptr_t nImportedEntities, MlirAttribute const *importedEntities);
 
+/// Creates an LLVM DICompileUnit attribute with a DWARF v6 source language
+/// name, version, and optional source language dialect.
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirLLVMDICompileUnitAttrGetWithSourceLanguageName(
+    MlirContext ctx, MlirAttribute recId, bool isRecSelf, MlirAttribute id,
+    unsigned int sourceLanguageName, uint32_t sourceLanguageVersion,
+    unsigned int sourceLanguageDialect, MlirAttribute file,
+    MlirAttribute producer, bool isOptimized,
+    MlirLLVMDIEmissionKind emissionKind, bool isDebugInfoForProfiling,
+    MlirLLVMDINameTableKind nameTableKind, MlirAttribute splitDebugFilename,
+    intptr_t nImportedEntities, MlirAttribute const *importedEntities);
+
 MLIR_CAPI_EXPORTED MlirStringRef mlirLLVMDICompileUnitAttrGetName(void);
 
 /// Creates a LLVM DIFlags attribute.
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index a9fd24e605120..88888e5c462b9 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -360,6 +360,24 @@ def LLVM_DILanguageParameter : LLVM_DIParameter<
   "language", /*default=*/"0", "Language", /*errorCase=*/"0"
 >;
 
+def LLVM_DISourceLanguageNameParameter : AttrOrTypeParameter<
+  "unsigned", "debug info source language name"> {
+  let parser = [{ [&]() -> FailureOr<unsigned> {
+    SMLoc loc = $_parser.getCurrentLocation();
+    StringRef name;
+    if ($_parser.parseKeyword(&name))
+      return failure();
+    unsigned value = llvm::dwarf::getSourceLanguageName(name);
+    if (!value)
+      return $_parser.emitError(loc)
+        << "invalid debug info source language name: " << name;
+    return value;
+  }() }];
+  let printer = [{ $_printer << llvm::dwarf::SourceLanguageNameString(
+      static_cast<llvm::dwarf::SourceLanguageName>($_self)) }];
+  let defaultValue = "0";
+}
+
 // Source-language dialect values are defined by LLVM's
 // dwarf::LanguageDialectAttribute enum in llvm/BinaryFormat/Dwarf.h. LLVM
 // represents "no source-language dialect" as 0; the LLVM IR printer omits the
@@ -443,6 +461,30 @@ def LLVM_DIBasicTypeAttr : LLVM_Attr<"DIBasicType", "di_basic_type",
   let genMnemonicAlias = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// DISourceLanguageNameAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DISourceLanguageNameAttr : LLVM_Attr<"DISourceLanguageName",
+                                               "di_source_language_name"> {
+  let parameters = (ins
+    // An unversioned source-language name (a DW_LANG_* value). This maps to
+    // llvm::DISourceLanguageName::Name when HasVersion is false.
+    LLVM_DILanguageParameter:$language,
+    // A version-independent source-language name (a DW_LNAME_* value). This
+    // maps to llvm::DISourceLanguageName::Name when HasVersion is true.
+    LLVM_DISourceLanguageNameParameter:$name,
+    // The language-dependent version. Its presence maps to
+    // llvm::DISourceLanguageName::HasVersion and its value maps to Version.
+    OptionalParameter<"std::optional<uint32_t>">:$version,
+    // An optional target-specific source-language dialect. Zero represents no
+    // dialect, its value maps to llvm::DISourceLanguageName::Dialect.
+    LLVM_DILanguageDialectParameter:$dialect
+  );
+  let assemblyFormat = "`<` struct(params) `>`";
+  let genVerifyDecl = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // DICompileUnitAttr
 //===----------------------------------------------------------------------===//
@@ -456,8 +498,10 @@ def LLVM_DICompileUnitAttr : LLVM_Attr<"DICompileUnit", "di_compile_unit",
     OptionalParameter<"bool">:$isRecSelf,
     // DICompileUnitAttr specific parameters.
     OptionalParameter<"DistinctAttr">:$id,
-    LLVM_DILanguageParameter:$sourceLanguage,
-    LLVM_DILanguageDialectParameter:$sourceLanguageDialect,
+    // A plain DW_LANG value uses the historical inline syntax. Source language
+    // names, versions, and dialects are represented by
+    // DISourceLanguageNameAttr.
+    OptionalParameter<"DISourceLanguageNameAttr">:$sourceLanguage,
     OptionalParameter<"DIFileAttr">:$file,
     OptionalParameter<"StringAttr">:$producer,
     OptionalParameter<"bool">:$isOptimized,
@@ -478,8 +522,11 @@ def LLVM_DICompileUnitAttr : LLVM_Attr<"DICompileUnit", "di_compile_unit",
       CArg<"StringAttr", "{}">:$splitDebugFilename,
       CArg<"ArrayRef<DINodeAttr>", "{}">:$importedEntities
     ), [{
+      auto language = DISourceLanguageNameAttr::get(
+          id.getContext(), sourceLanguage, /*name=*/0,
+          /*version=*/std::nullopt, sourceLanguageDialect);
       return $_get(id.getContext(), /*recId=*/nullptr, /*isRecSelf=*/false, id,
-                   sourceLanguage, sourceLanguageDialect, file, producer,
+                   language, file, producer,
                    isOptimized, emissionKind, isDebugInfoForProfiling,
                    nameTableKind, splitDebugFilename, importedEntities);
     }]>,
@@ -492,13 +539,25 @@ def LLVM_DICompileUnitAttr : LLVM_Attr<"DICompileUnit", "di_compile_unit",
       CArg<"StringAttr", "{}">:$splitDebugFilename,
       CArg<"ArrayRef<DINodeAttr>", "{}">:$importedEntities
     ), [{
+      auto language = DISourceLanguageNameAttr::get(
+          id.getContext(), sourceLanguage, /*name=*/0,
+          /*version=*/std::nullopt, /*dialect=*/0);
       return $_get(id.getContext(), /*recId=*/nullptr, /*isRecSelf=*/false, id,
-                   sourceLanguage, /*sourceLanguageDialect=*/0, file, producer,
+                   language, file, producer,
                    isOptimized, emissionKind, isDebugInfoForProfiling,
                    nameTableKind, splitDebugFilename, importedEntities);
     }]>
   ];
-  let assemblyFormat = "`<` struct(params) `>`";
+  let assemblyFormat = [{
+    `<` struct(
+      $recId, $isRecSelf, $id,
+      custom<SourceLanguage>($sourceLanguage),
+      $file, $producer, $isOptimized, $emissionKind,
+      $isDebugInfoForProfiling, $nameTableKind, $splitDebugFilename,
+      $importedEntities
+    ) `>`
+  }];
+  let genVerifyDecl = 1;
   let extraClassDeclaration = [{
     /// Requirements of DIRecursiveTypeAttrInterface.
     /// @{
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
index fe63c106a3e7c..15d81c4449ac5 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
@@ -124,6 +124,17 @@ def DISubroutineTypeAttr : DialectAttribute<(attr
   OptionalArrayRef<"DITypeAttr">:$types
 )>;
 
+//===----------------------------------------------------------------------===//
+// DISourceLanguageNameAttr
+//===----------------------------------------------------------------------===//
+
+def DISourceLanguageNameAttr : DialectAttribute<(attr
+  VarInt:$language,
+  VarInt:$name,
+  OptionalInt<"uint32_t">:$version,
+  VarInt:$dialect
+)>;
+
 //===----------------------------------------------------------------------===//
 // DICompileUnitAttr
 //===----------------------------------------------------------------------===//
@@ -132,8 +143,7 @@ def DICompileUnitAttr : DialectAttribute<(attr
   OptionalAttribute<"DistinctAttr">:$recId,
   Bool:$isRecSelf,
   OptionalAttribute<"DistinctAttr">:$id,
-  VarInt:$sourceLanguage,
-  VarInt:$sourceLanguageDialect,
+  OptionalAttribute<"DISourceLanguageNameAttr">:$sourceLanguage,
   OptionalAttribute<"DIFileAttr">:$file,
   OptionalAttribute<"StringAttr">:$producer,
   Bool:$isOptimized,
diff --git a/mlir/lib/CAPI/Dialect/LLVM.cpp b/mlir/lib/CAPI/Dialect/LLVM.cpp
index 9885ae7b2b77f..c9a0cc1f15af4 100644
--- a/mlir/lib/CAPI/Dialect/LLVM.cpp
+++ b/mlir/lib/CAPI/Dialect/LLVM.cpp
@@ -372,9 +372,37 @@ MlirAttribute mlirLLVMDICompileUnitAttrGetWithSourceLanguageDialect(
     intptr_t nImportedEntities, MlirAttribute const *importedEntities) {
   SmallVector<Attribute> importsStorage;
   importsStorage.reserve(nImportedEntities);
+  auto sourceLanguageAttr = DISourceLanguageNameAttr::get(
+      unwrap(ctx), sourceLanguage, /*name=*/0, /*version=*/std::nullopt,
+      sourceLanguageDialect);
   return wrap(DICompileUnitAttr::get(
       unwrap(ctx), cast<DistinctAttr>(unwrap(recId)), isRecSelf,
-      cast<DistinctAttr>(unwrap(id)), sourceLanguage, sourceLanguageDialect,
+      cast<DistinctAttr>(unwrap(id)), sourceLanguageAttr,
+      cast<DIFileAttr>(unwrap(file)), cast<StringAttr>(unwrap(producer)),
+      isOptimized, DIEmissionKind(emissionKind), isDebugInfoForProfiling,
+      DINameTableKind(nameTableKind),
+      cast<StringAttr>(unwrap(splitDebugFilename)),
+      llvm::map_to_vector(
+          unwrapList(nImportedEntities, importedEntities, importsStorage),
+          llvm::CastTo<DINodeAttr>)));
+}
+
+MlirAttribute mlirLLVMDICompileUnitAttrGetWithSourceLanguageName(
+    MlirContext ctx, MlirAttribute recId, bool isRecSelf, MlirAttribute id,
+    unsigned int sourceLanguageName, uint32_t sourceLanguageVersion,
+    unsigned int sourceLanguageDialect, MlirAttribute file,
+    MlirAttribute producer, bool isOptimized,
+    MlirLLVMDIEmissionKind emissionKind, bool isDebugInfoForProfiling,
+    MlirLLVMDINameTableKind nameTableKind, MlirAttribute splitDebugFilename,
+    intptr_t nImportedEntities, MlirAttribute const *importedEntities) {
+  SmallVector<Attribute> importsStorage;
+  importsStorage.reserve(nImportedEntities);
+  auto sourceLanguageAttr = DISourceLanguageNameAttr::get(
+      unwrap(ctx), /*language=*/0, sourceLanguageName,
+      std::optional<uint32_t>(sourceLanguageVersion), sourceLanguageDialect);
+  return wrap(DICompileUnitAttr::get(
+      unwrap(ctx), cast<DistinctAttr>(unwrap(recId)), isRecSelf,
+      cast<DistinctAttr>(unwrap(id)), sourceLanguageAttr,
       cast<DIFileAttr>(unwrap(file)), cast<StringAttr>(unwrap(producer)),
       isOptimized, DIEmissionKind(emissionKind), isDebugInfoForProfiling,
       DINameTableKind(nameTableKind),
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 77a8b9d3846ab..b81b3121f2e18 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -21,6 +21,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -38,6 +39,17 @@ static ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
 static void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
                                ArrayRef<uint64_t> args);
 
+/// Parses a source language from either the historical inline `DW_LANG_*`
+/// syntax or a nested `DISourceLanguageNameAttr`.
+static ParseResult parseSourceLanguage(AsmParser &parser,
+                                       DISourceLanguageNameAttr &language);
+
+/// Prints an unversioned source language without a dialect using the
+/// historical inline `DW_LANG_*` syntax. All other source languages are
+/// printed as a nested `DISourceLanguageNameAttr`.
+static void printSourceLanguage(AsmPrinter &printer,
+                                DISourceLanguageNameAttr language);
+
 #include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.cpp.inc"
 #include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc"
 #define GET_ATTRDEF_CLASSES
@@ -382,6 +394,60 @@ DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
                                   {}, {}, {}, {}, {});
 }
 
+//===----------------------------------------------------------------------===//
+// DISourceLanguageNameAttr
+//===----------------------------------------------------------------------===//
+
+static ParseResult parseSourceLanguage(AsmParser &parser,
+                                       DISourceLanguageNameAttr &language) {
+  DISourceLanguageNameAttr nestedLanguage;
+  OptionalParseResult nestedResult =
+      parser.parseOptionalAttribute(nestedLanguage);
+  if (nestedResult.has_value()) {
+    if (failed(*nestedResult))
+      return failure();
+    language = nestedLanguage;
+    return success();
+  }
+
+  // If we cannot parse the full attr, try to just parse a DWARF language.
+  SMLoc loc = parser.getCurrentLocation();
+  StringRef spelling;
+  if (parser.parseKeyword(&spelling))
+    return failure();
+  if (unsigned value = llvm::dwarf::getLanguage(spelling)) {
+    language = DISourceLanguageNameAttr::get(
+        parser.getContext(), value, /*name=*/0, /*version=*/std::nullopt,
+        /*dialect=*/0);
+    return success();
+  }
+  return parser.emitError(loc)
+         << "invalid debug info source language: " << spelling;
+}
+
+static void printSourceLanguage(AsmPrinter &printer,
+                                DISourceLanguageNameAttr language) {
+  // Print only the DWARF language if the other fields are not set.
+  if (language.getLanguage() && !language.getName() && !language.getVersion() &&
+      !language.getDialect()) {
+    printer << llvm::dwarf::LanguageString(language.getLanguage());
+    return;
+  }
+  printer.printAttribute(language);
+}
+
+LogicalResult DISourceLanguageNameAttr::verify(
+    function_ref<InFlightDiagnostic()> emitError, unsigned language,
+    unsigned name, std::optional<uint32_t> version, unsigned /*dialect*/) {
+  if (static_cast<bool>(language) == static_cast<bool>(name))
+    return emitError() << "expected exactly one of language or name";
+  if (name && !version)
+    return emitError() << "DW_LNAME requires a version";
+  if (language && version)
+    return emitError() << "DW_LANG cannot have a version";
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // DICompileUnitAttr
 //===----------------------------------------------------------------------===//
@@ -389,21 +455,35 @@ DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
 DIRecursiveTypeAttrInterface DICompileUnitAttr::withRecId(DistinctAttr recId) {
   return DICompileUnitAttr::get(
       getContext(), recId, getIsRecSelf(), getId(), getSourceLanguage(),
-      getSourceLanguageDialect(), getFile(), getProducer(), getIsOptimized(),
-      getEmissionKind(), getIsDebugInfoForProfiling(), getNameTableKind(),
-      getSplitDebugFilename(), getImportedEntities());
+      getFile(), getProducer(), getIsOptimized(), getEmissionKind(),
+      getIsDebugInfoForProfiling(), getNameTableKind(), getSplitDebugFilename(),
+      getImportedEntities());
 }
 
 DIRecursiveTypeAttrInterface DICompileUnitAttr::getRecSelf(DistinctAttr recId) {
 
   return DICompileUnitAttr::get(
       recId.getContext(), recId, /*isRecSelf=*/true, /*id=*/{},
-      /*sourceLanguage=*/0u, /*sourceLanguageDialect=*/0u, /*file=*/{},
-      /*producer=*/{}, /*isOptimized=*/false, DIEmissionKind::None,
+      /*sourceLanguage=*/{},
+      /*file=*/{}, /*producer=*/{}, /*isOptimized=*/false, DIEmissionKind::None,
       /*isDebugInfoForProfiling=*/false, DINameTableKind::Default,
       /*splitDebugFilename=*/{}, /*importedEntities=*/{});
 }
 
+LogicalResult DICompileUnitAttr::verify(
+    function_ref<InFlightDiagnostic()> emitError, DistinctAttr recId,
+    bool isRecSelf, DistinctAttr id, DISourceLanguageNameAttr sourceLanguage,
+    DIFileAttr file, StringAttr producer, bool isOptimized,
+    DIEmissionKind emissionKind, bool isDebugInfoForProfiling,
+    DINameTableKind nameTableKind, StringAttr splitDebugFilename,
+    ArrayRef<DINodeAttr> importedEntities) {
+  if (isRecSelf)
+    return success();
+  if (!sourceLanguage)
+    return emitError() << "sourceLanguage must be set";
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // DISubprogramAttr
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp
index 82beb2984b043..92a8c9aad249f 100644
--- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp
@@ -65,13 +65,22 @@ DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) {
         imports.push_back(nodeAttr);
   }
   llvm::DISourceLanguageName sourceLanguage = node->getSourceLanguage();
+  DISourceLanguageNameAttr sourceLanguageAttr;
+  if (sourceLanguage.hasVersionedName()) {
+    sourceLanguageAttr = DISourceLanguageNameAttr::get(
+        context, /*language=*/0, sourceLanguage.getName(),
+        sourceLanguage.getVersion(), sourceLanguage.getDialect());
+  } else {
+    sourceLanguageAttr = DISourceLanguageNameAttr::get(
+        context, sourceLanguage.getName(), /*name=*/0,
+        /*version=*/std::nullopt, sourceLanguage.getDialect());
+  }
   return DICompileUnitAttr::get(
       context, /*recId=*/DistinctAttr{}, /*isRecSelf=*/false,
-      getOrCreateDistinctID(node), sourceLanguage.getUnversionedName(),
-      sourceLanguage.getDialect(), translate(node->getFile()),
-      getStringAttrOrNull(node->getRawProducer()), node->isOptimized(),
-      emissionKind.value(), node->isDebugInfoForProfiling(),
-      nameTableKind.value(),
+      getOrCreateDistinctID(node), sourceLanguageAttr,
+      translate(node->getFile()), getStringAttrOrNull(node->getRawProducer()),
+      node->isOptimized(), emissionKind.value(),
+      node->isDebugInfoForProfiling(), nameTableKind.value(),
       getStringAttrOrNull(node->getRawSplitDebugFilename()), imports);
 }
 
diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
index 4dc9e91b4e1c2..3ac2ccd506df3 100644
--- a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
@@ -139,11 +139,17 @@ llvm::DIBasicType *DebugTranslation::translateImpl(DIBasicTypeAttr attr) {
 }
 
 static llvm::DISourceLanguageName getSourceLanguage(DICompileUnitAttr attr) {
-  // DISourceLanguageName represents "no source-language dialect" as 0; the
-  // LLVM IR printer omits the `dialect:` field for that value.
+  DISourceLanguageNameAttr sourceLanguage = attr.getSourceLanguage();
+  // A DW_LNAME value selects the versioned source-language representation;
+  // otherwise, the value is an unversioned DW_LANG value.
+  if (sourceLanguage.getName())
+    return llvm::DISourceLanguageName(
+        static_cast<uint16_t>(sourceLanguage.getName()),
+        *sourceLanguage.getVersion(),
+        static_cast<uint16_t>(sourceLanguage.getDialect()));
   return llvm::DISourceLanguageName(
-      static_cast<uint16_t>(attr.getSourceLanguage()),
-      static_cast<uint16_t>(attr.getSourceLanguageDialect()));
+      static_cast<uint16_t>(sourceLanguage.getLanguage()),
+      static_cast<uint16_t>(sourceLanguage.getDialect()));
 }
 
 llvm::TempDICompileUnit
diff --git a/mlir/test/CAPI/llvm.c b/mlir/test/CAPI/llvm.c
index 692a846d3b3c9..554c570943396 100644
--- a/mlir/test/CAPI/llvm.c
+++ b/mlir/test/CAPI/llvm.c
@@ -280,15 +280,30 @@ static void testDebugInfoAttributes(MlirContext ctx) {
   // LLVM's dwarf::LanguageDialectAttribute enum.
   MlirAttribute compile_unit =
       mlirLLVMDICompileUnitAttrGetWithSourceLanguageDialect(
-          ctx, recId0, false, id, LLVMDWARFSourceLanguageC99,
+          ctx, recId0, false, id, /*DW_LANG_C99=*/0x000c,
           /*sourceLanguageDialect=*/1, file, foo, false,
           MlirLLVMDIEmissionKindFull, false, MlirLLVMDINameTableKindDefault,
           bar, 0, NULL);
 
-  // CHECK: #llvm.di_compile_unit<{{.*}}sourceLanguageDialect =
-  // CHECK-SAME: DW_LLVM_LANG_DIALECT_simt{{.*}}>
+  // CHECK: #llvm.di_compile_unit<{{.*}}sourceLanguage =
+  // CHECK-SAME: #llvm.di_source_language_name<language = DW_LANG_C99
+  // CHECK-SAME: dialect = DW_LLVM_LANG_DIALECT_simt>
   mlirAttributeDump(compile_unit);
 
+  // sourceLanguageName 4 is DW_LNAME_C_plus_plus.
+  MlirAttribute versioned_compile_unit =
+      mlirLLVMDICompileUnitAttrGetWithSourceLanguageName(
+          ctx, recId0, false, id, /*sourceLanguageName=*/4,
+          /*sourceLanguageVersion=*/202002,
+          /*sourceLanguageDialect=*/1, file, foo, false,
+          MlirLLVMDIEmissionKindFull, false, MlirLLVMDINameTableKindDefault,
+          bar, 0, NULL);
+
+  // CHECK: #llvm.di_compile_unit<{{.*}}sourceLanguage =
+  // CHECK-SAME: #llvm.di_source_language_name<name = DW_LNAME_C_plus_plus
+  // CHECK-SAME: version = 202002
+  mlirAttributeDump(versioned_compile_unit);
+
   // CHECK: #llvm.di_compile_unit<recId = {{.*}}, isRecSelf = true>
   mlirAttributeDump(mlirLLVMDICompileUnitAttrGetRecSelf(recId1));
 
diff --git a/mlir/test/Dialect/LLVMIR/bytecode.mlir b/mlir/test/Dialect/LLVMIR/bytecode.mlir
index 02409c8adab94..095684a5bdd93 100644
--- a/mlir/test/Dialect/LLVMIR/bytecode.mlir
+++ b/mlir/test/Dialect/LLVMIR/bytecode.mlir
@@ -8,7 +8,14 @@
 #loc6 = loc(fused<#di_subprogram>[#loc1])
 #loc7 = loc(fused<#di_subprogram>[#loc2])
 #loop_annotation = #llvm.loop_annotation<disableNonforced = false, mustProgress = true, startLoc = #loc6, endLoc = #loc7, parallelAccesses = #access_group, #access_group1>
-module {
+#versioned_file = #llvm.di_file<"test.f90" in "">
+#versioned_cu = #llvm.di_compile_unit<
+  id = distinct[7]<>, sourceLanguage = #llvm.di_source_language_name<
+    name = DW_LNAME_Fortran, version = 2018,
+    dialect = DW_LLVM_LANG_DIALECT_tile>,
+  file = #versioned_file, isOptimized = false, emissionKind = Full
+>
+module attributes {test.versioned_cu = #versioned_cu} {
   llvm.func @imp_fn() {
     llvm.return loc(#loc2)
   } loc(#loc8)
@@ -24,7 +31,7 @@ module {
 #loc3 = loc("test-path":36:3)
 #loc4 = loc("test-path":37:5)
 #loc5 = loc("test-path":39:5)
-#di_compile_unit = #llvm.di_compile_unit<id = distinct[3]<>, sourceLanguage = DW_LANG_Fortran95, sourceLanguageDialect = DW_LLVM_LANG_DIALECT_tile, file = #di_file, isOptimized = false, emissionKind = Full>
+#di_compile_unit = #llvm.di_compile_unit<id = distinct[3]<>, sourceLanguage = #llvm.di_source_language_name<language = DW_LANG_Fortran95, dialect = DW_LLVM_LANG_DIALECT_tile>, file = #di_file, isOptimized = false, emissionKind = Full>
 #di_compile_unit1 = #llvm.di_compile_unit<id = distinct[4]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, isOptimized = false, emissionKind = Full>
 #di_compile_unit2 = #llvm.di_compile_unit<id = distinct[5]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, isOptimized = false, emissionKind = Full>
 #di_module = #llvm.di_module<file = #di_file, scope = #di_compile_unit1, name = "mod1">
diff --git a/mlir/test/Dialect/LLVMIR/debuginfo.mlir b/mlir/test/Dialect/LLVMIR/debuginfo.mlir
index 020f3b3b0ee7a..15ebd664d99af 100644
--- a/mlir/test/Dialect/LLVMIR/debuginfo.mlir
+++ b/mlir/test/Dialect/LLVMIR/debuginfo.mlir
@@ -5,12 +5,12 @@
 
 // CHECK-DAG: #[[NS:.*]] = #llvm.di_namespace<name = "cu_import_ns", exportSymbols = false>
 // CHECK-DAG: #[[IE:.*]] = #llvm.di_imported_entity<tag = DW_TAG_imported_module, scope = #[[FILE]], entity = #[[NS]], file = #[[FILE]]>
-// CHECK-DAG: #[[CU:.*]] = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_C, sourceLanguageDialect = DW_LLVM_LANG_DIALECT_simt, file = #[[FILE]], producer = "MLIR", isOptimized = true, emissionKind = Full, isDebugInfoForProfiling = true, importedEntities = #[[IE]]>
+// CHECK-DAG: #[[CU:.*]] = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = #llvm.di_source_language_name<language = DW_LANG_C, dialect = DW_LLVM_LANG_DIALECT_simt>, file = #[[FILE]], producer = "MLIR", isOptimized = true, emissionKind = Full, isDebugInfoForProfiling = true, importedEntities = #[[IE]]>
 #cu_import_ns = #llvm.di_namespace<name = "cu_import_ns", exportSymbols = false>
 #cu_import_ie = #llvm.di_imported_entity<tag = DW_TAG_imported_module, scope = #file, entity = #cu_import_ns, file = #file>
 #cu = #llvm.di_compile_unit<
-  id = distinct[0]<>, sourceLanguage = DW_LANG_C,
-  sourceLanguageDialect = DW_LLVM_LANG_DIALECT_simt, file = #file,
+  id = distinct[0]<>, sourceLanguage = #llvm.di_source_language_name<
+  language = DW_LANG_C, dialect = DW_LLVM_LANG_DIALECT_simt>, file = #file,
   producer = "MLIR", isOptimized = true, emissionKind = Full,
   isDebugInfoForProfiling = true, importedEntities = #cu_import_ie
 >
diff --git a/mlir/test/Dialect/LLVMIR/di-compile-unit-source-language.mlir b/mlir/test/Dialect/LLVMIR/di-compile-unit-source-language.mlir
new file mode 100644
index 0000000000000..34d86a1aa0948
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/di-compile-unit-source-language.mlir
@@ -0,0 +1,24 @@
+// RUN: mlir-opt %s --verify-roundtrip | FileCheck %s
+
+#file = #llvm.di_file<"source.cpp" in "/test/">
+
+// A plain DW_LANG retains the historical inline syntax.
+// CHECK: sourceLanguage = DW_LANG_C_plus_plus_20
+module attributes {test.language = #llvm.di_compile_unit<
+  id = distinct[0]<>, sourceLanguage = DW_LANG_C_plus_plus_20, file = #file
+>} {}
+
+// CHECK: sourceLanguage = #llvm.di_source_language_name<name = DW_LNAME_C_plus_plus, version = 202002, dialect = DW_LLVM_LANG_DIALECT_simt>
+module attributes {test.versioned = #llvm.di_compile_unit<
+  id = distinct[1]<>, sourceLanguage = #llvm.di_source_language_name<
+    name = DW_LNAME_C_plus_plus, version = 202002,
+    dialect = DW_LLVM_LANG_DIALECT_simt>, file = #file
+>} {}
+
+// An explicitly set zero version selects a source language name.
+// CHECK: #llvm.di_compile_unit<
+// CHECK-SAME: sourceLanguage = #llvm.di_source_language_name<name = DW_LNAME_Rust, version = 0>
+module attributes {test.unversioned_name = #llvm.di_compile_unit<
+  id = distinct[2]<>, sourceLanguage = #llvm.di_source_language_name<
+    version = 0, name = DW_LNAME_Rust>, file = #file
+>} {}
diff --git a/mlir/test/Dialect/LLVMIR/invalid-di-compile-unit-source-language.mlir b/mlir/test/Dialect/LLVMIR/invalid-di-compile-unit-source-language.mlir
new file mode 100644
index 0000000000000..7a285c91e30d4
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/invalid-di-compile-unit-source-language.mlir
@@ -0,0 +1,31 @@
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics
+
+#file = #llvm.di_file<"source.cpp" in "/test/">
+
+// expected-error @+1 {{expected exactly one of language or name}}
+module attributes {test.language = #llvm.di_source_language_name<>} {}
+
+// -----
+
+// expected-error @+1 {{expected exactly one of language or name}}
+module attributes {test.language = #llvm.di_source_language_name<language = DW_LANG_C, name = DW_LNAME_C, version = 199901>} {}
+
+// -----
+
+// expected-error @+1 {{duplicate or unknown struct parameter name: sourceLanguage}}
+module attributes {test.cu = #llvm.di_compile_unit<sourceLanguage = DW_LANG_C_plus_plus_20, sourceLanguage = #llvm.di_source_language_name<name = DW_LNAME_C_plus_plus, version = 202002>, file = #file>} {}
+
+// -----
+
+// expected-error @+1 {{sourceLanguage must be set}}
+module attributes {test.cu = #llvm.di_compile_unit<>} {}
+
+// -----
+
+// expected-error @+1 {{DW_LANG cannot have a version}}
+module attributes {test.cu = #llvm.di_compile_unit<sourceLanguage = #llvm.di_source_language_name<language = DW_LANG_C, version = 202002>>} {}
+
+// -----
+
+// expected-error @+1 {{DW_LNAME requires a version}}
+module attributes {test.cu = #llvm.di_compile_unit<sourceLanguage = #llvm.di_source_language_name<name = DW_LNAME_Rust>>} {}
diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll
index f00fd792e77fa..5d222ad08f91e 100644
--- a/mlir/test/Target/LLVMIR/Import/debug-info.ll
+++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll
@@ -1050,7 +1050,7 @@ define void @fn_with_static_local() !dbg !3 {
 ; // -----
 
 ; CHECK-DAG: #[[DIALECT_FILE:.+]] = #llvm.di_file<"dialect.ll" in "/">
-; CHECK-DAG: #[[DIALECT_CU:.+]] = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_C, sourceLanguageDialect = DW_LLVM_LANG_DIALECT_tile, file = #[[DIALECT_FILE]]>
+; CHECK-DAG: #[[DIALECT_CU:.+]] = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = #llvm.di_source_language_name<language = DW_LANG_C, dialect = DW_LLVM_LANG_DIALECT_tile>, file = #[[DIALECT_FILE]]>
 
 define void @fn_cu_dialect() !dbg !3 {
   ret void
@@ -1065,3 +1065,22 @@ define void @fn_cu_dialect() !dbg !3 {
 !3 = distinct !DISubprogram(name: "fn_cu_dialect", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1, type: !4)
 !4 = !DISubroutineType(types: !5)
 !5 = !{null}
+
+; // -----
+
+; CHECK-DAG: #[[LNAME_FILE:.+]] = #llvm.di_file<"language-name.cpp" in "/test/">
+; CHECK-DAG: #[[LNAME_CU:.+]] = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = #llvm.di_source_language_name<name = DW_LNAME_C_plus_plus, version = 202002, dialect = DW_LLVM_LANG_DIALECT_simt>, file = #[[LNAME_FILE]]>
+
+define void @fn_cu_source_language_name() !dbg !3 {
+  ret void
+}
+
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = distinct !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202002, file: !2, dialect: DW_LLVM_LANG_DIALECT_simt)
+!2 = !DIFile(filename: "language-name.cpp", directory: "/test/")
+!3 = distinct !DISubprogram(name: "fn_cu_source_language_name", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1, type: !4)
+!4 = !DISubroutineType(types: !5)
+!5 = !{null}
diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir
index 6628b2882a26c..27858cc008956 100644
--- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir
@@ -872,8 +872,8 @@ llvm.func @fn_cu_import_cycle() {
 
 #file = #llvm.di_file<"dialect.mlir" in "/test/">
 #cu = #llvm.di_compile_unit<
-  id = distinct[0]<>, sourceLanguage = DW_LANG_C,
-  sourceLanguageDialect = DW_LLVM_LANG_DIALECT_simt, file = #file,
+  id = distinct[0]<>, sourceLanguage = #llvm.di_source_language_name<
+    language = DW_LANG_C, dialect = DW_LLVM_LANG_DIALECT_simt>, file = #file,
   isOptimized = false, emissionKind = Full
 >
 #sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
@@ -892,6 +892,28 @@ llvm.func @fn_cu_dialect() {
 
 // -----
 
+#file = #llvm.di_file<"language-name.cpp" in "/test/">
+#cu = #llvm.di_compile_unit<
+  id = distinct[0]<>, sourceLanguage = #llvm.di_source_language_name<
+    name = DW_LNAME_C_plus_plus, version = 202002,
+    dialect = DW_LLVM_LANG_DIALECT_simt>, file = #file,
+  isOptimized = false, emissionKind = Full
+>
+#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
+#sp = #llvm.di_subprogram<
+  compileUnit = #cu, scope = #file, name = "fn_cu_source_language_name",
+  file = #file, line = 1, scopeLine = 1, subprogramFlags = Definition,
+  type = #sp_ty
+>
+
+// CHECK-LABEL: define void @fn_cu_source_language_name()
+// CHECK-DAG: ![[LNAME_CU:[0-9]+]] = distinct !DICompileUnit(sourceLanguageName: DW_LNAME_C_plus_plus, sourceLanguageVersion: 202002, file: !{{[0-9]+}}, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, dialect: DW_LLVM_LANG_DIALECT_simt)
+llvm.func @fn_cu_source_language_name() {
+  llvm.return
+} loc(fused<#sp>["language-name.cpp":1:1])
+
+// -----
+
 #di_file  = #llvm.di_file<"foo.mlir" in "/tmp">
 #di_cu    = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_C, file = #di_file, isOptimized = false, emissionKind = Full>
 #di_uint8 = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "uint8", sizeInBits = 8, encoding = DW_ATE_unsigned>



More information about the Mlir-commits mailing list