@@ -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 (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 ()
51
+
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 )
44
61
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 )
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
@@ -163,12 +177,15 @@ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libclc.pc DESTINATION "${CMAKE_INSTAL
163
177
install ( DIRECTORY generic/include/clc DESTINATION "${CMAKE_INSTALL_INCLUDEDIR} " )
164
178
165
179
if ( ENABLE_RUNTIME_SUBNORMAL )
166
- add_library ( subnormal_use_default STATIC
167
- generic/lib/subnormal_use_default.ll )
168
- add_library ( subnormal_disable STATIC
169
- generic/lib/subnormal_disable.ll )
170
- install ( TARGETS subnormal_use_default subnormal_disable ARCHIVE
171
- DESTINATION "${CMAKE_INSTALL_DATADIR} /clc" )
180
+ foreach ( file subnormal_use_default subnormal_disable )
181
+ link_bc (
182
+ OUTPUT ${LIBCLC_OBJFILE_DIR} /${file}.bc
183
+ INPUTS ${PROJECT_SOURCE_DIR} /generic/lib/${file}.ll
184
+ )
185
+ add_custom_target ( ${file} .bc ALL DEPENDS ${LIBCLC_OBJFILE_DIR} /${file}.bc )
186
+ install ( FILES ${LIBCLC_OBJFILE_DIR} /${file}.bc ARCHIVE
187
+ DESTINATION "${CMAKE_INSTALL_DATADIR} /clc" )
188
+ endforeach ()
172
189
endif ()
173
190
174
191
find_package ( Python3 REQUIRED COMPONENTS Interpreter )
@@ -228,99 +245,123 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
228
245
229
246
# Add the generated convert.cl here to prevent adding the one listed in
230
247
# SOURCES
248
+ set ( objects ) # A "set" of already-added input files
249
+ set ( rel_files ) # Source directory input files, relative to the root dir
250
+ set ( gen_files ) # Generated binary input files, relative to the binary dir
231
251
if ( NOT ${ARCH} STREQUAL "spirv" AND NOT ${ARCH} STREQUAL "spirv64" )
232
252
if ( NOT ENABLE_RUNTIME_SUBNORMAL AND NOT ${ARCH} STREQUAL "clspv" AND
233
253
NOT ${ARCH} STREQUAL "clspv64" )
234
- set ( rel_files convert.cl )
235
- set ( objects convert.cl )
254
+ list ( APPEND gen_files convert.cl )
255
+ list ( APPEND objects convert.cl )
236
256
list ( APPEND rel_files generic/lib/subnormal_use_default.ll )
237
257
elseif (${ARCH} STREQUAL "clspv" OR ${ARCH} STREQUAL "clspv64" )
238
- set ( rel_files clspv-convert.cl )
239
- set ( objects clspv-convert.cl )
258
+ list ( APPEND gen_files clspv-convert.cl )
259
+ list ( APPEND objects clspv-convert.cl )
240
260
endif ()
241
- else ()
242
- set ( rel_files )
243
- set ( objects )
244
261
endif ()
245
262
246
263
foreach ( l ${source_list} )
247
264
file ( READ ${l} file_list )
248
265
string ( REPLACE "\n " ";" file_list ${file_list} )
249
266
get_filename_component ( dir ${l} DIRECTORY )
250
267
foreach ( f ${file_list} )
251
- list ( FIND objects ${f} found )
252
- if ( found EQUAL -1 )
268
+ # Only add each file once, so that targets can 'specialize' builtins
269
+ if ( NOT ${f} IN_LIST objects )
253
270
list ( APPEND objects ${f} )
254
271
list ( APPEND rel_files ${dir} /${f} )
255
- # FIXME: This should really go away
256
- file ( TO_CMAKE_PATH ${PROJECT_SOURCE_DIR} /${dir}/${f} src_loc )
257
- get_filename_component ( fdir ${src_loc} DIRECTORY )
258
-
259
- set_source_files_properties ( ${dir} /${f}
260
- PROPERTIES COMPILE_FLAGS "-I ${fdir} " )
261
272
endif ()
262
273
endforeach ()
263
274
endforeach ()
264
275
265
276
foreach ( d ${${t}_devices} )
266
- # Some targets don't have a specific GPU to target
267
- if ( ${d} STREQUAL "none" OR ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" )
268
- set ( mcpu )
269
- set ( arch_suffix "${t} " )
270
- else ()
271
- set ( mcpu "-mcpu=${d} " )
272
- set ( arch_suffix "${d} -${t} " )
277
+ get_libclc_device_info (
278
+ TRIPLE ${t}
279
+ DEVICE ${d}
280
+ CPU cpu
281
+ ARCH_SUFFIX arch_suffix
282
+ CLANG_TRIPLE clang_triple
283
+ )
284
+
285
+ set ( mcpu )
286
+ if ( NOT "${cpu} " STREQUAL "" )
287
+ set ( mcpu "-mcpu=${cpu} " )
273
288
endif ()
289
+
274
290
message ( STATUS " device: ${d} ( ${${d} _aliases} )" )
275
291
276
- if ( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" )
277
- if ( ${ARCH} STREQUAL "spirv" )
278
- set ( t "spir--" )
279
- else ()
280
- set ( t "spir64--" )
281
- endif ()
292
+ if ( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
282
293
set ( build_flags -O0 -finline-hint-functions )
283
294
set ( opt_flags )
284
295
set ( spvflags --spirv-max-version=1.1 )
285
- elseif ( ${ARCH} STREQUAL "clspv" )
286
- set ( t "spir--" )
287
- set ( build_flags "-Wno-unknown-assumption" )
288
- set ( opt_flags -O3 )
289
- elseif ( ${ARCH} STREQUAL "clspv64" )
290
- set ( t "spir64--" )
296
+ elseif ( ARCH STREQUAL clspv OR ARCH STREQUAL clspv64 )
291
297
set ( build_flags "-Wno-unknown-assumption" )
292
298
set ( opt_flags -O3 )
293
299
else ()
294
300
set ( build_flags )
295
301
set ( opt_flags -O3 )
296
302
endif ()
297
303
298
- set ( builtins_link_lib_tgt builtins.link.${arch_suffix} )
299
- add_library ( ${builtins_link_lib_tgt} STATIC ${rel_files} )
300
- # Make sure we depend on the pseudo target to prevent
301
- # multiple invocations
302
- add_dependencies ( ${builtins_link_lib_tgt} generate_convert.cl )
303
- add_dependencies ( ${builtins_link_lib_tgt} clspv-generate_convert.cl )
304
- # CMake will turn this include into absolute path
305
- target_include_directories ( ${builtins_link_lib_tgt} PRIVATE
306
- "generic/include" )
307
- target_compile_definitions ( ${builtins_link_lib_tgt} PRIVATE
308
- "__CLC_INTERNAL" )
309
- string ( TOUPPER "-DCLC_${ARCH} " CLC_TARGET_DEFINE )
310
- target_compile_definitions ( ${builtins_link_lib_tgt} PRIVATE
311
- ${CLC_TARGET_DEFINE} )
312
- target_compile_options ( ${builtins_link_lib_tgt} PRIVATE -target
313
- ${t} ${mcpu} -fno-builtin -nostdlib ${build_flags} )
314
- set_target_properties ( ${builtins_link_lib_tgt} PROPERTIES
315
- LINKER_LANGUAGE CLC )
304
+ set ( LIBCLC_ARCH_OBJFILE_DIR "${LIBCLC_OBJFILE_DIR} /${arch_suffix} " )
305
+ file ( MAKE_DIRECTORY ${LIBCLC_ARCH_OBJFILE_DIR} )
306
+
307
+ string ( TOUPPER "CLC_${ARCH} " CLC_TARGET_DEFINE )
308
+
309
+ list ( APPEND build_flags
310
+ -D__CLC_INTERNAL
311
+ -D${CLC_TARGET_DEFINE}
312
+ -I${PROJECT_SOURCE_DIR}/generic/include
313
+ # FIXME: Fix libclc to not require disabling this noisy warnings
314
+ -Wno-bitwise-conditional-parentheses
315
+ )
316
+
317
+ set ( bytecode_files "" )
318
+ foreach ( file IN LISTS gen_files rel_files )
319
+ # We need to take each file and produce an absolute input file, as well
320
+ # as a unique architecture-specific output file. We deal with a mix of
321
+ # different input files, which makes this trickier.
322
+ if ( ${file} IN_LIST gen_files )
323
+ # Generated files are given just as file names, which we must make
324
+ # absolute to the binary directory.
325
+ set ( input_file ${CMAKE_CURRENT_BINARY_DIR} /${file} )
326
+ set ( output_file "${LIBCLC_ARCH_OBJFILE_DIR} /${file} .o" )
327
+ else ()
328
+ # Other files are originally relative to each SOURCE file, which are
329
+ # then make relative to the libclc root directory. We must normalize
330
+ # the path (e.g., ironing out any ".."), then make it relative to the
331
+ # root directory again, and use that relative path component for the
332
+ # binary path.
333
+ get_filename_component ( abs_path ${file} ABSOLUTE BASE_DIR ${PROJECT_SOURCE_DIR} )
334
+ file ( RELATIVE_PATH root_rel_path ${PROJECT_SOURCE_DIR} ${abs_path} )
335
+ set ( input_file ${PROJECT_SOURCE_DIR} /${file} )
336
+ set ( output_file "${LIBCLC_ARCH_OBJFILE_DIR} /${root_rel_path} .o" )
337
+ endif ()
338
+
339
+ get_filename_component ( file_dir ${file} DIRECTORY )
340
+
341
+ compile_to_bc (
342
+ TRIPLE ${clang_triple}
343
+ INPUT ${input_file}
344
+ OUTPUT ${output_file}
345
+ EXTRA_OPTS "${mcpu} " -fno-builtin -nostdlib
346
+ "${build_flags} " -I${PROJECT_SOURCE_DIR}/${file_dir}
347
+ )
348
+ list (APPEND bytecode_files ${output_file} )
349
+ endforeach ()
350
+
351
+ set ( builtins_link_lib_tgt builtins.link.${arch_suffix}.bc )
352
+
353
+ link_bc (
354
+ OUTPUT ${builtins_link_lib_tgt}
355
+ INPUTS ${bytecode_files}
356
+ )
316
357
317
358
set ( obj_suffix ${arch_suffix} .bc )
318
359
set ( builtins_opt_lib_tgt builtins.opt.${obj_suffix} )
319
360
320
361
# Add opt target
321
362
add_custom_command ( OUTPUT ${builtins_opt_lib_tgt}
322
- COMMAND ${LLVM_OPT} ${opt_flags} -o ${builtins_opt_lib_tgt}
323
- $< TARGET_FILE: $ {builtins_link_lib_tgt}>
363
+ COMMAND libclc::opt ${opt_flags} -o ${builtins_opt_lib_tgt}
364
+ ${builtins_link_lib_tgt}
324
365
DEPENDS ${builtins_link_lib_tgt} )
325
366
add_custom_target ( "opt.${obj_suffix} " ALL
326
367
DEPENDS ${builtins_opt_lib_tgt} )
@@ -341,15 +382,15 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
341
382
add_custom_target ( "prepare-${obj_suffix} " ALL DEPENDS "${obj_suffix} " )
342
383
343
384
# nvptx-- targets don't include workitem builtins
344
- if ( NOT ${t } MATCHES ".*ptx.*--$" )
385
+ if ( NOT ${clang_triple } MATCHES ".*ptx.*--$" )
345
386
add_test ( NAME external-calls-${obj_suffix}
346
387
COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR} /${obj_suffix} ${LLVM_TOOLS_BINARY_DIR}
347
388
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} )
348
389
endif ()
349
390
350
391
install ( FILES ${CMAKE_CURRENT_BINARY_DIR} /${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR} /clc" )
351
392
foreach ( a ${${d}_aliases} )
352
- set ( alias_suffix "${a} -${t } .bc" )
393
+ set ( alias_suffix "${a} -${clang_triple } .bc" )
353
394
add_custom_target ( ${alias_suffix} ALL
354
395
COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix}
355
396
DEPENDS "prepare-${obj_suffix} " )
@@ -358,3 +399,7 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
358
399
endif ()
359
400
endforeach ( d )
360
401
endforeach ( t )
402
+
403
+ if ( NOT LIBCLC_STANDALONE_BUILD )
404
+ add_subdirectory ( test )
405
+ endif ()
0 commit comments