mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
Wasm: trying to revive GC debugger in wasm2c generator and implement emulation for WASI
This commit is contained in:
parent
8285799b2b
commit
4a025f2605
|
@ -1,19 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CheckStyle-IDEA">
|
||||
<option name="configuration">
|
||||
<map>
|
||||
<entry key="active-configuration" value="LOCAL_FILE:$PROJECT_DIR$/checkstyle.xml:TeaVM" />
|
||||
<entry key="checkstyle-version" value="8.41" />
|
||||
<entry key="copy-libs" value="false" />
|
||||
<entry key="location-0" value="BUNDLED:(bundled):Sun Checks" />
|
||||
<entry key="location-1" value="BUNDLED:(bundled):Google Checks" />
|
||||
<entry key="location-2" value="LOCAL_FILE:$PROJECT_DIR$/checkstyle.xml:TeaVM" />
|
||||
<entry key="property-2.config_loc" value="." />
|
||||
<entry key="scan-before-checkin" value="false" />
|
||||
<entry key="scanscope" value="JavaOnlyWithTests" />
|
||||
<entry key="suppress-errors" value="false" />
|
||||
</map>
|
||||
<component name="CheckStyle-IDEA" serialisationVersion="2">
|
||||
<checkstyleVersion>8.41.1</checkstyleVersion>
|
||||
<scanScope>JavaOnlyWithTests</scanScope>
|
||||
<option name="thirdPartyClasspath" />
|
||||
<option name="activeLocationIds">
|
||||
<option value="c65b2ab0-cb40-4423-befb-a37d514deee5" />
|
||||
</option>
|
||||
<option name="locations">
|
||||
<list>
|
||||
<ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
|
||||
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
|
||||
<ConfigurationLocation id="c65b2ab0-cb40-4423-befb-a37d514deee5" type="LOCAL_FILE" scope="All" description="TeaVM">
|
||||
$PROJECT_DIR$/checkstyle.xml
|
||||
<option name="properties">
|
||||
<map>
|
||||
<entry key="config_loc" value="." />
|
||||
</map>
|
||||
</option>
|
||||
</ConfigurationLocation>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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("}");
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -8,9 +8,12 @@
|
|||
#include <wctype.h>
|
||||
#include <time.h>
|
||||
#include <uchar.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user