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 a6ee9008c16eae9a81e4704f44217ed89ed3ed3f..ce76b9870d2ec52f83cae85f83445971d7ac9573 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,7 +25,7 @@ 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.UpCallUnwrap; +import com.oracle.truffle.r.ffi.impl.upcalls.UpCallUnwrap; import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; @MessageResolution(receiverType = SetDotSymbolValuesCall.class) 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 42d3e293c6d2bfacf3ca147241961a59faf19293..cb72d9283acff60d5c7563922f843e324f2caad5 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 @@ -34,12 +34,12 @@ 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.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.UpCallUnwrap; import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ATTRIB.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ATTRIB.java new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java index 3f675ef3eca28cb4df8dd056b4731c6127405d6e..0bce74744dc62ef55b09ffbd5568067ce7084672 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java @@ -28,6 +28,11 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CADDRNodeGen; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CADRNodeGen; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CARNodeGen; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CDDRNodeGen; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CDRNodeGen; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode; import com.oracle.truffle.r.runtime.RInternalError; @@ -83,6 +88,10 @@ public final class ListAccessNodes { protected Object car(@SuppressWarnings("unused") Object obj) { throw RInternalError.unimplemented("CAR only works on pair lists, language objects, argument lists, and symbols"); } + + public static CARNode create() { + return CARNodeGen.create(); + } } @TypeSystemReference(RTypes.class) @@ -123,7 +132,10 @@ public final class ListAccessNodes { @Fallback protected Object cdr(@SuppressWarnings("unused") Object obj) { throw RInternalError.unimplemented("CDR only works on pair lists, language objects, and argument lists"); + } + public static CDRNode create() { + return CDRNodeGen.create(); } } @@ -143,6 +155,10 @@ public final class ListAccessNodes { protected Object cadr(@SuppressWarnings("unused") Object obj) { throw RInternalError.unimplemented("CADR only works on pair lists and language objects"); } + + public static CADRNode create() { + return CADRNodeGen.create(); + } } @TypeSystemReference(RTypes.class) @@ -161,6 +177,10 @@ public final class ListAccessNodes { protected Object caddr(@SuppressWarnings("unused") Object obj) { throw RInternalError.unimplemented("CADDR only works on pair lists and language objects"); } + + public static CADDRNode create() { + return CADDRNodeGen.create(); + } } @TypeSystemReference(RTypes.class) @@ -179,7 +199,10 @@ public final class ListAccessNodes { @Fallback protected Object cddr(@SuppressWarnings("unused") Object obj) { throw RInternalError.unimplemented("CDDR only works on pair lists and language objects"); + } + public static CDDRNode create() { + return CDDRNodeGen.create(); } } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java index 918352aba3a2b7ee6660ef9c5ad7fd41e976f82a..b4e1b39d568d6586c7c2ebcb9ae251cb0039956a 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java @@ -26,6 +26,10 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.LENGTHNodeGen; +import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoNewObjectNodeGen; +import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoSlotAssignNodeGen; +import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoSlotNodeGen; import com.oracle.truffle.r.nodes.access.AccessSlotNode; import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen; import com.oracle.truffle.r.nodes.access.UpdateSlotNode; @@ -102,6 +106,10 @@ public final class MiscNodes { CompilerDirectives.transferToInterpreter(); throw RError.error(RError.SHOW_CALLER2, RError.Message.LENGTH_MISAPPLIED, SEXPTYPE.gnuRTypeForObject(obj).name()); } + + public static LENGTHNode create() { + return LENGTHNodeGen.create(); + } } @TypeSystemReference(RTypes.class) @@ -122,6 +130,10 @@ public final class MiscNodes { Object doSlot(@SuppressWarnings("unused") Object o, Object name) { throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name()); } + + public static RDoSlotNode create() { + return RDoSlotNodeGen.create(); + } } @TypeSystemReference(RTypes.class) @@ -142,6 +154,10 @@ public final class MiscNodes { Object doSlot(@SuppressWarnings("unused") Object o, Object name, @SuppressWarnings("unused") Object value) { throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name()); } + + public static RDoSlotAssignNode create() { + return RDoSlotAssignNodeGen.create(); + } } @TypeSystemReference(RTypes.class) @@ -157,6 +173,10 @@ public final class MiscNodes { Object doNewObject(Object classDef) { return newObjectNode.execute(classDef); } + + public static RDoNewObjectNode create() { + return RDoNewObjectNodeGen.create(); + } } @TypeSystemReference(RTypes.class) diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/AbstractDowncallForeign.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/AbstractDowncallForeign.java new file mode 100644 index 0000000000000000000000000000000000000000..dcb23038b56cc7afc6ea9a8f5b14103efcbdcd2c --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/AbstractDowncallForeign.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2017, 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.ffi.impl.upcalls; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.interop.ForeignAccess.Factory; +import com.oracle.truffle.api.interop.ForeignAccess.Factory26; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.nodes.RootNode; + +public abstract class AbstractDowncallForeign implements Factory26, Factory { + @Override + public CallTarget accessIsNull() { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } + + @Override + public CallTarget accessIsExecutable() { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(true)); + } + + @Override + public CallTarget accessIsBoxed() { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } + + @Override + public CallTarget accessHasSize() { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } + + @Override + public CallTarget accessGetSize() { + return null; + } + + @Override + public CallTarget accessUnbox() { + return null; + } + + @Override + public CallTarget accessRead() { + return null; + } + + @Override + public CallTarget accessWrite() { + return null; + } + + @Override + public CallTarget accessInvoke(int argumentsLength) { + return null; + } + + @Override + public CallTarget accessNew(int argumentsLength) { + return null; + } + + @Override + public CallTarget accessKeyInfo() { + return null; + } + + @Override + public CallTarget accessKeys() { + return null; + } + + @Override + public CallTarget accessIsPointer() { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } + + @Override + public CallTarget accessAsPointer() { + return null; + } + + @Override + public CallTarget accessToNative() { + return null; + } + + @Override + public CallTarget accessMessage(Message unknown) { + return null; + } +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java index 6226535d30b75aa31f47e75d6d361b23f2eb8cb8..b569971b0250b159f2b9275e4b4157c5a17a0201 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java @@ -22,7 +22,19 @@ */ package com.oracle.truffle.r.ffi.impl.upcalls; +import com.oracle.truffle.r.ffi.impl.nodes.ATTRIB; +import com.oracle.truffle.r.ffi.impl.nodes.AsCharNode; +import com.oracle.truffle.r.ffi.impl.nodes.AsIntegerNode; +import com.oracle.truffle.r.ffi.impl.nodes.AsLogicalNode; +import com.oracle.truffle.r.ffi.impl.nodes.AsRealNode; +import com.oracle.truffle.r.ffi.impl.nodes.CoerceVectorNode; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CADDRNode; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CADRNode; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CARNode; +import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CDRNode; +import com.oracle.truffle.r.ffi.impl.nodes.MiscNodes.LENGTHNode; import com.oracle.truffle.r.ffi.processor.RFFICstring; +import com.oracle.truffle.r.ffi.processor.RFFIUpCallNode; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RIntVector; @@ -60,14 +72,19 @@ public interface StdUpCallsRFFI { RStringVector Rf_ScalarString(Object value); + @RFFIUpCallNode(AsIntegerNode.class) int Rf_asInteger(Object x); + @RFFIUpCallNode(AsRealNode.class) double Rf_asReal(Object x); + @RFFIUpCallNode(AsLogicalNode.class) int Rf_asLogical(Object x); + @RFFIUpCallNode(AsCharNode.class) Object Rf_asChar(Object x); + @RFFIUpCallNode(CoerceVectorNode.class) Object Rf_coerceVector(Object x, int mode); Object Rf_mkCharLenCE(@RFFICstring(convert = false) Object bytes, int len, int encoding); @@ -89,6 +106,7 @@ public interface StdUpCallsRFFI { Object Rf_findVarInFrame3(Object envArg, Object symbolArg, int doGet); + @RFFIUpCallNode(ATTRIB.class) Object ATTRIB(Object obj); Object Rf_getAttrib(Object obj, Object name); @@ -127,6 +145,7 @@ public interface StdUpCallsRFFI { int Rf_ncols(Object x); + @RFFIUpCallNode(LENGTHNode.class) int LENGTH(Object x); int /* void */ SET_STRING_ELT(Object x, long i, Object v); @@ -163,12 +182,16 @@ public interface StdUpCallsRFFI { Object TAG(Object e); + @RFFIUpCallNode(CARNode.class) Object CAR(Object e); + @RFFIUpCallNode(CDRNode.class) Object CDR(Object e); + @RFFIUpCallNode(CADRNode.class) Object CADR(Object e); + @RFFIUpCallNode(CADDRNode.class) Object CADDR(Object e); Object CDDR(Object e); diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/UpCallUnwrap.java similarity index 98% rename from com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/UpCallUnwrap.java index cbaa000be27e05852271586265fab913b3d6bba5..65f03708e12c29ecfbe6aa08b61dbdc51f519731 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/UpCallUnwrap.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.ffi.impl.common; +package com.oracle.truffle.r.ffi.impl.upcalls; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 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 355660afa1b638fc4c773423a0a20d8d31711a2c..b40b966fbe08676165a700c175e0fcb90abe95b5 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 @@ -40,6 +40,7 @@ import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; +import javax.lang.model.type.MirroredTypeException; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Types; @@ -157,55 +158,27 @@ public final class FFIProcessor extends AbstractProcessor { for (int i = 0; i < methods.length; i++) { ExecutableElement m = methods[i]; generateCallClass(m); - generateMessageClass(m); } } private void generateCallClass(ExecutableElement m) throws IOException { - String name = m.getSimpleName().toString(); - String callName = name + "Call"; - JavaFileObject fileObj = processingEnv.getFiler().createSourceFile("com.oracle.truffle.r.ffi.impl.upcalls." + callName); - 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"); - w.append("import com.oracle.truffle.api.interop.ForeignAccess;\n"); - w.append("import com.oracle.truffle.api.interop.TruffleObject;\n"); - w.append("import com.oracle.truffle.r.runtime.data.RTruffleObject;\n"); - w.append("// Checkstyle: stop method name check\n\n"); - w.append("public final class ").append(callName).append(" implements RTruffleObject {\n"); - w.append('\n'); - w.append(" public final UpCallsRFFI upCallsImpl;\n"); - w.append('\n'); - w.append(" protected ").append(callName).append("(UpCallsRFFI upCallsImpl) {\n"); - w.append(" this.upCallsImpl = upCallsImpl;\n"); - w.append(" }\n"); - w.append('\n'); - w.append(" public static boolean isInstance(TruffleObject value) {\n"); - w.append(" return value instanceof ").append(callName).append(";\n"); - w.append(" }\n"); - w.append('\n'); - - w.append(" @Override\n"); - w.append(" public ForeignAccess getForeignAccess() {\n"); - w.append(" return ").append(callName).append("MRForeign.ACCESS;\n"); - w.append(" }\n"); - w.append("}\n"); - w.close(); - } - - private void generateMessageClass(ExecutableElement m) throws IOException { - String name = m.getSimpleName().toString(); - String callName = name + "Call"; - String returnType = getTypeName(m.getReturnType()); + RFFIUpCallNode nodeAnnotation = m.getAnnotation(RFFIUpCallNode.class); + String node = null; + if (nodeAnnotation != null) { + try { + nodeAnnotation.value(); + } catch (MirroredTypeException e) { + node = ((TypeElement) processingEnv.getTypeUtils().asElement(e.getTypeMirror())).getQualifiedName().toString(); + } + } + // process arguments first to see if unwrap is necessary List<? extends VariableElement> params = m.getParameters(); - 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); + int unwrapCount = 0; + for (int i = 0; i < params.size(); i++) { + if (i != 0) { + arguments.append(", "); + } String paramTypeName = getTypeName(params.get(i).asType()); boolean isScalar = true; boolean needCast = !paramTypeName.equals("java.lang.Object"); @@ -213,60 +186,91 @@ public final class FFIProcessor extends AbstractProcessor { arguments.append('(').append(paramTypeName).append(") "); } if (isScalar) { - usesUnwrap = true; - arguments.append("unwrap.unwrap("); + arguments.append("unwrap").append(unwrapCount).append(".unwrap("); + unwrapCount++; } - arguments.append("arguments[").append(is).append("]"); + arguments.append("arguments.get(").append(i).append(")"); if (isScalar) { arguments.append(')'); } - if (i != lparams - 1) { - arguments.append(", "); - } } - JavaFileObject fileObj = processingEnv.getFiler().createSourceFile("com.oracle.truffle.r.ffi.impl.upcalls." + callName + "MR"); + String name = m.getSimpleName().toString(); + String callName = name + "Call"; + JavaFileObject fileObj = processingEnv.getFiler().createSourceFile("com.oracle.truffle.r.ffi.impl.upcalls." + callName); 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"); - 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"); - if (usesUnwrap) { - w.append("import com.oracle.truffle.r.ffi.impl.common.UpCallUnwrap;\n"); + w.append("\n"); + w.append("package com.oracle.truffle.r.ffi.impl.upcalls;\n"); + w.append("\n"); + w.append("import java.util.List;\n"); + w.append("\n"); + w.append("import com.oracle.truffle.api.CallTarget;\n"); + w.append("import com.oracle.truffle.api.Truffle;\n"); + w.append("import com.oracle.truffle.api.frame.VirtualFrame;\n"); + w.append("import com.oracle.truffle.api.interop.ForeignAccess;\n"); + w.append("import com.oracle.truffle.api.interop.TruffleObject;\n"); + w.append("import com.oracle.truffle.api.nodes.RootNode;\n"); + w.append("import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;\n"); + w.append("import com.oracle.truffle.r.runtime.data.RTruffleObject;\n"); + w.append("\n"); + w.append("// Checkstyle: stop method name check\n"); + w.append("\n"); + w.append("final class ").append(callName).append(" implements RTruffleObject {\n"); + w.append('\n'); + if (node == null) { + w.append(" private final UpCallsRFFI upCallsImpl;\n"); + w.append('\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(" ").append(callName).append("(UpCallsRFFI upCallsImpl) {\n"); + w.append(" assert upCallsImpl != null;\n"); + if (node == null) { + w.append(" this.upCallsImpl = upCallsImpl;\n"); + } + w.append(" }\n"); + w.append('\n'); + w.append(" private static final class ").append(callName).append("Factory extends AbstractDowncallForeign {\n"); + w.append(" @Override\n"); + w.append(" public boolean canHandle(TruffleObject obj) {\n"); + w.append(" return obj instanceof ").append(callName).append(";\n"); + w.append(" }\n"); + w.append("\n"); + w.append(" @Override\n"); + w.append(" public CallTarget accessExecute(int argumentsLength) {\n"); + w.append(" return Truffle.getRuntime().createCallTarget(new RootNode(null) {\n"); + w.append("\n"); + if (unwrapCount > 0) { + for (int i = 0; i < unwrapCount; i++) { + w.append(" @Child private UpCallUnwrap unwrap").append(Integer.toString(i)).append(" = new UpCallUnwrap();\n"); + } + w.append("\n"); } - w.append(" protected ").append(returnType).append(" access(").append(callName).append(" receiver, "); - if (params.size() == 0) { - w.append("@SuppressWarnings(\"unused\") "); + if (node != null) { + w.append(" @Child private ").append(node).append(" node").append(" = ").append(node).append(".create();\n"); + w.append("\n"); } - w.append("Object[] arguments) {\n"); - w.append(" ").append("return").append(" receiver.upCallsImpl.").append(name).append("("); - - w.append(arguments); - - w.append(");\n"); + w.append(" @Override\n"); + w.append(" public Object execute(VirtualFrame frame) {\n"); + w.append(" List<Object> arguments = ForeignAccess.getArguments(frame);\n"); + w.append(" assert arguments.size() == ").append(Integer.toString(params.size())).append(" : \"wrong number of arguments passed to ").append(name).append("\";\n"); + if (node != null) { + w.append(" return node.executeObject(").append(arguments).append(");\n"); + } else { + w.append(" return ((").append(callName).append(") ForeignAccess.getReceiver(frame)).upCallsImpl.").append(name).append("(").append(arguments).append(");\n"); + } + w.append(" }\n"); + w.append(" });\n"); w.append(" }\n"); w.append(" }\n"); w.append("\n"); - - w.append(" @Resolve(message = \"IS_EXECUTABLE\")\n"); - w.append(" public abstract static class ").append(callName).append("IsExecutable extends Node {\n"); - w.append(" protected Object access(@SuppressWarnings(\"unused\") ").append(callName).append(" receiver) {\n"); - w.append(" return true;\n"); - w.append(" }\n"); + w.append(" private static final ForeignAccess ACCESS = ForeignAccess.create(new ").append(callName).append("Factory(), null);\n"); + w.append("\n"); + w.append(" @Override\n"); + w.append(" public ForeignAccess getForeignAccess() {\n"); + w.append(" return ACCESS;\n"); w.append(" }\n"); w.append("}\n"); w.close(); - } private void generateCallbacks(ExecutableElement[] methods) throws IOException { diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallNode.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallNode.java new file mode 100644 index 0000000000000000000000000000000000000000..d41af7c487beae6947807b2e41b4646576dd8a3e --- /dev/null +++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallNode.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 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.ffi.processor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * Tags upcall functions that have a corresponding node implementation. + */ +@Target({ElementType.METHOD}) +public @interface RFFIUpCallNode { + Class<?> value(); +}