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 @@
-
-
+
+
+ (bundled)
+ (bundled)
+
+ $PROJECT_DIR$/checkstyle.xml
+
+
+
+
+
\ 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