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 191e2ab1d193921a84a6671dcc5c7472f333bc34..027ad9d9dd1f50fd87fa712acfdc1dc20166c2e7 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 701d96249d63f209a1badcbea2db36949b3948f6..c0c338cfb7ec3716e457b23fe35a561d69d11684 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 fcb0c4e66cd4b677849fa704b41711a4931b2fca..3c00139f868ba1148f9f7d281eb70956feb519d9 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 f1fd7172b7038e094154ef986cb38c00fba33d2e..c9a4c1e4776290b1b95b9c6eca453a1e66c995c0 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 eba39a0222d81f587b472704186d5d52e8a7f59e..08bbe61e9ef6c174d80e5205c1b8062f406f6bb0 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 f26f5152db3f4a515f2c9e32c9a5dc980408a2f7..feac93f6afefa4645328330d64fcb10c8949d214 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 46d4ce53d48725a0c2399b2086aba4772cfad13e..4202b55d79b54e8f96eaf3149a1a7ddfe2b296f7 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 1f40f124ddcf7bf9c6be3f6c5140df4250381a1f..2c7d26e85ebb434f93a49538445f719cba5a7375 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 59af7efb20e6dd2ae3990d0e90aa4c04442be195..56d518440ae3062513a00edd065a6da31272278e 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 7f427019eb26d27068ca1a3fd09c61e6f2871d56..0b306587388575e332cb810dcfcb9bb583ae2f19 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 49c62b47ce81e8fa1de6e555423e369f0b4187b6..e63607fbadda495659e53bb855afef2f44343882 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 3b3f9151830d370f9d55d5bd33e7b9e57373302f..c57a4ef1c2197f84982373ba98aaf3edcde1158b 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 1c98d1a352c6fe1beb2d0e5b43ec23dabd1fe31b..ec104be3726d0e89594296895dbe3f81f5159d3d 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 7b9482207fa504a3e86288b59800d9f49f73abd6..2af43470aff66f8bcf04a47c3debca8249cda764 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 692d85abf04ec3aca5f71cd3bc0bccf64771ea58..e1f80e8b460a9c9fbbd7d3403d019b72a2c1a86e 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 b7614ecb6d359bcfe478b85748375f9bfa0d0dd7..ed6a6b96dd9e86e2bee7ca4b629c17badd010fc1 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 1156a95d30ae2872f2e2c89d9a130509b324f968..c871aa49bd28cc1d851c34f8d76cc0cf85a6103f 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 e71f6f3450bfa319bdfb8b4c787e025781c61200..9a43c2012e071fe9df7ebb8467af21edcc09f818 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 7eb1a77dd4eb3d2d2921cb6c096c59c94a6603c6..4ae8e1bc7916132740624742e253acf270df06fd 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 9311149b78f661ada3e36a033fb248298896b249..38b91d235c8a737322a7ca897d8b6ae3a78dade8 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 60e4849da510533cf94c597f48145f165e6bbf45..aa46ff8da7eb3ac5072177291084578551044f86 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 a0e06198112092166d231e27ba70f0ebb5179ec2..f690726257af4ad477cadd3f826ca937536cf730 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 9aa6e79d3426372eac3b29810ce4fb1e4b684449..146301963b7405eaf7e9c06776afcd32f287cfea 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 59e06668ffdc48b9cafbef3984126d16f85d0ddf..0ae668fb01b09f1d97a02e595be1391b9d50f598 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 11cc17e1237b3ca740154544ac593446b41a3b95..7619494a14a06927e38bd058ca0336f9e6f99621 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)