[llvm] e910926 - [ORC] Add SymbolNameSpec, hoist name mangling into Shared.

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 8 00:06:52 PDT 2026


Author: Lang Hames
Date: 2026-09-08T17:06:48+10:00
New Revision: e91092685eab2ab0348ea06df2c3446001b480d4

URL: https://github.com/llvm/llvm-project/commit/e91092685eab2ab0348ea06df2c3446001b480d4
DIFF: https://github.com/llvm/llvm-project/commit/e91092685eab2ab0348ea06df2c3446001b480d4.diff

LOG: [ORC] Add SymbolNameSpec, hoist name mangling into Shared.

Introduce two Shared, ExecutionSession-independent pieces:

 - SymbolNameSpec (Shared/SymbolNameSpec.h): a StringRef paired with a
   SymbolNameKind (Verbatim, Linker, IR, C) describing the naming level
   a symbol name is expressed in. A lightweight, dependency-free value
   type, so it can describe interface-name constants in Shared headers.

 - Mangler (Shared/Mangler.h, Shared/Mangler.cpp): the linker
   name-mangling logic factored out of MangleAndInterner. It holds only
   a ManglingMode (no ExecutionSession or SymbolStringPool), so names
   can be mangled on the executor side as well as the controller
   side. It exposes withMangledNameDo (which avoids allocating when
   mangling is a no-op) and a mangledCopy convenience, both dispatching
   on the spec's SymbolNameKind.

MangleAndInterner becomes a thin wrapper: it derives a ManglingMode
(from an ABIName / ManglingMode / DataLayout), holds a Mangler, and
interns whatever the Mangler produces. Behavior is unchanged.

This lets lookup utilities eventually accept C / IR source names and
mangle them to linker level on the caller's behalf, rather than
requiring pre-mangled names. The MangleAndInternerTest unit tests are
renamed to ManglerTest and now exercise Mangler directly;
MangleAndInterner is left untested since it is slated for removal.

Added: 
    llvm/include/llvm/ExecutionEngine/Orc/Shared/Mangler.h
    llvm/include/llvm/ExecutionEngine/Orc/Shared/SymbolNameSpec.h
    llvm/lib/ExecutionEngine/Orc/Shared/Mangler.cpp
    llvm/unittests/ExecutionEngine/Orc/ManglerTest.cpp

Modified: 
    llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
    llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
    llvm/lib/ExecutionEngine/Orc/Mangling.cpp
    llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
    llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt

Removed: 
    llvm/unittests/ExecutionEngine/Orc/MangleAndInternerTest.cpp


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
index 650ba1fe8cc54..f592608ef1557 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
@@ -14,6 +14,7 @@
 #define LLVM_EXECUTIONENGINE_ORC_MANGLING_H
 
 #include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Shared/Mangler.h"
 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Compiler.h"
@@ -26,30 +27,32 @@ namespace llvm::orc {
 /// ExecutionSession.
 class MangleAndInterner {
 public:
-  enum class ManglingMode {
-    None,
-    ELF,
-    MachO,
-    WinCOFF,
-    WinCOFFX86,
-    GOFF,
-    Mips,
-    XCOFF
-  };
+  using ManglingMode = Mangler::Mode;
 
-  LLVM_ABI MangleAndInterner(ExecutionSession &ES, StringRef ABIName = "");
-  LLVM_ABI MangleAndInterner(ExecutionSession &ES, ManglingMode Mode);
-  LLVM_ABI MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);
-  LLVM_ABI SymbolStringPtr operator()(StringRef Name);
+  MangleAndInterner(ExecutionSession &ES, Mangler M)
+      : ES(ES), M(std::move(M)) {}
+  MangleAndInterner(ExecutionSession &ES, ManglingMode Mode)
+      : ES(ES), M(Mode) {}
+  MangleAndInterner(ExecutionSession &ES, StringRef ABIName = "")
+      : ES(ES), M(ES.getTargetTriple(), ABIName) {}
+  MangleAndInterner(ExecutionSession &ES, const DataLayout &DL)
+      : ES(ES), M(DL.getStringRepresentation()) {}
 
-private:
-  static ManglingMode fromDataLayoutStr(StringRef DLStr);
-  static ManglingMode fromTriple(const Triple &TT, StringRef ABIName);
-  static ManglingMode fromDataLayout(const DataLayout &DL);
-  bool doNotMangleLeadingQuestionMark() const;
+  const Mangler &mangler() const { return M; }
+
+  SymbolStringPtr operator()(const SymbolNameSpec &NameSpec) {
+    return M.withMangledNameDo(
+        [this](StringRef MangledName) { return ES.intern(MangledName); },
+        NameSpec);
+  }
 
+  SymbolStringPtr operator()(StringRef Name) {
+    return (*this)(SymbolNameSpec(Name, SymbolNameKind::IR));
+  }
+
+private:
   ExecutionSession &ES;
-  ManglingMode Mode;
+  Mangler M;
 };
 
 /// Maps IR global values to their linker symbol names / flags.

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/Mangler.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/Mangler.h
new file mode 100644
index 0000000000000..e9a2f268fbaff
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/Mangler.h
@@ -0,0 +1,90 @@
+//===------- Mangler.h -- Linker name mangling for ORC ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Linker name mangling for ORC.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_MANGLER_H
+#define LLVM_EXECUTIONENGINE_ORC_SHARED_MANGLER_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SymbolNameSpec.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+class Triple;
+
+namespace orc {
+
+/// Applies linker name-mangling for a target.
+class Mangler {
+public:
+  /// The linker name-mangling scheme for a target, determined by its object
+  /// format. This captures the platform decoration applied to symbol names
+  /// (e.g. a leading '_' on MachO), independently of any ExecutionSession.
+  enum class Mode { None, ELF, MachO, WinCOFF, WinCOFFX86, GOFF, Mips, XCOFF };
+
+  explicit Mangler(Mode MM) : MM(MM) {}
+  explicit Mangler(StringRef DLStr) : MM(fromDataLayoutStr(DLStr)) {}
+  explicit Mangler(const Triple &TT, StringRef ABIName = "")
+      : MM(fromTriple(TT, ABIName)) {}
+
+  /// Calls the given callback with the mangled version of NameSpec as a
+  /// StringRef. The mangled name is only valid for the duration of the callback
+  /// and must not escape. This allows withMangledNameDo to avoid allocations
+  /// when mangling is a no-op.
+  template <typename HandlerFn>
+  decltype(auto) withMangledNameDo(HandlerFn &&H,
+                                   const SymbolNameSpec &NameSpec) const {
+    if (NameSpec.getKind() == SymbolNameKind::Verbatim ||
+        NameSpec.getKind() == SymbolNameKind::Linker)
+      return H(NameSpec.getName());
+
+    if (NameSpec.getName().empty())
+      return H(NameSpec.getName());
+
+    if (NameSpec.getName()[0] == '\1')
+      return H(NameSpec.getName().substr(1));
+
+    if (NameSpec.getName()[0] == '?' && doNotMangleLeadingQuestionMark())
+      return H(NameSpec.getName());
+
+    if (MM == Mode::MachO || MM == Mode::WinCOFFX86) {
+      SmallString<1024> MangledName;
+      MangledName.append({StringRef("_"), NameSpec.getName()});
+      return H(StringRef(MangledName));
+    }
+
+    return H(NameSpec.getName());
+  }
+
+  /// Construct a mangled version of the given name as a std::string.
+  /// This always produces a copy, even for no-op manglings. Prefer
+  /// withMangledNameDo in any performance-sensitive context.
+  std::string mangledCopy(const SymbolNameSpec &Name) const {
+    return withMangledNameDo(
+        [](StringRef MangledName) { return MangledName.str(); }, Name);
+  }
+
+private:
+  LLVM_ABI static Mode fromDataLayoutStr(StringRef DLStr);
+  LLVM_ABI static Mode fromTriple(const Triple &TT, StringRef ABIName);
+  bool doNotMangleLeadingQuestionMark() const {
+    return MM == Mode::WinCOFF || MM == Mode::WinCOFFX86;
+  }
+
+  Mode MM;
+};
+
+} // namespace orc
+} // namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_MANGLING_H

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/SymbolNameSpec.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/SymbolNameSpec.h
new file mode 100644
index 0000000000000..c52d4e1f770af
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/SymbolNameSpec.h
@@ -0,0 +1,68 @@
+//===- SymbolNameSpec.h - A symbol name plus its mangling kind --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A symbol name paired with the naming level it is expressed in.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SYMBOLNAMESPEC_H
+#define LLVM_EXECUTIONENGINE_ORC_SHARED_SYMBOLNAMESPEC_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm::orc {
+
+/// The naming level a symbol name is expressed in, which determines how it is
+/// mangled before being interned for lookup.
+enum class SymbolNameKind {
+  Verbatim, // Use the name as given, with no mangling.
+  Linker,   // An already-decorated linker name; a synonym for Verbatim.
+  IR,       // An IR global name; mangled to linker level for the target.
+  C,        // A C source name; handled identically to IR.
+};
+
+/// A symbol name together with the naming level (SymbolNameKind) it is
+/// expressed in, so that a Mangler / MangleAndInterner can mangle it to linker
+/// level rather than requiring callers to pre-mangle.
+///
+/// The name is not copied: a SymbolNameSpec must not outlive the string it
+/// refers to.
+///
+/// Implicitly constructible from a StringRef, defaulting to Verbatim, so that
+/// APIs taking a SymbolNameSpec stay drop-in replacements for ones that
+/// previously took an already-mangled StringRef.
+class SymbolNameSpec {
+public:
+  constexpr SymbolNameSpec(StringRef Name,
+                           SymbolNameKind Kind = SymbolNameKind::Verbatim)
+      : Name(Name), Kind(Kind) {}
+
+  static constexpr SymbolNameSpec verbatim(StringRef Name) {
+    return {Name, SymbolNameKind::Verbatim};
+  }
+  static constexpr SymbolNameSpec linker(StringRef Name) {
+    return {Name, SymbolNameKind::Linker};
+  }
+  static constexpr SymbolNameSpec ir(StringRef Name) {
+    return {Name, SymbolNameKind::IR};
+  }
+  static constexpr SymbolNameSpec c(StringRef Name) {
+    return {Name, SymbolNameKind::C};
+  }
+
+  constexpr StringRef getName() const { return Name; }
+  constexpr SymbolNameKind getKind() const { return Kind; }
+
+private:
+  StringRef Name;
+  SymbolNameKind Kind;
+};
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SYMBOLNAMESPEC_H

diff  --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 04d24d1d30497..938c8e076eb07 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -1105,7 +1105,7 @@ std::string LLJIT::mangle(StringRef UnmangledName) const {
   std::string MangledName;
   {
     raw_string_ostream MangledNameStream(MangledName);
-    Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
+    llvm::Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
   }
   return MangledName;
 }

diff  --git a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
index ec95b56ef0e95..2fe78d615a5b5 100644
--- a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
@@ -7,92 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/Orc/Mangling.h"
-#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/Constants.h"
-#include "llvm/IR/Mangler.h"
-#include "llvm/Support/ErrorHandling.h"
 
 #define DEBUG_TYPE "orc"
 
 namespace llvm::orc {
 
-MangleAndInterner::MangleAndInterner(ExecutionSession &ES, StringRef ABIName)
-    : ES(ES), Mode(fromTriple(ES.getTargetTriple(), ABIName)) {}
-
-MangleAndInterner::MangleAndInterner(ExecutionSession &ES, ManglingMode Mode)
-    : ES(ES), Mode(Mode) {}
-
-MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL)
-    : ES(ES), Mode(fromDataLayout(DL)) {}
-
-// TODO: The prefixing rules below, and the mangling-mode derivation in
-// fromDataLayoutStr, duplicate logic that already lives in llvm::Mangler
-// (getNameWithPrefix) and DataLayout (ManglingModeT and its "m:" spec
-// parsing). They are re-implemented here only because those APIs require a
-// full DataLayout, which this class is meant to work without. We should
-// refactor to have one copy of this code, probably best defined in
-// TargetParser, shared between all users.
-SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {
-  if (Name.empty())
-    return ES.intern(Name);
-
-  if (Name.front() == '\1')
-    return ES.intern(Name.substr(1));
-
-  if (Name[0] == '?' && doNotMangleLeadingQuestionMark())
-    return ES.intern(Name);
-
-  if (Mode == ManglingMode::MachO || Mode == ManglingMode::WinCOFFX86)
-    return ES.intern(("_" + Name).str());
-
-  return ES.intern(Name);
-}
-
-MangleAndInterner::ManglingMode
-MangleAndInterner::fromDataLayoutStr(StringRef DLStr) {
-  for (StringRef Spec : split(DLStr, '-')) {
-    if (!Spec.starts_with("m:"))
-      continue;
-    auto ModeStr = Spec.drop_front(2);
-    assert(ModeStr.size() == 1 &&
-           "invalid data layout string from Triple::computeDataLayout");
-    switch (ModeStr[0]) {
-    case 'e':
-      return ManglingMode::ELF;
-    case 'l':
-      return ManglingMode::GOFF;
-    case 'o':
-      return ManglingMode::MachO;
-    case 'm':
-      return ManglingMode::Mips;
-    case 'w':
-      return ManglingMode::WinCOFF;
-    case 'x':
-      return ManglingMode::WinCOFFX86;
-    case 'a':
-      return ManglingMode::XCOFF;
-    default:
-      llvm_unreachable("Invalid mangling mode from Triple::computeDataLayout");
-    }
-  }
-  return ManglingMode::None;
-}
-
-MangleAndInterner::ManglingMode
-MangleAndInterner::fromTriple(const Triple &TT, StringRef ABIName) {
-  return fromDataLayoutStr(TT.computeDataLayout(ABIName));
-}
-
-MangleAndInterner::ManglingMode
-MangleAndInterner::fromDataLayout(const DataLayout &DL) {
-  return fromDataLayoutStr(DL.getStringRepresentation());
-}
-
-bool MangleAndInterner::doNotMangleLeadingQuestionMark() const {
-  return Mode == ManglingMode::WinCOFF || Mode == ManglingMode::WinCOFFX86;
-}
-
 void IRSymbolMapper::add(ExecutionSession &ES, const ManglingOptions &MO,
                          ArrayRef<GlobalValue *> GVs,
                          SymbolFlagsMap &SymbolFlags,

diff  --git a/llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
index 717fc21826aba..33a8a41df1e0f 100644
--- a/llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_llvm_component_library(LLVMOrcShared
   AllocationActions.cpp
   MachOObjectFormat.cpp
+  Mangler.cpp
   ObjectFormats.cpp
   OrcError.cpp
   OrcRTBridge.cpp

diff  --git a/llvm/lib/ExecutionEngine/Orc/Shared/Mangler.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/Mangler.cpp
new file mode 100644
index 0000000000000..824b3d7053ddd
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/Mangler.cpp
@@ -0,0 +1,53 @@
+//===------------- Mangler.cpp -- Linker name mangling for ORC ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/Shared/Mangler.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <cassert>
+
+#define DEBUG_TYPE "orc"
+
+namespace llvm::orc {
+
+Mangler::Mode Mangler::fromDataLayoutStr(StringRef DLStr) {
+  for (StringRef Spec : split(DLStr, '-')) {
+    if (!Spec.starts_with("m:"))
+      continue;
+    auto ModeStr = Spec.drop_front(2);
+    assert(ModeStr.size() == 1 &&
+           "invalid data layout string from Triple::computeDataLayout");
+    switch (ModeStr[0]) {
+    case 'e':
+      return Mode::ELF;
+    case 'l':
+      return Mode::GOFF;
+    case 'o':
+      return Mode::MachO;
+    case 'm':
+      return Mode::Mips;
+    case 'w':
+      return Mode::WinCOFF;
+    case 'x':
+      return Mode::WinCOFFX86;
+    case 'a':
+      return Mode::XCOFF;
+    default:
+      llvm_unreachable("Invalid mangling mode from Triple::computeDataLayout");
+    }
+  }
+  return Mode::None;
+}
+
+Mangler::Mode Mangler::fromTriple(const Triple &TT, StringRef ABIName) {
+  return fromDataLayoutStr(TT.computeDataLayout(ABIName));
+}
+
+} // namespace llvm::orc

diff  --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index a9271bac9d1c7..7e5f3f2192011 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -33,7 +33,7 @@ add_llvm_unittest(OrcJITTests
   LinkGraphLinkingLayerTest.cpp
   LookupAndApplyTest.cpp
   MachOBuilderTest.cpp
-  MangleAndInternerTest.cpp
+  ManglerTest.cpp
   MachOPlatformTest.cpp
   MapperJITLinkMemoryManagerTest.cpp
   MemoryFlagsTest.cpp

diff  --git a/llvm/unittests/ExecutionEngine/Orc/MangleAndInternerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/MangleAndInternerTest.cpp
deleted file mode 100644
index a047985ad1d3b..0000000000000
--- a/llvm/unittests/ExecutionEngine/Orc/MangleAndInternerTest.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-//===---- MangleAndInternerTest.cpp - Unit tests for MangleAndInterner ----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ExecutionEngine/Orc/Mangling.h"
-#include "llvm/Support/Error.h"
-
-#include "OrcTestCommon.h"
-
-using namespace llvm;
-using namespace llvm::orc;
-
-namespace {
-
-ExecutionSession makeES(StringRef TT) {
-  return ExecutionSession(std::make_unique<UnsupportedExecutorProcessControl>(
-      nullptr, nullptr, TT.str()));
-}
-
-struct ManglingCase {
-  StringRef Triple;
-  StringRef Input;
-  StringRef Expected;
-};
-
-} // namespace
-
-TEST(MangleAndInternerTest, FromTripleAcrossFormats) {
-  static const ManglingCase Cases[] = {
-      // ELF: no prefix.
-      {"x86_64-unknown-linux-gnu", "foo", "foo"},
-      // MachO: leading underscore.
-      {"x86_64-apple-darwin", "foo", "_foo"},
-      {"arm64-apple-darwin", "foo", "_foo"},
-      // Windows COFF, x86_64: no prefix.
-      {"x86_64-pc-windows-msvc", "foo", "foo"},
-      // Windows COFF, x86 (32-bit): leading underscore.
-      {"i686-pc-windows-msvc", "foo", "_foo"},
-      // AIX XCOFF: no prefix.
-      {"powerpc64-ibm-aix", "foo", "foo"},
-      // z/OS GOFF: no prefix.
-      {"s390x-ibm-zos", "foo", "foo"},
-      // MIPS O32: no prefix.
-      {"mipsel-unknown-linux-gnu", "foo", "foo"},
-  };
-
-  for (const auto &C : Cases) {
-    SCOPED_TRACE(C.Triple);
-    ExecutionSession ES = makeES(C.Triple);
-    MangleAndInterner Mangle(ES);
-    EXPECT_EQ(*Mangle(C.Input), C.Expected);
-    cantFail(ES.endSession());
-  }
-}
-
-TEST(MangleAndInternerTest, DoNotMangleLeadingBackslash1) {
-  ExecutionSession ES = makeES("x86_64-apple-darwin");
-  MangleAndInterner Mangle(ES);
-  EXPECT_EQ(*Mangle("\1foo"), "foo");
-  cantFail(ES.endSession());
-}
-
-TEST(MangleAndInternerTest, WindowsQuestionMarkNotMangled) {
-  ExecutionSession ES = makeES("x86_64-pc-windows-msvc");
-  MangleAndInterner Mangle(ES);
-  EXPECT_EQ(*Mangle("?foo@@YAHXZ"), "?foo@@YAHXZ");
-  cantFail(ES.endSession());
-}
-
-TEST(MangleAndInternerTest, MachOQuestionMarkIsMangled) {
-  // MachO has no question-mark suppression: gets the usual '_' prefix.
-  ExecutionSession ES = makeES("x86_64-apple-darwin");
-  MangleAndInterner Mangle(ES);
-  EXPECT_EQ(*Mangle("?foo"), "_?foo");
-  cantFail(ES.endSession());
-}
-
-TEST(MangleAndInternerTest, ExplicitManglingMode) {
-  ExecutionSession ES = makeES("x86_64-unknown-linux-gnu");
-  MangleAndInterner Mangle(ES, MangleAndInterner::ManglingMode::MachO);
-  EXPECT_EQ(*Mangle("foo"), "_foo");
-  cantFail(ES.endSession());
-}

diff  --git a/llvm/unittests/ExecutionEngine/Orc/ManglerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ManglerTest.cpp
new file mode 100644
index 0000000000000..ed0aff788cfd0
--- /dev/null
+++ b/llvm/unittests/ExecutionEngine/Orc/ManglerTest.cpp
@@ -0,0 +1,87 @@
+//===-------------- ManglerTest.cpp - Unit tests for Mangler --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/Shared/Mangler.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SymbolNameSpec.h"
+
+#include "OrcTestCommon.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+struct ManglingCase {
+  StringRef Triple;
+  StringRef Input;
+  StringRef Expected;
+};
+
+} // namespace
+
+TEST(ManglerTest, FromTripleAcrossFormats) {
+  static const ManglingCase Cases[] = {
+      // ELF: no prefix.
+      {"x86_64-unknown-linux-gnu", "foo", "foo"},
+      // MachO: leading underscore.
+      {"x86_64-apple-darwin", "foo", "_foo"},
+      {"arm64-apple-darwin", "foo", "_foo"},
+      // Windows COFF, x86_64: no prefix.
+      {"x86_64-pc-windows-msvc", "foo", "foo"},
+      // Windows COFF, x86 (32-bit): leading underscore.
+      {"i686-pc-windows-msvc", "foo", "_foo"},
+      // AIX XCOFF: no prefix.
+      {"powerpc64-ibm-aix", "foo", "foo"},
+      // z/OS GOFF: no prefix.
+      {"s390x-ibm-zos", "foo", "foo"},
+      // MIPS O32: no prefix.
+      {"mipsel-unknown-linux-gnu", "foo", "foo"},
+  };
+
+  for (const auto &C : Cases) {
+    SCOPED_TRACE(C.Triple);
+    Mangler Mangle(Triple(C.Triple));
+    EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::ir(C.Input)), C.Expected);
+  }
+}
+
+TEST(ManglerTest, DoNotMangleLeadingBackslash1) {
+  Mangler Mangle(Triple("x86_64-apple-darwin"));
+  EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::ir("\1foo")), "foo");
+}
+
+TEST(ManglerTest, WindowsQuestionMarkNotMangled) {
+  Mangler Mangle(Triple("x86_64-pc-windows-msvc"));
+  EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::ir("?foo@@YAHXZ")),
+            "?foo@@YAHXZ");
+}
+
+TEST(ManglerTest, MachOQuestionMarkIsMangled) {
+  // MachO has no question-mark suppression: gets the usual '_' prefix.
+  Mangler Mangle(Triple("x86_64-apple-darwin"));
+  EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::ir("?foo")), "_?foo");
+}
+
+TEST(ManglerTest, ExplicitManglingMode) {
+  Mangler Mangle(Mangler::Mode::MachO);
+  EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::ir("foo")), "_foo");
+}
+
+// Use a MachO triple so that mangling ("_" prefix) is observably 
diff erent from
+// interning verbatim.
+TEST(ManglerTest, SymbolNameSpecKindDispatch) {
+  Mangler Mangle(Triple("x86_64-apple-darwin"));
+
+  // Verbatim and Linker are interned unmodified.
+  EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::verbatim("foo")), "foo");
+  EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::linker("foo")), "foo");
+
+  // IR and C are mangled (leading "_" on MachO).
+  EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::ir("foo")), "_foo");
+  EXPECT_EQ(Mangle.mangledCopy(SymbolNameSpec::c("foo")), "_foo");
+}


        


More information about the llvm-commits mailing list