When SPIRV-LLVM-Translator is built in-tree (i.e., placed in llvm/projects folder), llvm-spirv target exists. Drop legacy llvm-spirv_target dependency (was for non-runtime build) and add llvm-spirv to runtimes dependencies.
282 lines
9.1 KiB
CMake
282 lines
9.1 KiB
CMake
cmake_minimum_required(VERSION 3.20.0)
|
|
|
|
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
|
project(libclc VERSION 0.2.0 LANGUAGES CXX C)
|
|
endif()
|
|
set(LLVM_SUBPROJECT_TITLE "libclc")
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
|
|
# Add path for custom modules
|
|
list( INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" )
|
|
|
|
enable_language( CLC )
|
|
|
|
include( AddLibclc )
|
|
|
|
include( GNUInstallDirs )
|
|
|
|
set( LIBCLC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
|
|
|
|
# A runtimes cross-build should only use the requested target.
|
|
set( LIBCLC_DEFAULT_TARGET "all" )
|
|
if( LLVM_RUNTIMES_BUILD AND LLVM_DEFAULT_TARGET_TRIPLE MATCHES "^nvptx|^amdgcn" )
|
|
set( LIBCLC_DEFAULT_TARGET ${LLVM_DEFAULT_TARGET_TRIPLE} )
|
|
endif()
|
|
set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_DEFAULT_TARGET}
|
|
CACHE STRING "Semicolon-separated list of libclc targets to build, or 'all'." )
|
|
|
|
option(
|
|
LIBCLC_USE_SPIRV_BACKEND "Build SPIR-V targets with the SPIR-V backend." OFF
|
|
)
|
|
|
|
# List of all supported targets.
|
|
set( LIBCLC_TARGETS_ALL
|
|
amdgcn-amd-amdhsa-llvm
|
|
clspv--
|
|
clspv64--
|
|
nvptx64--
|
|
nvptx64--nvidiacl
|
|
nvptx64-nvidia-cuda
|
|
)
|
|
|
|
if( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
|
|
set( LIBCLC_STANDALONE_BUILD TRUE )
|
|
|
|
find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}")
|
|
include(AddLLVM)
|
|
|
|
message( STATUS "libclc LLVM version: ${LLVM_PACKAGE_VERSION}" )
|
|
|
|
foreach( tool IN ITEMS llvm-link opt )
|
|
find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
|
|
set( ${tool}_exe ${LLVM_TOOL_${tool}} )
|
|
set( ${tool}_target )
|
|
endforeach()
|
|
|
|
# Setup the paths where libclc runtimes should be stored.
|
|
set( LIBCLC_OUTPUT_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} )
|
|
set( LIBCLC_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/clc )
|
|
else()
|
|
set( LIBCLC_STANDALONE_BUILD FALSE )
|
|
|
|
if( NOT LLVM_PACKAGE_VERSION )
|
|
set( LLVM_PACKAGE_VERSION ${LLVM_VERSION} )
|
|
endif()
|
|
set( PACKAGE_VERSION ${LLVM_PACKAGE_VERSION} )
|
|
|
|
# Note that we check this later (for both build types) but we can provide a
|
|
# more useful error message when built in-tree. We assume that LLVM tools are
|
|
# always available so don't warn here.
|
|
if( NOT LLVM_RUNTIMES_BUILD AND NOT clang IN_LIST LLVM_ENABLE_PROJECTS )
|
|
message(FATAL_ERROR "Clang is not enabled, but is required to build libclc in-tree")
|
|
endif()
|
|
|
|
get_host_tool_path( llvm-link LLVM_LINK llvm-link_exe llvm-link_target )
|
|
get_host_tool_path( opt OPT opt_exe opt_target )
|
|
|
|
# Setup the paths where libclc runtimes should be stored. By default, in an
|
|
# in-tree build we place the libraries in clang's resource driectory.
|
|
include(GetClangResourceDir)
|
|
get_clang_resource_dir( LIBCLC_INSTALL_DIR )
|
|
cmake_path( APPEND LIBCLC_INSTALL_DIR "lib" )
|
|
|
|
cmake_path( GET LLVM_LIBRARY_OUTPUT_INTDIR PARENT_PATH LIBCLC_OUTPUT_LIBRARY_DIR )
|
|
cmake_path( APPEND LIBCLC_OUTPUT_LIBRARY_DIR ${LIBCLC_INSTALL_DIR} )
|
|
endif()
|
|
|
|
if( NOT LIBCLC_USE_SPIRV_BACKEND )
|
|
# llvm-spirv is an optional dependency, used to build spirv-* targets when
|
|
# the SPIR-V backend hasn't been requested. It may be provided in-tree or
|
|
# externally.
|
|
if( TARGET llvm-spirv )
|
|
get_host_tool_path( llvm-spirv LLVM_SPIRV llvm-spirv_exe llvm-spirv_target )
|
|
else()
|
|
find_program( LLVM_SPIRV llvm-spirv HINTS ${LLVM_TOOLS_BINARY_DIR} )
|
|
set( llvm-spirv_exe "${LLVM_SPIRV}" )
|
|
endif()
|
|
endif()
|
|
|
|
if( LIBCLC_USE_SPIRV_BACKEND OR llvm-spirv_exe )
|
|
list( APPEND LIBCLC_TARGETS_ALL spirv-mesa3d- spirv64-mesa3d- )
|
|
endif()
|
|
|
|
if( LIBCLC_TARGETS_TO_BUILD STREQUAL "all" )
|
|
set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} )
|
|
else()
|
|
foreach(TARGET_TO_BUILD ${LIBCLC_TARGETS_TO_BUILD})
|
|
if (NOT ${TARGET_TO_BUILD} IN_LIST LIBCLC_TARGETS_ALL)
|
|
message( FATAL_ERROR
|
|
"Unknown target in LIBCLC_TARGETS_TO_BUILD: \"${TARGET_TO_BUILD}\"\n"
|
|
"Valid targets are: ${LIBCLC_TARGETS_ALL}\n")
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
|
|
list( SORT LIBCLC_TARGETS_TO_BUILD )
|
|
|
|
foreach( tool IN ITEMS opt llvm-link )
|
|
if( NOT EXISTS "${${tool}_exe}" AND "${${tool}_target}" STREQUAL "" )
|
|
message( FATAL_ERROR "libclc toolchain incomplete - missing tool ${tool}!" )
|
|
endif()
|
|
endforeach()
|
|
|
|
add_subdirectory(clc/lib/generic)
|
|
add_subdirectory(clc/lib/amdgpu)
|
|
add_subdirectory(clc/lib/ptx-nvidiacl)
|
|
add_subdirectory(clc/lib/spirv)
|
|
add_subdirectory(clc/lib/clspv)
|
|
|
|
add_subdirectory(opencl/lib/generic)
|
|
add_subdirectory(opencl/lib/amdgpu)
|
|
add_subdirectory(opencl/lib/clspv)
|
|
add_subdirectory(opencl/lib/spirv)
|
|
|
|
add_custom_target( libclc ALL )
|
|
|
|
add_custom_target( libclc-opencl-builtins COMMENT "Build libclc OpenCL builtins" )
|
|
add_dependencies( libclc libclc-opencl-builtins )
|
|
|
|
foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
|
|
message( STATUS "libclc target '${t}' is enabled" )
|
|
string( REPLACE "-" ";" TRIPLE ${t} )
|
|
list( GET TRIPLE 0 ARCH )
|
|
list( GET TRIPLE 1 VENDOR )
|
|
list( GET TRIPLE 2 OS )
|
|
|
|
# Determine the clang target triple.
|
|
set(clang_triple ${t})
|
|
if(ARCH STREQUAL spirv AND LIBCLC_USE_SPIRV_BACKEND)
|
|
set(clang_triple spirv32--)
|
|
elseif(ARCH STREQUAL spirv64 AND LIBCLC_USE_SPIRV_BACKEND)
|
|
set(clang_triple spirv64--)
|
|
elseif(ARCH STREQUAL spirv OR ARCH STREQUAL clspv)
|
|
set(clang_triple spir--)
|
|
elseif(ARCH STREQUAL spirv64 OR ARCH STREQUAL clspv64)
|
|
set(clang_triple spir64--)
|
|
endif()
|
|
|
|
# Determine the preprocessor identifier for this target.
|
|
set(MACRO_ARCH ${ARCH})
|
|
if(ARCH STREQUAL spirv)
|
|
set(MACRO_ARCH SPIRV32)
|
|
elseif(ARCH STREQUAL spirv64)
|
|
set(MACRO_ARCH SPIRV64)
|
|
elseif(ARCH STREQUAL clspv)
|
|
set(MACRO_ARCH CLSPV32)
|
|
elseif(ARCH STREQUAL clspv64)
|
|
set(MACRO_ARCH CLSPV64)
|
|
endif()
|
|
string(TOUPPER "CLC_${MACRO_ARCH}" target_define)
|
|
|
|
# Address space values.
|
|
set(private_addrspace_val 0)
|
|
set(generic_addrspace_val 0)
|
|
if(ARCH STREQUAL amdgcn)
|
|
set(private_addrspace_val 5)
|
|
endif()
|
|
if(ARCH STREQUAL spirv OR ARCH STREQUAL spirv64)
|
|
set(generic_addrspace_val 4)
|
|
endif()
|
|
|
|
# Target-specific compile flags and defines.
|
|
set(target_compile_flags)
|
|
set(target_extra_defines)
|
|
set(opt_flags -O3)
|
|
|
|
if(ARCH STREQUAL spirv OR ARCH STREQUAL spirv64)
|
|
list(APPEND target_compile_flags -O0 -finline-hint-functions)
|
|
list(APPEND target_extra_defines CLC_SPIRV)
|
|
set(opt_flags)
|
|
elseif(ARCH STREQUAL clspv OR ARCH STREQUAL clspv64)
|
|
list(APPEND target_compile_flags -Wno-unknown-assumption
|
|
-U__opencl_c_int64)
|
|
list(APPEND target_extra_defines CLC_CLSPV)
|
|
elseif(ARCH STREQUAL amdgcn)
|
|
list(APPEND target_compile_flags "SHELL:-Xclang -mcode-object-version=none")
|
|
endif()
|
|
|
|
# Collect CLC sources; target-specific sources override generic ones by basename.
|
|
set(_clc_overrides)
|
|
if(ARCH STREQUAL amdgcn)
|
|
list(APPEND _clc_overrides ${CLC_AMDGPU_SOURCES})
|
|
elseif(ARCH STREQUAL nvptx64 AND (OS STREQUAL nvidiacl OR OS STREQUAL cuda))
|
|
list(APPEND _clc_overrides ${CLC_PTX_NVIDIACL_SOURCES})
|
|
elseif(ARCH STREQUAL spirv OR ARCH STREQUAL spirv64)
|
|
list(APPEND _clc_overrides ${CLC_SPIRV_SOURCES})
|
|
elseif(ARCH STREQUAL clspv OR ARCH STREQUAL clspv64)
|
|
list(APPEND _clc_overrides ${CLC_CLSPV_SOURCES})
|
|
endif()
|
|
libclc_merge_sources(clc_sources ${CLC_GENERIC_SOURCES} ${_clc_overrides})
|
|
|
|
# Collect OpenCL sources. SPIR-V and Clspv targets use self-contained
|
|
# subsets while others merge with target-specific overrides.
|
|
if(ARCH STREQUAL spirv OR ARCH STREQUAL spirv64)
|
|
set(opencl_sources ${OPENCL_SPIRV_SOURCES})
|
|
elseif(ARCH STREQUAL clspv OR ARCH STREQUAL clspv64)
|
|
set(opencl_sources ${OPENCL_CLSPV_SOURCES})
|
|
else()
|
|
set(_opencl_overrides)
|
|
if(ARCH STREQUAL amdgcn)
|
|
list(APPEND _opencl_overrides ${OPENCL_AMDGCN_SOURCES})
|
|
endif()
|
|
libclc_merge_sources(opencl_sources
|
|
${OPENCL_GENERIC_SOURCES} ${_opencl_overrides})
|
|
endif()
|
|
|
|
# Common compile options shared by CLC and OpenCL libraries.
|
|
set(compile_flags
|
|
-flto
|
|
--target=${clang_triple}
|
|
-nostdlib
|
|
-nostdlibinc
|
|
-cl-no-stdinc
|
|
-cl-std=CL3.0
|
|
-include opencl-c-base.h
|
|
-Werror=undef
|
|
-Wall
|
|
-Wextra
|
|
-fdiscard-value-names
|
|
-ffp-contract=fast-honor-pragmas
|
|
-fdenormal-fp-math=dynamic
|
|
${target_compile_flags}
|
|
)
|
|
|
|
set(_common_defs
|
|
${target_define}
|
|
${target_extra_defines}
|
|
__CLC_PRIVATE_ADDRSPACE_VAL=${private_addrspace_val}
|
|
__CLC_GENERIC_ADDRSPACE_VAL=${generic_addrspace_val}
|
|
)
|
|
|
|
# Build the CLC internal builtins library.
|
|
string(REPLACE "-" "_" lib_suffix ${t})
|
|
set(clc_lib clc_builtins_${lib_suffix})
|
|
add_libclc_builtin_library(${clc_lib}
|
|
SOURCES ${clc_sources}
|
|
COMPILE_OPTIONS ${compile_flags}
|
|
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/clc/include
|
|
COMPILE_DEFINITIONS ${_common_defs}
|
|
FOLDER "libclc/Device IR/CLC"
|
|
)
|
|
|
|
# Build, link, and install the final OpenCL builtins library.
|
|
add_libclc_library(libclc-${t}
|
|
ARCH ${ARCH}
|
|
TRIPLE ${clang_triple}
|
|
TARGET_TRIPLE ${t}
|
|
SOURCES ${opencl_sources}
|
|
COMPILE_OPTIONS ${compile_flags} "SHELL:-Xclang -fdeclare-opencl-builtins"
|
|
INCLUDE_DIRS
|
|
${CMAKE_CURRENT_SOURCE_DIR}/clc/include
|
|
${CMAKE_CURRENT_SOURCE_DIR}/opencl/include
|
|
COMPILE_DEFINITIONS ${_common_defs}
|
|
INTERNALIZE_LIBRARIES ${clc_lib}
|
|
OPT_FLAGS ${opt_flags}
|
|
OUTPUT_FILENAME libclc
|
|
PARENT_TARGET libclc-opencl-builtins
|
|
)
|
|
endforeach()
|
|
|
|
add_subdirectory(test)
|