From ad075c58ac5b224ba1a34541c1ab570419e75559 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 8 Feb 2017 11:50:14 -0800
Subject: [PATCH] rffi: annotate upcall paramaters that are C strings in the R
 FFI

---
 .../r/nodes/ffi/FFIUpCallRootNode.java        |  2 +-
 .../truffle/r/nodes/ffi/RFFIUpCallMethod.java |  2 +-
 .../truffle/r/runtime/ffi/RFFICstring.java    | 37 +++++++++++++++++++
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java | 16 ++++----
 .../test/tools/RFFIUpCallMethodGenerate.java  | 13 +++++--
 5 files changed, 56 insertions(+), 14 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
index 24b0336f26..6cd1f9fe0e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 public final class FFIUpCallRootNode extends RootNode {
-    private static RootCallTarget[] rootCallTargets = new RootCallTarget[RFFIUpCallMethod.values().length];
+    private static final RootCallTarget[] rootCallTargets = new RootCallTarget[RFFIUpCallMethod.values().length];
 
     @Child private FFIUpCallNode theFFIUpCallNode;
     private final int numArgs;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index 280484b54e..3074783733 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -152,7 +152,7 @@ public enum RFFIUpCallMethod {
 
     public static void main(String[] args) {
         for (RFFIUpCallMethod f : RFFIUpCallMethod.values()) {
-            System.out.printf("#define %s %d\n", f.name(), f.ordinal());
+            System.out.printf("#define %s_x %d\n", f.name(), f.ordinal());
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java
new file mode 100644
index 0000000000..c8dbee39e1
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Tags an upcall argument as being (on the native side) a C string.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface RFFICstring {
+
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
index f396021354..b8f0ecf89d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
@@ -63,13 +63,13 @@ public interface StdUpCallsRFFI {
 
     Object Rf_asChar(Object x);
 
-    Object Rf_mkCharLenCE(Object bytes, int len, int encoding);
+    Object Rf_mkCharLenCE(@RFFICstring Object bytes, int len, int encoding);
 
     Object Rf_cons(Object car, Object cdr);
 
     void Rf_defineVar(Object symbolArg, Object value, Object envArg);
 
-    Object R_do_MAKE_CLASS(Object clazz);
+    Object R_do_MAKE_CLASS(@RFFICstring Object clazz);
 
     /**
      * WARNING: argument order reversed from Rf_findVarInFrame!
@@ -84,9 +84,9 @@ public interface StdUpCallsRFFI {
 
     void Rf_setAttrib(Object obj, Object name, Object val);
 
-    int Rf_inherits(Object x, Object clazz);
+    int Rf_inherits(@RFFICstring Object x, Object clazz);
 
-    Object Rf_install(Object name);
+    Object Rf_install(@RFFICstring Object name);
 
     Object Rf_lengthgets(Object x, int newSize);
 
@@ -96,11 +96,11 @@ public interface StdUpCallsRFFI {
 
     Object Rf_PairToVectorList(Object x);
 
-    void Rf_error(Object msg);
+    void Rf_error(@RFFICstring Object msg);
 
-    void Rf_warning(Object msg);
+    void Rf_warning(@RFFICstring Object msg);
 
-    void Rf_warningcall(Object call, Object msg);
+    void Rf_warningcall(Object call, @RFFICstring Object msg);
 
     Object Rf_allocateVector(int mode, int n);
 
@@ -212,7 +212,7 @@ public interface StdUpCallsRFFI {
 
     int IS_S4_OBJECT(Object x);
 
-    void Rprintf(Object message);
+    void Rprintf(@RFFICstring Object message);
 
     void GetRNGstate();
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
index e9a7a0a5dc..60881ee7aa 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
@@ -22,11 +22,14 @@
  */
 package com.oracle.truffle.r.test.tools;
 
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedType;
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.Comparator;
 
 import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
+import com.oracle.truffle.r.runtime.ffi.RFFICstring;
 import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 /**
@@ -55,11 +58,12 @@ public class RFFIUpCallMethodGenerate {
 
     private static String getNFISignature(Method m) {
         Class<?>[] paramTypes = m.getParameterTypes();
+        Annotation[][] annotations = m.getParameterAnnotations();
         StringBuilder sb = new StringBuilder();
         sb.append('(');
         for (int i = 0; i < paramTypes.length; i++) {
             Class<?> paramType = paramTypes[i];
-            String nfiParam = nfiParamName(paramType);
+            String nfiParam = nfiParamName(paramType, annotations[i]);
             sb.append(nfiParam);
             if (i != paramTypes.length - 1) {
                 sb.append(", ");
@@ -67,15 +71,16 @@ public class RFFIUpCallMethodGenerate {
         }
         sb.append(')');
         sb.append(" : ");
-        sb.append(nfiParamName(m.getReturnType()));
+        sb.append(nfiParamName(m.getReturnType(), new Annotation[0]));
         return sb.toString();
     }
 
-    static String nfiParamName(Class<?> paramType) {
+    static String nfiParamName(Class<?> paramType, Annotation[] annotation) {
         String paramName = paramType.getSimpleName();
+        Class<?> klass = annotation.length == 0 ? null : annotation[0].annotationType();
         switch (paramName) {
             case "Object":
-                return "object";
+                return klass == null ? "object" : "pointer";
             case "int":
                 return "sint32";
             case "double":
-- 
GitLab