xref: /llvm-project/libclc/cmake/modules/AddLibclc.cmake (revision 76befc86dea9cad6be870c04732379f7ecf596dd)
172f9881cSFraser Cormack# Compiles an OpenCL C - or assembles an LL file - to bytecode
272f9881cSFraser Cormack#
372f9881cSFraser Cormack# Arguments:
472f9881cSFraser Cormack# * TRIPLE <string>
572f9881cSFraser Cormack#     Target triple for which to compile the bytecode file.
672f9881cSFraser Cormack# * INPUT <string>
772f9881cSFraser Cormack#     File to compile/assemble to bytecode
872f9881cSFraser Cormack# * OUTPUT <string>
972f9881cSFraser Cormack#     Bytecode file to generate
1072f9881cSFraser Cormack# * EXTRA_OPTS <string> ...
1172f9881cSFraser Cormack#     List of compiler options to use. Note that some are added by default.
1272f9881cSFraser Cormack# * DEPENDENCIES <string> ...
1372f9881cSFraser Cormack#     List of extra dependencies to inject
1472f9881cSFraser Cormack#
155ee53d41SHarald van Dijk# Depends on the clang, llvm-as, and llvm-link targets for compiling,
165ee53d41SHarald van Dijk# assembling, and linking, respectively.
1772f9881cSFraser Cormackfunction(compile_to_bc)
1872f9881cSFraser Cormack  cmake_parse_arguments(ARG
1972f9881cSFraser Cormack    ""
2072f9881cSFraser Cormack    "TRIPLE;INPUT;OUTPUT"
2172f9881cSFraser Cormack    "EXTRA_OPTS;DEPENDENCIES"
2272f9881cSFraser Cormack    ${ARGN}
2372f9881cSFraser Cormack  )
2472f9881cSFraser Cormack
2572f9881cSFraser Cormack  # If this is an LLVM IR file (identified soley by its file suffix),
2672f9881cSFraser Cormack  # pre-process it with clang to a temp file, then assemble that to bytecode.
2772f9881cSFraser Cormack  set( TMP_SUFFIX )
2872f9881cSFraser Cormack  get_filename_component( FILE_EXT ${ARG_INPUT} EXT )
2972f9881cSFraser Cormack  if( NOT ${FILE_EXT} STREQUAL ".ll" )
3072f9881cSFraser Cormack    # Pass '-c' when not running the preprocessor
3172f9881cSFraser Cormack    set( PP_OPTS -c )
3272f9881cSFraser Cormack  else()
3372f9881cSFraser Cormack    set( PP_OPTS -E;-P )
3472f9881cSFraser Cormack    set( TMP_SUFFIX .tmp )
3572f9881cSFraser Cormack  endif()
3672f9881cSFraser Cormack
3772f9881cSFraser Cormack  set( TARGET_ARG )
3872f9881cSFraser Cormack  if( ARG_TRIPLE )
3972f9881cSFraser Cormack    set( TARGET_ARG "-target" ${ARG_TRIPLE} )
4072f9881cSFraser Cormack  endif()
4172f9881cSFraser Cormack
42e614e037SFraser Cormack  # Ensure the directory we are told to output to exists
43e614e037SFraser Cormack  get_filename_component( ARG_OUTPUT_DIR ${ARG_OUTPUT} DIRECTORY )
44e614e037SFraser Cormack  file( MAKE_DIRECTORY ${ARG_OUTPUT_DIR} )
45e614e037SFraser Cormack
4672f9881cSFraser Cormack  add_custom_command(
4772f9881cSFraser Cormack    OUTPUT ${ARG_OUTPUT}${TMP_SUFFIX}
485ee53d41SHarald van Dijk    COMMAND ${clang_exe}
4972f9881cSFraser Cormack      ${TARGET_ARG}
5072f9881cSFraser Cormack      ${PP_OPTS}
5172f9881cSFraser Cormack      ${ARG_EXTRA_OPTS}
5272f9881cSFraser Cormack      -MD -MF ${ARG_OUTPUT}.d -MT ${ARG_OUTPUT}${TMP_SUFFIX}
5372f9881cSFraser Cormack      # LLVM 13 enables standard includes by default - we don't want
5472f9881cSFraser Cormack      # those when pre-processing IR. We disable it unconditionally.
5572f9881cSFraser Cormack      $<$<VERSION_GREATER_EQUAL:${LLVM_PACKAGE_VERSION},13.0.0>:-cl-no-stdinc>
5672f9881cSFraser Cormack      -emit-llvm
5772f9881cSFraser Cormack      -o ${ARG_OUTPUT}${TMP_SUFFIX}
5872f9881cSFraser Cormack      -x cl
5972f9881cSFraser Cormack      ${ARG_INPUT}
6072f9881cSFraser Cormack    DEPENDS
615ee53d41SHarald van Dijk      ${clang_target}
6272f9881cSFraser Cormack      ${ARG_INPUT}
6372f9881cSFraser Cormack      ${ARG_DEPENDENCIES}
6472f9881cSFraser Cormack    DEPFILE ${ARG_OUTPUT}.d
6572f9881cSFraser Cormack  )
6672f9881cSFraser Cormack
6772f9881cSFraser Cormack  if( ${FILE_EXT} STREQUAL ".ll" )
6872f9881cSFraser Cormack    add_custom_command(
6972f9881cSFraser Cormack      OUTPUT ${ARG_OUTPUT}
705ee53d41SHarald van Dijk      COMMAND ${llvm-as_exe} -o ${ARG_OUTPUT} ${ARG_OUTPUT}${TMP_SUFFIX}
715ee53d41SHarald van Dijk      DEPENDS ${llvm-as_target} ${ARG_OUTPUT}${TMP_SUFFIX}
7272f9881cSFraser Cormack    )
7372f9881cSFraser Cormack  endif()
7472f9881cSFraser Cormackendfunction()
7572f9881cSFraser Cormack
7672f9881cSFraser Cormack# Links together one or more bytecode files
7772f9881cSFraser Cormack#
7872f9881cSFraser Cormack# Arguments:
79b2bdd8bdSFraser Cormack# * INTERNALIZE
80b2bdd8bdSFraser Cormack#     Set if -internalize flag should be passed when linking
8172f9881cSFraser Cormack# * TARGET <string>
8272f9881cSFraser Cormack#     Custom target to create
8372f9881cSFraser Cormack# * INPUT <string> ...
8472f9881cSFraser Cormack#     List of bytecode files to link together
8564796044STim Creech# * DEPENDENCIES <string> ...
8664796044STim Creech#     List of extra dependencies to inject
8772f9881cSFraser Cormackfunction(link_bc)
8872f9881cSFraser Cormack  cmake_parse_arguments(ARG
89b2bdd8bdSFraser Cormack    "INTERNALIZE"
9072f9881cSFraser Cormack    "TARGET"
9164796044STim Creech    "INPUTS;DEPENDENCIES"
9272f9881cSFraser Cormack    ${ARGN}
9372f9881cSFraser Cormack  )
9472f9881cSFraser Cormack
95effb2f19SFraser Cormack  set( LINK_INPUT_ARG ${ARG_INPUTS} )
96effb2f19SFraser Cormack  if( WIN32 OR CYGWIN )
97effb2f19SFraser Cormack    # Create a response file in case the number of inputs exceeds command-line
98effb2f19SFraser Cormack    # character limits on certain platforms.
99effb2f19SFraser Cormack    file( TO_CMAKE_PATH ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.rsp RSP_FILE )
100effb2f19SFraser Cormack    # Turn it into a space-separate list of input files
101effb2f19SFraser Cormack    list( JOIN ARG_INPUTS " " RSP_INPUT )
102b2bdd8bdSFraser Cormack    file( GENERATE OUTPUT ${RSP_FILE} CONTENT ${RSP_INPUT} )
103effb2f19SFraser Cormack    # Ensure that if this file is removed, we re-run CMake
104effb2f19SFraser Cormack    set_property( DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
105effb2f19SFraser Cormack      ${RSP_FILE}
106effb2f19SFraser Cormack    )
107effb2f19SFraser Cormack    set( LINK_INPUT_ARG "@${RSP_FILE}" )
108effb2f19SFraser Cormack  endif()
109effb2f19SFraser Cormack
11072f9881cSFraser Cormack  add_custom_command(
11172f9881cSFraser Cormack    OUTPUT ${ARG_TARGET}.bc
112b2bdd8bdSFraser Cormack    COMMAND ${llvm-link_exe} $<$<BOOL:${ARG_INTERNALIZE}>:--internalize> -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG}
1135ee53d41SHarald van Dijk    DEPENDS ${llvm-link_target} ${ARG_DEPENDENCIES} ${ARG_INPUTS} ${RSP_FILE}
11472f9881cSFraser Cormack  )
11572f9881cSFraser Cormack
11672f9881cSFraser Cormack  add_custom_target( ${ARG_TARGET} ALL DEPENDS ${ARG_TARGET}.bc )
1176838c7afSMichael Kruse  set_target_properties( ${ARG_TARGET} PROPERTIES
1189f3728d1SFraser Cormack    TARGET_FILE ${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}.bc
1196838c7afSMichael Kruse    FOLDER "libclc/Device IR/Linking"
1206838c7afSMichael Kruse  )
12172f9881cSFraser Cormackendfunction()
12272f9881cSFraser Cormack
12372f9881cSFraser Cormack# Decomposes and returns variables based on a libclc triple and architecture
12472f9881cSFraser Cormack# combination. Returns data via one or more optional output variables.
12572f9881cSFraser Cormack#
12672f9881cSFraser Cormack# Arguments:
12772f9881cSFraser Cormack# * TRIPLE <string>
12872f9881cSFraser Cormack#     libclc target triple to query
12972f9881cSFraser Cormack# * DEVICE <string>
13072f9881cSFraser Cormack#     libclc device to query
13172f9881cSFraser Cormack#
13272f9881cSFraser Cormack# Optional Arguments:
13372f9881cSFraser Cormack# * CPU <var>
13472f9881cSFraser Cormack#     Variable name to be set to the target CPU
13572f9881cSFraser Cormack# * ARCH_SUFFIX <var>
13672f9881cSFraser Cormack#     Variable name to be set to the triple/architecture suffix
13772f9881cSFraser Cormack# * CLANG_TRIPLE <var>
13872f9881cSFraser Cormack#     Variable name to be set to the normalized clang triple
13972f9881cSFraser Cormackfunction(get_libclc_device_info)
14072f9881cSFraser Cormack  cmake_parse_arguments(ARG
14172f9881cSFraser Cormack    ""
14272f9881cSFraser Cormack    "TRIPLE;DEVICE;CPU;ARCH_SUFFIX;CLANG_TRIPLE"
14372f9881cSFraser Cormack    ""
14472f9881cSFraser Cormack    ${ARGN}
14572f9881cSFraser Cormack  )
14672f9881cSFraser Cormack
14772f9881cSFraser Cormack  if( NOT ARG_TRIPLE OR NOT ARG_DEVICE )
14872f9881cSFraser Cormack    message( FATAL_ERROR "Must provide both TRIPLE and DEVICE" )
14972f9881cSFraser Cormack  endif()
15072f9881cSFraser Cormack
15172f9881cSFraser Cormack  string( REPLACE "-" ";" TRIPLE  ${ARG_TRIPLE} )
15272f9881cSFraser Cormack  list( GET TRIPLE 0 ARCH )
15372f9881cSFraser Cormack
15472f9881cSFraser Cormack  # Some targets don't have a specific device architecture to target
15572f9881cSFraser Cormack  if( ARG_DEVICE STREQUAL none OR ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
15672f9881cSFraser Cormack    set( cpu )
15772f9881cSFraser Cormack    set( arch_suffix "${ARG_TRIPLE}" )
15872f9881cSFraser Cormack  else()
15972f9881cSFraser Cormack    set( cpu "${ARG_DEVICE}" )
16072f9881cSFraser Cormack    set( arch_suffix "${ARG_DEVICE}-${ARG_TRIPLE}" )
16172f9881cSFraser Cormack  endif()
16272f9881cSFraser Cormack
16372f9881cSFraser Cormack  if( ARG_CPU )
16472f9881cSFraser Cormack    set( ${ARG_CPU} ${cpu} PARENT_SCOPE )
16572f9881cSFraser Cormack  endif()
16672f9881cSFraser Cormack
16772f9881cSFraser Cormack  if( ARG_ARCH_SUFFIX )
16872f9881cSFraser Cormack    set( ${ARG_ARCH_SUFFIX} ${arch_suffix} PARENT_SCOPE )
16972f9881cSFraser Cormack  endif()
17072f9881cSFraser Cormack
17172f9881cSFraser Cormack  # Some libclc targets are not real clang triples: return their canonical
17272f9881cSFraser Cormack  # triples.
17372f9881cSFraser Cormack  if( ARCH STREQUAL spirv OR ARCH STREQUAL clspv )
17472f9881cSFraser Cormack    set( ARG_TRIPLE "spir--" )
17572f9881cSFraser Cormack  elseif( ARCH STREQUAL spirv64 OR ARCH STREQUAL clspv64 )
17672f9881cSFraser Cormack    set( ARG_TRIPLE "spir64--" )
17772f9881cSFraser Cormack  endif()
17872f9881cSFraser Cormack
17972f9881cSFraser Cormack  if( ARG_CLANG_TRIPLE )
18072f9881cSFraser Cormack    set( ${ARG_CLANG_TRIPLE} ${ARG_TRIPLE} PARENT_SCOPE )
18172f9881cSFraser Cormack  endif()
18272f9881cSFraser Cormackendfunction()
183183b38ebSFraser Cormack
184183b38ebSFraser Cormack# Compiles a list of library source files (provided by LIB_FILES/GEN_FILES) and
185183b38ebSFraser Cormack# compiles them to LLVM bytecode (or SPIR-V), links them together and optimizes
186183b38ebSFraser Cormack# them.
187183b38ebSFraser Cormack#
188183b38ebSFraser Cormack# For bytecode libraries, a list of ALIASES may optionally be provided to
189183b38ebSFraser Cormack# produce additional symlinks.
190183b38ebSFraser Cormack#
191183b38ebSFraser Cormack# Arguments:
192183b38ebSFraser Cormack#  * ARCH <string>
193183b38ebSFraser Cormack#      libclc architecture being built
194183b38ebSFraser Cormack#  * ARCH_SUFFIX <string>
195183b38ebSFraser Cormack#      libclc architecture/triple suffix
196183b38ebSFraser Cormack#  * TRIPLE <string>
197183b38ebSFraser Cormack#      Triple used to compile
198183b38ebSFraser Cormack#
199183b38ebSFraser Cormack# Optional Arguments:
200b2bdd8bdSFraser Cormack# * CLC_INTERNAL
201b2bdd8bdSFraser Cormack#     Pass if compiling the internal CLC builtin libraries, which are not
202b2bdd8bdSFraser Cormack#     optimized and do not have aliases created.
203183b38ebSFraser Cormack#  * LIB_FILES <string> ...
204183b38ebSFraser Cormack#      List of files that should be built for this library
205183b38ebSFraser Cormack#  * GEN_FILES <string> ...
206183b38ebSFraser Cormack#      List of generated files (in build dir) that should be built for this library
207183b38ebSFraser Cormack#  * COMPILE_FLAGS <string> ...
208183b38ebSFraser Cormack#      Compilation options (for clang)
209183b38ebSFraser Cormack#  * OPT_FLAGS <string> ...
210183b38ebSFraser Cormack#      Optimization options (for opt)
211183b38ebSFraser Cormack#  * ALIASES <string> ...
212183b38ebSFraser Cormack#      List of aliases
213b2bdd8bdSFraser Cormack#  * INTERNAL_LINK_DEPENDENCIES <string> ...
214b2bdd8bdSFraser Cormack#      A list of extra bytecode files to link into the builtin library. Symbols
215b2bdd8bdSFraser Cormack#      from these link dependencies will be internalized during linking.
216183b38ebSFraser Cormackfunction(add_libclc_builtin_set)
217183b38ebSFraser Cormack  cmake_parse_arguments(ARG
218b2bdd8bdSFraser Cormack    "CLC_INTERNAL"
219183b38ebSFraser Cormack    "ARCH;TRIPLE;ARCH_SUFFIX"
220b2bdd8bdSFraser Cormack    "LIB_FILES;GEN_FILES;COMPILE_FLAGS;OPT_FLAGS;ALIASES;INTERNAL_LINK_DEPENDENCIES"
221183b38ebSFraser Cormack    ${ARGN}
222183b38ebSFraser Cormack  )
223183b38ebSFraser Cormack
224183b38ebSFraser Cormack  if( NOT ARG_ARCH OR NOT ARG_ARCH_SUFFIX OR NOT ARG_TRIPLE )
225183b38ebSFraser Cormack    message( FATAL_ERROR "Must provide ARCH, ARCH_SUFFIX, and TRIPLE" )
226183b38ebSFraser Cormack  endif()
227183b38ebSFraser Cormack
228183b38ebSFraser Cormack  set( bytecode_files "" )
229183b38ebSFraser Cormack  foreach( file IN LISTS ARG_GEN_FILES ARG_LIB_FILES )
230183b38ebSFraser Cormack    # We need to take each file and produce an absolute input file, as well
231183b38ebSFraser Cormack    # as a unique architecture-specific output file. We deal with a mix of
232183b38ebSFraser Cormack    # different input files, which makes this trickier.
233183b38ebSFraser Cormack    if( ${file} IN_LIST ARG_GEN_FILES )
234183b38ebSFraser Cormack      # Generated files are given just as file names, which we must make
235183b38ebSFraser Cormack      # absolute to the binary directory.
236183b38ebSFraser Cormack      set( input_file ${CMAKE_CURRENT_BINARY_DIR}/${file} )
237183b38ebSFraser Cormack      set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${file}.bc" )
238183b38ebSFraser Cormack    else()
239183b38ebSFraser Cormack      # Other files are originally relative to each SOURCE file, which are
240183b38ebSFraser Cormack      # then make relative to the libclc root directory. We must normalize
241183b38ebSFraser Cormack      # the path (e.g., ironing out any ".."), then make it relative to the
242183b38ebSFraser Cormack      # root directory again, and use that relative path component for the
243183b38ebSFraser Cormack      # binary path.
244183b38ebSFraser Cormack      get_filename_component( abs_path ${file} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
245183b38ebSFraser Cormack      file( RELATIVE_PATH root_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${abs_path} )
246183b38ebSFraser Cormack      set( input_file ${CMAKE_CURRENT_SOURCE_DIR}/${file} )
247183b38ebSFraser Cormack      set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${root_rel_path}.bc" )
248183b38ebSFraser Cormack    endif()
249183b38ebSFraser Cormack
250183b38ebSFraser Cormack    get_filename_component( file_dir ${file} DIRECTORY )
251183b38ebSFraser Cormack
252183b38ebSFraser Cormack    compile_to_bc(
253183b38ebSFraser Cormack      TRIPLE ${ARG_TRIPLE}
254183b38ebSFraser Cormack      INPUT ${input_file}
255183b38ebSFraser Cormack      OUTPUT ${output_file}
256183b38ebSFraser Cormack      EXTRA_OPTS -fno-builtin -nostdlib
257183b38ebSFraser Cormack        "${ARG_COMPILE_FLAGS}" -I${CMAKE_CURRENT_SOURCE_DIR}/${file_dir}
258183b38ebSFraser Cormack      DEPENDENCIES generate_convert.cl clspv-generate_convert.cl
259183b38ebSFraser Cormack    )
260183b38ebSFraser Cormack    list( APPEND bytecode_files ${output_file} )
261183b38ebSFraser Cormack  endforeach()
262183b38ebSFraser Cormack
263183b38ebSFraser Cormack  set( builtins_comp_lib_tgt builtins.comp.${ARG_ARCH_SUFFIX} )
264183b38ebSFraser Cormack  add_custom_target( ${builtins_comp_lib_tgt}
265183b38ebSFraser Cormack    DEPENDS ${bytecode_files}
266183b38ebSFraser Cormack  )
267183b38ebSFraser Cormack  set_target_properties( ${builtins_comp_lib_tgt} PROPERTIES FOLDER "libclc/Device IR/Comp" )
268183b38ebSFraser Cormack
269b2bdd8bdSFraser Cormack  if( NOT bytecode_files )
270b2bdd8bdSFraser Cormack    message(FATAL_ERROR "Cannot create an empty builtins library")
271b2bdd8bdSFraser Cormack  endif()
272b2bdd8bdSFraser Cormack
273183b38ebSFraser Cormack  set( builtins_link_lib_tgt builtins.link.${ARG_ARCH_SUFFIX} )
274b2bdd8bdSFraser Cormack
275b2bdd8bdSFraser Cormack  if( NOT ARG_INTERNAL_LINK_DEPENDENCIES )
276183b38ebSFraser Cormack    link_bc(
277183b38ebSFraser Cormack      TARGET ${builtins_link_lib_tgt}
278183b38ebSFraser Cormack      INPUTS ${bytecode_files}
279183b38ebSFraser Cormack      DEPENDENCIES ${builtins_comp_lib_tgt}
280183b38ebSFraser Cormack    )
281b2bdd8bdSFraser Cormack  else()
282b2bdd8bdSFraser Cormack    # If we have libraries to link while internalizing their symbols, we need
283b2bdd8bdSFraser Cormack    # two separate link steps; the --internalize flag applies to all link
284b2bdd8bdSFraser Cormack    # inputs but the first.
285b2bdd8bdSFraser Cormack    set( builtins_link_lib_tmp_tgt builtins.link.pre-deps.${ARG_ARCH_SUFFIX} )
286b2bdd8bdSFraser Cormack    link_bc(
287b2bdd8bdSFraser Cormack      TARGET ${builtins_link_lib_tmp_tgt}
288b2bdd8bdSFraser Cormack      INPUTS ${bytecode_files}
289b2bdd8bdSFraser Cormack      DEPENDENCIES ${builtins_comp_lib_tgt}
290b2bdd8bdSFraser Cormack    )
291b2bdd8bdSFraser Cormack    link_bc(
292b2bdd8bdSFraser Cormack      INTERNALIZE
293b2bdd8bdSFraser Cormack      TARGET ${builtins_link_lib_tgt}
294b2bdd8bdSFraser Cormack      INPUTS $<TARGET_PROPERTY:${builtins_link_lib_tmp_tgt},TARGET_FILE>
295b2bdd8bdSFraser Cormack        ${ARG_INTERNAL_LINK_DEPENDENCIES}
296b2bdd8bdSFraser Cormack      DEPENDENCIES ${builtins_link_lib_tmp_tgt}
297b2bdd8bdSFraser Cormack    )
298b2bdd8bdSFraser Cormack  endif()
299b2bdd8bdSFraser Cormack
300b2bdd8bdSFraser Cormack  # For the CLC internal builtins, exit here - we only optimize the targets'
301b2bdd8bdSFraser Cormack  # entry points once we've linked the CLC buitins into them
302b2bdd8bdSFraser Cormack  if( ARG_CLC_INTERNAL )
303b2bdd8bdSFraser Cormack    return()
304b2bdd8bdSFraser Cormack  endif()
305183b38ebSFraser Cormack
306183b38ebSFraser Cormack  set( builtins_link_lib $<TARGET_PROPERTY:${builtins_link_lib_tgt},TARGET_FILE> )
307183b38ebSFraser Cormack
308183b38ebSFraser Cormack  if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 )
309183b38ebSFraser Cormack    set( spv_suffix ${ARG_ARCH_SUFFIX}.spv )
310183b38ebSFraser Cormack    add_custom_command( OUTPUT ${spv_suffix}
311183b38ebSFraser Cormack      COMMAND ${llvm-spirv_exe} ${spvflags} -o ${spv_suffix} ${builtins_link_lib}
312183b38ebSFraser Cormack      DEPENDS ${llvm-spirv_target} ${builtins_link_lib} ${builtins_link_lib_tgt}
313183b38ebSFraser Cormack    )
314183b38ebSFraser Cormack    add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${spv_suffix}" )
315183b38ebSFraser Cormack    set_target_properties( "prepare-${spv_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" )
316183b38ebSFraser Cormack    install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix}
317183b38ebSFraser Cormack       DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
318183b38ebSFraser Cormack
319183b38ebSFraser Cormack    return()
320183b38ebSFraser Cormack  endif()
321183b38ebSFraser Cormack
322183b38ebSFraser Cormack  set( builtins_opt_lib_tgt builtins.opt.${ARG_ARCH_SUFFIX} )
323183b38ebSFraser Cormack
324183b38ebSFraser Cormack  # Add opt target
325183b38ebSFraser Cormack  add_custom_command( OUTPUT ${builtins_opt_lib_tgt}.bc
326183b38ebSFraser Cormack    COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${builtins_opt_lib_tgt}.bc
327183b38ebSFraser Cormack      ${builtins_link_lib}
328183b38ebSFraser Cormack    DEPENDS ${opt_target} ${builtins_link_lib} ${builtins_link_lib_tgt}
329183b38ebSFraser Cormack  )
330183b38ebSFraser Cormack  add_custom_target( ${builtins_opt_lib_tgt}
331183b38ebSFraser Cormack    ALL DEPENDS ${builtins_opt_lib_tgt}.bc
332183b38ebSFraser Cormack  )
333183b38ebSFraser Cormack  set_target_properties( ${builtins_opt_lib_tgt} PROPERTIES
334183b38ebSFraser Cormack    TARGET_FILE ${CMAKE_CURRENT_BINARY_DIR}/${builtins_opt_lib_tgt}.bc
335183b38ebSFraser Cormack    FOLDER "libclc/Device IR/Opt"
336183b38ebSFraser Cormack  )
337183b38ebSFraser Cormack
338183b38ebSFraser Cormack  set( builtins_opt_lib $<TARGET_PROPERTY:${builtins_opt_lib_tgt},TARGET_FILE> )
339183b38ebSFraser Cormack
340183b38ebSFraser Cormack  # Add prepare target
341183b38ebSFraser Cormack  set( obj_suffix ${ARG_ARCH_SUFFIX}.bc )
342183b38ebSFraser Cormack  add_custom_command( OUTPUT ${obj_suffix}
343183b38ebSFraser Cormack    COMMAND ${prepare_builtins_exe} -o ${obj_suffix} ${builtins_opt_lib}
344183b38ebSFraser Cormack    DEPENDS ${builtins_opt_lib} ${builtins_opt_lib_tgt} ${prepare_builtins_target} )
345183b38ebSFraser Cormack  add_custom_target( prepare-${obj_suffix} ALL DEPENDS ${obj_suffix} )
346183b38ebSFraser Cormack  set_target_properties( "prepare-${obj_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" )
347183b38ebSFraser Cormack
348183b38ebSFraser Cormack  # nvptx-- targets don't include workitem builtins
349183b38ebSFraser Cormack  if( NOT ARG_TRIPLE MATCHES ".*ptx.*--$" )
350183b38ebSFraser Cormack    add_test( NAME external-calls-${obj_suffix}
351183b38ebSFraser Cormack      COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} ${LLVM_TOOLS_BINARY_DIR}
352183b38ebSFraser Cormack      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
353183b38ebSFraser Cormack  endif()
354183b38ebSFraser Cormack
355183b38ebSFraser Cormack  install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
356183b38ebSFraser Cormack  foreach( a ${ARG_ALIASES} )
357183b38ebSFraser Cormack    set( alias_suffix "${a}-${ARG_TRIPLE}.bc" )
358*76befc86SFraser Cormack    add_custom_command(
359*76befc86SFraser Cormack      OUTPUT ${alias_suffix}
360183b38ebSFraser Cormack      COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix}
361183b38ebSFraser Cormack      DEPENDS prepare-${obj_suffix} )
362*76befc86SFraser Cormack    add_custom_target( alias-${alias_suffix} ALL DEPENDS ${alias_suffix} )
363*76befc86SFraser Cormack    set_target_properties( alias-${alias_suffix} PROPERTIES FOLDER "libclc/Device IR/Aliases" )
364*76befc86SFraser Cormack    install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix}
365*76befc86SFraser Cormack             DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
366183b38ebSFraser Cormack  endforeach( a )
367183b38ebSFraser Cormackendfunction(add_libclc_builtin_set)
368183b38ebSFraser Cormack
369183b38ebSFraser Cormack# Produces a list of libclc source files by walking over SOURCES files in a
370183b38ebSFraser Cormack# given directory. Outputs the list of files in LIB_FILE_LIST.
371183b38ebSFraser Cormack#
372183b38ebSFraser Cormack# LIB_FILE_LIST may be pre-populated and is appended to.
373183b38ebSFraser Cormack#
374183b38ebSFraser Cormack# Arguments:
375b2bdd8bdSFraser Cormack# * CLC_INTERNAL
376b2bdd8bdSFraser Cormack#     Pass if compiling the internal CLC builtin libraries, which have a
377b2bdd8bdSFraser Cormack#     different directory structure.
378183b38ebSFraser Cormack# * LIB_ROOT_DIR <string>
379183b38ebSFraser Cormack#     Root directory containing target's lib files, relative to libclc root
380183b38ebSFraser Cormack#     directory. If not provided, is set to '.'.
381183b38ebSFraser Cormack# * DIRS <string> ...
382183b38ebSFraser Cormack#     List of directories under LIB_ROOT_DIR to walk over searching for SOURCES
383183b38ebSFraser Cormack#     files
384183b38ebSFraser Cormackfunction(libclc_configure_lib_source LIB_FILE_LIST)
385183b38ebSFraser Cormack  cmake_parse_arguments(ARG
386b2bdd8bdSFraser Cormack    "CLC_INTERNAL"
387183b38ebSFraser Cormack    "LIB_ROOT_DIR"
388183b38ebSFraser Cormack    "DIRS"
389183b38ebSFraser Cormack    ${ARGN}
390183b38ebSFraser Cormack  )
391183b38ebSFraser Cormack
392183b38ebSFraser Cormack  if( NOT ARG_LIB_ROOT_DIR )
393183b38ebSFraser Cormack    set(ARG_LIB_ROOT_DIR  ".")
394183b38ebSFraser Cormack  endif()
395183b38ebSFraser Cormack
396183b38ebSFraser Cormack  # Enumerate SOURCES* files
397183b38ebSFraser Cormack  set( source_list )
398183b38ebSFraser Cormack  foreach( l ${ARG_DIRS} )
399183b38ebSFraser Cormack    foreach( s "SOURCES" "SOURCES_${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}" )
400b2bdd8bdSFraser Cormack      if( ARG_CLC_INTERNAL )
401b2bdd8bdSFraser Cormack        file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/lib/${l}/${s} file_loc )
402b2bdd8bdSFraser Cormack      else()
403183b38ebSFraser Cormack        file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/${l}/lib/${s} file_loc )
404b2bdd8bdSFraser Cormack      endif()
405183b38ebSFraser Cormack      file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file_loc} loc )
406183b38ebSFraser Cormack      # Prepend the location to give higher priority to
407183b38ebSFraser Cormack      # specialized implementation
408183b38ebSFraser Cormack      if( EXISTS ${loc} )
409183b38ebSFraser Cormack        set( source_list ${file_loc} ${source_list} )
410183b38ebSFraser Cormack      endif()
411183b38ebSFraser Cormack    endforeach()
412183b38ebSFraser Cormack  endforeach()
413183b38ebSFraser Cormack
414183b38ebSFraser Cormack  ## Add the generated convert files here to prevent adding the ones listed in
415183b38ebSFraser Cormack  ## SOURCES
416183b38ebSFraser Cormack  set( rel_files ${${LIB_FILE_LIST}} ) # Source directory input files, relative to the root dir
417183b38ebSFraser Cormack  set( objects ${${LIB_FILE_LIST}} )   # A "set" of already-added input files
418183b38ebSFraser Cormack
419183b38ebSFraser Cormack  foreach( l ${source_list} )
420183b38ebSFraser Cormack    file( READ ${l} file_list )
421183b38ebSFraser Cormack    string( REPLACE "\n" ";" file_list ${file_list} )
422183b38ebSFraser Cormack    get_filename_component( dir ${l} DIRECTORY )
423183b38ebSFraser Cormack    foreach( f ${file_list} )
424183b38ebSFraser Cormack      # Only add each file once, so that targets can 'specialize' builtins
425183b38ebSFraser Cormack      if( NOT ${f} IN_LIST objects )
426183b38ebSFraser Cormack        list( APPEND objects ${f} )
427183b38ebSFraser Cormack        list( APPEND rel_files ${dir}/${f} )
428183b38ebSFraser Cormack      endif()
429183b38ebSFraser Cormack    endforeach()
430183b38ebSFraser Cormack  endforeach()
431183b38ebSFraser Cormack
432183b38ebSFraser Cormack  set( ${LIB_FILE_LIST} ${rel_files} PARENT_SCOPE )
433183b38ebSFraser Cormackendfunction(libclc_configure_lib_source LIB_FILE_LIST)
434