mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-12-03 01:50:07 +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.WasmCRenderer;
|
||||
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.MemoryAccessTraceTransformation;
|
||||
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(Thread.class, "setCurrentThread", Thread.class,
|
||||
void.class)).use();
|
||||
dependencyAnalyzer.linkMethod(new MethodReference(WasmSupport.class, "getArgs", String[].class)).use();
|
||||
|
||||
ClassReader fiberClass = dependencyAnalyzer.getClassSource().get(Fiber.class.getName());
|
||||
for (MethodReader method : fiberClass.getMethods()) {
|
||||
@ -516,7 +518,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||
module.add(initFunction);
|
||||
module.setStartFunction(initFunction);
|
||||
module.add(createStartFunction(names));
|
||||
module.add(createStartCallerFunction());
|
||||
module.add(createStartCallerFunction(names));
|
||||
|
||||
for (String functionName : classGenerator.getFunctionTable()) {
|
||||
WasmFunction function = module.getFunctions().get(functionName);
|
||||
@ -568,12 +570,14 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||
return function;
|
||||
}
|
||||
|
||||
private WasmFunction createStartCallerFunction() {
|
||||
private WasmFunction createStartCallerFunction(NameProvider names) {
|
||||
WasmFunction function = new WasmFunction("teavm_call_start");
|
||||
function.setExportName("_start");
|
||||
|
||||
WasmCall argsCall = new WasmCall(names.forMethod(new MethodReference(WasmSupport.class,
|
||||
"getArgs", String[].class)));
|
||||
WasmCall call = new WasmCall("teavm_start");
|
||||
call.getArguments().add(new WasmInt32Constant(0));
|
||||
call.getArguments().add(argsCall);
|
||||
function.getBody().add(call);
|
||||
|
||||
return function;
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.teavm.backend.wasm.runtime;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.teavm.backend.wasm.wasi.IOVec;
|
||||
import org.teavm.backend.wasm.wasi.LongResult;
|
||||
import org.teavm.backend.wasm.wasi.SizeResult;
|
||||
@ -65,7 +66,7 @@ public class WasiSupport {
|
||||
int end = Math.min(s.length(), i + charsInChunk);
|
||||
int count = end - i;
|
||||
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);
|
||||
}
|
||||
@ -74,6 +75,8 @@ public class WasiSupport {
|
||||
@Unmanaged
|
||||
public static void printInt(int i) {
|
||||
int count = 0;
|
||||
boolean negative = i < 0;
|
||||
i = Math.abs(i);
|
||||
Address buffer = WasiBuffer.getBuffer().add(WasiBuffer.getBufferSize());
|
||||
do {
|
||||
++count;
|
||||
@ -81,6 +84,11 @@ public class WasiSupport {
|
||||
buffer.putByte((byte) ((i % 10) + (int) '0'));
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
if (negative) {
|
||||
++count;
|
||||
buffer = buffer.add(-1);
|
||||
buffer.putByte((byte) '-');
|
||||
}
|
||||
putCharsStderr(buffer, count);
|
||||
}
|
||||
|
||||
@ -92,4 +100,34 @@ public class WasiSupport {
|
||||
@Unmanaged
|
||||
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")
|
||||
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;
|
||||
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Import;
|
||||
|
||||
public final class Wasi {
|
||||
public static final int CLOCKID_REALTIME = 0;
|
||||
public static final short ERRNO_SUCCESS = 0;
|
||||
|
||||
private Wasi() {
|
||||
}
|
||||
@ -28,4 +30,10 @@ public final class Wasi {
|
||||
|
||||
@Import(name = "clock_time_get", module = "wasi_snapshot_preview1")
|
||||
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