mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Wasm: support command line args in WASI
This commit is contained in:
parent
1ca2c75e1c
commit
34eb06f5f0
|
@ -104,6 +104,7 @@ import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||||
import org.teavm.backend.wasm.render.WasmBinaryWriter;
|
import org.teavm.backend.wasm.render.WasmBinaryWriter;
|
||||||
import org.teavm.backend.wasm.render.WasmCRenderer;
|
import org.teavm.backend.wasm.render.WasmCRenderer;
|
||||||
import org.teavm.backend.wasm.render.WasmRenderer;
|
import org.teavm.backend.wasm.render.WasmRenderer;
|
||||||
|
import org.teavm.backend.wasm.runtime.WasmSupport;
|
||||||
import org.teavm.backend.wasm.transformation.IndirectCallTraceTransformation;
|
import org.teavm.backend.wasm.transformation.IndirectCallTraceTransformation;
|
||||||
import org.teavm.backend.wasm.transformation.MemoryAccessTraceTransformation;
|
import org.teavm.backend.wasm.transformation.MemoryAccessTraceTransformation;
|
||||||
import org.teavm.backend.wasm.transformation.WasiSupportClassTransformer;
|
import org.teavm.backend.wasm.transformation.WasiSupportClassTransformer;
|
||||||
|
@ -388,6 +389,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
dependencyAnalyzer.linkMethod(new MethodReference(EventQueue.class, "isStopped", boolean.class)).use();
|
dependencyAnalyzer.linkMethod(new MethodReference(EventQueue.class, "isStopped", boolean.class)).use();
|
||||||
dependencyAnalyzer.linkMethod(new MethodReference(Thread.class, "setCurrentThread", Thread.class,
|
dependencyAnalyzer.linkMethod(new MethodReference(Thread.class, "setCurrentThread", Thread.class,
|
||||||
void.class)).use();
|
void.class)).use();
|
||||||
|
dependencyAnalyzer.linkMethod(new MethodReference(WasmSupport.class, "getArgs", String[].class)).use();
|
||||||
|
|
||||||
ClassReader fiberClass = dependencyAnalyzer.getClassSource().get(Fiber.class.getName());
|
ClassReader fiberClass = dependencyAnalyzer.getClassSource().get(Fiber.class.getName());
|
||||||
for (MethodReader method : fiberClass.getMethods()) {
|
for (MethodReader method : fiberClass.getMethods()) {
|
||||||
|
@ -516,7 +518,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
module.add(initFunction);
|
module.add(initFunction);
|
||||||
module.setStartFunction(initFunction);
|
module.setStartFunction(initFunction);
|
||||||
module.add(createStartFunction(names));
|
module.add(createStartFunction(names));
|
||||||
module.add(createStartCallerFunction());
|
module.add(createStartCallerFunction(names));
|
||||||
|
|
||||||
for (String functionName : classGenerator.getFunctionTable()) {
|
for (String functionName : classGenerator.getFunctionTable()) {
|
||||||
WasmFunction function = module.getFunctions().get(functionName);
|
WasmFunction function = module.getFunctions().get(functionName);
|
||||||
|
@ -568,12 +570,14 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
private WasmFunction createStartCallerFunction() {
|
private WasmFunction createStartCallerFunction(NameProvider names) {
|
||||||
WasmFunction function = new WasmFunction("teavm_call_start");
|
WasmFunction function = new WasmFunction("teavm_call_start");
|
||||||
function.setExportName("_start");
|
function.setExportName("_start");
|
||||||
|
|
||||||
|
WasmCall argsCall = new WasmCall(names.forMethod(new MethodReference(WasmSupport.class,
|
||||||
|
"getArgs", String[].class)));
|
||||||
WasmCall call = new WasmCall("teavm_start");
|
WasmCall call = new WasmCall("teavm_start");
|
||||||
call.getArguments().add(new WasmInt32Constant(0));
|
call.getArguments().add(argsCall);
|
||||||
function.getBody().add(call);
|
function.getBody().add(call);
|
||||||
|
|
||||||
return function;
|
return function;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.runtime;
|
package org.teavm.backend.wasm.runtime;
|
||||||
|
|
||||||
|
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.LongResult;
|
import org.teavm.backend.wasm.wasi.LongResult;
|
||||||
import org.teavm.backend.wasm.wasi.SizeResult;
|
import org.teavm.backend.wasm.wasi.SizeResult;
|
||||||
|
@ -65,7 +66,7 @@ public class WasiSupport {
|
||||||
int end = Math.min(s.length(), i + charsInChunk);
|
int end = Math.min(s.length(), i + charsInChunk);
|
||||||
int count = end - i;
|
int count = end - i;
|
||||||
for (int j = 0; j < count; ++j) {
|
for (int j = 0; j < count; ++j) {
|
||||||
buffer.add(offsetInBuffer + j).putByte((byte) s.charAt(j));
|
buffer.add(j).putByte((byte) s.charAt(i + j));
|
||||||
}
|
}
|
||||||
putCharsStderr(buffer, count);
|
putCharsStderr(buffer, count);
|
||||||
}
|
}
|
||||||
|
@ -74,6 +75,8 @@ public class WasiSupport {
|
||||||
@Unmanaged
|
@Unmanaged
|
||||||
public static void printInt(int i) {
|
public static void printInt(int i) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
boolean negative = i < 0;
|
||||||
|
i = Math.abs(i);
|
||||||
Address buffer = WasiBuffer.getBuffer().add(WasiBuffer.getBufferSize());
|
Address buffer = WasiBuffer.getBuffer().add(WasiBuffer.getBufferSize());
|
||||||
do {
|
do {
|
||||||
++count;
|
++count;
|
||||||
|
@ -81,6 +84,11 @@ public class WasiSupport {
|
||||||
buffer.putByte((byte) ((i % 10) + (int) '0'));
|
buffer.putByte((byte) ((i % 10) + (int) '0'));
|
||||||
i /= 10;
|
i /= 10;
|
||||||
} while (i > 0);
|
} while (i > 0);
|
||||||
|
if (negative) {
|
||||||
|
++count;
|
||||||
|
buffer = buffer.add(-1);
|
||||||
|
buffer.putByte((byte) '-');
|
||||||
|
}
|
||||||
putCharsStderr(buffer, count);
|
putCharsStderr(buffer, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,4 +100,34 @@ public class WasiSupport {
|
||||||
@Unmanaged
|
@Unmanaged
|
||||||
public static void initHeapTrace(int maxHeap) {
|
public static void initHeapTrace(int maxHeap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String[] getArgs() {
|
||||||
|
Address buffer = WasiBuffer.getBuffer();
|
||||||
|
SizeResult sizesReceiver = buffer.toStructure();
|
||||||
|
SizeResult bufferSizeReceiver = buffer.add(Structure.sizeOf(SizeResult.class)).toStructure();
|
||||||
|
short errno = Wasi.argsSizesGet(sizesReceiver, bufferSizeReceiver);
|
||||||
|
|
||||||
|
if (errno != Wasi.ERRNO_SUCCESS) {
|
||||||
|
throw new RuntimeException("Could not get command line arguments");
|
||||||
|
}
|
||||||
|
int argvSize = sizesReceiver.value;
|
||||||
|
int argvBufSize = bufferSizeReceiver.value;
|
||||||
|
|
||||||
|
int[] argvOffsets = new int[argvSize];
|
||||||
|
byte[] argvBuffer = new byte[argvBufSize];
|
||||||
|
errno = Wasi.argsGet(Address.ofData(argvOffsets), Address.ofData(argvBuffer));
|
||||||
|
|
||||||
|
if (errno != Wasi.ERRNO_SUCCESS) {
|
||||||
|
throw new RuntimeException("Could not get command line arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] args = new String[argvSize - 1];
|
||||||
|
for (int i = 1; i < argvSize; ++i) {
|
||||||
|
int offset = argvOffsets[i] - Address.ofData(argvBuffer).toInt();
|
||||||
|
int length = (i == argvSize - 1 ? argvBufSize - offset : argvOffsets[i + 1] - argvOffsets[i]) - 1;
|
||||||
|
args[i - 1] = new String(argvBuffer, offset, length, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,4 +49,8 @@ public class WasmSupport {
|
||||||
|
|
||||||
@Import(name = "init", module = "teavmHeapTrace")
|
@Import(name = "init", module = "teavmHeapTrace")
|
||||||
public static native void initHeapTrace(int maxHeap);
|
public static native void initHeapTrace(int maxHeap);
|
||||||
|
|
||||||
|
public static String[] getArgs() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.wasi;
|
package org.teavm.backend.wasm.wasi;
|
||||||
|
|
||||||
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.interop.Import;
|
import org.teavm.interop.Import;
|
||||||
|
|
||||||
public final class Wasi {
|
public final class Wasi {
|
||||||
public static final int CLOCKID_REALTIME = 0;
|
public static final int CLOCKID_REALTIME = 0;
|
||||||
|
public static final short ERRNO_SUCCESS = 0;
|
||||||
|
|
||||||
private Wasi() {
|
private Wasi() {
|
||||||
}
|
}
|
||||||
|
@ -28,4 +30,10 @@ public final class Wasi {
|
||||||
|
|
||||||
@Import(name = "clock_time_get", module = "wasi_snapshot_preview1")
|
@Import(name = "clock_time_get", module = "wasi_snapshot_preview1")
|
||||||
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")
|
||||||
|
public static native short argsSizesGet(SizeResult argvSize, SizeResult argvBufSize);
|
||||||
|
|
||||||
|
@Import(name = "args_get", module = "wasi_snapshot_preview1")
|
||||||
|
public static native short argsGet(Address argv, Address argvBuf);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user