Skip to content

[MLIR][DLTI] Add mangling style #125875

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 5, 2025
Merged

[MLIR][DLTI] Add mangling style #125875

merged 3 commits into from
Mar 5, 2025

Conversation

ghehg
Copy link
Contributor

@ghehg ghehg commented Feb 5, 2025

Add mangling style as a spec entry to datalayout, and implemented importing and exporting LLVM IR to MLIR (LLVM dialect).
Its represented as string as the scope of this PR is to preserve info from LLVM IR, so client in MLIR still need to map deduce the meaning of the string, like "e" means ELF, "o" for Mach-O, etc.

it addresses one of issues mentioned in this issue

@llvmbot
Copy link
Member

llvmbot commented Feb 5, 2025

@llvm/pr-subscribers-mlir-dlti

Author: Guojin (ghehg)

Changes

Add mangling style as a spec entry to datalayout, and implemented importing and exporting LLVM IR to MLIR (LLVM dialect).
Its represented as string as the scope of this PR is to preserve info from LLVM IR, so client in MLIR still need to map deduce the meaning of the string, like "e" means ELF, "o" for Mach-O, etc.


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

14 Files Affected:

  • (modified) mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td (+3)
  • (modified) mlir/include/mlir/Dialect/DLTI/DLTIBase.td (+3)
  • (modified) mlir/include/mlir/Interfaces/DataLayoutInterfaces.h (+9)
  • (modified) mlir/include/mlir/Interfaces/DataLayoutInterfaces.td (+18)
  • (modified) mlir/lib/Dialect/DLTI/DLTI.cpp (+8-1)
  • (modified) mlir/lib/Interfaces/DataLayoutInterfaces.cpp (+27)
  • (modified) mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp (+22)
  • (modified) mlir/lib/Target/LLVMIR/DataLayoutImporter.h (+4)
  • (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+5)
  • (modified) mlir/test/Target/LLVMIR/Import/data-layout.ll (+1)
  • (modified) mlir/test/Target/LLVMIR/Import/import-failure.ll (+5)
  • (modified) mlir/test/Target/LLVMIR/data-layout.mlir (+2)
  • (modified) mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp (+5)
  • (modified) mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp (+4)
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
index d54b3191eed7e66..9bede41a83374e4 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
@@ -77,6 +77,9 @@ def DLTI_DataLayoutSpecAttr :
     /// Returns the alloca memory space identifier.
     StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const;
 
+    /// Returns the mangling style identifier.
+    StringAttr getManglingStyleIdentifier(MLIRContext *context) const;
+
     /// Returns the program memory space identifier.
     StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const;
 
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
index f84149c43e0fcdf..b1f54c608e03eeb 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
@@ -49,6 +49,9 @@ def DLTI_Dialect : Dialect {
     constexpr const static ::llvm::StringLiteral
     kDataLayoutEndiannessLittle = "little";
 
+    constexpr const static ::llvm::StringLiteral
+    kDataLayoutManglingStyleKey = "dlti.mangling_style";
+
     constexpr const static ::llvm::StringLiteral
     kDataLayoutAllocaMemorySpaceKey = "dlti.alloca_memory_space";
     
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
index 7a7b659724f860b..33fadf842cef1b0 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
@@ -78,6 +78,10 @@ Attribute getDefaultEndianness(DataLayoutEntryInterface entry);
 /// DataLayoutInterface if specified, otherwise returns the default.
 Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry);
 
+/// Default handler for mangling style request. Dispatches to the
+/// DataLayoutInterface if specified, otherwise returns the default.
+Attribute getDefaultManglingStyle(DataLayoutEntryInterface entry);
+
 /// Default handler for program memory space request. Dispatches to the
 /// DataLayoutInterface if specified, otherwise returns the default.
 Attribute getDefaultProgramMemorySpace(DataLayoutEntryInterface entry);
@@ -230,6 +234,9 @@ class DataLayout {
   /// Returns the memory space used for AllocaOps.
   Attribute getAllocaMemorySpace() const;
 
+  /// Returns the mangling style.
+  Attribute getManglingStyle() const;
+
   /// Returns the memory space used for program memory operations.
   Attribute getProgramMemorySpace() const;
 
@@ -276,6 +283,8 @@ class DataLayout {
 
   /// Cache for the endianness.
   mutable std::optional<Attribute> endianness;
+  /// Cache for the mangling style.
+  mutable std::optional<Attribute> manglingStyle;
   /// Cache for alloca, global, and program memory spaces.
   mutable std::optional<Attribute> allocaMemorySpace;
   mutable std::optional<Attribute> programMemorySpace;
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
index 0d09b92928fe336..8626fb0709a240c 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
@@ -153,6 +153,12 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface", [DLTIQuer
       /*methodName=*/"getGlobalMemorySpaceIdentifier",
       /*args=*/(ins "::mlir::MLIRContext *":$context)
     >,
+    InterfaceMethod<
+      /*description=*/"Returns the mangling style identifier.",
+      /*retTy=*/"::mlir::StringAttr",
+      /*methodName=*/"getManglingStyleIdentifier",
+      /*args=*/(ins "::mlir::MLIRContext *":$context)
+    >,
     InterfaceMethod<
       /*description=*/"Returns the stack alignment identifier.",
       /*retTy=*/"::mlir::StringAttr",
@@ -481,6 +487,18 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
         return ::mlir::detail::getDefaultAllocaMemorySpace(entry);
       }]
     >,
+    StaticInterfaceMethod<
+      /*description=*/"Returns the mangling style computed "
+                      "using the relevant entries. The data layout object "
+                      "can be used for recursive queries.",
+      /*retTy=*/"::mlir::Attribute",
+      /*methodName=*/"getManglingStyle",
+      /*args=*/(ins "::mlir::DataLayoutEntryInterface":$entry),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{
+        return ::mlir::detail::getDefaultManglingStyle(entry);
+      }]
+    >,
     StaticInterfaceMethod<
       /*description=*/"Returns the memory space used by the ABI computed "
                       "using the relevant entries. The data layout object "
diff --git a/mlir/lib/Dialect/DLTI/DLTI.cpp b/mlir/lib/Dialect/DLTI/DLTI.cpp
index 2510e774f2b2aa1..fcb76eb34d0b7ba 100644
--- a/mlir/lib/Dialect/DLTI/DLTI.cpp
+++ b/mlir/lib/Dialect/DLTI/DLTI.cpp
@@ -397,6 +397,12 @@ DataLayoutSpecAttr::getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
       DLTIDialect::kDataLayoutGlobalMemorySpaceKey);
 }
 
+StringAttr
+DataLayoutSpecAttr::getManglingStyleIdentifier(MLIRContext *context) const {
+  return Builder(context).getStringAttr(
+      DLTIDialect::kDataLayoutManglingStyleKey);
+}
+
 StringAttr
 DataLayoutSpecAttr::getStackAlignmentIdentifier(MLIRContext *context) const {
   return Builder(context).getStringAttr(
@@ -589,7 +595,8 @@ class TargetDataLayoutInterface : public DataLayoutDialectInterface {
     if (entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey ||
         entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||
         entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||
-        entryName == DLTIDialect::kDataLayoutStackAlignmentKey)
+        entryName == DLTIDialect::kDataLayoutStackAlignmentKey ||
+        entryName == DLTIDialect::kDataLayoutManglingStyleKey)
       return success();
     return emitError(loc) << "unknown data layout entry name: " << entryName;
   }
diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
index 049d7f123cec8f3..93f91bdc451f982 100644
--- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
+++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
@@ -258,6 +258,17 @@ mlir::detail::getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry) {
   return entry.getValue();
 }
 
+// Returns the mangling style if specified in the given entry.
+// If the entry is empty, an empty attribute is returned.
+Attribute
+mlir::detail::getDefaultManglingStyle(DataLayoutEntryInterface entry) {
+  if (entry == DataLayoutEntryInterface()) {
+    return Attribute();
+  }
+
+  return entry.getValue();
+}
+
 // Returns the memory space used for the program memory space.  if
 // specified in the given entry. If the entry is empty the default
 // memory space represented by an empty attribute is returned.
@@ -612,6 +623,22 @@ mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const {
   return *allocaMemorySpace;
 }
 
+mlir::Attribute mlir::DataLayout::getManglingStyle() const {
+  checkValid();
+  if (manglingStyle)
+    return *manglingStyle;
+  DataLayoutEntryInterface entry;
+  if (originalLayout)
+    entry = originalLayout.getSpecForIdentifier(
+        originalLayout.getManglingStyleIdentifier(originalLayout.getContext()));
+
+  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
+    manglingStyle = iface.getManglingStyle(entry);
+  else
+    manglingStyle = detail::getDefaultManglingStyle(entry);
+  return *manglingStyle;
+}
+
 mlir::Attribute mlir::DataLayout::getProgramMemorySpace() const {
   checkValid();
   if (programMemorySpace)
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
index 35fdbc0be22c31e..b79ee902ff29f6c 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
@@ -163,6 +163,21 @@ DataLayoutImporter::tryToEmplaceEndiannessEntry(StringRef endianness,
   return success();
 }
 
+LogicalResult DataLayoutImporter::tryToEmplaceManglingStyleEntry(
+    StringRef token, llvm::StringLiteral manglingKey) {
+  auto key = StringAttr::get(context, manglingKey);
+  if (keyEntries.count(key))
+    return success();
+
+  token.consume_front(":");
+  if (token.empty())
+    return failure();
+
+  keyEntries.try_emplace(
+      key, DataLayoutEntryAttr::get(key, StringAttr::get(context, token)));
+  return success();
+}
+
 LogicalResult
 DataLayoutImporter::tryToEmplaceAddrSpaceEntry(StringRef token,
                                                llvm::StringLiteral spaceKey) {
@@ -254,6 +269,13 @@ void DataLayoutImporter::translateDataLayout(
         return;
       continue;
     }
+    // Parse the mangling style.
+    if (*prefix == "m") {
+      if (failed(tryToEmplaceManglingStyleEntry(
+              token, DLTIDialect::kDataLayoutManglingStyleKey)))
+        return;
+      continue;
+    }
     // Parse the global address space.
     if (*prefix == "G") {
       if (failed(tryToEmplaceAddrSpaceEntry(
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
index 59b60acd24be20f..a66402065cb1051 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
@@ -100,6 +100,10 @@ class DataLayoutImporter {
   LogicalResult tryToEmplaceAddrSpaceEntry(StringRef token,
                                            llvm::StringLiteral spaceKey);
 
+  /// Adds an mangling style entry if there is none yet.
+  LogicalResult tryToEmplaceManglingStyleEntry(StringRef token,
+                                               llvm::StringLiteral manglingKey);
+
   /// Adds a stack alignment entry if there is none yet.
   LogicalResult tryToEmplaceStackAlignmentEntry(StringRef token);
 
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 4367100e3aca682..7f4b9fd3e0e3efa 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -198,6 +198,11 @@ translateDataLayout(DataLayoutSpecInterface attribute,
       layoutStream << "-" << (isLittleEndian ? "e" : "E");
       continue;
     }
+    if (key.getValue() == DLTIDialect::kDataLayoutManglingStyleKey) {
+      auto value = cast<StringAttr>(entry.getValue());
+      layoutStream << "-m:" << value.getValue();
+      continue;
+    }
     if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
       auto value = cast<IntegerAttr>(entry.getValue());
       uint64_t space = value.getValue().getZExtValue();
diff --git a/mlir/test/Target/LLVMIR/Import/data-layout.ll b/mlir/test/Target/LLVMIR/Import/data-layout.ll
index c397053585e3c99..b21043718e19e5e 100644
--- a/mlir/test/Target/LLVMIR/Import/data-layout.ll
+++ b/mlir/test/Target/LLVMIR/Import/data-layout.ll
@@ -29,6 +29,7 @@ target datalayout = ""
 ; CHECK-DAG:   !llvm.ptr<271> = dense<32> : vector<4xi64>
 ; CHECK-DAG:   !llvm.ptr<272> = dense<64> : vector<4xi64>
 ; CHECK-DAG:   "dlti.stack_alignment" = 128 : i64
+; CHECK-DAG:   "dlti.mangling_style" = "e"
 target datalayout = "e-m:e-p270:32:64-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 
 ; // -----
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index d929a5928476223..80656493a99eb76 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -354,6 +354,11 @@ declare void @llvm.experimental.noalias.scope.decl(metadata)
 ; CHECK-SAME: warning: unhandled data layout token: ni:42
 target datalayout = "e-ni:42-i64:64"
 
+; // -----
+; CHECK:      import-failure.ll
+; CHECK-SAME: malformed specification, must be of the form "m:<mangling>"
+target datalayout = "e-m-i64:64"
+
 ; // -----
 
 ; CHECK:      <unknown>
diff --git a/mlir/test/Target/LLVMIR/data-layout.mlir b/mlir/test/Target/LLVMIR/data-layout.mlir
index 881d6727e2a17a1..c8aa7ed14b73fe8 100644
--- a/mlir/test/Target/LLVMIR/data-layout.mlir
+++ b/mlir/test/Target/LLVMIR/data-layout.mlir
@@ -4,6 +4,7 @@
 // CHECK: E-
 // CHECK: A4-
 // CHECK: S128-
+// CHECK: m:e-
 // CHECK: i64:64:128
 // CHECK: f80:128:256
 // CHECK: p0:32:64:128:32
@@ -12,6 +13,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<
 #dlti.dl_entry<"dlti.endianness", "big">,
 #dlti.dl_entry<"dlti.alloca_memory_space", 4 : ui32>,
 #dlti.dl_entry<"dlti.stack_alignment", 128 : i32>,
+#dlti.dl_entry<"dlti.mangling_style", "e">,
 #dlti.dl_entry<index, 64>,
 #dlti.dl_entry<i64, dense<[64,128]> : vector<2xi64>>,
 #dlti.dl_entry<f80, dense<[128,256]> : vector<2xi64>>,
diff --git a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
index 56f309f150ca5d3..21c635023d5915b 100644
--- a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
+++ b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
@@ -43,6 +43,7 @@ struct TestDataLayoutQuery
       uint64_t index = layout.getTypeIndexBitwidth(op.getType()).value_or(0);
       Attribute endianness = layout.getEndianness();
       Attribute allocaMemorySpace = layout.getAllocaMemorySpace();
+      Attribute manglingStyle = layout.getManglingStyle();
       Attribute programMemorySpace = layout.getProgramMemorySpace();
       Attribute globalMemorySpace = layout.getGlobalMemorySpace();
       uint64_t stackAlignment = layout.getStackAlignment();
@@ -72,6 +73,10 @@ struct TestDataLayoutQuery
                                 allocaMemorySpace == Attribute()
                                     ? builder.getUI32IntegerAttr(0)
                                     : allocaMemorySpace),
+           builder.getNamedAttr("mangling_style",
+                                manglingStyle == Attribute()
+                                    ? builder.getStringAttr("")
+                                    : manglingStyle),
            builder.getNamedAttr("program_memory_space",
                                 programMemorySpace == Attribute()
                                     ? builder.getUI32IntegerAttr(0)
diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
index db294b8b040e9da..8815190daf55a20 100644
--- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
+++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
@@ -25,6 +25,7 @@ constexpr static llvm::StringLiteral kAttrName = "dltest.layout";
 constexpr static llvm::StringLiteral kEndiannesKeyName = "dltest.endianness";
 constexpr static llvm::StringLiteral kAllocaKeyName =
     "dltest.alloca_memory_space";
+constexpr static llvm::StringLiteral kManglingStyleKeyName = "dltest.mangling";
 constexpr static llvm::StringLiteral kProgramKeyName =
     "dltest.program_memory_space";
 constexpr static llvm::StringLiteral kGlobalKeyName =
@@ -83,6 +84,9 @@ struct CustomDataLayoutSpec
   StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
     return Builder(context).getStringAttr(kAllocaKeyName);
   }
+  StringAttr getManglingStyleIdentifier(MLIRContext *context) const {
+    return Builder(context).getStringAttr(kManglingStyleKeyName);
+  }
   StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
     return Builder(context).getStringAttr(kProgramKeyName);
   }

@llvmbot
Copy link
Member

llvmbot commented Feb 5, 2025

@llvm/pr-subscribers-mlir

Author: Guojin (ghehg)

Changes

Add mangling style as a spec entry to datalayout, and implemented importing and exporting LLVM IR to MLIR (LLVM dialect).
Its represented as string as the scope of this PR is to preserve info from LLVM IR, so client in MLIR still need to map deduce the meaning of the string, like "e" means ELF, "o" for Mach-O, etc.


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

14 Files Affected:

  • (modified) mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td (+3)
  • (modified) mlir/include/mlir/Dialect/DLTI/DLTIBase.td (+3)
  • (modified) mlir/include/mlir/Interfaces/DataLayoutInterfaces.h (+9)
  • (modified) mlir/include/mlir/Interfaces/DataLayoutInterfaces.td (+18)
  • (modified) mlir/lib/Dialect/DLTI/DLTI.cpp (+8-1)
  • (modified) mlir/lib/Interfaces/DataLayoutInterfaces.cpp (+27)
  • (modified) mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp (+22)
  • (modified) mlir/lib/Target/LLVMIR/DataLayoutImporter.h (+4)
  • (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+5)
  • (modified) mlir/test/Target/LLVMIR/Import/data-layout.ll (+1)
  • (modified) mlir/test/Target/LLVMIR/Import/import-failure.ll (+5)
  • (modified) mlir/test/Target/LLVMIR/data-layout.mlir (+2)
  • (modified) mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp (+5)
  • (modified) mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp (+4)
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
index d54b3191eed7e6..9bede41a83374e 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
@@ -77,6 +77,9 @@ def DLTI_DataLayoutSpecAttr :
     /// Returns the alloca memory space identifier.
     StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const;
 
+    /// Returns the mangling style identifier.
+    StringAttr getManglingStyleIdentifier(MLIRContext *context) const;
+
     /// Returns the program memory space identifier.
     StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const;
 
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
index f84149c43e0fcd..b1f54c608e03ee 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
@@ -49,6 +49,9 @@ def DLTI_Dialect : Dialect {
     constexpr const static ::llvm::StringLiteral
     kDataLayoutEndiannessLittle = "little";
 
+    constexpr const static ::llvm::StringLiteral
+    kDataLayoutManglingStyleKey = "dlti.mangling_style";
+
     constexpr const static ::llvm::StringLiteral
     kDataLayoutAllocaMemorySpaceKey = "dlti.alloca_memory_space";
     
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
index 7a7b659724f860..33fadf842cef1b 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
@@ -78,6 +78,10 @@ Attribute getDefaultEndianness(DataLayoutEntryInterface entry);
 /// DataLayoutInterface if specified, otherwise returns the default.
 Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry);
 
+/// Default handler for mangling style request. Dispatches to the
+/// DataLayoutInterface if specified, otherwise returns the default.
+Attribute getDefaultManglingStyle(DataLayoutEntryInterface entry);
+
 /// Default handler for program memory space request. Dispatches to the
 /// DataLayoutInterface if specified, otherwise returns the default.
 Attribute getDefaultProgramMemorySpace(DataLayoutEntryInterface entry);
@@ -230,6 +234,9 @@ class DataLayout {
   /// Returns the memory space used for AllocaOps.
   Attribute getAllocaMemorySpace() const;
 
+  /// Returns the mangling style.
+  Attribute getManglingStyle() const;
+
   /// Returns the memory space used for program memory operations.
   Attribute getProgramMemorySpace() const;
 
@@ -276,6 +283,8 @@ class DataLayout {
 
   /// Cache for the endianness.
   mutable std::optional<Attribute> endianness;
+  /// Cache for the mangling style.
+  mutable std::optional<Attribute> manglingStyle;
   /// Cache for alloca, global, and program memory spaces.
   mutable std::optional<Attribute> allocaMemorySpace;
   mutable std::optional<Attribute> programMemorySpace;
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
index 0d09b92928fe33..8626fb0709a240 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
@@ -153,6 +153,12 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface", [DLTIQuer
       /*methodName=*/"getGlobalMemorySpaceIdentifier",
       /*args=*/(ins "::mlir::MLIRContext *":$context)
     >,
+    InterfaceMethod<
+      /*description=*/"Returns the mangling style identifier.",
+      /*retTy=*/"::mlir::StringAttr",
+      /*methodName=*/"getManglingStyleIdentifier",
+      /*args=*/(ins "::mlir::MLIRContext *":$context)
+    >,
     InterfaceMethod<
       /*description=*/"Returns the stack alignment identifier.",
       /*retTy=*/"::mlir::StringAttr",
@@ -481,6 +487,18 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
         return ::mlir::detail::getDefaultAllocaMemorySpace(entry);
       }]
     >,
+    StaticInterfaceMethod<
+      /*description=*/"Returns the mangling style computed "
+                      "using the relevant entries. The data layout object "
+                      "can be used for recursive queries.",
+      /*retTy=*/"::mlir::Attribute",
+      /*methodName=*/"getManglingStyle",
+      /*args=*/(ins "::mlir::DataLayoutEntryInterface":$entry),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{
+        return ::mlir::detail::getDefaultManglingStyle(entry);
+      }]
+    >,
     StaticInterfaceMethod<
       /*description=*/"Returns the memory space used by the ABI computed "
                       "using the relevant entries. The data layout object "
diff --git a/mlir/lib/Dialect/DLTI/DLTI.cpp b/mlir/lib/Dialect/DLTI/DLTI.cpp
index 2510e774f2b2aa..fcb76eb34d0b7b 100644
--- a/mlir/lib/Dialect/DLTI/DLTI.cpp
+++ b/mlir/lib/Dialect/DLTI/DLTI.cpp
@@ -397,6 +397,12 @@ DataLayoutSpecAttr::getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
       DLTIDialect::kDataLayoutGlobalMemorySpaceKey);
 }
 
+StringAttr
+DataLayoutSpecAttr::getManglingStyleIdentifier(MLIRContext *context) const {
+  return Builder(context).getStringAttr(
+      DLTIDialect::kDataLayoutManglingStyleKey);
+}
+
 StringAttr
 DataLayoutSpecAttr::getStackAlignmentIdentifier(MLIRContext *context) const {
   return Builder(context).getStringAttr(
@@ -589,7 +595,8 @@ class TargetDataLayoutInterface : public DataLayoutDialectInterface {
     if (entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey ||
         entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||
         entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||
-        entryName == DLTIDialect::kDataLayoutStackAlignmentKey)
+        entryName == DLTIDialect::kDataLayoutStackAlignmentKey ||
+        entryName == DLTIDialect::kDataLayoutManglingStyleKey)
       return success();
     return emitError(loc) << "unknown data layout entry name: " << entryName;
   }
diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
index 049d7f123cec8f..93f91bdc451f98 100644
--- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
+++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
@@ -258,6 +258,17 @@ mlir::detail::getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry) {
   return entry.getValue();
 }
 
+// Returns the mangling style if specified in the given entry.
+// If the entry is empty, an empty attribute is returned.
+Attribute
+mlir::detail::getDefaultManglingStyle(DataLayoutEntryInterface entry) {
+  if (entry == DataLayoutEntryInterface()) {
+    return Attribute();
+  }
+
+  return entry.getValue();
+}
+
 // Returns the memory space used for the program memory space.  if
 // specified in the given entry. If the entry is empty the default
 // memory space represented by an empty attribute is returned.
@@ -612,6 +623,22 @@ mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const {
   return *allocaMemorySpace;
 }
 
+mlir::Attribute mlir::DataLayout::getManglingStyle() const {
+  checkValid();
+  if (manglingStyle)
+    return *manglingStyle;
+  DataLayoutEntryInterface entry;
+  if (originalLayout)
+    entry = originalLayout.getSpecForIdentifier(
+        originalLayout.getManglingStyleIdentifier(originalLayout.getContext()));
+
+  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
+    manglingStyle = iface.getManglingStyle(entry);
+  else
+    manglingStyle = detail::getDefaultManglingStyle(entry);
+  return *manglingStyle;
+}
+
 mlir::Attribute mlir::DataLayout::getProgramMemorySpace() const {
   checkValid();
   if (programMemorySpace)
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
index 35fdbc0be22c31..b79ee902ff29f6 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
@@ -163,6 +163,21 @@ DataLayoutImporter::tryToEmplaceEndiannessEntry(StringRef endianness,
   return success();
 }
 
+LogicalResult DataLayoutImporter::tryToEmplaceManglingStyleEntry(
+    StringRef token, llvm::StringLiteral manglingKey) {
+  auto key = StringAttr::get(context, manglingKey);
+  if (keyEntries.count(key))
+    return success();
+
+  token.consume_front(":");
+  if (token.empty())
+    return failure();
+
+  keyEntries.try_emplace(
+      key, DataLayoutEntryAttr::get(key, StringAttr::get(context, token)));
+  return success();
+}
+
 LogicalResult
 DataLayoutImporter::tryToEmplaceAddrSpaceEntry(StringRef token,
                                                llvm::StringLiteral spaceKey) {
@@ -254,6 +269,13 @@ void DataLayoutImporter::translateDataLayout(
         return;
       continue;
     }
+    // Parse the mangling style.
+    if (*prefix == "m") {
+      if (failed(tryToEmplaceManglingStyleEntry(
+              token, DLTIDialect::kDataLayoutManglingStyleKey)))
+        return;
+      continue;
+    }
     // Parse the global address space.
     if (*prefix == "G") {
       if (failed(tryToEmplaceAddrSpaceEntry(
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
index 59b60acd24be20..a66402065cb105 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
@@ -100,6 +100,10 @@ class DataLayoutImporter {
   LogicalResult tryToEmplaceAddrSpaceEntry(StringRef token,
                                            llvm::StringLiteral spaceKey);
 
+  /// Adds an mangling style entry if there is none yet.
+  LogicalResult tryToEmplaceManglingStyleEntry(StringRef token,
+                                               llvm::StringLiteral manglingKey);
+
   /// Adds a stack alignment entry if there is none yet.
   LogicalResult tryToEmplaceStackAlignmentEntry(StringRef token);
 
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 4367100e3aca68..7f4b9fd3e0e3ef 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -198,6 +198,11 @@ translateDataLayout(DataLayoutSpecInterface attribute,
       layoutStream << "-" << (isLittleEndian ? "e" : "E");
       continue;
     }
+    if (key.getValue() == DLTIDialect::kDataLayoutManglingStyleKey) {
+      auto value = cast<StringAttr>(entry.getValue());
+      layoutStream << "-m:" << value.getValue();
+      continue;
+    }
     if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
       auto value = cast<IntegerAttr>(entry.getValue());
       uint64_t space = value.getValue().getZExtValue();
diff --git a/mlir/test/Target/LLVMIR/Import/data-layout.ll b/mlir/test/Target/LLVMIR/Import/data-layout.ll
index c397053585e3c9..b21043718e19e5 100644
--- a/mlir/test/Target/LLVMIR/Import/data-layout.ll
+++ b/mlir/test/Target/LLVMIR/Import/data-layout.ll
@@ -29,6 +29,7 @@ target datalayout = ""
 ; CHECK-DAG:   !llvm.ptr<271> = dense<32> : vector<4xi64>
 ; CHECK-DAG:   !llvm.ptr<272> = dense<64> : vector<4xi64>
 ; CHECK-DAG:   "dlti.stack_alignment" = 128 : i64
+; CHECK-DAG:   "dlti.mangling_style" = "e"
 target datalayout = "e-m:e-p270:32:64-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 
 ; // -----
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index d929a592847622..80656493a99eb7 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -354,6 +354,11 @@ declare void @llvm.experimental.noalias.scope.decl(metadata)
 ; CHECK-SAME: warning: unhandled data layout token: ni:42
 target datalayout = "e-ni:42-i64:64"
 
+; // -----
+; CHECK:      import-failure.ll
+; CHECK-SAME: malformed specification, must be of the form "m:<mangling>"
+target datalayout = "e-m-i64:64"
+
 ; // -----
 
 ; CHECK:      <unknown>
diff --git a/mlir/test/Target/LLVMIR/data-layout.mlir b/mlir/test/Target/LLVMIR/data-layout.mlir
index 881d6727e2a17a..c8aa7ed14b73fe 100644
--- a/mlir/test/Target/LLVMIR/data-layout.mlir
+++ b/mlir/test/Target/LLVMIR/data-layout.mlir
@@ -4,6 +4,7 @@
 // CHECK: E-
 // CHECK: A4-
 // CHECK: S128-
+// CHECK: m:e-
 // CHECK: i64:64:128
 // CHECK: f80:128:256
 // CHECK: p0:32:64:128:32
@@ -12,6 +13,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<
 #dlti.dl_entry<"dlti.endianness", "big">,
 #dlti.dl_entry<"dlti.alloca_memory_space", 4 : ui32>,
 #dlti.dl_entry<"dlti.stack_alignment", 128 : i32>,
+#dlti.dl_entry<"dlti.mangling_style", "e">,
 #dlti.dl_entry<index, 64>,
 #dlti.dl_entry<i64, dense<[64,128]> : vector<2xi64>>,
 #dlti.dl_entry<f80, dense<[128,256]> : vector<2xi64>>,
diff --git a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
index 56f309f150ca5d..21c635023d5915 100644
--- a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
+++ b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
@@ -43,6 +43,7 @@ struct TestDataLayoutQuery
       uint64_t index = layout.getTypeIndexBitwidth(op.getType()).value_or(0);
       Attribute endianness = layout.getEndianness();
       Attribute allocaMemorySpace = layout.getAllocaMemorySpace();
+      Attribute manglingStyle = layout.getManglingStyle();
       Attribute programMemorySpace = layout.getProgramMemorySpace();
       Attribute globalMemorySpace = layout.getGlobalMemorySpace();
       uint64_t stackAlignment = layout.getStackAlignment();
@@ -72,6 +73,10 @@ struct TestDataLayoutQuery
                                 allocaMemorySpace == Attribute()
                                     ? builder.getUI32IntegerAttr(0)
                                     : allocaMemorySpace),
+           builder.getNamedAttr("mangling_style",
+                                manglingStyle == Attribute()
+                                    ? builder.getStringAttr("")
+                                    : manglingStyle),
            builder.getNamedAttr("program_memory_space",
                                 programMemorySpace == Attribute()
                                     ? builder.getUI32IntegerAttr(0)
diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
index db294b8b040e9d..8815190daf55a2 100644
--- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
+++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
@@ -25,6 +25,7 @@ constexpr static llvm::StringLiteral kAttrName = "dltest.layout";
 constexpr static llvm::StringLiteral kEndiannesKeyName = "dltest.endianness";
 constexpr static llvm::StringLiteral kAllocaKeyName =
     "dltest.alloca_memory_space";
+constexpr static llvm::StringLiteral kManglingStyleKeyName = "dltest.mangling";
 constexpr static llvm::StringLiteral kProgramKeyName =
     "dltest.program_memory_space";
 constexpr static llvm::StringLiteral kGlobalKeyName =
@@ -83,6 +84,9 @@ struct CustomDataLayoutSpec
   StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
     return Builder(context).getStringAttr(kAllocaKeyName);
   }
+  StringAttr getManglingStyleIdentifier(MLIRContext *context) const {
+    return Builder(context).getStringAttr(kManglingStyleKeyName);
+  }
   StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
     return Builder(context).getStringAttr(kProgramKeyName);
   }

@llvmbot
Copy link
Member

llvmbot commented Feb 5, 2025

@llvm/pr-subscribers-mlir-llvm

Author: Guojin (ghehg)

Changes

Add mangling style as a spec entry to datalayout, and implemented importing and exporting LLVM IR to MLIR (LLVM dialect).
Its represented as string as the scope of this PR is to preserve info from LLVM IR, so client in MLIR still need to map deduce the meaning of the string, like "e" means ELF, "o" for Mach-O, etc.


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

14 Files Affected:

  • (modified) mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td (+3)
  • (modified) mlir/include/mlir/Dialect/DLTI/DLTIBase.td (+3)
  • (modified) mlir/include/mlir/Interfaces/DataLayoutInterfaces.h (+9)
  • (modified) mlir/include/mlir/Interfaces/DataLayoutInterfaces.td (+18)
  • (modified) mlir/lib/Dialect/DLTI/DLTI.cpp (+8-1)
  • (modified) mlir/lib/Interfaces/DataLayoutInterfaces.cpp (+27)
  • (modified) mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp (+22)
  • (modified) mlir/lib/Target/LLVMIR/DataLayoutImporter.h (+4)
  • (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+5)
  • (modified) mlir/test/Target/LLVMIR/Import/data-layout.ll (+1)
  • (modified) mlir/test/Target/LLVMIR/Import/import-failure.ll (+5)
  • (modified) mlir/test/Target/LLVMIR/data-layout.mlir (+2)
  • (modified) mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp (+5)
  • (modified) mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp (+4)
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
index d54b3191eed7e66..9bede41a83374e4 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
@@ -77,6 +77,9 @@ def DLTI_DataLayoutSpecAttr :
     /// Returns the alloca memory space identifier.
     StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const;
 
+    /// Returns the mangling style identifier.
+    StringAttr getManglingStyleIdentifier(MLIRContext *context) const;
+
     /// Returns the program memory space identifier.
     StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const;
 
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
index f84149c43e0fcdf..b1f54c608e03eeb 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
@@ -49,6 +49,9 @@ def DLTI_Dialect : Dialect {
     constexpr const static ::llvm::StringLiteral
     kDataLayoutEndiannessLittle = "little";
 
+    constexpr const static ::llvm::StringLiteral
+    kDataLayoutManglingStyleKey = "dlti.mangling_style";
+
     constexpr const static ::llvm::StringLiteral
     kDataLayoutAllocaMemorySpaceKey = "dlti.alloca_memory_space";
     
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
index 7a7b659724f860b..33fadf842cef1b0 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
@@ -78,6 +78,10 @@ Attribute getDefaultEndianness(DataLayoutEntryInterface entry);
 /// DataLayoutInterface if specified, otherwise returns the default.
 Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry);
 
+/// Default handler for mangling style request. Dispatches to the
+/// DataLayoutInterface if specified, otherwise returns the default.
+Attribute getDefaultManglingStyle(DataLayoutEntryInterface entry);
+
 /// Default handler for program memory space request. Dispatches to the
 /// DataLayoutInterface if specified, otherwise returns the default.
 Attribute getDefaultProgramMemorySpace(DataLayoutEntryInterface entry);
@@ -230,6 +234,9 @@ class DataLayout {
   /// Returns the memory space used for AllocaOps.
   Attribute getAllocaMemorySpace() const;
 
+  /// Returns the mangling style.
+  Attribute getManglingStyle() const;
+
   /// Returns the memory space used for program memory operations.
   Attribute getProgramMemorySpace() const;
 
@@ -276,6 +283,8 @@ class DataLayout {
 
   /// Cache for the endianness.
   mutable std::optional<Attribute> endianness;
+  /// Cache for the mangling style.
+  mutable std::optional<Attribute> manglingStyle;
   /// Cache for alloca, global, and program memory spaces.
   mutable std::optional<Attribute> allocaMemorySpace;
   mutable std::optional<Attribute> programMemorySpace;
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
index 0d09b92928fe336..8626fb0709a240c 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
@@ -153,6 +153,12 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface", [DLTIQuer
       /*methodName=*/"getGlobalMemorySpaceIdentifier",
       /*args=*/(ins "::mlir::MLIRContext *":$context)
     >,
+    InterfaceMethod<
+      /*description=*/"Returns the mangling style identifier.",
+      /*retTy=*/"::mlir::StringAttr",
+      /*methodName=*/"getManglingStyleIdentifier",
+      /*args=*/(ins "::mlir::MLIRContext *":$context)
+    >,
     InterfaceMethod<
       /*description=*/"Returns the stack alignment identifier.",
       /*retTy=*/"::mlir::StringAttr",
@@ -481,6 +487,18 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
         return ::mlir::detail::getDefaultAllocaMemorySpace(entry);
       }]
     >,
+    StaticInterfaceMethod<
+      /*description=*/"Returns the mangling style computed "
+                      "using the relevant entries. The data layout object "
+                      "can be used for recursive queries.",
+      /*retTy=*/"::mlir::Attribute",
+      /*methodName=*/"getManglingStyle",
+      /*args=*/(ins "::mlir::DataLayoutEntryInterface":$entry),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{
+        return ::mlir::detail::getDefaultManglingStyle(entry);
+      }]
+    >,
     StaticInterfaceMethod<
       /*description=*/"Returns the memory space used by the ABI computed "
                       "using the relevant entries. The data layout object "
diff --git a/mlir/lib/Dialect/DLTI/DLTI.cpp b/mlir/lib/Dialect/DLTI/DLTI.cpp
index 2510e774f2b2aa1..fcb76eb34d0b7ba 100644
--- a/mlir/lib/Dialect/DLTI/DLTI.cpp
+++ b/mlir/lib/Dialect/DLTI/DLTI.cpp
@@ -397,6 +397,12 @@ DataLayoutSpecAttr::getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
       DLTIDialect::kDataLayoutGlobalMemorySpaceKey);
 }
 
+StringAttr
+DataLayoutSpecAttr::getManglingStyleIdentifier(MLIRContext *context) const {
+  return Builder(context).getStringAttr(
+      DLTIDialect::kDataLayoutManglingStyleKey);
+}
+
 StringAttr
 DataLayoutSpecAttr::getStackAlignmentIdentifier(MLIRContext *context) const {
   return Builder(context).getStringAttr(
@@ -589,7 +595,8 @@ class TargetDataLayoutInterface : public DataLayoutDialectInterface {
     if (entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey ||
         entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||
         entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||
-        entryName == DLTIDialect::kDataLayoutStackAlignmentKey)
+        entryName == DLTIDialect::kDataLayoutStackAlignmentKey ||
+        entryName == DLTIDialect::kDataLayoutManglingStyleKey)
       return success();
     return emitError(loc) << "unknown data layout entry name: " << entryName;
   }
diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
index 049d7f123cec8f3..93f91bdc451f982 100644
--- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
+++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
@@ -258,6 +258,17 @@ mlir::detail::getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry) {
   return entry.getValue();
 }
 
+// Returns the mangling style if specified in the given entry.
+// If the entry is empty, an empty attribute is returned.
+Attribute
+mlir::detail::getDefaultManglingStyle(DataLayoutEntryInterface entry) {
+  if (entry == DataLayoutEntryInterface()) {
+    return Attribute();
+  }
+
+  return entry.getValue();
+}
+
 // Returns the memory space used for the program memory space.  if
 // specified in the given entry. If the entry is empty the default
 // memory space represented by an empty attribute is returned.
@@ -612,6 +623,22 @@ mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const {
   return *allocaMemorySpace;
 }
 
+mlir::Attribute mlir::DataLayout::getManglingStyle() const {
+  checkValid();
+  if (manglingStyle)
+    return *manglingStyle;
+  DataLayoutEntryInterface entry;
+  if (originalLayout)
+    entry = originalLayout.getSpecForIdentifier(
+        originalLayout.getManglingStyleIdentifier(originalLayout.getContext()));
+
+  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
+    manglingStyle = iface.getManglingStyle(entry);
+  else
+    manglingStyle = detail::getDefaultManglingStyle(entry);
+  return *manglingStyle;
+}
+
 mlir::Attribute mlir::DataLayout::getProgramMemorySpace() const {
   checkValid();
   if (programMemorySpace)
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
index 35fdbc0be22c31e..b79ee902ff29f6c 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
@@ -163,6 +163,21 @@ DataLayoutImporter::tryToEmplaceEndiannessEntry(StringRef endianness,
   return success();
 }
 
+LogicalResult DataLayoutImporter::tryToEmplaceManglingStyleEntry(
+    StringRef token, llvm::StringLiteral manglingKey) {
+  auto key = StringAttr::get(context, manglingKey);
+  if (keyEntries.count(key))
+    return success();
+
+  token.consume_front(":");
+  if (token.empty())
+    return failure();
+
+  keyEntries.try_emplace(
+      key, DataLayoutEntryAttr::get(key, StringAttr::get(context, token)));
+  return success();
+}
+
 LogicalResult
 DataLayoutImporter::tryToEmplaceAddrSpaceEntry(StringRef token,
                                                llvm::StringLiteral spaceKey) {
@@ -254,6 +269,13 @@ void DataLayoutImporter::translateDataLayout(
         return;
       continue;
     }
+    // Parse the mangling style.
+    if (*prefix == "m") {
+      if (failed(tryToEmplaceManglingStyleEntry(
+              token, DLTIDialect::kDataLayoutManglingStyleKey)))
+        return;
+      continue;
+    }
     // Parse the global address space.
     if (*prefix == "G") {
       if (failed(tryToEmplaceAddrSpaceEntry(
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
index 59b60acd24be20f..a66402065cb1051 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
@@ -100,6 +100,10 @@ class DataLayoutImporter {
   LogicalResult tryToEmplaceAddrSpaceEntry(StringRef token,
                                            llvm::StringLiteral spaceKey);
 
+  /// Adds an mangling style entry if there is none yet.
+  LogicalResult tryToEmplaceManglingStyleEntry(StringRef token,
+                                               llvm::StringLiteral manglingKey);
+
   /// Adds a stack alignment entry if there is none yet.
   LogicalResult tryToEmplaceStackAlignmentEntry(StringRef token);
 
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 4367100e3aca682..7f4b9fd3e0e3efa 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -198,6 +198,11 @@ translateDataLayout(DataLayoutSpecInterface attribute,
       layoutStream << "-" << (isLittleEndian ? "e" : "E");
       continue;
     }
+    if (key.getValue() == DLTIDialect::kDataLayoutManglingStyleKey) {
+      auto value = cast<StringAttr>(entry.getValue());
+      layoutStream << "-m:" << value.getValue();
+      continue;
+    }
     if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
       auto value = cast<IntegerAttr>(entry.getValue());
       uint64_t space = value.getValue().getZExtValue();
diff --git a/mlir/test/Target/LLVMIR/Import/data-layout.ll b/mlir/test/Target/LLVMIR/Import/data-layout.ll
index c397053585e3c99..b21043718e19e5e 100644
--- a/mlir/test/Target/LLVMIR/Import/data-layout.ll
+++ b/mlir/test/Target/LLVMIR/Import/data-layout.ll
@@ -29,6 +29,7 @@ target datalayout = ""
 ; CHECK-DAG:   !llvm.ptr<271> = dense<32> : vector<4xi64>
 ; CHECK-DAG:   !llvm.ptr<272> = dense<64> : vector<4xi64>
 ; CHECK-DAG:   "dlti.stack_alignment" = 128 : i64
+; CHECK-DAG:   "dlti.mangling_style" = "e"
 target datalayout = "e-m:e-p270:32:64-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 
 ; // -----
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index d929a5928476223..80656493a99eb76 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -354,6 +354,11 @@ declare void @llvm.experimental.noalias.scope.decl(metadata)
 ; CHECK-SAME: warning: unhandled data layout token: ni:42
 target datalayout = "e-ni:42-i64:64"
 
+; // -----
+; CHECK:      import-failure.ll
+; CHECK-SAME: malformed specification, must be of the form "m:<mangling>"
+target datalayout = "e-m-i64:64"
+
 ; // -----
 
 ; CHECK:      <unknown>
diff --git a/mlir/test/Target/LLVMIR/data-layout.mlir b/mlir/test/Target/LLVMIR/data-layout.mlir
index 881d6727e2a17a1..c8aa7ed14b73fe8 100644
--- a/mlir/test/Target/LLVMIR/data-layout.mlir
+++ b/mlir/test/Target/LLVMIR/data-layout.mlir
@@ -4,6 +4,7 @@
 // CHECK: E-
 // CHECK: A4-
 // CHECK: S128-
+// CHECK: m:e-
 // CHECK: i64:64:128
 // CHECK: f80:128:256
 // CHECK: p0:32:64:128:32
@@ -12,6 +13,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<
 #dlti.dl_entry<"dlti.endianness", "big">,
 #dlti.dl_entry<"dlti.alloca_memory_space", 4 : ui32>,
 #dlti.dl_entry<"dlti.stack_alignment", 128 : i32>,
+#dlti.dl_entry<"dlti.mangling_style", "e">,
 #dlti.dl_entry<index, 64>,
 #dlti.dl_entry<i64, dense<[64,128]> : vector<2xi64>>,
 #dlti.dl_entry<f80, dense<[128,256]> : vector<2xi64>>,
diff --git a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
index 56f309f150ca5d3..21c635023d5915b 100644
--- a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
+++ b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
@@ -43,6 +43,7 @@ struct TestDataLayoutQuery
       uint64_t index = layout.getTypeIndexBitwidth(op.getType()).value_or(0);
       Attribute endianness = layout.getEndianness();
       Attribute allocaMemorySpace = layout.getAllocaMemorySpace();
+      Attribute manglingStyle = layout.getManglingStyle();
       Attribute programMemorySpace = layout.getProgramMemorySpace();
       Attribute globalMemorySpace = layout.getGlobalMemorySpace();
       uint64_t stackAlignment = layout.getStackAlignment();
@@ -72,6 +73,10 @@ struct TestDataLayoutQuery
                                 allocaMemorySpace == Attribute()
                                     ? builder.getUI32IntegerAttr(0)
                                     : allocaMemorySpace),
+           builder.getNamedAttr("mangling_style",
+                                manglingStyle == Attribute()
+                                    ? builder.getStringAttr("")
+                                    : manglingStyle),
            builder.getNamedAttr("program_memory_space",
                                 programMemorySpace == Attribute()
                                     ? builder.getUI32IntegerAttr(0)
diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
index db294b8b040e9da..8815190daf55a20 100644
--- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
+++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
@@ -25,6 +25,7 @@ constexpr static llvm::StringLiteral kAttrName = "dltest.layout";
 constexpr static llvm::StringLiteral kEndiannesKeyName = "dltest.endianness";
 constexpr static llvm::StringLiteral kAllocaKeyName =
     "dltest.alloca_memory_space";
+constexpr static llvm::StringLiteral kManglingStyleKeyName = "dltest.mangling";
 constexpr static llvm::StringLiteral kProgramKeyName =
     "dltest.program_memory_space";
 constexpr static llvm::StringLiteral kGlobalKeyName =
@@ -83,6 +84,9 @@ struct CustomDataLayoutSpec
   StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
     return Builder(context).getStringAttr(kAllocaKeyName);
   }
+  StringAttr getManglingStyleIdentifier(MLIRContext *context) const {
+    return Builder(context).getStringAttr(kManglingStyleKeyName);
+  }
   StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
     return Builder(context).getStringAttr(kProgramKeyName);
   }

@bcardosolopes bcardosolopes requested a review from gysit February 5, 2025 23:36
Copy link
Contributor

@gysit gysit left a comment

Choose a reason for hiding this comment

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

Nice!

Can you extend the actual unit tests and maybe also layout.mlir (mentioned below)? There are quite a lot of tests for the data layout and so far we kept updating all of them.

Comment on lines 265 to 267
if (entry == DataLayoutEntryInterface()) {
return Attribute();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (entry == DataLayoutEntryInterface()) {
return Attribute();
}
if (entry == DataLayoutEntryInterface())
return Attribute();

ultra nit: I know it is inconsistent above, but the coding convention would be to drop trivial branches.

@@ -354,6 +354,11 @@ declare void @llvm.experimental.noalias.scope.decl(metadata)
; CHECK-SAME: warning: unhandled data layout token: ni:42
target datalayout = "e-ni:42-i64:64"

; // -----
; CHECK: import-failure.ll
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
; CHECK: import-failure.ll
; CHECK: import-failure.ll

ultra nit: newline missing before the check line.

@@ -83,6 +84,9 @@ struct CustomDataLayoutSpec
StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
return Builder(context).getStringAttr(kAllocaKeyName);
}
StringAttr getManglingStyleIdentifier(MLIRContext *context) const {
return Builder(context).getStringAttr(kManglingStyleKeyName);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you also add checks in the actual unit tests below (such as the FallbackDefault etc).

@@ -72,6 +73,10 @@ struct TestDataLayoutQuery
allocaMemorySpace == Attribute()
? builder.getUI32IntegerAttr(0)
: allocaMemorySpace),
builder.getNamedAttr("mangling_style",
Copy link
Contributor

Choose a reason for hiding this comment

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

This test pass is used by /llvm-project/mlir/test/Dialect/LLVMIR/layout.mlir and other tests, to check if querying the data layout works. Can you add some check lines in one of the tests to check the mangling styles work as expected (probably in layout.mlir)?

@gysit gysit requested review from rolfmorel and rengolin February 6, 2025 07:21
@gysit
Copy link
Contributor

gysit commented Feb 6, 2025

Adding @rengolin and @rolfmorel since they are working on the data layout AFAIK.

@@ -77,6 +77,9 @@ def DLTI_DataLayoutSpecAttr :
/// Returns the alloca memory space identifier.
StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const;

/// Returns the mangling style identifier.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where is the meaning of "mangling style" documented?
I'm raising this because my first thought when hearing about "mangling" is rather "Itanium C++" than "MachO".

Copy link
Contributor Author

@ghehg ghehg Feb 24, 2025

Choose a reason for hiding this comment

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

Where is the meaning of "mangling style" documented? I'm raising this because my first thought when hearing about "mangling" is rather "Itanium C++" than "MachO".

This is part of datalayout string spec in the LLVM Doc .

Copy link
Collaborator

Choose a reason for hiding this comment

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

Right, I'm familiar with this: my question is rather "where is this document in MLIR / this PR", I'm pointing out that the comment here is ambiguous basically.
It's a bit annoying that the is naming conflict on "mangling", I wish they would have specified it a "object mangling" or something like that.

@rengolin
Copy link
Member

rengolin commented Feb 6, 2025

I'm concerned here that we're re-implementing data layout logic in MLIR, while this is already done in LLVM (which we already depend on). Quick fixing a string is one thing, but adding repeat code into MLIR is different.

@rengolin rengolin requested a review from ftynse February 6, 2025 12:21
Copy link
Contributor

@rolfmorel rolfmorel left a comment

Choose a reason for hiding this comment

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

Just two comments:

  1. is this concerning the "mangling mode" property from LLVM's Data Layout? If so, why not reuse that name?

  2. As @rengolin notes, there's considerable overlap in what these files are achieving (e.g. parsing of the data layout string) and what's already available in LLVM proper. While this PR is clearly continuing on a road previously forged, it would be good for us to step back and see if there's a simpler and cleaner way of obtaining and exposing this information, reusing available infrastructure where possible.

    • One approach @rengolin and I have been discussing is to automatically derive all Data Layout attributes (and TTI attributes etc.) from target triple+cpu+feature flags strings, by means of, e.g., the TargetMachine infrastructure in LLVM. One of the advantages would be it being more straightforward to stay in sync with the properties that LLVM provides. There are a couple of things to still work out regarding this approach though...

Point 2 is not meant to block this PR - instead it's meant to initiate discussion on how we can rely more on what LLVM is already providing and simplifying the code involved in exposing Data Layout info and the like.

@@ -49,6 +49,9 @@ def DLTI_Dialect : Dialect {
constexpr const static ::llvm::StringLiteral
kDataLayoutEndiannessLittle = "little";

constexpr const static ::llvm::StringLiteral
kDataLayoutManglingStyleKey = "dlti.mangling_style";
Copy link
Contributor

Choose a reason for hiding this comment

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

Related to @joker-eph's comment above: is this "mangling style" supposed to correspond to a property from LLVM's Data Layout?

As you are parsing the "m" key in the Data Layout string, I would expect that you are wanting to represent the property that is named "mangling mode" in LLVM's Data Layout. See here and here.

Some elaboration on what property is meant - here on the PR and in doc strings - would be appreciated.

Copy link
Contributor

Choose a reason for hiding this comment

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

LLVM's language reference uses style instead of mode. It makes sense to switch to "dlti.mangling_mode" then!

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair point! Might be a good idea to update the one occurrence of "mangling style" in the lang ref to (the currently not referred to) "mangling mode" just to make it consistent with what exists in the codebase.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, will use "mangling mode"

@@ -612,6 +623,22 @@ mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const {
return *allocaMemorySpace;
}

mlir::Attribute mlir::DataLayout::getManglingStyle() const {
Copy link
Contributor

Choose a reason for hiding this comment

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

A general note: the amount of duplicate (boilerplate) code among these methods is rather silly. We should find a better way deal with supporting these properties. Not needed for this PR though as it it just keeps to the existing theme.

@bcardosolopes
Copy link
Member

@ghehg do you have plans to continue the work here? If not I volunteer to take over and follow up with the reviewer comments. Thanks!

@ghehg
Copy link
Contributor Author

ghehg commented Feb 20, 2025

@ghehg do you have plans to continue the work here? If not I volunteer to take over and follow up with the reviewer comments. Thanks!

Yeah, I'll address review comments in the next 2 days and get this done.

@ghehg ghehg force-pushed the ash8 branch 2 times, most recently from 80959a8 to 735628a Compare February 24, 2025 02:45
Copy link

github-actions bot commented Feb 24, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@ghehg ghehg force-pushed the ash8 branch 2 times, most recently from cac2eed to 4e3ddc4 Compare February 24, 2025 03:18
Copy link
Contributor

@gysit gysit left a comment

Choose a reason for hiding this comment

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

Thanks for addressing the comment!

LGTM from my end modulo my last comments.

@@ -49,6 +49,10 @@ def DLTI_Dialect : Dialect {
constexpr const static ::llvm::StringLiteral
kDataLayoutEndiannessLittle = "little";

// Mangling mode, a.k.a mangling style used to mangle llvm names
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Mangling mode, a.k.a mangling style used to mangle llvm names
// Mangling mode, a.k.a mangling style used to mangle llvm names.

ultra nit: missing dot.

@@ -474,6 +478,7 @@ module {}
EXPECT_EQ(layout.getProgramMemorySpace(), Attribute());
EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute());
EXPECT_EQ(layout.getStackAlignment(), 0u);
EXPECT_EQ(layout.getManglingMode(), Attribute());
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add this to the following tests as well:

EmptySpec, NullSpec

And add an actuel entry in

SpecWithEntries

?

PS I know we test certain things twice but the unit test really covers all the different paths to get to a default / actual value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tests added. Let me know anything more we add.

Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM feel free to land!

@bcardosolopes
Copy link
Member

Seems like @ghehg applied most of the feedback from @gysit, gentle ping - what else is needed here?

@gysit
Copy link
Contributor

gysit commented Mar 5, 2025

This is good to go! Should I land it?

@ghehg
Copy link
Contributor Author

ghehg commented Mar 5, 2025

This is good to go! Should I land it?

Yes, please, I don't think I have the permission to merge.

@gysit gysit merged commit 8c0e9ad into llvm:main Mar 5, 2025
11 checks passed
jph-13 pushed a commit to jph-13/llvm-project that referenced this pull request Mar 21, 2025
Add mangling style as a spec entry to datalayout, and implemented
importing and exporting LLVM IR to MLIR (LLVM dialect).
Its represented as string as the scope of this PR is to preserve info
from LLVM IR, so client in MLIR still need to map deduce the meaning of
the string, like "e" means ELF, "o" for Mach-O, etc.

it addresses one of issues mentioned in this
[issue](llvm#126046)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants