@@ -4,6 +4,15 @@ project( libclc VERSION 0.2.0 LANGUAGES CXX C)
4
4
5
5
set (CMAKE_CXX_STANDARD 17 )
6
6
7
+ # Add path for custom modules
8
+ list ( INSERT CMAKE_MODULE_PATH 0 "${PROJECT_SOURCE_DIR} /cmake/modules" )
9
+
10
+ set ( LIBCLC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
11
+ set ( LIBCLC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} )
12
+ set ( LIBCLC_OBJFILE_DIR ${LIBCLC_BINARY_DIR} /obj.libclc.dir )
13
+
14
+ include ( AddLibclc )
15
+
7
16
include ( GNUInstallDirs )
8
17
set_property (DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
9
18
amdgcn-amdhsa/lib/SOURCES;
@@ -27,31 +36,51 @@ set( LIBCLC_TARGETS_TO_BUILD "all"
27
36
28
37
option ( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support." OFF )
29
38
30
- find_package (LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR} " )
31
- include (AddLLVM )
39
+ if ( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
40
+ # Out-of-tree configuration
41
+ set ( LIBCLC_STANDALONE_BUILD TRUE )
32
42
33
- message ( STATUS "libclc LLVM version: ${LLVM_PACKAGE_VERSION} " )
43
+ find_package (LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR} " )
44
+ include (AddLLVM )
34
45
35
- if ( LLVM_PACKAGE_VERSION VERSION_LESS LIBCLC_MIN_LLVM )
36
- message ( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM} " )
37
- endif ()
46
+ message ( STATUS "libclc LLVM version: ${LLVM_PACKAGE_VERSION} " )
38
47
39
- find_program ( LLVM_CLANG clang PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
40
- find_program ( LLVM_AS llvm-as PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
41
- find_program ( LLVM_LINK llvm-link PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
42
- find_program ( LLVM_OPT opt PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
43
- find_program ( LLVM_SPIRV llvm-spirv PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
48
+ if ( LLVM_PACKAGE_VERSION VERSION_LESS LIBCLC_MIN_LLVM )
49
+ message ( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM} " )
50
+ endif ()
44
51
45
- # Print toolchain
46
- message ( STATUS "libclc toolchain - clang: ${LLVM_CLANG} " )
47
- message ( STATUS "libclc toolchain - llvm-as: ${LLVM_AS} " )
48
- message ( STATUS "libclc toolchain - llvm-link: ${LLVM_LINK} " )
49
- message ( STATUS "libclc toolchain - opt: ${LLVM_OPT} " )
50
- message ( STATUS "libclc toolchain - llvm-spirv: ${LLVM_SPIRV} " )
51
- if ( NOT LLVM_CLANG OR NOT LLVM_OPT OR NOT LLVM_AS OR NOT LLVM_LINK )
52
+ # Import required tools as targets
53
+ foreach ( tool clang llvm-as llvm-link opt )
54
+ find_program ( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
55
+ add_executable ( libclc::${tool} IMPORTED GLOBAL )
56
+ set_target_properties ( libclc::${tool} PROPERTIES IMPORTED_LOCATION ${LLVM_TOOL_${tool}} )
57
+ endforeach ()
58
+ else ()
59
+ # In-tree configuration
60
+ set ( LIBCLC_STANDALONE_BUILD FALSE )
61
+
62
+ set ( LLVM_PACKAGE_VERSION ${LLVM_VERSION} )
63
+
64
+ # Note that we check this later (for both build types) but we can provide a
65
+ # more useful error message when built in-tree. We assume that LLVM tools are
66
+ # always available so don't warn here.
67
+ if ( NOT clang IN_LIST LLVM_ENABLE_PROJECTS )
68
+ message (FATAL_ERROR "Clang is not enabled, but is required to build libclc in-tree" )
69
+ endif ()
70
+
71
+ foreach ( tool clang llvm-as llvm-link opt )
72
+ add_executable (libclc::${tool} ALIAS ${tool} )
73
+ endforeach ()
74
+ endif ()
75
+
76
+ if ( NOT TARGET libclc::clang OR NOT TARGET libclc::opt
77
+ OR NOT TARGET libclc::llvm-as OR NOT TARGET libclc::llvm-link )
52
78
message ( FATAL_ERROR "libclc toolchain incomplete!" )
53
79
endif ()
54
80
81
+ # llvm-spirv is an optional dependency, used to build spirv-* targets.
82
+ find_program ( LLVM_SPIRV llvm-spirv PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
83
+
55
84
# List of all targets. Note that some are added dynamically below.
56
85
set ( LIBCLC_TARGETS_ALL
57
86
amdgcn--
@@ -90,24 +119,9 @@ if( "spirv-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD OR "spirv64-mesa3d-" IN_LIST
90
119
endif ()
91
120
endif ()
92
121
93
- set ( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR} /cmake )
94
- set ( CMAKE_CLC_COMPILER ${LLVM_CLANG} )
95
- set ( CMAKE_CLC_ARCHIVE ${LLVM_LINK} )
96
- set ( CMAKE_LLAsm_PREPROCESSOR ${LLVM_CLANG} )
97
- set ( CMAKE_LLAsm_COMPILER ${LLVM_AS} )
98
- set ( CMAKE_LLAsm_ARCHIVE ${LLVM_LINK} )
99
-
100
122
# Construct LLVM version define
101
123
set ( LLVM_VERSION_DEFINE "-DHAVE_LLVM=0x${LLVM_VERSION_MAJOR} 0${LLVM_VERSION_MINOR} " )
102
124
103
-
104
- # LLVM 13 enables standard includes by default
105
- if ( LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 13.0.0 )
106
- set ( CMAKE_LLAsm_FLAGS "${CMAKE_LLAsm_FLAGS} -cl-no-stdinc" )
107
- set ( CMAKE_CLC_FLAGS "${CMAKE_CLC_FLAGS} -cl-no-stdinc" )
108
- endif ()
109
-
110
- enable_language ( CLC LLAsm )
111
125
# This needs to be set before any target that needs it
112
126
# We need to use LLVM_INCLUDE_DIRS here, because if we are linking to an
113
127
# llvm build directory, this includes $src/llvm/include which is where all the
@@ -122,7 +136,7 @@ set(LLVM_LINK_COMPONENTS
122
136
IRReader
123
137
Support
124
138
)
125
- if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
139
+ if ( LIBCLC_STANDALONE_BUILD )
126
140
add_llvm_executable ( prepare_builtins utils/prepare-builtins.cpp )
127
141
else ()
128
142
add_llvm_utility ( prepare_builtins utils/prepare-builtins.cpp )
@@ -167,12 +181,15 @@ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libclc.pc DESTINATION "${CMAKE_INSTAL
167
181
install ( DIRECTORY generic/include/clc DESTINATION "${CMAKE_INSTALL_INCLUDEDIR} " )
168
182
169
183
if ( ENABLE_RUNTIME_SUBNORMAL )
170
- add_library ( subnormal_use_default STATIC
171
- generic/lib/subnormal_use_default.ll )
172
- add_library ( subnormal_disable STATIC
173
- generic/lib/subnormal_disable.ll )
174
- install ( TARGETS subnormal_use_default subnormal_disable ARCHIVE
175
- DESTINATION "${CMAKE_INSTALL_DATADIR} /clc" )
184
+ foreach ( file subnormal_use_default subnormal_disable )
185
+ link_bc (
186
+ OUTPUT ${LIBCLC_OBJFILE_DIR} /${file}.bc
187
+ INPUTS ${PROJECT_SOURCE_DIR} /generic/lib/${file}.ll
188
+ )
189
+ add_custom_target ( ${file} .bc ALL DEPENDS ${LIBCLC_OBJFILE_DIR} /${file}.bc )
190
+ install ( FILES ${LIBCLC_OBJFILE_DIR} /${file}.bc ARCHIVE
191
+ DESTINATION "${CMAKE_INSTALL_DATADIR} /clc" )
192
+ endforeach ()
176
193
endif ()
177
194
178
195
find_package ( Python3 REQUIRED COMPONENTS Interpreter )
@@ -232,128 +249,152 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
232
249
233
250
# Add the generated convert.cl here to prevent adding the one listed in
234
251
# SOURCES
252
+ set ( objects ) # A "set" of already-added input files
253
+ set ( rel_files ) # Source directory input files, relative to the root dir
254
+ set ( gen_files ) # Generated binary input files, relative to the binary dir
235
255
if ( NOT ${ARCH} STREQUAL "spirv" AND NOT ${ARCH} STREQUAL "spirv64" )
236
256
if ( NOT ENABLE_RUNTIME_SUBNORMAL AND NOT ${ARCH} STREQUAL "clspv" AND
237
257
NOT ${ARCH} STREQUAL "clspv64" )
238
- set ( rel_files convert.cl )
239
- set ( objects convert.cl )
258
+ list ( APPEND gen_files convert.cl )
259
+ list ( APPEND objects convert.cl )
240
260
list ( APPEND rel_files generic/lib/subnormal_use_default.ll )
241
261
elseif (${ARCH} STREQUAL "clspv" OR ${ARCH} STREQUAL "clspv64" )
242
- set ( rel_files clspv-convert.cl )
243
- set ( objects clspv-convert.cl )
262
+ list ( APPEND gen_files clspv-convert.cl )
263
+ list ( APPEND objects clspv-convert.cl )
244
264
endif ()
245
- else ()
246
- set ( rel_files )
247
- set ( objects )
248
265
endif ()
249
266
250
267
foreach ( l ${source_list} )
251
268
file ( READ ${l} file_list )
252
269
string ( REPLACE "\n " ";" file_list ${file_list} )
253
270
get_filename_component ( dir ${l} DIRECTORY )
254
271
foreach ( f ${file_list} )
255
- list ( FIND objects ${f} found )
256
- if ( found EQUAL -1 )
272
+ # Only add each file once, so that targets can 'specialize' builtins
273
+ if ( NOT ${f} IN_LIST objects )
257
274
list ( APPEND objects ${f} )
258
275
list ( APPEND rel_files ${dir} /${f} )
259
- # FIXME: This should really go away
260
- file ( TO_CMAKE_PATH ${PROJECT_SOURCE_DIR} /${dir}/${f} src_loc )
261
- get_filename_component ( fdir ${src_loc} DIRECTORY )
262
-
263
- set_source_files_properties ( ${dir} /${f}
264
- PROPERTIES COMPILE_FLAGS "-I ${fdir} " )
265
276
endif ()
266
277
endforeach ()
267
278
endforeach ()
268
279
269
280
foreach ( d ${${t}_devices} )
270
- # Some targets don't have a specific GPU to target
271
- if ( ${d} STREQUAL "none" OR ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" )
272
- set ( mcpu )
273
- set ( arch_suffix "${t} " )
274
- else ()
275
- set ( mcpu "-mcpu=${d} " )
276
- set ( arch_suffix "${d} -${t} " )
281
+ get_libclc_device_info (
282
+ TRIPLE ${t}
283
+ DEVICE ${d}
284
+ CPU cpu
285
+ ARCH_SUFFIX arch_suffix
286
+ CLANG_TRIPLE clang_triple
287
+ )
288
+
289
+ set ( mcpu )
290
+ if ( NOT "${cpu} " STREQUAL "" )
291
+ set ( mcpu "-mcpu=${cpu} " )
277
292
endif ()
293
+
278
294
message ( STATUS " device: ${d} ( ${${d} _aliases} )" )
279
295
280
- if ( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" )
281
- if ( ${ARCH} STREQUAL "spirv" )
282
- set ( t "spir--" )
283
- else ()
284
- set ( t "spir64--" )
285
- endif ()
296
+ if ( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
286
297
set ( build_flags -O0 -finline-hint-functions )
287
298
set ( opt_flags )
288
299
set ( spvflags --spirv-max-version=1.1 )
289
- elseif ( ${ARCH} STREQUAL "clspv" )
290
- set ( t "spir--" )
291
- set ( build_flags "-Wno-unknown-assumption" )
292
- set ( opt_flags -O3 )
293
- elseif ( ${ARCH} STREQUAL "clspv64" )
294
- set ( t "spir64--" )
300
+ elseif ( ARCH STREQUAL clspv OR ARCH STREQUAL clspv64 )
295
301
set ( build_flags "-Wno-unknown-assumption" )
296
302
set ( opt_flags -O3 )
297
303
else ()
298
304
set ( build_flags )
299
305
set ( opt_flags -O3 )
300
306
endif ()
301
307
302
- set ( builtins_link_lib_tgt builtins.link.${arch_suffix} )
303
- add_library ( ${builtins_link_lib_tgt} STATIC ${rel_files} )
304
- # Make sure we depend on the pseudo target to prevent
305
- # multiple invocations
306
- add_dependencies ( ${builtins_link_lib_tgt} generate_convert.cl )
307
- add_dependencies ( ${builtins_link_lib_tgt} clspv-generate_convert.cl )
308
- # CMake will turn this include into absolute path
309
- target_include_directories ( ${builtins_link_lib_tgt} PRIVATE
310
- "generic/include" )
311
- target_compile_definitions ( ${builtins_link_lib_tgt} PRIVATE
312
- "__CLC_INTERNAL" )
313
- string ( TOUPPER "-DCLC_${ARCH} " CLC_TARGET_DEFINE )
314
- target_compile_definitions ( ${builtins_link_lib_tgt} PRIVATE
315
- ${CLC_TARGET_DEFINE} )
316
- target_compile_options ( ${builtins_link_lib_tgt} PRIVATE -target
317
- ${t} ${mcpu} -fno-builtin -nostdlib ${build_flags} )
318
- set_target_properties ( ${builtins_link_lib_tgt} PROPERTIES
319
- LINKER_LANGUAGE CLC )
320
-
321
- set ( obj_suffix ${arch_suffix} .bc )
322
- set ( builtins_opt_lib_tgt builtins.opt.${obj_suffix} )
323
-
324
- # Add opt target
325
- add_custom_command ( OUTPUT ${builtins_opt_lib_tgt}
326
- COMMAND ${LLVM_OPT} ${opt_flags} -o ${builtins_opt_lib_tgt}
327
- $< TARGET_FILE:${builtins_link_lib_tgt} >
328
- DEPENDS ${builtins_link_lib_tgt} )
329
- add_custom_target ( "opt.${obj_suffix} " ALL
330
- DEPENDS ${builtins_opt_lib_tgt} )
331
-
332
- if ( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" )
308
+ set ( LIBCLC_ARCH_OBJFILE_DIR "${LIBCLC_OBJFILE_DIR} /${arch_suffix} " )
309
+ file ( MAKE_DIRECTORY ${LIBCLC_ARCH_OBJFILE_DIR} )
310
+
311
+ string ( TOUPPER "CLC_${ARCH} " CLC_TARGET_DEFINE )
312
+
313
+ list ( APPEND build_flags
314
+ -D__CLC_INTERNAL
315
+ -D${CLC_TARGET_DEFINE}
316
+ -I${PROJECT_SOURCE_DIR}/generic/include
317
+ # FIXME: Fix libclc to not require disabling this noisy warnings
318
+ -Wno-bitwise-conditional-parentheses
319
+ )
320
+
321
+ set ( bytecode_files "" )
322
+ foreach ( file IN LISTS gen_files rel_files )
323
+ # We need to take each file and produce an absolute input file, as well
324
+ # as a unique architecture-specific output file. We deal with a mix of
325
+ # different input files, which makes this trickier.
326
+ if ( ${file} IN_LIST gen_files )
327
+ # Generated files are given just as file names, which we must make
328
+ # absolute to the binary directory.
329
+ set ( input_file ${CMAKE_CURRENT_BINARY_DIR} /${file} )
330
+ set ( output_file "${LIBCLC_ARCH_OBJFILE_DIR} /${file} .o" )
331
+ else ()
332
+ # Other files are originally relative to each SOURCE file, which are
333
+ # then make relative to the libclc root directory. We must normalize
334
+ # the path (e.g., ironing out any ".."), then make it relative to the
335
+ # root directory again, and use that relative path component for the
336
+ # binary path.
337
+ get_filename_component ( abs_path ${file} ABSOLUTE BASE_DIR ${PROJECT_SOURCE_DIR} )
338
+ file ( RELATIVE_PATH root_rel_path ${PROJECT_SOURCE_DIR} ${abs_path} )
339
+ set ( input_file ${PROJECT_SOURCE_DIR} /${file} )
340
+ set ( output_file "${LIBCLC_ARCH_OBJFILE_DIR} /${root_rel_path} .o" )
341
+ endif ()
342
+
343
+ get_filename_component ( file_dir ${file} DIRECTORY )
344
+
345
+ compile_to_bc (
346
+ TRIPLE ${clang_triple}
347
+ INPUT ${input_file}
348
+ OUTPUT ${output_file}
349
+ EXTRA_OPTS "${mcpu} " -fno-builtin -nostdlib
350
+ "${build_flags} " -I${PROJECT_SOURCE_DIR}/${file_dir}
351
+ )
352
+ list (APPEND bytecode_files ${output_file} )
353
+ endforeach ()
354
+
355
+ set ( builtins_link_lib_tgt builtins.link.${arch_suffix}.bc )
356
+
357
+ link_bc (
358
+ OUTPUT ${builtins_link_lib_tgt}
359
+ INPUTS ${bytecode_files}
360
+ )
361
+
362
+ if ( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
333
363
set ( spv_suffix ${arch_suffix} .spv )
334
364
add_custom_command ( OUTPUT "${spv_suffix} "
335
- COMMAND ${LLVM_SPIRV} ${spvflags} -o "${spv_suffix} " $< TARGET_FILE: $ {builtins_link_lib_tgt}>
365
+ COMMAND ${LLVM_SPIRV} ${spvflags} -o "${spv_suffix} " ${builtins_link_lib_tgt}
336
366
DEPENDS ${builtins_link_lib_tgt} )
337
367
add_custom_target ( "prepare-${spv_suffix} " ALL DEPENDS "${spv_suffix} " )
338
368
install ( FILES ${CMAKE_CURRENT_BINARY_DIR} /${spv_suffix}
339
369
DESTINATION "${CMAKE_INSTALL_DATADIR} /clc" )
340
370
else ()
371
+ set ( obj_suffix ${arch_suffix} .bc )
372
+ set ( builtins_opt_lib_tgt builtins.opt.${obj_suffix} )
373
+
374
+ # Add opt target
375
+ add_custom_command ( OUTPUT ${builtins_opt_lib_tgt}
376
+ COMMAND libclc::opt ${opt_flags} -o ${builtins_opt_lib_tgt}
377
+ ${builtins_link_lib_tgt}
378
+ DEPENDS ${builtins_link_lib_tgt} )
379
+ add_custom_target ( "opt.${obj_suffix} " ALL
380
+ DEPENDS ${builtins_opt_lib_tgt} )
381
+
341
382
# Add prepare target
342
383
add_custom_command ( OUTPUT "${obj_suffix} "
343
384
COMMAND prepare_builtins -o "${obj_suffix} " ${builtins_opt_lib_tgt}
344
385
DEPENDS "opt.${obj_suffix} " ${builtins_opt_lib_tgt} prepare_builtins )
345
386
add_custom_target ( "prepare-${obj_suffix} " ALL DEPENDS "${obj_suffix} " )
346
387
347
388
# nvptx-- targets don't include workitem builtins
348
- if ( NOT ${t} MATCHES ".*ptx.*--$" )
389
+ if ( NOT clang_triple MATCHES ".*ptx.*--$" )
349
390
add_test ( NAME external-calls-${obj_suffix}
350
391
COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR} /${obj_suffix} ${LLVM_TOOLS_BINARY_DIR}
351
392
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} )
352
393
endif ()
353
394
354
395
install ( FILES ${CMAKE_CURRENT_BINARY_DIR} /${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR} /clc" )
355
396
foreach ( a ${${d}_aliases} )
356
- set ( alias_suffix "${a} -${t } .bc" )
397
+ set ( alias_suffix "${a} -${clang_triple } .bc" )
357
398
add_custom_target ( ${alias_suffix} ALL
358
399
COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix}
359
400
DEPENDS "prepare-${obj_suffix} " )
0 commit comments