diff --git a/function-annotations/src/main/java/com/dylibso/chicory/function/annotations/Buffer.java b/function-annotations/src/main/java/com/dylibso/chicory/function/annotations/Buffer.java new file mode 100644 index 000000000..c7df67ebe --- /dev/null +++ b/function-annotations/src/main/java/com/dylibso/chicory/function/annotations/Buffer.java @@ -0,0 +1,10 @@ +package com.dylibso.chicory.function.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface Buffer {} diff --git a/function-annotations/src/main/java/com/dylibso/chicory/function/annotations/CString.java b/function-annotations/src/main/java/com/dylibso/chicory/function/annotations/CString.java new file mode 100644 index 000000000..f55218d17 --- /dev/null +++ b/function-annotations/src/main/java/com/dylibso/chicory/function/annotations/CString.java @@ -0,0 +1,10 @@ +package com.dylibso.chicory.function.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface CString {} diff --git a/function-processor/src/main/java/com/dylibso/chicory/function/processor/FunctionProcessor.java b/function-processor/src/main/java/com/dylibso/chicory/function/processor/FunctionProcessor.java index a6e538558..364ecdf7e 100644 --- a/function-processor/src/main/java/com/dylibso/chicory/function/processor/FunctionProcessor.java +++ b/function-processor/src/main/java/com/dylibso/chicory/function/processor/FunctionProcessor.java @@ -6,6 +6,8 @@ import static javax.tools.Diagnostic.Kind.ERROR; import static javax.tools.Diagnostic.Kind.NOTE; +import com.dylibso.chicory.function.annotations.Buffer; +import com.dylibso.chicory.function.annotations.CString; import com.dylibso.chicory.function.annotations.HostModule; import com.dylibso.chicory.function.annotations.WasmExport; import com.github.javaparser.ast.ArrayCreationLevel; @@ -137,10 +139,7 @@ private Expression processMethod( NodeList paramTypes = new NodeList<>(); NodeList arguments = new NodeList<>(); for (VariableElement parameter : executable.getParameters()) { - var argExpr = - new ArrayAccessExpr( - new NameExpr("args"), - new IntegerLiteralExpr(String.valueOf(paramTypes.size()))); + var argExpr = argExpr(paramTypes.size()); switch (parameter.asType().toString()) { case "int": paramTypes.add(valueType("I32")); @@ -158,6 +157,31 @@ private Expression processMethod( paramTypes.add(valueType("F64")); arguments.add(new MethodCallExpr(argExpr, "asDouble")); break; + case "java.lang.String": + if (annotatedWith(parameter, Buffer.class)) { + var lenExpr = argExpr(paramTypes.size() + 1); + paramTypes.add(valueType("I32")); + paramTypes.add(valueType("I32")); + arguments.add( + new MethodCallExpr( + new MethodCallExpr(new NameExpr("instance"), "memory"), + "readString", + new NodeList<>( + new MethodCallExpr(argExpr, "asInt"), + new MethodCallExpr(lenExpr, "asInt")))); + } else if (annotatedWith(parameter, CString.class)) { + paramTypes.add(valueType("I32")); + paramTypes.add(valueType("I32")); + arguments.add( + new MethodCallExpr( + new MethodCallExpr(new NameExpr("instance"), "memory"), + "readCString", + new NodeList<>(new MethodCallExpr(argExpr, "asInt")))); + } else { + log(ERROR, "Missing annotation for WASM type: java.lang.String", parameter); + throw new AbortProcessingException(); + } + break; case "com.dylibso.chicory.runtime.Instance": arguments.add(new NameExpr("instance")); break; @@ -266,6 +290,10 @@ private static boolean annotatedWith(Element element, Class { - functions.print(instance.memory(), args[0].asInt(), args[1].asInt()); + functions.print( + instance.memory().readString(args[0].asInt(), args[1].asInt())); return null; }, "simple", @@ -24,6 +25,26 @@ public static HostFunction[] toHostFunctions(Simple functions) { List.of(ValueType.I32, ValueType.I32), List.of() ), + new HostFunction( + (Instance instance, Value... args) -> { + functions.printx(instance.memory().readCString(args[0].asInt())); + return null; + }, + "simple", + "printx", + List.of(ValueType.I32, ValueType.I32), + List.of() + ), + new HostFunction( + (Instance instance, Value... args) -> { + functions.randomGet(instance.memory(), args[0].asInt(), args[1].asInt()); + return null; + }, + "simple", + "random_get", + List.of(ValueType.I32, ValueType.I32), + List.of() + ), new HostFunction( (Instance instance, Value... args) -> { functions.exit(); diff --git a/wasi/src/main/java/com/dylibso/chicory/wasi/WasiPreview1.java b/wasi/src/main/java/com/dylibso/chicory/wasi/WasiPreview1.java index ddccdad7c..c647e09e3 100644 --- a/wasi/src/main/java/com/dylibso/chicory/wasi/WasiPreview1.java +++ b/wasi/src/main/java/com/dylibso/chicory/wasi/WasiPreview1.java @@ -12,6 +12,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.stream.Collectors.toList; +import com.dylibso.chicory.function.annotations.Buffer; import com.dylibso.chicory.function.annotations.HostModule; import com.dylibso.chicory.function.annotations.WasmExport; import com.dylibso.chicory.log.Logger; @@ -691,8 +692,8 @@ public int fdWrite(Memory memory, int fd, int iovs, int iovsLen, int nwrittenPtr } @WasmExport - public int pathCreateDirectory(Memory memory, int dirFd, int pathPtr, int pathLen) { - logger.infof("path_create_directory: [%s, %s, %s]", dirFd, pathPtr, pathLen); + public int pathCreateDirectory(int dirFd, @Buffer String rawPath) { + logger.infof("path_create_directory: [%s, \"%s\"]", dirFd, rawPath); var descriptor = descriptors.get(dirFd); if (descriptor == null) { return wasiResult(WasiErrno.EBADF); @@ -703,7 +704,6 @@ public int pathCreateDirectory(Memory memory, int dirFd, int pathPtr, int pathLe } Path directory = ((Directory) descriptor).path(); - String rawPath = memory.readString(pathPtr, pathLen); Path path = resolvePath(directory, rawPath); if (path == null) { return wasiResult(WasiErrno.EACCES); @@ -723,10 +723,8 @@ public int pathCreateDirectory(Memory memory, int dirFd, int pathPtr, int pathLe @WasmExport public int pathFilestatGet( - Memory memory, int dirFd, int lookupFlags, int pathPtr, int pathLen, int buf) { - logger.infof( - "path_filestat_get: [%s, %s, %s, %s, %s]", - dirFd, lookupFlags, pathPtr, pathLen, buf); + Memory memory, int dirFd, int lookupFlags, @Buffer String rawPath, int buf) { + logger.infof("path_filestat_get: [%s, %s, \"%s\", %s]", dirFd, lookupFlags, rawPath, buf); var descriptor = descriptors.get(dirFd); if (descriptor == null) { return wasiResult(WasiErrno.EBADF); @@ -737,7 +735,6 @@ public int pathFilestatGet( } Path directory = ((Directory) descriptor).path(); - String rawPath = memory.readString(pathPtr, pathLen); Path path = resolvePath(directory, rawPath); if (path == null) { return wasiResult(WasiErrno.EACCES); @@ -765,14 +762,13 @@ public int pathFilestatGet( public int pathFilestatSetTimes( int fd, int lookupFlags, - int pathPtr, - int pathLen, + @Buffer String rawPath, long accessTime, long modifiedTime, int fstFlags) { logger.infof( - "path_filestat_set_times: [%s, %s, %s, %s, %s, %s, %s]", - fd, lookupFlags, pathPtr, pathLen, accessTime, modifiedTime, fstFlags); + "path_filestat_set_times: [%s, %s, \"%s\", %s, %s, %s]", + fd, lookupFlags, rawPath, accessTime, modifiedTime, fstFlags); throw new WASMRuntimeException( "We don't yet support this WASI call: path_filestat_set_size"); } @@ -781,14 +777,12 @@ public int pathFilestatSetTimes( public int pathLink( int oldFd, int oldFlags, - int oldPathPtr, - int oldPathLen, + @Buffer String rawOldPath, int newFd, - int newPathPtr, - int newPathLen) { + @Buffer String rawNewPath) { logger.infof( - "path_link: [%s, %s, %s, %s, %s, %s, %s]", - oldFd, oldFlags, oldPathPtr, oldPathLen, newFd, newPathPtr, newPathLen); + "path_link: [%s, %s, \"%s\", %s, \"%s\"]", + oldFd, oldFlags, rawOldPath, newFd, rawNewPath); throw new WASMRuntimeException("We don't yet support this WASI call: path_link"); } @@ -797,19 +791,17 @@ public int pathOpen( Memory memory, int dirFd, int lookupFlags, - int pathPtr, - int pathLen, + @Buffer String rawPath, int openFlags, long rightsBase, long rightsInheriting, int fdFlags, int fdPtr) { logger.infof( - "path_open: [%s, %s, %s, %s, %s, %s, %s, %s, %s]", + "path_open: [%s, %s, \"%s\", %s, %s, %s, %s, %s]", dirFd, lookupFlags, - pathPtr, - pathLen, + rawPath, openFlags, rightsBase, rightsInheriting, @@ -825,7 +817,6 @@ public int pathOpen( } Path directory = ((Directory) descriptor).path(); - String rawPath = memory.readString(pathPtr, pathLen); Path path = resolvePath(directory, rawPath); if (path == null) { return wasiResult(WasiErrno.EACCES); @@ -894,16 +885,15 @@ public int pathOpen( } @WasmExport - public int pathReadlink(int dirFd, int pathPtr, int pathLen, int buf, int bufLen, int bufUsed) { + public int pathReadlink(int dirFd, @Buffer String rawPath, int buf, int bufLen, int bufUsed) { logger.infof( - "path_readlink: [%s, %s, %s, %s, %s, %s]", - dirFd, pathPtr, pathLen, buf, bufLen, bufUsed); + "path_readlink: [%s, \"%s\", %s, %s, %s]", dirFd, rawPath, buf, bufLen, bufUsed); throw new WASMRuntimeException("We don't yet support this WASI call: path_readlink"); } @WasmExport - public int pathRemoveDirectory(Memory memory, int dirFd, int pathPtr, int pathLen) { - logger.infof("path_remove_directory: [%s, %s, %s]", dirFd, pathPtr, pathLen); + public int pathRemoveDirectory(int dirFd, @Buffer String rawPath) { + logger.infof("path_remove_directory: [%s, \"%s\"]", dirFd, rawPath); var descriptor = descriptors.get(dirFd); if (descriptor == null) { return wasiResult(WasiErrno.EBADF); @@ -914,7 +904,6 @@ public int pathRemoveDirectory(Memory memory, int dirFd, int pathPtr, int pathLe } Path directory = ((Directory) descriptor).path(); - String rawPath = memory.readString(pathPtr, pathLen); Path path = resolvePath(directory, rawPath); if (path == null) { return wasiResult(WasiErrno.EACCES); @@ -940,16 +929,8 @@ public int pathRemoveDirectory(Memory memory, int dirFd, int pathPtr, int pathLe @WasmExport public int pathRename( - Memory memory, - int oldFd, - int oldPathPtr, - int oldPathLen, - int newFd, - int newPathPtr, - int newPathLen) { - logger.infof( - "path_rename: [%s, %s, %s, %s, %s, %s]", - oldFd, oldPathPtr, oldPathLen, newFd, newPathPtr, newPathLen); + int oldFd, @Buffer String oldRawPath, int newFd, @Buffer String newRawPath) { + logger.infof("path_rename: [%s, \"%s\", %s, \"%s\"]", oldFd, oldRawPath, newFd, newRawPath); var oldDescriptor = descriptors.get(oldFd); if (oldDescriptor == null) { return wasiResult(WasiErrno.EBADF); @@ -968,13 +949,11 @@ public int pathRename( } Path newDirectory = ((Directory) newDescriptor).path(); - String oldRawPath = memory.readString(oldPathPtr, oldPathLen); Path oldPath = resolvePath(oldDirectory, oldRawPath); if (oldPath == null) { return wasiResult(WasiErrno.EACCES); } - String newRawPath = memory.readString(newPathPtr, newPathLen); Path newPath = resolvePath(newDirectory, newRawPath); if (newPath == null) { return wasiResult(WasiErrno.EACCES); @@ -1007,17 +986,14 @@ public int pathRename( } @WasmExport - public int pathSymlink( - int oldPathPtr, int oldPathLen, int dirFd, int newPathPtr, int newPathLen) { - logger.infof( - "path_symlink: [%s, %s, %s, %s, %s]", - oldPathPtr, oldPathLen, dirFd, newPathPtr, newPathLen); + public int pathSymlink(@Buffer String oldRawPath, int dirFd, @Buffer String newRawPath) { + logger.infof("path_symlink: [\"%s\", %s, \"%s\"]", oldRawPath, dirFd, newRawPath); throw new WASMRuntimeException("We don't yet support this WASI call: path_symlink"); } @WasmExport - public int pathUnlinkFile(Memory memory, int dirFd, int pathPtr, int pathLen) { - logger.infof("path_unlink_file: [%s, %s, %s]", dirFd, pathPtr, pathLen); + public int pathUnlinkFile(int dirFd, @Buffer String rawPath) { + logger.infof("path_unlink_file: [%s, \"%s\"]", dirFd, rawPath); var descriptor = descriptors.get(dirFd); if (descriptor == null) { return wasiResult(WasiErrno.EBADF); @@ -1028,7 +1004,6 @@ public int pathUnlinkFile(Memory memory, int dirFd, int pathPtr, int pathLen) { } Path directory = ((Directory) descriptor).path(); - String rawPath = memory.readString(pathPtr, pathLen); Path path = resolvePath(directory, rawPath); if (path == null) { return wasiResult(WasiErrno.EACCES);