[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