mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Wasm: support file IO and random generator in WASI
This commit is contained in:
parent
e428e2ac7a
commit
224810d0ab
|
@ -18,6 +18,7 @@ package org.teavm.classlib.java.util;
|
||||||
import java.util.function.DoublePredicate;
|
import java.util.function.DoublePredicate;
|
||||||
import java.util.function.IntPredicate;
|
import java.util.function.IntPredicate;
|
||||||
import java.util.function.LongPredicate;
|
import java.util.function.LongPredicate;
|
||||||
|
import org.teavm.backend.wasm.runtime.WasmSupport;
|
||||||
import org.teavm.classlib.PlatformDetector;
|
import org.teavm.classlib.PlatformDetector;
|
||||||
import org.teavm.classlib.java.io.TSerializable;
|
import org.teavm.classlib.java.io.TSerializable;
|
||||||
import org.teavm.classlib.java.lang.TMath;
|
import org.teavm.classlib.java.lang.TMath;
|
||||||
|
@ -144,6 +145,8 @@ public class TRandom extends TObject implements TSerializable {
|
||||||
public double nextDouble() {
|
public double nextDouble() {
|
||||||
if (PlatformDetector.isC()) {
|
if (PlatformDetector.isC()) {
|
||||||
return crand();
|
return crand();
|
||||||
|
} else if (PlatformDetector.isWebAssembly()) {
|
||||||
|
return WasmSupport.random();
|
||||||
} else {
|
} else {
|
||||||
return random();
|
return random();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ public final class WasmHeap {
|
||||||
public static final int PAGE_SIZE = 65536;
|
public static final int PAGE_SIZE = 65536;
|
||||||
public static final int DEFAULT_STACK_SIZE = PAGE_SIZE * 4;
|
public static final int DEFAULT_STACK_SIZE = PAGE_SIZE * 4;
|
||||||
public static final int DEFAULT_REGION_SIZE = 1024;
|
public static final int DEFAULT_REGION_SIZE = 1024;
|
||||||
|
public static final int DEFAULT_BUFFER_SIZE = 512;
|
||||||
|
|
||||||
public static int minHeapSize;
|
public static int minHeapSize;
|
||||||
public static int maxHeapSize;
|
public static int maxHeapSize;
|
||||||
|
@ -42,6 +43,8 @@ public final class WasmHeap {
|
||||||
public static Address stackAddress;
|
public static Address stackAddress;
|
||||||
public static Address stack;
|
public static Address stack;
|
||||||
public static int stackSize;
|
public static int stackSize;
|
||||||
|
public static Address buffer;
|
||||||
|
public static int bufferSize;
|
||||||
|
|
||||||
private WasmHeap() {
|
private WasmHeap() {
|
||||||
}
|
}
|
||||||
|
@ -64,10 +67,13 @@ public final class WasmHeap {
|
||||||
WasmSupport.initHeapTrace(maxHeap);
|
WasmSupport.initHeapTrace(maxHeap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initHeap(Address start, int minHeap, int maxHeap, int stackSize) {
|
public static void initHeap(Address start, int minHeap, int maxHeap, int stackSize, int bufferSize) {
|
||||||
initHeapTrace(maxHeap);
|
initHeapTrace(maxHeap);
|
||||||
stackAddress = start;
|
buffer = start;
|
||||||
stack = start;
|
buffer = WasmRuntime.align(start, 16);
|
||||||
|
WasmHeap.bufferSize = bufferSize;
|
||||||
|
stack = WasmRuntime.align(buffer.add(bufferSize), 16);
|
||||||
|
stackAddress = stack;
|
||||||
heapAddress = WasmRuntime.align(stackAddress.add(stackSize), 16);
|
heapAddress = WasmRuntime.align(stackAddress.add(stackSize), 16);
|
||||||
memoryLimit = WasmRuntime.align(start, PAGE_SIZE);
|
memoryLimit = WasmRuntime.align(start, PAGE_SIZE);
|
||||||
minHeapSize = minHeap;
|
minHeapSize = minHeap;
|
||||||
|
|
|
@ -175,7 +175,7 @@ import org.teavm.vm.spi.TeaVMHostExtension;
|
||||||
|
|
||||||
public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
private static final MethodReference INIT_HEAP_REF = new MethodReference(WasmHeap.class, "initHeap",
|
private static final MethodReference INIT_HEAP_REF = new MethodReference(WasmHeap.class, "initHeap",
|
||||||
Address.class, int.class, int.class, int.class, void.class);
|
Address.class, int.class, int.class, int.class, int.class, void.class);
|
||||||
private static final MethodReference RESIZE_HEAP_REF = new MethodReference(WasmHeap.class, "resizeHeap",
|
private static final MethodReference RESIZE_HEAP_REF = new MethodReference(WasmHeap.class, "resizeHeap",
|
||||||
int.class, void.class);
|
int.class, void.class);
|
||||||
private static final Set<MethodReference> VIRTUAL_METHODS = new HashSet<>(Arrays.asList(
|
private static final Set<MethodReference> VIRTUAL_METHODS = new HashSet<>(Arrays.asList(
|
||||||
|
@ -621,7 +621,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
|
|
||||||
initFunction.getBody().add(new WasmCall(names.forMethod(INIT_HEAP_REF),
|
initFunction.getBody().add(new WasmCall(names.forMethod(INIT_HEAP_REF),
|
||||||
new WasmInt32Constant(heapAddress), new WasmInt32Constant(minHeapSize),
|
new WasmInt32Constant(heapAddress), new WasmInt32Constant(minHeapSize),
|
||||||
new WasmInt32Constant(maxHeapSize), new WasmInt32Constant(WasmHeap.DEFAULT_STACK_SIZE)));
|
new WasmInt32Constant(maxHeapSize), new WasmInt32Constant(WasmHeap.DEFAULT_STACK_SIZE),
|
||||||
|
new WasmInt32Constant(WasmHeap.DEFAULT_BUFFER_SIZE)));
|
||||||
|
|
||||||
for (Class<?> javaCls : new Class<?>[] { GC.class }) {
|
for (Class<?> javaCls : new Class<?>[] { GC.class }) {
|
||||||
ClassReader cls = classes.get(javaCls.getName());
|
ClassReader cls = classes.get(javaCls.getName());
|
||||||
|
@ -949,6 +950,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
int newRegionsCount = WasmHeap.calculateRegionsCount(maxHeapSize, WasmHeap.DEFAULT_REGION_SIZE);
|
int newRegionsCount = WasmHeap.calculateRegionsCount(maxHeapSize, WasmHeap.DEFAULT_REGION_SIZE);
|
||||||
int newRegionsSize = WasmHeap.calculateRegionsSize(newRegionsCount);
|
int newRegionsSize = WasmHeap.calculateRegionsSize(newRegionsCount);
|
||||||
|
|
||||||
|
address = WasmRuntime.align(address, 16);
|
||||||
|
address = WasmRuntime.align(address + WasmHeap.DEFAULT_BUFFER_SIZE, 16);
|
||||||
address = WasmRuntime.align(address + WasmHeap.DEFAULT_STACK_SIZE, 16);
|
address = WasmRuntime.align(address + WasmHeap.DEFAULT_STACK_SIZE, 16);
|
||||||
address = WasmRuntime.align(address + maxHeapSize, 16);
|
address = WasmRuntime.align(address + maxHeapSize, 16);
|
||||||
address = WasmRuntime.align(address + newRegionsSize, 16);
|
address = WasmRuntime.align(address + newRegionsSize, 16);
|
||||||
|
|
|
@ -15,19 +15,18 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.runtime;
|
package org.teavm.backend.wasm.runtime;
|
||||||
|
|
||||||
|
import org.teavm.backend.wasm.WasmHeap;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
|
|
||||||
public final class WasiBuffer {
|
public final class WasiBuffer {
|
||||||
private static byte[] argBuffer = new byte[256];
|
|
||||||
|
|
||||||
private WasiBuffer() {
|
private WasiBuffer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getBufferSize() {
|
public static int getBufferSize() {
|
||||||
return argBuffer.length;
|
return WasmHeap.bufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Address getBuffer() {
|
public static Address getBuffer() {
|
||||||
return Address.ofData(argBuffer);
|
return WasmHeap.buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.runtime;
|
package org.teavm.backend.wasm.runtime;
|
||||||
|
|
||||||
|
import static org.teavm.backend.wasm.wasi.Wasi.ERRNO_SUCCESS;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import org.teavm.backend.wasm.wasi.IOVec;
|
import org.teavm.backend.wasm.wasi.IOVec;
|
||||||
|
import org.teavm.backend.wasm.wasi.IntResult;
|
||||||
import org.teavm.backend.wasm.wasi.LongResult;
|
import org.teavm.backend.wasm.wasi.LongResult;
|
||||||
import org.teavm.backend.wasm.wasi.SizeResult;
|
import org.teavm.backend.wasm.wasi.SizeResult;
|
||||||
import org.teavm.backend.wasm.wasi.Wasi;
|
import org.teavm.backend.wasm.wasi.Wasi;
|
||||||
|
@ -26,6 +28,9 @@ import org.teavm.interop.Unmanaged;
|
||||||
|
|
||||||
@Unmanaged
|
@Unmanaged
|
||||||
public class WasiSupport {
|
public class WasiSupport {
|
||||||
|
private static long nextRandom;
|
||||||
|
private static boolean randomInitialized;
|
||||||
|
|
||||||
private WasiSupport() {
|
private WasiSupport() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +48,7 @@ public class WasiSupport {
|
||||||
public static void putChars(int fd, Address address, int count) {
|
public static void putChars(int fd, Address address, int count) {
|
||||||
Address argsAddress = WasiBuffer.getBuffer();
|
Address argsAddress = WasiBuffer.getBuffer();
|
||||||
IOVec ioVec = argsAddress.toStructure();
|
IOVec ioVec = argsAddress.toStructure();
|
||||||
SizeResult result = argsAddress.add(Structure.sizeOf(IOVec.class)).toStructure();
|
SizeResult result = Address.align(argsAddress.add(Structure.sizeOf(IOVec.class)), 16).toStructure();
|
||||||
ioVec.buffer = address;
|
ioVec.buffer = address;
|
||||||
ioVec.bufferLength = count;
|
ioVec.bufferLength = count;
|
||||||
Wasi.fdWrite(fd, ioVec, 1, result);
|
Wasi.fdWrite(fd, ioVec, 1, result);
|
||||||
|
@ -51,8 +56,7 @@ public class WasiSupport {
|
||||||
|
|
||||||
@Unmanaged
|
@Unmanaged
|
||||||
public static long currentTimeMillis() {
|
public static long currentTimeMillis() {
|
||||||
Address argsAddress = WasiBuffer.getBuffer();
|
LongResult result = WasiBuffer.getBuffer().toStructure();
|
||||||
LongResult result = argsAddress.toStructure();
|
|
||||||
Wasi.clockTimeGet(Wasi.CLOCKID_REALTIME, 10, result);
|
Wasi.clockTimeGet(Wasi.CLOCKID_REALTIME, 10, result);
|
||||||
return result.value;
|
return result.value;
|
||||||
}
|
}
|
||||||
|
@ -103,21 +107,22 @@ public class WasiSupport {
|
||||||
|
|
||||||
public static String[] getArgs() {
|
public static String[] getArgs() {
|
||||||
Address buffer = WasiBuffer.getBuffer();
|
Address buffer = WasiBuffer.getBuffer();
|
||||||
SizeResult sizesReceiver = buffer.toStructure();
|
IntResult sizesReceiver = buffer.toStructure();
|
||||||
SizeResult bufferSizeReceiver = buffer.add(Structure.sizeOf(SizeResult.class)).toStructure();
|
IntResult bufferSizeReceiver = Address.align(buffer.add(Structure.sizeOf(IntResult.class)), 16)
|
||||||
|
.toStructure();
|
||||||
short errno = Wasi.argsSizesGet(sizesReceiver, bufferSizeReceiver);
|
short errno = Wasi.argsSizesGet(sizesReceiver, bufferSizeReceiver);
|
||||||
|
|
||||||
if (errno != Wasi.ERRNO_SUCCESS) {
|
if (errno != ERRNO_SUCCESS) {
|
||||||
throw new RuntimeException("Could not get command line arguments");
|
throw new RuntimeException("Could not get command line arguments");
|
||||||
}
|
}
|
||||||
int argvSize = sizesReceiver.value;
|
int argvSize = (int) sizesReceiver.value;
|
||||||
int argvBufSize = bufferSizeReceiver.value;
|
int argvBufSize = (int) bufferSizeReceiver.value;
|
||||||
|
|
||||||
int[] argvOffsets = new int[argvSize];
|
int[] argvOffsets = new int[argvSize];
|
||||||
byte[] argvBuffer = new byte[argvBufSize];
|
byte[] argvBuffer = new byte[argvBufSize];
|
||||||
errno = Wasi.argsGet(Address.ofData(argvOffsets), Address.ofData(argvBuffer));
|
errno = Wasi.argsGet(Address.ofData(argvOffsets), Address.ofData(argvBuffer));
|
||||||
|
|
||||||
if (errno != Wasi.ERRNO_SUCCESS) {
|
if (errno != ERRNO_SUCCESS) {
|
||||||
throw new RuntimeException("Could not get command line arguments");
|
throw new RuntimeException("Could not get command line arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,4 +135,23 @@ public class WasiSupport {
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double random() {
|
||||||
|
return (((long) nextRandom(26) << 27) + nextRandom(27)) / (double) (1L << 53);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int nextRandom(int bits) {
|
||||||
|
if (!randomInitialized) {
|
||||||
|
short errno = Wasi.randomGet(WasiBuffer.getBuffer(), 8);
|
||||||
|
|
||||||
|
if (errno != ERRNO_SUCCESS) {
|
||||||
|
throw new RuntimeException("random_get: " + errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
nextRandom = WasiBuffer.getBuffer().getLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
nextRandom = ((nextRandom * 0x5DEECE66DL) + 0xBL) & ((1L << 48) - 1);
|
||||||
|
return (int) (nextRandom >>> (48 - bits));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,4 +53,7 @@ public class WasmSupport {
|
||||||
public static String[] getArgs() {
|
public static String[] getArgs() {
|
||||||
return new String[0];
|
return new String[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Import(module = "teavmMath", name = "random")
|
||||||
|
public static native double random();
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ public class WasiVirtualFile implements VirtualFile {
|
||||||
if (baseFd < 0) {
|
if (baseFd < 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Filestat filestat = Address.align(WasiBuffer.getBuffer(), 8).toStructure();
|
Filestat filestat = WasiBuffer.getBuffer().toStructure();
|
||||||
int errno;
|
int errno;
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
byte[] bytes = path.getBytes(StandardCharsets.UTF_8);
|
byte[] bytes = path.getBytes(StandardCharsets.UTF_8);
|
||||||
|
@ -207,7 +207,7 @@ public class WasiVirtualFile implements VirtualFile {
|
||||||
fdflags |= FDFLAGS_APPEND;
|
fdflags |= FDFLAGS_APPEND;
|
||||||
}
|
}
|
||||||
int fd = open((short) 0, rights, fdflags);
|
int fd = open((short) 0, rights, fdflags);
|
||||||
return fd >= 0 ? new WasiVirtualFileAccessor(fs, fd) : null;
|
return fd >= 0 ? new WasiVirtualFileAccessor(this, fd) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,88 +15,88 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.runtime.fs;
|
package org.teavm.backend.wasm.runtime.fs;
|
||||||
|
|
||||||
|
import static org.teavm.backend.wasm.wasi.Wasi.ERRNO_SUCCESS;
|
||||||
|
import static org.teavm.backend.wasm.wasi.Wasi.WHENCE_CURRENT;
|
||||||
|
import static org.teavm.backend.wasm.wasi.Wasi.WHENCE_START;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.teavm.backend.wasm.runtime.WasiBuffer;
|
import org.teavm.backend.wasm.runtime.WasiBuffer;
|
||||||
|
import org.teavm.backend.wasm.wasi.IOVec;
|
||||||
|
import org.teavm.backend.wasm.wasi.SizeResult;
|
||||||
|
import org.teavm.backend.wasm.wasi.Wasi;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
|
import org.teavm.interop.Structure;
|
||||||
import org.teavm.runtime.fs.VirtualFileAccessor;
|
import org.teavm.runtime.fs.VirtualFileAccessor;
|
||||||
|
|
||||||
public class WasiVirtualFileAccessor implements VirtualFileAccessor {
|
public class WasiVirtualFileAccessor implements VirtualFileAccessor {
|
||||||
// Enough room for an I32 plus padding for alignment:
|
private WasiVirtualFile file;
|
||||||
private static final byte[] EIGHT_BYTE_BUFFER = new byte[8];
|
|
||||||
// Enough room for an I64 plus padding for alignment:
|
|
||||||
private static final byte[] SIXTEEN_BYTE_BUFFER = new byte[16];
|
|
||||||
|
|
||||||
private WasiFileSystem fs;
|
|
||||||
private int fd;
|
private int fd;
|
||||||
|
|
||||||
public WasiVirtualFileAccessor(WasiFileSystem fs, int fd) {
|
WasiVirtualFileAccessor(WasiVirtualFile file, int fd) {
|
||||||
this.fs = fs;
|
this.file = file;
|
||||||
this.fd = fd;
|
this.fd = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||||
byte[] vecBuffer = SIXTEEN_BYTE_BUFFER;
|
Address buf = WasiBuffer.getBuffer();
|
||||||
Address vec = WasiBuffer.getBuffer();
|
IOVec vec = buf.toStructure();
|
||||||
vec.putInt(Address.ofData(buffer).add(offset).toInt());
|
vec.buffer = Address.ofData(buffer).add(offset);
|
||||||
vec.add(4).putInt(length);
|
vec.bufferLength = length;
|
||||||
byte[] sizeBuffer = EIGHT_BYTE_BUFFER;
|
|
||||||
Address size = Address.align(Address.ofData(sizeBuffer), 4);
|
SizeResult sizeResult = Address.align(buf.add(Structure.sizeOf(IOVec.class)), 16).toStructure();
|
||||||
short errno = Wasi.fdRead(fd, vec, 1, size);
|
short errno = Wasi.fdRead(fd, vec, 1, sizeResult);
|
||||||
|
|
||||||
if (errno == ERRNO_SUCCESS) {
|
if (errno == ERRNO_SUCCESS) {
|
||||||
return size.getInt();
|
return (int) sizeResult.value;
|
||||||
} else {
|
} else {
|
||||||
throw new IOException(errnoMessage("fd_read", errno));
|
throw new IOException("fd_read: " + errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(byte[] buffer, int offset, int length) throws IOException {
|
public void write(byte[] buffer, int offset, int length) throws IOException {
|
||||||
byte[] vecBuffer = SIXTEEN_BYTE_BUFFER;
|
Address buf = WasiBuffer.getBuffer();
|
||||||
Address vec = Address.align(Address.ofData(vecBuffer), 4);
|
IOVec vec = buf.toStructure();
|
||||||
byte[] sizeBuffer = EIGHT_BYTE_BUFFER;
|
SizeResult sizeResult = Address.align(buf.add(Structure.sizeOf(IOVec.class)), 16).toStructure();
|
||||||
Address size = Address.align(Address.ofData(sizeBuffer), 4);
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
vec.putInt(Address.ofData(buffer).add(offset + index).toInt());
|
vec.buffer = Address.ofData(buffer).add(offset);
|
||||||
vec.add(4).putInt(length - index);
|
vec.bufferLength = length;
|
||||||
short errno = Wasi.fdWrite(fd, vec, 1, size);
|
short errno = Wasi.fdWrite(fd, vec, 1, sizeResult);
|
||||||
|
|
||||||
if (errno == ERRNO_SUCCESS) {
|
if (errno == ERRNO_SUCCESS) {
|
||||||
index += size.getInt();
|
int size = (int) sizeResult.value;
|
||||||
if (index >= length) {
|
offset += size;
|
||||||
|
length -= size;
|
||||||
|
if (length <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IOException(errnoMessage("fd_write", errno));
|
throw new IOException("fd_write: " + errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int tell() throws IOException {
|
public int tell() throws IOException {
|
||||||
byte[] filesizeBuffer = SIXTEEN_BYTE_BUFFER;
|
SizeResult filesize = WasiBuffer.getBuffer().toStructure();
|
||||||
Address filesize = Address.align(Address.ofData(filesizeBuffer), 8);
|
|
||||||
short errno = Wasi.fdTell(fd, filesize);
|
short errno = Wasi.fdTell(fd, filesize);
|
||||||
|
|
||||||
if (errno == ERRNO_SUCCESS) {
|
if (errno == ERRNO_SUCCESS) {
|
||||||
return (int) filesize.getLong();
|
return (int) filesize.value;
|
||||||
} else {
|
} else {
|
||||||
throw new IOException(errnoMessage("fd_tell", errno));
|
throw new IOException("fd_tell: " + errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long seek(long offset, byte whence) throws IOException {
|
private long seek(long offset, byte whence) throws IOException {
|
||||||
byte[] filesizeBuffer = SIXTEEN_BYTE_BUFFER;
|
SizeResult filesize = WasiBuffer.getBuffer().toStructure();
|
||||||
Address filesize = Address.align(Address.ofData(filesizeBuffer), 8);
|
|
||||||
short errno = Wasi.fdSeek(fd, offset, whence, filesize);
|
short errno = Wasi.fdSeek(fd, offset, whence, filesize);
|
||||||
|
|
||||||
if (errno == ERRNO_SUCCESS) {
|
if (errno == ERRNO_SUCCESS) {
|
||||||
return filesize.getLong();
|
return filesize.value;
|
||||||
} else {
|
} else {
|
||||||
throw new IOException(errnoMessage("fd_seek", errno));
|
throw new IOException("fd_seek: " + errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ public class WasiVirtualFileAccessor implements VirtualFileAccessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() throws IOException {
|
public int size() throws IOException {
|
||||||
return (int) new WasiVirtualFile(fd, null).stat().filesize;
|
return (int) file.stat().filesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,7 +120,7 @@ public class WasiVirtualFileAccessor implements VirtualFileAccessor {
|
||||||
short errno = Wasi.fdFilestatSetSize(fd, size);
|
short errno = Wasi.fdFilestatSetSize(fd, size);
|
||||||
|
|
||||||
if (errno != ERRNO_SUCCESS) {
|
if (errno != ERRNO_SUCCESS) {
|
||||||
throw new IOException(errnoMessage("fd_filestat_set_size", errno));
|
throw new IOException("fd_filestat_set_size" + errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ public class WasiVirtualFileAccessor implements VirtualFileAccessor {
|
||||||
short errno = Wasi.fdClose(fd);
|
short errno = Wasi.fdClose(fd);
|
||||||
|
|
||||||
if (errno != ERRNO_SUCCESS) {
|
if (errno != ERRNO_SUCCESS) {
|
||||||
throw new IOException(errnoMessage("fd_close", errno));
|
throw new IOException("fd_close: " + errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ public class WasiVirtualFileAccessor implements VirtualFileAccessor {
|
||||||
short errno = Wasi.fdSync(fd);
|
short errno = Wasi.fdSync(fd);
|
||||||
|
|
||||||
if (errno != ERRNO_SUCCESS) {
|
if (errno != ERRNO_SUCCESS) {
|
||||||
throw new IOException(errnoMessage("fd_sync", errno));
|
throw new IOException("fd_sync: " + errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.wasi;
|
||||||
|
|
||||||
|
import org.teavm.interop.Structure;
|
||||||
|
|
||||||
|
public class IntResult extends Structure {
|
||||||
|
public int value;
|
||||||
|
}
|
|
@ -18,5 +18,5 @@ package org.teavm.backend.wasm.wasi;
|
||||||
import org.teavm.interop.Structure;
|
import org.teavm.interop.Structure;
|
||||||
|
|
||||||
public class SizeResult extends Structure {
|
public class SizeResult extends Structure {
|
||||||
public int value;
|
public long value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,14 +62,23 @@ public final class Wasi {
|
||||||
public static native short clockTimeGet(int clockId, long precision, LongResult result);
|
public static native short clockTimeGet(int clockId, long precision, LongResult result);
|
||||||
|
|
||||||
@Import(name = "args_sizes_get", module = "wasi_snapshot_preview1")
|
@Import(name = "args_sizes_get", module = "wasi_snapshot_preview1")
|
||||||
public static native short argsSizesGet(SizeResult argvSize, SizeResult argvBufSize);
|
public static native short argsSizesGet(IntResult argvSize, IntResult argvBufSize);
|
||||||
|
|
||||||
@Import(name = "args_get", module = "wasi_snapshot_preview1")
|
@Import(name = "args_get", module = "wasi_snapshot_preview1")
|
||||||
public static native short argsGet(Address argv, Address argvBuf);
|
public static native short argsGet(Address argv, Address argvBuf);
|
||||||
|
|
||||||
|
@Import(name = "fd_read", module = "wasi_snapshot_preview1")
|
||||||
|
public static native short fdRead(int fd, IOVec vecArray, int vecArrayLength, SizeResult size);
|
||||||
|
|
||||||
@Import(name = "fd_write", module = "wasi_snapshot_preview1")
|
@Import(name = "fd_write", module = "wasi_snapshot_preview1")
|
||||||
public static native short fdWrite(int fd, IOVec vectors, int vectorsCont, SizeResult result);
|
public static native short fdWrite(int fd, IOVec vectors, int vectorsCont, SizeResult result);
|
||||||
|
|
||||||
|
@Import(name = "fd_tell", module = "wasi_snapshot_preview1")
|
||||||
|
public static native short fdTell(int fd, SizeResult size);
|
||||||
|
|
||||||
|
@Import(name = "fd_seek", module = "wasi_snapshot_preview1")
|
||||||
|
public static native short fdSeek(int fd, long offset, byte whence, SizeResult size);
|
||||||
|
|
||||||
@Import(name = "fd_prestat_get", module = "wasi_snapshot_preview1")
|
@Import(name = "fd_prestat_get", module = "wasi_snapshot_preview1")
|
||||||
public static native short fdPrestatGet(int fd, Prestat prestat);
|
public static native short fdPrestatGet(int fd, Prestat prestat);
|
||||||
|
|
||||||
|
@ -109,4 +118,14 @@ public final class Wasi {
|
||||||
@Import(name = "path_filestat_set_times", module = "wasi_snapshot_preview1")
|
@Import(name = "path_filestat_set_times", module = "wasi_snapshot_preview1")
|
||||||
public static native short pathFilestatSetTimes(int fd, int lookupFlags, Address path, int pathLength,
|
public static native short pathFilestatSetTimes(int fd, int lookupFlags, Address path, int pathLength,
|
||||||
long atime, long mtime, short fstflags);
|
long atime, long mtime, short fstflags);
|
||||||
|
|
||||||
|
@Import(name = "fd_filestat_set_size", module = "wasi_snapshot_preview1")
|
||||||
|
public static native short fdFilestatSetSize(int fd, long size);
|
||||||
|
|
||||||
|
@Import(name = "fd_sync", module = "wasi_snapshot_preview1")
|
||||||
|
public static native short fdSync(int fd);
|
||||||
|
|
||||||
|
@Import(name = "random_get", module = "wasi_snapshot_preview1")
|
||||||
|
public static native short randomGet(Address buffer, int bufferLength);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user