[llvm] [orc-rt] Consolidate symbol export macros (PR #220495)

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 1 23:46:49 PDT 2026


https://github.com/lhames created https://github.com/llvm/llvm-project/pull/220495

Replace the overlapping visibility macros with a single pair, one per public API surface:

  ORC_RT_C_EXPORT (orc-rt-c/support/Compiler.h) - the C API
  ORC_RT_EXPORT   (orc-rt/support/Compiler.h)   - the C++ API

ORC_RT_C_ABI is renamed to ORC_RT_C_EXPORT. ORC_RT_INTERFACE, ORC_RT_HIDDEN and ORC_RT_IMPORT are removed.

ORC_RT_EXPORT is currently defined as ORC_RT_C_EXPORT so that the platform logic lives in one place. It becomes separately switchable once there is an option to hide the C++ API.

No change to generated code: every macro expands to exactly what it did before. The Windows dllexport/dllimport and static-build cases are left as a TODO for the commit that adds the shared-library build.

>From dbd081bb5ce99909002a55f02c884d5acc8eee7e Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Wed, 2 Sep 2026 16:39:49 +1000
Subject: [PATCH] [orc-rt] Consolidate symbol export macros

Replace the overlapping visibility macros with a single pair, one per
public API surface:

  ORC_RT_C_EXPORT (orc-rt-c/support/Compiler.h) - the C API
  ORC_RT_EXPORT   (orc-rt/support/Compiler.h)   - the C++ API

ORC_RT_C_ABI is renamed to ORC_RT_C_EXPORT. ORC_RT_INTERFACE,
ORC_RT_HIDDEN and ORC_RT_IMPORT are removed.

ORC_RT_EXPORT is currently defined as ORC_RT_C_EXPORT so that the
platform logic lives in one place. It becomes separately switchable once
there is an option to hide the C++ API.

No change to generated code: every macro expands to exactly what it did
before. The Windows dllexport/dllimport and static-build cases are left
as a TODO for the commit that adds the shared-library build.
---
 orc-rt/include/orc-rt-c/support/Compiler.h | 14 +++++++++-----
 orc-rt/include/orc-rt-c/support/Error.h    | 17 ++++++++++-------
 orc-rt/include/orc-rt/support/Compiler.h   | 20 +++++++++++---------
 orc-rt/lib/bedrock/GDBJITRegistrar.cpp     | 11 ++++++++---
 4 files changed, 38 insertions(+), 24 deletions(-)

diff --git a/orc-rt/include/orc-rt-c/support/Compiler.h b/orc-rt/include/orc-rt-c/support/Compiler.h
index c740b549481f3..89b1b1d874c66 100644
--- a/orc-rt/include/orc-rt-c/support/Compiler.h
+++ b/orc-rt/include/orc-rt-c/support/Compiler.h
@@ -38,14 +38,18 @@
 #define ORC_RT_C_EXTERN_C_END ORC_RT_C_STRICT_PROTOTYPES_END
 #endif
 
-/* ORC_RT_C_ABI is the export/visibility macro used to mark symbols declared
-   in orc-rt-c as exported when built as a shared library. */
+/* ORC_RT_C_EXPORT marks a symbol declared in orc-rt-c as part of the ORC
+   runtime's binary interface: exported from the runtime when it is built as a
+   shared library, and imported by consumers of that library.
+
+   TODO: Add the Windows __declspec(dllexport) / __declspec(dllimport) and
+   static-build cases once there is a shared-library build to exercise them. */
 #if defined(__has_attribute) && __has_attribute(visibility)
-#define ORC_RT_C_ABI __attribute__((visibility("default")))
+#define ORC_RT_C_EXPORT __attribute__((visibility("default")))
 #endif
 
-#if !defined(ORC_RT_C_ABI)
-#define ORC_RT_C_ABI
+#if !defined(ORC_RT_C_EXPORT)
+#define ORC_RT_C_EXPORT
 #endif
 
 /* ORC_RT_C_NOTHROW indicates that a function won't throw a C++ exception. */
diff --git a/orc-rt/include/orc-rt-c/support/Error.h b/orc-rt/include/orc-rt-c/support/Error.h
index 7afa373c7d75e..91b038f494cef 100644
--- a/orc-rt/include/orc-rt-c/support/Error.h
+++ b/orc-rt/include/orc-rt-c/support/Error.h
@@ -32,7 +32,7 @@ typedef const void *orc_rt_Error_TypeId;
  * Returns the type id for the given error instance, which must be a failure
  * value (i.e. non-null).
  */
-ORC_RT_C_ABI orc_rt_Error_TypeId orc_rt_Error_getTypeId(orc_rt_ErrorRef Err)
+ORC_RT_C_EXPORT orc_rt_Error_TypeId orc_rt_Error_getTypeId(orc_rt_ErrorRef Err)
     ORC_RT_C_NOTHROW;
 
 /**
@@ -42,7 +42,7 @@ ORC_RT_C_ABI orc_rt_Error_TypeId orc_rt_Error_getTypeId(orc_rt_ErrorRef Err)
  * Note: This method *only* needs to be called if the error is not being passed
  * to some other consuming operation, e.g. LLVMGetErrorMessage.
  */
-ORC_RT_C_ABI void orc_rt_Error_consume(orc_rt_ErrorRef Err) ORC_RT_C_NOTHROW;
+ORC_RT_C_EXPORT void orc_rt_Error_consume(orc_rt_ErrorRef Err) ORC_RT_C_NOTHROW;
 
 /**
  * Report a fatal error if Err is a failure value.
@@ -50,7 +50,8 @@ ORC_RT_C_ABI void orc_rt_Error_consume(orc_rt_ErrorRef Err) ORC_RT_C_NOTHROW;
  * This function can be used to wrap calls to fallible functions ONLY when it is
  * known that the Error will always be a success value.
  */
-ORC_RT_C_ABI void orc_rt_Error_cantFail(orc_rt_ErrorRef Err) ORC_RT_C_NOTHROW;
+ORC_RT_C_EXPORT void
+orc_rt_Error_cantFail(orc_rt_ErrorRef Err) ORC_RT_C_NOTHROW;
 
 /**
  * Returns the given string's error message. This operation consumes the error,
@@ -58,23 +59,25 @@ ORC_RT_C_ABI void orc_rt_Error_cantFail(orc_rt_ErrorRef Err) ORC_RT_C_NOTHROW;
  * The caller is responsible for disposing of the string by calling
  * LLVMDisposeErrorMessage.
  */
-ORC_RT_C_ABI char *orc_rt_Error_toString(orc_rt_ErrorRef Err) ORC_RT_C_NOTHROW;
+ORC_RT_C_EXPORT char *
+orc_rt_Error_toString(orc_rt_ErrorRef Err) ORC_RT_C_NOTHROW;
 
 /**
  * Dispose of the given error message.
  */
-ORC_RT_C_ABI void orc_rt_Error_freeErrorMessage(char *ErrMsg) ORC_RT_C_NOTHROW;
+ORC_RT_C_EXPORT void
+orc_rt_Error_freeErrorMessage(char *ErrMsg) ORC_RT_C_NOTHROW;
 
 /**
  * Returns the type id for llvm StringError.
  */
-ORC_RT_C_ABI orc_rt_Error_TypeId orc_rt_StringError_getTypeId(void)
+ORC_RT_C_EXPORT orc_rt_Error_TypeId orc_rt_StringError_getTypeId(void)
     ORC_RT_C_NOTHROW;
 
 /**
  * Create a StringError.
  */
-ORC_RT_C_ABI orc_rt_ErrorRef orc_rt_StringError_create(const char *ErrMsg)
+ORC_RT_C_EXPORT orc_rt_ErrorRef orc_rt_StringError_create(const char *ErrMsg)
     ORC_RT_C_NOTHROW;
 
 ORC_RT_C_EXTERN_C_END
diff --git a/orc-rt/include/orc-rt/support/Compiler.h b/orc-rt/include/orc-rt/support/Compiler.h
index c568707a61d2b..e2c4e7c6fe14d 100644
--- a/orc-rt/include/orc-rt/support/Compiler.h
+++ b/orc-rt/include/orc-rt/support/Compiler.h
@@ -15,17 +15,19 @@
 #ifndef ORC_RT_SUPPORT_COMPILER_H
 #define ORC_RT_SUPPORT_COMPILER_H
 
+#include "orc-rt-c/support/Compiler.h"
+
 #include <cassert>
 
-#if defined(_WIN32)
-#define ORC_RT_INTERFACE extern "C"
-#define ORC_RT_HIDDEN
-#define ORC_RT_IMPORT extern "C" __declspec(dllimport)
-#else
-#define ORC_RT_INTERFACE extern "C" __attribute__((visibility("default")))
-#define ORC_RT_HIDDEN __attribute__((visibility("hidden")))
-#define ORC_RT_IMPORT extern "C"
-#endif
+// ORC_RT_EXPORT marks a symbol declared in orc-rt as part of the ORC runtime's
+// binary interface: exported from the runtime when it is built as a shared
+// library, and imported by consumers of that library.
+//
+// Symbols belonging to the C API use ORC_RT_C_EXPORT instead. The two are
+// equivalent today, but the C++ API is expected to change far more often than
+// the C API, so ORC_RT_EXPORT may become separately switchable to allow the C++
+// API to be hidden.
+#define ORC_RT_EXPORT ORC_RT_C_EXPORT
 
 #ifndef __has_builtin
 #define __has_builtin(x) 0
diff --git a/orc-rt/lib/bedrock/GDBJITRegistrar.cpp b/orc-rt/lib/bedrock/GDBJITRegistrar.cpp
index 586f557eab4e2..9cfa01fdb5b72 100644
--- a/orc-rt/lib/bedrock/GDBJITRegistrar.cpp
+++ b/orc-rt/lib/bedrock/GDBJITRegistrar.cpp
@@ -45,15 +45,20 @@ static constexpr uint32_t JitDescriptorVersion = 1;
 // We put information about the JIT'd object in this global, which the
 // debugger reads. Make sure to specify the version statically, because the
 // debugger checks the version before we can set it during runtime.
-ORC_RT_INTERFACE struct jit_descriptor __jit_debug_descriptor = {
+//
+// The symbols below are part of the debugger's contract with the runtime, so
+// they use ORC_RT_C_EXPORT rather than ORC_RT_EXPORT: they must stay exported
+// even in builds that hide the C++ API. (They are already within the extern "C"
+// block opened above, so no linkage specifier is needed here.)
+ORC_RT_C_EXPORT struct jit_descriptor __jit_debug_descriptor = {
     JitDescriptorVersion, JIT_NOACTION, nullptr, nullptr};
 
 // Debuggers that implement the GDB JIT interface put a special breakpoint in
 // this function.
 #if defined(_MSC_VER)
-ORC_RT_INTERFACE void __jit_debug_register_code() {}
+ORC_RT_C_EXPORT void __jit_debug_register_code() {}
 #else
-ORC_RT_INTERFACE __attribute__((noinline)) void __jit_debug_register_code() {
+ORC_RT_C_EXPORT __attribute__((noinline)) void __jit_debug_register_code() {
   // The noinline attribute above and the asm volatile below prevent calls to
   // this function from being optimized out.
   asm volatile("" ::: "memory");



More information about the llvm-commits mailing list