[llvm] [BOLT] Add bolt-rt to runtimes (PR #187308)
Casey Smalley via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 05:50:58 PDT 2026
https://github.com/CaseySmalley updated https://github.com/llvm/llvm-project/pull/187308
>From a359cd327495a1731a6cf2da77261217572b4cf2 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Wed, 18 Mar 2026 13:36:47 +0000
Subject: [PATCH 01/13] [BOLT] Add bolt-rt to runtimes
Separate bolt-rt into the runtimes build. Bolt now looks for libraries
based on a triple.
This enables using bolt to instrument binaries across different
architectures.
[BOLT] tmp move
[BOLT] tmp move back
---
bolt-rt/CMakeLists.txt | 114 ++++++++++++++++++++++++
{bolt/runtime => bolt-rt}/common.h | 0
{bolt/runtime => bolt-rt}/config.h.in | 0
{bolt/runtime => bolt-rt}/hugify.cpp | 0
{bolt/runtime => bolt-rt}/instr.cpp | 0
{bolt/runtime => bolt-rt}/sys_aarch64.h | 0
{bolt/runtime => bolt-rt}/sys_riscv64.h | 0
{bolt/runtime => bolt-rt}/sys_x86_64.h | 0
bolt/CMakeLists.txt | 46 +---------
bolt/lib/RuntimeLibs/RuntimeLibrary.cpp | 12 +++
bolt/runtime/CMakeLists.txt | 86 ------------------
bolt/tools/driver/CMakeLists.txt | 15 +---
llvm/CMakeLists.txt | 7 +-
runtimes/CMakeLists.txt | 2 +-
14 files changed, 138 insertions(+), 144 deletions(-)
create mode 100644 bolt-rt/CMakeLists.txt
rename {bolt/runtime => bolt-rt}/common.h (100%)
rename {bolt/runtime => bolt-rt}/config.h.in (100%)
rename {bolt/runtime => bolt-rt}/hugify.cpp (100%)
rename {bolt/runtime => bolt-rt}/instr.cpp (100%)
rename {bolt/runtime => bolt-rt}/sys_aarch64.h (100%)
rename {bolt/runtime => bolt-rt}/sys_riscv64.h (100%)
rename {bolt/runtime => bolt-rt}/sys_x86_64.h (100%)
delete mode 100644 bolt/runtime/CMakeLists.txt
diff --git a/bolt-rt/CMakeLists.txt b/bolt-rt/CMakeLists.txt
new file mode 100644
index 0000000000000..2d7c3101d3dd1
--- /dev/null
+++ b/bolt-rt/CMakeLists.txt
@@ -0,0 +1,114 @@
+cmake_minimum_required(VERSION 3.20.0)
+
+include(CheckCXXCompilerFlag)
+include(CheckIncludeFiles)
+include(CMakeParseArguments)
+include(GNUInstallDirs)
+
+# Is this built via -DLLVM_ENABLE_RUNTIMES="bolt-rt"?.
+if(LLVM_RUNTIMES_BUILD)
+ set(LLVM_SUBPROJECT_TITLE "Bolt-RT")
+# Is this being built directly?
+elseif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ project(bolt-rt)
+endif()
+
+# Use LLVM_RUNTIMES_TARGET when built under runtimes.
+if(LLVM_RUNTIMES_BUILD)
+ set(BOLT_RT_TARGET_TRIPLE "${LLVM_RUNTIMES_TARGET}")
+endif()
+
+if(NOT BOLT_RT_TARGET_TRIPLE)
+ message(STATUS "bolt_rt: BOLT_RT_TARGET_TRIPLE is unset, building for the host.")
+ get_host_triple(BOLT_RT_TARGET_TRIPLE)
+endif()
+
+message(STATUS "bolt-rt: targeting ${BOLT_RT_TARGET_TRIPLE}")
+
+# Add custom target for runtime builds.
+if(LLVM_RUNTIMES_BUILD)
+ add_custom_target(bolt-rt)
+ set_target_properties(bolt-rt PROPERTIES FOLDER "BOLT-RT/Metatargets")
+ add_llvm_install_targets(install-bolt-rt
+ DEPENDS bolt-rt
+ COMPONENTS bolt-rt)
+endif()
+
+# For runtime builds, the installation directory is already known,
+# otherwise assume lib.
+if(LLVM_RUNTIMES_BUILD)
+ set(BOLT_RT_LIBRARY_DIR "${LLVM_LIBRARY_DIR}")
+else()
+ set(BOLT_RT_LIBRARY_DIR "lib${LLVM_LIBDIR_SUFFIX}")
+endif()
+
+if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
+ string(APPEND BOLT_RT_LIBRARY_DIR "/${BOLT_RT_TARGET_TRIPLE}")
+ set(BOLT_RT_ARCHIVE_SUFFIX "")
+else()
+ # TODO(casey.smalley at arm.com): Does this need to account for
+ # LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF?
+ message(FATAL_ERROR "bolt_rt: Not implemented.")
+endif()
+
+# Build flags.
+list(APPEND BOLT_RT_FLAGS
+ -ffreestanding
+ -fno-exceptions
+ -fno-rtti
+ -fno-stack-protector
+ -fPIC
+ # Runtime currently assumes omitted frame pointers for functions marked __attribute((naked)).
+ # Protect against distros adding -fno-omit-frame-pointer and compiling with GCC.
+ # Refs: llvm/llvm-project#148595 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77882
+ -fomit-frame-pointer)
+
+if(BOLT_RT_TARGET_TRIPLE MATCHES "x86_64")
+ list(APPEND BOLT_RT_FLAGS
+ -mno-sse
+ -mgeneral-regs-only)
+elseif(BOLT_RT_TARGET_TRIPLE MATCHES "aarch64")
+ check_cxx_compiler_flag("-mno-outline-atomics" CXX_SUPPORTS_OUTLINE_ATOMICS)
+
+ if(CXX_SUPPORTS_OUTLINE_ATOMICS)
+ list(APPEND BOLT_RT_FLAGS
+ -mno-outline-atomics
+ -mgeneral-regs-only)
+ endif()
+endif()
+
+# Build libraries.
+check_include_files(elf.h HAVE_ELF_H)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/config.h")
+
+function(add_bolt_rt_library)
+ cmake_parse_arguments(ARG "" "TARGET" "SOURCES;FLAGS" ${ARGN})
+ add_library(${ARG_TARGET} ${ARG_SOURCES})
+
+ # Don't let the compiler think it can create calls to standard libs
+ target_include_directories(${ARG_TARGET}
+ PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
+
+ target_compile_options(${ARG_TARGET}
+ PRIVATE ${BOLT_RT_FLAGS} ${ARG_FLAGS})
+
+ # Ouput archives into a per-triple path or with a per triple suffix.
+ set_target_properties(${ARG_TARGET} PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY "${BOLT_RT_LIBRARY_DIR}"
+ ARCHIVE_OUTPUT_NAME "${ARG_TARGET}${BOLT_RT_ARCHIVE_SUFFIX}")
+
+ if(LLVM_RUNTIMES_BUILD)
+ add_dependencies(bolt-rt ${ARG_TARGET})
+ endif()
+
+ # Install to a matching directory.
+ install(TARGETS ${ARG_TARGET}
+ DESTINATION "${BOLT_RT_LIBRARY_DIR}")
+endfunction()
+
+add_bolt_rt_library(TARGET bolt_rt_instr
+ SOURCES instr.cpp)
+
+add_bolt_rt_library(TARGET bolt_rt_hugify
+ SOURCES hugify.cpp)
diff --git a/bolt/runtime/common.h b/bolt-rt/common.h
similarity index 100%
rename from bolt/runtime/common.h
rename to bolt-rt/common.h
diff --git a/bolt/runtime/config.h.in b/bolt-rt/config.h.in
similarity index 100%
rename from bolt/runtime/config.h.in
rename to bolt-rt/config.h.in
diff --git a/bolt/runtime/hugify.cpp b/bolt-rt/hugify.cpp
similarity index 100%
rename from bolt/runtime/hugify.cpp
rename to bolt-rt/hugify.cpp
diff --git a/bolt/runtime/instr.cpp b/bolt-rt/instr.cpp
similarity index 100%
rename from bolt/runtime/instr.cpp
rename to bolt-rt/instr.cpp
diff --git a/bolt/runtime/sys_aarch64.h b/bolt-rt/sys_aarch64.h
similarity index 100%
rename from bolt/runtime/sys_aarch64.h
rename to bolt-rt/sys_aarch64.h
diff --git a/bolt/runtime/sys_riscv64.h b/bolt-rt/sys_riscv64.h
similarity index 100%
rename from bolt/runtime/sys_riscv64.h
rename to bolt-rt/sys_riscv64.h
diff --git a/bolt/runtime/sys_x86_64.h b/bolt-rt/sys_x86_64.h
similarity index 100%
rename from bolt/runtime/sys_x86_64.h
rename to bolt-rt/sys_x86_64.h
diff --git a/bolt/CMakeLists.txt b/bolt/CMakeLists.txt
index 5c7d51e1e398c..4458c237ebd9f 100644
--- a/bolt/CMakeLists.txt
+++ b/bolt/CMakeLists.txt
@@ -94,16 +94,6 @@ if ((CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
set(BOLT_ENABLE_RUNTIME_default ON)
endif()
option(BOLT_ENABLE_RUNTIME "Enable BOLT runtime" ${BOLT_ENABLE_RUNTIME_default})
-if (BOLT_ENABLE_RUNTIME)
- # Some systems prevent reading /proc/self/map_files
- execute_process(COMMAND ls /proc/self/map_files
- RESULT_VARIABLE LS OUTPUT_QUIET ERROR_QUIET)
- if (LS)
- message(WARNING
- "BOLT runtime may not be able to read /proc/self/map_files. Please use
- `--instrumentation-binpath <path-to-instrumented-binary>` option.")
- endif()
-endif()
set(BOLT_CLANG_EXE "" CACHE FILEPATH "Path to clang executable for the target \
architecture for use in BOLT tests")
@@ -140,38 +130,6 @@ if (LLVM_INCLUDE_TESTS)
endif()
endif()
-if (BOLT_ENABLE_RUNTIME)
- message(STATUS "Building BOLT runtime libraries for ${CMAKE_SYSTEM_PROCESSOR}")
- set(extra_args "")
- if(CMAKE_SYSROOT)
- list(APPEND extra_args -DCMAKE_SYSROOT=${CMAKE_SYSROOT})
- endif()
-
- include(ExternalProject)
- ExternalProject_Add(bolt_rt
- SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/runtime"
- STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/bolt_rt-stamps
- BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/bolt_rt-bins
- CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
- -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
- -DLLVM_LIBDIR_SUFFIX=${LLVM_LIBDIR_SUFFIX}
- -DLLVM_LIBRARY_DIR=${LLVM_LIBRARY_DIR}
- -DBOLT_BUILT_STANDALONE=${BOLT_BUILT_STANDALONE}
- ${extra_args}
- INSTALL_COMMAND ""
- BUILD_ALWAYS True
- )
- install(CODE "execute_process\(COMMAND \${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=\${CMAKE_INSTALL_PREFIX} -P ${CMAKE_CURRENT_BINARY_DIR}/bolt_rt-bins/cmake_install.cmake \)"
- COMPONENT bolt)
- add_llvm_install_targets(install-bolt_rt
- DEPENDS bolt_rt bolt
- COMPONENT bolt)
- set(LIBBOLT_RT_INSTR "${CMAKE_CURRENT_BINARY_DIR}/bolt_rt-bins/lib${LLVM_LIBDIR_SUFFIX}/libbolt_rt_instr.a")
- set(LIBBOLT_RT_HUGIFY "${CMAKE_CURRENT_BINARY_DIR}/bolt_rt-bins/lib${LLVM_LIBDIR_SUFFIX}/libbolt_rt_hugify.a")
-endif()
-
find_program(GNU_LD_EXECUTABLE NAMES ${LLVM_DEFAULT_TARGET_TRIPLE}-ld.bfd ld.bfd DOC "GNU ld")
include(AddBOLT)
@@ -183,6 +141,10 @@ add_custom_target(bolt)
set_target_properties(bolt PROPERTIES FOLDER "BOLT/Metatargets")
add_llvm_install_targets(install-bolt DEPENDS bolt COMPONENT bolt)
+if (bolt-rt IN_LIST LLVM_ENABLE_RUNTIMES)
+ add_dependencies(bolt bolt-rt)
+endif()
+
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include
diff --git a/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp b/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
index 98852ee691ceb..51f134e22e8e3 100644
--- a/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
+++ b/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
@@ -13,10 +13,14 @@
#include "bolt/RuntimeLibs/RuntimeLibrary.h"
#include "bolt/Core/Linker.h"
#include "bolt/RuntimeLibs/RuntimeLibraryVariables.inc"
+#include "bolt/Utils/CommandLineOpts.h"
#include "bolt/Utils/Utils.h"
#include "llvm/BinaryFormat/Magic.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
@@ -25,6 +29,12 @@
using namespace llvm;
using namespace bolt;
+namespace opts {
+static cl::opt<std::string> TargetTriple(
+ "target", cl::desc("Target triple used to select runtime libraries."),
+ cl::init(LLVM_DEFAULT_TARGET_TRIPLE), cl::cat(BoltOptCategory));
+} // namespace opts
+
void RuntimeLibrary::anchor() {}
std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,
@@ -32,6 +42,7 @@ std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,
StringRef Dir = llvm::sys::path::parent_path(ToolPath);
SmallString<128> LibPath = llvm::sys::path::parent_path(Dir);
llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);
+ llvm::sys::path::append(LibPath, opts::TargetTriple);
if (!llvm::sys::fs::exists(LibPath)) {
// In some cases we install bolt binary into one level deeper in bin/,
// we need to go back one more level to find lib directory.
@@ -61,6 +72,7 @@ std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,
std::string RuntimeLibrary::getLibPathByInstalled(StringRef LibFileName) {
SmallString<128> LibPath(CMAKE_INSTALL_FULL_LIBDIR);
+ llvm::sys::path::append(LibPath, opts::TargetTriple);
llvm::sys::path::append(LibPath, LibFileName);
return std::string(LibPath);
}
diff --git a/bolt/runtime/CMakeLists.txt b/bolt/runtime/CMakeLists.txt
deleted file mode 100644
index 63f178bd263c2..0000000000000
--- a/bolt/runtime/CMakeLists.txt
+++ /dev/null
@@ -1,86 +0,0 @@
-cmake_minimum_required(VERSION 3.20.0)
-include(CheckCXXCompilerFlag)
-include(CheckIncludeFiles)
-include(GNUInstallDirs)
-
-set(CMAKE_CXX_EXTENSIONS OFF)
-set(CMAKE_CXX_STANDARD 17)
-
-project(libbolt_rt_project)
-
-check_include_files(elf.h HAVE_ELF_H)
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
- ${CMAKE_CURRENT_BINARY_DIR}/config.h)
-
-add_library(bolt_rt_instr STATIC
- instr.cpp
- ${CMAKE_CURRENT_BINARY_DIR}/config.h
- )
-set_target_properties(bolt_rt_instr PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "lib${LLVM_LIBDIR_SUFFIX}")
-add_library(bolt_rt_hugify STATIC
- hugify.cpp
- ${CMAKE_CURRENT_BINARY_DIR}/config.h
- )
-set_target_properties(bolt_rt_hugify PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "lib${LLVM_LIBDIR_SUFFIX}")
-
-if(NOT BOLT_BUILT_STANDALONE)
- add_custom_command(TARGET bolt_rt_instr POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/libbolt_rt_instr.a" "${LLVM_LIBRARY_DIR}")
- add_custom_command(TARGET bolt_rt_hugify POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/libbolt_rt_hugify.a" "${LLVM_LIBRARY_DIR}")
-endif()
-
-set(BOLT_RT_FLAGS
- -ffreestanding
- -fno-exceptions
- -fno-rtti
- -fno-stack-protector
- -fPIC
- # Runtime currently assumes omitted frame pointers for functions marked __attribute((naked)).
- # Protect against distros adding -fno-omit-frame-pointer and compiling with GCC.
- # Refs: llvm/llvm-project#148595 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77882
- -fomit-frame-pointer
-)
-if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
- set(BOLT_RT_FLAGS ${BOLT_RT_FLAGS}
- -mno-sse
- -mgeneral-regs-only)
-endif()
-if (CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64")
- set(BOLT_RT_FLAGS ${BOLT_RT_FLAGS})
-endif()
-if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
- check_cxx_compiler_flag("-mno-outline-atomics" CXX_SUPPORTS_OUTLINE_ATOMICS)
- if (CXX_SUPPORTS_OUTLINE_ATOMICS)
- set(BOLT_RT_FLAGS ${BOLT_RT_FLAGS}
- -mno-outline-atomics
- -mgeneral-regs-only)
- endif()
-endif()
-
-# Don't let the compiler think it can create calls to standard libs
-target_compile_options(bolt_rt_instr PRIVATE ${BOLT_RT_FLAGS})
-target_include_directories(bolt_rt_instr PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-target_compile_options(bolt_rt_hugify PRIVATE ${BOLT_RT_FLAGS})
-target_include_directories(bolt_rt_hugify PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-
-install(TARGETS bolt_rt_instr DESTINATION "lib${LLVM_LIBDIR_SUFFIX}")
-install(TARGETS bolt_rt_hugify DESTINATION "lib${LLVM_LIBDIR_SUFFIX}")
-
-if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*" AND CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- add_library(bolt_rt_instr_osx STATIC
- instr.cpp
- ${CMAKE_CURRENT_BINARY_DIR}/config.h
- )
- set_target_properties(bolt_rt_instr_osx PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "lib${LLVM_LIBDIR_SUFFIX}")
- target_include_directories(bolt_rt_instr_osx PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
- target_compile_options(bolt_rt_instr_osx PRIVATE
- -target x86_64-apple-darwin19.6.0
- ${BOLT_RT_FLAGS})
- install(TARGETS bolt_rt_instr_osx DESTINATION "lib${LLVM_LIBDIR_SUFFIX}")
-
- if(NOT BOLT_BUILT_STANDALONE)
- add_custom_command(TARGET bolt_rt_instr_osx POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/libbolt_rt_instr_osx.a" "${LLVM_LIBRARY_DIR}")
- endif()
-endif()
diff --git a/bolt/tools/driver/CMakeLists.txt b/bolt/tools/driver/CMakeLists.txt
index 4b3c7416de974..52cbd9d30cd7c 100644
--- a/bolt/tools/driver/CMakeLists.txt
+++ b/bolt/tools/driver/CMakeLists.txt
@@ -5,20 +5,7 @@ set(LLVM_LINK_COMPONENTS
Support
)
-if (BOLT_ENABLE_RUNTIME)
- set(BOLT_DRIVER_DEPS "bolt_rt")
-else()
- set(BOLT_DRIVER_DEPS "")
-endif()
-
-add_bolt_tool(llvm-bolt
- llvm-bolt.cpp
-
- DISABLE_LLVM_LINK_LLVM_DYLIB
-
- DEPENDS
- ${BOLT_DRIVER_DEPS}
- )
+add_bolt_tool(llvm-bolt llvm-bolt.cpp DISABLE_LLVM_LINK_LLVM_DYLIB)
target_link_libraries(llvm-bolt
PRIVATE
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 6001928f92e37..7e211f87a4e2a 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -164,7 +164,7 @@ endforeach()
# As we migrate runtimes to using the bootstrapping build, the set of default runtimes
# should grow as we remove those runtimes from LLVM_ENABLE_PROJECTS above.
set(LLVM_DEFAULT_RUNTIMES "libcxx;libcxxabi;libunwind;libclc;compiler-rt;openmp")
-set(LLVM_SUPPORTED_RUNTIMES "libc;libunwind;libcxxabi;libcxx;compiler-rt;openmp;llvm-libgcc;offload;flang-rt;libclc;libsycl;orc-rt")
+set(LLVM_SUPPORTED_RUNTIMES "bolt-rt;libc;libunwind;libcxxabi;libcxx;compiler-rt;openmp;llvm-libgcc;offload;flang-rt;libclc;libsycl;orc-rt")
set(LLVM_ENABLE_RUNTIMES "" CACHE STRING
"Semicolon-separated list of runtimes to build, or \"all\" (${LLVM_DEFAULT_RUNTIMES}). Supported runtimes are ${LLVM_SUPPORTED_RUNTIMES}.")
if(LLVM_ENABLE_RUNTIMES STREQUAL "all")
@@ -716,6 +716,11 @@ if("flang" IN_LIST LLVM_ENABLE_PROJECTS AND
list(APPEND LLVM_ENABLE_RUNTIMES "compiler-rt")
endif()
+if("bolt" IN_LIST LLVM_ENABLE_PROJECTS AND NOT ("bolt-rt" IN_LIST LLVM_ENABLE_RUNTIMES))
+ message(STATUS "Enabling bolt-rt as a dependency of bolt.")
+ list(APPEND LLVM_ENABLE_RUNTIMES "bolt-rt")
+endif()
+
set(LLVM_TARGETS_TO_BUILD
${LLVM_TARGETS_TO_BUILD}
${LLVM_EXPERIMENTAL_TARGETS_TO_BUILD})
diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index eba41b8b10ac4..bd1e31c41bed7 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -37,7 +37,7 @@ list(INSERT CMAKE_MODULE_PATH 0
# compiler-rt can depend on libc++, so we put it after. Offload can depend on
# flang-rt so we order it before.
set(LLVM_DEFAULT_RUNTIMES "libc;libunwind;libcxxabi;libcxx;compiler-rt;libclc;openmp;offload")
-set(LLVM_SUPPORTED_RUNTIMES "libc;libunwind;libcxxabi;libcxx;compiler-rt;libclc;openmp;flang-rt;offload;llvm-libgcc;libsycl;orc-rt")
+set(LLVM_SUPPORTED_RUNTIMES "libc;libunwind;libcxxabi;libcxx;compiler-rt;libclc;openmp;flang-rt;offload;llvm-libgcc;libsycl;orc-rt;bolt-rt")
set(LLVM_ENABLE_RUNTIMES "" CACHE STRING
"Semicolon-separated list of runtimes to build, or \"all\" (${LLVM_DEFAULT_RUNTIMES}). Supported runtimes are ${LLVM_SUPPORTED_RUNTIMES}.")
if(LLVM_ENABLE_RUNTIMES STREQUAL "all" )
>From e485b44b4004a3a02f6a3099e58a636253207d0b Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Mon, 23 Mar 2026 09:56:18 +0000
Subject: [PATCH 02/13] [BOLT] remove unused cmake code
---
bolt/CMakeLists.txt | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/bolt/CMakeLists.txt b/bolt/CMakeLists.txt
index 4458c237ebd9f..2bc4ca26e7a4d 100644
--- a/bolt/CMakeLists.txt
+++ b/bolt/CMakeLists.txt
@@ -84,17 +84,6 @@ foreach (tgt ${BOLT_TARGETS_TO_BUILD})
message(STATUS "Targeting ${tgt} in llvm-bolt")
endforeach()
-set(BOLT_ENABLE_RUNTIME_default OFF)
-if ((CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
- OR CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$"
- OR CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
- AND (CMAKE_SYSTEM_NAME STREQUAL "Linux"
- OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- AND (NOT CMAKE_CROSSCOMPILING))
- set(BOLT_ENABLE_RUNTIME_default ON)
-endif()
-option(BOLT_ENABLE_RUNTIME "Enable BOLT runtime" ${BOLT_ENABLE_RUNTIME_default})
-
set(BOLT_CLANG_EXE "" CACHE FILEPATH "Path to clang executable for the target \
architecture for use in BOLT tests")
set(BOLT_LLD_EXE "" CACHE FILEPATH "Path to lld executable for the target \
>From 333a3e30ade754cb24cb140694fc9dcc6f09a6a1 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Mon, 23 Mar 2026 09:56:45 +0000
Subject: [PATCH 03/13] [BOLT] Restore missing bolt-rt dependency
---
bolt/test/CMakeLists.txt | 6 ++++++
bolt/tools/driver/CMakeLists.txt | 15 ++++++++++++++-
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/bolt/test/CMakeLists.txt b/bolt/test/CMakeLists.txt
index 6e18b028bddfc..0f19de43ff2e9 100644
--- a/bolt/test/CMakeLists.txt
+++ b/bolt/test/CMakeLists.txt
@@ -1,3 +1,9 @@
+if("bolt-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
+ set(BOLT_ENABLE_RUNTIME ON)
+else()
+ set(BOLT_ENABLE_RUNTIME OFF)
+endif()
+
llvm_canonicalize_cmake_booleans(
BOLT_ENABLE_RUNTIME
)
diff --git a/bolt/tools/driver/CMakeLists.txt b/bolt/tools/driver/CMakeLists.txt
index 52cbd9d30cd7c..fbb655cb4b3fd 100644
--- a/bolt/tools/driver/CMakeLists.txt
+++ b/bolt/tools/driver/CMakeLists.txt
@@ -5,7 +5,20 @@ set(LLVM_LINK_COMPONENTS
Support
)
-add_bolt_tool(llvm-bolt llvm-bolt.cpp DISABLE_LLVM_LINK_LLVM_DYLIB)
+if ("bolt-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
+ set(BOLT_DRIVER_DEPS "bolt-rt")
+else()
+ set(BOLT_DRIVER_DEPS "")
+endif()
+
+add_bolt_tool(llvm-bolt
+ llvm-bolt.cpp
+
+ DISABLE_LLVM_LINK_LLVM_DYLIB
+
+ DEPENDS
+ ${BOLT_DRIVER_DEPS}
+ )
target_link_libraries(llvm-bolt
PRIVATE
>From 38f86611ebdaa1d12289964e5b9bf5e12988b4e7 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Mon, 23 Mar 2026 12:23:30 +0000
Subject: [PATCH 04/13] [BOLT] add --target for clang compilers
---
bolt-rt/CMakeLists.txt | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/bolt-rt/CMakeLists.txt b/bolt-rt/CMakeLists.txt
index 2d7c3101d3dd1..22b3d06963348 100644
--- a/bolt-rt/CMakeLists.txt
+++ b/bolt-rt/CMakeLists.txt
@@ -23,6 +23,15 @@ if(NOT BOLT_RT_TARGET_TRIPLE)
get_host_triple(BOLT_RT_TARGET_TRIPLE)
endif()
+# Append --target for clang compilers. Otherwise it is assumed that
+# one of the following has been configured.
+# 1. CMAKE_CXX_FLAGS for stand alone builds.
+# 2. RUNTIMES_<target-triple>_CMAKE_CXX_FLAGS for runtime builds.
+if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ list(APPEND BOLT_RT_FLAGS
+ "--target=${BOLT_RT_TARGET_TRIPLE}")
+endif()
+
message(STATUS "bolt-rt: targeting ${BOLT_RT_TARGET_TRIPLE}")
# Add custom target for runtime builds.
>From 67404911bace88f484d2cc65585fee506be150c7 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Mon, 23 Mar 2026 13:23:46 +0000
Subject: [PATCH 05/13] [BOLT] Assume LLVM_ENABLE_PER_TARGET_RUNTIME_DIR
---
bolt-rt/CMakeLists.txt | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/bolt-rt/CMakeLists.txt b/bolt-rt/CMakeLists.txt
index 22b3d06963348..9538fc8d6151a 100644
--- a/bolt-rt/CMakeLists.txt
+++ b/bolt-rt/CMakeLists.txt
@@ -51,14 +51,9 @@ else()
set(BOLT_RT_LIBRARY_DIR "lib${LLVM_LIBDIR_SUFFIX}")
endif()
-if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
- string(APPEND BOLT_RT_LIBRARY_DIR "/${BOLT_RT_TARGET_TRIPLE}")
- set(BOLT_RT_ARCHIVE_SUFFIX "")
-else()
- # TODO(casey.smalley at arm.com): Does this need to account for
- # LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF?
- message(FATAL_ERROR "bolt_rt: Not implemented.")
-endif()
+# Act as if LLVM_ENABLE_PER_TARGET_RUNTIME_DIR is always true.
+string(APPEND BOLT_RT_LIBRARY_DIR "/bolt/${BOLT_RT_TARGET_TRIPLE}")
+set(BOLT_RT_ARCHIVE_SUFFIX "")
# Build flags.
list(APPEND BOLT_RT_FLAGS
>From 2f1c3489eb04c98515d2758b4173cd9117c9f581 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Mon, 23 Mar 2026 13:35:56 +0000
Subject: [PATCH 06/13] [BOLT] Fix runtime lookup path
---
bolt/lib/RuntimeLibs/RuntimeLibrary.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp b/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
index 51f134e22e8e3..0dd9511293b45 100644
--- a/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
+++ b/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
@@ -42,13 +42,14 @@ std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,
StringRef Dir = llvm::sys::path::parent_path(ToolPath);
SmallString<128> LibPath = llvm::sys::path::parent_path(Dir);
llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);
- llvm::sys::path::append(LibPath, opts::TargetTriple);
if (!llvm::sys::fs::exists(LibPath)) {
// In some cases we install bolt binary into one level deeper in bin/,
// we need to go back one more level to find lib directory.
LibPath = llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir));
llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);
}
+ llvm::sys::path::append(LibPath, "bolt");
+ llvm::sys::path::append(LibPath, opts::TargetTriple);
llvm::sys::path::append(LibPath, LibFileName);
if (!llvm::sys::fs::exists(LibPath)) {
// If it is a symlink, check the directory that the symlink points to.
@@ -72,6 +73,7 @@ std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,
std::string RuntimeLibrary::getLibPathByInstalled(StringRef LibFileName) {
SmallString<128> LibPath(CMAKE_INSTALL_FULL_LIBDIR);
+ llvm::sys::path::append(LibPath, "bolt");
llvm::sys::path::append(LibPath, opts::TargetTriple);
llvm::sys::path::append(LibPath, LibFileName);
return std::string(LibPath);
>From d5df9a0a20bb9c8ed3bf63ef52f8fe5127b0e3f2 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Mon, 23 Mar 2026 15:33:57 +0000
Subject: [PATCH 07/13] [BOLT] suppress bolt-rt warnings
---
bolt-rt/CMakeLists.txt | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/bolt-rt/CMakeLists.txt b/bolt-rt/CMakeLists.txt
index 9538fc8d6151a..cb6840364337c 100644
--- a/bolt-rt/CMakeLists.txt
+++ b/bolt-rt/CMakeLists.txt
@@ -32,6 +32,15 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
"--target=${BOLT_RT_TARGET_TRIPLE}")
endif()
+# TODO: Fix reported warnings.
+list(APPEND BOLT_RT_FLAGS
+ -Wno-unused-function
+ -Wno-unused-variable
+ -Wno-unused-but-set-variable
+ -Wno-cast-qual
+ -Wno-sign-compare
+ -Wno-unknown-attributes)
+
message(STATUS "bolt-rt: targeting ${BOLT_RT_TARGET_TRIPLE}")
# Add custom target for runtime builds.
>From 2fced6bbcc7c3c3310a497475bfe6c34c27e5ed2 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Mon, 23 Mar 2026 15:52:33 +0000
Subject: [PATCH 08/13] [BOLT] apply clang-format
---
bolt-rt/common.h | 12 +++----
bolt-rt/instr.cpp | 88 +++++++++++++++++++++--------------------------
2 files changed, 45 insertions(+), 55 deletions(-)
diff --git a/bolt-rt/common.h b/bolt-rt/common.h
index 8689bc8b72041..2ee7c21870c01 100644
--- a/bolt-rt/common.h
+++ b/bolt-rt/common.h
@@ -21,12 +21,12 @@
typedef __SIZE_TYPE__ size_t;
#define __SSIZE_TYPE__ \
- __typeof__(_Generic((__SIZE_TYPE__)0, unsigned long long int \
- : (long long int)0, unsigned long int \
- : (long int)0, unsigned int \
- : (int)0, unsigned short \
- : (short)0, unsigned char \
- : (signed char)0))
+ __typeof__(_Generic((__SIZE_TYPE__)0, \
+ unsigned long long int: (long long int)0, \
+ unsigned long int: (long int)0, \
+ unsigned int: (int)0, \
+ unsigned short: (short)0, \
+ unsigned char: (signed char)0))
typedef __SSIZE_TYPE__ ssize_t;
typedef unsigned long long uint64_t;
diff --git a/bolt-rt/instr.cpp b/bolt-rt/instr.cpp
index 3470e391224ba..a34555b0c96a0 100644
--- a/bolt-rt/instr.cpp
+++ b/bolt-rt/instr.cpp
@@ -43,7 +43,7 @@
#include "common.h"
// Enables a very verbose logging to stderr useful when debugging
-//#define ENABLE_DEBUG
+// #define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DEBUG(X) \
@@ -58,10 +58,10 @@
extern "C" {
#if defined(__APPLE__)
-extern uint64_t* _bolt_instr_locations_getter();
+extern uint64_t *_bolt_instr_locations_getter();
extern uint32_t _bolt_num_counters_getter();
-extern uint8_t* _bolt_instr_tables_getter();
+extern uint8_t *_bolt_instr_tables_getter();
extern uint32_t _bolt_instr_num_funcs_getter();
#else
@@ -134,7 +134,8 @@ class BumpPtrAllocator {
#if defined(__ANDROID__)
__attribute__((noinline))
#endif
- void *allocate(size_t Size) {
+ void *
+ allocate(size_t Size) {
Lock L(M);
if (StackBase == nullptr) {
@@ -164,7 +165,8 @@ class BumpPtrAllocator {
#if defined(__ANDROID__)
__attribute__((noinline))
#endif
- void deallocate(void *Ptr) {
+ void
+ deallocate(void *Ptr) {
Lock L(M);
uint8_t MetadataOffset = sizeof(EntryMetadata);
auto *M = reinterpret_cast<EntryMetadata *>(
@@ -243,9 +245,7 @@ void *operator new(size_t Sz, BumpPtrAllocator &A, char C) {
memset(Ptr, C, Sz);
return Ptr;
}
-void *operator new[](size_t Sz, BumpPtrAllocator &A) {
- return A.allocate(Sz);
-}
+void *operator new[](size_t Sz, BumpPtrAllocator &A) { return A.allocate(Sz); }
void *operator new[](size_t Sz, BumpPtrAllocator &A, char C) {
auto *Ptr = reinterpret_cast<char *>(A.allocate(Sz));
memset(Ptr, C, Sz);
@@ -414,8 +414,8 @@ class SimpleHashTable {
// Defer to the next level
if (Entry.Key & FollowUpTableMarker) {
return getEntry(
- reinterpret_cast<MapEntry *>(Entry.Key & ~FollowUpTableMarker),
- Key, Remainder, Alloc, CurLevel + 1);
+ reinterpret_cast<MapEntry *>(Entry.Key & ~FollowUpTableMarker), Key,
+ Remainder, Alloc, CurLevel + 1);
}
// Conflict - create the next level
@@ -449,9 +449,7 @@ class SimpleHashTable {
}
};
-template <typename T> void resetIndCallCounter(T &Entry) {
- Entry.Val = 0;
-}
+template <typename T> void resetIndCallCounter(T &Entry) { Entry.Val = 0; }
template <typename T, uint32_t X, uint32_t Y>
void SimpleHashTable<T, X, Y>::resetCounters() {
@@ -582,10 +580,10 @@ struct ProfileWriterContext {
const IndCallTargetDescription *IndCallTargets;
const uint8_t *FuncDescriptions;
const char *Strings; // String table with function names used in this binary
- int FileDesc; // File descriptor for the file on disk backing this
- // information in memory via mmap
+ int FileDesc; // File descriptor for the file on disk backing this
+ // information in memory via mmap
const void *MMapPtr; // The mmap ptr
- int MMapSize; // The mmap size
+ int MMapSize; // The mmap size
/// Hash table storing all possible call destinations to detect untracked
/// calls and correctly report them as [unknown] in output fdata.
@@ -612,8 +610,9 @@ int compareStr(const char *Str1, const char *Str2, int Size) {
#if defined(__ANDROID__)
__attribute__((noinline))
#endif
-char *serializeLoc(const ProfileWriterContext &Ctx, char *OutBuf,
- const Location Loc, uint32_t BufSize) {
+char *
+serializeLoc(const ProfileWriterContext &Ctx, char *OutBuf, const Location Loc,
+ uint32_t BufSize) {
// fdata location format: Type Name Offset
// Type 1 - regular symbol
OutBuf = strCopy(OutBuf, "1 ");
@@ -860,7 +859,6 @@ void printStats(const ProfileWriterContext &Ctx) {
}
#endif
-
/// This is part of a simple CFG representation in memory, where we store
/// a dynamically sized array of input and output edges per node, and store
/// a dynamically sized array of nodes per graph. We also store the spanning
@@ -948,8 +946,8 @@ Graph::Graph(BumpPtrAllocator &Alloc, const FunctionDescription &D,
DEBUG(reportNumber("G->CFGNodes = 0x", (uint64_t)CFGNodes, 16));
SpanningTreeNodes = new (Alloc) Node[MaxNodes];
- DEBUG(reportNumber("G->SpanningTreeNodes = 0x",
- (uint64_t)SpanningTreeNodes, 16));
+ DEBUG(reportNumber("G->SpanningTreeNodes = 0x", (uint64_t)SpanningTreeNodes,
+ 16));
// Figure out how much to allocate to each vector (in/out edge sets)
for (int I = 0; I < D.NumEdges; ++I) {
@@ -995,13 +993,11 @@ Graph::Graph(BumpPtrAllocator &Alloc, const FunctionDescription &D,
if (D.Edges[I].Counter != 0xffffffff)
continue;
- E = &SpanningTreeNodes[Src]
- .OutEdges[SpanningTreeNodes[Src].NumOutEdges++];
+ E = &SpanningTreeNodes[Src].OutEdges[SpanningTreeNodes[Src].NumOutEdges++];
E->Node = Dst;
E->ID = I;
- E = &SpanningTreeNodes[Dst]
- .InEdges[SpanningTreeNodes[Dst].NumInEdges++];
+ E = &SpanningTreeNodes[Dst].InEdges[SpanningTreeNodes[Dst].NumInEdges++];
E->Node = Src;
E->ID = I;
}
@@ -1148,8 +1144,8 @@ void Graph::computeEdgeFrequencies(const uint64_t *Counters,
if (NumNodes == 0)
return;
- EdgeFreqs = D.NumEdges ? new (Alloc, 0) uint64_t [D.NumEdges] : nullptr;
- CallFreqs = D.NumCalls ? new (Alloc, 0) uint64_t [D.NumCalls] : nullptr;
+ EdgeFreqs = D.NumEdges ? new (Alloc, 0) uint64_t[D.NumEdges] : nullptr;
+ CallFreqs = D.NumCalls ? new (Alloc, 0) uint64_t[D.NumCalls] : nullptr;
// Setup a lookup for calls present in each node (BB)
NodeToCallsMap *CallMap = new (Alloc) NodeToCallsMap(Alloc, D, NumNodes);
@@ -1158,7 +1154,7 @@ void Graph::computeEdgeFrequencies(const uint64_t *Counters,
// spanning tree don't have explicit counters. We must infer their value using
// a linear combination of other counters (sum of counters of the outgoing
// edges minus sum of counters of the incoming edges).
- uint32_t *Stack = new (Alloc) uint32_t [NumNodes];
+ uint32_t *Stack = new (Alloc) uint32_t[NumNodes];
uint32_t StackTop = 0;
enum Status : uint8_t { S_NEW = 0, S_VISITING, S_VISITED };
Status *Visited = new (Alloc, 0) Status[NumNodes];
@@ -1179,8 +1175,8 @@ void Graph::computeEdgeFrequencies(const uint64_t *Counters,
for (int I = 0; I < D.NumEntryNodes; ++I) {
EntryAddress[D.EntryNodes[I].Node] = D.EntryNodes[I].Address;
DEBUG({
- reportNumber("Entry Node# ", D.EntryNodes[I].Node, 10);
- reportNumber(" Address: ", D.EntryNodes[I].Address, 16);
+ reportNumber("Entry Node# ", D.EntryNodes[I].Node, 10);
+ reportNumber(" Address: ", D.EntryNodes[I].Address, 16);
});
}
// Add all root nodes to the stack
@@ -1413,9 +1409,8 @@ ProfileWriterContext::lookupIndCallTarget(uint64_t Target) const {
}
/// Write a single indirect call <src, target> pair to the fdata file
-void visitIndCallCounter(IndirectCallHashTable::MapEntry &Entry,
- int FD, int CallsiteID,
- ProfileWriterContext *Ctx) {
+void visitIndCallCounter(IndirectCallHashTable::MapEntry &Entry, int FD,
+ int CallsiteID, ProfileWriterContext *Ctx) {
if (Entry.Val == 0)
return;
DEBUG(reportNumber("Target func 0x", Entry.Key, 16));
@@ -1506,8 +1501,8 @@ int openProfile() {
if (static_cast<int64_t>(FD) < 0) {
report("Error while trying to open profile file for writing: ");
report(Buf);
- reportNumber("\nFailed with error number: 0x",
- 0 - static_cast<int64_t>(FD), 16);
+ reportNumber("\nFailed with error number: 0x", 0 - static_cast<int64_t>(FD),
+ 16);
__exit(1);
}
return FD;
@@ -1713,8 +1708,7 @@ instrumentIndirectCall(uint64_t Target, uint64_t IndCallID) {
/// We receive as in-stack arguments the identifier of the indirect call site
/// as well as the target address for the call
-extern "C" __attribute((naked)) void __bolt_instr_indirect_call()
-{
+extern "C" __attribute((naked)) void __bolt_instr_indirect_call() {
#if defined(__aarch64__)
// clang-format off
__asm__ __volatile__(SAVE_ALL
@@ -1748,8 +1742,7 @@ extern "C" __attribute((naked)) void __bolt_instr_indirect_call()
#endif
}
-extern "C" __attribute((naked)) void __bolt_instr_indirect_tailcall()
-{
+extern "C" __attribute((naked)) void __bolt_instr_indirect_tailcall() {
#if defined(__aarch64__)
// clang-format off
__asm__ __volatile__(SAVE_ALL
@@ -1783,8 +1776,7 @@ extern "C" __attribute((naked)) void __bolt_instr_indirect_tailcall()
}
/// This is hooking ELF's entry, it needs to save all machine state.
-extern "C" __attribute((naked)) void __bolt_instr_start()
-{
+extern "C" __attribute((naked)) void __bolt_instr_start() {
#if defined(__aarch64__)
// clang-format off
__asm__ __volatile__(SAVE_ALL
@@ -1872,10 +1864,9 @@ extern "C" void __bolt_instr_data_dump() {
// On OSX/iOS the final symbol name of an extern "C" function/variable contains
// one extra leading underscore: _bolt_instr_setup -> __bolt_instr_setup.
-extern "C"
-__attribute__((section("__TEXT,__setup")))
-__attribute__((force_align_arg_pointer))
-void _bolt_instr_setup() {
+extern "C" __attribute__((section("__TEXT,__setup")))
+__attribute__((force_align_arg_pointer)) void
+_bolt_instr_setup() {
__asm__ __volatile__(SAVE_ALL :::);
report("Hello!\n");
@@ -1883,10 +1874,9 @@ void _bolt_instr_setup() {
__asm__ __volatile__(RESTORE_ALL :::);
}
-extern "C"
-__attribute__((section("__TEXT,__fini")))
-__attribute__((force_align_arg_pointer))
-void _bolt_instr_fini() {
+extern "C" __attribute__((section("__TEXT,__fini")))
+__attribute__((force_align_arg_pointer)) void
+_bolt_instr_fini() {
report("Bye!\n");
__bolt_instr_data_dump();
}
>From b3bc9c3114f8b4fa37ab5f30ff1c25be0779b88b Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Mon, 23 Mar 2026 16:45:12 +0000
Subject: [PATCH 09/13] [BOLT] fix install paths
---
bolt-rt/CMakeLists.txt | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/bolt-rt/CMakeLists.txt b/bolt-rt/CMakeLists.txt
index cb6840364337c..870569b72a1c4 100644
--- a/bolt-rt/CMakeLists.txt
+++ b/bolt-rt/CMakeLists.txt
@@ -49,7 +49,7 @@ if(LLVM_RUNTIMES_BUILD)
set_target_properties(bolt-rt PROPERTIES FOLDER "BOLT-RT/Metatargets")
add_llvm_install_targets(install-bolt-rt
DEPENDS bolt-rt
- COMPONENTS bolt-rt)
+ COMPONENT bolt-rt)
endif()
# For runtime builds, the installation directory is already known,
@@ -61,8 +61,7 @@ else()
endif()
# Act as if LLVM_ENABLE_PER_TARGET_RUNTIME_DIR is always true.
-string(APPEND BOLT_RT_LIBRARY_DIR "/bolt/${BOLT_RT_TARGET_TRIPLE}")
-set(BOLT_RT_ARCHIVE_SUFFIX "")
+set(BOLT_RT_LIBRARY_SUBDIR "/bolt/${BOLT_RT_TARGET_TRIPLE}")
# Build flags.
list(APPEND BOLT_RT_FLAGS
@@ -108,8 +107,8 @@ function(add_bolt_rt_library)
# Ouput archives into a per-triple path or with a per triple suffix.
set_target_properties(${ARG_TARGET} PROPERTIES
- ARCHIVE_OUTPUT_DIRECTORY "${BOLT_RT_LIBRARY_DIR}"
- ARCHIVE_OUTPUT_NAME "${ARG_TARGET}${BOLT_RT_ARCHIVE_SUFFIX}")
+ ARCHIVE_OUTPUT_DIRECTORY "${BOLT_RT_LIBRARY_DIR}/${BOLT_RT_LIBRARY_SUBDIR}"
+ ARCHIVE_OUTPUT_NAME "${ARG_TARGET}")
if(LLVM_RUNTIMES_BUILD)
add_dependencies(bolt-rt ${ARG_TARGET})
@@ -117,7 +116,15 @@ function(add_bolt_rt_library)
# Install to a matching directory.
install(TARGETS ${ARG_TARGET}
- DESTINATION "${BOLT_RT_LIBRARY_DIR}")
+ ARCHIVE
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/${BOLT_RT_LIBRARY_SUBDIR}"
+ COMPONENT bolt-rt)
+
+ if(NOT LLVM_ENABLE_IDE)
+ add_llvm_install_targets(install-${ARG_TARGET}
+ DEPENDS ${ARG_TARGET}
+ COMPONENT bolt-rt)
+ endif()
endfunction()
add_bolt_rt_library(TARGET bolt_rt_instr
>From 51968e03ed7ad80a0204803851ac240329859550 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Wed, 15 Apr 2026 14:40:34 +0100
Subject: [PATCH 10/13] [BOLT] update docs
---
bolt-rt/CMakeLists.txt | 2 +-
bolt/docs/RuntimeLibrary.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/bolt-rt/CMakeLists.txt b/bolt-rt/CMakeLists.txt
index 870569b72a1c4..0ebb2a9dcf3f4 100644
--- a/bolt-rt/CMakeLists.txt
+++ b/bolt-rt/CMakeLists.txt
@@ -105,7 +105,7 @@ function(add_bolt_rt_library)
target_compile_options(${ARG_TARGET}
PRIVATE ${BOLT_RT_FLAGS} ${ARG_FLAGS})
- # Ouput archives into a per-triple path or with a per triple suffix.
+ # Ouput archives into a per-triple path.
set_target_properties(${ARG_TARGET} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${BOLT_RT_LIBRARY_DIR}/${BOLT_RT_LIBRARY_SUBDIR}"
ARCHIVE_OUTPUT_NAME "${ARG_TARGET}")
diff --git a/bolt/docs/RuntimeLibrary.md b/bolt/docs/RuntimeLibrary.md
index b969ebd3e3547..b5f6c65120e02 100644
--- a/bolt/docs/RuntimeLibrary.md
+++ b/bolt/docs/RuntimeLibrary.md
@@ -15,7 +15,7 @@ However, this approach quickly becomes awkward if we want to insert a lot of cod
Currently, our runtime library is written in C++ and contains code that helps us instrument a binary.
### Limitations
-Our library is not written with regular C++ code as it is not linked against any other libraries (this means we cannot rely on anything defined on libstdc++, glibc, libgcc etc), but is self sufficient. In runtime/CMakeLists.txt, we can see it is built with -ffreestanding, which requires the compiler to avoid using a runtime library by itself.
+Our library is not written with regular C++ code as it is not linked against any other libraries (this means we cannot rely on anything defined on libstdc++, glibc, libgcc etc), but is self sufficient. In bolt-rt/CMakeLists.txt, we can see it is built with -ffreestanding, which requires the compiler to avoid using a runtime library by itself.
While this requires us to make our own syscalls, it does simplify our linker a lot, which is very limited and can only do basic function name resolving. However, this is a big improvement in comparison with programmatically generating the code in assembly language using MCInsts.
>From aae2113d3b24425d77a0fd64a00c4ed9ddbad48a Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Wed, 15 Apr 2026 14:40:46 +0100
Subject: [PATCH 11/13] [BOLT] fix section-orders.test
---
bolt-rt/CMakeLists.txt | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/bolt-rt/CMakeLists.txt b/bolt-rt/CMakeLists.txt
index 0ebb2a9dcf3f4..9390bad2f0f6a 100644
--- a/bolt-rt/CMakeLists.txt
+++ b/bolt-rt/CMakeLists.txt
@@ -32,14 +32,20 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
"--target=${BOLT_RT_TARGET_TRIPLE}")
endif()
-# TODO: Fix reported warnings.
list(APPEND BOLT_RT_FLAGS
+ # TODO: Fix reported warnings.
-Wno-unused-function
-Wno-unused-variable
-Wno-unused-but-set-variable
-Wno-cast-qual
-Wno-sign-compare
- -Wno-unknown-attributes)
+ -Wno-unknown-attributes
+ # Disable function/data sections, these are set in
+ # llvm/cmake/modules/HandleLLVMOptions.cmake.
+ # Leaving them turned on breaks
+ # bolt/test/runtimes/X86/section-order.test.
+ -fno-function-sections
+ -fno-data-sections)
message(STATUS "bolt-rt: targeting ${BOLT_RT_TARGET_TRIPLE}")
@@ -102,6 +108,9 @@ function(add_bolt_rt_library)
target_include_directories(${ARG_TARGET}
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
+ # Use C++17
+ target_compile_features(${ARG_TARGET} PUBLIC cxx_std_17)
+
target_compile_options(${ARG_TARGET}
PRIVATE ${BOLT_RT_FLAGS} ${ARG_FLAGS})
>From b7f94e11e2cf452b39e8341583dbcbe015d25817 Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Thu, 16 Apr 2026 13:40:35 +0100
Subject: [PATCH 12/13] [BOLT] add check for standalone installations
---
bolt-rt/CMakeLists.txt | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/bolt-rt/CMakeLists.txt b/bolt-rt/CMakeLists.txt
index 9390bad2f0f6a..676a9470d1f0c 100644
--- a/bolt-rt/CMakeLists.txt
+++ b/bolt-rt/CMakeLists.txt
@@ -1,10 +1,5 @@
cmake_minimum_required(VERSION 3.20.0)
-include(CheckCXXCompilerFlag)
-include(CheckIncludeFiles)
-include(CMakeParseArguments)
-include(GNUInstallDirs)
-
# Is this built via -DLLVM_ENABLE_RUNTIMES="bolt-rt"?.
if(LLVM_RUNTIMES_BUILD)
set(LLVM_SUBPROJECT_TITLE "Bolt-RT")
@@ -13,6 +8,11 @@ elseif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
project(bolt-rt)
endif()
+include(CheckCXXCompilerFlag)
+include(CheckIncludeFiles)
+include(CMakeParseArguments)
+include(GNUInstallDirs)
+
# Use LLVM_RUNTIMES_TARGET when built under runtimes.
if(LLVM_RUNTIMES_BUILD)
set(BOLT_RT_TARGET_TRIPLE "${LLVM_RUNTIMES_TARGET}")
@@ -129,7 +129,7 @@ function(add_bolt_rt_library)
DESTINATION "${CMAKE_INSTALL_LIBDIR}/${BOLT_RT_LIBRARY_SUBDIR}"
COMPONENT bolt-rt)
- if(NOT LLVM_ENABLE_IDE)
+ if(LLVM_RUNTIMES_BUILD AND NOT LLVM_ENABLE_IDE)
add_llvm_install_targets(install-${ARG_TARGET}
DEPENDS ${ARG_TARGET}
COMPONENT bolt-rt)
>From 7db6e433259fc00df622499ee6fb765a7198cb7d Mon Sep 17 00:00:00 2001
From: Casey Smalley <casey.smalley at arm.com>
Date: Thu, 16 Apr 2026 13:40:43 +0100
Subject: [PATCH 13/13] [BOLT] update README
---
bolt/README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/bolt/README.md b/bolt/README.md
index 40bd483a9125f..73252b2d0ff0a 100644
--- a/bolt/README.md
+++ b/bolt/README.md
@@ -175,6 +175,61 @@ instrumenting the binary with BOLT and then running it.
llvm-bolt <executable> -instrument -o <instrumented-executable>
```
+Instrumentation relies on a runtime library which is compiled as part of
+llvm runtimes, similar to compiler-rt. Thus it can be cross compiled for
+multiple targets as a part of an LLVM build. This enables bolt to
+instrument binaries across architectures.
+
+Cross compiling bolt-rtj
+```
+> ANDROID_NDK_BIN="<android ndk>/toolchains/llvm/prebuilt/linux-x86_64/bin"
+> cmake \
+ -S llvm-project/llvm \
+ -B build \
+ -G Ninja \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DLLVM_ENABLE_PROJECTS="clang;lld;bolt" \
+ -DLLVM_ENABLE_RUNTIMES="bolt-rt" \
+ -DLLVM_TARGETS_TO_BUILD="X86;AArch64" \
+ -DLLVM_RUNTIME_TARGETS="x86_64-unknown-linux-gnu;aarch64-unknown-linux-android21" \
+ -DRUNTIMES_x86_64-unknown-linux-gnu_CMAKE_CXX_COMPILER=clang++ \
+ -DRUNTIMES_aarch64-unknown-linux-android21_CMAKE_CXX_COMPILER=$ANDROID_NDK_BIN/clang++
+
+> cmake --build build --target bolt-rt
+```
+
+Or bolt-rt can be cross compiled as a stand alone build.
+```
+> ANDROID_NDK_BIN="<android ndk>/toolchains/llvm/prebuilt/linux-x86_64/bin"
+> cmake \
+ -S llvm-project/bolt-rt\
+ -B build \
+ -G Ninja \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_CXX_COMPILER=$ANDROID_NDK_BIN/clang++ \
+ -DBOLT_RT_TARGET_TRIPLE=aarch64-unknown-linux-android21
+
+> cmake --build build --target libbolt_rt_instr.a
+```
+
+Then a binary can be cross instrumented by specifying a target.
+```
+llvm-bolt \
+ <executable> \
+ -instrument \
+ -target aarch64-unknown-linux-gnu \
+ -o <instrumented executable>
+```
+
+Or with a direct path to the compiled runtime library.
+```
+llvm-bolt \
+ <executable> \
+ -instrument \
+ -runtime-instrumentation-lib <llvm build>/lib/bolt/aarch64-unknown-linux-android21/libbolt_rt_instr.a \
+ -o <instrumented executable>
+```
+
After you run instrumented-executable with the desired workload, its BOLT
profile should be ready for you in `/tmp/prof.fdata` and you can skip
**Step 2**.
More information about the llvm-commits
mailing list