brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.2 KiB · 3228926 Raw
609 lines · plain
1# Compiles an OpenCL C - or assembles an LL file - to bytecode2#3# Arguments:4# * TRIPLE <string>5#     Target triple for which to compile the bytecode file.6# * INPUT <string>7#     File to compile/assemble to bytecode8# * OUTPUT <string>9#     Bytecode file to generate10# * EXTRA_OPTS <string> ...11#     List of compiler options to use. Note that some are added by default.12# * DEPENDENCIES <string> ...13#     List of extra dependencies to inject14#15# Depends on the clang, llvm-as, and llvm-link targets for compiling,16# assembling, and linking, respectively.17function(compile_to_bc)18  cmake_parse_arguments(ARG19    ""20    "TRIPLE;INPUT;OUTPUT"21    "EXTRA_OPTS;DEPENDENCIES"22    ${ARGN}23  )24 25  # If this is an LLVM IR file (identified solely by its file suffix),26  # pre-process it with clang to a temp file, then assemble that to bytecode.27  set( TMP_SUFFIX )28  get_filename_component( FILE_EXT ${ARG_INPUT} EXT )29  if( NOT ${FILE_EXT} STREQUAL ".ll" )30    # Pass '-c' when not running the preprocessor31    set( PP_OPTS -c )32  else()33    set( PP_OPTS -E;-P )34    set( TMP_SUFFIX .tmp )35  endif()36 37  set( TARGET_ARG )38  if( ARG_TRIPLE )39    set( TARGET_ARG "-target" ${ARG_TRIPLE} )40  endif()41 42  # Ensure the directory we are told to output to exists43  get_filename_component( ARG_OUTPUT_DIR ${ARG_OUTPUT} DIRECTORY )44  file( MAKE_DIRECTORY ${ARG_OUTPUT_DIR} )45 46  add_custom_command(47    OUTPUT ${ARG_OUTPUT}${TMP_SUFFIX}48    COMMAND ${clang_exe}49      ${TARGET_ARG}50      ${PP_OPTS}51      ${ARG_EXTRA_OPTS}52      -MD -MF ${ARG_OUTPUT}.d -MT ${ARG_OUTPUT}${TMP_SUFFIX}53      # LLVM 13 enables standard includes by default - we don't want54      # those when pre-processing IR. We disable it unconditionally.55      $<$<VERSION_GREATER_EQUAL:${LLVM_PACKAGE_VERSION},13.0.0>:-cl-no-stdinc>56      -emit-llvm57      -o ${ARG_OUTPUT}${TMP_SUFFIX}58      -x cl59      ${ARG_INPUT}60    DEPENDS61      ${clang_target}62      ${ARG_INPUT}63      ${ARG_DEPENDENCIES}64    DEPFILE ${ARG_OUTPUT}.d65  )66 67  if( ${FILE_EXT} STREQUAL ".ll" )68    add_custom_command(69      OUTPUT ${ARG_OUTPUT}70      COMMAND ${llvm-as_exe} -o ${ARG_OUTPUT} ${ARG_OUTPUT}${TMP_SUFFIX}71      DEPENDS ${llvm-as_target} ${ARG_OUTPUT}${TMP_SUFFIX}72    )73  endif()74endfunction()75 76# Links together one or more bytecode files77#78# Arguments:79# * INTERNALIZE80#     Set if -internalize flag should be passed when linking81# * TARGET <string>82#     Custom target to create83# * INPUT <string> ...84#     List of bytecode files to link together85# * DEPENDENCIES <string> ...86#     List of extra dependencies to inject87function(link_bc)88  cmake_parse_arguments(ARG89    "INTERNALIZE"90    "TARGET"91    "INPUTS;DEPENDENCIES"92    ${ARGN}93  )94 95  if( ARG_INTERNALIZE )96    set( inputs_with_flag ${ARG_INPUTS} )97  else()98    # Add the --override flag for non-generic bitcode files so that their99    # symbols can override definitions in generic bitcode files.100    set( inputs_with_flag )101    foreach( file IN LISTS ARG_INPUTS )102      string( FIND ${file} "/generic/" is_generic )103      if( is_generic LESS 0 )104        list( APPEND inputs_with_flag "--override" )105      endif()106      list( APPEND inputs_with_flag ${file} )107    endforeach()108  endif()109 110  if( WIN32 OR CYGWIN )111    # Create a response file in case the number of inputs exceeds command-line112    # character limits on certain platforms.113    file( TO_CMAKE_PATH ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.rsp RSP_FILE )114    # Turn it into a space-separate list of input files115    list( JOIN inputs_with_flag " " RSP_INPUT )116    file( GENERATE OUTPUT ${RSP_FILE} CONTENT ${RSP_INPUT} )117    # Ensure that if this file is removed, we re-run CMake118    set_property( DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS119      ${RSP_FILE}120    )121    set( LINK_INPUT_ARG "@${RSP_FILE}" )122  else()123    set( LINK_INPUT_ARG ${inputs_with_flag} )124  endif()125 126  if( ARG_INTERNALIZE )127    set( link_flags --internalize --only-needed )128  endif()129 130  add_custom_command(131    OUTPUT ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc132    COMMAND ${llvm-link_exe} ${link_flags} -o ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc ${LINK_INPUT_ARG}133    DEPENDS ${llvm-link_target} ${ARG_DEPENDENCIES} ${ARG_INPUTS} ${RSP_FILE}134  )135 136  add_custom_target( ${ARG_TARGET} ALL DEPENDS ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc )137  set_target_properties( ${ARG_TARGET} PROPERTIES138    TARGET_FILE ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc139    FOLDER "libclc/Device IR/Linking"140  )141endfunction()142 143# Create a custom target for each bitcode file, which is the output of a custom144# command. This is required for parallel compilation of the custom commands that145# generate the bitcode files when using the CMake MSVC generator on Windows.146#147# Arguments:148#  * compile_tgts149#      Output list of compile targets150#  * ARCH_SUFFIX <string>151#      libclc architecture/triple suffix152#  * FILES <string> ...153#     List of bitcode files154function(create_compile_targets compile_tgts)155  cmake_parse_arguments( ARG "" "ARCH_SUFFIX" "FILES" ${ARGN} )156 157  if( NOT ARG_ARCH_SUFFIX OR NOT ARG_FILES )158    message( FATAL_ERROR "Must provide ARCH_SUFFIX, and FILES" )159  endif()160 161  set( tgts )162  foreach( file IN LISTS ARG_FILES )163    cmake_path( GET file STEM stem )164    cmake_path( GET file PARENT_PATH parent_path )165    cmake_path( GET parent_path STEM parent_path_stem )166    set( tgt compile-${ARG_ARCH_SUFFIX}-${parent_path_stem}-${stem} )167    add_custom_target( ${tgt} DEPENDS ${file} )168    list( APPEND tgts ${tgt} )169  endforeach()170 171  set( compile_tgts ${tgts} PARENT_SCOPE )172endfunction()173 174# Decomposes and returns variables based on a libclc triple and architecture175# combination. Returns data via one or more optional output variables.176#177# Arguments:178# * TRIPLE <string>179#     libclc target triple to query180# * DEVICE <string>181#     libclc device to query182#183# Optional Arguments:184# * CPU <var>185#     Variable name to be set to the target CPU186# * ARCH_SUFFIX <var>187#     Variable name to be set to the triple/architecture suffix188# * CLANG_TRIPLE <var>189#     Variable name to be set to the normalized clang triple190function(get_libclc_device_info)191  cmake_parse_arguments(ARG192    ""193    "TRIPLE;DEVICE;CPU;ARCH_SUFFIX;CLANG_TRIPLE"194    ""195    ${ARGN}196  )197 198  if( NOT ARG_TRIPLE OR NOT ARG_DEVICE )199    message( FATAL_ERROR "Must provide both TRIPLE and DEVICE" )200  endif()201 202  string( REPLACE "-" ";" TRIPLE  ${ARG_TRIPLE} )203  list( GET TRIPLE 0 ARCH )204 205  # Some targets don't have a specific device architecture to target206  if( ARG_DEVICE STREQUAL none207      OR ((ARCH STREQUAL spirv OR ARCH STREQUAL spirv64)208          AND NOT LIBCLC_USE_SPIRV_BACKEND) )209    set( cpu )210    set( arch_suffix "${ARG_TRIPLE}" )211  else()212    set( cpu "${ARG_DEVICE}" )213    set( arch_suffix "${ARG_DEVICE}-${ARG_TRIPLE}" )214  endif()215 216  if( ARG_CPU )217    set( ${ARG_CPU} ${cpu} PARENT_SCOPE )218  endif()219 220  if( ARG_ARCH_SUFFIX )221    set( ${ARG_ARCH_SUFFIX} ${arch_suffix} PARENT_SCOPE )222  endif()223 224  # Some libclc targets are not real clang triples: return their canonical225  # triples.226  if( ARCH STREQUAL spirv AND LIBCLC_USE_SPIRV_BACKEND )227    set( ARG_TRIPLE "spirv32--" )228  elseif( ARCH STREQUAL spirv64 AND LIBCLC_USE_SPIRV_BACKEND )229    set( ARG_TRIPLE "spirv64--" )230  elseif( ARCH STREQUAL spirv OR ARCH STREQUAL clspv )231    set( ARG_TRIPLE "spir--" )232  elseif( ARCH STREQUAL spirv64 OR ARCH STREQUAL clspv64 )233    set( ARG_TRIPLE "spir64--" )234  endif()235 236  if( ARG_CLANG_TRIPLE )237    set( ${ARG_CLANG_TRIPLE} ${ARG_TRIPLE} PARENT_SCOPE )238  endif()239endfunction()240 241# Install libclc artifacts.242#243# Arguments:244#  * FILES <string> ...245#      List of libclc artifact files to be installed.246function(libclc_install)247  cmake_parse_arguments(ARG "" "" "FILES" ${ARGN})248 249  if( NOT ARG_FILES )250    message( FATAL_ERROR "Must provide FILES" )251  endif()252 253  if( NOT CMAKE_CFG_INTDIR STREQUAL "." )254    # Replace CMAKE_CFG_INTDIR with CMAKE_INSTALL_CONFIG_NAME for multiple-255    # configuration generators.256    string( REPLACE ${CMAKE_CFG_INTDIR} "\$\{CMAKE_INSTALL_CONFIG_NAME\}"257            files ${ARG_FILES} )258  else()259    set( files ${ARG_FILES} )260  endif()261 262  install(263    FILES ${files}264    DESTINATION ${LIBCLC_INSTALL_DIR}265  )266endfunction()267 268# Compiles a list of library source files (provided by LIB_FILES/GEN_FILES) and269# compiles them to LLVM bytecode (or SPIR-V), links them together and optimizes270# them.271#272# For bytecode libraries, a list of ALIASES may optionally be provided to273# produce additional symlinks.274#275# Arguments:276#  * ARCH <string>277#      libclc architecture being built278#  * ARCH_SUFFIX <string>279#      libclc architecture/triple suffix280#  * TRIPLE <string>281#      Triple used to compile282#  * PARENT_TARGET <string>283#      Target into which to group the target builtins284#285# Optional Arguments:286# * CLC_INTERNAL287#     Pass if compiling the internal CLC builtin libraries, which are not288#     optimized and do not have aliases created.289#  * LIB_FILES <string> ...290#      List of files that should be built for this library291#  * GEN_FILES <string> ...292#      List of generated files (in build dir) that should be built for this library293#  * COMPILE_FLAGS <string> ...294#      Compilation options (for clang)295#  * OPT_FLAGS <string> ...296#      Optimization options (for opt)297#  * ALIASES <string> ...298#      List of aliases299#  * INTERNAL_LINK_DEPENDENCIES <target> ...300#      A list of extra bytecode file's targets. The bitcode files will be linked301#      into the builtin library. Symbols from these link dependencies will be302#      internalized during linking.303function(add_libclc_builtin_set)304  cmake_parse_arguments(ARG305    "CLC_INTERNAL"306    "ARCH;TRIPLE;ARCH_SUFFIX;PARENT_TARGET"307    "LIB_FILES;GEN_FILES;COMPILE_FLAGS;OPT_FLAGS;ALIASES;INTERNAL_LINK_DEPENDENCIES"308    ${ARGN}309  )310 311  if( NOT ARG_ARCH OR NOT ARG_ARCH_SUFFIX OR NOT ARG_TRIPLE )312    message( FATAL_ERROR "Must provide ARCH, ARCH_SUFFIX, and TRIPLE" )313  endif()314 315  set( bytecode_files )316  set( bytecode_ir_files )317  foreach( file IN LISTS ARG_GEN_FILES ARG_LIB_FILES )318    # We need to take each file and produce an absolute input file, as well319    # as a unique architecture-specific output file. We deal with a mix of320    # different input files, which makes this trickier.321    set( input_file_dep )322    if( ${file} IN_LIST ARG_GEN_FILES )323      # Generated files are given just as file names, which we must make324      # absolute to the binary directory.325      set( input_file ${CMAKE_CURRENT_BINARY_DIR}/${file} )326      set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${file}.bc" )327      # If a target exists that generates this file, add that as a dependency328      # of the custom command.329      if( TARGET generate-${file} )330        set( input_file_dep generate-${file} )331      endif()332    else()333      # Other files are originally relative to each SOURCE file, which are334      # then make relative to the libclc root directory. We must normalize335      # the path (e.g., ironing out any ".."), then make it relative to the336      # root directory again, and use that relative path component for the337      # binary path.338      get_filename_component( abs_path ${file} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )339      file( RELATIVE_PATH root_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${abs_path} )340      set( input_file ${CMAKE_CURRENT_SOURCE_DIR}/${file} )341      set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${root_rel_path}.bc" )342    endif()343 344    get_filename_component( file_dir ${file} DIRECTORY )345 346    set( file_specific_compile_options )347    get_source_file_property( compile_opts ${file} COMPILE_OPTIONS)348    if( compile_opts )349      set( file_specific_compile_options "${compile_opts}" )350    endif()351 352    compile_to_bc(353      TRIPLE ${ARG_TRIPLE}354      INPUT ${input_file}355      OUTPUT ${output_file}356      EXTRA_OPTS -nostdlib "${ARG_COMPILE_FLAGS}"357        "${file_specific_compile_options}"358        -I${CMAKE_CURRENT_SOURCE_DIR}/${file_dir}359      DEPENDENCIES ${input_file_dep}360    )361 362    # Collect all files originating in LLVM IR separately363    get_filename_component( file_ext ${file} EXT )364    if( ${file_ext} STREQUAL ".ll" )365      list( APPEND bytecode_ir_files ${output_file} )366    else()367      list( APPEND bytecode_files ${output_file} )368    endif()369  endforeach()370 371  set( builtins_comp_lib_tgt builtins.comp.${ARG_ARCH_SUFFIX} )372  if ( CMAKE_GENERATOR MATCHES "Visual Studio" )373    # Don't put commands in one custom target to avoid serialized compilation.374    create_compile_targets( compile_tgts375      ARCH_SUFFIX ${ARG_ARCH_SUFFIX}376      FILES ${bytecode_files}377    )378    add_custom_target( ${builtins_comp_lib_tgt} DEPENDS ${bytecode_ir_files} )379    add_dependencies( ${builtins_comp_lib_tgt} ${compile_tgts} )380  else()381    add_custom_target( ${builtins_comp_lib_tgt}382      DEPENDS ${bytecode_files} ${bytecode_ir_files}383    )384  endif()385  set_target_properties( ${builtins_comp_lib_tgt} PROPERTIES FOLDER "libclc/Device IR/Comp" )386 387  # Prepend all LLVM IR files to the list so they are linked into the final388  # bytecode modules first. This helps to suppress unnecessary warnings389  # regarding different data layouts while linking. Any LLVM IR files without a390  # data layout will (silently) be given the first data layout the linking391  # process comes across.392  list( PREPEND bytecode_files ${bytecode_ir_files} )393 394  if( NOT bytecode_files )395    message(FATAL_ERROR "Cannot create an empty builtins library for ${ARG_ARCH_SUFFIX}")396  endif()397 398  set( builtins_link_lib_tgt builtins.link.${ARG_ARCH_SUFFIX} )399 400  if( NOT ARG_INTERNAL_LINK_DEPENDENCIES )401    link_bc(402      TARGET ${builtins_link_lib_tgt}403      INPUTS ${bytecode_files}404      DEPENDENCIES ${builtins_comp_lib_tgt}405    )406  else()407    # If we have libraries to link while internalizing their symbols, we need408    # two separate link steps; the --internalize flag applies to all link409    # inputs but the first.410    set( builtins_link_lib_tmp_tgt builtins.link.pre-deps.${ARG_ARCH_SUFFIX} )411    link_bc(412      TARGET ${builtins_link_lib_tmp_tgt}413      INPUTS ${bytecode_files}414      DEPENDENCIES ${builtins_comp_lib_tgt}415    )416    set( internal_link_depend_files )417    foreach( tgt ${ARG_INTERNAL_LINK_DEPENDENCIES} )418      list( APPEND internal_link_depend_files $<TARGET_PROPERTY:${tgt},TARGET_FILE> )419    endforeach()420    link_bc(421      INTERNALIZE422      TARGET ${builtins_link_lib_tgt}423      INPUTS $<TARGET_PROPERTY:${builtins_link_lib_tmp_tgt},TARGET_FILE>424        ${internal_link_depend_files}425      DEPENDENCIES ${builtins_link_lib_tmp_tgt} ${ARG_INTERNAL_LINK_DEPENDENCIES}426    )427  endif()428 429  # For the CLC internal builtins, exit here - we only optimize the targets'430  # entry points once we've linked the CLC buitins into them431  if( ARG_CLC_INTERNAL )432    return()433  endif()434 435  set( builtins_link_lib $<TARGET_PROPERTY:${builtins_link_lib_tgt},TARGET_FILE> )436 437  # For SPIR-V targets we diverage at this point and generate SPIR-V using the438  # llvm-spirv tool.439  if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 )440    set( obj_suffix ${ARG_ARCH_SUFFIX}.spv )441    set( libclc_builtins_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${obj_suffix} )442    if ( LIBCLC_USE_SPIRV_BACKEND )443      add_custom_command( OUTPUT ${libclc_builtins_lib}444        COMMAND ${clang_exe} --target=${ARG_TRIPLE} -x ir -o ${libclc_builtins_lib} ${builtins_link_lib}445        DEPENDS ${clang_target} ${builtins_link_lib} ${builtins_link_lib_tgt}446      )447    else()448      add_custom_command( OUTPUT ${libclc_builtins_lib}449        COMMAND ${llvm-spirv_exe} ${spvflags} -o ${libclc_builtins_lib} ${builtins_link_lib}450        DEPENDS ${llvm-spirv_target} ${builtins_link_lib} ${builtins_link_lib_tgt}451      )452    endif()453  else()454    # Non-SPIR-V targets add an extra step to optimize the bytecode455    set( builtins_opt_lib_tgt builtins.opt.${ARG_ARCH_SUFFIX} )456 457    add_custom_command( OUTPUT ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc458      COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc459        ${builtins_link_lib}460      DEPENDS ${opt_target} ${builtins_link_lib} ${builtins_link_lib_tgt}461    )462    add_custom_target( ${builtins_opt_lib_tgt}463      ALL DEPENDS ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc464    )465    set_target_properties( ${builtins_opt_lib_tgt} PROPERTIES466      TARGET_FILE ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc467      FOLDER "libclc/Device IR/Opt"468    )469 470    set( builtins_opt_lib $<TARGET_PROPERTY:${builtins_opt_lib_tgt},TARGET_FILE> )471 472    set( obj_suffix ${ARG_ARCH_SUFFIX}.bc )473    set( libclc_builtins_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${obj_suffix} )474    add_custom_command( OUTPUT ${libclc_builtins_lib}475      COMMAND ${prepare_builtins_exe} -o ${libclc_builtins_lib} ${builtins_opt_lib}476      DEPENDS ${builtins_opt_lib} ${builtins_opt_lib_tgt} ${prepare_builtins_target}477    )478  endif()479 480  # Add a 'prepare' target481  add_custom_target( prepare-${obj_suffix} ALL DEPENDS ${libclc_builtins_lib} )482  set_target_properties( "prepare-${obj_suffix}" PROPERTIES483    TARGET_FILE ${libclc_builtins_lib}484    FOLDER "libclc/Device IR/Prepare"485  )486 487  # Also add a 'prepare' target for the triple. Since a triple may have488  # multiple devices, ensure we only try to create the triple target once. The489  # triple's target will build all of the bytecode for its constituent devices.490  if( NOT TARGET prepare-${ARG_TRIPLE} )491    add_custom_target( prepare-${ARG_TRIPLE} ALL )492  endif()493  add_dependencies( prepare-${ARG_TRIPLE} prepare-${obj_suffix} )494  # Add dependency to top-level pseudo target to ease making other495  # targets dependent on libclc.496  add_dependencies( ${ARG_PARENT_TARGET} prepare-${ARG_TRIPLE} )497 498  libclc_install(FILES ${libclc_builtins_lib})499 500  # SPIR-V targets can exit early here501  if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 )502    return()503  endif()504 505  # Add a test for whether or not the libraries contain unresolved functions506  # which would usually indicate a build problem. Note that we don't perform507  # this test for all libclc targets:508  # * nvptx-- targets don't include workitem builtins509  # * clspv targets don't include all OpenCL builtins510  if( NOT ARG_ARCH MATCHES "^(nvptx|clspv)(64)?$" )511    add_test( NAME external-funcs-${obj_suffix}512      COMMAND ./check_external_funcs.sh ${libclc_builtins_lib} ${LLVM_TOOLS_BINARY_DIR}513      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )514  endif()515 516  foreach( a IN LISTS ARG_ALIASES )517    if(CMAKE_HOST_UNIX OR LLVM_USE_SYMLINKS)518      cmake_path(RELATIVE_PATH libclc_builtins_lib519        BASE_DIRECTORY ${LIBCLC_OUTPUT_LIBRARY_DIR}520        OUTPUT_VARIABLE LIBCLC_LINK_OR_COPY_SOURCE)521      set(LIBCLC_LINK_OR_COPY create_symlink)522    else()523      set(LIBCLC_LINK_OR_COPY_SOURCE ${libclc_builtins_lib})524      set(LIBCLC_LINK_OR_COPY copy)525    endif()526 527    set( alias_suffix "${a}-${ARG_TRIPLE}.bc" )528    add_custom_command(529      OUTPUT ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix}530      COMMAND ${CMAKE_COMMAND} -E ${LIBCLC_LINK_OR_COPY} ${LIBCLC_LINK_OR_COPY_SOURCE} ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix}531      DEPENDS prepare-${obj_suffix}532    )533    add_custom_target( alias-${alias_suffix} ALL534      DEPENDS ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix}535    )536    add_dependencies( ${ARG_PARENT_TARGET} alias-${alias_suffix} )537    set_target_properties( alias-${alias_suffix}538      PROPERTIES FOLDER "libclc/Device IR/Aliases"539    )540    libclc_install(FILES ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix})541  endforeach( a )542endfunction(add_libclc_builtin_set)543 544# Produces a list of libclc source files by walking over SOURCES files in a545# given directory. Outputs the list of files in LIB_FILE_LIST.546#547# LIB_FILE_LIST may be pre-populated and is appended to.548#549# Arguments:550# * LIB_ROOT_DIR <string>551#     Root directory containing target's lib files, relative to libclc root552#     directory. If not provided, is set to '.'.553# * DIRS <string> ...554#     List of directories under LIB_ROOT_DIR to walk over searching for SOURCES555#     files. Directories earlier in the list have lower priority than556#     subsequent ones.557function(libclc_configure_lib_source LIB_FILE_LIST)558  cmake_parse_arguments(ARG559    ""560    "LIB_ROOT_DIR"561    "DIRS"562    ${ARGN}563  )564 565  if( NOT ARG_LIB_ROOT_DIR )566    set(ARG_LIB_ROOT_DIR  ".")567  endif()568 569  # Enumerate SOURCES* files570  set( source_list )571  foreach( l IN LISTS ARG_DIRS )572    foreach( s "SOURCES" "SOURCES_${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}" )573      file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/lib/${l}/${s} file_loc )574      file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file_loc} loc )575      # Prepend the location to give higher priority to the specialized576      # implementation577      if( EXISTS ${loc} )578        list( PREPEND source_list ${file_loc} )579      endif()580    endforeach()581  endforeach()582 583  ## Add the generated convert files here to prevent adding the ones listed in584  ## SOURCES585  set( rel_files ${${LIB_FILE_LIST}} ) # Source directory input files, relative to the root dir586  # A "set" of already-added input files587  set( objects )588  foreach( f ${${LIB_FILE_LIST}} )589    get_filename_component( name ${f} NAME )590    list( APPEND objects ${name} )591  endforeach()592 593  foreach( l ${source_list} )594    file( READ ${l} file_list )595    string( REPLACE "\n" ";" file_list ${file_list} )596    get_filename_component( dir ${l} DIRECTORY )597    foreach( f ${file_list} )598      get_filename_component( name ${f} NAME )599      # Only add each file once, so that targets can 'specialize' builtins600      if( NOT ${name} IN_LIST objects )601        list( APPEND objects ${name} )602        list( APPEND rel_files ${dir}/${f} )603      endif()604    endforeach()605  endforeach()606 607  set( ${LIB_FILE_LIST} ${rel_files} PARENT_SCOPE )608endfunction(libclc_configure_lib_source LIB_FILE_LIST)609