diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml index 2c339c219..6f3de1980 100644 --- a/.idea/checkstyle-idea.xml +++ b/.idea/checkstyle-idea.xml @@ -1,19 +1,25 @@ - - \ No newline at end of file diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java index 09cbfb417..d6e35a07b 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java @@ -348,8 +348,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { String.class, void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "printInt", int.class, void.class)).use(); - dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "printOutOfMemory", - void.class)).use(); + dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "printOutOfMemory", void.class)).use(); dependencyAnalyzer.linkMethod(INIT_HEAP_REF).use(); dependencyAnalyzer.linkMethod(RESIZE_HEAP_REF).use(); @@ -471,10 +470,11 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { context.addIntrinsic(new ObjectIntrinsic()); context.addIntrinsic(new ConsoleIntrinsic()); context.addGenerator(new ArrayGenerator()); - if (!Boolean.parseBoolean(System.getProperty("teavm.wasm.vmAssertions", "false"))) { + boolean vmAssertions = Boolean.parseBoolean(System.getProperty("teavm.wasm.vmAssertions", "false")); + if (!vmAssertions) { context.addIntrinsic(new MemoryTraceIntrinsic()); } - context.addIntrinsic(new WasmHeapIntrinsic()); + context.addIntrinsic(new WasmHeapIntrinsic(vmAssertions)); context.addIntrinsic(new FiberIntrinsic()); IntrinsicFactoryContext intrinsicFactoryContext = new IntrinsicFactoryContext(); diff --git a/core/src/main/java/org/teavm/backend/wasm/intrinsics/ConsoleIntrinsic.java b/core/src/main/java/org/teavm/backend/wasm/intrinsics/ConsoleIntrinsic.java index bb591c578..7c184ef41 100644 --- a/core/src/main/java/org/teavm/backend/wasm/intrinsics/ConsoleIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/wasm/intrinsics/ConsoleIntrinsic.java @@ -49,13 +49,13 @@ public class ConsoleIntrinsic implements WasmIntrinsic { switch (invocation.getMethod().getName()) { case "printString": { String name = manager.getNames().forMethod(PRINT_STRING); - WasmCall call = new WasmCall(name, true); + WasmCall call = new WasmCall(name); call.getArguments().add(manager.generate(invocation.getArguments().get(0))); return call; } case "printInt": { String name = manager.getNames().forMethod(PRINT_INT); - WasmCall call = new WasmCall(name, true); + WasmCall call = new WasmCall(name); call.getArguments().add(manager.generate(invocation.getArguments().get(0))); return call; } diff --git a/core/src/main/java/org/teavm/backend/wasm/intrinsics/GCIntrinsic.java b/core/src/main/java/org/teavm/backend/wasm/intrinsics/GCIntrinsic.java index 0b774d93c..43c3e6d65 100644 --- a/core/src/main/java/org/teavm/backend/wasm/intrinsics/GCIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/wasm/intrinsics/GCIntrinsic.java @@ -111,7 +111,7 @@ public class GCIntrinsic implements WasmIntrinsic { return intToLong(getStaticField(manager, "heapSize")); case "outOfMemory": { WasmBlock block = new WasmBlock(false); - WasmCall call = new WasmCall(manager.getNames().forMethod(PRINT_OUT_OF_MEMORY), true); + WasmCall call = new WasmCall(manager.getNames().forMethod(PRINT_OUT_OF_MEMORY)); block.getBody().add(call); block.getBody().add(new WasmUnreachable()); return block; diff --git a/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmHeapIntrinsic.java b/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmHeapIntrinsic.java index dcbd32659..94e577065 100644 --- a/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmHeapIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmHeapIntrinsic.java @@ -17,17 +17,27 @@ package org.teavm.backend.wasm.intrinsics; import org.teavm.ast.InvocationExpr; import org.teavm.backend.wasm.WasmHeap; +import org.teavm.backend.wasm.model.expression.WasmDrop; import org.teavm.backend.wasm.model.expression.WasmExpression; +import org.teavm.backend.wasm.model.expression.WasmInt32Constant; import org.teavm.backend.wasm.model.expression.WasmMemoryGrow; import org.teavm.model.MethodReference; public class WasmHeapIntrinsic implements WasmIntrinsic { + private boolean trace; + + public WasmHeapIntrinsic(boolean trace) { + this.trace = trace; + } + @Override public boolean isApplicable(MethodReference methodReference) { if (!methodReference.getClassName().equals(WasmHeap.class.getName())) { return false; } switch (methodReference.getName()) { + case "initHeapTrace": + return !trace; case "growMemory": return true; default: @@ -38,6 +48,8 @@ public class WasmHeapIntrinsic implements WasmIntrinsic { @Override public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) { switch (invocation.getMethod().getName()) { + case "initHeapTrace": + return new WasmDrop(new WasmInt32Constant(0)); case "growMemory": return new WasmMemoryGrow(manager.generate(invocation.getArguments().get(0))); default: diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderer.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderer.java index 4da803fa8..7db62ca66 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderer.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderer.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmLocal; import org.teavm.backend.wasm.model.WasmMemorySegment; @@ -80,9 +81,11 @@ public class WasmCRenderer { } } - line("void main() {"); + line("void main(int argc, char** argv) {"); indent(); + line("wasm_args = argc;"); + line("wasm_argv = argv;"); renderHeap(module); if (module.getStartFunction() != null) { line(module.getStartFunction().getName() + "();"); @@ -94,6 +97,12 @@ public class WasmCRenderer { } } + for (WasmFunction function : module.getFunctions().values()) { + if (Objects.equals(function.getExportName(), "_start")) { + line(function.getName() + "();"); + } + } + outdent(); line("}"); } diff --git a/core/src/main/java/org/teavm/backend/wasm/runtime/WasiSupport.java b/core/src/main/java/org/teavm/backend/wasm/runtime/WasiSupport.java index 5bc705ef6..7bead97ab 100644 --- a/core/src/main/java/org/teavm/backend/wasm/runtime/WasiSupport.java +++ b/core/src/main/java/org/teavm/backend/wasm/runtime/WasiSupport.java @@ -102,10 +102,6 @@ public class WasiSupport { printString("Out of memory"); } - @Unmanaged - public static void initHeapTrace(int maxHeap) { - } - public static String[] getArgs() { Address buffer = WasiBuffer.getBuffer(); IntResult sizesReceiver = buffer.toStructure(); @@ -143,6 +139,7 @@ public class WasiSupport { private static int nextRandom(int bits) { if (!randomInitialized) { + randomInitialized = true; short errno = Wasi.randomGet(WasiBuffer.getBuffer(), 8); if (errno != ERRNO_SUCCESS) { diff --git a/core/src/main/java/org/teavm/backend/wasm/transformation/WasiSupportClassTransformer.java b/core/src/main/java/org/teavm/backend/wasm/transformation/WasiSupportClassTransformer.java index 578716b23..047896690 100644 --- a/core/src/main/java/org/teavm/backend/wasm/transformation/WasiSupportClassTransformer.java +++ b/core/src/main/java/org/teavm/backend/wasm/transformation/WasiSupportClassTransformer.java @@ -17,6 +17,7 @@ package org.teavm.backend.wasm.transformation; import org.teavm.backend.wasm.runtime.WasiSupport; import org.teavm.backend.wasm.runtime.WasmSupport; +import org.teavm.interop.Import; import org.teavm.model.ClassHierarchy; import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolderTransformer; @@ -45,6 +46,7 @@ public class WasiSupportClassTransformer implements ClassHolderTransformer { if (method.hasModifier(ElementModifier.NATIVE)) { method.getModifiers().remove(ElementModifier.NATIVE); } + method.getAnnotations().remove(Import.class.getName()); ProgramEmitter pe = ProgramEmitter.create(method, classHierarchy); ValueEmitter[] args = new ValueEmitter[method.parameterCount()]; for (int i = 0; i < args.length; ++i) { diff --git a/core/src/main/resources/org/teavm/backend/wasm/wasm-runtime.c b/core/src/main/resources/org/teavm/backend/wasm/wasm-runtime.c index 3b7da14a9..ef3fdbdb0 100644 --- a/core/src/main/resources/org/teavm/backend/wasm/wasm-runtime.c +++ b/core/src/main/resources/org/teavm/backend/wasm/wasm-runtime.c @@ -8,9 +8,12 @@ #include #include #include +#include static int8_t *wasm_heap; static int32_t wasm_heap_size; +static int wasm_args; +static char** wasm_argv; float teavm_teavm_getNaN() { return NAN; @@ -22,7 +25,7 @@ float teavm_teavm_getNaN() { #define teavmMath_ceil ceil #define teavmMath_floor floor -double teavm_currentTimeMillis() { +int64_t teavm_currentTimeMillis() { struct timespec time; clock_gettime(CLOCK_REALTIME, &time); @@ -74,4 +77,77 @@ void teavm_logString(int32_t string) { void teavm_logInt(int32_t v) { wprintf(L"%" PRId32, v); +} + +int32_t wasi_snapshot_preview1_clock_time_get(int32_t clock_id, int64_t precision, int32_t result_ptr) { + int64_t* resultAddr = (int64_t*) (wasm_heap + result_ptr); + *resultAddr = teavm_currentTimeMillis(); + return 0; +} + +int32_t wasi_snapshot_preview1_args_sizes_get(int32_t argv_size, int32_t argv_buffer_size) { + int32_t* argvSizePtr = (int32_t*) (wasm_heap + argv_size); + int32_t* argvBufferSizePtr = (int32_t*) (wasm_heap + argv_buffer_size); + *argvSizePtr = (int32_t) wasm_args; + + int32_t bufferSize = 0; + for (int i = 0; i < wasm_args; ++i) { + bufferSize += (int32_t) strlen(wasm_argv[i]); + } + *argvBufferSizePtr = bufferSize; + return 0; +} + +int32_t wasi_snapshot_preview1_args_get(int32_t sizes_ptr, int32_t args_ptr) { + int32_t* sizesPtr = (int32_t*) (wasm_heap + sizes_ptr); + char* argsPtr = (char*) (wasm_heap + args_ptr); + int offset = 0; + for (int i = 0; i < wasm_args; ++i) { + sizesPtr[i] = (int32_t) offset; + int len = strlen(wasm_argv[i]); + memcpy(argsPtr + offset, wasm_argv[i], len); + offset += len; + } + return 0; +} + +typedef struct { + int32_t tag; + union { + struct { + int32_t name_length; + } dir; + } data; +} WasiPrestat; + +int32_t wasi_snapshot_preview1_fd_prestat_get(int32_t fd, int32_t prestat_ptr) { + if (fd != 3) { + return 8; + } + WasiPrestat* prestat = (WasiPrestat*) (wasm_heap + prestat_ptr); + prestat->tag = 0; + prestat->data.dir.name_length = 1; + return 0; +} + +int32_t wasi_snapshot_preview1_fd_prestat_dir_name(int32_t fd, int32_t path, int32_t path_length) { + char* pathPtr = (char*) (wasm_heap + path); + *pathPtr = '/'; + return 0; +} + +typedef struct { + int32_t buf; + int32_t buf_len; +} WasiIOVec; + +int32_t wasi_snapshot_preview1_fd_write(int32_t fd, int32_t iovs, int32_t count, int32_t result) { + WasiIOVec* vec = (WasiIOVec*) (wasm_heap + iovs); + int32_t written = 0; + for (int32_t i = 0; i < count; ++i) { + written += write((int) fd, (char*) (wasm_heap + vec->buf), vec->buf_len); + } + int32_t* resultPtr = (int32_t*) (wasm_heap + result); + *resultPtr = written; + return 0; } \ No newline at end of file