Skip to content
Snippets Groups Projects
Commit d11c1319 authored by Florian Angerer's avatar Florian Angerer
Browse files

Added minimal implementation for 'eSoftVersion' and 'La_library'.

parent adf0bf74
No related branches found
No related tags found
No related merge requests found
Showing
with 263 additions and 18 deletions
/*
* Copyright (c) 2018, 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.interop.base;
import java.util.HashMap;
import java.util.Map;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.r.runtime.data.RTruffleObject;
public final class ESoftVersionResult implements RTruffleObject {
private final Map<String, String> paths = new HashMap<>();
public void putVersion(String libName, String version) {
paths.put(libName, version);
}
public Map<String, String> getVersions() {
return paths;
}
@Override
public ForeignAccess getForeignAccess() {
return ESoftVersionResultMRForeign.ACCESS;
}
}
/*
* Copyright (c) 2018, 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.interop.base;
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;
@MessageResolution(receiverType = ESoftVersionResult.class)
public class ESoftVersionResultMR {
@CanResolve
public abstract static class ESoftVersionResultCallbackCheck extends Node {
protected static boolean test(TruffleObject receiver) {
return receiver instanceof ESoftVersionResult;
}
}
@Resolve(message = "IS_EXECUTABLE")
public abstract static class ESoftVersionResultIsExecutable extends Node {
protected Object access(@SuppressWarnings("unused") ESoftVersionResult receiver) {
return true;
}
}
@Resolve(message = "EXECUTE")
public abstract static class ESoftVersionResultCallbackExecute extends Node {
protected Object access(ESoftVersionResult receiver, Object[] arguments) {
if (arguments.length == 2) {
receiver.putVersion("zlib", arguments[0].toString());
receiver.putVersion("PCRE", arguments[1].toString());
}
return receiver;
}
}
}
...@@ -24,8 +24,10 @@ package com.oracle.truffle.r.ffi.impl.llvm; ...@@ -24,8 +24,10 @@ package com.oracle.truffle.r.ffi.impl.llvm;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map;
import com.oracle.truffle.r.ffi.impl.interop.NativeCharArray; import com.oracle.truffle.r.ffi.impl.interop.NativeCharArray;
import com.oracle.truffle.r.ffi.impl.interop.base.ESoftVersionResult;
import com.oracle.truffle.r.ffi.impl.interop.base.GlobResult; import com.oracle.truffle.r.ffi.impl.interop.base.GlobResult;
import com.oracle.truffle.r.ffi.impl.interop.base.ReadlinkResult; import com.oracle.truffle.r.ffi.impl.interop.base.ReadlinkResult;
import com.oracle.truffle.r.ffi.impl.interop.base.StrtolResult; import com.oracle.truffle.r.ffi.impl.interop.base.StrtolResult;
...@@ -224,6 +226,22 @@ public class TruffleLLVM_Base implements BaseRFFI { ...@@ -224,6 +226,22 @@ public class TruffleLLVM_Base implements BaseRFFI {
} }
} }
private static class TruffleLLVM_ESoftVersionNode extends TruffleLLVM_DownCallNode implements ESoftVersionNode {
@Override
protected NativeFunction getFunction() {
return NativeFunction.eSoftVersion;
}
@Override
public Map<String, String> eSoftVersion() {
ESoftVersionResult result = new ESoftVersionResult();
call(result);
return result.getVersions();
}
}
@Override @Override
public GetpidNode createGetpidNode() { public GetpidNode createGetpidNode() {
return new TruffleLLVM_GetpidNode(); return new TruffleLLVM_GetpidNode();
...@@ -273,4 +291,9 @@ public class TruffleLLVM_Base implements BaseRFFI { ...@@ -273,4 +291,9 @@ public class TruffleLLVM_Base implements BaseRFFI {
public GlobNode createGlobNode() { public GlobNode createGlobNode() {
return new TruffleLLVM_GlobNode(); return new TruffleLLVM_GlobNode();
} }
@Override
public ESoftVersionNode createESoftVersionNode() {
return new TruffleLLVM_ESoftVersionNode();
}
} }
...@@ -200,4 +200,9 @@ public class Managed_Base implements BaseRFFI { ...@@ -200,4 +200,9 @@ public class Managed_Base implements BaseRFFI {
public GlobNode createGlobNode() { public GlobNode createGlobNode() {
return null; return null;
} }
@Override
public ESoftVersionNode createESoftVersionNode() {
return null;
}
} }
...@@ -24,9 +24,11 @@ package com.oracle.truffle.r.ffi.impl.nfi; ...@@ -24,9 +24,11 @@ package com.oracle.truffle.r.ffi.impl.nfi;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.interop.java.JavaInterop;
import com.oracle.truffle.r.ffi.impl.interop.base.ESoftVersionResult;
import com.oracle.truffle.r.ffi.impl.interop.base.GlobResult; import com.oracle.truffle.r.ffi.impl.interop.base.GlobResult;
import com.oracle.truffle.r.ffi.impl.interop.base.ReadlinkResult; import com.oracle.truffle.r.ffi.impl.interop.base.ReadlinkResult;
import com.oracle.truffle.r.ffi.impl.interop.base.StrtolResult; import com.oracle.truffle.r.ffi.impl.interop.base.StrtolResult;
...@@ -214,6 +216,22 @@ public class TruffleNFI_Base implements BaseRFFI { ...@@ -214,6 +216,22 @@ public class TruffleNFI_Base implements BaseRFFI {
} }
} }
private static class TruffleNFI_ESoftVersionNode extends TruffleNFI_DownCallNode implements ESoftVersionNode {
@Override
protected NativeFunction getFunction() {
return NativeFunction.eSoftVersion;
}
@Override
public Map<String, String> eSoftVersion() {
ESoftVersionResult result = new ESoftVersionResult();
call(result);
return result.getVersions();
}
}
@Override @Override
public GetpidNode createGetpidNode() { public GetpidNode createGetpidNode() {
return new TruffleNFI_GetpidNode(); return new TruffleNFI_GetpidNode();
...@@ -263,4 +281,10 @@ public class TruffleNFI_Base implements BaseRFFI { ...@@ -263,4 +281,10 @@ public class TruffleNFI_Base implements BaseRFFI {
public GlobNode createGlobNode() { public GlobNode createGlobNode() {
return new TruffleNFI_GlobNode(); return new TruffleNFI_GlobNode();
} }
@Override
public ESoftVersionNode createESoftVersionNode() {
return new TruffleNFI_ESoftVersionNode();
}
} }
...@@ -107,3 +107,18 @@ void call_base_strtol(void (*call_setresult)(long result, int cerrno), char *s, ...@@ -107,3 +107,18 @@ void call_base_strtol(void (*call_setresult)(long result, int cerrno), char *s,
long rc = strtol(s, NULL, base); long rc = strtol(s, NULL, base);
call_setresult(rc, errno); call_setresult(rc, errno);
} }
#include <zlib.h>
#include <bzlib.h>
#ifdef HAVE_PCRE_PCRE_H
# include <pcre/pcre.h>
#else
# include <pcre.h>
#endif
void call_base_eSoftVersion(void (*call_eSoftVersion_setfields)(char *zlibVersion, char *pcreVersion)) {
char sZlibVersion[256], sPcreVersion[256];
snprintf(sZlibVersion, 256, "%s", zlibVersion());
snprintf(sPcreVersion, 256, "%s", pcre_version());
call_eSoftVersion_setfields(sZlibVersion, sPcreVersion);
}
...@@ -600,6 +600,7 @@ public class BasePackage extends RBuiltinPackage { ...@@ -600,6 +600,7 @@ public class BasePackage extends RBuiltinPackage {
add(LaFunctions.Version.class, LaFunctionsFactory.VersionNodeGen::create); add(LaFunctions.Version.class, LaFunctionsFactory.VersionNodeGen::create);
add(LaFunctions.LaSolve.class, LaFunctionsFactory.LaSolveNodeGen::create); add(LaFunctions.LaSolve.class, LaFunctionsFactory.LaSolveNodeGen::create);
add(LaFunctions.Svd.class, LaFunctionsFactory.SvdNodeGen::create); add(LaFunctions.Svd.class, LaFunctionsFactory.SvdNodeGen::create);
add(LaFunctions.LaLibrary.class, LaFunctionsFactory.LaLibraryNodeGen::create);
add(Lapply.class, LapplyNodeGen::create); add(Lapply.class, LapplyNodeGen::create);
add(Length.class, LengthNodeGen::create); add(Length.class, LengthNodeGen::create);
add(Lengths.class, LengthsNodeGen::create); add(Lengths.class, LengthsNodeGen::create);
......
...@@ -33,15 +33,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; ...@@ -33,15 +33,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.List;
import java.util.Map; import java.util.Map;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.r.ffi.impl.common.LibPaths;
import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.runtime.RCompression;
import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.builtins.RBuiltin;
...@@ -51,6 +54,8 @@ import com.oracle.truffle.r.runtime.data.RList; ...@@ -51,6 +54,8 @@ import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RStringVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
import com.oracle.truffle.r.runtime.ffi.BaseRFFI.ESoftVersionNode;
import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL;
import com.oracle.truffle.r.runtime.ffi.DLL.DLLException; import com.oracle.truffle.r.runtime.ffi.DLL.DLLException;
import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
...@@ -223,6 +228,7 @@ public class DynLoadFunctions { ...@@ -223,6 +228,7 @@ public class DynLoadFunctions {
@RBuiltin(name = "eSoftVersion", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) @RBuiltin(name = "eSoftVersion", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
public abstract static class ExtSoftVersion extends RBuiltinNode.Arg0 { public abstract static class ExtSoftVersion extends RBuiltinNode.Arg0 {
@Child private ESoftVersionNode eSoftVersionNode = BaseRFFI.ESoftVersionNode.create();
static { static {
Casts.noCasts(ExtSoftVersion.class); Casts.noCasts(ExtSoftVersion.class);
...@@ -231,22 +237,32 @@ public class DynLoadFunctions { ...@@ -231,22 +237,32 @@ public class DynLoadFunctions {
@Specialization @Specialization
@TruffleBoundary @TruffleBoundary
protected RStringVector getSymbolInfo() { protected RStringVector getSymbolInfo() {
String[] data = new String[]{"zlib", "bzlib", "xz", "PCRE", "ICU", "TRE", "iconv"};
RStringVector names = RDataFactory.createStringVector(data, true); Map<String, String> eSoftVersion = eSoftVersionNode.eSoftVersion();
Map<String, String> versionFunctionTable = new HashMap<>(); List<String> libNames = new ArrayList<>();
versionFunctionTable.put("zlib", "zlibVersion"); List<String> versions = new ArrayList<>();
versionFunctionTable.put("bzlib", "BZ2_bzlibVersion");
versionFunctionTable.put("xz", "lzma_version_string"); for (Map.Entry<String, String> versionEntry : eSoftVersion.entrySet()) {
versionFunctionTable.put("PCRE", "pcre_version"); libNames.add(versionEntry.getKey());
versionFunctionTable.put("TRE", "tre_version"); versions.add(versionEntry.getValue());
}
// TODO
// BZIP2
// ICU -> empty try {
// TRE mandatory versions.add(RCompression.getBz2Version());
// iconv -> unknown libNames.add("bzip2");
return RDataFactory.createStringVector(0); } catch (IOException e) {
// ignore
}
// BLAS
libNames.add("BLAS");
versions.add(LibPaths.getBuiltinLibPath("Rblas"));
RStringVector names = RDataFactory.createStringVector(libNames.toArray(new String[0]), true);
return RDataFactory.createStringVector(versions.toArray(new String[0]), true, names);
} }
} }
} }
...@@ -41,6 +41,7 @@ import com.oracle.truffle.api.dsl.Cached; ...@@ -41,6 +41,7 @@ import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.ffi.impl.common.LibPaths;
import com.oracle.truffle.r.nodes.access.vector.ExtractListElement; import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
import com.oracle.truffle.r.nodes.attributes.CopyAttributesNode; import com.oracle.truffle.r.nodes.attributes.CopyAttributesNode;
import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
...@@ -63,7 +64,6 @@ import com.oracle.truffle.r.runtime.data.RComplexVector; ...@@ -63,7 +64,6 @@ import com.oracle.truffle.r.runtime.data.RComplexVector;
import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RDataFactory.VectorFactory; import com.oracle.truffle.r.runtime.data.RDataFactory.VectorFactory;
import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RDoubleVector;
import com.oracle.truffle.r.runtime.data.RFunction;
import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RStringVector;
...@@ -866,4 +866,17 @@ public class LaFunctions { ...@@ -866,4 +866,17 @@ public class LaFunctions {
return RDataFactory.createList(val, nm); return RDataFactory.createList(val, nm);
} }
} }
@RBuiltin(name = "La_library", kind = INTERNAL, parameterNames = {}, behavior = PURE)
public abstract static class LaLibrary extends RBuiltinNode.Arg0 {
static {
Casts.noCasts(LaLibrary.class);
}
@Specialization
protected Object doLibrary() {
return RDataFactory.createStringVector(LibPaths.getBuiltinLibPath("Rlapack"));
}
}
} }
...@@ -250,4 +250,36 @@ public class RCompression { ...@@ -250,4 +250,36 @@ public class RCompression {
} }
throw new IOException(); throw new IOException();
} }
public static String getBz2Version() throws IOException {
// assumes: "bzip2, a block-sorting file compressor. Version 1.0.6, 6-Sept-2010."
String[] command = {"bzip2", "-V"};
int rc;
ProcessBuilder pb = new ProcessBuilder(command);
Process p = pb.start();
// version is written to the error output stream
InputStream is = p.getErrorStream();
ProcessOutputManager.OutputThreadVariable readThread = new ProcessOutputManager.OutputThreadVariable(command[0], is);
readThread.start();
try {
rc = p.waitFor();
if (rc == 0) {
String output = new String(readThread.getData());
String version = "Version ";
String firstLine = output.split("\\n")[0];
int versionIdx = firstLine.indexOf(version);
if (versionIdx >= 0) {
int commaIdx = firstLine.lastIndexOf('.');
if (commaIdx > versionIdx) {
return firstLine.substring(versionIdx + version.length(), commaIdx);
}
}
} else {
throw new IOException("bzip2 error code: " + rc);
}
} catch (InterruptedException ex) {
// fall through
}
throw new IOException();
}
} }
...@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.ffi; ...@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.ffi;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map;
import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.NodeInterface; import com.oracle.truffle.api.nodes.NodeInterface;
...@@ -163,6 +164,14 @@ public interface BaseRFFI { ...@@ -163,6 +164,14 @@ public interface BaseRFFI {
} }
} }
interface ESoftVersionNode extends NodeInterface {
Map<String, String> eSoftVersion();
static ESoftVersionNode create() {
return RFFIFactory.getBaseRFFI().createESoftVersionNode();
}
}
/* /*
* The RFFI implementation influences exactly what subclass of the above nodes is created. Each * The RFFI implementation influences exactly what subclass of the above nodes is created. Each
* implementation must therefore, implement these methods that are called by the associated * implementation must therefore, implement these methods that are called by the associated
...@@ -189,6 +198,8 @@ public interface BaseRFFI { ...@@ -189,6 +198,8 @@ public interface BaseRFFI {
GlobNode createGlobNode(); GlobNode createGlobNode();
ESoftVersionNode createESoftVersionNode();
/* /*
* Some functions are called from non-Truffle contexts, which requires a RootNode * Some functions are called from non-Truffle contexts, which requires a RootNode
*/ */
......
...@@ -43,6 +43,7 @@ public enum NativeFunction { ...@@ -43,6 +43,7 @@ public enum NativeFunction {
strtol("((sint64, sint32): void, string, sint32): void", "call_base_"), strtol("((sint64, sint32): void, string, sint32): void", "call_base_"),
uname("((string, string, string, string, string): void): void", "call_base_"), uname("((string, string, string, string, string): void): void", "call_base_"),
glob("((string): void, string): void", "call_base_"), glob("((string): void, string): void", "call_base_"),
eSoftVersion("((string, string): void): void", "call_base_"),
// PCRE // PCRE
maketables("(): sint64", "call_pcre_"), maketables("(): sint64", "call_pcre_"),
compile("((uint64, string, sint32): void, string, sint32, uint64): void", "call_pcre_"), compile("((uint64, string, sint32): void, string, sint32, uint64): void", "call_pcre_"),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment