Files
revng-revng/CMakeLists.txt
Andrea Gussoni b10024bfc8 InlineHelpers: limit loop-unroll to x86
Only the x86 softfloat helpers iterate over the vector-register lanes
with bounded `for` loops (e.g. the packed `helper_*p[sd]` operate on
`XMM/ZMM_D(i)`). `fix-helpers` can only rewrite the per-lane CSV
accesses once those loops are unrolled. This step is not needed on other
archs, so we avoid it to save space on the generated libtcg helpers and
build time.
2026-06-19 15:35:18 +02:00

455 lines
16 KiB
CMake

#
# This file is distributed under the MIT License. See LICENSE.md for details.
#
cmake_minimum_required(VERSION 3.15.0)
project(revng)
include(share/revng/cmake/Common.cmake)
find_program(CLANG_PATH NAMES clang)
# Copy system configuration.yml
if(REVNG_SYSTEM_CONFIG AND EXISTS "${REVNG_SYSTEM_CONFIG}")
set(REVNG_CONFIG_PATH "${CMAKE_BINARY_DIR}/etc/revng/configuration.yml")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/etc/revng")
file(COPY_FILE "${REVNG_SYSTEM_CONFIG}" "${REVNG_CONFIG_PATH}")
install(FILES "${REVNG_CONFIG_PATH}" DESTINATION etc/revng)
endif()
#
# Compile flags
#
# These have to be first to get highest priority
include_directories("${CMAKE_SOURCE_DIR}/include")
include_directories("${CMAKE_BINARY_DIR}/include")
add_definitions("-DINSTALL_PATH=\"${CMAKE_INSTALL_PREFIX}\"")
# Uncomment the following line if recursive coroutines make debugging hard
# add_definitions("-DDISABLE_RECURSIVE_COROUTINES")
# Remove -rdynamic
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
# Basic compiler options
# cmake-format: off
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -shared-libasan")
# cmake-format: on
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# set(TUPLE_TREE_GENERATOR_EMIT_TRACKING_DEBUG ON)
if(${TUPLE_TREE_GENERATOR_EMIT_TRACKING_DEBUG})
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -DTUPLE_TREE_GENERATOR_EMIT_TRACKING_DEBUG")
endif()
# Uncomment the following line if errors like `Couldn't find method
# SomeType::method` make debugging hard
#
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-limit-debug-info")
if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_flag_if_available("-Wno-unused-local-typedefs")
endif()
# Disable some warnings
add_flag_if_available("-Wno-unused-parameter")
add_flag_if_available("-Wno-unused-variable")
add_flag_if_available("-Wno-maybe-uninitialized")
add_flag_if_available("-Wno-init-list-lifetime")
add_flag_if_available("-Wno-ambiguous-reversed-operator")
# Add some extra warnings
add_flag_if_available("-Wstrict-aliasing")
add_flag_if_available("-fstrict-aliasing")
add_flag_if_available("-Wnon-virtual-dtor")
add_flag_if_available("-Wunreachable-code-break")
add_flag_if_available("-Winconsistent-missing-destructor-override")
add_flag_if_available("-Wnewline-eof")
add_flag_if_available("-Wmissing-prototypes")
add_flag_if_available("-Wimplicit-fallthrough")
add_definitions("-D_FILE_OFFSET_BITS=64")
check_cxx_compiler_flag("-no-pie" COMPILER_SUPPORTS_NO_PIE)
if(COMPILER_SUPPORTS_NO_PIE)
set(NO_PIE "-no-pie")
endif()
include(CheckIncludeFiles)
check_include_files(valgrind/callgrind.h HAVE_VALGRIND_CALLGRIND_H)
if(HAVE_VALGRIND_CALLGRIND_H)
add_definitions("-DHAVE_VALGRIND_CALLGRIND_H")
endif()
#
# Link LLVM
#
find_package(LLVM REQUIRED CONFIG)
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
link_directories(${LLVM_LIBRARY_DIRS})
llvm_map_components_to_libnames(
LLVM_LIBRARIES
core
support
irreader
ScalarOpts
linker
Analysis
object
transformutils
BitWriter
BitReader
InstCombine
CodeGen
Passes
TargetParser)
# MLIR CMake stuff
find_package(MLIR REQUIRED CONFIG)
include_directories(${MLIR_INCLUDE_DIRS})
#
# Link Clang
#
find_package(Clang REQUIRED CONFIG)
#
# Component hash
#
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/share/revng/component-hashes")
set(COMPONENT_HASH_PATH
"${CMAKE_BINARY_DIR}/share/revng/component-hashes/revng")
add_custom_command(
OUTPUT "${COMPONENT_HASH_PATH}"
COMMAND
sh -c
' (git -C "${CMAKE_SOURCE_DIR}" rev-parse HEAD || echo "\"${CMAKE_PROJECT_VERSION}\"") '
> "${COMPONENT_HASH_PATH}")
add_custom_target(generate-component-hash ALL DEPENDS "${COMPONENT_HASH_PATH}")
install(FILES "${COMPONENT_HASH_PATH}"
DESTINATION "${CMAKE_INSTALL_DIR}/share/revng/component-hashes/")
#
# share/revng
#
add_custom_target(copy_share ALL COMMAND cp -Tar "${CMAKE_SOURCE_DIR}/share/"
"${CMAKE_BINARY_DIR}/share/")
install(
DIRECTORY "${CMAKE_BINARY_DIR}/share/"
DESTINATION share/
USE_SOURCE_PERMISSIONS)
# Export CMake targets
install(
EXPORT revng
NAMESPACE DESTINATION
share/revng/cmake)
# Create share/revng/additional-bin-paths
set(ADDITIONAL_BIN_PATHS "${CMAKE_BINARY_DIR}/share/revng/additional-bin-paths")
file(WRITE "${ADDITIONAL_BIN_PATHS}" "libexec/revng\n")
file(RELATIVE_PATH RELATIVE_LLVM_TOOLS_BINARY_DIR "${CMAKE_INSTALL_PREFIX}"
"${LLVM_TOOLS_BINARY_DIR}")
file(APPEND "${ADDITIONAL_BIN_PATHS}" "${RELATIVE_LLVM_TOOLS_BINARY_DIR}\n")
# Create additional-search-prefixes
file(WRITE "${CMAKE_BINARY_DIR}/additional-search-prefixes"
"${CMAKE_INSTALL_PREFIX}\n")
file(RELATIVE_PATH RELATIVE_LLVM_TOOLS_BINARY_DIR "${CMAKE_INSTALL_PREFIX}"
"${LLVM_TOOLS_BINARY_DIR}")
file(APPEND "${ADDITIONAL_BIN_PATHS}" "${RELATIVE_LLVM_TOOLS_BINARY_DIR}\n")
# Build the support module for each architecture and in several configurations
set(SUPPORT_MODULES_CONFIGS "normal;trace")
set(SUPPORT_MODULES_CONFIG_normal "")
set(SUPPORT_MODULES_CONFIG_trace "-DTRACE")
# A set of llvm modules that contain all the known helpers.
set(HELPER_MODULE_LIST, "")
foreach(
ARCH
aarch64
arm
mips
mipsel
x86_64
i386
s390x)
set(OUTPUT "early-linked-${ARCH}.ll")
add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/share/revng/${OUTPUT}"
DEPENDS "${CMAKE_SOURCE_DIR}/share/revng/early-linked.c"
COMMAND
${TARGET_CLANG} ARGS "${CMAKE_SOURCE_DIR}/share/revng/early-linked.c" -o
"${CMAKE_BINARY_DIR}/share/revng/${OUTPUT}" -S -emit-llvm -g
-DTARGET_${ARCH} -I"${CMAKE_SOURCE_DIR}/share/revng"
-I"${CMAKE_CURRENT_SOURCE_DIR}/include")
add_custom_target("early-linked-module-${OUTPUT}" ALL
DEPENDS "${CMAKE_BINARY_DIR}/share/revng/${OUTPUT}")
add_dependencies(revng-all-binaries "early-linked-module-${OUTPUT}")
list(APPEND HELPER_MODULE_LIST "${CMAKE_BINARY_DIR}/share/revng/${OUTPUT}")
# Enable the support for C exceptions to avoid optimizations that break
# exception support when linking a module with isolated functions
foreach(CONFIG ${SUPPORT_MODULES_CONFIGS})
set(OUTPUT "support-${ARCH}-${CONFIG}.ll")
add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/share/revng/${OUTPUT}"
DEPENDS "${CMAKE_SOURCE_DIR}/share/revng/support.c"
COMMAND
${TARGET_CLANG} ARGS "${CMAKE_SOURCE_DIR}/share/revng/support.c" -O2
-fexceptions -o "${CMAKE_BINARY_DIR}/share/revng/${OUTPUT}" -S
-emit-llvm -g -DTARGET_${ARCH} -I"${CMAKE_SOURCE_DIR}/share/revng"
-I"${CMAKE_CURRENT_SOURCE_DIR}/include"
${SUPPORT_MODULES_CONFIG_${CONFIG}})
add_custom_target("support-module-${OUTPUT}" ALL
DEPENDS "${CMAKE_BINARY_DIR}/share/revng/${OUTPUT}")
add_dependencies(revng-all-binaries "support-module-${OUTPUT}")
list(APPEND HELPER_MODULE_LIST "${CMAKE_BINARY_DIR}/share/revng/${OUTPUT}")
endforeach()
# Annotate `libtcg-helpers-*.bc`. This loads the `libtcg-helpers` bitcode
# files and runs analyses that determine which CSVs are accessed by each
# helper function.
set(LIBTCG_HELPERS
"${CMAKE_INSTALL_PREFIX}/share/libtcg/libtcg-helpers-${ARCH}.bc")
set(LIBTCG_HELPERS_FULL
"${CMAKE_BINARY_DIR}/share/revng/libtcg-helpers-full-${ARCH}.bc")
# Build-time helper-annotation pipeline. Order is significant:
#
# * `mark-inline-helpers-up-to` tags every helper that transitively reaches
# the configured runtime-library directories with the `revng_inline`
# section. Runs first so all subsequent passes see the tag set.
# * `sroa` + `instsimplify` simplify the body of every helper so the
# downstream analyses see the smallest possible IR.
# * `cpu-loop-exit` rewrites the CPU loop-exit pattern into something
# `analyze-helper-arguments` can understand.
# * `analyze-helper-arguments` discovers, for every helper, which arguments
# alias CSVs at the call site.
# * `loop-unroll` (x86 only, see below) unrolls loops so the subsequent
# `fix-helpers` pass can rewrite the accesses contained in bounded loop
# bodies.
# * `fix-helpers` rewrites helper bodies to access CSVs via the env pointer,
# switching on env-relative offsets.
# * `detect-uninlinable-helpers` excludes not viable helpers from inlining.
# Only the x86 softfloat helpers iterate over the vector-register lanes with
# bounded `for` loops (e.g. the packed `helper_*p[sd]` operate on
# `XMM/ZMM_D(i)`). `fix-helpers` can only rewrite the per-lane CSV accesses
# once those loops are unrolled. This step is not needed on other archs, so we
# avoid it to save space on the generated libtcg helpers and build time.
set(EXTRA_HELPER_PASSES "")
if(ARCH STREQUAL "x86_64" OR ARCH STREQUAL "i386")
set(EXTRA_HELPER_PASSES -loop-unroll)
endif()
add_custom_command(
OUTPUT "${LIBTCG_HELPERS_FULL}"
DEPENDS "${LIBTCG_HELPERS}" revng-all-binaries revngHelperArgumentsAnalysis
revngHelperInliningAnalyses
COMMAND
./bin/revng opt -mark-inline-helpers-up-to -sroa -instsimplify
-cpu-loop-exit -analyze-helper-arguments ${EXTRA_HELPER_PASSES}
-fix-helpers -fix-helpers-architecture="${ARCH}" -dce
-detect-uninlinable-helpers "${LIBTCG_HELPERS}" -o
"${LIBTCG_HELPERS_FULL}")
add_custom_target("annotated-libtcg-helpers-${ARCH}" ALL
DEPENDS "${LIBTCG_HELPERS_FULL}")
function(process_helper_module)
set(options)
set(oneValueArgs NAME)
set(multiValueArgs PASSES)
cmake_parse_arguments(OPT "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
set(PROCESS_HELPER_MODULE_OUTPUT
"${CMAKE_BINARY_DIR}/share/revng/libtcg-helpers-${OPT_NAME}-${ARCH}.bc")
list(TRANSFORM OPT_PASSES PREPEND -)
add_custom_command(
OUTPUT "${PROCESS_HELPER_MODULE_OUTPUT}"
DEPENDS "${LIBTCG_HELPERS_FULL}" revng-all-binaries
revngHelperArgumentsAnalysis revngHelperInliningAnalyses
COMMAND ./bin/revng opt ${OPT_PASSES} "${LIBTCG_HELPERS_FULL}" -o
"${PROCESS_HELPER_MODULE_OUTPUT}")
add_custom_target("annotated-libtcg-helpers-${OPT_NAME}-${ARCH}" ALL
DEPENDS "${PROCESS_HELPER_MODULE_OUTPUT}")
list(APPEND HELPER_MODULE_LIST "${PROCESS_HELPER_MODULE_OUTPUT}")
set(HELPER_MODULE_LIST
"${HELPER_MODULE_LIST}"
PARENT_SCOPE)
endfunction()
# Produce to-inline version of helpers. In this version the bitcode file only
# contains helper functions that are in the `revng_inline` section and the
# CSVs that are used by them. This is used by `inline-helpers` to allow
# inlining the body of the `revng_inline` function into the isolated
# functions' bodies.
process_helper_module(
NAME
to-inline
PASSES
slim-down-helpers-module
sroa
instsimplify
simplifycfg
strip-dead-debug-info)
# Produce declarations-only version of helpers. In this version of the bitcode
# file all the helper functions have been turned into declarations and all
# CSVs have been dropped. This will be used in `lift` to import the helper
# declarations to be used in the lifting process.
process_helper_module(
NAME declarations-only PASSES helpers-module-to-declarations globaldce
strip-dead-debug-info)
endforeach()
# Custom command to create .clang-format file from revng-check-conventions
add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/share/revng/.clang-format"
DEPENDS "${CMAKE_SOURCE_DIR}/libexec/revng/check-conventions"
"${CMAKE_SOURCE_DIR}/share/revng/clang-format-style-file.yml"
copy_share copy_libexec
COMMAND
"${CMAKE_BINARY_DIR}/libexec/revng/check-conventions" ARGS
--print-clang-format-config >
"${CMAKE_BINARY_DIR}/share/revng/.clang-format")
add_custom_target(clang-format-dot-file ALL
DEPENDS "${CMAKE_BINARY_DIR}/share/revng/.clang-format")
#
# libexec/revng
#
add_custom_target(
copy_libexec ALL COMMAND cp -Tar "${CMAKE_SOURCE_DIR}/libexec/"
"${CMAKE_BINARY_DIR}/libexec/")
install(
DIRECTORY "${CMAKE_BINARY_DIR}/libexec/"
DESTINATION libexec/
USE_SOURCE_PERMISSIONS)
#
# Export information useful for subdirectories
#
set(PYTHON_GENERATED_MODEL_PATH revng/model/_generated.py)
#
# Enable CTest
#
enable_testing()
#
# Find Python using the FindPython module. We request two components: *
# Interpreter: needed for some variables, such as $Python_SITELIB * Development:
# needed to compile nanobind module and friends, provides the
# $Python_INCLUDE_DIRS and $Python_LIBRARIES variables
#
find_package(
Python3
COMPONENTS Interpreter Development
REQUIRED)
file(RELATIVE_PATH PYTHON_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}"
"${Python3_SITELIB}")
#
# Build docs
#
configure_file(mkdocs.yml "${CMAKE_BINARY_DIR}" COPYONLY)
set(HTML_DOCS_PATH "${CMAKE_CURRENT_BINARY_DIR}/share/doc/revng/html")
find_program(MKDOCS NAMES mkdocs)
add_custom_command(
OUTPUT share/doc/revng/html/404.html
DEPENDS mkdocs.yml
copy_share
"share/doc/revng/references/abi-definition.md"
"share/doc/revng/references/mime-types.md"
"share/doc/revng/references/ptml.md"
"share/doc/revng/references/cli/revng-common.md"
"share/doc/revng/references/cli/revng-artifact.md"
"share/doc/revng/references/cli/revng-analyze.md"
"share/doc/revng/references/cli/revng2-project-analyze.md"
"share/doc/revng/references/cli/revng2-project-artifact.md"
"share/doc/revng/user-manual/index.md"
"share/doc/revng/user-manual/initial-setup.md"
"share/doc/revng/user-manual/key-concepts/metaaddress.md"
"share/doc/revng/user-manual/key-concepts/model.md"
"share/doc/revng/user-manual/key-concepts/artifacts-and-analyses.md"
"share/doc/revng/user-manual/tutorial/model-from-scratch.md"
"share/doc/revng/user-manual/tutorial/running-analyses.md"
"share/doc/revng/what-is-revng.md"
"share/doc/revng/index.md"
generate-revngModel-tuple-tree-code
generate-revngPipeline-tuple-tree-code
python/revng/internal/cli/_commands/process_docs_yaml/pipeline.md.tpl
python/revng/internal/cli/_commands/process_docs_yaml/artifacts.md.tpl
python/revng/internal/cli/_commands/process_docs_yaml/analyses.md.tpl
python/revng/internal/cli/_commands/process_docs_yaml/common.md.tpl
share/revng/pipelines/revng-pipelines.yml
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
COMMAND
"./bin/revng" process-docs-yaml
"${CMAKE_SOURCE_DIR}/python/revng/internal/cli/_commands/process_docs_yaml/pipeline.md.tpl"
< "${CMAKE_SOURCE_DIR}/share/revng/pipelines/revng-pipelines.yml" >
share/doc/revng/references/pipeline.md
COMMAND
"./bin/revng" process-docs-yaml
"${CMAKE_SOURCE_DIR}/python/revng/internal/cli/_commands/process_docs_yaml/analyses.md.tpl"
< "${CMAKE_SOURCE_DIR}/share/revng/pipelines/revng-pipelines.yml" >
share/doc/revng/references/analyses.md
COMMAND
"./bin/revng" process-docs-yaml
"${CMAKE_SOURCE_DIR}/python/revng/internal/cli/_commands/process_docs_yaml/artifacts.md.tpl"
< "${CMAKE_SOURCE_DIR}/share/revng/pipelines/revng-pipelines.yml" >
share/doc/revng/references/artifacts.md
COMMAND env NO_MKDOCS_2_WARNING=1 ${MKDOCS} build --quiet --strict --site-dir
mkdocs-output
COMMAND rm -rf "${HTML_DOCS_PATH}"
COMMAND mv -T mkdocs-output "${HTML_DOCS_PATH}"
COMMENT "Generating mkdocs")
add_custom_target(mkdocs ALL DEPENDS share/doc/revng/html/404.html)
#
# Gather helper names
#
add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/share/revng/helper-list.csv"
COMMAND
${CMAKE_SOURCE_DIR}/scripts/extract-helper-names.sh ${HELPER_MODULE_LIST} >
"${CMAKE_BINARY_DIR}/share/revng/helper-list.csv"
DEPENDS copy_share ${HELPER_MODULE_LIST})
add_custom_target(helper-list ALL
DEPENDS "${CMAKE_BINARY_DIR}/share/revng/helper-list.csv")
#
# Proceed to subdirectories
#
add_subdirectory(docs)
add_subdirectory(include)
add_subdirectory(lib)
add_subdirectory(python)
add_subdirectory(tests)
add_subdirectory(tools)
add_subdirectory(typescript)