From f4f418c9f28188d0c80be56c28e6e08ff92354ee Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 26 Jun 2017 11:45:50 +0200
Subject: [PATCH] additional TO_NATIVE handlers, support c++ compilation for
 llvm, use node for ffi unwrap operation, convert scalars to vectors at native
 boundary, use proper nodes for interop messages

---
 .../truffle/r/engine/interop/RFunctionMR.java |  8 ++
 .../truffle/r/engine/interop/RLanguageMR.java |  8 ++
 .../truffle/r/engine/interop/RSymbolMR.java   | 10 +++
 .../ffi/impl/common/JavaUpCallsRFFIImpl.java  | 20 ++++-
 .../truffle/r/ffi/impl/common/RFFIUtils.java  | 10 ++-
 .../{TruffleUnwrap.java => UpCallUnwrap.java} | 51 +++++++++---
 .../r/ffi/impl/interop/NativePointer.java     |  1 -
 .../r/ffi/impl/interop/base/GlobResultMR.java |  4 +-
 .../impl/interop/base/ReadlinkResultMR.java   |  4 +-
 .../ffi/impl/interop/base/StrtolResultMR.java |  4 +-
 .../ffi/impl/interop/base/UnameResultMR.java  |  4 +-
 .../interop/pcre/CaptureNamesResultMR.java    |  9 ++-
 .../impl/interop/pcre/CompileResultMR.java    |  8 +-
 .../pkginit/SetDotSymbolValuesCallMR.java     |  6 +-
 .../r/ffi/impl/llvm/TruffleLLVM_Call.java     | 79 +++++++++++++++++--
 .../truffle/r/ffi/processor/FFIProcessor.java | 17 ++--
 .../nodes/builtin/base/DynLoadFunctions.java  |  1 +
 .../r/nodes/function/ArgumentMatcher.java     |  2 +-
 .../oracle/truffle/r/runtime/RDeparse.java    |  8 +-
 .../com/oracle/truffle/r/runtime/RError.java  |  1 +
 .../truffle/r/runtime/data/RLanguage.java     |  6 +-
 .../com/oracle/truffle/r/runtime/ffi/DLL.java |  4 +
 .../truffle/r/runtime/gnur/SEXPTYPE.java      | 12 ++-
 documentation/dev/truffle_llvm_ffi.md         |  2 +-
 mx.fastr/mx_fastr_compile.py                  | 25 +++---
 25 files changed, 236 insertions(+), 68 deletions(-)
 rename com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/{TruffleUnwrap.java => UpCallUnwrap.java} (58%)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
index 191e2ab1d1..027ad9d9dd 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -50,6 +51,13 @@ public class RFunctionMR {
         }
     }
 
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class RFunctionToNativeNode extends Node {
+        protected Object access(RFunction receiver) {
+            return new NativePointer(receiver);
+        }
+    }
+
     @Resolve(message = "EXECUTE")
     public abstract static class RFunctionExecuteNode extends Node {
         private static final FrameDescriptor emptyFrameDescriptor = FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<interop>", new FrameDescriptor("R interop frame"));
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
index 701d96249d..c0c338cfb7 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -60,6 +61,13 @@ public class RLanguageMR {
         }
     }
 
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class RLanguageToNativeNode extends Node {
+        protected Object access(RLanguage receiver) {
+            return new NativePointer(receiver);
+        }
+    }
+
     @Resolve(message = "READ")
     public abstract static class RLanguageReadNode extends Node {
         @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
index fcb0c4e66c..3c00139f86 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
@@ -24,12 +24,22 @@ package com.oracle.truffle.r.engine.interop;
 
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 
 @MessageResolution(receiverType = RSymbol.class)
 public class RSymbolMR {
+
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class RSymbolToNativeNode extends Node {
+        protected Object access(RSymbol receiver) {
+            return new NativePointer(receiver);
+        }
+    }
+
     @CanResolve
     public abstract static class RSymbolCheck extends Node {
 
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 f1fd7172b7..c9a4c1e477 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
@@ -768,6 +768,24 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return result;
     }
 
+    private static final Object processResult(Object value) {
+        if (value instanceof Integer) {
+            int v = (int) value;
+            return RDataFactory.createIntVector(new int[]{v}, RRuntime.isNA(v));
+        } else if (value instanceof Double) {
+            double v = (double) value;
+            return RDataFactory.createDoubleVector(new double[]{v}, RRuntime.isNA(v));
+        } else if (value instanceof Byte) {
+            byte v = (byte) value;
+            return RDataFactory.createLogicalVector(new byte[]{v}, RRuntime.isNA(v));
+        } else if (value instanceof String) {
+            String v = (String) value;
+            return RDataFactory.createStringVector(new String[]{v}, RRuntime.isNA(v));
+        } else {
+            return value;
+        }
+    }
+
     @Override
     public Object Rf_eval(Object expr, Object env) {
         guarantee(env instanceof REnvironment);
@@ -794,7 +812,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
             // just return value
             result = expr;
         }
-        return result;
+        return processResult(result);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java
index eba39a0222..08bbe61e9e 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java
@@ -27,6 +27,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.file.Path;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.ffi.impl.nodes.FFIUpCallRootNode;
 import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
@@ -192,10 +193,12 @@ public class RFFIUtils {
 
     // Error handling
     static RuntimeException unimplemented() {
+        CompilerDirectives.transferToInterpreter();
         return unimplemented("");
     }
 
     static RuntimeException unimplemented(String message) {
+        CompilerDirectives.transferToInterpreter();
         throw RInternalError.unimplemented(message);
     }
 
@@ -205,15 +208,18 @@ public class RFFIUtils {
 
     static void guarantee(boolean condition, String message) {
         if (!condition) {
+            CompilerDirectives.transferToInterpreter();
             unimplemented(message);
         }
     }
 
     public static <T> T guaranteeInstanceOf(Object x, Class<T> clazz) {
         if (x == null) {
-            guarantee(false, "unexpected type: null instead of " + clazz.getSimpleName());
+            CompilerDirectives.transferToInterpreter();
+            unimplemented("unexpected type: null instead of " + clazz.getSimpleName());
         } else if (!clazz.isInstance(x)) {
-            guarantee(false, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName());
+            CompilerDirectives.transferToInterpreter();
+            unimplemented("unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName());
         }
         return clazz.cast(x);
     }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TruffleUnwrap.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java
similarity index 58%
rename from com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TruffleUnwrap.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java
index f26f5152db..feac93f6af 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TruffleUnwrap.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java
@@ -22,14 +22,25 @@
  */
 package com.oracle.truffle.r.ffi.impl.common;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
-public class TruffleUnwrap {
+public final class UpCallUnwrap extends Node {
+
+    @Child private Node isBoxed;
+    @Child private Node unbox;
+    private final BranchProfile nativePointerProfile = isLLVM() ? BranchProfile.create() : null;
+
     /**
      * There are three possibilities as enumerated below.
      * <ul>
@@ -44,25 +55,47 @@ public class TruffleUnwrap {
      * to do.</li>
      * </ul>
      */
-    public static Object unwrap(Object x) {
+    public Object unwrap(Object x) {
         if (x instanceof RTruffleObject) {
             return x;
         } else if (x instanceof TruffleObject) {
-            Object r = JavaInterop.unbox((TruffleObject) x);
-            if (r == null) {
+            if (isBoxed == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                isBoxed = insert(Message.IS_BOXED.createNode());
+            }
+            TruffleObject xTo = (TruffleObject) x;
+            if (ForeignAccess.sendIsBoxed(isBoxed, xTo)) {
+                if (unbox == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    unbox = insert(Message.UNBOX.createNode());
+                }
+                try {
+                    return ForeignAccess.sendUnbox(unbox, xTo);
+                } catch (UnsupportedMessageException e) {
+                    throw RInternalError.shouldNotReachHere(e, "UNBOX message fails after IS_BOXED=true");
+                }
+            } else {
                 // didn't UNBOX or really was null (e.g. null String)
-                if (RFFIFactory.getType() == RFFIFactory.Type.LLVM) {
-                    TruffleObject xto = (TruffleObject) x;
-                    TruffleObject xtoObject = NativePointer.check(xto);
+                if (isLLVM()) {
+                    nativePointerProfile.enter();
+                    TruffleObject xtoObject = checkNativePointer(xTo);
                     if (xtoObject != null) {
                         return xtoObject;
                     }
                 }
+                return x;
             }
-            return r;
         } else {
             return x;
         }
     }
 
+    private static boolean isLLVM() {
+        return RFFIFactory.getType() == RFFIFactory.Type.LLVM;
+    }
+
+    @TruffleBoundary
+    private static TruffleObject checkNativePointer(TruffleObject xto) {
+        return NativePointer.check(xto);
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointer.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointer.java
index 46d4ce53d4..4202b55d79 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointer.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointer.java
@@ -113,5 +113,4 @@ public class NativePointer implements TruffleObject {
     protected long asPointerImpl() {
         return System.identityHashCode(object);
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResultMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResultMR.java
index 1f40f124dd..2c7d26e85e 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResultMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResultMR.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.ffi.impl.interop.base;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
@@ -48,10 +47,9 @@ public class GlobResultMR {
 
     @Resolve(message = "EXECUTE")
     public abstract static class BaseGlobResultCallbackExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, GlobResult receiver, Object[] arguments) {
+        protected Object access(GlobResult receiver, Object[] arguments) {
             receiver.addPath((String) arguments[0]);
             return receiver;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResultMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResultMR.java
index 59af7efb20..56d518440a 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResultMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResultMR.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.ffi.impl.interop.base;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
@@ -48,10 +47,9 @@ public class ReadlinkResultMR {
 
     @Resolve(message = "EXECUTE")
     public abstract static class BaseReadlinkResultCallbackExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, ReadlinkResult receiver, Object[] arguments) {
+        protected Object access(ReadlinkResult receiver, Object[] arguments) {
             receiver.setResult((String) arguments[0], (int) arguments[1]);
             return receiver;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResultMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResultMR.java
index 7f427019eb..0b30658738 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResultMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResultMR.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.ffi.impl.interop.base;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
@@ -48,10 +47,9 @@ public class StrtolResultMR {
 
     @Resolve(message = "EXECUTE")
     public abstract static class BaseStrtolResultCallbackExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, StrtolResult receiver, Object[] arguments) {
+        protected Object access(StrtolResult receiver, Object[] arguments) {
             receiver.setResult((long) arguments[0], (int) arguments[1]);
             return receiver;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResultMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResultMR.java
index 49c62b47ce..e63607fbad 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResultMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResultMR.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.ffi.impl.interop.base;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
@@ -48,10 +47,9 @@ public class UnameResultMR {
 
     @Resolve(message = "EXECUTE")
     public abstract static class BaseUnameResultCallbackExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, UnameResult receiver, Object[] arguments) {
+        protected Object access(UnameResult receiver, Object[] arguments) {
             receiver.setResult((String) arguments[0], (String) arguments[1], (String) arguments[2], (String) arguments[3], (String) arguments[4]);
             return receiver;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResultMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResultMR.java
index 3b3f915183..c57a4ef1c2 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResultMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResultMR.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.r.runtime.RInternalError;
 
 @MessageResolution(receiverType = CaptureNamesResult.class)
@@ -52,14 +53,18 @@ public class CaptureNamesResultMR {
 
     @Resolve(message = "EXECUTE")
     public abstract static class CaptureNamesCallbackExecute extends Node {
+
+        @Child private Node isNullNode = Message.IS_NULL.createNode();
+        @Child private Node unboxNode = Message.UNBOX.createNode();
+
         protected Object access(@SuppressWarnings("unused") VirtualFrame frame, CaptureNamesResult receiver, Object[] arguments) {
             try {
                 Object arg1 = arguments[1];
                 if (arg1 instanceof TruffleObject) {
-                    if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) {
+                    if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) arg1)) {
                         arg1 = null;
                     } else {
-                        arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1);
+                        arg1 = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) arg1);
                     }
                 }
                 receiver.addName((int) arguments[0], (String) arg1);
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResultMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResultMR.java
index 1c98d1a352..ec104be372 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResultMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResultMR.java
@@ -52,14 +52,18 @@ public class CompileResultMR {
 
     @Resolve(message = "EXECUTE")
     public abstract static class ResultCallbackExecute extends Node {
+
+        @Child private Node isNullNode = Message.IS_NULL.createNode();
+        @Child private Node unboxNode = Message.UNBOX.createNode();
+
         protected Object access(@SuppressWarnings("unused") VirtualFrame frame, CompileResult receiver, Object[] arguments) {
             try {
                 Object arg1 = arguments[1];
                 if (arg1 instanceof TruffleObject) {
-                    if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) {
+                    if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) arg1)) {
                         arg1 = null;
                     } else {
-                        arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1);
+                        arg1 = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) arg1);
                     }
                 }
                 receiver.set((long) arguments[0], (String) arg1, (int) arguments[2]);
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCallMR.java
index 7b9482207f..2af43470af 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCallMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCallMR.java
@@ -25,15 +25,17 @@ package com.oracle.truffle.r.ffi.impl.interop.pkginit;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.ffi.impl.common.TruffleUnwrap;
+import com.oracle.truffle.r.ffi.impl.common.UpCallUnwrap;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 
 @MessageResolution(receiverType = SetDotSymbolValuesCall.class)
 public class SetDotSymbolValuesCallMR {
     @Resolve(message = "EXECUTE")
     public abstract static class SetDotSymbolValuesCallExecute extends Node {
+        @Child private UpCallUnwrap unwrap = new UpCallUnwrap();
+
         protected java.lang.Object access(SetDotSymbolValuesCall receiver, Object[] arguments) {
-            return receiver.pkgInitUpCalls.setDotSymbolValues((DLLInfo) arguments[0], (String) TruffleUnwrap.unwrap(arguments[1]), arguments[2], (int) arguments[3]);
+            return receiver.pkgInitUpCalls.setDotSymbolValues((DLLInfo) arguments[0], (String) unwrap.unwrap(arguments[1]), arguments[2], (int) arguments[3]);
         }
     }
 
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java
index 692d85abf0..e1f80e8b46 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java
@@ -22,24 +22,32 @@
  */
 package com.oracle.truffle.r.ffi.impl.llvm;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
-import com.oracle.truffle.r.ffi.impl.common.TruffleUnwrap;
+import com.oracle.truffle.r.ffi.impl.common.UpCallUnwrap;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_CallFactory.ToNativeNodeGen;
 import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_CallFactory.TruffleLLVM_InvokeCallNodeGen;
 import com.oracle.truffle.r.ffi.impl.llvm.upcalls.BytesToNativeCharArrayCall;
 import com.oracle.truffle.r.ffi.impl.llvm.upcalls.CharSXPToNativeArrayCall;
 import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks;
 import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RScalar;
+import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
@@ -137,33 +145,92 @@ final class TruffleLLVM_Call implements CallRFFI {
         }
     }
 
+    abstract static class ToNativeNode extends Node {
+
+        public abstract Object execute(Object value);
+
+        @Specialization
+        protected static Object convert(int value) {
+            return RDataFactory.createIntVector(new int[]{value}, RRuntime.isNA(value));
+        }
+
+        @Specialization
+        protected static Object convert(double value) {
+            return RDataFactory.createDoubleVector(new double[]{value}, RRuntime.isNA(value));
+        }
+
+        @Specialization
+        protected static Object convert(RVector<?> value) {
+            return value;
+        }
+
+        @Specialization
+        protected static Object convert(RScalar value) {
+            return value;
+        }
+
+        @Specialization
+        protected static Object convert(byte value) {
+            return RDataFactory.createLogicalVector(new byte[]{value}, RRuntime.isNA(value));
+        }
+
+        @Specialization
+        protected static Object convert(String value) {
+            return RDataFactory.createStringVector(new String[]{value}, RRuntime.isNA(value));
+        }
+
+        @Fallback
+        protected static Object convert(Object value) {
+            return value;
+        }
+    }
+
     @ImportStatic({Message.class})
     public abstract static class TruffleLLVM_InvokeCallNode extends InvokeCallNode {
+
+        @Child private UpCallUnwrap unwrap;
         private final boolean isVoid;
 
         protected TruffleLLVM_InvokeCallNode(boolean isVoid) {
             this.isVoid = isVoid;
+            this.unwrap = isVoid ? null : new UpCallUnwrap();
+        }
+
+        protected static ToNativeNode[] createConvertNodes(int length) {
+            ToNativeNode[] result = new ToNativeNode[length];
+            for (int i = 0; i < length; i++) {
+                result[i] = ToNativeNodeGen.create();
+            }
+            return result;
         }
 
         @Specialization(guards = {"cachedNativeCallInfo.name.equals(nativeCallInfo.name)", "args.length == cachedArgCount"})
         protected Object invokeCallCached(NativeCallInfo nativeCallInfo, Object[] args,
                         @SuppressWarnings("unused") @Cached("nativeCallInfo") NativeCallInfo cachedNativeCallInfo,
                         @SuppressWarnings("unused") @Cached("argCount(args)") int cachedArgCount,
-                        @Cached("createMessageNode(args)") Node cachedMessageNode) {
-            return doInvoke(cachedMessageNode, nativeCallInfo, args);
+                        @Cached("createMessageNode(args)") Node cachedMessageNode,
+                        @Cached("createConvertNodes(cachedArgCount)") ToNativeNode[] convert) {
+            return doInvoke(cachedMessageNode, nativeCallInfo, args, convert);
         }
 
         @Specialization(replaces = "invokeCallCached")
+        @TruffleBoundary
         protected Object invokeCallNormal(NativeCallInfo nativeCallInfo, Object[] args) {
-            return doInvoke(Message.createExecute(args.length).createNode(), nativeCallInfo, args);
+            return doInvoke(Message.createExecute(args.length).createNode(), nativeCallInfo, args, null);
         }
 
-        private Object doInvoke(Node messageNode, NativeCallInfo nativeCallInfo, Object[] args) {
+        @ExplodeLoop
+        private Object doInvoke(Node messageNode, NativeCallInfo nativeCallInfo, Object[] args, ToNativeNode[] convert) {
             boolean isNullSetting = RContext.getRForeignAccessFactory().setIsNull(false);
             try {
+                if (convert != null) {
+                    for (int i = 0; i < convert.length; i++) {
+                        args[i] = convert[i].execute(args[i]);
+                    }
+                }
                 Object result = ForeignAccess.sendExecute(messageNode, nativeCallInfo.address.asTruffleObject(), args);
                 if (!isVoid) {
-                    result = TruffleUnwrap.unwrap(result);
+                    result = unwrap.unwrap(result);
                 }
                 return result;
             } catch (InteropException t) {
diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
index b7614ecb6d..ed6a6b96dd 100644
--- a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
+++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
@@ -189,7 +189,6 @@ public final class FFIProcessor extends AbstractProcessor {
         w.append("    public ForeignAccess getForeignAccess() {\n");
         w.append("        return ").append(callName).append("MRForeign.ACCESS;\n");
         w.append("    }\n");
-        w.append('\n');
         w.append("}\n");
         w.close();
     }
@@ -203,6 +202,7 @@ public final class FFIProcessor extends AbstractProcessor {
         StringBuilder arguments = new StringBuilder();
         boolean usesUnwrap = false;
 
+        // process arguments first to see if unwrap is necessary
         int lparams = params.size();
         for (int i = 0; i < lparams; i++) {
             String is = Integer.toString(i);
@@ -214,7 +214,7 @@ public final class FFIProcessor extends AbstractProcessor {
             }
             if (isScalar) {
                 usesUnwrap = true;
-                arguments.append("unwrap(");
+                arguments.append("unwrap.unwrap(");
             }
             arguments.append("arguments[").append(is).append("]");
             if (isScalar) {
@@ -229,19 +229,21 @@ public final class FFIProcessor extends AbstractProcessor {
         Writer w = fileObj.openWriter();
         w.append("// GENERATED; DO NOT EDIT\n");
         w.append("package ").append("com.oracle.truffle.r.ffi.impl.upcalls").append(";\n\n");
-        if (usesUnwrap) {
-            w.append("import static com.oracle.truffle.r.ffi.impl.common.TruffleUnwrap.unwrap;\n");
-        }
         w.append("import com.oracle.truffle.api.interop.MessageResolution;\n");
         w.append("import com.oracle.truffle.api.interop.Resolve;\n");
         w.append("import com.oracle.truffle.api.nodes.Node;\n");
-        w.append("import com.oracle.truffle.r.ffi.impl.interop.NativePointer;\n");
+        if (usesUnwrap) {
+            w.append("import com.oracle.truffle.r.ffi.impl.common.UpCallUnwrap;\n");
+        }
         w.append("// Checkstyle: stop method name check\n\n");
 
         w.append("@MessageResolution(receiverType = ").append(name).append("Call.class)\n");
         w.append("public class ").append(callName).append("MR {\n");
         w.append("    @Resolve(message = \"EXECUTE\")\n");
         w.append("    public abstract static class ").append(callName).append("Execute extends Node {\n");
+        if (usesUnwrap) {
+            w.append("\n        @Child private UpCallUnwrap unwrap = new UpCallUnwrap();\n\n");
+        }
         w.append("        protected ").append(returnType).append(" access(").append(callName).append(" receiver, ");
         if (params.size() == 0) {
             w.append("@SuppressWarnings(\"unused\") ");
@@ -262,8 +264,6 @@ public final class FFIProcessor extends AbstractProcessor {
         w.append("            return true;\n");
         w.append("        }\n");
         w.append("    }\n");
-        w.append("\n");
-
         w.append("}\n");
         w.close();
 
@@ -386,5 +386,4 @@ public final class FFIProcessor extends AbstractProcessor {
         string.flush();
         return e.getMessage() + "\r\n" + string.toString();
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
index 1156a95d30..c871aa49bd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
@@ -76,6 +76,7 @@ public class DynLoadFunctions {
                 DLLInfo dllInfo = loadPackageDLLNode.execute(lib, local, now);
                 return dllInfo.toRList();
             } catch (DLLException ex) {
+                ex.printStackTrace();
                 throw error(ex);
             }
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index e71f6f3450..9a43c2012e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -466,7 +466,7 @@ public class ArgumentMatcher {
      * method updates any wrapped ReadVariableNode to just return missing values without raising an
      * error.
      *
-     * @see com.oracle.truffle.r.nodes.function.PromiseNode.InlineVarArgsNode
+     * see {@code com.oracle.truffle.r.nodes.function.PromiseNode.InlineVarArgsNode}
      */
     @SuppressWarnings("javadoc")
     private static RNode updateInlinedArg(RNode node) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 7eb1a77dd4..4ae8e1bc79 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -58,6 +58,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
@@ -781,7 +782,12 @@ public class RDeparse {
                 }
                 append(')');
             } else if (value instanceof RExternalPtr) {
-                append("<pointer: 0x").append(Long.toHexString(((RExternalPtr) value).getAddr().asAddress())).append('>');
+                SymbolHandle handle = ((RExternalPtr) value).getAddr();
+                if (handle.isLong()) {
+                    append("<pointer: 0x").append(Long.toHexString(handle.asAddress())).append('>');
+                } else {
+                    append("<pointer: external ptr 0x").append(Long.toHexString(System.identityHashCode(handle.asTruffleObject()))).append('>');
+                }
             } else if (value instanceof REnvironment) {
                 append("<environment>");
             } else if (value instanceof REmpty) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 9311149b78..38b91d235c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -66,6 +66,7 @@ public final class RError extends RuntimeException implements TruffleException {
         private final RError.Message msg;
         @CompilationFinal(dimensions = 1) private final Object[] args;
 
+        @TruffleBoundary
         protected RErrorException(Throwable cause, RError.Message msg, Object[] args) {
             super(RErrorHandling.formatMessage(msg, args), cause);
             this.msg = msg;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index 60e4849da5..aa46ff8da7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  *
  */
 @ValueType
-public class RLanguage extends RSharingAttributeStorage implements RAbstractContainer {
+public final class RLanguage extends RSharingAttributeStorage implements RAbstractContainer {
 
     /*
      * Used for RLanguage construction from separate AST components.
@@ -193,7 +193,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
     }
 
     @Override
-    public final void setNames(RStringVector newNames) {
+    public void setNames(RStringVector newNames) {
         if (list == null) {
             /* See getNames */
             RContext.getRRuntimeASTAccess().setNames(this, newNames);
@@ -241,7 +241,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
         return String.format("RLanguage(rep=%s)", getRep());
     }
 
-    public final RPairList getPairListInternal() {
+    public RPairList getPairListInternal() {
         return this.list;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
index a0e0619811..f690726257 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
@@ -366,6 +366,10 @@ public class DLL {
             }
         }
 
+        public boolean isLong() {
+            return value instanceof Long;
+        }
+
         public TruffleObject asTruffleObject() {
             if (value instanceof TruffleObject) {
                 return (TruffleObject) value;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
index 9aa6e79d34..146301963b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
@@ -11,9 +11,6 @@
  */
 package com.oracle.truffle.r.runtime.gnur;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -98,21 +95,22 @@ public enum SEXPTYPE {
     public final int code;
     public final Class<?>[] fastRClasses;
 
+    private static final SEXPTYPE[] codeMap = new SEXPTYPE[501];
+
     SEXPTYPE(int code, Class<?>... fastRClasses) {
         this.code = code;
         this.fastRClasses = fastRClasses;
     }
 
-    private static final Map<Integer, SEXPTYPE> codeMap = new HashMap<>();
-
     static {
         for (SEXPTYPE type : SEXPTYPE.values()) {
-            SEXPTYPE.codeMap.put(type.code, type);
+            assert type.code >= 0 && type.code < codeMap.length;
+            codeMap[type.code] = type;
         }
     }
 
     public static SEXPTYPE mapInt(int type) {
-        return codeMap.get(type);
+        return codeMap[type];
     }
 
     /**
diff --git a/documentation/dev/truffle_llvm_ffi.md b/documentation/dev/truffle_llvm_ffi.md
index 59e06668ff..0ae668fb01 100644
--- a/documentation/dev/truffle_llvm_ffi.md
+++ b/documentation/dev/truffle_llvm_ffi.md
@@ -18,7 +18,7 @@ On Mac OS, these can be installed with MacPorts (recommended) or Brew. Having in
 
 The above definitions assume a MacPorts installation.
 
-On Linux, the installation is system  dependent, but once installed, set the same environment variables.
+On Linux, the installation is system dependent, but once installed, set the same environment variables.
 
 ## Building Sulong
 The `sulong` repository must be cloned to a sibling directory of `fastr` and built:
diff --git a/mx.fastr/mx_fastr_compile.py b/mx.fastr/mx_fastr_compile.py
index 11cc17e123..7619494a14 100644
--- a/mx.fastr/mx_fastr_compile.py
+++ b/mx.fastr/mx_fastr_compile.py
@@ -78,7 +78,7 @@ def _analyze_args(args, dragonEgg=False):
     Result is an instance of AnalyzedArgs:
     '''
     compile_args = []
-    emit_llvm_args = []
+    emit_llvm_args = ['-g']
     llvm_ir_file_ext = '.bc'
     if not dragonEgg:
         emit_llvm_args.append('-emit-llvm')
@@ -171,15 +171,22 @@ def cpp(args):
     sulong = _sulong()
     if sulong:
         analyzed_args = _analyze_args(args)
-        if _is_linux():
-            rc = sulong.dragonEggGPP(analyzed_args.compile_args)
-        elif _is_darwin():
-            rc = sulong.compileWithClangPP(analyzed_args.compile_args)
-            if rc == 0:
-                if analyzed_args.llvm_ir_file:
-                    rc = sulong.compileWithClangPP(analyzed_args.emit_llvm_args)
+        rc = 0
+        if analyzed_args.is_link:
+            rc = _create_bc_lib(args)
         else:
-            mx.abort('unsupported platform')
+            if _is_linux():
+                rc = sulong.dragonEggGPP(analyzed_args.compile_args)
+            elif _is_darwin():
+                rc = sulong.compileWithClangPP(analyzed_args.compile_args)
+                if rc == 0:
+                    if analyzed_args.llvm_ir_file:
+                        rc = sulong.compileWithClangPP(analyzed_args.emit_llvm_args)
+            else:
+                mx.abort('unsupported platform')
+        if rc == 0 and not analyzed_args.is_link and analyzed_args.llvm_ir_file:
+            rc = _mem2reg_opt(analyzed_args.llvm_ir_file)
+            _fake_obj(analyzed_args.llvm_ir_file.replace('.bc', '.o'))
     else:
         compiler = 'g++'
         rc = mx.run([compiler] + args, nonZeroIsFatal=False)
-- 
GitLab