From 969bdd333944b35de3d6727f99d263cd6e5a26fb Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Tue, 27 Sep 2016 01:39:56 +0900 Subject: [PATCH 1/3] Add a build-system for compiler-rt. Compiler-rt is the runtime library of LLVM and sometimes we need to resolve library calls to it. There are two moments were we need to handle library calls to compiler-rt. 1. `sys.so` or any other Julia code compiled into shlibs. In this case we perform static linking, as with other runtime libraries. 2. JIT time. When we compile a Julia function that uses a libcall to crt we need to resolve that against a shlib copy of compiler-rt. Compiler-rt is usually only distributed as a static library, so we provide a step to turn the static library into a shared one. The buildsystem of compiler-rt is tightly tied to LLVM. Because of this we have a staged build-script that builds compiler-rt from source. This standalone version should only be used for Julia. --- Make.inc | 12 +++ Makefile | 3 +- contrib/windows/msys_build.sh | 2 +- deps/Makefile | 5 +- deps/compiler-rt.mk | 149 +++++++++++++++++++++++++++++++++ deps/compiler-rt_standalone.mk | 90 ++++++++++++++++++++ deps/llvm.mk | 46 +++++++--- deps/tools/common.mk | 1 + 8 files changed, 294 insertions(+), 14 deletions(-) create mode 100644 deps/compiler-rt.mk create mode 100644 deps/compiler-rt_standalone.mk diff --git a/Make.inc b/Make.inc index 8f6cc419eaaf2..d2fa14096fd67 100644 --- a/Make.inc +++ b/Make.inc @@ -228,6 +228,11 @@ LLVM_DEBUG := 0 #LLVM_USE_CMAKE: defined in deps/llvm-ver.mk as it depends on LLVM_VER_SHORT # set to 1 to get clang and compiler-rt BUILD_LLVM_CLANG := 0 +# set to 0 to disable building compiler-rt standalone. +# Currently compiler-rt can only be built alongside clang +# so we default to the standalone build +STANDALONE_COMPILER_RT := 1 + # set to 1 to get lldb (often does not work, no chance with llvm3.2 and earlier) # see http://lldb.llvm.org/build.html for dependencies BUILD_LLDB := 0 @@ -483,10 +488,17 @@ OBJCOPY := $(CROSS_COMPILE)objcopy # file extensions ifeq ($(OS), WINNT) SHLIB_EXT := dll +ifeq ($(USEMSVC),1) + STATICLIB_EXT := lib +else + STATICLIB_EXT := a +endif else ifeq ($(OS), Darwin) SHLIB_EXT := dylib + STATICLIB_EXT := a else SHLIB_EXT := so + STATICLIB_EXT := a endif # On Windows, we want shared library files to end up in $(build_bindir), instead of $(build_libdir) diff --git a/Makefile b/Makefile index 4dc5a41aebcc6..ac1450a3ab04a 100644 --- a/Makefile +++ b/Makefile @@ -170,6 +170,7 @@ $(build_datarootdir)/julia/julia-config.jl : $(JULIAHOME)/contrib/julia-config.j $(build_private_libdir)/%.$(SHLIB_EXT): $(build_private_libdir)/%.o @$(call PRINT_LINK, $(CXX) $(LDFLAGS) -shared $(fPIC) -L$(build_private_libdir) -L$(build_libdir) -L$(build_shlibdir) -o $@ $< \ $(if $(findstring -debug.$(SHLIB_EXT),$(notdir $@)),-ljulia-debug,-ljulia) \ + $(build_private_libdir)/libcompiler-rt.$(STATICLIB_EXT) \ $$([ $(OS) = WINNT ] && echo '' -lssp)) @$(INSTALL_NAME_CMD)$(notdir $@) $@ @$(DSYMUTIL) $@ @@ -226,7 +227,7 @@ $(build_depsbindir)/stringreplace: $(JULIAHOME)/contrib/stringreplace.c | $(buil JL_LIBS := julia julia-debug # private libraries, that are installed in $(prefix)/lib/julia -JL_PRIVATE_LIBS := ccalltest +JL_PRIVATE_LIBS := ccalltest compiler-rt ifeq ($(USE_GPL_LIBS), 1) JL_PRIVATE_LIBS += suitesparse_wrapper endif diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index b99561319c54f..ab0ce616bda2b 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -176,7 +176,7 @@ echo 'override LIBLAPACKNAME = $(LIBBLASNAME)' >> Make.user # libuv since its static lib is no longer included in the binaries # openlibm since we need it as a static library to work properly # utf8proc since its headers are not in the binary download -echo 'override DEP_LIBS = libuv utf8proc' >> Make.user +echo 'override DEP_LIBS = compiler-rt libuv utf8proc' >> Make.user if [ -n "$USEMSVC" ]; then # Openlibm doesn't build well with MSVC right now diff --git a/deps/Makefile b/deps/Makefile index 53953d2c4cfbb..4c51bb86e3dea 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -38,7 +38,7 @@ include $(SRCDIR)/tools/git-external.mk # prevent installing libs into usr/lib64 on opensuse unexport CONFIG_SITE -DEP_LIBS := +DEP_LIBS := compiler-rt ifeq ($(USE_GPL_LIBS), 1) DEP_LIBS += suitesparse-wrapper @@ -175,9 +175,10 @@ uninstall: $(addprefix uninstall-, $(DEP_LIBS_STAGED)) cleanall: $(addprefix clean-, $(DEP_LIBS)) distcleanall: $(addprefix distclean-, $(DEP_LIBS)) rm -rf $(build_prefix) -getall: get-llvm get-libuv get-pcre get-openlibm get-openspecfun get-dsfmt get-openblas get-lapack get-fftw get-suitesparse get-arpack get-unwind get-osxunwind get-gmp get-mpfr get-patchelf get-utf8proc get-objconv get-mbedtls get-libssh2 get-curl get-libgit2 +getall: get-llvm get-compiler-rt get-libuv get-pcre get-openlibm get-openspecfun get-dsfmt get-openblas get-lapack get-fftw get-suitesparse get-arpack get-unwind get-osxunwind get-gmp get-mpfr get-patchelf get-utf8proc get-objconv get-mbedtls get-libssh2 get-curl get-libgit2 include $(SRCDIR)/llvm.mk +include $(SRCDIR)/compiler-rt.mk include $(SRCDIR)/libuv.mk include $(SRCDIR)/pcre.mk include $(SRCDIR)/openlibm.mk diff --git a/deps/compiler-rt.mk b/deps/compiler-rt.mk new file mode 100644 index 0000000000000..5c05cba06cb1a --- /dev/null +++ b/deps/compiler-rt.mk @@ -0,0 +1,149 @@ +## +# In order to support fallbacks within llvm we need to support +# compiler-rt. This means linking sys.so against it and resolving +# symbols during JIT compilation (see jitlayers.cpp). For the latter part we need to create +# a .so that we can load, but compiler-rt only comes in a .a. +# +# There are several configurations to take into account. +# 1. STANDALONE_COMPILER_RT == 1 +# Download and install compiler_rt independently of llvm/clang. +# We still use the the LLVM_VER to pick the right compiler-rt. +# 2. STANDALONE_COMPILER_RT == 0 +# On LLVM >= 3.8 we can build compiler-rt along side LLVM. +# 3. USE_SYSTEM_LLVM == 1 && STANDALONE_COMPILER_RT == 0 +# Fallback definition. +# libclang_rt.builtins is distributed with clang and so +# we assume that USE_SYSTEM_LLVM == 1 means that clang is also +# installed. +# This is intended as a last ressort and if you use USE_SYSTEM_LLVM +# consider setting STANDALONE_COMPILER_RT:=1 +# +# Since we need the shared objectfile for JIT, there is no USE_SYSTEM_COMPILER_RT +## +COMPILER_RT_BUILDDIR := $(BUILDDIR)/compiler-rt-$(LLVM_VER) +COMPILER_RT_SRCDIR := $(SRCDIR)/srccache/compiler-rt-$(LLVM_VER) +COMPILER_RT_LIBFILE := libcompiler-rt.$(SHLIB_EXT) +COMPILER_RT_STATICLIBFILE := libcompiler-rt.$(STATICLIB_EXT) + +## +# The naming of the static file for compiler-rt is slightly weird +# and we have to figure out what the proper name is on the current +# platform. +# +# TODO: +# - Currently this build-mode is not supported on Windows. +## +CRT_OS := $(call lower,$(OS)) +CRT_LDFLAGS := +ifneq (,$(filter $(ARCH), powerpc64le ppc64le)) +CRT_ARCH := ppc +else ifneq (,$(filter $(ARCH), armv7l armv6l)) +CRT_ARCH := armhf +CRT_LDFLAGS += -Wl,--allow-multiple-definition +else +CRT_ARCH := $(call patsubst,i%86,i386,$(ARCH)) +CRT_LDFLAGS := +endif +CRT_STATIC_NAME := clang_rt.builtins-$(CRT_ARCH) + +ifeq ($(STANDALONE_COMPILER_RT),1) +COMPILER_RT_TAR := $(SRCDIR)/srccache/compiler-rt-$(LLVM_TAR_EXT) +else +COMPILER_RT_TAR := +ifeq ($(USE_SYSTEM_LLVM), 1) +CRT_VER:=$(word 1,$(subst svn-, ,$(shell llvm-config --version))) +CRT_DIR := $(shell llvm-config --libdir)/clang/$(CRT_VER)/lib/$(CRT_OS) +else ifeq ($(BUILD_LLVM_COMPILER_RT), 1) +CRT_DIR := $(LLVM_BUILDDIR_withtype)/lib/clang/$(LLVM_VER)/lib/$(CRT_OS) +$(CRT_DIR)/lib$(CRT_STATIC_NAME).$(STATICLIB_EXT): | $(LLVM_BUILDDIR_withtype)/build-compiled +else +$(error Compiler-rt is not available, please set STANDALONE_COMPILER_RT:=1) +endif +endif + +$(COMPILER_RT_SRCDIR)/source-extracted: | $(COMPILER_RT_TAR) + mkdir -p $(COMPILER_RT_SRCDIR) +ifneq ($(COMPILER_RT_TAR),) + $(JLCHECKSUM) $(COMPILER_RT_TAR) + $(TAR) -C $(COMPILER_RT_SRCDIR) --strip-components 1 -xf $(COMPILER_RT_TAR) +endif + echo 1 > $@ + +$(COMPILER_RT_BUILDDIR): + mkdir -p $@ +$(COMPILER_RT_BUILDDIR)/$(CRT_ARCH): + mkdir -p $@ + +ifeq ($(STANDALONE_COMPILER_RT),1) +$(COMPILER_RT_BUILDDIR)/Makefile: compiler-rt_standalone.mk | $(COMPILER_RT_BUILDDIR) + cp $< $@ +$(COMPILER_RT_BUILDDIR)/build-configured: $(COMPILER_RT_BUILDDIR)/Makefile | $(COMPILER_RT_BUILDDIR)/$(CRT_ARCH) + echo 1 > $@ + +$(COMPILER_RT_BUILDDIR)/build-compiled: | $(COMPILER_RT_SRCDIR)/source-extracted $(COMPILER_RT_BUILDDIR)/build-configured + $(MAKE) -C $(COMPILER_RT_BUILDDIR) \ + CC='$(CC)' \ + AR='$(AR)' \ + LIBFILE=$(COMPILER_RT_LIBFILE) \ + SLIBFILE=$(COMPILER_RT_STATICLIBFILE) \ + CRT_SRCDIR=$(COMPILER_RT_SRCDIR) \ + OS=$(CRT_OS) \ + ARCH=$(CRT_ARCH) \ + USE_CLANG=$(USE_CLANG) \ + fPIC=$(fPIC) all +$(COMPILER_RT_BUILDDIR)/$(COMPILER_RT_LIBFILE): | $(COMPILER_RT_BUILDDIR)/build-compiled +$(COMPILER_RT_BUILDDIR)/$(COMPILER_RT_STATICLIBFILE): | $(COMPILER_RT_BUILDDIR)/build-compiled +else +$(COMPILER_RT_BUILDDIR)/build-configured: $(COMPILER_RT_BUILDDIR) + echo 1 > $@ +# Use compiler-rt from the clang installation +$(COMPILER_RT_BUILDDIR)/$(COMPILER_RT_LIBFILE): $(CRT_DIR)/lib$(CRT_STATIC_NAME).$(STATICLIB_EXT) | $(COMPILER_RT_BUILDDIR)/build-configured + $(CC) $(LDFLAGS) -nostdlib $(CRT_LDFLAGS) -shared $(fPIC) -o $@ $(WHOLE_ARCHIVE) -L$(dir $<) -l$(CRT_STATIC_NAME) $(WHOLE_NOARCHIVE) +$(COMPILER_RT_BUILDDIR)/$(COMPILER_RT_STATICLIBFILE): $(CRT_DIR)/lib$(CRT_STATIC_NAME).$(STATICLIB_EXT) | $(COMPILER_RT_BUILDDIR)/build-configured + cp $^ $@ +endif + +ifneq ($(COMPILER_RT_TAR),) +ifeq ($(LLVM_COMPILER_RT_TAR),) +$(COMPILER_RT_TAR): | $(SRCDIR)/srccache + $(JLDOWNLOAD) $@ $(LLVM_SRC_URL)/$(notdir $@) +endif +endif + +get-compiler-rt: $(COMPILER_RT_TAR) +ifeq ($(STANDALONE_COMPILER_RT), 0) +extract-compiler-rt: #NONE +else +extract-compiler-rt: $(COMPILER_RT_SRCDIR)/source-extracted +endif + +$(build_shlibdir)/$(COMPILER_RT_LIBFILE): $(COMPILER_RT_BUILDDIR)/$(COMPILER_RT_LIBFILE) + mkdir -p $(dir $@) + cp $< $@ + @$(INSTALL_NAME_CMD)$(notdir $@) $@ + @$(DSYMUTIL) $@ + +$(build_private_libdir)/$(COMPILER_RT_STATICLIBFILE): $(COMPILER_RT_BUILDDIR)/$(COMPILER_RT_STATICLIBFILE) + mkdir -p $(dir $@) + cp $< $@ + +$(build_prefix)/manifest/compiler-rt: | $(build_prefix)/manifest + echo "compiler-rt-$(LLVM_VER)" > $@ + +check-compiler-rt: #NONE +fastcheck-compiler-rt: #NONE +configure-compiler-rt: $(COMPILER_RT_BUILDDIR)/build-configured +clean-compiler-rt: + rm -rf $(COMPILER_RT_BUILDDIR) +distclean-compiler-rt: clean-compiler-rt + rm -f $(COMPILER_RT_TAR) + rm -rf $(COMPILER_RT_SRCDIR) +uninstall-compiler-rt: + rm -f $(build_prefix)/manifest/compiler-rt + rm -f $(build_shlibdir)/$(COMPILER_RT_LIBFILE) + rm -f $(build_private_libdir)/$(COMPILER_RT_STATICLIBFILE) +distclean-compiler-rt clean-compiler-rt: | uninstall-compiler-rt + +compile-compiler-rt: $(COMPILER_RT_BUILDDIR)/$(COMPILER_RT_LIBFILE) +install-compiler-rt: $(build_shlibdir)/$(COMPILER_RT_LIBFILE) $(build_private_libdir)/$(COMPILER_RT_STATICLIBFILE) $(build_prefix)/manifest/compiler-rt + diff --git a/deps/compiler-rt_standalone.mk b/deps/compiler-rt_standalone.mk new file mode 100644 index 0000000000000..89e96d52e5dc1 --- /dev/null +++ b/deps/compiler-rt_standalone.mk @@ -0,0 +1,90 @@ +## +# This Makefile will be executed in $(BUILDDIR)/compiler-rt-$(LLVM_VER) +# Expected variables from the parent +# CRT_SRCDIR +# LIBFILE +# SLIBFILE +# OS (CRT_OS not JL_OS) +# ARCH (CRT_ARCH not JL_ARCH) +# USE_CLANG +# fPIC +## + +# The standalone compiler-rt build is inspired by +# https://github.com/ReservedField/arm-compiler-rt +SRCDIR := $(CRT_SRCDIR)/lib/builtins + +ifeq ($(ARCH), armhf) +ARCH_SRCDIR := $(SRCDIR)/arm +else ifeq ($(ARCH), aarch64) +ARCH_SRCDIR := $(SRCDIR)/arm64 +else +ARCH_SRCDIR := $(SRCDIR)/$(ARCH) +endif + +INCLUDES := -I$(SRCDIR) -I$(ARCH_SRCDIR) +# TODO(vchuravy) discover architecture flags +CRT_CFLAGS := $(CPPFLAGS) $(CFLAGS) -O2 -std=c11 \ + $(fPIC) $(INCLUDES) \ + -fno-builtin -ffreestanding +ifeq ($(USE_CLANG),1) +CRT_CFLAGS += -Wno-unknown-attributes -Wno-macro-redefined +endif + +## +# Blacklist a few files we don't want to deal with +## +MAKEFLAGS := --no-builtin-rules +BLACKLIST := atomic.o atomic_flag_clear.o atomic_flag_clear_explicit.o \ + atomic_flag_test_and_set.o atomic_flag_test_and_set_explicit.o \ + atomic_signal_fence.o atomic_thread_fence.o emutls.o + +CRT_LDFLAGS := +ifeq ($(ARCH),ppc) +BLACKLIST += saveFP.o restFP.o +else ifeq ($(ARCH), armhf) +CRT_LDFLAGS += -Wl,--allow-multiple-definition +endif + + +ifeq ($(OS),darwin) +# Which blacklist should we choose +BLACKLIST += $(shell cat $(SRCDIR)/Darwin-excludes/osx.txt) +else ifeq ($(OS), winnt) +CRT_CFLAGS += -D_WIN32 +endif + +CFILES := $(wildcard $(SRCDIR)/*.c) +GENERAL_OBJS1 := $(filter-out $(BLACKLIST), $(notdir $(CFILES:.c=.o))) + +ARCH_CFILES := $(wildcard $(ARCH_SRCDIR)/*.c) +ARCH_SFILES := $(wildcard $(ARCH_SRCDIR)/*.S) +ARCH_OBJS := $(filter-out $(BLACKLIST), $(notdir $(join $(ARCH_CFILES:.c=.o),$(ARCH_SFILES:.S=.o)))) + +GENERAL_OBJS := $(filter-out $(ARCH_OBJS), $(GENERAL_OBJS1)) + +OBJS := $(GENERAL_OBJS) $(ARCH_OBJS) + +%.o: $(SRCDIR)/%.c + $(CC) $(CRT_CFLAGS) -c $< -o $@ + +%.o: $(SRCDIR)/%.S + $(CC) $(CRT_CFLAGS) -c $< -o $@ + +%.o: $(ARCH_SRCDIR)/%.c + $(CC) $(CRT_CFLAGS) -c $< -o $@ + +%.o: $(ARCH_SRCDIR)/%.S + $(CC) $(CRT_CFLAGS) -c $< -o $@ + +$(LIBFILE): $(OBJS) + $(CC) $(CRT_LDFLAGS) $(CRT_CFLAGS) $(LDFLAGS) -shared -o $@ $^ + +$(SLIBFILE): $(OBJS) + $(AR) rs $@ $^ + +.PHONY: all +all: $(LIBFILE) $(SLIBFILE) +clean: $(OBJS) $(LIBFILE) $(SLIBFILE) + rm $^ + diff --git a/deps/llvm.mk b/deps/llvm.mk index 477ac6d9ed797..ba85dc6013156 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -59,12 +59,25 @@ ifeq ($(BUILD_LLDB),1) LLVM_LLDB_TAR:=$(SRCDIR)/srccache/lldb-$(LLVM_TAR_EXT) endif # BUILD_LLDB +# Decide when to build compiler-rt alongside LLVM. +ifeq ($(STANDALONE_COMPILER_RT),0) +BUILD_LLVM_COMPILER_RT:=1 +else ifeq ($(BUILD_LLVM_CLANG), 1) +BUILD_LLVM_COMPILER_RT:=1 +else +BUILD_LLVM_COMPILER_RT:=0 +endif + +ifeq ($(BUILD_LLVM_COMPILER_RT),1) +LLVM_COMPILER_RT_TAR:=$(SRCDIR)/srccache/compiler-rt-$(LLVM_TAR_EXT) +else +LLVM_COMPILER_RT_TAR:= +endif # BUILD_LLVM_COMPILER_RT + ifeq ($(BUILD_LLVM_CLANG),1) LLVM_CLANG_TAR:=$(SRCDIR)/srccache/cfe-$(LLVM_TAR_EXT) -LLVM_COMPILER_RT_TAR:=$(SRCDIR)/srccache/compiler-rt-$(LLVM_TAR_EXT) else LLVM_CLANG_TAR:= -LLVM_COMPILER_RT_TAR:= LLVM_LIBCXX_TAR:= endif # BUILD_LLVM_CLANG @@ -224,19 +237,30 @@ LLVM_CMAKE += -DCMAKE_C_FLAGS="$(LLVM_CPPFLAGS) $(LLVM_CFLAGS)" \ -DCMAKE_EXE_LINKER_FLAGS="$(LLVM_LDFLAGS)" \ -DCMAKE_SHARED_LINKER_FLAGS="$(LLVM_LDFLAGS)" +ifeq ($(BUILD_LLVM_COMPILER_RT),1) +ifneq ($(BUILD_LLVM_CLANG),1) +#block default building of Clang +LLVM_MFLAGS += OPTIONAL_PARALLEL_DIRS=compiler-rt +endif +else +ifeq ($(LLVM_VER_SHORT),$(filter $(LLVM_VER_SHORT),3.3 3.4 3.5 3.6 3.7)) +LLVM_CMAKE += -DLLVM_EXTERNAL_COMPILER_RT_BUILD=OFF +else +LLVM_CMAKE += -DLLVM_TOOL_COMPILER_RT_BUILD=OFF +endif +endif + ifeq ($(BUILD_LLVM_CLANG),1) LLVM_MFLAGS += OPTIONAL_PARALLEL_DIRS=clang else # block default building of Clang -LLVM_MFLAGS += OPTIONAL_PARALLEL_DIRS= ifeq ($(LLVM_VER_SHORT),$(filter $(LLVM_VER_SHORT),3.3 3.4 3.5 3.6 3.7)) LLVM_CMAKE += -DLLVM_EXTERNAL_CLANG_BUILD=OFF -LLVM_CMAKE += -DLLVM_EXTERNAL_COMPILER_RT_BUILD=OFF else LLVM_CMAKE += -DLLVM_TOOL_CLANG_BUILD=OFF -LLVM_CMAKE += -DLLVM_TOOL_COMPILER_RT_BUILD=OFF endif endif + ifeq ($(BUILD_LLDB),1) LLVM_MFLAGS += OPTIONAL_DIRS=lldb else @@ -384,15 +408,17 @@ ifneq ($(LLVM_LLDB_TAR),) $(TAR) -C $(LLVM_SRC_DIR)/tools/lldb --strip-components 1 -xf $(LLVM_LLDB_TAR) endif # LLVM_LLDB_TAR else # LLVM_VER +ifeq ($(BUILD_LLVM_COMPILER_RT),1) + ([ ! -d $(LLVM_SRC_DIR)/projects/compiler-rt ] && \ + git clone $(LLVM_GIT_URL_COMPILER_RT) $(LLVM_SRC_DIR)/projects/compiler-rt ) || \ + (cd $(LLVM_SRC_DIR)/projects/compiler-rt && \ + git pull --ff-only) +endif #BUILD_LLVM_COMPILER_RT ifeq ($(BUILD_LLVM_CLANG),1) ([ ! -d $(LLVM_SRC_DIR)/tools/clang ] && \ git clone $(LLVM_GIT_URL_CLANG) $(LLVM_SRC_DIR)/tools/clang ) || \ (cd $(LLVM_SRC_DIR)/tools/clang && \ git pull --ff-only) - ([ ! -d $(LLVM_SRC_DIR)/projects/compiler-rt ] && \ - git clone $(LLVM_GIT_URL_COMPILER_RT) $(LLVM_SRC_DIR)/projects/compiler-rt ) || \ - (cd $(LLVM_SRC_DIR)/projects/compiler-rt && \ - git pull --ff-only) ifneq ($(LLVM_GIT_VER_CLANG),) (cd $(LLVM_SRC_DIR)/tools/clang && \ git checkout $(LLVM_GIT_VER_CLANG)) @@ -506,7 +532,7 @@ ifeq ($(LLVM_VER),3.7.1) ifeq ($(BUILD_LLDB),1) $(eval $(call LLVM_PATCH,lldb-3.7.1)) endif -ifeq ($(BUILD_LLVM_CLANG),1) +ifeq ($(BUILD_LLVM_COMPILER_RT),1) $(eval $(call LLVM_PATCH,compiler-rt-3.7.1)) endif endif diff --git a/deps/tools/common.mk b/deps/tools/common.mk index cf92a637451fa..ed1ad574100b1 100644 --- a/deps/tools/common.mk +++ b/deps/tools/common.mk @@ -100,6 +100,7 @@ $(eval $(call dir_target,$(SRCDIR)/srccache)) upper = $(shell echo $1 | tr a-z A-Z) +lower = $(shell echo $1 | tr A-Z a-z) ## A rule for calling `make install` ## # example usage: From b0711f84d90603bbd73b012c15f72d16dd43544a Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 9 Jul 2016 03:27:41 +0900 Subject: [PATCH 2/3] Load a shared version of compiler-rt in jitlayers LLVM intrinsics either map to instructions or to functions in compiler-rt. If we can't find a symbol look into a shared version of compiler-rt and resolve the functions there. On Darwin we have to use a unmangled version of the function name. --- src/jitlayers.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 0c4ba6a9bafcc..19292c156aa9b 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -312,6 +312,29 @@ void NotifyDebugger(jit_code_entry *JITCodeEntry) } // ------------------------ END OF TEMPORARY COPY FROM LLVM ----------------- +// Resolve compiler-rt functions in the shared library that we created from compiler-rt +static uint64_t resolve_compiler_rt(const char *name) +{ + static void *compiler_rt_hdl = jl_load_dynamic_library_e("libcompiler-rt", + JL_RTLD_LOCAL | JL_RTLD_LAZY); + static const char *const prefix = "__"; + if (!compiler_rt_hdl) { + jl_printf(JL_STDERR, "WARNING: Unable to load compiler-rt\n"); + return 0; + } + if (strncmp(name, prefix, strlen(prefix)) != 0) + return 0; +#if defined(_OS_DARWIN_) + // jl_dlsym_e expects an unmangled 'C' symbol name, + // so iff we are on Darwin we strip the leading '_' off. + static const char *const mangled_prefix = "___"; + if (strncmp(name, mangled_prefix, strlen(mangled_prefix)) == 0) { + ++name; + } +#endif + return (uintptr_t)jl_dlsym_e(compiler_rt_hdl, name); +} + #if defined(_OS_LINUX_) // Resolve non-lock free atomic functions in the libatomic library. // This is the library that provides support for c11/c++11 atomic operations. @@ -548,6 +571,8 @@ void JuliaOJIT::addModule(std::unique_ptr M) if (uint64_t addr = resolve_atomic(Name.c_str())) return JL_SymbolInfo(addr, JITSymbolFlags::Exported); #endif + if (uint64_t addr = resolve_compiler_rt(Name.c_str())) + return JL_SymbolInfo(addr, JITSymbolFlags::Exported); // Return failure code return JL_SymbolInfo(nullptr); }, From 34de9840a8e3a60a626131d79b4756be2be31e43 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 3 Oct 2016 12:38:57 +0900 Subject: [PATCH 3/3] adds test for llvm intrinsics One most systems (except modern mac) these tests will fail if compiler-rt is not properly configured. --- test/llvmcall.jl | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/llvmcall.jl b/test/llvmcall.jl index 2b29c7e3d43ca..010bc9db5d6d7 100644 --- a/test/llvmcall.jl +++ b/test/llvmcall.jl @@ -154,6 +154,38 @@ function call_jl_errno() end call_jl_errno() +# Test support for llvm intrinsics. +llvm_convert(::Type{Float32}, val::Float16) = + llvmcall(("""declare float @llvm.convert.from.fp16.f32(i16)""", + """%2 = call float @llvm.convert.from.fp16.f32(i16 %0) + ret float %2"""), + Float32, Tuple{Int16}, reinterpret(Int16, val)) + +llvm_convert(::Type{Float64}, val::Float16) = + llvmcall(("""declare double @llvm.convert.from.fp16.f64(i16)""", + """%2 = call double @llvm.convert.from.fp16.f64(i16 %0) + ret double %2"""), + Float64, Tuple{Int16}, reinterpret(Int16, val)) + +llvm_convert(::Type{Float16}, val::Float32) = + reinterpret(Float16, + llvmcall(("""declare i16 @llvm.convert.to.fp16.f32(float)""", + """%2 = call i16 @llvm.convert.to.fp16.f32(float %0) + ret i16 %2"""), + Int16, Tuple{Float32}, val)) + +llvm_convert(::Type{Float16}, val::Float64) = + reinterpret(Float16, + llvmcall(("""declare i16 @llvm.convert.to.fp16.f64(double)""", + """%2 = call i16 @llvm.convert.to.fp16.f64(double %0) + ret i16 %2"""), + Int16, Tuple{Float64}, val)) + +@test llvm_convert(Float32, Float16(1.0)) === 1.0f0 +@test llvm_convert(Float64, Float16(3.0)) === 3.0 +@test llvm_convert(Float16, 1.0f0) === Float16(1.0) +@test llvm_convert(Float16, 3.0) === Float16(3.0) + module ObjLoadTest using Base: Test, llvmcall, @ccallable didcall = false