1
2#=============================================================================
3#   CMake build system files for detecting Clang and LLVM
4#
5#   Copyright (c) 2014-2020 pocl developers
6#
7#   Permission is hereby granted, free of charge, to any person obtaining a copy
8#   of this software and associated documentation files (the "Software"), to deal
9#   in the Software without restriction, including without limitation the rights
10#   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11#   copies of the Software, and to permit persons to whom the Software is
12#   furnished to do so, subject to the following conditions:
13#
14#   The above copyright notice and this permission notice shall be included in
15#   all copies or substantial portions of the Software.
16#
17#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18#   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20#   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21#   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22#   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23#   THE SOFTWARE.
24#
25#=============================================================================
26
27if(DEFINED WITH_LLVM_CONFIG AND WITH_LLVM_CONFIG)
28  # search for preferred version
29  if(IS_ABSOLUTE "${WITH_LLVM_CONFIG}")
30    if(EXISTS "${WITH_LLVM_CONFIG}")
31      set(LLVM_CONFIG "${WITH_LLVM_CONFIG}")
32    endif()
33  else()
34    find_program(LLVM_CONFIG NAMES "${WITH_LLVM_CONFIG}")
35  endif()
36else()
37  # search for any version
38  find_program(LLVM_CONFIG
39    NAMES
40      "llvmtce-config"
41      "llvm-config"
42      "llvm-config-mp-13.0" "llvm-config-13" "llvm-config130"
43      "llvm-config-mp-12.0" "llvm-config-12" "llvm-config120"
44      "llvm-config-mp-11.0" "llvm-config-11" "llvm-config110"
45      "llvm-config-mp-10.0" "llvm-config-10" "llvm-config100"
46      "llvm-config-mp-9.0" "llvm-config-9" "llvm-config90"
47      "llvm-config-mp-8.0" "llvm-config-8" "llvm-config80"
48      "llvm-config-mp-7.0" "llvm-config-7" "llvm-config70"
49      "llvm-config-mp-6.0" "llvm-config-6.0" "llvm-config60"
50    DOC "llvm-config executable")
51endif()
52
53set(WITH_LLVM_CONFIG "${WITH_LLVM_CONFIG}" CACHE PATH "Path to preferred llvm-config")
54
55if(NOT LLVM_CONFIG)
56  message(FATAL_ERROR "llvm-config not found !")
57else()
58  file(TO_CMAKE_PATH "${LLVM_CONFIG}" LLVM_CONFIG)
59  message(STATUS "Using llvm-config: ${LLVM_CONFIG}")
60  if(LLVM_CONFIG MATCHES "llvmtce-config${CMAKE_EXECUTABLE_SUFFIX}$")
61    set(LLVM_BINARY_SUFFIX "")
62  elseif(LLVM_CONFIG MATCHES "llvm-config${CMAKE_EXECUTABLE_SUFFIX}$")
63    set(LLVM_BINARY_SUFFIX "")
64  elseif(LLVM_CONFIG MATCHES "llvm-config(.*)${CMAKE_EXECUTABLE_SUFFIX}$")
65    set(LLVM_BINARY_SUFFIX "${CMAKE_MATCH_1}")
66  else()
67    message(WARNING "Cannot determine llvm binary suffix from ${LLVM_CONFIG}")
68  endif()
69  message(STATUS "LLVM binaries suffix : ${LLVM_BINARY_SUFFIX}")
70endif()
71
72get_filename_component(LLVM_CONFIG_LOCATION "${LLVM_CONFIG}" DIRECTORY)
73
74##########################################################################
75
76# A macro to run llvm config
77macro(run_llvm_config VARIABLE_NAME)
78  execute_process(
79    COMMAND "${LLVM_CONFIG}" ${ARGN}
80    OUTPUT_VARIABLE LLVM_CONFIG_VALUE
81    RESULT_VARIABLE LLVM_CONFIG_RETVAL
82    OUTPUT_STRIP_TRAILING_WHITESPACE
83  )
84  if(LLVM_CONFIG_RETVAL)
85    message(SEND_ERROR "Error running llvm-config with arguments: ${ARGN}")
86  else()
87    set(${VARIABLE_NAME} ${LLVM_CONFIG_VALUE} CACHE STRING "llvm-config's ${VARIABLE_NAME} value")
88    message(STATUS "llvm-config's ${VARIABLE_NAME} is: ${${VARIABLE_NAME}}")
89  endif()
90endmacro(run_llvm_config)
91
92run_llvm_config(LLVM_PREFIX --prefix)
93# on windows, llvm-config returs "C:\llvm_prefix/bin" mixed style paths,
94# and cmake doesn't like the "\" - thinks its an escape char..
95file(TO_CMAKE_PATH "${LLVM_PREFIX}" LLVM_PREFIX_CMAKE)
96
97set(LLVM_PREFIX_BIN "${LLVM_PREFIX_CMAKE}/bin")
98run_llvm_config(LLVM_VERSION_FULL --version)
99# sigh, sanitize version... `llvm --version` on debian might return 3.4.1 but llvm command names are still <command>-3.4
100string(REGEX REPLACE "([0-9]+)\\.([0-9]+).*" "\\1.\\2" LLVM_VERSION "${LLVM_VERSION_FULL}")
101message(STATUS "LLVM_VERSION: ${LLVM_VERSION}")
102
103string(REPLACE "." ";" LLVM_VERSION_PARSED "${LLVM_VERSION}")
104list(GET LLVM_VERSION_PARSED 0 LLVM_VERSION_MAJOR)
105list(GET LLVM_VERSION_PARSED 1 LLVM_VERSION_MINOR)
106
107run_llvm_config(LLVM_CFLAGS --cflags)
108string(REPLACE "${LLVM_PREFIX}" "${LLVM_PREFIX_CMAKE}" LLVM_CFLAGS "${LLVM_CFLAGS}")
109run_llvm_config(LLVM_CXXFLAGS --cxxflags)
110string(REPLACE "${LLVM_PREFIX}" "${LLVM_PREFIX_CMAKE}" LLVM_CXXFLAGS "${LLVM_CXXFLAGS}")
111run_llvm_config(LLVM_CPPFLAGS --cppflags)
112string(REPLACE "${LLVM_PREFIX}" "${LLVM_PREFIX_CMAKE}" LLVM_CPPFLAGS "${LLVM_CPPFLAGS}")
113run_llvm_config(LLVM_LDFLAGS --ldflags)
114string(REPLACE "${LLVM_PREFIX}" "${LLVM_PREFIX_CMAKE}" LLVM_LDFLAGS "${LLVM_LDFLAGS}")
115run_llvm_config(LLVM_BINDIR --bindir)
116string(REPLACE "${LLVM_PREFIX}" "${LLVM_PREFIX_CMAKE}" LLVM_BINDIR "${LLVM_BINDIR}")
117run_llvm_config(LLVM_LIBDIR --libdir)
118string(REPLACE "${LLVM_PREFIX}" "${LLVM_PREFIX_CMAKE}" LLVM_LIBDIR "${LLVM_LIBDIR}")
119run_llvm_config(LLVM_INCLUDEDIR --includedir)
120string(REPLACE "${LLVM_PREFIX}" "${LLVM_PREFIX_CMAKE}" LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}")
121
122run_llvm_config(LLVM_SRC_ROOT --src-root)
123run_llvm_config(LLVM_OBJ_ROOT --obj-root)
124string(REPLACE "${LLVM_PREFIX}" "${LLVM_PREFIX_CMAKE}" LLVM_OBJ_ROOT "${LLVM_OBJ_ROOT}")
125run_llvm_config(LLVM_ALL_TARGETS --targets-built)
126run_llvm_config(LLVM_HOST_TARGET --host-target)
127run_llvm_config(LLVM_BUILD_MODE --build-mode)
128run_llvm_config(LLVM_ASSERTS_BUILD --assertion-mode)
129run_llvm_config(LLVM_SYSLIBS --system-libs)
130string(STRIP "${LLVM_SYSLIBS}" LLVM_SYSLIBS)
131
132if(MSVC)
133  string(REPLACE "-L${LLVM_LIBDIR}" "" LLVM_LDFLAGS "${LLVM_LDFLAGS}")
134  string(STRIP "${LLVM_LDFLAGS}" LLVM_LDFLAGS)
135endif()
136
137if(LLVM_BUILD_MODE MATCHES "Debug")
138  set(LLVM_BUILD_MODE_DEBUG 1)
139else()
140  set(LLVM_BUILD_MODE_DEBUG 0)
141endif()
142
143# A few work-arounds for llvm-config issues
144
145# - pocl doesn't compile with '-pedantic'
146#LLVM_CXX_FLAGS=$($LLVM_CONFIG --cxxflags | sed -e 's/ -pedantic / /g')
147string(REPLACE " -pedantic" "" LLVM_CXXFLAGS "${LLVM_CXXFLAGS}")
148
149#llvm-config clutters CXXFLAGS with a lot of -W<whatever> flags.
150#(They are not needed - we want to use -Wall anyways)
151#This is a problem if LLVM was built with a different compiler than we use here,
152#and our compiler chokes on unrecognized command-line options.
153string(REGEX REPLACE "-W[^ ]*" "" LLVM_CXXFLAGS "${LLVM_CXXFLAGS}")
154
155# Ubuntu's llvm reports "arm-unknown-linux-gnueabihf" triple, then if one tries
156# `clang --target=arm-unknown-linux-gnueabihf ...` it will produce armv6 code,
157# even if one's running armv7;
158# Here we replace the "arm" string with whatever's in CMAKE_HOST_SYSTEM_PROCESSOR
159# which should be "armv6l" on rasp pi, or "armv7l" on my cubieboard, hopefully its
160# more reasonable and reliable than llvm's own host flags
161if(NOT CMAKE_CROSSCOMPILING)
162  string(REPLACE "arm-" "${CMAKE_HOST_SYSTEM_PROCESSOR}-" LLVM_HOST_TARGET "${LLVM_HOST_TARGET}")
163endif()
164
165# In windows llvm-config reports --target=x86_64-pc-windows-msvc
166# however this causes clang to use MicrosoftCXXMangler, which does not
167# yet support mangling for extended vector types (with llvm 3.5)
168# so for now hardcode LLVM_HOST_TARGET to be x86_64-pc with windows
169if(WIN32)
170  set(LLVM_HOST_TARGET "x86_64-pc")
171endif(WIN32)
172
173# required for sources..
174if(LLVM_VERSION MATCHES "^6[.]0")
175  set(LLVM_MAJOR 6)
176  set(LLVM_6_0 1)
177  set(LLVM_OLDER_THAN_7_0 1)
178  set(LLVM_OLDER_THAN_8_0 1)
179  set(LLVM_OLDER_THAN_9_0 1)
180  set(LLVM_OLDER_THAN_10_0 1)
181elseif(LLVM_VERSION MATCHES "^7[.]")
182  set(LLVM_MAJOR 7)
183  set(LLVM_7_0 1)
184  set(LLVM_OLDER_THAN_8_0 1)
185  set(LLVM_OLDER_THAN_9_0 1)
186  set(LLVM_OLDER_THAN_10_0 1)
187elseif(LLVM_VERSION MATCHES "^8[.]")
188  set(LLVM_MAJOR 8)
189  set(LLVM_8_0 1)
190  set(LLVM_OLDER_THAN_9_0 1)
191  set(LLVM_OLDER_THAN_10_0 1)
192elseif(LLVM_VERSION MATCHES "^9[.]")
193  set(LLVM_MAJOR 9)
194  set(LLVM_9_0 1)
195  set(LLVM_OLDER_THAN_10_0 1)
196elseif(LLVM_VERSION MATCHES "^10[.]")
197  set(LLVM_MAJOR 10)
198  set(LLVM_10_0 1)
199elseif(LLVM_VERSION MATCHES "^11[.]")
200  set(LLVM_MAJOR 11)
201  set(LLVM_11_0 1)
202elseif(LLVM_VERSION MATCHES "^12[.]")
203  set(LLVM_MAJOR 12)
204  set(LLVM_12_0 1)
205elseif(LLVM_VERSION MATCHES "^13[.]")
206  set(LLVM_MAJOR 13)
207  set(LLVM_13_0 1)
208else()
209  message(FATAL_ERROR "LLVM version between 6.0 and 13.0 required, found: ${LLVM_VERSION}")
210endif()
211
212#############################################################
213
214run_llvm_config(LLVM_HAS_RTTI --has-rtti)
215
216if(DEFINED SINGLE_LLVM_LIB)
217   message(AUTHOR_WARNING "SINGLE_LLVM_LIB option was removed; pocl now uses only llvm-config to get the libraries. Use STATIC_LLVM=ON/OFF to affect which libraries pocl requests from llvm-config")
218endif()
219
220if(STATIC_LLVM)
221  set(LLVM_LIB_MODE --link-static)
222else()
223  set(LLVM_LIB_MODE --link-shared)
224endif()
225
226unset(LLVM_LIBS)
227run_llvm_config(LLVM_LIBS --libs ${LLVM_LIB_MODE})
228# Convert LLVM_LIBS from string -> list format to make handling them easier
229separate_arguments(LLVM_LIBS)
230
231# With Visual Studio llvm-config gives invalid list of static libs (libXXXX.a instead of XXXX.lib)
232# we extract the pure names (LLVMLTO, LLVMMipsDesc etc) and let find_library do its job
233foreach(LIBFLAG ${LLVM_LIBS})
234  STRING(REGEX REPLACE "^-l(.*)$" "\\1" LIB_NAME ${LIBFLAG})
235  list(APPEND LLVM_LIBNAMES "${LIB_NAME}")
236endforeach()
237
238foreach(LIBNAME ${LLVM_LIBNAMES})
239  find_library(L_LIBFILE_${LIBNAME} NAMES "${LIBNAME}" HINTS "${LLVM_LIBDIR}")
240  list(APPEND LLVM_LIBFILES "${L_LIBFILE_${LIBNAME}}")
241endforeach()
242
243set(POCL_LLVM_LIBS ${LLVM_LIBFILES})
244
245####################################################################
246
247run_llvm_config(LLVM_SYSLIBS --system-libs ${LLVM_LIB_MODE})
248string(STRIP "${LLVM_SYSLIBS}" LLVM_SYSLIBS)
249
250####################################################################
251
252# llvm-config does not include clang libs
253if((9 LESS LLVM_MAJOR) AND (NOT STATIC_LLVM))
254  # For Clang 10+, link against a single shared library instead of multiple component shared
255  # libraries.
256  if("${LLVM_LIBNAMES}" MATCHES "LLVMTCE")
257    set(CLANG_LIBNAMES clangTCE-cpp)
258  else()
259    set(CLANG_LIBNAMES clang-cpp)
260  endif()
261else()
262  set(CLANG_LIBNAMES clangCodeGen clangFrontendTool clangFrontend clangDriver clangSerialization
263      clangParse clangSema clangRewrite clangRewriteFrontend
264      clangStaticAnalyzerFrontend clangStaticAnalyzerCheckers
265      clangStaticAnalyzerCore clangAnalysis clangEdit clangAST clangASTMatchers clangLex clangBasic)
266endif()
267
268foreach(LIBNAME ${CLANG_LIBNAMES})
269  find_library(C_LIBFILE_${LIBNAME} NAMES "${LIBNAME}" HINTS "${LLVM_LIBDIR}")
270  list(APPEND CLANG_LIBFILES "${C_LIBFILE_${LIBNAME}}")
271  if(UNIX AND (NOT APPLE))
272    set(LLVM_LDFLAGS "${LLVM_LDFLAGS} -Wl,--exclude-libs,lib${LIBNAME}")
273  endif()
274endforeach()
275
276####################################################################
277
278macro(find_program_or_die OUTPUT_VAR PROG_NAME DOCSTRING)
279  find_program(${OUTPUT_VAR}
280    NAMES "${PROG_NAME}${LLVM_BINARY_SUFFIX}${CMAKE_EXECUTABLE_SUFFIX}" "${PROG_NAME}${CMAKE_EXECUTABLE_SUFFIX}"
281    HINTS "${LLVM_BINDIR}" "${LLVM_CONFIG_LOCATION}" "${LLVM_PREFIX}" "${LLVM_PREFIX_BIN}"
282    DOC "${DOCSTRING}"
283    NO_CMAKE_PATH
284    NO_CMAKE_ENVIRONMENT_PATH
285  )
286  if(${OUTPUT_VAR})
287    message(STATUS "Found ${PROG_NAME}: ${${OUTPUT_VAR}}")
288  else()
289    message(FATAL_ERROR "${PROG_NAME} executable not found!")
290  endif()
291endmacro()
292
293find_program_or_die( CLANG "clang" "clang binary")
294execute_process(COMMAND "${CLANG}" "--version" OUTPUT_VARIABLE LLVM_CLANG_VERSION RESULT_VARIABLE CLANG_RES)
295# TODO this should be optional
296find_program_or_die( CLANGXX "clang++" "clang++ binary")
297execute_process(COMMAND "${CLANGXX}" "--version" OUTPUT_VARIABLE LLVM_CLANGXX_VERSION RESULT_VARIABLE CLANGXX_RES)
298if(CLANGXX_RES OR CLANG_RES)
299  message(FATAL_ERROR "Failed running clang/clang++ --version")
300endif()
301
302find_program_or_die(LLVM_OPT  "opt"       "LLVM optimizer")
303find_program_or_die(LLVM_LLC  "llc"       "LLVM static compiler")
304find_program_or_die(LLVM_AS   "llvm-as"   "LLVM assembler")
305find_program_or_die(LLVM_LINK "llvm-link" "LLVM IR linker")
306find_program_or_die(LLVM_LLI  "lli"       "LLVM interpreter")
307
308if(NOT DEFINED LLVM_SPIRV)
309  find_program(LLVM_SPIRV NAMES "llvm-spirv${LLVM_BINARY_SUFFIX}${CMAKE_EXECUTABLE_SUFFIX}" "llvm-spirv${CMAKE_EXECUTABLE_SUFFIX}" HINTS "${LLVM_BINDIR}" "${LLVM_CONFIG_LOCATION}" "${LLVM_PREFIX}" "${LLVM_PREFIX_BIN}")
310  if(LLVM_SPIRV)
311    message(STATUS "Found llvm-spirv: ${LLVM_SPIRV}")
312  endif()
313endif()
314
315####################################################################
316
317# try compile with any compiler (supplied as argument)
318macro(custom_try_compile_any SILENT COMPILER SUFFIX SOURCE RES_VAR)
319  string(RANDOM RNDNAME)
320  set(RANDOM_FILENAME "${CMAKE_BINARY_DIR}/compile_test_${RNDNAME}.${SUFFIX}")
321  file(WRITE "${RANDOM_FILENAME}" "${SOURCE}")
322
323  math(EXPR LSIZE "${ARGC} - 4")
324
325  execute_process(COMMAND "${COMPILER}" ${ARGN} "${RANDOM_FILENAME}" RESULT_VARIABLE ${RES_VAR} OUTPUT_VARIABLE OV ERROR_VARIABLE EV)
326  if(${${RES_VAR}} AND (NOT ${SILENT}))
327    message(STATUS " ########## The command: ")
328    string(REPLACE ";" " " ARGN_STR "${ARGN}")
329    message(STATUS "${COMPILER} ${ARGN_STR} ${RANDOM_FILENAME}")
330    message(STATUS " ########## Exited with nonzero status: ${${RES_VAR}}")
331    if(OV)
332      message(STATUS "STDOUT: ${OV}")
333    endif()
334    if(EV)
335      message(STATUS "STDERR: ${EV}")
336    endif()
337  endif()
338  file(REMOVE "${RANDOM_FILENAME}")
339
340endmacro()
341
342# convenience c/c++ source wrapper
343macro(custom_try_compile_c_cxx COMPILER SUFFIX SOURCE1 SOURCE2 RES_VAR)
344  set(SOURCE_PROG "
345  ${SOURCE1}
346
347  int main(int argc, char** argv) {
348
349  ${SOURCE2}
350
351  }")
352  custom_try_compile_any(FALSE "${COMPILER}" ${SUFFIX} "${SOURCE_PROG}" ${RES_VAR} ${ARGN})
353endmacro()
354
355# convenience c/c++ source wrapper
356macro(custom_try_compile_c_cxx_silent COMPILER SUFFIX SOURCE1 SOURCE2 RES_VAR)
357  set(SOURCE_PROG "
358  ${SOURCE1}
359
360  int main(int argc, char** argv) {
361
362  ${SOURCE2}
363
364  }")
365  custom_try_compile_any(TRUE "${COMPILER}" ${SUFFIX} "${SOURCE_PROG}" ${RES_VAR} ${ARGN})
366endmacro()
367
368# clang++ try-compile macro
369macro(custom_try_compile_clangxx SOURCE1 SOURCE2 RES_VAR)
370  custom_try_compile_c_cxx("${CLANGXX}" "cc" "${SOURCE1}" "${SOURCE2}" ${RES_VAR}  "-c" ${ARGN})
371endmacro()
372
373# clang++ try-compile macro
374macro(custom_try_compile_clang SOURCE1 SOURCE2 RES_VAR)
375  custom_try_compile_c_cxx("${CLANG}" "c" "${SOURCE1}" "${SOURCE2}" ${RES_VAR}  "-c" ${ARGN})
376endmacro()
377
378# clang++ try-compile macro
379macro(custom_try_compile_clang_silent SOURCE1 SOURCE2 RES_VAR)
380  custom_try_compile_c_cxx_silent("${CLANG}" "c" "${SOURCE1}" "${SOURCE2}" ${RES_VAR} "-c" ${ARGN})
381endmacro()
382
383# clang++ try-link macro
384macro(custom_try_link_clang SOURCE1 SOURCE2 RES_VAR)
385  set(RANDOM_FILENAME "${CMAKE_BINARY_DIR}/compile_test_${RNDNAME}.${SUFFIX}")
386  custom_try_compile_c_cxx_silent("${CLANG}" "c" "${SOURCE1}" "${SOURCE2}" ${RES_VAR}  "-o" "${RANDOM_FILENAME}" ${ARGN})
387  file(REMOVE "${RANDOM_FILENAME}")
388endmacro()
389
390# clang try-compile-run macro, running via native executable
391macro(custom_try_run_exe SOURCE1 SOURCE2 OUTPUT_VAR RES_VAR)
392  set(OUTF "${CMAKE_BINARY_DIR}/try_run${CMAKE_EXECUTABLE_SUFFIX}")
393  if(EXISTS "${OUTF}")
394    file(REMOVE "${OUTF}")
395  endif()
396  custom_try_compile_c_cxx("${CLANG}" "c" "${SOURCE1}" "${SOURCE2}" RESV "-o" "${OUTF}" "-x" "c")
397  set(${OUTPUT_VAR} "")
398  set(${RES_VAR} "")
399  if(RESV OR (NOT EXISTS "${OUTF}"))
400    message(STATUS " ########## Compilation failed")
401  else()
402    execute_process(COMMAND "${OUTF}" RESULT_VARIABLE RESV OUTPUT_VARIABLE ${OUTPUT_VAR} ERROR_VARIABLE EV)
403    set(${RES_VAR} ${RESV})
404    file(REMOVE "${OUTF}")
405    if(${RESV})
406      message(STATUS " ########## Running ${OUTF}")
407      message(STATUS " ########## Exited with nonzero status: ${RESV}")
408      if(${${OUTPUT_VAR}})
409        message(STATUS " ########## STDOUT: ${${OUTPUT_VAR}}")
410      endif()
411      if(EV)
412        message(STATUS " ########## STDERR: ${EV}")
413      endif()
414    endif()
415  endif()
416endmacro()
417
418# clang try-compile-run macro, run via lli, the llvm interpreter
419macro(custom_try_run_lli SILENT SOURCE1 SOURCE2 OUTPUT_VAR RES_VAR)
420# this uses "lli" - the interpreter, so we can run any -target
421# TODO variable for target !!
422  set(OUTF "${CMAKE_BINARY_DIR}/try_run.bc")
423  if(EXISTS "${OUTF}")
424    file(REMOVE "${OUTF}")
425  endif()
426  custom_try_compile_c_cxx("${CLANG}" "c" "${SOURCE1}" "${SOURCE2}" RESV "-o" "${OUTF}" "-x" "c" "-emit-llvm" "-c" ${ARGN})
427  set(${OUTPUT_VAR} "")
428  set(${RES_VAR} "")
429  if(RESV OR (NOT EXISTS "${OUTF}"))
430    message(STATUS " ########## Compilation failed")
431  else()
432    execute_process(COMMAND "${LLVM_LLI}" "-force-interpreter" "${OUTF}" RESULT_VARIABLE RESV OUTPUT_VARIABLE ${OUTPUT_VAR} ERROR_VARIABLE EV)
433    set(${RES_VAR} ${RESV})
434    file(REMOVE "${OUTF}")
435    if(${RESV} AND (NOT ${SILENT}))
436      message(STATUS " ########## The command ${LLVM_LLI} -force-interpreter ${OUTF}")
437      message(STATUS " ########## Exited with nonzero status: ${RESV}")
438      if(${${OUTPUT_VAR}})
439        message(STATUS " ########## STDOUT: ${${OUTPUT_VAR}}")
440      endif()
441      if(EV)
442        message(STATUS " ########## STDERR: ${EV}")
443      endif()
444    endif()
445  endif()
446endmacro()
447
448####################################################################
449####################################################################
450
451# The option for specifying the target changed; try the modern syntax
452# first, and fall back to the old-style syntax if this failed
453
454if(NOT DEFINED CLANG_TARGET_OPTION AND ENABLE_HOST_CPU_DEVICES)
455
456  custom_try_compile_clangxx("" "return 0;" RES "--target=${LLVM_HOST_TARGET}")
457  if(NOT RES)
458    set(CLANG_TGT "--target=")
459  else()
460    #EXECUTE_PROCESS(COMMAND "${CLANG}" "-target ${LLVM_HOST_TARGET}" "-x" "c" "/dev/null" "-S" RESULT_VARIABLE RES)
461    custom_try_compile_clangxx("" "return 0;" RES "-target ${LLVM_HOST_TARGET}")
462    if(NOT RES)
463      set(CLANG_TGT "-target ")
464    else()
465      message(FATAL_ERROR "Cannot determine Clang option to specify the target")
466    endif()
467  endif()
468
469  set(CLANG_TARGET_OPTION ${CLANG_TGT} CACHE INTERNAL "Clang option used to specify the target" )
470
471endif()
472
473####################################################################
474####################################################################
475
476if(NOT DEFINED CLANG_NEEDS_RTLIB)
477
478  set(RT128 OFF)
479  set(RT64 OFF)
480  set(NEEDS_RTLIB_FLAG OFF)
481
482  # on 32bit systems, we need 64bit emulation
483  if(CMAKE_SIZEOF_VOID_P EQUAL 4)
484    set(INC "#include <stdint.h>\n#include <stddef.h>")
485    set(SRC "int64_t a = argc; int64_t b = argc-1; int64_t c = a / b; return (int)c; ")
486    custom_try_link_clang("${INC}" "${SRC}" RES)
487    if(NOT RES)
488      message(STATUS "64bit division compiles without extra flags")
489      set(RT64 ON)
490    else()
491      custom_try_link_clang("${INC}" "${SRC}" RES "--rtlib=compiler-rt")
492      if(NOT RES)
493        message(STATUS "64bit division compiles WITH --rtlib=compiler-rt")
494        set(NEEDS_RTLIB_FLAG ON)
495        set(RT64 ON)
496      else()
497        message(WARNING "64bit division doesn't compile at all!")
498      endif()
499    endif()
500
501  else()
502
503    set(RT64 ON)
504    # on 64bit systems, we need 128bit integers for Errol
505    set(INC "extern __uint128_t __udivmodti4(__uint128_t a, __uint128_t b, __uint128_t* rem);")
506    set(SRC "__uint128_t low, mid, tmp1, pow19 = (__uint128_t)1000000000; mid = __udivmodti4(low, pow19, &tmp1); return 0;")
507    custom_try_link_clang("${INC}" "${SRC}" RES)
508
509    if(NOT RES)
510      message(STATUS "udivmodti4 compiles without extra flags")
511      set(RT128 ON)
512    else()
513      custom_try_link_clang("${INC}" "${SRC}" RES "--rtlib=compiler-rt")
514      if(NOT RES)
515        message(STATUS "udivmodti4 compiles WITH --rtlib=compiler-rt")
516        set(NEEDS_RTLIB_FLAG ON)
517        set(RT128 ON)
518      else()
519        message(WARNING "udivmodti4 doesn't compile at all!")
520      endif()
521    endif()
522
523  endif()
524
525  set(CLANG_HAS_64B_MATH ${RT64} CACHE INTERNAL "Clang's available with 64bit math")
526  set(CLANG_HAS_128B_MATH ${RT128} CACHE INTERNAL "Clang's available with 128bit math")
527  set(CLANG_NEEDS_RTLIB ${NEEDS_RTLIB_FLAG} CACHE INTERNAL "Clang needs extra --rtlib flag for compiler-rt math")
528
529endif()
530
531####################################################################
532
533macro(CHECK_ALIGNOF TYPE TYPEDEF OUT_VAR)
534
535  if(NOT DEFINED "${OUT_VAR}")
536
537    custom_try_run_lli(TRUE "
538#ifndef offsetof
539#define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
540#endif
541
542${TYPEDEF}" "typedef struct { char x; ${TYPE} y; } ac__type_alignof_;
543    int r = offsetof(ac__type_alignof_, y);
544    return r;" SIZEOF_STDOUT RESULT "${CLANG_TARGET_OPTION}${LLC_TRIPLE}")
545
546    #message(FATAL_ERROR "SIZEOF: ${SIZEOF_STDOUT} RES: ${RESULT}")
547    if(NOT ${RESULT})
548      message(SEND_ERROR "Could not determine align of(${TYPE})")
549    endif()
550
551    set(${OUT_VAR} "${RESULT}" CACHE INTERNAL "Align of ${TYPE}")
552
553  endif()
554
555endmacro()
556
557####################################################################
558#
559# clangxx works check
560#
561
562# TODO clang + vecmathlib doesn't work on Windows yet...
563if(CLANGXX AND (NOT WIN32) AND ENABLE_HOST_CPU_DEVICES)
564
565  message(STATUS "Checking if clang++ works (required by vecmathlib)")
566
567  set(CXX_WORKS 0)
568  set(CXX_STDLIB "")
569
570  if(NOT DEFINED CLANGXX_WORKS)
571
572    custom_try_compile_clangxx("namespace std { class type_info; } \n  #include <iostream> \n  #include <type_traits>" "std::cout << \"Hello clang++ world!\" << std::endl;" _STATUS_FAIL "-std=c++11")
573
574    if(NOT _STATUS_FAIL)
575      set(CXX_WORKS 1)
576    else()
577      custom_try_compile_clangxx("namespace std { class type_info; } \n  #include <iostream> \n  #include <type_traits>" "std::cout << \"Hello clang++ world!\" << std::endl;" _STATUS_FAIL "-stdlib=libstdc++" "-std=c++11")
578      if (NOT _STATUS_FAIL)
579        set(CXX_STDLIB "-stdlib=libstdc++")
580        set(CXX_WORKS 1)
581      else()
582        custom_try_compile_clangxx("namespace std { class type_info; } \n  #include <iostream> \n  #include <type_traits>" "std::cout << \"Hello clang++ world!\" << std::endl;" _STATUS_FAIL "-stdlib=libc++" "-std=c++11")
583        if(NOT _STATUS_FAIL)
584          set(CXX_STDLIB "-stdlib=libc++")
585          set(CXX_WORKS 1)
586        endif()
587      endif()
588    endif()
589
590    set(CLANGXX_WORKS ${CXX_WORKS} CACHE INTERNAL "Clang++ ")
591    set(CLANGXX_STDLIB ${CXX_STDLIB} CACHE INTERNAL "Clang++ stdlib")
592  endif()
593
594
595endif()
596
597if(CLANGXX_STDLIB AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
598  set(LLVM_CXXFLAGS "${CLANGXX_STDLIB} ${LLVM_CXXFLAGS}")
599  set(LLVM_LDFLAGS "${CLANGXX_STDLIB} ${LLVM_LDFLAGS}")
600endif()
601
602####################################################################
603#
604# - '-DNDEBUG' is a work-around for llvm bug 18253
605#
606# llvm-config does not always report the "-DNDEBUG" flag correctly
607# (see LLVM bug 18253). If LLVM and the pocl passes are built with
608# different NDEBUG settings, problems arise
609
610if(NOT DEFINED LLVM_NDEBUG_BUILD)
611
612  message(STATUS "Checking if LLVM is a DEBUG build")
613  separate_arguments(_FLAGS UNIX_COMMAND "${LLVM_CXXFLAGS}")
614
615  set(_TEST_SOURCE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/llvmNDEBUG.cc")
616  file(WRITE "${_TEST_SOURCE}"
617    "
618      #include <llvm/Support/Debug.h>
619      int main(int argc, char** argv) {
620        llvm::DebugFlag=true;
621      }
622    ")
623
624  set(TRY_COMPILE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXXFLAGS} -UNDEBUG")
625
626  try_compile(_TRY_SUCCESS ${CMAKE_BINARY_DIR} "${_TEST_SOURCE}"
627    CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${LLVM_INCLUDE_DIRS}"
628    CMAKE_FLAGS "-DLINK_DIRECTORIES:STRING=${LLVM_LIBDIR}"
629    LINK_LIBRARIES "${LLVM_LIBS} ${LLVM_SYSLIBS} ${LLVM_LDFLAGS}"
630    COMPILE_DEFINITIONS ${TRY_COMPILE_CXX_FLAGS}
631    OUTPUT_VARIABLE _TRY_COMPILE_OUTPUT
632  )
633
634  file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log"
635    "Test -NDEBUG flag: ${_TRY_COMPILE_OUTPUT}\n")
636
637  if(_TRY_SUCCESS)
638    message(STATUS "DEBUG build")
639    set(LLVM_NDEBUG_BUILD 0 CACHE INTERNAL "DNDEBUG")
640  else()
641    message(STATUS "Not a DEBUG build")
642    set(LLVM_NDEBUG_BUILD 1 CACHE INTERNAL "DNDEBUG")
643  endif()
644
645endif()
646
647if((NOT LLVM_CXXFLAGS MATCHES "-DNDEBUG") AND LLVM_NDEBUG_BUILD)
648  message(STATUS "adding -DNDEBUG explicitly")
649  set(LLVM_CXXFLAGS "${LLVM_CXXFLAGS} -DNDEBUG")
650endif()
651
652
653####################################################################
654
655# TODO: We need to set both target-triple and cpu-type when
656# building, since the ABI depends on both. We can either add flags
657# to all the scripts, or set the respective flags here in
658# *_CLANG_FLAGS and *_LLC_FLAGS. Note that clang and llc use
659# different option names to set these. Note that clang calls the
660# triple "target" and the cpu "architecture", which is different
661# from llc.
662
663# Normalise the triple. Otherwise, clang normalises it when
664# passing it to llc, which is then different from the triple we
665# pass to llc. This would lead to inconsistent bytecode files,
666# depending on whether they are generated via clang or directly
667# via llc.
668
669
670if(ENABLE_HOST_CPU_DEVICES AND NOT DEFINED LLC_TRIPLE)
671  message(STATUS "Find out LLC target triple (for host ${LLVM_HOST_TARGET})")
672  set(_EMPTY_C_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/tripletfind.c")
673  file(WRITE "${_EMPTY_C_FILE}" "")
674
675  execute_process(COMMAND ${CLANG} "${CLANG_TARGET_OPTION}${LLVM_HOST_TARGET}" -x c ${_EMPTY_C_FILE} -S -emit-llvm -o - RESULT_VARIABLE RES_VAR OUTPUT_VARIABLE OUTPUT_VAR)
676  if(RES_VAR)
677    message(FATAL_ERROR "Error ${RES_VAR} while determining target triple")
678  endif()
679  if(OUTPUT_VAR MATCHES "target triple = \"([^\"]+)")
680    string(STRIP "${CMAKE_MATCH_1}" LLC_TRIPLE)
681  else()
682    message(FATAL_ERROR "Could not find target triple in llvm output")
683  endif()
684
685  # TODO the armv7hl normalize
686  string(REPLACE "armv7l-" "armv7-" LLC_TRIPLE "${LLC_TRIPLE}")
687
688  set(LLC_TRIPLE "${LLC_TRIPLE}" CACHE INTERNAL "LLC_TRIPLE")
689
690endif()
691
692
693# FIXME: The cpu name printed by llc --version is the same cpu that will be
694# targeted if you pass -mcpu=native to llc, so we could replace this auto-detection
695# with just: set(LLC_HOST_CPU "native"), however, we can't do this at the moment
696# because of the work-around for arm1176jz-s.
697if(ENABLE_HOST_CPU_DEVICES AND NOT DEFINED LLC_HOST_CPU_AUTO)
698  message(STATUS "Find out LLC host CPU with ${LLVM_LLC}")
699  execute_process(COMMAND ${LLVM_LLC} "--version" RESULT_VARIABLE RES_VAR OUTPUT_VARIABLE OUTPUT_VAR)
700  # WTF, ^^ has return value 1
701  #if(RES_VAR)
702  #  message(FATAL_ERROR "Error ${RES_VAR} while determining LLC host CPU")
703  #endif()
704
705  if(OUTPUT_VAR MATCHES "Host CPU: ([^ ]*)")
706    # sigh... STRING(STRIP is to workaround regexp bug in cmake
707    string(STRIP "${CMAKE_MATCH_1}" LLC_HOST_CPU_AUTO)
708  else()
709    message(FATAL_ERROR "Couldnt determine host CPU from llc output")
710  endif()
711
712  #TODO better
713  if(CMAKE_LIBRARY_ARCHITECTURE MATCHES "gnueabihf" AND LLC_HOST_CPU_AUTO MATCHES "arm1176jz-s")
714    set(LLC_HOST_CPU_AUTO "arm1176jzf-s")
715  endif()
716endif()
717
718
719
720if((LLC_HOST_CPU_AUTO MATCHES "unknown") AND (NOT LLC_HOST_CPU))
721  message(FATAL_ERROR "LLVM could not recognize your CPU model automatically. Please run CMake with -DLLC_HOST_CPU=<cpu> (you can find valid names with: llc -mcpu=help)")
722else()
723  set(LLC_HOST_CPU_AUTO "${LLC_HOST_CPU_AUTO}" CACHE INTERNAL "Autodetected CPU")
724endif()
725
726if((DEFINED LLC_HOST_CPU) AND (NOT LLC_HOST_CPU STREQUAL LLC_HOST_CPU_AUTO))
727  message(STATUS "Autodetected CPU ${LLC_HOST_CPU_AUTO} overriden by user to ${LLC_HOST_CPU}")
728  set(HOST_CPU_FORCED 1 CACHE INTERNAL "CPU is forced by user")
729else()
730  set(LLC_HOST_CPU "${LLC_HOST_CPU_AUTO}" CACHE STRING "The Host CPU to use with llc")
731  set(HOST_CPU_FORCED 0 CACHE INTERNAL "CPU is forced by user")
732endif()
733
734
735####################################################################
736# Some architectures have -march and -mcpu reversed
737
738if(NOT DEFINED CLANG_MARCH_FLAG)
739  message(STATUS "Checking clang -march vs. -mcpu flag")
740  custom_try_compile_clang_silent("" "return 0;" RES ${CLANG_TARGET_OPTION}${LLC_TRIPLE} -march=${LLC_HOST_CPU})
741  if(NOT RES)
742    set(CLANG_MARCH_FLAG "-march=")
743  else()
744    custom_try_compile_clang_silent("" "return 0;" RES ${CLANG_TARGET_OPTION}${LLC_TRIPLE} -mcpu=${LLC_HOST_CPU})
745    if(NOT RES)
746      set(CLANG_MARCH_FLAG "-mcpu=")
747    else()
748      message(FATAL_ERROR "Could not determine whether to use -march or -mcpu with clang")
749    endif()
750  endif()
751  message(STATUS "  Using ${CLANG_MARCH_FLAG}")
752
753  set(CLANG_MARCH_FLAG ${CLANG_MARCH_FLAG} CACHE INTERNAL "Clang option used to specify the target cpu")
754endif()
755
756####################################################################
757
758# This tests that we can actually link to the llvm libraries.
759# Mostly to catch issues like #295 - cannot find -ledit
760
761if(NOT DEFINED LLVM_LINK_TEST)
762
763  set(LLVM_LINK_TEST_SOURCE "
764    #include <stdio.h>
765    #include \"llvm/IR/LLVMContext.h\"
766    #include \"llvm/Support/SourceMgr.h\"
767    #include \"llvm/IR/Module.h\"
768    #include \"llvm/IRReader/IRReader.h\"
769
770    int main( int argc, char* argv[] )
771    {
772       if( argc < 2 )
773         exit(2);
774
775       llvm::LLVMContext context;
776       llvm::SMDiagnostic err;
777       std::unique_ptr<llvm::Module> module = llvm::parseIRFile( argv[1], err, context );
778
779       if( !module )
780         exit(1);
781       else
782         printf(\"DataLayout = %s\\n\", module->getDataLayoutStr().c_str());
783
784       return 0;
785    }")
786
787  string(RANDOM RNDNAME)
788  set(LLVM_LINK_TEST_FILENAME "${CMAKE_BINARY_DIR}/llvm_link_test_${RNDNAME}.cc")
789  file(WRITE "${LLVM_LINK_TEST_FILENAME}" "${LLVM_LINK_TEST_SOURCE}")
790
791  try_compile(LLVM_LINK_TEST ${CMAKE_BINARY_DIR} "${LLVM_LINK_TEST_FILENAME}"
792              CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${LLVM_INCLUDE_DIRS}"
793              CMAKE_FLAGS "-DLINK_DIRECTORIES:STRING=${LLVM_LIBDIR}"
794              LINK_LIBRARIES "${LLVM_LDFLAGS} ${LLVM_LIBS} ${LLVM_SYSLIBS}"
795              COMPILE_DEFINITIONS "${CMAKE_CXX_FLAGS} ${LLVM_CXXFLAGS}"
796              OUTPUT_VARIABLE _TRY_COMPILE_OUTPUT)
797
798  if (LLVM_LINK_TEST)
799    message(STATUS "LLVM link test OK")
800    set(LLVM_LINK_TEST 1 CACHE INTERNAL "LLVM link test result")
801  else()
802    message(STATUS "LLVM link test output: ${_TRY_COMPILE_OUTPUT}")
803    message(FATAL_ERROR "LLVM link test FAILED. This mostly happens when your LLVM installation does not have all dependencies installed.")
804  endif()
805
806endif()
807
808
809####################################################################
810
811if(ENABLE_HOST_CPU_DEVICES AND NOT DEFINED ${CL_DISABLE_HALF})
812  set(CL_DISABLE_HALF 0)
813  message(STATUS "Checking fp16 support")
814  custom_try_compile_clang_silent("__fp16 callfp16(__fp16 a) { return a * (__fp16)1.8; };" "__fp16 x=callfp16((__fp16)argc);" RESV ${CLANG_TARGET_OPTION}${LLC_TRIPLE} ${CLANG_MARCH_FLAG}${LLC_HOST_CPU})
815  if(RESV)
816    set(CL_DISABLE_HALF 1)
817  endif()
818endif()
819
820set(CL_DISABLE_HALF "${CL_DISABLE_HALF}" CACHE INTERNAL "Disable cl_khr_fp16 because fp16 is not supported")
821message(STATUS "FP16 is disabled: ${CL_DISABLE_HALF}")
822
823#####################################################################
824
825execute_process(COMMAND "${CLANG}" "--print-resource-dir" OUTPUT_VARIABLE RESOURCE_DIR)
826string(STRIP "${RESOURCE_DIR}" RESOURCE_DIR)
827set(CLANG_RESOURCE_DIR "${RESOURCE_DIR}" CACHE INTERNAL "Clang resource dir")
828
829set(CLANG_OPENCL_HEADERS "${CLANG_RESOURCE_DIR}/include/opencl-c.h")
830if(NOT LLVM_OLDER_THAN_9_0)
831  list(APPEND CLANG_OPENCL_HEADERS "${CLANG_RESOURCE_DIR}/include/opencl-c-base.h")
832endif()
833