mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CheckStyle-IDEA">
|
<component name="CheckStyle-IDEA" serialisationVersion="2">
|
||||||
<option name="configuration">
|
<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>
|
<map>
|
||||||
<entry key="active-configuration" value="LOCAL_FILE:$PROJECT_DIR$/checkstyle.xml:TeaVM" />
|
<entry key="config_loc" value="." />
|
||||||
<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>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
|
</ConfigurationLocation>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -348,8 +348,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
String.class, void.class)).use();
|
String.class, void.class)).use();
|
||||||
dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "printInt",
|
dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "printInt",
|
||||||
int.class, void.class)).use();
|
int.class, void.class)).use();
|
||||||
dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "printOutOfMemory",
|
dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "printOutOfMemory", void.class)).use();
|
||||||
void.class)).use();
|
|
||||||
|
|
||||||
dependencyAnalyzer.linkMethod(INIT_HEAP_REF).use();
|
dependencyAnalyzer.linkMethod(INIT_HEAP_REF).use();
|
||||||
dependencyAnalyzer.linkMethod(RESIZE_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 ObjectIntrinsic());
|
||||||
context.addIntrinsic(new ConsoleIntrinsic());
|
context.addIntrinsic(new ConsoleIntrinsic());
|
||||||
context.addGenerator(new ArrayGenerator());
|
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 MemoryTraceIntrinsic());
|
||||||
}
|
}
|
||||||
context.addIntrinsic(new WasmHeapIntrinsic());
|
context.addIntrinsic(new WasmHeapIntrinsic(vmAssertions));
|
||||||
context.addIntrinsic(new FiberIntrinsic());
|
context.addIntrinsic(new FiberIntrinsic());
|
||||||
|
|
||||||
IntrinsicFactoryContext intrinsicFactoryContext = new IntrinsicFactoryContext();
|
IntrinsicFactoryContext intrinsicFactoryContext = new IntrinsicFactoryContext();
|
||||||
|
|
|
@ -49,13 +49,13 @@ public class ConsoleIntrinsic implements WasmIntrinsic {
|
||||||
switch (invocation.getMethod().getName()) {
|
switch (invocation.getMethod().getName()) {
|
||||||
case "printString": {
|
case "printString": {
|
||||||
String name = manager.getNames().forMethod(PRINT_STRING);
|
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)));
|
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
case "printInt": {
|
case "printInt": {
|
||||||
String name = manager.getNames().forMethod(PRINT_INT);
|
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)));
|
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ public class GCIntrinsic implements WasmIntrinsic {
|
||||||
return intToLong(getStaticField(manager, "heapSize"));
|
return intToLong(getStaticField(manager, "heapSize"));
|
||||||
case "outOfMemory": {
|
case "outOfMemory": {
|
||||||
WasmBlock block = new WasmBlock(false);
|
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(call);
|
||||||
block.getBody().add(new WasmUnreachable());
|
block.getBody().add(new WasmUnreachable());
|
||||||
return block;
|
return block;
|
||||||
|
|
|
@ -17,17 +17,27 @@ package org.teavm.backend.wasm.intrinsics;
|
||||||
|
|
||||||
import org.teavm.ast.InvocationExpr;
|
import org.teavm.ast.InvocationExpr;
|
||||||
import org.teavm.backend.wasm.WasmHeap;
|
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.WasmExpression;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
public class WasmHeapIntrinsic implements WasmIntrinsic {
|
public class WasmHeapIntrinsic implements WasmIntrinsic {
|
||||||
|
private boolean trace;
|
||||||
|
|
||||||
|
public WasmHeapIntrinsic(boolean trace) {
|
||||||
|
this.trace = trace;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isApplicable(MethodReference methodReference) {
|
public boolean isApplicable(MethodReference methodReference) {
|
||||||
if (!methodReference.getClassName().equals(WasmHeap.class.getName())) {
|
if (!methodReference.getClassName().equals(WasmHeap.class.getName())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (methodReference.getName()) {
|
switch (methodReference.getName()) {
|
||||||
|
case "initHeapTrace":
|
||||||
|
return !trace;
|
||||||
case "growMemory":
|
case "growMemory":
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
@ -38,6 +48,8 @@ public class WasmHeapIntrinsic implements WasmIntrinsic {
|
||||||
@Override
|
@Override
|
||||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||||
switch (invocation.getMethod().getName()) {
|
switch (invocation.getMethod().getName()) {
|
||||||
|
case "initHeapTrace":
|
||||||
|
return new WasmDrop(new WasmInt32Constant(0));
|
||||||
case "growMemory":
|
case "growMemory":
|
||||||
return new WasmMemoryGrow(manager.generate(invocation.getArguments().get(0)));
|
return new WasmMemoryGrow(manager.generate(invocation.getArguments().get(0)));
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import org.teavm.backend.wasm.model.WasmFunction;
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
import org.teavm.backend.wasm.model.WasmLocal;
|
import org.teavm.backend.wasm.model.WasmLocal;
|
||||||
import org.teavm.backend.wasm.model.WasmMemorySegment;
|
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();
|
indent();
|
||||||
|
|
||||||
|
line("wasm_args = argc;");
|
||||||
|
line("wasm_argv = argv;");
|
||||||
renderHeap(module);
|
renderHeap(module);
|
||||||
if (module.getStartFunction() != null) {
|
if (module.getStartFunction() != null) {
|
||||||
line(module.getStartFunction().getName() + "();");
|
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();
|
outdent();
|
||||||
line("}");
|
line("}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,10 +102,6 @@ public class WasiSupport {
|
||||||
printString("Out of memory");
|
printString("Out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmanaged
|
|
||||||
public static void initHeapTrace(int maxHeap) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] getArgs() {
|
public static String[] getArgs() {
|
||||||
Address buffer = WasiBuffer.getBuffer();
|
Address buffer = WasiBuffer.getBuffer();
|
||||||
IntResult sizesReceiver = buffer.toStructure();
|
IntResult sizesReceiver = buffer.toStructure();
|
||||||
|
@ -143,6 +139,7 @@ public class WasiSupport {
|
||||||
|
|
||||||
private static int nextRandom(int bits) {
|
private static int nextRandom(int bits) {
|
||||||
if (!randomInitialized) {
|
if (!randomInitialized) {
|
||||||
|
randomInitialized = true;
|
||||||
short errno = Wasi.randomGet(WasiBuffer.getBuffer(), 8);
|
short errno = Wasi.randomGet(WasiBuffer.getBuffer(), 8);
|
||||||
|
|
||||||
if (errno != ERRNO_SUCCESS) {
|
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.WasiSupport;
|
||||||
import org.teavm.backend.wasm.runtime.WasmSupport;
|
import org.teavm.backend.wasm.runtime.WasmSupport;
|
||||||
|
import org.teavm.interop.Import;
|
||||||
import org.teavm.model.ClassHierarchy;
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassHolderTransformer;
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
|
@ -45,6 +46,7 @@ public class WasiSupportClassTransformer implements ClassHolderTransformer {
|
||||||
if (method.hasModifier(ElementModifier.NATIVE)) {
|
if (method.hasModifier(ElementModifier.NATIVE)) {
|
||||||
method.getModifiers().remove(ElementModifier.NATIVE);
|
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||||
}
|
}
|
||||||
|
method.getAnnotations().remove(Import.class.getName());
|
||||||
ProgramEmitter pe = ProgramEmitter.create(method, classHierarchy);
|
ProgramEmitter pe = ProgramEmitter.create(method, classHierarchy);
|
||||||
ValueEmitter[] args = new ValueEmitter[method.parameterCount()];
|
ValueEmitter[] args = new ValueEmitter[method.parameterCount()];
|
||||||
for (int i = 0; i < args.length; ++i) {
|
for (int i = 0; i < args.length; ++i) {
|
||||||
|
|
|
@ -8,9 +8,12 @@
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <uchar.h>
|
#include <uchar.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
static int8_t *wasm_heap;
|
static int8_t *wasm_heap;
|
||||||
static int32_t wasm_heap_size;
|
static int32_t wasm_heap_size;
|
||||||
|
static int wasm_args;
|
||||||
|
static char** wasm_argv;
|
||||||
|
|
||||||
float teavm_teavm_getNaN() {
|
float teavm_teavm_getNaN() {
|
||||||
return NAN;
|
return NAN;
|
||||||
|
@ -22,7 +25,7 @@ float teavm_teavm_getNaN() {
|
||||||
#define teavmMath_ceil ceil
|
#define teavmMath_ceil ceil
|
||||||
#define teavmMath_floor floor
|
#define teavmMath_floor floor
|
||||||
|
|
||||||
double teavm_currentTimeMillis() {
|
int64_t teavm_currentTimeMillis() {
|
||||||
struct timespec time;
|
struct timespec time;
|
||||||
clock_gettime(CLOCK_REALTIME, &time);
|
clock_gettime(CLOCK_REALTIME, &time);
|
||||||
|
|
||||||
|
@ -75,3 +78,76 @@ void teavm_logString(int32_t string) {
|
||||||
void teavm_logInt(int32_t v) {
|
void teavm_logInt(int32_t v) {
|
||||||
wprintf(L"%" PRId32, 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