diff --git a/ci.hocon b/ci.hocon index f274b102ffab633d0266a478af40497b0283a00e..4c97461fc140d1de63becdf5323cd0dcb8e08801 100644 --- a/ci.hocon +++ b/ci.hocon @@ -146,7 +146,7 @@ gateTestLinuxLLVM : ${common} ${requireGCC} { environment : { TZDIR: "/usr/share/zoneinfo" FASTR_RFFI : "llvm" - FASTR_LLVM_HOME : "$DRAGONEGG_LLVM/bin" + FASTR_LLVM_TOOLS : "$DRAGONEGG_LLVM/bin" FASTR_LLVM_GFORTRAN_LLVM_AS : "$DRAGONEGG_LLVM/bin/llvm-as" FASTR_LLVM_GFORTRAN : "$DRAGONEGG_GCC/bin/gfortran" FASTR_LLVM_DRAGONEGG : "$DRAGONEGG_GCC/lib/dragonegg.so" @@ -192,7 +192,7 @@ gateTestDarwinLLVM: ${common} ${darwinEnvironment} ${requireGCC} { environment : { FASTR_RFFI : "llvm" - FASTR_LLVM_HOME : "$DRAGONEGG_LLVM/bin" + FASTR_LLVM_TOOLS : "$DRAGONEGG_LLVM/bin" FASTR_LLVM_GFORTRAN_LLVM_AS : "$DRAGONEGG_LLVM/bin/llvm-as" FASTR_LLVM_GFORTRAN : "$DRAGONEGG_GCC/bin/gfortran" FASTR_LLVM_DRAGONEGG : "$DRAGONEGG_GCC/lib/dragonegg.so" diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java index b219056de01d517ed77b33cb88872150d40ad8b1..3f524ddfaa00cb6378e28c51cd28b8cc372c246a 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java @@ -906,9 +906,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } /** - * Helper function for {@code R_TopLevelExec} which is similar to {@code R_TryEval} except that - * a C function is invoked (in the native layer) instead of an R expression. assert: this is - * ONLY called from R_TopLevelExec prior to calling C function. + * Helper function for {@code R_TopLevelExec} which is similar to {@code R_TryEval} except that a C + * function is invoked (in the native layer) instead of an R expression. assert: this is ONLY called + * from R_TopLevelExec prior to calling C function. */ @Override @TruffleBoundary @@ -1966,8 +1966,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { @Override public Object INTEGER(Object x) { // also handles LOGICAL - assert x instanceof RIntVector || x instanceof RLogicalVector || x == RNull.instance; - return VectorWrapper.get(guaranteeVectorOrNull(x, RVector.class)); + assert x instanceof RIntVector || x instanceof RLogicalVector || x == RNull.instance || x instanceof RUnboundValue : "" + x + ":" + x.getClass(); + if (x instanceof RUnboundValue) { + return VectorWrapper.get((RUnboundValue) x); + } else { + return VectorWrapper.get(guaranteeVectorOrNull(x, RVector.class)); + } } @Override diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java index 19ebc60087b43aa9e717c0a82e3ff6f7027e67be..41e4198d9ef720c68d5c497b6d8664eb0fad1dd7 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java @@ -24,9 +24,8 @@ * A collection of types and {@link com.oracle.truffle.api.interop.MessageResolution} classes that * support the implementations. * - * See {@link com.oracle.truffle.r.ffi.impl.interop.base} and - * {@link com.oracle.truffle.r.ffi.impl.interop.pcre} for similar classes specific to the - * {@link com.oracle.truffle.r.runtime.ffi.BaseRFFI} and + * See com.oracle.truffle.r.ffi.impl.interop.base and com.oracle.truffle.r.ffi.impl.interop.pcre for + * similar classes specific to the {@link com.oracle.truffle.r.runtime.ffi.BaseRFFI} and * {@link com.oracle.truffle.r.runtime.ffi.PCRERFFI} interfaces. */ package com.oracle.truffle.r.ffi.impl.interop; diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java index c48bb4886ac118825e99dd3017349142a521d17d..87b27410abff7d047bf27118a6a733e1f38727dd 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java @@ -88,7 +88,7 @@ final class TruffleLLVM_Context extends RFFIContext { TruffleLLVM_NativeDLL.NativeDLOpenRootNode.create().getCallTarget().call(libzPath, false, true); // String curlPath = LibPaths.getBuiltinLibPath("curl.4"); - String curlPath = "libcurl.dylib"; + String curlPath = "libcurl.so"; TruffleLLVM_NativeDLL.NativeDLOpenRootNode.create().getCallTarget().call(curlPath, false, true); } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java index 568b273a72b0de402d520a02798a4940a67f643b..a1ba42a71381bb0441198c4b94366fab04470b62 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java @@ -65,10 +65,10 @@ import com.oracle.truffle.r.runtime.ffi.DLLRFFI; public class TruffleLLVM_DLL implements DLLRFFI { static class ContextStateImpl implements RContext.ContextState { /** - * When a new {@link RContext} is created we have to re-parse the libR modules, - * unfortunately, as there is no way to propagate the LLVM state created in the initial - * context. TODO when do we really need to do this? This is certainly too early for contexts - * that will not invoke LLVM code (e.g. most unit tests) + * When a new {@link RContext} is created we have to re-parse the libR modules, unfortunately, as + * there is no way to propagate the LLVM state created in the initial context. TODO when do we + * really need to do this? This is certainly too early for contexts that will not invoke LLVM code + * (e.g. most unit tests) */ @Override public ContextState initialize(RContext context) { @@ -167,10 +167,9 @@ public class TruffleLLVM_DLL implements DLLRFFI { @Child private TruffleLLVM_NativeDLL.TruffleLLVM_NativeDLOpen nativeDLLOpenNode; /** - * If a library is enabled for LLVM, the IR for all the modules is retrieved and analyzed. - * Every exported symbol in the module added to the parseStatus map for the current - * {@link RContext}. This allows {@code dlsym} to definitively locate any symbol, even if - * the IR has not been parsed yet. + * If a library is enabled for LLVM, the IR for all the modules is retrieved and analyzed. Every + * exported symbol in the module added to the parseStatus map for the current {@link RContext}. This + * allows {@code dlsym} to definitively locate any symbol, even if the IR has not been parsed yet. */ @Override public Object execute(String path, boolean local, boolean now) { @@ -199,6 +198,7 @@ public class TruffleLLVM_DLL implements DLLRFFI { sb.append(t.getMessage()); t = t.getCause(); } + ex.printStackTrace(); throw new UnsatisfiedLinkError(sb.toString()); } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java index d6a1f4b67f5d8153fc01a3d1bf6abb775ef4b247..ad6eed382d4b3c7322dc5fbefc3d4fddc11ec70c 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java @@ -40,6 +40,7 @@ import com.oracle.truffle.r.runtime.data.RDouble; import com.oracle.truffle.r.runtime.data.RInteger; import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RScalar; +import com.oracle.truffle.r.runtime.data.RString; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL.CEntry; @@ -108,6 +109,8 @@ public class TruffleLLVM_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl { return RInteger.valueOf((int) x); } else if (x instanceof Byte) { return RLogical.valueOf((byte) x); + } else if (x instanceof String) { + return RString.valueOf((String) x); } else { throw RInternalError.shouldNotReachHere(); } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java index 115713fabac830b3415f1a145e1abde714fb6d5a..e6d51dbe8cf31523fe99b9882a4e1a984b8691ac 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java @@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RScalarList; import com.oracle.truffle.r.runtime.data.RScalarVector; import com.oracle.truffle.r.runtime.data.RSequence; +import com.oracle.truffle.r.runtime.data.RString; public abstract class FFIWrapNode extends Node { @@ -63,6 +64,11 @@ public abstract class FFIWrapNode extends Node { return wrap(RDataFactory.createStringVectorFromScalar(value)); } + @Specialization + protected static Object wrap(RString value) { + return wrap(RDataFactory.createStringVectorFromScalar(value.getValue())); + } + @Specialization protected static Object wrap(RInteger value) { return wrap(RDataFactory.createIntVectorFromScalar(value.getValue())); diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile index f6176fd2d0aa5d3f78ee729487b1dfa2c7a38ecf..e22efe39d81235211df630677b8d9cae7424ded4 100644 --- a/com.oracle.truffle.r.native/fficall/Makefile +++ b/com.oracle.truffle.r.native/fficall/Makefile @@ -57,7 +57,7 @@ ifeq ($(FASTR_RFFI),managed) else ifeq ($(OS_NAME),Darwin) $(DYLIB_LD) $(DYLIB_LDFLAGS) -Wl,-rpath,@loader_path/ -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -ldl -lRblas -lRlapack -lpcre -lz $(VERSION_FLAGS) -ifneq ($(FASTR_RFFI),llvm) +ifneq ($(FASTR_RFFI),llvm) install_name_tool -change libRblas.dylib @rpath/libRblas.dylib $(R_LIB) install_name_tool -change libRlapack.dylib @rpath/libRlapack.dylib $(R_LIB) install_name_tool -id @rpath/libR.dylib $(R_LIB) @@ -80,6 +80,12 @@ fficall.done: common.done else ifeq ($(FASTR_RFFI),llvm) +ifndef FASTR_LLVM_TOOLS +ifdef FASTR_LLVM_FOR_DRAGONEGG_HOME +export FASTR_LLVM_TOOLS = $(FASTR_LLVM_FOR_DRAGONEGG_HOME)/bin +$(info FASTR_LLVM_TOOLS set to $(FASTR_LLVM_TOOLS)) +endif +endif fficall.done: common.done $(MAKE) -C src/truffle_llvm all touch fficall.done @@ -90,7 +96,7 @@ endif #nfi endif #managed common.done: - $(MAKE) -C src/common all + $(MAKE) -C src/common all touch common.done clean: @@ -109,4 +115,3 @@ endif rm -rf $(R_LIB) rm -rf fficall.done rm -rf common.done - diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-c++ b/com.oracle.truffle.r.native/llvm_tools/llvm-c++ index 54c0ef43ed8c4701d9eaf01ee64bbbf3f95fb47c..a20027b69b0706e7e8ea764dca9271f8442f786d 100755 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-c++ +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-c++ @@ -38,12 +38,13 @@ then create_bc_lib $@ $extraObj else llvm_tool=clang++ - #get_llvm_tool - #runit $llvm_tool_bin $llvm_args - echo "Clang args: $llvm_args" - clang --version - clang $llvm_args - + get_llvm_tool + unamestr=`uname` + if [[ "$unamestr" == 'Linux' ]]; then + llvm_args="-stdlib=libc++ -I/usr/include/libcxxabi $llvm_args" + fi + runit $llvm_tool_bin $llvm_args + # the llvm_ir_file is empty if the result is sent to stdout if [ -n "$llvm_ir_file" ]; then mem2reg_opt diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-cc b/com.oracle.truffle.r.native/llvm_tools/llvm-cc index 38f1d992b0933632ddd94fe6ca86c4bebf2d3793..1ab1691aaa7a61d610b9dafb4d52df6e7878bb27 100755 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-cc +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-cc @@ -37,10 +37,9 @@ then fi create_bc_lib $@ $extraObj else - #llvm_tool=clang - #get_llvm_tool - #runit $llvm_tool_bin $llvm_args - runit clang $llvm_args + llvm_tool=clang + get_llvm_tool + runit $llvm_tool_bin $llvm_args # the llvm_ir_file is empty if the result is sent to stdout if [ -n "$llvm_ir_file" ]; then mem2reg_opt diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-helper b/com.oracle.truffle.r.native/llvm_tools/llvm-helper index 102283405c134948efaed29826cca35f680b82e3..88d41309ff27faa09043129217f78819e6363615 100644 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-helper +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-helper @@ -62,7 +62,7 @@ function analyze_args() { is_link=0 llvm_ir_file="" - + while [[ $# -gt 0 ]] do llvm_args+="$1 " @@ -96,9 +96,9 @@ function analyze_args() { # path to tool (defaults to plain ${llvm_tool}, assumed to be on the PATH) function get_llvm_tool() { - if [ -n "${FASTR_LLVM_HOME}" ] + if [ -n "${FASTR_LLVM_TOOLS}" ] then - llvm_tool_bin=${FASTR_LLVM_HOME}/${llvm_tool} + llvm_tool_bin=${FASTR_LLVM_TOOLS}/${llvm_tool} else llvm_tool_uc=`echo ${llvm_tool} | tr /a-z/ /A-Z/ | tr /+/ /P/` x=FASTR_LLVM_${llvm_tool_uc} @@ -111,12 +111,10 @@ function get_llvm_tool() { fi } - function mem2reg_opt() { - #llvm_tool="opt" - #get_llvm_tool - #runit ${llvm_tool_bin} -mem2reg $llvm_ir_file -o ${llvm_ir_file}.opt - runit opt -mem2reg $llvm_ir_file -o ${llvm_ir_file}.opt + llvm_tool="opt" + get_llvm_tool + runit ${llvm_tool_bin} -mem2reg $llvm_ir_file -o ${llvm_ir_file}.opt rc=$? if [ $rc -eq 0 ] then @@ -127,7 +125,7 @@ function mem2reg_opt() { function fake_obj() { f=`basename $llvm_ir_file` d=`dirname $llvm_ir_file` - runit touch ${d}/${f%%.*}.o + runit touch ${d}/${f%%.*}.o } # Input: all the arguments to the original command line @@ -161,20 +159,18 @@ function create_bc_lib() { # it will be the pathname, which we will reduce to a module name on input in FastR # link the bitcode files into a single one using llvm-link before zipping it - #llvm_tool=llvm-link - #get_llvm_tool - #runit $llvm_tool_bin $bcfiles -o $lib.bc - echo "Linking $lib.bc with $bcfiles" - runit llvm-link $bcfiles -o $lib.bc + llvm_tool=llvm-link + get_llvm_tool + runit $llvm_tool_bin $bcfiles -o $lib.bc runit zip -r $lib $lib.bc rm $lib.bc } -# It appends objects constituting a static library to the list of extra object files. +# It appends objects constituting a static library to the list of extra object files. # This list is maintained in $R_PACKAGE_DIR/libobjects and is later read in llvm-cc and -# llvm-c++ to append the object files from the list to other objects when making -# the package dynamic library. This mechanism is a workaround for the fact that the llvm -# linker does not support linking to static libraries, as the standard linker does +# llvm-c++ to append the object files from the list to other objects when making +# the package dynamic library. This mechanism is a workaround for the fact that the llvm +# linker does not support linking to static libraries, as the standard linker does # through the -l and -L options. function create_bc_archive() { @@ -187,12 +183,12 @@ function create_bc_archive() { archname=$1 arargs="rcs $archname " shift - + archObjCSVtmp="archived_objects.tmp" archObjCSV="archived_objects.csv" exportedObjCSV="exported_objects.csv" > $archObjCSV - + while [[ $# -gt 0 ]] do case $1 in @@ -215,10 +211,10 @@ function create_bc_archive() { sort -d --field-separator=' ' --key=1 $archObjCSVtmp > $archObjCSV - # Create the archive (via llvm-ar) that is then used to read the symbol table via llvm-nm. + # Create the archive (via llvm-ar) that is then used to read the symbol table via llvm-nm. # The symbol table allows for selecting a set of objects exporting unique symbols. llvm-ar $arargs - + # This command extracts a set of objects from the archive that do not export duplicate symbols llvm-nm -print-file-name $archname | grep "\-\-\-\-" | awk -F ' ' '{print $1" "$4}' | sort -d --field-separator=' ' --key=2 -u | awk -F ':' '{print $2}' | sort -d -u > $exportedObjCSV diff --git a/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm b/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm index d9a5864d77d6d0115a2d5ab58a250f6e39a18487..c4972785f1b97ace17efcf41e7d9d36f203e2910 100644 --- a/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm +++ b/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm @@ -8,6 +8,11 @@ d i CXX = $(R_HOME)/bin/llvm-c++ . +/^CXX11 =/ +d +i +CXX11 = $(R_HOME)/bin/llvm-c++ +. /^FC =/ d i diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java index e3be9c96ea3e37a40fd7df240ff2bfbe95fa3640..86be2ec8d8dc4bbef684c3233c4357079a9180d3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java @@ -48,8 +48,8 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra private Object car = RNull.instance; private Object cdr = RNull.instance; /** - * Externally, i.e., when serialized, this is either a SYMSXP ({@link RSymbol}) or an - * {@link RNull}. Internally it may take on other, non-null, values. + * Externally, i.e., when serialized, this is either a SYMSXP ({@link RSymbol}) or an {@link RNull}. + * Internally it may take on other, non-null, values. */ private Object tag = RNull.instance; @@ -390,6 +390,9 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra @Override public RPairList next() { + if (plt instanceof RLanguage) { + plt = ((RLanguage) plt).getPairList(); + } assert plt instanceof RPairList; RPairList curr = (RPairList) plt; plt = curr.cdr; diff --git a/documentation/dev/truffle_llvm_ffi.md b/documentation/dev/truffle_llvm_ffi.md index c0cbb908c0ec77477037ff3386533ea9fb05fa80..bff8c9114a7b862b5262873317c8832898a08391 100644 --- a/documentation/dev/truffle_llvm_ffi.md +++ b/documentation/dev/truffle_llvm_ffi.md @@ -65,7 +65,7 @@ FastR necessarily provides very fine control over the versions of the llvm tools The tools needed to build FastR and to install packages containing native code are `clang`, `clang++` and `opt`. Precisely which versions of these tools are used can be controlled in two ways. -1. Set `FASTR_LLVM_HOME` to a directory containing the tools, named as above. N.B. Since MacPorts uses names of the form `clang-mp-3.8` this requires using symbolic links. E.g. create a directory called, say, `llvm-3.8` and symlink to the MacPorts binary, e.g., `clang-mp-3.8` and name it as `clang`. Then set `FASTR_LLVM_HOME` to that directory. +1. Set `FASTR_LLVM_TOOLS` to a directory containing the tools, named as above. N.B. Since MacPorts uses names of the form `clang-mp-3.8` this requires using symbolic links. E.g. create a directory called, say, `llvm-3.8` and symlink to the MacPorts binary, e.g., `clang-mp-3.8` and name it as `clang`. Then set `FASTR_LLVM_TOOLS` to that directory. 2. Set `FASTR_LLVM_CLANG`, `FASTR_LLVM_CLANGPP` and `FASTR_LLVM_OPT` to the actual binary images, e.g., `export FASTR_LLVM_CLANG=/opt/local/bin/clang-mp-3.8`. Not all versions of the llvm tools can compile FastR. `clang-3.2` that is downloaded as part of the DragonEgg build is known to work. This currently is placed in `sulong/cache/tools/llvm/bin` by the DragonEgg build and, again, can be copied to a shared location. `clang-3.8` and `clang-4.0` are known not to work, but `clang-3.9` does.