1cmake_minimum_required(VERSION 3.13.4) 2 3project( libclc VERSION 0.2.0 LANGUAGES CXX ) 4include( GNUInstallDirs ) 5set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS 6 amdgcn-amdhsa/lib/SOURCES; 7 amdgcn/lib/SOURCES; 8 amdgcn-mesa3d/lib/SOURCES; 9 amdgpu/lib/SOURCES; 10 generic/lib/SOURCES; 11 ptx/lib/SOURCES; 12 ptx-nvidiacl/lib/SOURCES; 13 r600/lib/SOURCES; 14 spirv/lib/SOURCES; 15 spirv64/lib/SOURCES 16) 17 18# List of all targets 19set( LIBCLC_TARGETS_ALL 20 amdgcn-- 21 amdgcn--amdhsa 22 r600-- 23 nvptx-- 24 nvptx64-- 25 nvptx--nvidiacl 26 nvptx64--nvidiacl 27 spirv-mesa3d- 28 spirv64-mesa3d- 29) 30 31set( LIBCLC_MIN_LLVM "3.9.0" ) 32 33set( LIBCLC_TARGETS_TO_BUILD "all" 34 CACHE STRING "Semicolon-separated list of targets to build, or 'all'." ) 35 36option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support." 37OFF ) 38 39if( NOT LLVM_CONFIG ) 40 find_program( LLVM_CONFIG llvm-config ) 41endif() 42execute_process( COMMAND ${LLVM_CONFIG} "--version" 43 OUTPUT_VARIABLE LLVM_VERSION 44 OUTPUT_STRIP_TRAILING_WHITESPACE ) 45message( "LLVM version: ${LLVM_VERSION}" ) 46 47if( ${LLVM_VERSION} VERSION_LESS ${LIBCLC_MIN_LLVM} ) 48 message( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM}" ) 49endif() 50 51# mesa3d environment is only available since LLVM 4.0 52if( ${LLVM_VERSION} VERSION_GREATER "3.9.0" ) 53 set( LIBCLC_TARGETS_ALL ${LIBCLC_TARGETS_ALL} amdgcn-mesa-mesa3d ) 54endif() 55 56if( LIBCLC_TARGETS_TO_BUILD STREQUAL "all" ) 57 set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} ) 58endif() 59 60execute_process( COMMAND ${LLVM_CONFIG} "--system-libs" 61 OUTPUT_VARIABLE LLVM_SYSTEM_LIBS 62 OUTPUT_STRIP_TRAILING_WHITESPACE ) 63separate_arguments( LLVM_SYSTEM_LIBS ) 64execute_process( COMMAND ${LLVM_CONFIG} "--libs" "core" "bitreader" "bitwriter" 65 OUTPUT_VARIABLE LLVM_LIBS 66 OUTPUT_STRIP_TRAILING_WHITESPACE ) 67separate_arguments( LLVM_LIBS ) 68execute_process( COMMAND ${LLVM_CONFIG} "--libdir" 69 OUTPUT_VARIABLE LLVM_LIBDIR 70 OUTPUT_STRIP_TRAILING_WHITESPACE ) 71execute_process( COMMAND ${LLVM_CONFIG} "--ldflags" 72 OUTPUT_VARIABLE LLVM_LD_FLAGS 73 OUTPUT_STRIP_TRAILING_WHITESPACE ) 74execute_process( COMMAND ${LLVM_CONFIG} "--cxxflags" 75 OUTPUT_VARIABLE LLVM_CXX_FLAGS 76 OUTPUT_STRIP_TRAILING_WHITESPACE ) 77separate_arguments( LLVM_CXX_FLAGS ) 78execute_process( COMMAND ${LLVM_CONFIG} "--bindir" 79 OUTPUT_VARIABLE LLVM_BINDIR 80 OUTPUT_STRIP_TRAILING_WHITESPACE ) 81 82# These were not properly reported in early LLVM and we don't need them 83list( APPEND LLVM_CXX_FLAGS -fno-rtti -fno-exceptions ) 84 85# Print LLVM variables 86message( "LLVM system libs: ${LLVM_SYSTEM_LIBS}" ) 87message( "LLVM libs: ${LLVM_LIBS}" ) 88message( "LLVM libdir: ${LLVM_LIBDIR}" ) 89message( "LLVM bindir: ${LLVM_BINDIR}" ) 90message( "LLVM ld flags: ${LLVM_LD_FLAGS}" ) 91message( "LLVM cxx flags: ${LLVM_CXX_FLAGS}" ) 92message( "" ) 93 94find_program( LLVM_CLANG clang PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH ) 95find_program( LLVM_AS llvm-as PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH ) 96find_program( LLVM_LINK llvm-link PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH ) 97find_program( LLVM_OPT opt PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH ) 98find_program( LLVM_SPIRV llvm-spirv PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH ) 99 100# Print toolchain 101message( "clang: ${LLVM_CLANG}" ) 102message( "llvm-as: ${LLVM_AS}" ) 103message( "llvm-link: ${LLVM_LINK}" ) 104message( "opt: ${LLVM_OPT}" ) 105message( "llvm-spirv: ${LLVM_SPIRV}" ) 106message( "" ) 107if( NOT LLVM_CLANG OR NOT LLVM_OPT OR NOT LLVM_AS OR NOT LLVM_LINK ) 108 message( FATAL_ERROR "toolchain incomplete!" ) 109endif() 110 111list( SORT LIBCLC_TARGETS_TO_BUILD ) 112 113if( "spirv-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD OR "spirv64-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD ) 114 if( NOT LLVM_SPIRV ) 115 message( FATAL_ERROR "SPIR-V targets requested, but spirv-tools is not installed" ) 116 endif() 117endif() 118 119set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ) 120set( CMAKE_CLC_COMPILER ${LLVM_CLANG} ) 121set( CMAKE_CLC_ARCHIVE ${LLVM_LINK} ) 122set( CMAKE_LLAsm_PREPROCESSOR ${LLVM_CLANG} ) 123set( CMAKE_LLAsm_COMPILER ${LLVM_AS} ) 124set( CMAKE_LLAsm_ARCHIVE ${LLVM_LINK} ) 125enable_language( CLC LLAsm ) 126 127# Construct LLVM version define 128string( REPLACE "." ";" LLVM_VERSION_LIST ${LLVM_VERSION} ) 129list( GET LLVM_VERSION_LIST 0 LLVM_MAJOR ) 130list( GET LLVM_VERSION_LIST 1 LLVM_MINOR ) 131set( LLVM_VERSION_DEFINE "-DHAVE_LLVM=0x${LLVM_MAJOR}0${LLVM_MINOR}" ) 132 133# This needs to be set before any target that needs it 134link_directories( ${LLVM_LIBDIR} ) 135 136# Setup prepare_builtins tools 137add_executable( prepare_builtins utils/prepare-builtins.cpp ) 138target_compile_options( prepare_builtins PRIVATE ${LLVM_CXX_FLAGS} ) 139target_compile_definitions( prepare_builtins PRIVATE ${LLVM_VERSION_DEFINE} ) 140target_link_libraries( prepare_builtins PRIVATE ${LLVM_LIBS} ) 141target_link_libraries( prepare_builtins PRIVATE ${LLVM_SYSTEM_LIBS} ) 142 143# Setup arch devices 144set( r600--_devices cedar cypress barts cayman ) 145set( amdgcn--_devices tahiti ) 146set( amdgcn-mesa-mesa3d_devices ${amdgcn--_devices} ) 147set( amdgcn--amdhsa_devices none ) 148set( nvptx--_devices none ) 149set( nvptx64--_devices none ) 150set( nvptx--nvidiacl_devices none ) 151set( nvptx64--nvidiacl_devices none ) 152set( spirv-mesa3d-_devices none ) 153set( spirv64-mesa3d-_devices none ) 154 155# Setup aliases 156set( cedar_aliases palm sumo sumo2 redwood juniper ) 157set( cypress_aliases hemlock ) 158set( barts_aliases turks caicos ) 159set( cayman_aliases aruba ) 160set( tahiti_aliases pitcairn verde oland hainan bonaire kabini kaveri hawaii 161 mullins tonga iceland carrizo fiji stoney polaris10 polaris11 ) 162 163# Support for gfx9 was added in LLVM 5.0 (r295554) 164if( ${LLVM_VERSION} VERSION_GREATER "4.99.99" ) 165 set( tahiti_aliases ${tahiti_aliases} gfx900 gfx902 ) 166endif() 167 168# Support for Vega12 and Vega20 was added in LLVM 7 (r331215) 169if( ${LLVM_VERSION} VERSION_GREATER "6.99.99" ) 170 set( tahiti_aliases ${tahiti_aliases} gfx904 gfx906 ) 171endif() 172 173# pkg-config file 174configure_file( libclc.pc.in libclc.pc @ONLY ) 175install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libclc.pc DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig ) 176install( DIRECTORY generic/include/clc DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) 177 178if( ENABLE_RUNTIME_SUBNORMAL ) 179 add_library( subnormal_use_default STATIC 180 generic/lib/subnormal_use_default.ll ) 181 add_library( subnormal_disable STATIC 182 generic/lib/subnormal_disable.ll ) 183 install( TARGETS subnormal_use_default subnormal_disable ARCHIVE 184 DESTINATION ${CMAKE_INSTALL_DATADIR}/clc ) 185endif() 186 187find_package( Python3 REQUIRED COMPONENTS Interpreter ) 188file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/generic/lib/gen_convert.py script_loc ) 189add_custom_command( 190 OUTPUT convert.cl 191 COMMAND ${Python3_EXECUTABLE} ${script_loc} > convert.cl 192 DEPENDS ${script_loc} ) 193add_custom_target( "generate_convert.cl" DEPENDS convert.cl ) 194 195enable_testing() 196 197foreach( t ${LIBCLC_TARGETS_TO_BUILD} ) 198 message( "BUILDING ${t}" ) 199 string( REPLACE "-" ";" TRIPLE ${t} ) 200 list( GET TRIPLE 0 ARCH ) 201 list( GET TRIPLE 1 VENDOR ) 202 list( GET TRIPLE 2 OS ) 203 204 set( dirs ) 205 206 if ( NOT ${ARCH} STREQUAL spirv AND NOT ${ARCH} STREQUAL spirv64 ) 207 LIST( APPEND dirs generic ) 208 endif() 209 210 if( ${ARCH} STREQUAL r600 OR ${ARCH} STREQUAL amdgcn ) 211 list( APPEND dirs amdgpu ) 212 endif() 213 214 #nvptx is special 215 if( ${ARCH} STREQUAL nvptx OR ${ARCH} STREQUAL nvptx64 ) 216 set( DARCH ptx ) 217 else() 218 set( DARCH ${ARCH} ) 219 endif() 220 221 # Enumerate SOURCES* files 222 set( source_list ) 223 foreach( l ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS} ) 224 foreach( s "SOURCES" "SOURCES_${LLVM_MAJOR}.${LLVM_MINOR}" ) 225 file( TO_CMAKE_PATH ${l}/lib/${s} file_loc ) 226 file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/${file_loc} loc ) 227 # Prepend the location to give higher priority to 228 # specialized implementation 229 if( EXISTS ${loc} ) 230 set( source_list ${file_loc} ${source_list} ) 231 endif() 232 endforeach() 233 endforeach() 234 235 # Add the generated convert.cl here to prevent adding 236 # the one listed in SOURCES 237 if( NOT ${ARCH} STREQUAL "spirv" AND NOT ${ARCH} STREQUAL "spirv64" ) 238 set( rel_files convert.cl ) 239 set( objects convert.cl ) 240 if( NOT ENABLE_RUNTIME_SUBNORMAL ) 241 list( APPEND rel_files generic/lib/subnormal_use_default.ll ) 242 endif() 243 else() 244 set( rel_files ) 245 set( objects ) 246 endif() 247 248 foreach( l ${source_list} ) 249 file( READ ${l} file_list ) 250 string( REPLACE "\n" ";" file_list ${file_list} ) 251 get_filename_component( dir ${l} DIRECTORY ) 252 foreach( f ${file_list} ) 253 list( FIND objects ${f} found ) 254 if( found EQUAL -1 ) 255 list( APPEND objects ${f} ) 256 list( APPEND rel_files ${dir}/${f} ) 257 # FIXME: This should really go away 258 file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/${dir}/${f} src_loc ) 259 get_filename_component( fdir ${src_loc} DIRECTORY ) 260 261 set_source_files_properties( ${dir}/${f} 262 PROPERTIES COMPILE_FLAGS "-I ${fdir}" ) 263 endif() 264 endforeach() 265 endforeach() 266 267 foreach( d ${${t}_devices} ) 268 # Some targets don't have a specific GPU to target 269 if( ${d} STREQUAL "none" OR ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) 270 set( mcpu ) 271 set( arch_suffix "${t}" ) 272 else() 273 set( mcpu "-mcpu=${d}" ) 274 set( arch_suffix "${d}-${t}" ) 275 endif() 276 message( " DEVICE: ${d} ( ${${d}_aliases} )" ) 277 278 if ( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) 279 if( ${ARCH} STREQUAL "spirv" ) 280 set( t "spir--" ) 281 else() 282 set( t "spir64--" ) 283 endif() 284 set( build_flags -O0 -finline-hint-functions ) 285 set( opt_flags ) 286 set( spvflags --spirv-max-version=1.1 ) 287 else() 288 set( build_flags ) 289 set( opt_flags -O3 ) 290 endif() 291 292 add_library( builtins.link.${arch_suffix} STATIC ${rel_files} ) 293 # Make sure we depend on the pseudo target to prevent 294 # multiple invocations 295 add_dependencies( builtins.link.${arch_suffix} 296 generate_convert.cl ) 297 # CMake will turn this include into absolute path 298 target_include_directories( builtins.link.${arch_suffix} PRIVATE 299 "generic/include" ) 300 target_compile_definitions( builtins.link.${arch_suffix} PRIVATE 301 "__CLC_INTERNAL" ) 302 string( TOUPPER "-DCLC_${ARCH}" CLC_TARGET_DEFINE ) 303 target_compile_definitions( builtins.link.${arch_suffix} PRIVATE 304 ${CLC_TARGET_DEFINE} ) 305 target_compile_options( builtins.link.${arch_suffix} PRIVATE -target 306 ${t} ${mcpu} -fno-builtin -nostdlib ${build_flags} ) 307 set_target_properties( builtins.link.${arch_suffix} PROPERTIES 308 LINKER_LANGUAGE CLC ) 309 310 set( obj_suffix ${arch_suffix}.bc ) 311 312 # Add opt target 313 add_custom_command( OUTPUT "builtins.opt.${obj_suffix}" 314 COMMAND ${LLVM_OPT} ${opt_flags} -o 315 "builtins.opt.${obj_suffix}" 316 "builtins.link.${obj_suffix}" 317 DEPENDS "builtins.link.${arch_suffix}" ) 318 add_custom_target( "opt.${obj_suffix}" ALL 319 DEPENDS "builtins.opt.${obj_suffix}" ) 320 321 if( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) 322 set( spv_suffix ${arch_suffix}.spv ) 323 add_custom_command( OUTPUT "${spv_suffix}" 324 COMMAND ${LLVM_SPIRV} ${spvflags} 325 -o "${spv_suffix}" 326 "builtins.link.${obj_suffix}" 327 DEPENDS "builtins.link.${arch_suffix}" ) 328 add_custom_target( "prepare-${spv_suffix}" ALL 329 DEPENDS "${spv_suffix}" ) 330 install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix} 331 DESTINATION ${CMAKE_INSTALL_DATADIR}/clc ) 332 else() 333 334 # Add prepare target 335 add_custom_command( OUTPUT "${obj_suffix}" 336 COMMAND prepare_builtins -o 337 "${obj_suffix}" 338 "builtins.opt.${obj_suffix}" 339 DEPENDS "opt.${obj_suffix}" 340 "builtins.opt.${obj_suffix}" 341 prepare_builtins ) 342 add_custom_target( "prepare-${obj_suffix}" ALL 343 DEPENDS "${obj_suffix}" ) 344 345 # nvptx-- targets don't include workitem builtins 346 if( NOT ${t} MATCHES ".*ptx.*--$" ) 347 add_test( NAME external-calls-${obj_suffix} 348 COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} 349 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) 350 set_tests_properties( external-calls-${obj_suffix} 351 PROPERTIES ENVIRONMENT "LLVM_CONFIG=${LLVM_CONFIG}" ) 352 endif() 353 354 install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION ${CMAKE_INSTALL_DATADIR}/clc ) 355 foreach( a ${${d}_aliases} ) 356 set( alias_suffix "${a}-${t}.bc" ) 357 add_custom_target( ${alias_suffix} ALL 358 COMMAND ${CMAKE_COMMAND} -E 359 create_symlink ${obj_suffix} 360 ${alias_suffix} 361 DEPENDS "prepare-${obj_suffix}" ) 362 install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix} DESTINATION ${CMAKE_INSTALL_DATADIR}/clc ) 363 endforeach( a ) 364 endif() 365 endforeach( d ) 366endforeach( t ) 367