mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Wasm: initial WASI support
This commit is contained in:
parent
d5cdd740f5
commit
1ca2c75e1c
|
@ -16,7 +16,9 @@
|
|||
package org.teavm.classlib.impl.console;
|
||||
|
||||
import org.teavm.backend.c.intrinsic.RuntimeInclude;
|
||||
import org.teavm.backend.wasm.runtime.WasmSupport;
|
||||
import org.teavm.classlib.PlatformDetector;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Import;
|
||||
import org.teavm.interop.Unmanaged;
|
||||
import org.teavm.jso.JSBody;
|
||||
|
@ -25,30 +27,36 @@ public final class Console {
|
|||
private Console() {
|
||||
}
|
||||
|
||||
public static void writeStderr(int b) {
|
||||
public static void writeStderr(byte[] data, int off, int len) {
|
||||
if (PlatformDetector.isC()) {
|
||||
writeC(b);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte b = data[i + off];
|
||||
writeC(b & 0xFF);
|
||||
}
|
||||
} else if (PlatformDetector.isWebAssembly()) {
|
||||
writeWasm(b);
|
||||
WasmSupport.putCharsStderr(Address.ofData(data).add(off), len);
|
||||
} else {
|
||||
writeJs(b);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte b = data[i + off];
|
||||
writeJs(b & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeStdout(int b) {
|
||||
public static void writeStdout(byte[] data, int off, int len) {
|
||||
if (PlatformDetector.isC()) {
|
||||
writeC(b);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte b = data[i + off];
|
||||
writeC(b & 0xFF);
|
||||
}
|
||||
} else if (PlatformDetector.isWebAssembly()) {
|
||||
writeWasm(b);
|
||||
WasmSupport.putCharsStdout(Address.ofData(data).add(off), len);
|
||||
} else {
|
||||
writeJsStdout(b);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte b = data[i + off];
|
||||
writeJs(b & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeStdout(String s) {
|
||||
for (int i = 0; i < s.length(); ++i) {
|
||||
writeStderr(s.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
@JSBody(params = "b", script = "$rt_putStderr(b);")
|
||||
|
@ -57,9 +65,6 @@ public final class Console {
|
|||
@JSBody(params = "b", script = "$rt_putStdout(b);")
|
||||
private static native void writeJsStdout(int b);
|
||||
|
||||
@Import(name = "putwchar", module = "teavm")
|
||||
private static native void writeWasm(int b);
|
||||
|
||||
@Unmanaged
|
||||
@Import(name = "teavm_logchar")
|
||||
@RuntimeInclude("log.h")
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.impl.console;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public abstract class ConsoleOutputStream extends OutputStream {
|
||||
private byte[] buffer = new byte[1];
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
buffer[0] = (byte) b;
|
||||
write(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void write(byte[] b, int off, int len) throws IOException;
|
||||
}
|
|
@ -16,16 +16,15 @@
|
|||
package org.teavm.classlib.impl.console;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class StderrOutputStream extends OutputStream {
|
||||
public class StderrOutputStream extends ConsoleOutputStream {
|
||||
public static final StderrOutputStream INSTANCE = new StderrOutputStream();
|
||||
|
||||
private StderrOutputStream() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
Console.writeStderr(b);
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
Console.writeStderr(b, off, len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,16 +16,15 @@
|
|||
package org.teavm.classlib.impl.console;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class StdoutOutputStream extends OutputStream {
|
||||
public class StdoutOutputStream extends ConsoleOutputStream {
|
||||
public static final StdoutOutputStream INSTANCE = new StdoutOutputStream();
|
||||
|
||||
private StdoutOutputStream() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
Console.writeStdout(b);
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
Console.writeStdout(b, off, len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.Enumeration;
|
|||
import java.util.Properties;
|
||||
import org.teavm.backend.c.intrinsic.RuntimeInclude;
|
||||
import org.teavm.backend.javascript.spi.GeneratedBy;
|
||||
import org.teavm.backend.wasm.runtime.WasmSupport;
|
||||
import org.teavm.classlib.PlatformDetector;
|
||||
import org.teavm.classlib.fs.VirtualFileSystemProvider;
|
||||
import org.teavm.classlib.fs.c.CFileSystem;
|
||||
|
@ -144,15 +145,12 @@ public final class TSystem extends TObject {
|
|||
|
||||
private static long currentTimeMillisLowLevel() {
|
||||
if (PlatformDetector.isWebAssembly()) {
|
||||
return (long) currentTimeMillisWasm();
|
||||
return WasmSupport.currentTimeMillis();
|
||||
} else {
|
||||
return (long) currentTimeMillisC();
|
||||
return currentTimeMillisC();
|
||||
}
|
||||
}
|
||||
|
||||
@Import(name = "currentTimeMillis", module = "teavm")
|
||||
private static native double currentTimeMillisWasm();
|
||||
|
||||
@Import(name = "teavm_currentTimeMillis")
|
||||
@RuntimeInclude("time.h")
|
||||
private static native long currentTimeMillisC();
|
||||
|
|
|
@ -20,4 +20,6 @@ import org.teavm.vm.spi.TeaVMHostExtension;
|
|||
|
||||
public interface TeaVMWasmHost extends TeaVMHostExtension {
|
||||
void add(WasmIntrinsicFactory intrinsicFactory);
|
||||
|
||||
WasmRuntimeType getRuntimeType();
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
*/
|
||||
package org.teavm.backend.wasm;
|
||||
|
||||
import org.teavm.backend.wasm.runtime.WasmSupport;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Import;
|
||||
import org.teavm.interop.StaticInit;
|
||||
import org.teavm.interop.Unmanaged;
|
||||
|
||||
|
@ -60,8 +60,9 @@ public final class WasmHeap {
|
|||
|
||||
public static native void growMemory(int amount);
|
||||
|
||||
@Import(name = "init", module = "teavmHeapTrace")
|
||||
private static native void initHeapTrace(int maxHeap);
|
||||
private static void initHeapTrace(int maxHeap) {
|
||||
WasmSupport.initHeapTrace(maxHeap);
|
||||
}
|
||||
|
||||
public static void initHeap(Address start, int minHeap, int maxHeap, int stackSize) {
|
||||
initHeapTrace(maxHeap);
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
*/
|
||||
package org.teavm.backend.wasm;
|
||||
|
||||
import org.teavm.backend.wasm.runtime.WasmSupport;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Import;
|
||||
import org.teavm.interop.StaticInit;
|
||||
import org.teavm.interop.Unmanaged;
|
||||
import org.teavm.runtime.RuntimeObject;
|
||||
|
@ -84,17 +84,21 @@ public final class WasmRuntime {
|
|||
return value;
|
||||
}
|
||||
|
||||
@Import(name = "print", module = "spectest")
|
||||
public static native void print(int a);
|
||||
public static void print(int a) {
|
||||
WasmSupport.print(a);
|
||||
}
|
||||
|
||||
@Import(name = "logString", module = "teavm")
|
||||
public static native void printString(String s);
|
||||
public static void printString(String s) {
|
||||
WasmSupport.printString(s);
|
||||
}
|
||||
|
||||
@Import(name = "logInt", module = "teavm")
|
||||
public static native void printInt(int i);
|
||||
public static void printInt(int i) {
|
||||
WasmSupport.printInt(i);
|
||||
}
|
||||
|
||||
@Import(name = "logOutOfMemory", module = "teavm")
|
||||
public static native void printOutOfMemory();
|
||||
public static void printOutOfMemory() {
|
||||
WasmSupport.printOutOfMemory();
|
||||
}
|
||||
|
||||
public static void fillZero(Address address, int count) {
|
||||
fill(address, (byte) 0, count);
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm;
|
||||
|
||||
public enum WasmRuntimeType {
|
||||
TEAVM,
|
||||
WASI
|
||||
}
|
|
@ -106,6 +106,7 @@ import org.teavm.backend.wasm.render.WasmCRenderer;
|
|||
import org.teavm.backend.wasm.render.WasmRenderer;
|
||||
import org.teavm.backend.wasm.transformation.IndirectCallTraceTransformation;
|
||||
import org.teavm.backend.wasm.transformation.MemoryAccessTraceTransformation;
|
||||
import org.teavm.backend.wasm.transformation.WasiSupportClassTransformer;
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.dependency.ClassDependency;
|
||||
import org.teavm.dependency.DependencyAnalyzer;
|
||||
|
@ -199,6 +200,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
|||
private boolean obfuscated;
|
||||
private Set<MethodReference> asyncMethods;
|
||||
private boolean hasThreads;
|
||||
private WasmRuntimeType runtimeType = WasmRuntimeType.TEAVM;
|
||||
|
||||
@Override
|
||||
public void setController(TeaVMTargetController controller) {
|
||||
|
@ -233,6 +235,9 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
|||
List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||
transformers.add(new ClassPatch());
|
||||
transformers.add(new WasmDependencyListener());
|
||||
if (runtimeType == WasmRuntimeType.WASI) {
|
||||
transformers.add(new WasiSupportClassTransformer());
|
||||
}
|
||||
return transformers;
|
||||
}
|
||||
|
||||
|
@ -291,6 +296,15 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
|||
this.obfuscated = obfuscated;
|
||||
}
|
||||
|
||||
public void setRuntimeType(WasmRuntimeType runtimeType) {
|
||||
this.runtimeType = runtimeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmRuntimeType getRuntimeType() {
|
||||
return runtimeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeDependencies(DependencyAnalyzer dependencyAnalyzer) {
|
||||
for (Class<?> type : Arrays.asList(int.class, long.class, float.class, double.class)) {
|
||||
|
@ -502,6 +516,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
|||
module.add(initFunction);
|
||||
module.setStartFunction(initFunction);
|
||||
module.add(createStartFunction(names));
|
||||
module.add(createStartCallerFunction());
|
||||
|
||||
for (String functionName : classGenerator.getFunctionTable()) {
|
||||
WasmFunction function = module.getFunctions().get(functionName);
|
||||
|
@ -553,6 +568,17 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
|||
return function;
|
||||
}
|
||||
|
||||
private WasmFunction createStartCallerFunction() {
|
||||
WasmFunction function = new WasmFunction("teavm_call_start");
|
||||
function.setExportName("_start");
|
||||
|
||||
WasmCall call = new WasmCall("teavm_start");
|
||||
call.getArguments().add(new WasmInt32Constant(0));
|
||||
function.getBody().add(call);
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
private class IntrinsicFactoryContext implements WasmIntrinsicFactoryContext {
|
||||
@Override
|
||||
public ClassReaderSource getClassSource() {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.runtime;
|
||||
|
||||
import org.teavm.interop.Address;
|
||||
|
||||
public final class WasiBuffer {
|
||||
private static byte[] argBuffer = new byte[256];
|
||||
|
||||
private WasiBuffer() {
|
||||
}
|
||||
|
||||
public static int getBufferSize() {
|
||||
return argBuffer.length;
|
||||
}
|
||||
|
||||
public static Address getBuffer() {
|
||||
return Address.ofData(argBuffer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.runtime;
|
||||
|
||||
import org.teavm.backend.wasm.wasi.IOVec;
|
||||
import org.teavm.backend.wasm.wasi.LongResult;
|
||||
import org.teavm.backend.wasm.wasi.SizeResult;
|
||||
import org.teavm.backend.wasm.wasi.Wasi;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Structure;
|
||||
import org.teavm.interop.Unmanaged;
|
||||
|
||||
@Unmanaged
|
||||
public class WasiSupport {
|
||||
private WasiSupport() {
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static void putCharsStdout(Address address, int count) {
|
||||
putChars(1, address, count);
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static void putCharsStderr(Address address, int count) {
|
||||
putChars(2, address, count);
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static void putChars(int fd, Address address, int count) {
|
||||
Address argsAddress = WasiBuffer.getBuffer();
|
||||
IOVec ioVec = argsAddress.toStructure();
|
||||
SizeResult result = argsAddress.add(Structure.sizeOf(IOVec.class)).toStructure();
|
||||
ioVec.buffer = address;
|
||||
ioVec.bufferLength = count;
|
||||
Wasi.fdWrite(fd, ioVec, 1, result);
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static long currentTimeMillis() {
|
||||
Address argsAddress = WasiBuffer.getBuffer();
|
||||
LongResult result = argsAddress.toStructure();
|
||||
Wasi.clockTimeGet(Wasi.CLOCKID_REALTIME, 10, result);
|
||||
return result.value;
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static void printString(String s) {
|
||||
int charsInChunk = 128;
|
||||
int offsetInBuffer = 128;
|
||||
Address buffer = WasiBuffer.getBuffer().add(offsetInBuffer);
|
||||
for (int i = 0; i < s.length(); i += charsInChunk) {
|
||||
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));
|
||||
}
|
||||
putCharsStderr(buffer, count);
|
||||
}
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static void printInt(int i) {
|
||||
int count = 0;
|
||||
Address buffer = WasiBuffer.getBuffer().add(WasiBuffer.getBufferSize());
|
||||
do {
|
||||
++count;
|
||||
buffer = buffer.add(-1);
|
||||
buffer.putByte((byte) ((i % 10) + (int) '0'));
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
putCharsStderr(buffer, count);
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static void printOutOfMemory() {
|
||||
printString("Out of memory");
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static void initHeapTrace(int maxHeap) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.runtime;
|
||||
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Import;
|
||||
|
||||
public class WasmSupport {
|
||||
private WasmSupport() {
|
||||
}
|
||||
|
||||
@Import(name = "putwcharsOut", module = "teavm")
|
||||
public static native void putCharsStderr(Address address, int count);
|
||||
|
||||
@Import(name = "putwcharsErr", module = "teavm")
|
||||
public static native void putCharsStdout(Address address, int count);
|
||||
|
||||
public static long currentTimeMillis() {
|
||||
return (long) currentTimeMillisImpl();
|
||||
}
|
||||
|
||||
@Import(name = "currentTimeMillis", module = "teavm")
|
||||
private static native double currentTimeMillisImpl();
|
||||
|
||||
@Import(name = "print", module = "spectest")
|
||||
public static native void print(int a);
|
||||
|
||||
@Import(name = "logString", module = "teavm")
|
||||
public static native void printString(String s);
|
||||
|
||||
@Import(name = "logInt", module = "teavm")
|
||||
public static native void printInt(int i);
|
||||
|
||||
@Import(name = "logOutOfMemory", module = "teavm")
|
||||
public static native void printOutOfMemory();
|
||||
|
||||
@Import(name = "init", module = "teavmHeapTrace")
|
||||
public static native void initHeapTrace(int maxHeap);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.transformation;
|
||||
|
||||
import org.teavm.backend.wasm.runtime.WasiSupport;
|
||||
import org.teavm.backend.wasm.runtime.WasmSupport;
|
||||
import org.teavm.model.ClassHierarchy;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.ClassHolderTransformerContext;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.emit.ProgramEmitter;
|
||||
import org.teavm.model.emit.ValueEmitter;
|
||||
|
||||
public class WasiSupportClassTransformer implements ClassHolderTransformer {
|
||||
@Override
|
||||
public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) {
|
||||
if (cls.getName().equals(WasmSupport.class.getName())) {
|
||||
transformWasm(cls, context.getHierarchy());
|
||||
}
|
||||
}
|
||||
|
||||
private void transformWasm(ClassHolder cls, ClassHierarchy classHierarchy) {
|
||||
ClassReader sourceCls = classHierarchy.getClassSource().get(WasiSupport.class.getName());
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
MethodReader sourceMethod = sourceCls.getMethod(method.getDescriptor());
|
||||
if (sourceMethod != null) {
|
||||
if (method.hasModifier(ElementModifier.NATIVE)) {
|
||||
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||
}
|
||||
ProgramEmitter pe = ProgramEmitter.create(method, classHierarchy);
|
||||
ValueEmitter[] args = new ValueEmitter[method.parameterCount()];
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
args[i] = pe.var(i + 1, method.parameterType(i));
|
||||
}
|
||||
ValueEmitter result = pe.invoke(sourceMethod.getReference(), args);
|
||||
if (method.getResultType() != ValueType.VOID) {
|
||||
result.returnValue();
|
||||
} else {
|
||||
pe.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
core/src/main/java/org/teavm/backend/wasm/wasi/IOVec.java
Normal file
24
core/src/main/java/org/teavm/backend/wasm/wasi/IOVec.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.wasi;
|
||||
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Structure;
|
||||
|
||||
public class IOVec extends Structure {
|
||||
public Address buffer;
|
||||
public int bufferLength;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.wasi;
|
||||
|
||||
import org.teavm.interop.Structure;
|
||||
|
||||
public class LongResult extends Structure {
|
||||
public long value;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.wasi;
|
||||
|
||||
import org.teavm.interop.Structure;
|
||||
|
||||
public class SizeResult extends Structure {
|
||||
public int value;
|
||||
}
|
31
core/src/main/java/org/teavm/backend/wasm/wasi/Wasi.java
Normal file
31
core/src/main/java/org/teavm/backend/wasm/wasi/Wasi.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2022 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.wasi;
|
||||
|
||||
import org.teavm.interop.Import;
|
||||
|
||||
public final class Wasi {
|
||||
public static final int CLOCKID_REALTIME = 0;
|
||||
|
||||
private Wasi() {
|
||||
}
|
||||
|
||||
@Import(name = "fd_write", module = "wasi_snapshot_preview1")
|
||||
public static native short fdWrite(int fd, IOVec vectors, int vectorsCont, SizeResult result);
|
||||
|
||||
@Import(name = "clock_time_get", module = "wasi_snapshot_preview1")
|
||||
public static native short clockTimeGet(int clockId, long precision, LongResult result);
|
||||
}
|
|
@ -31,6 +31,14 @@ TeaVM.wasm = function() {
|
|||
lineBuffer += String.fromCharCode(charCode);
|
||||
}
|
||||
}
|
||||
function putwchars(buffer, count) {
|
||||
let instance = controller.instance;
|
||||
let memory = instance.exports.memory.buffer;
|
||||
for (let i = 0; i < count; ++i) {
|
||||
// TODO: support UTF-8
|
||||
putwchar(memory[buffer++]);
|
||||
}
|
||||
}
|
||||
function towlower(code) {
|
||||
return String.fromCharCode(code).toLowerCase().charCodeAt(0);
|
||||
}
|
||||
|
@ -90,7 +98,8 @@ TeaVM.wasm = function() {
|
|||
teavm_getNaN: function() { return NaN; },
|
||||
isinf: function(n) { return !isFinite(n) },
|
||||
isfinite: isFinite,
|
||||
putwchar: putwchar,
|
||||
putwcharsOut: (chars, count) => putwchars(controller, chars, count),
|
||||
putwcharsErr: (chars, count) => putwchars(controller, chars, count),
|
||||
towlower: towlower,
|
||||
towupper: towupper,
|
||||
getNativeOffset: getNativeOffset,
|
||||
|
|
|
@ -58,7 +58,7 @@ public final class TeaVMRunner {
|
|||
options.addOption(Option.builder("t")
|
||||
.argName("target")
|
||||
.hasArg()
|
||||
.desc("target type (javascript/js, webassembly/wasm, C)")
|
||||
.desc("target type (javascript/js, webassembly/wasm, webassembly-wasi/wasm-wasi/wasi, C)")
|
||||
.build());
|
||||
options.addOption(Option.builder("d")
|
||||
.argName("directory")
|
||||
|
@ -220,6 +220,11 @@ public final class TeaVMRunner {
|
|||
case "wasm":
|
||||
tool.setTargetType(TeaVMTargetType.WEBASSEMBLY);
|
||||
break;
|
||||
case "webassembly-wasi":
|
||||
case "wasm-wasi":
|
||||
case "wasi":
|
||||
tool.setTargetType(TeaVMTargetType.WEBASSEMBLY);
|
||||
break;
|
||||
case "c":
|
||||
tool.setTargetType(TeaVMTargetType.C);
|
||||
break;
|
||||
|
|
|
@ -18,5 +18,6 @@ package org.teavm.tooling;
|
|||
public enum TeaVMTargetType {
|
||||
JAVASCRIPT,
|
||||
WEBASSEMBLY,
|
||||
WEBASSEMBLY_WASI,
|
||||
C
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.teavm.backend.c.generate.CNameProvider;
|
|||
import org.teavm.backend.c.generate.ShorteningFileNameProvider;
|
||||
import org.teavm.backend.c.generate.SimpleFileNameProvider;
|
||||
import org.teavm.backend.javascript.JavaScriptTarget;
|
||||
import org.teavm.backend.wasm.WasmRuntimeType;
|
||||
import org.teavm.backend.wasm.WasmTarget;
|
||||
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||
import org.teavm.cache.AlwaysStaleCacheStatus;
|
||||
|
@ -315,7 +316,9 @@ public class TeaVMTool {
|
|||
case JAVASCRIPT:
|
||||
return prepareJavaScriptTarget();
|
||||
case WEBASSEMBLY:
|
||||
return prepareWebAssemblyTarget();
|
||||
return prepareWebAssemblyDefaultTarget();
|
||||
case WEBASSEMBLY_WASI:
|
||||
return prepareWebAssemblyWasiTarget();
|
||||
case C:
|
||||
return prepareCTarget();
|
||||
}
|
||||
|
@ -347,6 +350,18 @@ public class TeaVMTool {
|
|||
return webAssemblyTarget;
|
||||
}
|
||||
|
||||
private WasmTarget prepareWebAssemblyDefaultTarget() {
|
||||
WasmTarget target = prepareWebAssemblyTarget();
|
||||
target.setRuntimeType(WasmRuntimeType.TEAVM);
|
||||
return target;
|
||||
}
|
||||
|
||||
private WasmTarget prepareWebAssemblyWasiTarget() {
|
||||
WasmTarget target = prepareWebAssemblyTarget();
|
||||
target.setRuntimeType(WasmRuntimeType.WASI);
|
||||
return target;
|
||||
}
|
||||
|
||||
private CTarget prepareCTarget() {
|
||||
cTarget = new CTarget(new CNameProvider());
|
||||
cTarget.setMinHeapSize(minHeapSize);
|
||||
|
|
Loading…
Reference in New Issue
Block a user