6 Commits

Author SHA1 Message Date
vms
42bd748d95 first prototype 2019-08-12 16:04:44 +03:00
vms
f583e6f0c9 some work with preopened dirs 2019-08-12 11:55:28 +03:00
vms
c3bdffc2a2 fix EnvModule 2019-08-11 23:17:12 +03:00
vms
2144c74a66 work goes on 2019-08-11 23:04:46 +03:00
vms
4c5af2e998 Merge branch 'master' into wasi_stage_1 2019-08-11 17:20:55 +03:00
vms
d707a03b3f initial commit 2019-08-10 14:38:25 +03:00
14 changed files with 646 additions and 18 deletions

View File

@ -21,7 +21,7 @@ buildscript {
allprojects {
apply plugin: 'java'
group 'com.github.cretz.asmble'
version '0.4.11-fl'
version '0.4.11-fl_experiment_29'
// skips building and running for the specified examples
ext.skipExamples = ['c-simple', 'go-simple', 'rust-regex']
@ -309,9 +309,9 @@ def publishSettings(project, projectName, projectDescription) {
}
bintray {
if(!hasProperty("bintrayUser") || !hasProperty("bintrayKey")) {
return
}
// if(!hasProperty("bintrayUser") || !hasProperty("bintrayKey")) {
// return
// }
user = bintrayUser
key = bintrayKey

View File

@ -36,5 +36,7 @@ public abstract class MemoryBuffer {
public abstract short getShort(int index);
public abstract float getFloat(int index);
public abstract double getDouble(int index);
public abstract byte get();
public abstract void get(byte[] arr, int offset, int length);
public abstract MemoryBuffer get(byte[] arr);
}

View File

@ -3,6 +3,9 @@ package asmble.cli
import asmble.ast.Script
import asmble.compile.jvm.*
import asmble.run.jvm.*
import asmble.run.jvm.native_modules.LoggerModule
import asmble.run.jvm.native_modules.EnvModule
import asmble.run.jvm.native_modules.wasi.WASIModule
import java.io.File
import java.io.PrintWriter
import java.util.*
@ -86,6 +89,24 @@ abstract class ScriptCommand<T> : Command<T>() {
}
}
PrintWriter(System.out, true).println("asmble is running");
// TODO: this hack should be refactored in future with rewritting the part of Asmble core code
// check that there is only one main module
if(context.modules.size == 1 && args.memoryBuilder != null) {
PrintWriter(System.out, true).println("WASI module loaded");
val capacity = Math.multiplyExact(args.defaultMaxMemPages, Mem.PAGE_SIZE)
val moduleMem = args.memoryBuilder.build(capacity)
context.moduleMem = moduleMem
// add the WASI Wasm module for support a subset of WASI syscalls
// WASI is enabled only for one module mode
context = context.withModuleRegistered(
"wasi_unstable",
Module.Native(WASIModule(moduleMem, arrayOf("/Users/")))
)
}
// Do registrations
context = args.registrations.fold(context) { ctx, (moduleName, className) ->
ctx.withModuleRegistered(moduleName,
@ -95,15 +116,14 @@ abstract class ScriptCommand<T> : Command<T>() {
if (args.specTestRegister) context = context.withHarnessRegistered()
if (args.enableLogger) {
// add logger Wasm module for logging
context =
context.withModuleRegistered(
// add the logger Wasm module for logging
context = context.withModuleRegistered(
"logger",
Module.Native(LoggerModule(PrintWriter(System.out)))
)
}
// add env Wasm module for gas metering
// add the env Wasm module for gas metering
context =
context.withModuleRegistered(
"env",

View File

@ -108,6 +108,14 @@ open class MemoryByteBuffer(val bb: ByteBuffer) : MemoryBuffer() {
return bb.getDouble(index)
}
override fun get(): Byte {
return bb.get();
}
override fun get(arr: ByteArray, offset: Int, length: Int) {
bb.get(arr, offset, length);
}
override fun equals(other: Any?): Boolean {
if (this === other)
return true

View File

@ -77,6 +77,7 @@ interface Module {
// If there is a memory import, we have to get the one with the mem class as the first
val memImport = mod.imports.find { it.kind is Node.Import.Kind.Memory }
val builder = ctx.memoryBuilder
val moduleMem = ctx.moduleMem
val memLimit = if (memImport != null) {
constructor = cls.declaredConstructors.find { it.parameterTypes.firstOrNull()?.ref == mem.memType }
@ -91,6 +92,11 @@ interface Module {
throw RunErr.ImportMemoryCapacityTooLarge(it * Mem.PAGE_SIZE, memCap)
}
memLimit
} else if (moduleMem != null) {
constructor = cls.declaredConstructors.find { it.parameterTypes.firstOrNull()?.ref == mem.memType }
constructorParams += moduleMem
ctx.defaultMaxMemPages * Mem.PAGE_SIZE
} else if (builder != null) {
constructor = cls.declaredConstructors.find { it.parameterTypes.firstOrNull()?.ref == mem.memType }

View File

@ -6,6 +6,7 @@ import asmble.ast.Script
import asmble.compile.jvm.*
import asmble.io.AstToSExpr
import asmble.io.SExprToStr
import asmble.run.jvm.native_modules.TestHarness
import asmble.util.Logger
import asmble.util.toRawIntBits
import asmble.util.toRawLongBits
@ -44,7 +45,8 @@ data class ScriptContext(
val exceptionTranslator: ExceptionTranslator = ExceptionTranslator,
val defaultMaxMemPages: Int = 1,
val includeBinaryInCompiledClass: Boolean = false,
val memoryBuilder: MemoryBufferBuilder? = null
val memoryBuilder: MemoryBufferBuilder? = null,
var moduleMem: MemoryBuffer? = null
) : Logger by logger {
fun withHarnessRegistered(out: PrintWriter = PrintWriter(System.out, true)) =

View File

@ -1,4 +1,4 @@
package asmble.run.jvm
package asmble.run.jvm.native_modules
/**
* Used to tack the state of the environment module.
@ -46,11 +46,17 @@ open class EnvModule(private val gasLimit: Long) {
}
/**
* Returns environment module state.
* Used from WasmVm to determine spent gas and executed instruction counter after each invocation.
* Returns spent gas.
*/
fun getState(): EnvState {
return state;
fun getSpentGas(): Long {
return state.spentGas;
}
/**
* Returns executed instruction counter.
*/
fun getEIC(): Long {
return state.EIC;
}
}

View File

@ -1,4 +1,4 @@
package asmble.run.jvm
package asmble.run.jvm.native_modules
import asmble.compile.jvm.Mem
import java.io.PrintWriter

View File

@ -1,7 +1,5 @@
package asmble.run.jvm
package asmble.run.jvm.native_modules
import asmble.annotation.WasmExport
import asmble.annotation.WasmExternalKind
import asmble.compile.jvm.Mem
import asmble.compile.jvm.MemoryBuffer
import asmble.compile.jvm.MemoryByteBuffer

View File

@ -0,0 +1,402 @@
package asmble.run.jvm.native_modules.wasi
import asmble.ast.Script
import asmble.compile.jvm.MemoryBuffer
import asmble.run.jvm.ScriptAssertionError
import java.io.File
import java.io.PrintWriter
import java.lang.Integer.min
import java.util.*
import kotlin.collections.HashMap
/**
* Module used for support WASI, contains the realization of several WASI imports
* for operating with file system. Should be registered as 'wasi_unstable'.
*/
open class WASIModule(private val mem: MemoryBuffer, private val preopenedDirNames: Array<String>) {
/*
+ (import "wasi_unstable" "fd_prestat_get" (func $__wasi_fd_prestat_get (type 2)))
+ (import "wasi_unstable" "fd_prestat_dir_name" (func $__wasi_fd_prestat_dir_name (type 1)))
+ (import "wasi_unstable" "environ_sizes_get" (func $__wasi_environ_sizes_get (type 2)))
+ (import "wasi_unstable" "environ_get" (func $__wasi_environ_get (type 2)))
+ (import "wasi_unstable" "args_sizes_get" (func $__wasi_args_sizes_get (type 2)))
+ (import "wasi_unstable" "args_get" (func $__wasi_args_get (type 2)))
(import "wasi_unstable" "fd_close" (func $fd_close (type 3)))
(import "wasi_unstable" "fd_write" (func $fd_write (type 9)))
(import "wasi_unstable" "fd_read" (func $fd_read (type 9)))
(import "wasi_unstable" "path_open" (func $path_open (type 10)))
+ (import "wasi_unstable" "proc_exit" (func $__wasi_proc_exit (type 0)))
(import "wasi_unstable" "fd_fdstat_get" (func $__wasi_fd_fdstat_get (type 2)))
*/
private val writer = PrintWriter(System.out, true);
// this error code will be returned by all non-implemented methods
private val wasiErrorCode: Int = __WASI_EACCES
private val stdin: Int = 0
private val stdout: Int = 1
private val stderr: Int = 2
private var nextPreopenedDirId = 0;
private val preopenedDirs = HashMap<Int, String>()
// mapping between file descriptors and opened file
private val openedFiles = HashMap<Int, File>()
private val openedFilesOffset = HashMap<Int, Int>()
private val openedFileNames = HashMap<String, Int>()
/**
* [Wasm function]
* Gets metadata about a preopened file descriptor.
*
* @param fd the preopened file descriptor to query
* @param buf_ptr where the metadata will be written
* @return WASI code of result
*/
fun fd_prestat_get(
fd: Int,
buf_ptr: Int
): Int {
writer.println("fd_prestat_get: $fd, $buf_ptr");
writer.flush();
if (nextPreopenedDirId >= preopenedDirNames.size) {
return __WASI_EBADF;
}
// dir type
mem.putInt(buf_ptr, 0);
// dir length
writer.println("fd_prestat_get: returning ${preopenedDirNames[nextPreopenedDirId].length} as the string length");
writer.flush();
mem.putInt(buf_ptr + 4, preopenedDirNames[nextPreopenedDirId].length);
preopenedDirs[fd] = preopenedDirNames[nextPreopenedDirId];
++nextPreopenedDirId;
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Gets state of preopened file descriptors.
*
* @param fd the preopened file descriptor to query
* @param path where the metadata will be written
* @param path_len the length of metadata
* @return WASI code of result
*/
fun fd_prestat_dir_name(
fd: Int,
path: Int,
path_len: Int
): Int {
writer.println("fd_prestat_dir_name: $fd, $path, $path_len");
writer.flush();
val memView = mem.duplicate();
memView.position(path);
if(preopenedDirs.containsKey(fd) ) {
writer.println("fd_prestat_dir_name: return string ${preopenedDirs[fd]}");
writer.flush();
memView.put(preopenedDirs[fd]!!.toByteArray(), 0, path_len);
} else {
// TODO: handle error
memView.put(path, 0);
}
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Gets metadata of a file descriptor.
*
* @param fd the file descriptor whose metadata will be accessed
* @param buf the location where the metadata will be written
* @return WASI code of result
*/
fun fd_fdstat_get(
fd: Int,
path: Int
): Int {
writer.println("fd_fdstat_get: $fd, $path");
writer.flush();
if(preopenedDirs.containsKey(fd)) {
mem.put(path, __WASI_FILETYPE_DIRECTORY.toByte());
mem.putShort(path + 2, __WASI_FILETYPE_DIRECTORY.toShort());
// all rights
mem.putLong(path + 8, Long.MAX_VALUE);
mem.putLong(path + 16, Long.MAX_VALUE);
}
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Opens file located at the given path.
*
* @param dirfd the descriptor corresponding to the directory that the file is in
* @param dirflags flags specifying how the path will be resolved
* @param path_offset the path of the file or directory to be open
* @param path_len the lenght of the path string
* @param o_flags how the file will be open
* @param fs_rights_base the rights of the created file descriptor
* @param fs_rightsinheriting the rights of file descriptors derived from the created file descriptor
* @param fs_flags the flags of the file descriptor
* @param fd the new file descriptor
* @return WASI code of result
*/
fun path_open(
dirfd: __wasi_fd_t,
dirflags: __wasi_lookupflags_t,
path_offset: Int,
path_len: Int,
o_flags: __wasi_oflags_t,
fs_rights_base: __wasi_rights_t,
fs_rightsinheriting: __wasi_rights_t,
fs_flags: __wasi_fdflags_t,
fd: __wasi_fd_t
): Int {
// path_open: 3, 1, 1114408, 43, 9, 264749053, 264749053, 0, 1048400
writer.println("path_open: $dirfd, $dirflags, $path_offset, $path_len, $o_flags, $fs_rights_base, $fs_rightsinheriting, $fs_flags, $fd");
writer.flush();
if( (dirflags and __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) {
// TODO
writer.println("path_open: will follow debug links");
writer.flush();
}
val pathToOpen = preopenedDirs[dirfd]!! + readUTF8String(mem, path_offset, path_len);
writer.println("path_open: $pathToOpen");
writer.flush();
var newFd = 2 + nextPreopenedDirId + 10;
if(openedFileNames.containsKey(pathToOpen)) {
newFd = openedFileNames[pathToOpen]!!;
} else {
if(o_flags and __WASI_O_CREAT == 0) {
return __WASI_EINVAL;
}
if(o_flags and __WASI_O_DIRECTORY != 0) {
return __WASI_ENOTDIR;
}
val file = File(pathToOpen);
if(file.exists() && (o_flags and __WASI_O_EXCL != 0)) {
return __WASI_EINVAL;
}
file.createNewFile();
openedFileNames[pathToOpen] = newFd;
openedFilesOffset[newFd] = 0;
openedFiles[newFd] = File(pathToOpen);
}
mem.putInt(fd, newFd);
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Reads data from file descriptor.
*
* @param fd a file descriptor from which data will be read
* @param iovs vectors where data will be stored
* @param iovs_len the length of data in `iovs`
* @param nread number of bytes read
*/
fun fd_read(
fd: __wasi_fd_t,
iovs: Int,
iovs_len: Int,
nread: Int
): Int {
writer.println("fd_read: $fd, $iovs, $iovs_len, $nread");
writer.flush();
// check that is isn't standart i/o descriptor
if(fd <= 2) {
// return 0 bytes written if we try to read from the stdin
mem.putInt(nread, 0);
return __WASI_ESUCCESS;
}
val data_ptr = mem.getInt(iovs);
val data_len = mem.getInt(iovs + 4);
val readBytes = openedFiles[fd]!!.readBytes();
val offset = if(openedFilesOffset.containsKey(fd)) {
openedFilesOffset[fd]!!
} else {
0
}
val readBytesCount = min(data_len, readBytes.size - offset);
val tmpMem = ByteArray(readBytesCount);
writer.println("fd_read: $data_ptr $data_len $readBytesCount");
writer.flush();
System.arraycopy(readBytes, offset, tmpMem, 0, readBytesCount);
writer.println("fd_read: $data_ptr $data_len $readBytes $tmpMem");
writer.flush();
openedFilesOffset[fd] = offset + readBytesCount;
val memView = mem.duplicate();
memView.position(data_ptr);
memView.put(tmpMem, 0, readBytesCount);
mem.putInt(nread, readBytesCount);
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Writes data to the file descriptor.
*
* @param fd a file descriptor (opened with writing) to write to
* @param iovs a list of vectors to read data from
* @param iovs_len the length of data in `iovs`
* @param nwritten the number of bytes written
*/
fun fd_write(
fd: __wasi_fd_t,
iovs: Int,
iovs_len: Int,
nwritten: Int
): Int {
val data_ptr = mem.getInt(iovs);
val data_len = mem.getInt(iovs + 4);
val str = readUTF8String(mem, data_ptr, data_len);
writer.println("fd_write: $fd, $iovs, $iovs_len, $nwritten, $str");
writer.flush();
// check that is isn't standart i/o descriptor
if(fd > 2) {
openedFiles[fd]!!.writeText(str);
}
mem.putInt(nwritten, data_len);
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Close an open file descriptor
*
* @param fd a file descriptor mapping to an open file to close
*/
fun fd_close(
fd: __wasi_fd_t
): Int {
writer.println("fd_close: $fd");
writer.flush();
openedFiles.remove(fd);
openedFilesOffset.remove(fd);
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Returns a command-line arguments size.
*
* @param argc the number of arguments
* @param argv_buf_size the size of the argument string data
*/
fun args_sizes_get(
argc: Int,
argv_buf_size: Int
): Int {
writer.println("args_sizes_get: $argc, $argv_buf_size");
writer.flush();
mem.putInt(argc, 0);
mem.putInt(argv_buf_size, 0);
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Reads a command-line arguments.
*
* @param argv a pointer to a buffer to write the argument pointers
* @param argv_buf a pointer to a buffer to write the argument string data
*/
fun args_get(
argv: Int,
argv_buf: Int
): Int {
writer.println("args_get: $argv, $argv_buf");
writer.flush();
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Returns a command-line arguments size.
*
* @param environ_count the number of environment variables
* @param environ_buf_size the size of the environment variable string data
*/
fun environ_sizes_get(
environ_count: Int,
environ_buf_size: Int
): Int {
writer.println("environ_sizes_get: $environ_count, $environ_buf_size");
writer.flush();
mem.putInt(environ_count, 0);
mem.putInt(environ_buf_size, 0);
return __WASI_ESUCCESS;
}
/**
* [Wasm function]
* Reads a command-line arguments.
*/
fun environ_get(
environ: Int,
environ_buf: Int
): Int {
writer.println("environ_get: $environ, $environ_buf");
writer.flush();
return wasiErrorCode;
}
/**
* [Wasm function]
* Reads a command-line arguments.
*
* @param code the exit code
*/
fun proc_exit(code: Int){
writer.println("proc_exit: $code");
writer.flush();
throw ScriptAssertionError(Script.Cmd.Assertion.Trap(Script.Cmd.Action.Get("", ""), "trap"), "proc_exit")
}
}

View File

@ -0,0 +1,12 @@
package asmble.run.jvm.native_modules.wasi
import java.io.File
/**
* Module used for support WASI, contains the realization of several WASI imports
* for operating with file system. Should be registered as 'wasi_unstable'.
*/
data class WASIState (
// mapping between file descriptors and opened file
val openFiles: HashMap<Int, File> = HashMap<Int, File>()
)

View File

@ -0,0 +1,154 @@
package asmble.run.jvm.native_modules.wasi
typealias __wasi_fd_t = Int;
val __WASI_STDIN_FILENO: __wasi_fd_t = 0;
val __WASI_STDOUT_FILENO: __wasi_fd_t = 1;
val __WASI_STDERR_FILENO: __wasi_fd_t = 2;
typealias __wasi_lookupflags_t = Int;
val __WASI_LOOKUP_SYMLINK_FOLLOW: __wasi_lookupflags_t = 1;
typealias __wasi_oflags_t = Int;//Short;
val __WASI_O_CREAT: __wasi_oflags_t = 1;
val __WASI_O_DIRECTORY: __wasi_oflags_t = 2;
val __WASI_O_EXCL: __wasi_oflags_t = 4;
val __WASI_O_TRUNC: __wasi_oflags_t = 8;
val __WASI_ESUCCESS = 0
val __WASI_E2BIG = 1
val __WASI_EACCES = 2
val __WASI_EADDRINUSE = 3
val __WASI_EADDRNOTAVAIL = 4
val __WASI_EAFNOSUPPORT = 5
val __WASI_EAGAIN = 6
val __WASI_EALREADY = 7
val __WASI_EBADF = 8
val __WASI_EBADMSG = 9
val __WASI_EBUSY = 10
val __WASI_ECANCELED = 11
val __WASI_ECHILD = 12
val __WASI_ECONNABORTED = 13
val __WASI_ECONNREFUSED = 14
val __WASI_ECONNRESET = 15
val __WASI_EDEADLK = 16
val __WASI_EDESTADDRREQ = 17
val __WASI_EDOM = 18
val __WASI_EDQUOT = 19
val __WASI_EEXIST = 20
val __WASI_EFAULT = 21
val __WASI_EFBIG = 22
val __WASI_EHOSTUNREACH = 23
val __WASI_EIDRM = 24
val __WASI_EILSEQ = 25
val __WASI_EINPROGRESS = 26
val __WASI_EINTR = 27
val __WASI_EINVAL = 28
val __WASI_EIO = 29
val __WASI_EISCONN = 30
val __WASI_EISDIR = 31
val __WASI_ELOOP = 32
val __WASI_EMFILE = 33
val __WASI_EMLINK = 34
val __WASI_EMSGSIZE = 35
val __WASI_EMULTIHOP = 36
val __WASI_ENAMETOOLONG = 37
val __WASI_ENETDOWN = 38
val __WASI_ENETRESET = 39
val __WASI_ENETUNREACH = 40
val __WASI_ENFILE = 41
val __WASI_ENOBUFS = 42
val __WASI_ENODEV = 43
val __WASI_ENOENT = 44
val __WASI_ENOEXEC = 45
val __WASI_ENOLCK = 46
val __WASI_ENOLINK = 47
val __WASI_ENOMEM = 48
val __WASI_ENOMSG = 49
val __WASI_ENOPROTOOPT = 50
val __WASI_ENOSPC = 51
val __WASI_ENOSYS = 52
val __WASI_ENOTCONN = 53
val __WASI_ENOTDIR = 54
val __WASI_ENOTEMPTY = 55
val __WASI_ENOTRECOVERABLE = 56
val __WASI_ENOTSOCK = 57
val __WASI_ENOTSUP = 58
val __WASI_ENOTTY = 59
val __WASI_ENXIO = 60
val __WASI_EOVERFLOW = 61
val __WASI_EOWNERDEAD = 62
val __WASI_EPERM = 63
val __WASI_EPIPE = 64
val __WASI_EPROTO = 65
val __WASI_EPROTONOSUPPORT = 66
val __WASI_EPROTOTYPE = 67
val __WASI_ERANGE = 68
val __WASI_EROFS = 69
val __WASI_ESPIPE = 70
val __WASI_ESRCH = 71
val __WASI_ESTALE = 72
val __WASI_ETIMEDOUT = 73
val __WASI_ETXTBSY = 74
val __WASI_EXDEV = 75
val __WASI_ENOTCAPABLE = 76
typealias __wasi_filetype_t = Int;//Byte;
val __WASI_FILETYPE_UNKNOWN: __wasi_filetype_t = 0;
val __WASI_FILETYPE_BLOCK_DEVICE: __wasi_filetype_t = 1;
val __WASI_FILETYPE_CHARACTER_DEVICE: __wasi_filetype_t = 2;
val __WASI_FILETYPE_DIRECTORY: __wasi_filetype_t = 3;
val __WASI_FILETYPE_REGULAR_FILE: __wasi_filetype_t = 4;
val __WASI_FILETYPE_SOCKET_DGRAM: __wasi_filetype_t = 5;
val __WASI_FILETYPE_SOCKET_STREAM: __wasi_filetype_t = 6;
val __WASI_FILETYPE_SYMBOLIC_LINK: __wasi_filetype_t = 7;
typealias __wasi_fstflags_t = Int;//Short;
val __WASI_FILESTAT_SET_ATIM: __wasi_fstflags_t = 1;
val __WASI_FILESTAT_SET_ATIM_NOW: __wasi_fstflags_t = 2;
val __WASI_FILESTAT_SET_MTIM: __wasi_fstflags_t = 4;
val __WASI_FILESTAT_SET_MTIM_NOW: __wasi_fstflags_t = 8;
typealias __wasi_fdflags_t = Int;//Short;
val __WASI_FDFLAG_APPEND: __wasi_fdflags_t = 1;
val __WASI_FDFLAG_DSYNC: __wasi_fdflags_t = 2;
val __WASI_FDFLAG_NONBLOCK: __wasi_fdflags_t = 4;
val __WASI_FDFLAG_RSYNC: __wasi_fdflags_t = 8;
val __WASI_FDFLAG_SYNC: __wasi_fdflags_t = 16;
typealias __wasi_rights_t = Long;
val __WASI_RIGHT_FD_DATASYNC: __wasi_rights_t = 1;
val __WASI_RIGHT_FD_READ: __wasi_rights_t = 2;
val __WASI_RIGHT_FD_SEEK: __wasi_rights_t = 4;
val __WASI_RIGHT_FD_FDSTAT_SET_FLAGS: __wasi_rights_t = 8;
val __WASI_RIGHT_FD_SYNC: __wasi_rights_t = 16;
val __WASI_RIGHT_FD_TELL: __wasi_rights_t = 32;
val __WASI_RIGHT_FD_WRITE: __wasi_rights_t = 64;
val __WASI_RIGHT_FD_ADVISE: __wasi_rights_t = 128;
val __WASI_RIGHT_FD_ALLOCATE: __wasi_rights_t = 256;
val __WASI_RIGHT_PATH_CREATE_DIRECTORY: __wasi_rights_t = 512;
val __WASI_RIGHT_PATH_CREATE_FILE: __wasi_rights_t = 1024;
val __WASI_RIGHT_PATH_LINK_SOURCE: __wasi_rights_t = 2048;
val __WASI_RIGHT_PATH_LINK_TARGET: __wasi_rights_t = 4096;
val __WASI_RIGHT_PATH_OPEN: __wasi_rights_t = 8192;
val __WASI_RIGHT_FD_READDIR: __wasi_rights_t = 16384;
val __WASI_RIGHT_PATH_READLINK: __wasi_rights_t = 32768;
val __WASI_RIGHT_PATH_RENAME_SOURCE: __wasi_rights_t = 65536;
val __WASI_RIGHT_PATH_RENAME_TARGET: __wasi_rights_t = 131072;
val __WASI_RIGHT_PATH_FILESTAT_GET: __wasi_rights_t = 262144;
val __WASI_RIGHT_PATH_FILESTAT_SET_SIZE: __wasi_rights_t = 524288;
val __WASI_RIGHT_PATH_FILESTAT_SET_TIMES: __wasi_rights_t = 1048576;
val __WASI_RIGHT_FD_FILESTAT_GET: __wasi_rights_t = 2097152;
val __WASI_RIGHT_FD_FILESTAT_SET_SIZE: __wasi_rights_t = 4194304;
val __WASI_RIGHT_FD_FILESTAT_SET_TIMES: __wasi_rights_t = 8388608;
val __WASI_RIGHT_PATH_SYMLINK: __wasi_rights_t = 16777216;
val __WASI_RIGHT_PATH_UNLINK_FILE: __wasi_rights_t = 33554432;
val __WASI_RIGHT_PATH_REMOVE_DIRECTORY: __wasi_rights_t = 67108864;
val __WASI_RIGHT_POLL_FD_READWRITE: __wasi_rights_t = 134217728;
val __WASI_RIGHT_SOCK_SHUTDOWN: __wasi_rights_t = 268435456;
data class __wasi_fdstat_t (
var fs_filetype: __wasi_filetype_t,
var fs_flags: __wasi_fdflags_t,
var fs_rights_base: __wasi_rights_t,
var fs_rights_inheriting: __wasi_rights_t
)

View File

@ -0,0 +1,17 @@
package asmble.run.jvm.native_modules.wasi
import asmble.compile.jvm.MemoryBuffer
import java.io.PrintWriter
import java.nio.charset.Charset
import kotlin.ByteArray
fun readUTF8String(mem: MemoryBuffer, offset: Int, length: Int): String {
// TODO: too many copying
val duplicatedMem = mem.duplicate();
duplicatedMem.position(offset);
val arr = ByteArray(length);
duplicatedMem.get(arr, 0, length);
return String(arr, 0, length, Charset.forName("UTF-8"));
}

View File

@ -1,6 +1,7 @@
package asmble.run.jvm
import asmble.TestBase
import asmble.run.jvm.native_modules.LoggerModule
import org.junit.Test
import java.io.PrintWriter
import java.io.StringWriter