Files
UnrealEngine/Engine/Source/ThirdParty/Intel/ISPC/ispc-1.21.0/cmake/GenerateBuiltins.cmake
2025-05-18 13:04:45 +08:00

432 lines
18 KiB
CMake

#
# Copyright (c) 2018-2023, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
#
# ispc GenerateBuiltins.cmake
#
find_program(M4_EXECUTABLE m4)
if (NOT M4_EXECUTABLE)
message(FATAL_ERROR "Failed to find M4 macro processor" )
endif()
message(STATUS "M4 macro processor: " ${M4_EXECUTABLE})
if (WIN32)
set(TARGET_OS_LIST_FOR_LL "windows" "unix")
elseif (UNIX)
set(TARGET_OS_LIST_FOR_LL "unix")
endif()
# Explicitly enumerate .ll and .m4 files included by target .ll files.
# This is overly conservative, as they are added to every target .ll file.
# But m4 doesn't support building depfile, so explicit enumeration is the
# easiest workaround.
list(APPEND M4_IMPLICIT_DEPENDENCIES
builtins/builtins-cm-32.ll
builtins/builtins-cm-64.ll
builtins/svml.m4
builtins/target-avx-utils.ll
builtins/target-avx-common-8.ll
builtins/target-avx-common-16.ll
builtins/target-avx1-i64x4base.ll
builtins/target-avx512-common-4.ll
builtins/target-avx512-common-8.ll
builtins/target-avx512-common-16.ll
builtins/target-avx512-utils.ll
builtins/target-neon-common.ll
builtins/target-sse2-common.ll
builtins/target-sse4-common.ll
builtins/target-xe.ll
builtins/util-xe.m4
builtins/util.m4)
function(target_ll_to_cpp llFileName bit os_name resultFileName)
set(inputFilePath builtins/${llFileName}.ll)
set(includePath builtins)
string(TOUPPER ${os_name} os_name_macro)
# Neon targets constrains: neon-i8x16 and neon-i16x8 are implemented only for 32 bit ARM.
if ("${bit}" STREQUAL "64" AND
(${llFileName} STREQUAL "target-neon-i8x16" OR ${llFileName} STREQUAL "target-neon-i16x8"))
return()
endif()
# Xe targets are implemented only for 64 bit.
string(REGEX MATCH "^target-xe" isXe "${llFileName}")
if ("${bit}" STREQUAL "32" AND isXe)
return()
endif()
set(output ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/builtins-${llFileName}-${bit}bit-${os_name}.cpp)
add_custom_command(
OUTPUT ${output}
COMMAND ${M4_EXECUTABLE} -I${includePath}
-DLLVM_VERSION=${LLVM_VERSION} -DBUILD_OS=${os_name_macro} -DRUNTIME=${bit} ${inputFilePath}
| \"${Python3_EXECUTABLE}\" bitcode2cpp.py ${inputFilePath} --type=ispc-target --runtime=${bit} --os=${os_name_macro} --llvm_as ${LLVM_AS_EXECUTABLE} --opaque_flags="${LLVM_TOOLS_OPAQUE_FLAGS}"
> ${output}
DEPENDS ${inputFilePath} bitcode2cpp.py ${M4_IMPLICIT_DEPENDENCIES}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
set(${resultFileName} ${output} PARENT_SCOPE)
set_source_files_properties(${resultFileName} PROPERTIES GENERATED true)
endfunction()
function(dispatch_ll_to_cpp llFileName os_name resultFileName)
set(inputFilePath builtins/${llFileName}.ll)
set(output ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/builtins-${llFileName}.cpp)
add_custom_command(
OUTPUT ${output}
COMMAND ${M4_EXECUTABLE} -DLLVM_VERSION=${LLVM_VERSION} ${inputFilePath}
| \"${Python3_EXECUTABLE}\" bitcode2cpp.py ${inputFilePath} --type=dispatch --os=${os_name} --llvm_as ${LLVM_AS_EXECUTABLE} --opaque_flags="${LLVM_TOOLS_OPAQUE_FLAGS}"
> ${output}
DEPENDS ${inputFilePath} bitcode2cpp.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
set(${resultFileName} ${output} PARENT_SCOPE)
set_source_files_properties(${resultFileName} PROPERTIES GENERATED true)
endfunction()
function(builtin_to_cpp bit os_name arch supported_archs supported_oses resultFileName)
set(inputFilePath builtins/builtins-c-cpu.cpp)
set(includePath "")
set(SKIP OFF)
if (NOT ${arch} IN_LIST supported_archs OR NOT ${os_name} IN_LIST supported_oses)
set(SKIP ON)
endif()
if (( ${os_name} STREQUAL "web" AND NOT ${arch} STREQUAL "wasm") OR
(NOT ${os_name} STREQUAL "web" AND ${arch} STREQUAL "wasm"))
return()
endif()
if ("${bit}" STREQUAL "32" AND ${arch} STREQUAL "x86")
set(target_arch "i686")
elseif ("${bit}" STREQUAL "64" AND ${arch} STREQUAL "x86")
set(target_arch "x86_64")
elseif ("${bit}" STREQUAL "32" AND ${arch} STREQUAL "arm")
set(target_arch "armv7")
elseif ("${bit}" STREQUAL "64" AND ${arch} STREQUAL "arm")
set(target_arch "aarch64")
elseif ("${bit}" STREQUAL "32" AND ${arch} STREQUAL "wasm")
set(target_arch "wasm32")
elseif ("${bit}" STREQUAL "64" AND ${arch} STREQUAL "wasm")
set(target_arch "wasm64")
else()
message(FATAL_ERROR "Error")
endif()
# Host to target OS constrains
if (WIN32)
if (${os_name} STREQUAL "ios")
set(SKIP ON)
endif()
elseif (APPLE)
if (${os_name} STREQUAL "windows")
set(SKIP ON)
elseif (${os_name} STREQUAL "ps4")
set(SKIP ON)
endif()
else()
if (${os_name} STREQUAL "windows")
set(SKIP ON)
elseif (${os_name} STREQUAL "ps4")
set(SKIP ON)
elseif (${os_name} STREQUAL "ios")
set(SKIP ON)
endif()
endif()
# OS to arch constrains
if (${os_name} STREQUAL "windows" AND ${arch} STREQUAL "arm" AND "${bit}" STREQUAL "32")
set(SKIP ON)
endif()
if (${os_name} STREQUAL "macos")
if (${target_arch} STREQUAL "x86_64")
# Fall through (do not set SKIP to OFF!)
elseif(${target_arch} STREQUAL "aarch64" AND ISPC_MACOS_ARM_TARGET)
set(target_arch "arm64")
# Fall through (do not set SKIP to OFF!)
else()
set(SKIP ON)
endif()
endif()
if (${os_name} STREQUAL "ps4" AND NOT ${target_arch} STREQUAL "x86_64")
set(SKIP ON)
endif()
if (${os_name} STREQUAL "ios")
if (${target_arch} STREQUAL "aarch64")
set(target_arch "arm64")
else()
set(SKIP ON)
endif()
endif()
# Return if the target is not supported.
if (${SKIP})
return()
endif()
# Report supported targets.
message (STATUS "Enabling target: ${os_name} / ${target_arch}")
# Determine triple
set(fpic "")
set(debian_triple)
if (${os_name} STREQUAL "windows")
set(triple ${target_arch}-pc-win32)
elseif (${os_name} STREQUAL "linux")
if (${target_arch} STREQUAL "i686" OR ${target_arch} STREQUAL "x86_64" OR ${target_arch} STREQUAL "aarch64")
set(triple ${target_arch}-unknown-linux-gnu)
set(debian_triple ${target_arch}-linux-gnu)
elseif (${target_arch} STREQUAL "armv7")
set(triple ${target_arch}-unknown-linux-gnueabihf)
set(debian_triple arm-linux-gnueabihf)
else()
message(FATAL_ERROR "Error")
endif()
set(fpic -fPIC)
elseif (${os_name} STREQUAL "freebsd")
set(triple ${target_arch}-unknown-freebsd)
set(fpic -fPIC)
elseif (${os_name} STREQUAL "macos")
set(triple ${target_arch}-apple-macosx)
elseif (${os_name} STREQUAL "android")
set(triple ${target_arch}-unknown-linux-android)
set(fpic -fPIC)
elseif (${os_name} STREQUAL "ios")
set(triple ${target_arch}-apple-ios)
elseif (${os_name} STREQUAL "ps4")
set(triple ${target_arch}-scei-ps)
set(fpic -fPIC)
elseif (${os_name} STREQUAL "web")
set(triple ${target_arch}-unknown-unknown)
set(fpic -fPIC)
else()
message(FATAL_ERROR "Error")
endif()
# Determine include path
if (WIN32)
if (${os_name} STREQUAL "windows")
set(includePath "")
elseif(${os_name} STREQUAL "macos")
# -isystemC:/iusers/MacOSX10.14.sdk.tar/MacOSX10.14.sdk/usr/include
set(includePath -isystem${ISPC_MACOS_SDK_PATH}/usr/include)
else()
# -isystemC:/gnuwin32/include/glibc
set(includePath -isystem${ISPC_GNUWIN32_PATH}/include/glibc)
endif()
elseif (APPLE)
if (${os_name} STREQUAL "ios")
# -isystem/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/
set(includePath -isystem${ISPC_IOS_SDK_PATH}/usr/include)
elseif (${os_name} STREQUAL "linux" OR ${os_name} STREQUAL "android" OR ${os_name} STREQUAL "freebsd")
if (${target_arch} STREQUAL "armv7")
# -isystem/Users/Shared/android-ndk-r20/sysroot/usr/include -isystem/Users/Shared/android-ndk-r20/sysroot/usr/include/arm-linux-androideabi
set(includePath -isystem${ISPC_ANDROID_NDK_PATH}/sysroot/usr/include -isystem${ISPC_ANDROID_NDK_PATH}/sysroot/usr/include/arm-linux-androideabi)
elseif (${target_arch} STREQUAL "aarch64")
# -isystem/Users/Shared/android-ndk-r20/sysroot/usr/include -isystem/Users/Shared/android-ndk-r20/sysroot/usr/include/aarch64-linux-android
set(includePath -isystem${ISPC_ANDROID_NDK_PATH}/sysroot/usr/include -isystem${ISPC_ANDROID_NDK_PATH}/sysroot/usr/include/aarch64-linux-android)
elseif(${target_arch} STREQUAL "i686")
# -isystem/Users/Shared/android-ndk-r20/sysroot/usr/include -isystem/Users/Shared/android-ndk-r20/sysroot/usr/include/i686-linux-android
set(includePath -isystem${ISPC_ANDROID_NDK_PATH}/sysroot/usr/include -isystem${ISPC_ANDROID_NDK_PATH}/sysroot/usr/include/i686-linux-android)
else()
# -isystem/Users/Shared/android-ndk-r20/sysroot/usr/include -isystem/Users/Shared/android-ndk-r20/sysroot/usr/include/x86_64-linux-android
set(includePath -isystem${ISPC_ANDROID_NDK_PATH}/sysroot/usr/include -isystem${ISPC_ANDROID_NDK_PATH}/sysroot/usr/include/x86_64-linux-android)
endif()
elseif (${os_name} STREQUAL "macos")
set(includePath -isystem${ISPC_MACOS_SDK_PATH}/usr/include)
endif()
else()
if (${os_name} STREQUAL "macos")
# -isystem/iusers/MacOSX10.14.sdk.tar/MacOSX10.14.sdk/usr/include
set(includePath -isystem${ISPC_MACOS_SDK_PATH}/usr/include)
elseif(NOT ${debian_triple} STREQUAL "")
# When compiling on Linux, there are two way to support cross targets:
# - add "foreign" architecture to the set of supported architectures and install corresponding toolchain.
# For example on aarch64: "dpkg --add-architecture armhf" and "apt-get install libc6-dev:armhf".
# In this case the headers will be installed in /usr/include/arm-linux-gnueabihf and will be
# automatically picked up by clang.
# - install cross library. For example: "apt-get install libc6-dev-armhf-cross".
# In this case headers will be installed in /usr/arm-linux-gnueabihf/include and will not be picked up
# by clang by default. So the following line adds such path explicitly. If this path doesn't exist and
# the headers can be found in other locations, this should not be a problem.
set(includePath -isystem/usr/${debian_triple}/include)
endif()
endif()
# Compose target flags
set(target_flags --target=${triple} ${fpic} ${includePath})
set(output ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/builtins-cpp-${bit}-${os_name}-${target_arch}.cpp)
if (${os_name} STREQUAL "web")
if("${bit}" STREQUAL "64")
list(APPEND emcc_flags "-sMEMORY64")
endif()
add_custom_command(
OUTPUT ${output}
COMMAND ${EMCC_EXECUTABLE} -DWASM -s WASM_OBJECT_FILES=0 ${emcc_flags} ${ISPC_OPAQUE_FLAGS} -I${CMAKE_SOURCE_DIR} -c ${inputFilePath} --std=gnu++17 -emit-llvm -c -o -
| (\"${LLVM_DIS_EXECUTABLE}\" ${LLVM_TOOLS_OPAQUE_FLAGS} - || echo "builtins-c-*.cpp compile error")
| \"${Python3_EXECUTABLE}\" bitcode2cpp.py c --type=builtins-c --runtime=${bit} --os=${os_name} --arch=${target_arch} --llvm_as ${LLVM_AS_EXECUTABLE} --opaque_flags="${LLVM_TOOLS_OPAQUE_FLAGS}"
> ${output}
DEPENDS ${inputFilePath} bitcode2cpp.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
else()
add_custom_command(
OUTPUT ${output}
COMMAND ${CLANGPP_EXECUTABLE} ${target_flags} -I${CMAKE_SOURCE_DIR} -m${bit} -emit-llvm ${ISPC_OPAQUE_FLAGS} --std=gnu++17 -c ${inputFilePath} -o - | (\"${LLVM_DIS_EXECUTABLE}\" ${LLVM_TOOLS_OPAQUE_FLAGS} - || echo "builtins-c-*.cpp compile error")
| \"${Python3_EXECUTABLE}\" bitcode2cpp.py c --type=builtins-c --runtime=${bit} --os=${os_name} --arch=${target_arch} --llvm_as ${LLVM_AS_EXECUTABLE} --opaque_flags="${LLVM_TOOLS_OPAQUE_FLAGS}"
> ${output}
DEPENDS ${inputFilePath} bitcode2cpp.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif()
set(${resultFileName} ${output} PARENT_SCOPE)
set_source_files_properties(${resultFileName} PROPERTIES GENERATED true)
endfunction()
function(builtin_xe_to_cpp bit resultFileName)
set(inputFilePath builtins/builtins-cm-${bit}.ll)
set(SKIP OFF)
if (WIN32)
set(os_name "windows")
elseif (APPLE)
set(SKIP ON)
else ()
set(os_name "linux")
endif()
set(target_arch "xe64")
if (NOT "${bit}" STREQUAL "64")
set(SKIP ON)
endif()
if (NOT SKIP)
set(output ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/builtins-cm-${bit}.cpp)
add_custom_command(
OUTPUT ${output}
COMMAND cat ${inputFilePath}
| \"${Python3_EXECUTABLE}\" bitcode2cpp.py cm --type=builtins-c --runtime=${bit}
--os=${os_name} --arch=${target_arch} --llvm_as ${LLVM_AS_EXECUTABLE} --opaque_flags="${LLVM_TOOLS_OPAQUE_FLAGS}"
> ${output}
DEPENDS ${inputFilePath} bitcode2cpp.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
set(${resultFileName} ${output} PARENT_SCOPE)
set_source_files_properties(${resultFileName} PROPERTIES GENERATED true)
endif()
endfunction()
function (generate_target_builtins resultList)
# Dispatch module for macOS and all the rest of targets.
if (${LLVM_VERSION_NUMBER} VERSION_GREATER_EQUAL "14.0.0")
dispatch_ll_to_cpp(dispatch "linux" output_generic)
else()
dispatch_ll_to_cpp(dispatch-no-spr "linux" output_generic)
endif()
dispatch_ll_to_cpp(dispatch-macos "macos" output_macos)
list(APPEND tmpList ${output_generic} ${output_macos})
if(MSVC)
# Group generated files inside Visual Studio
source_group("Generated Builtins" FILES ${output_generic} ${output_macos})
endif()
# "Regular" targets, targeting specific real ISA: sse/avx/neon
set(regular_targets ${ARGN})
list(FILTER regular_targets EXCLUDE REGEX wasm)
foreach (ispc_target ${regular_targets})
foreach (bit 32 64)
foreach (os_name ${TARGET_OS_LIST_FOR_LL})
target_ll_to_cpp(target-${ispc_target} ${bit} ${os_name} output${os_name}${bit})
list(APPEND tmpList ${output${os_name}${bit}})
if(MSVC)
# Group generated files inside Visual Studio
source_group("Generated Builtins" FILES ${output${os_name}${bit}})
endif()
endforeach()
endforeach()
endforeach()
# WASM targets.
if (WASM_ENABLED)
set(wasm_targets ${ARGN})
list(FILTER wasm_targets INCLUDE REGEX wasm)
foreach (wasm_target ${wasm_targets})
target_ll_to_cpp(target-${wasm_target} 32 web outputweb32)
target_ll_to_cpp(target-${wasm_target} 64 web outputweb64)
list(APPEND tmpList ${outputweb32} ${outputweb64})
if(MSVC)
source_group("Generated Builtins" FILES ${outputweb32} ${outputweb64})
endif()
endforeach()
endif()
# Return the list
set(${resultList} ${tmpList} PARENT_SCOPE)
endfunction()
function (generate_common_builtins resultList)
# Supported architectures
if (X86_ENABLED)
list (APPEND supported_archs "x86")
endif()
if (ARM_ENABLED)
list (APPEND supported_archs "arm")
endif()
if (WASM_ENABLED)
list (APPEND supported_archs "wasm")
list (APPEND supported_oses "web")
endif()
# Supported OSes.
if (ISPC_WINDOWS_TARGET)
list (APPEND supported_oses "windows")
endif()
if (ISPC_LINUX_TARGET)
list (APPEND supported_oses "linux")
endif()
if (ISPC_FREEBSD_TARGET)
list (APPEND supported_oses "freebsd")
endif()
if (ISPC_MACOS_TARGET)
list (APPEND supported_oses "macos")
endif()
if (ISPC_ANDROID_TARGET)
list (APPEND supported_oses "android")
endif()
if (ISPC_IOS_TARGET)
list (APPEND supported_oses "ios")
endif()
if (ISPC_PS_TARGET)
list (APPEND supported_oses "ps4")
endif()
message (STATUS "ISPC will be built with support of ${supported_oses} for ${supported_archs}")
foreach (bit 32 64)
foreach (os_name "windows" "linux" "freebsd" "macos" "android" "ios" "ps4" "web")
foreach (arch "x86" "arm" "wasm")
builtin_to_cpp(${bit} ${os_name} ${arch} "${supported_archs}" "${supported_oses}" res${bit}${os_name}${arch})
list(APPEND tmpList ${res${bit}${os_name}${arch}} )
if(MSVC)
# Group generated files inside Visual Studio
source_group("Generated Builtins" FILES ${res${bit}${os_name}${arch}})
endif()
endforeach()
endforeach()
endforeach()
if (XE_ENABLED)
set(bit 64)
builtin_xe_to_cpp(${bit} res_xe_${bit})
list(APPEND tmpList ${res_xe_${bit}} )
if(MSVC)
# Group generated files inside Visual Studio
source_group("Generated Builtins" FILES ${res_xe_${bit}})
endif()
endif()
set(${resultList} ${tmpList} PARENT_SCOPE)
endfunction()