mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-31 12:24:10 -08:00
WASM: implementing support of 0xC binary version
This commit is contained in:
parent
499ce8c029
commit
386c703459
|
@ -32,7 +32,6 @@ import org.teavm.backend.wasm.generate.WasmClassGenerator;
|
||||||
import org.teavm.backend.wasm.generate.WasmDependencyListener;
|
import org.teavm.backend.wasm.generate.WasmDependencyListener;
|
||||||
import org.teavm.backend.wasm.generate.WasmGenerationContext;
|
import org.teavm.backend.wasm.generate.WasmGenerationContext;
|
||||||
import org.teavm.backend.wasm.generate.WasmGenerator;
|
import org.teavm.backend.wasm.generate.WasmGenerator;
|
||||||
import org.teavm.backend.wasm.generate.WasmGeneratorUtil;
|
|
||||||
import org.teavm.backend.wasm.generate.WasmMangling;
|
import org.teavm.backend.wasm.generate.WasmMangling;
|
||||||
import org.teavm.backend.wasm.generate.WasmStringPool;
|
import org.teavm.backend.wasm.generate.WasmStringPool;
|
||||||
import org.teavm.backend.wasm.intrinsics.AddressIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.AddressIntrinsic;
|
||||||
|
@ -57,7 +56,6 @@ import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
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.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
|
@ -72,6 +70,7 @@ import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
import org.teavm.backend.wasm.optimization.UnusedFunctionElimination;
|
import org.teavm.backend.wasm.optimization.UnusedFunctionElimination;
|
||||||
import org.teavm.backend.wasm.patches.ClassPatch;
|
import org.teavm.backend.wasm.patches.ClassPatch;
|
||||||
import org.teavm.backend.wasm.render.WasmBinaryRenderer;
|
import org.teavm.backend.wasm.render.WasmBinaryRenderer;
|
||||||
|
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;
|
||||||
|
@ -131,6 +130,7 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
private ClassInitializerTransformer classInitializerTransformer;
|
private ClassInitializerTransformer classInitializerTransformer;
|
||||||
private ShadowStackTransformer shadowStackTransformer;
|
private ShadowStackTransformer shadowStackTransformer;
|
||||||
private MethodDescriptor clinitDescriptor = new MethodDescriptor("<clinit>", void.class);
|
private MethodDescriptor clinitDescriptor = new MethodDescriptor("<clinit>", void.class);
|
||||||
|
private WasmBinaryVersion version = WasmBinaryVersion.V_0xC;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setController(TeaVMTargetController controller) {
|
public void setController(TeaVMTargetController controller) {
|
||||||
|
@ -189,6 +189,14 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
this.cEmitted = cEmitted;
|
this.cEmitted = cEmitted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmBinaryVersion getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(WasmBinaryVersion version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeDependencies(DependencyChecker dependencyChecker) {
|
public void contributeDependencies(DependencyChecker dependencyChecker) {
|
||||||
for (Class type : Arrays.asList(int.class, long.class, float.class, double.class)) {
|
for (Class type : Arrays.asList(int.class, long.class, float.class, double.class)) {
|
||||||
|
@ -291,7 +299,7 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
|
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
|
||||||
new HashSet<>());
|
new HashSet<>());
|
||||||
WasmStringPool stringPool = new WasmStringPool(classGenerator, binaryWriter);
|
WasmStringPool stringPool = new WasmStringPool(classGenerator, binaryWriter);
|
||||||
WasmGenerationContext context = new WasmGenerationContext(classes, controller.getDiagnostics(),
|
WasmGenerationContext context = new WasmGenerationContext(classes, module, controller.getDiagnostics(),
|
||||||
vtableProvider, tagRegistry, stringPool);
|
vtableProvider, tagRegistry, stringPool);
|
||||||
|
|
||||||
context.addIntrinsic(new AddressIntrinsic(classGenerator));
|
context.addIntrinsic(new AddressIntrinsic(classGenerator));
|
||||||
|
@ -369,7 +377,7 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
WasmBinaryWriter writer = new WasmBinaryWriter();
|
WasmBinaryWriter writer = new WasmBinaryWriter();
|
||||||
WasmBinaryRenderer renderer = new WasmBinaryRenderer(writer);
|
WasmBinaryRenderer renderer = new WasmBinaryRenderer(writer, version);
|
||||||
renderer.render(module);
|
renderer.render(module);
|
||||||
|
|
||||||
try (OutputStream output = buildTarget.createResource(outputName)) {
|
try (OutputStream output = buildTarget.createResource(outputName)) {
|
||||||
|
@ -413,52 +421,59 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
|
|
||||||
private void generateMethods(ListableClassHolderSource classes, WasmGenerationContext context,
|
private void generateMethods(ListableClassHolderSource classes, WasmGenerationContext context,
|
||||||
WasmGenerator generator, WasmModule module) {
|
WasmGenerator generator, WasmModule module) {
|
||||||
|
List<MethodHolder> methods = new ArrayList<>();
|
||||||
for (String className : classes.getClassNames()) {
|
for (String className : classes.getClassNames()) {
|
||||||
ClassHolder cls = classes.get(className);
|
ClassHolder cls = classes.get(className);
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
if (context.getIntrinsic(method.getReference()) != null) {
|
if (context.getIntrinsic(method.getReference()) != null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
module.add(generator.generateDefinition(method.getReference()));
|
||||||
|
methods.add(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MethodHolder implementor = method;
|
for (MethodHolder method : methods) {
|
||||||
AnnotationHolder delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName());
|
ClassHolder cls = classes.get(method.getOwnerName());
|
||||||
if (delegateAnnot != null) {
|
|
||||||
String methodName = delegateAnnot.getValue("value").getString();
|
MethodHolder implementor = method;
|
||||||
boolean found = false;
|
AnnotationHolder delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName());
|
||||||
for (MethodHolder candidate : cls.getMethods()) {
|
if (delegateAnnot != null) {
|
||||||
if (candidate.getName().equals(methodName)) {
|
String methodName = delegateAnnot.getValue("value").getString();
|
||||||
if (found) {
|
boolean found = false;
|
||||||
controller.getDiagnostics().error(new CallLocation(method.getReference()),
|
for (MethodHolder candidate : cls.getMethods()) {
|
||||||
"Method is delegated to " + methodName + " but several implementations "
|
if (candidate.getName().equals(methodName)) {
|
||||||
+ "found");
|
if (found) {
|
||||||
break;
|
controller.getDiagnostics().error(new CallLocation(method.getReference()),
|
||||||
}
|
"Method is delegated to " + methodName + " but several implementations "
|
||||||
implementor = candidate;
|
+ "found");
|
||||||
found = true;
|
break;
|
||||||
}
|
}
|
||||||
|
implementor = candidate;
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (implementor.hasModifier(ElementModifier.NATIVE)) {
|
if (implementor.hasModifier(ElementModifier.NATIVE)) {
|
||||||
if (context.getImportedMethod(method.getReference()) == null) {
|
if (context.getImportedMethod(method.getReference()) == null) {
|
||||||
CallLocation location = new CallLocation(method.getReference());
|
CallLocation location = new CallLocation(method.getReference());
|
||||||
controller.getDiagnostics().error(location, "Method {{m0}} is native but "
|
controller.getDiagnostics().error(location, "Method {{m0}} is native but "
|
||||||
+ "has no {{c1}} annotation on it", method.getReference(), Import.class.getName());
|
+ "has no {{c1}} annotation on it", method.getReference(), Import.class.getName());
|
||||||
}
|
|
||||||
module.add(generator.generateNative(method.getReference()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (implementor.getProgram() == null || implementor.getProgram().basicBlockCount() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (method == implementor) {
|
|
||||||
module.add(generator.generate(method.getReference(), implementor));
|
|
||||||
} else {
|
|
||||||
module.add(generateStub(method, implementor));
|
|
||||||
}
|
|
||||||
if (controller.wasCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
generator.generateNative(method.getReference());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (implementor.getProgram() == null || implementor.getProgram().basicBlockCount() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (method == implementor) {
|
||||||
|
generator.generate(method.getReference(), implementor);
|
||||||
|
} else {
|
||||||
|
generateStub(module, method, implementor);
|
||||||
|
}
|
||||||
|
if (controller.wasCancelled()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,12 +528,14 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
WasmExpression lowerCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.LT_SIGNED,
|
WasmExpression lowerCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.LT_SIGNED,
|
||||||
new WasmGetLocal(subtypeVar), new WasmInt32Constant(lower));
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(lower));
|
||||||
WasmConditional testLower = new WasmConditional(lowerCondition);
|
WasmConditional testLower = new WasmConditional(lowerCondition);
|
||||||
|
testLower.setType(WasmType.INT32);
|
||||||
testLower.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
testLower.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
body.add(testLower);
|
body.add(testLower);
|
||||||
|
|
||||||
WasmExpression upperCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.GT_SIGNED,
|
WasmExpression upperCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.GT_SIGNED,
|
||||||
new WasmGetLocal(subtypeVar), new WasmInt32Constant(upper));
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(upper));
|
||||||
WasmConditional testUpper = new WasmConditional(upperCondition);
|
WasmConditional testUpper = new WasmConditional(upperCondition);
|
||||||
|
testLower.setType(WasmType.INT32);
|
||||||
testUpper.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
testUpper.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
body.add(testUpper);
|
body.add(testUpper);
|
||||||
|
|
||||||
|
@ -555,6 +572,7 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
WasmExpression itemCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ,
|
WasmExpression itemCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ,
|
||||||
new WasmGetLocal(subtypeVar), new WasmInt32Constant(0));
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(0));
|
||||||
WasmConditional itemTest = new WasmConditional(itemCondition);
|
WasmConditional itemTest = new WasmConditional(itemCondition);
|
||||||
|
itemTest.setType(WasmType.INT32);
|
||||||
itemTest.getThenBlock().getBody().add(new WasmInt32Constant(0));
|
itemTest.getThenBlock().getBody().add(new WasmInt32Constant(0));
|
||||||
|
|
||||||
WasmCall delegateToItem = new WasmCall(WasmMangling.mangleIsSupertype(itemType));
|
WasmCall delegateToItem = new WasmCall(WasmMangling.mangleIsSupertype(itemType));
|
||||||
|
@ -564,15 +582,8 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
body.add(new WasmReturn(itemTest));
|
body.add(new WasmReturn(itemTest));
|
||||||
}
|
}
|
||||||
|
|
||||||
private WasmFunction generateStub(MethodHolder method, MethodHolder implementor) {
|
private WasmFunction generateStub(WasmModule module, MethodHolder method, MethodHolder implementor) {
|
||||||
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(method.getReference()));
|
WasmFunction function = module.getFunctions().get(WasmMangling.mangleMethod(method.getReference()));
|
||||||
if (!method.hasModifier(ElementModifier.STATIC)) {
|
|
||||||
function.getParameters().add(WasmType.INT32);
|
|
||||||
}
|
|
||||||
ValueType[] parameterTypes = method.getParameterTypes();
|
|
||||||
for (ValueType parameterType : parameterTypes) {
|
|
||||||
function.getParameters().add(WasmGeneratorUtil.mapType(parameterType));
|
|
||||||
}
|
|
||||||
|
|
||||||
WasmCall call = new WasmCall(WasmMangling.mangleMethod(implementor.getReference()));
|
WasmCall call = new WasmCall(WasmMangling.mangleMethod(implementor.getReference()));
|
||||||
for (WasmType param : function.getParameters()) {
|
for (WasmType param : function.getParameters()) {
|
||||||
|
@ -581,10 +592,8 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
call.getArguments().add(new WasmGetLocal(local));
|
call.getArguments().add(new WasmGetLocal(local));
|
||||||
}
|
}
|
||||||
|
|
||||||
function.setResult(WasmGeneratorUtil.mapType(method.getResultType()));
|
|
||||||
|
|
||||||
if (method.getResultType() == ValueType.VOID) {
|
if (method.getResultType() == ValueType.VOID) {
|
||||||
function.getBody().add(new WasmDrop(call));
|
function.getBody().add(call);
|
||||||
} else {
|
} else {
|
||||||
function.getBody().add(new WasmReturn(call));
|
function.getBody().add(new WasmReturn(call));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.interop.Import;
|
import org.teavm.interop.Import;
|
||||||
import org.teavm.model.AnnotationReader;
|
import org.teavm.model.AnnotationReader;
|
||||||
|
@ -36,6 +38,7 @@ import org.teavm.model.classes.VirtualTableProvider;
|
||||||
|
|
||||||
public class WasmGenerationContext {
|
public class WasmGenerationContext {
|
||||||
private ClassReaderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
|
private WasmModule module;
|
||||||
private Diagnostics diagnostics;
|
private Diagnostics diagnostics;
|
||||||
private VirtualTableProvider vtableProvider;
|
private VirtualTableProvider vtableProvider;
|
||||||
private TagRegistry tagRegistry;
|
private TagRegistry tagRegistry;
|
||||||
|
@ -44,9 +47,10 @@ public class WasmGenerationContext {
|
||||||
private List<WasmIntrinsic> intrinsics = new ArrayList<>();
|
private List<WasmIntrinsic> intrinsics = new ArrayList<>();
|
||||||
private Map<MethodReference, WasmIntrinsicHolder> intrinsicCache = new HashMap<>();
|
private Map<MethodReference, WasmIntrinsicHolder> intrinsicCache = new HashMap<>();
|
||||||
|
|
||||||
public WasmGenerationContext(ClassReaderSource classSource, Diagnostics diagnostics,
|
public WasmGenerationContext(ClassReaderSource classSource, WasmModule module, Diagnostics diagnostics,
|
||||||
VirtualTableProvider vtableProvider, TagRegistry tagRegistry, WasmStringPool stringPool) {
|
VirtualTableProvider vtableProvider, TagRegistry tagRegistry, WasmStringPool stringPool) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
|
this.module = module;
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
this.vtableProvider = vtableProvider;
|
this.vtableProvider = vtableProvider;
|
||||||
this.tagRegistry = tagRegistry;
|
this.tagRegistry = tagRegistry;
|
||||||
|
@ -97,6 +101,10 @@ public class WasmGenerationContext {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmFunction getFunction(String name) {
|
||||||
|
return module.getFunctions().get(name);
|
||||||
|
}
|
||||||
|
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return classSource;
|
return classSource;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,7 @@ import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
|
import org.teavm.backend.wasm.render.WasmTypeInference;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
@ -122,6 +123,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
private static FieldReference tagField = new FieldReference(RuntimeClass.class.getName(), "tag");
|
private static FieldReference tagField = new FieldReference(RuntimeClass.class.getName(), "tag");
|
||||||
private WasmGenerationContext context;
|
private WasmGenerationContext context;
|
||||||
private WasmClassGenerator classGenerator;
|
private WasmClassGenerator classGenerator;
|
||||||
|
private WasmTypeInference typeInference;
|
||||||
private WasmFunction function;
|
private WasmFunction function;
|
||||||
private int firstVariable;
|
private int firstVariable;
|
||||||
private IdentifiedStatement currentContinueTarget;
|
private IdentifiedStatement currentContinueTarget;
|
||||||
|
@ -145,6 +147,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
for (int i = 0; i < typeCount; ++i) {
|
for (int i = 0; i < typeCount; ++i) {
|
||||||
temporaryVariablesByType.add(new ArrayDeque<>());
|
temporaryVariablesByType.add(new ArrayDeque<>());
|
||||||
}
|
}
|
||||||
|
typeInference = new WasmTypeInference(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void accept(Expr expr) {
|
private void accept(Expr expr) {
|
||||||
|
@ -330,6 +333,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
|
|
||||||
private void generateAnd(BinaryExpr expr) {
|
private void generateAnd(BinaryExpr expr) {
|
||||||
WasmBlock block = new WasmBlock(false);
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
block.setType(WasmType.INT32);
|
||||||
|
|
||||||
accept(expr.getFirstOperand());
|
accept(expr.getFirstOperand());
|
||||||
WasmBranch branch = new WasmBranch(negate(result), block);
|
WasmBranch branch = new WasmBranch(negate(result), block);
|
||||||
|
@ -348,6 +352,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
|
|
||||||
private void generateOr(BinaryExpr expr) {
|
private void generateOr(BinaryExpr expr) {
|
||||||
WasmBlock block = new WasmBlock(false);
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
block.setType(WasmType.INT32);
|
||||||
|
|
||||||
accept(expr.getFirstOperand());
|
accept(expr.getFirstOperand());
|
||||||
WasmBranch branch = new WasmBranch(result, block);
|
WasmBranch branch = new WasmBranch(result, block);
|
||||||
|
@ -450,8 +455,11 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
Expr left = statement.getLeftValue();
|
Expr left = statement.getLeftValue();
|
||||||
if (left == null) {
|
if (left == null) {
|
||||||
accept(statement.getRightValue());
|
accept(statement.getRightValue());
|
||||||
result = new WasmDrop(result);
|
result.acceptVisitor(typeInference);
|
||||||
result.setLocation(statement.getLocation());
|
if (typeInference.getResult() != null) {
|
||||||
|
result = new WasmDrop(result);
|
||||||
|
result.setLocation(statement.getLocation());
|
||||||
|
}
|
||||||
} else if (left instanceof VariableExpr) {
|
} else if (left instanceof VariableExpr) {
|
||||||
VariableExpr varExpr = (VariableExpr) left;
|
VariableExpr varExpr = (VariableExpr) left;
|
||||||
WasmLocal local = function.getLocalVariables().get(varExpr.getIndex() - firstVariable);
|
WasmLocal local = function.getLocalVariables().get(varExpr.getIndex() - firstVariable);
|
||||||
|
@ -552,6 +560,13 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
accept(expr.getAlternative());
|
accept(expr.getAlternative());
|
||||||
conditional.getElseBlock().getBody().add(result);
|
conditional.getElseBlock().getBody().add(result);
|
||||||
|
|
||||||
|
conditional.getThenBlock().acceptVisitor(typeInference);
|
||||||
|
WasmType thenType = typeInference.getResult();
|
||||||
|
conditional.getElseBlock().acceptVisitor(typeInference);
|
||||||
|
WasmType elseType = typeInference.getResult();
|
||||||
|
assert thenType == elseType;
|
||||||
|
conditional.setType(thenType);
|
||||||
|
|
||||||
result = conditional;
|
result = conditional;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,6 +848,8 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
result = call;
|
result = call;
|
||||||
} else if (expr.getType() == InvocationType.CONSTRUCTOR) {
|
} else if (expr.getType() == InvocationType.CONSTRUCTOR) {
|
||||||
WasmBlock block = new WasmBlock(false);
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
block.setType(WasmType.INT32);
|
||||||
|
|
||||||
WasmLocal tmp = getTemporary(WasmType.INT32);
|
WasmLocal tmp = getTemporary(WasmType.INT32);
|
||||||
block.getBody().add(new WasmSetLocal(tmp, allocateObject(expr.getMethod().getClassName(),
|
block.getBody().add(new WasmSetLocal(tmp, allocateObject(expr.getMethod().getClassName(),
|
||||||
expr.getLocation())));
|
expr.getLocation())));
|
||||||
|
@ -854,6 +871,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
accept(expr.getArguments().get(0));
|
accept(expr.getArguments().get(0));
|
||||||
WasmExpression instance = result;
|
WasmExpression instance = result;
|
||||||
WasmBlock block = new WasmBlock(false);
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
block.setType(WasmGeneratorUtil.mapType(expr.getMethod().getReturnType()));
|
||||||
|
|
||||||
WasmLocal instanceVar = getTemporary(WasmType.INT32);
|
WasmLocal instanceVar = getTemporary(WasmType.INT32);
|
||||||
block.getBody().add(new WasmSetLocal(instanceVar, instance));
|
block.getBody().add(new WasmSetLocal(instanceVar, instance));
|
||||||
|
@ -1135,6 +1153,8 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
ValueType type = expr.getType();
|
ValueType type = expr.getType();
|
||||||
|
|
||||||
WasmBlock block = new WasmBlock(false);
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
block.setType(WasmType.INT32);
|
||||||
|
|
||||||
int dimensionList = -1;
|
int dimensionList = -1;
|
||||||
for (Expr dimension : expr.getDimensions()) {
|
for (Expr dimension : expr.getDimensions()) {
|
||||||
int dimensionAddress = binaryWriter.append(DataPrimitives.INT.createValue());
|
int dimensionAddress = binaryWriter.append(DataPrimitives.INT.createValue());
|
||||||
|
@ -1180,7 +1200,9 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
ranges.sort(Comparator.comparingInt(range -> range.lower));
|
ranges.sort(Comparator.comparingInt(range -> range.lower));
|
||||||
|
|
||||||
WasmBlock block = new WasmBlock(false);
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
block.setType(WasmType.INT32);
|
||||||
block.setLocation(expr.getLocation());
|
block.setLocation(expr.getLocation());
|
||||||
|
|
||||||
WasmLocal tagVar = getTemporary(WasmType.INT32);
|
WasmLocal tagVar = getTemporary(WasmType.INT32);
|
||||||
int tagOffset = classGenerator.getFieldOffset(tagField);
|
int tagOffset = classGenerator.getFieldOffset(tagField);
|
||||||
WasmExpression tagPtr = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
WasmExpression tagPtr = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
||||||
|
@ -1204,6 +1226,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
WasmIntBinaryOperation.GT_SIGNED, new WasmGetLocal(tagVar),
|
WasmIntBinaryOperation.GT_SIGNED, new WasmGetLocal(tagVar),
|
||||||
new WasmInt32Constant(ranges.get(i - 1).upper));
|
new WasmInt32Constant(ranges.get(i - 1).upper));
|
||||||
WasmConditional conditional = new WasmConditional(upperThanExcluded);
|
WasmConditional conditional = new WasmConditional(upperThanExcluded);
|
||||||
|
conditional.setType(WasmType.INT32);
|
||||||
WasmExpression lowerThanExcluded = new WasmIntBinary(WasmIntType.INT32,
|
WasmExpression lowerThanExcluded = new WasmIntBinary(WasmIntType.INT32,
|
||||||
WasmIntBinaryOperation.LT_SIGNED, new WasmGetLocal(tagVar),
|
WasmIntBinaryOperation.LT_SIGNED, new WasmGetLocal(tagVar),
|
||||||
new WasmInt32Constant(ranges.get(i).lower));
|
new WasmInt32Constant(ranges.get(i).lower));
|
||||||
|
|
|
@ -47,12 +47,30 @@ public class WasmGenerator {
|
||||||
this.binaryWriter = binaryWriter;
|
this.binaryWriter = binaryWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmFunction generateDefinition(MethodReference methodReference) {
|
||||||
|
ClassHolder cls = classSource.get(methodReference.getClassName());
|
||||||
|
MethodHolder method = cls.getMethod(methodReference.getDescriptor());
|
||||||
|
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(method.getReference()));
|
||||||
|
|
||||||
|
if (!method.hasModifier(ElementModifier.STATIC)) {
|
||||||
|
function.getParameters().add(WasmType.INT32);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < method.parameterCount(); ++i) {
|
||||||
|
function.getParameters().add(WasmGeneratorUtil.mapType(method.parameterType(i)));
|
||||||
|
}
|
||||||
|
if (method.getResultType() != ValueType.VOID) {
|
||||||
|
function.setResult(WasmGeneratorUtil.mapType(method.getResultType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
public WasmFunction generate(MethodReference methodReference, MethodHolder bodyMethod) {
|
public WasmFunction generate(MethodReference methodReference, MethodHolder bodyMethod) {
|
||||||
ClassHolder cls = classSource.get(methodReference.getClassName());
|
ClassHolder cls = classSource.get(methodReference.getClassName());
|
||||||
MethodHolder method = cls.getMethod(methodReference.getDescriptor());
|
MethodHolder method = cls.getMethod(methodReference.getDescriptor());
|
||||||
|
|
||||||
RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod);
|
RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod);
|
||||||
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(methodReference));
|
WasmFunction function = context.getFunction(WasmMangling.mangleMethod(methodReference));
|
||||||
int firstVariable = method.hasModifier(ElementModifier.STATIC) ? 1 : 0;
|
int firstVariable = method.hasModifier(ElementModifier.STATIC) ? 1 : 0;
|
||||||
for (int i = firstVariable; i < methodAst.getVariables().size(); ++i) {
|
for (int i = firstVariable; i < methodAst.getVariables().size(); ++i) {
|
||||||
VariableNode variable = methodAst.getVariables().get(i);
|
VariableNode variable = methodAst.getVariables().get(i);
|
||||||
|
@ -62,13 +80,6 @@ public class WasmGenerator {
|
||||||
function.add(new WasmLocal(type, variable.getName()));
|
function.add(new WasmLocal(type, variable.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = firstVariable; i <= methodReference.parameterCount(); ++i) {
|
|
||||||
function.getParameters().add(function.getLocalVariables().get(i - firstVariable).getType());
|
|
||||||
}
|
|
||||||
if (methodReference.getReturnType() != ValueType.VOID) {
|
|
||||||
function.setResult(WasmGeneratorUtil.mapType(methodReference.getReturnType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, binaryWriter, function,
|
WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, binaryWriter, function,
|
||||||
firstVariable);
|
firstVariable);
|
||||||
methodAst.getBody().acceptVisitor(visitor);
|
methodAst.getBody().acceptVisitor(visitor);
|
||||||
|
@ -83,12 +94,7 @@ public class WasmGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmFunction generateNative(MethodReference methodReference) {
|
public WasmFunction generateNative(MethodReference methodReference) {
|
||||||
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(methodReference));
|
WasmFunction function = context.getFunction(WasmMangling.mangleMethod(methodReference));
|
||||||
for (int i = 0; i < methodReference.parameterCount(); ++i) {
|
|
||||||
WasmType paramType = WasmGeneratorUtil.mapType(methodReference.parameterType(i));
|
|
||||||
function.getParameters().add(paramType);
|
|
||||||
}
|
|
||||||
function.setResult(WasmGeneratorUtil.mapType(methodReference.getReturnType()));
|
|
||||||
|
|
||||||
WasmGenerationContext.ImportedMethod importedMethod = context.getImportedMethod(methodReference);
|
WasmGenerationContext.ImportedMethod importedMethod = context.getImportedMethod(methodReference);
|
||||||
if (importedMethod != null) {
|
if (importedMethod != null) {
|
||||||
|
|
|
@ -17,10 +17,12 @@ package org.teavm.backend.wasm.model.expression;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
|
||||||
public class WasmBlock extends WasmExpression {
|
public class WasmBlock extends WasmExpression {
|
||||||
private boolean loop;
|
private boolean loop;
|
||||||
private List<WasmExpression> body = new ArrayList<>();
|
private List<WasmExpression> body = new ArrayList<>();
|
||||||
|
private WasmType type;
|
||||||
|
|
||||||
public WasmBlock(boolean loop) {
|
public WasmBlock(boolean loop) {
|
||||||
this.loop = loop;
|
this.loop = loop;
|
||||||
|
@ -38,6 +40,14 @@ public class WasmBlock extends WasmExpression {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(WasmType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -16,11 +16,13 @@
|
||||||
package org.teavm.backend.wasm.model.expression;
|
package org.teavm.backend.wasm.model.expression;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
|
||||||
public class WasmConditional extends WasmExpression {
|
public class WasmConditional extends WasmExpression {
|
||||||
private WasmExpression condition;
|
private WasmExpression condition;
|
||||||
private WasmBlock thenBlock = new WasmBlock(false);
|
private WasmBlock thenBlock = new WasmBlock(false);
|
||||||
private WasmBlock elseBlock = new WasmBlock(false);
|
private WasmBlock elseBlock = new WasmBlock(false);
|
||||||
|
private WasmType type;
|
||||||
|
|
||||||
public WasmConditional(WasmExpression condition) {
|
public WasmConditional(WasmExpression condition) {
|
||||||
Objects.requireNonNull(condition);
|
Objects.requireNonNull(condition);
|
||||||
|
@ -44,6 +46,14 @@ public class WasmConditional extends WasmExpression {
|
||||||
return elseBlock;
|
return elseBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(WasmType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -28,19 +28,43 @@ import org.teavm.backend.wasm.model.WasmType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
|
||||||
public class WasmBinaryRenderer {
|
public class WasmBinaryRenderer {
|
||||||
|
private static final int SECTION_UNKNOWN = 0;
|
||||||
|
private static final int SECTION_TYPE = 1;
|
||||||
|
private static final int SECTION_IMPORT = 2;
|
||||||
|
private static final int SECTION_FUNCTION = 3;
|
||||||
|
private static final int SECTION_TABLE = 4;
|
||||||
|
private static final int SECTION_MEMORY = 5;
|
||||||
|
private static final int SECTION_EXPORT = 7;
|
||||||
|
private static final int SECTION_START = 8;
|
||||||
|
private static final int SECTION_ELEMENT = 9;
|
||||||
|
private static final int SECTION_CODE = 10;
|
||||||
|
private static final int SECTION_DATA = 11;
|
||||||
|
|
||||||
|
private static final int EXTERNAL_KIND_FUNCTION = 0;
|
||||||
|
|
||||||
private WasmBinaryWriter output;
|
private WasmBinaryWriter output;
|
||||||
|
private WasmBinaryVersion version;
|
||||||
private List<WasmSignature> signatures = new ArrayList<>();
|
private List<WasmSignature> signatures = new ArrayList<>();
|
||||||
private Map<WasmSignature, Integer> signatureIndexes = new HashMap<>();
|
private Map<WasmSignature, Integer> signatureIndexes = new HashMap<>();
|
||||||
private Map<String, Integer> importIndexes = new HashMap<>();
|
private Map<String, Integer> importIndexes = new HashMap<>();
|
||||||
private Map<String, Integer> functionIndexes = new HashMap<>();
|
private Map<String, Integer> functionIndexes = new HashMap<>();
|
||||||
|
|
||||||
public WasmBinaryRenderer(WasmBinaryWriter output) {
|
public WasmBinaryRenderer(WasmBinaryWriter output, WasmBinaryVersion version) {
|
||||||
this.output = output;
|
this.output = output;
|
||||||
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(WasmModule module) {
|
public void render(WasmModule module) {
|
||||||
output.writeInt32(0x6d736100);
|
output.writeInt32(0x6d736100);
|
||||||
output.writeInt32(11);
|
switch (version) {
|
||||||
|
case V_0xB:
|
||||||
|
output.writeInt32(0xB);
|
||||||
|
break;
|
||||||
|
case V_0xC:
|
||||||
|
output.writeInt32(0xC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
renderSignatures(module);
|
renderSignatures(module);
|
||||||
renderImports(module);
|
renderImports(module);
|
||||||
renderFunctions(module);
|
renderFunctions(module);
|
||||||
|
@ -48,6 +72,7 @@ public class WasmBinaryRenderer {
|
||||||
renderMemory(module);
|
renderMemory(module);
|
||||||
renderExport(module);
|
renderExport(module);
|
||||||
renderStart(module);
|
renderStart(module);
|
||||||
|
renderElement(module);
|
||||||
renderCode(module);
|
renderCode(module);
|
||||||
renderData(module);
|
renderData(module);
|
||||||
renderNames(module);
|
renderNames(module);
|
||||||
|
@ -79,7 +104,7 @@ public class WasmBinaryRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSection("type", section.getData());
|
writeSection(SECTION_TYPE, "type", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderImports(WasmModule module) {
|
private void renderImports(WasmModule module) {
|
||||||
|
@ -90,7 +115,11 @@ public class WasmBinaryRenderer {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
functions.add(function);
|
functions.add(function);
|
||||||
importIndexes.put(function.getName(), index++);
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
importIndexes.put(function.getName(), index++);
|
||||||
|
} else {
|
||||||
|
functionIndexes.put(function.getName(), functions.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (functions.isEmpty()) {
|
if (functions.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -101,7 +130,10 @@ public class WasmBinaryRenderer {
|
||||||
section.writeLEB(functions.size());
|
section.writeLEB(functions.size());
|
||||||
for (WasmFunction function : functions) {
|
for (WasmFunction function : functions) {
|
||||||
WasmSignature signature = WasmSignature.fromFunction(function);
|
WasmSignature signature = WasmSignature.fromFunction(function);
|
||||||
section.writeLEB(signatureIndexes.get(signature));
|
int signatureIndex = signatureIndexes.get(signature);
|
||||||
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
section.writeLEB(signatureIndex);
|
||||||
|
}
|
||||||
|
|
||||||
String moduleName = function.getImportModule();
|
String moduleName = function.getImportModule();
|
||||||
if (moduleName == null) {
|
if (moduleName == null) {
|
||||||
|
@ -110,9 +142,14 @@ public class WasmBinaryRenderer {
|
||||||
section.writeAsciiString(moduleName);
|
section.writeAsciiString(moduleName);
|
||||||
|
|
||||||
section.writeAsciiString(function.getImportName());
|
section.writeAsciiString(function.getImportName());
|
||||||
|
|
||||||
|
if (version == WasmBinaryVersion.V_0xC) {
|
||||||
|
section.writeByte(EXTERNAL_KIND_FUNCTION);
|
||||||
|
section.writeLEB(signatureIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSection("import", section.getData());
|
writeSection(SECTION_IMPORT, "import", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFunctions(WasmModule module) {
|
private void renderFunctions(WasmModule module) {
|
||||||
|
@ -132,7 +169,7 @@ public class WasmBinaryRenderer {
|
||||||
section.writeLEB(signatureIndexes.get(signature));
|
section.writeLEB(signatureIndexes.get(signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSection("function", section.getData());
|
writeSection(SECTION_FUNCTION, "function", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderTable(WasmModule module) {
|
private void renderTable(WasmModule module) {
|
||||||
|
@ -142,22 +179,35 @@ public class WasmBinaryRenderer {
|
||||||
|
|
||||||
WasmBinaryWriter section = new WasmBinaryWriter();
|
WasmBinaryWriter section = new WasmBinaryWriter();
|
||||||
|
|
||||||
section.writeLEB(module.getFunctionTable().size());
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
for (WasmFunction function : module.getFunctionTable()) {
|
section.writeLEB(module.getFunctionTable().size());
|
||||||
section.writeLEB(functionIndexes.get(function.getName()));
|
for (WasmFunction function : module.getFunctionTable()) {
|
||||||
|
section.writeLEB(functionIndexes.get(function.getName()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
section.writeByte(1);
|
||||||
|
section.writeByte(0x20);
|
||||||
|
section.writeByte(1);
|
||||||
|
section.writeLEB(functionIndexes.size());
|
||||||
|
//section.writeLEB(functionIndexes.size());
|
||||||
}
|
}
|
||||||
|
writeSection(SECTION_TABLE, "table", section.getData());
|
||||||
writeSection("table", section.getData());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderMemory(WasmModule module) {
|
private void renderMemory(WasmModule module) {
|
||||||
WasmBinaryWriter section = new WasmBinaryWriter();
|
WasmBinaryWriter section = new WasmBinaryWriter();
|
||||||
|
|
||||||
|
if (version == WasmBinaryVersion.V_0xC) {
|
||||||
|
section.writeByte(1);
|
||||||
|
section.writeByte(3);
|
||||||
|
}
|
||||||
section.writeLEB(module.getMemorySize());
|
section.writeLEB(module.getMemorySize());
|
||||||
section.writeLEB(module.getMemorySize());
|
section.writeLEB(module.getMemorySize());
|
||||||
section.writeByte(1);
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
section.writeByte(1);
|
||||||
|
}
|
||||||
|
|
||||||
writeSection("memory", section.getData());
|
writeSection(SECTION_MEMORY, "memory", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderExport(WasmModule module) {
|
private void renderExport(WasmModule module) {
|
||||||
|
@ -172,12 +222,20 @@ public class WasmBinaryRenderer {
|
||||||
|
|
||||||
section.writeLEB(functions.size());
|
section.writeLEB(functions.size());
|
||||||
for (WasmFunction function : functions) {
|
for (WasmFunction function : functions) {
|
||||||
section.writeLEB(functionIndexes.get(function.getName()));
|
int functionIndex = functionIndexes.get(function.getName());
|
||||||
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
section.writeLEB(functionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
section.writeAsciiString(function.getExportName());
|
section.writeAsciiString(function.getExportName());
|
||||||
|
|
||||||
|
if (version == WasmBinaryVersion.V_0xC) {
|
||||||
|
section.writeByte(EXTERNAL_KIND_FUNCTION);
|
||||||
|
section.writeLEB(functionIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSection("export", section.getData());
|
writeSection(SECTION_EXPORT, "export", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderStart(WasmModule module) {
|
private void renderStart(WasmModule module) {
|
||||||
|
@ -188,7 +246,28 @@ public class WasmBinaryRenderer {
|
||||||
WasmBinaryWriter section = new WasmBinaryWriter();
|
WasmBinaryWriter section = new WasmBinaryWriter();
|
||||||
section.writeLEB(functionIndexes.get(module.getStartFunction().getName()));
|
section.writeLEB(functionIndexes.get(module.getStartFunction().getName()));
|
||||||
|
|
||||||
writeSection("start", section.getData());
|
writeSection(SECTION_START, "start", section.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderElement(WasmModule module) {
|
||||||
|
if (module.getFunctionTable().isEmpty() || version != WasmBinaryVersion.V_0xC) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WasmBinaryWriter section = new WasmBinaryWriter();
|
||||||
|
section.writeLEB(1);
|
||||||
|
section.writeLEB(0);
|
||||||
|
|
||||||
|
section.writeByte(0x10);
|
||||||
|
section.writeLEB(0);
|
||||||
|
section.writeByte(0x0F);
|
||||||
|
|
||||||
|
section.writeLEB(module.getFunctionTable().size());
|
||||||
|
for (WasmFunction function : module.getFunctionTable()) {
|
||||||
|
section.writeLEB(functionIndexes.get(function.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSection(SECTION_ELEMENT, "element", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderCode(WasmModule module) {
|
private void renderCode(WasmModule module) {
|
||||||
|
@ -205,7 +284,7 @@ public class WasmBinaryRenderer {
|
||||||
section.writeBytes(body);
|
section.writeBytes(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSection("code", section.getData());
|
writeSection(SECTION_CODE, "code", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] renderFunction(WasmFunction function) {
|
private byte[] renderFunction(WasmFunction function) {
|
||||||
|
@ -236,8 +315,8 @@ public class WasmBinaryRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WasmBinaryRenderingVisitor visitor = new WasmBinaryRenderingVisitor(code, functionIndexes, importIndexes,
|
WasmBinaryRenderingVisitor visitor = new WasmBinaryRenderingVisitor(code, version, functionIndexes,
|
||||||
signatureIndexes);
|
importIndexes, signatureIndexes);
|
||||||
for (WasmExpression part : function.getBody()) {
|
for (WasmExpression part : function.getBody()) {
|
||||||
part.acceptVisitor(visitor);
|
part.acceptVisitor(visitor);
|
||||||
}
|
}
|
||||||
|
@ -263,7 +342,7 @@ public class WasmBinaryRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSection("data", section.getData());
|
writeSection(SECTION_DATA, "data", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderNames(WasmModule module) {
|
private void renderNames(WasmModule module) {
|
||||||
|
@ -280,7 +359,7 @@ public class WasmBinaryRenderer {
|
||||||
section.writeLEB(0);
|
section.writeLEB(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSection("name", section.getData());
|
writeSection(SECTION_UNKNOWN, "name", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
static class LocalEntry {
|
static class LocalEntry {
|
||||||
|
@ -300,10 +379,22 @@ public class WasmBinaryRenderer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeSection(String id, byte[] data) {
|
private void writeSection(int id, String name, byte[] data) {
|
||||||
output.writeAsciiString(id);
|
if (version == WasmBinaryVersion.V_0xC) {
|
||||||
|
output.writeByte(id);
|
||||||
|
int length = data.length;
|
||||||
|
if (id == 0) {
|
||||||
|
length += name.length() + 1;
|
||||||
|
}
|
||||||
|
output.writeLEB(length);
|
||||||
|
if (id == 0) {
|
||||||
|
output.writeAsciiString(name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.writeAsciiString(name);
|
||||||
|
output.writeLEB(data.length);
|
||||||
|
}
|
||||||
|
|
||||||
output.writeLEB(data.length);
|
|
||||||
output.writeBytes(data);
|
output.writeBytes(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,15 +52,17 @@ import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
|
|
||||||
class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
private WasmBinaryWriter writer;
|
private WasmBinaryWriter writer;
|
||||||
|
private WasmBinaryVersion version;
|
||||||
private Map<String, Integer> functionIndexes;
|
private Map<String, Integer> functionIndexes;
|
||||||
private Map<String, Integer> importedIndexes;
|
private Map<String, Integer> importedIndexes;
|
||||||
private Map<WasmSignature, Integer> signatureIndexes;
|
private Map<WasmSignature, Integer> signatureIndexes;
|
||||||
private int depth;
|
private int depth;
|
||||||
private Map<WasmBlock, Integer> blockDepths = new HashMap<>();
|
private Map<WasmBlock, Integer> blockDepths = new HashMap<>();
|
||||||
|
|
||||||
WasmBinaryRenderingVisitor(WasmBinaryWriter writer, Map<String, Integer> functionIndexes,
|
WasmBinaryRenderingVisitor(WasmBinaryWriter writer, WasmBinaryVersion version, Map<String, Integer> functionIndexes,
|
||||||
Map<String, Integer> importedIndexes, Map<WasmSignature, Integer> signatureIndexes) {
|
Map<String, Integer> importedIndexes, Map<WasmSignature, Integer> signatureIndexes) {
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
|
this.version = version;
|
||||||
this.functionIndexes = functionIndexes;
|
this.functionIndexes = functionIndexes;
|
||||||
this.importedIndexes = importedIndexes;
|
this.importedIndexes = importedIndexes;
|
||||||
this.signatureIndexes = signatureIndexes;
|
this.signatureIndexes = signatureIndexes;
|
||||||
|
@ -71,6 +73,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
depth += expression.isLoop() ? 2 : 1;
|
depth += expression.isLoop() ? 2 : 1;
|
||||||
blockDepths.put(expression, depth);
|
blockDepths.put(expression, depth);
|
||||||
writer.writeByte(expression.isLoop() ? 0x02 : 0x01);
|
writer.writeByte(expression.isLoop() ? 0x02 : 0x01);
|
||||||
|
writeBlockType(expression.getType());
|
||||||
for (WasmExpression part : expression.getBody()) {
|
for (WasmExpression part : expression.getBody()) {
|
||||||
part.acceptVisitor(this);
|
part.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
|
@ -79,6 +82,12 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
depth -= expression.isLoop() ? 2 : 1;
|
depth -= expression.isLoop() ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeBlockType(WasmType type) {
|
||||||
|
if (version == WasmBinaryVersion.V_0xC) {
|
||||||
|
writer.writeType(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBranch expression) {
|
public void visit(WasmBranch expression) {
|
||||||
if (expression.getResult() != null) {
|
if (expression.getResult() != null) {
|
||||||
|
@ -86,7 +95,9 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
}
|
}
|
||||||
expression.getCondition().acceptVisitor(this);
|
expression.getCondition().acceptVisitor(this);
|
||||||
writer.writeByte(0x07);
|
writer.writeByte(0x07);
|
||||||
writer.writeByte(expression.getResult() != null ? 1 : 0);
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
writer.writeByte(expression.getResult() != null ? 1 : 0);
|
||||||
|
}
|
||||||
writeLabel(expression.getTarget());
|
writeLabel(expression.getTarget());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +107,9 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
expression.getResult().acceptVisitor(this);
|
expression.getResult().acceptVisitor(this);
|
||||||
}
|
}
|
||||||
writer.writeByte(0x06);
|
writer.writeByte(0x06);
|
||||||
writer.writeByte(expression.getResult() != null ? 1 : 0);
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
writer.writeByte(expression.getResult() != null ? 1 : 0);
|
||||||
|
}
|
||||||
writeLabel(expression.getTarget());
|
writeLabel(expression.getTarget());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,20 +117,33 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmSwitch expression) {
|
public void visit(WasmSwitch expression) {
|
||||||
expression.getSelector().acceptVisitor(this);
|
expression.getSelector().acceptVisitor(this);
|
||||||
writer.writeByte(0x08);
|
writer.writeByte(0x08);
|
||||||
writer.writeByte(0);
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
writer.writeByte(0);
|
||||||
|
}
|
||||||
writer.writeLEB(expression.getTargets().size());
|
writer.writeLEB(expression.getTargets().size());
|
||||||
for (WasmBlock target : expression.getTargets()) {
|
for (WasmBlock target : expression.getTargets()) {
|
||||||
int targetDepth = blockDepths.get(target);
|
int targetDepth = blockDepths.get(target);
|
||||||
writer.writeFixed(depth - targetDepth);
|
int relativeDepth = depth - targetDepth;
|
||||||
|
if (version == WasmBinaryVersion.V_0xC) {
|
||||||
|
writer.writeLEB(relativeDepth);
|
||||||
|
} else {
|
||||||
|
writer.writeFixed(relativeDepth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int defaultDepth = blockDepths.get(expression.getDefaultTarget());
|
int defaultDepth = blockDepths.get(expression.getDefaultTarget());
|
||||||
writer.writeFixed(depth - defaultDepth);
|
int relativeDepth = depth - defaultDepth;
|
||||||
|
if (version == WasmBinaryVersion.V_0xC) {
|
||||||
|
writer.writeLEB(relativeDepth);
|
||||||
|
} else {
|
||||||
|
writer.writeFixed(relativeDepth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmConditional expression) {
|
public void visit(WasmConditional expression) {
|
||||||
expression.getCondition().acceptVisitor(this);
|
expression.getCondition().acceptVisitor(this);
|
||||||
writer.writeByte(0x03);
|
writer.writeByte(0x03);
|
||||||
|
writeBlockType(expression.getType());
|
||||||
|
|
||||||
++depth;
|
++depth;
|
||||||
blockDepths.put(expression.getThenBlock(), depth);
|
blockDepths.put(expression.getThenBlock(), depth);
|
||||||
|
@ -145,12 +171,18 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
}
|
}
|
||||||
writer.writeByte(0x09);
|
writer.writeByte(0x09);
|
||||||
writer.writeByte(expression.getValue() != null ? 1 : 0);
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
writer.writeByte(expression.getValue() != null ? 1 : 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmUnreachable expression) {
|
public void visit(WasmUnreachable expression) {
|
||||||
writer.writeByte(0x0A);
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
writer.writeByte(0x0A);
|
||||||
|
} else {
|
||||||
|
writer.writeByte(0x0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -613,7 +645,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
for (WasmExpression argument : expression.getArguments()) {
|
for (WasmExpression argument : expression.getArguments()) {
|
||||||
argument.acceptVisitor(this);
|
argument.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
Integer functionIndex = !expression.isImported()
|
Integer functionIndex = !expression.isImported() || version == WasmBinaryVersion.V_0xC
|
||||||
? functionIndexes.get(expression.getFunctionName())
|
? functionIndexes.get(expression.getFunctionName())
|
||||||
: importedIndexes.get(expression.getFunctionName());
|
: importedIndexes.get(expression.getFunctionName());
|
||||||
if (functionIndex == null) {
|
if (functionIndex == null) {
|
||||||
|
@ -621,8 +653,12 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeByte(!expression.isImported() ? 0x16 : 0x18);
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
writer.writeLEB(expression.getArguments().size());
|
writer.writeByte(!expression.isImported() ? 0x16 : 0x18);
|
||||||
|
writer.writeLEB(expression.getArguments().size());
|
||||||
|
} else {
|
||||||
|
writer.writeByte(0x16);
|
||||||
|
}
|
||||||
writer.writeLEB(functionIndex);
|
writer.writeLEB(functionIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,7 +669,9 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
argument.acceptVisitor(this);
|
argument.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
writer.writeByte(0x17);
|
writer.writeByte(0x17);
|
||||||
writer.writeLEB(expression.getArguments().size());
|
if (version == WasmBinaryVersion.V_0xB) {
|
||||||
|
writer.writeLEB(expression.getArguments().size());
|
||||||
|
}
|
||||||
|
|
||||||
WasmType[] signatureTypes = new WasmType[expression.getParameterTypes().size() + 1];
|
WasmType[] signatureTypes = new WasmType[expression.getParameterTypes().size() + 1];
|
||||||
signatureTypes[0] = expression.getReturnType();
|
signatureTypes[0] = expression.getReturnType();
|
||||||
|
@ -646,6 +684,9 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmDrop expression) {
|
public void visit(WasmDrop expression) {
|
||||||
expression.getOperand().acceptVisitor(this);
|
expression.getOperand().acceptVisitor(this);
|
||||||
|
if (version == WasmBinaryVersion.V_0xC) {
|
||||||
|
writer.writeByte(0x0B);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.render;
|
||||||
|
|
||||||
|
public enum WasmBinaryVersion {
|
||||||
|
V_0xB,
|
||||||
|
V_0xC
|
||||||
|
}
|
|
@ -28,6 +28,10 @@ public class WasmBinaryWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeType(WasmType type) {
|
public void writeType(WasmType type) {
|
||||||
|
if (type == null) {
|
||||||
|
writeByte(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT32:
|
case INT32:
|
||||||
writeByte(1);
|
writeByte(1);
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.render;
|
||||||
|
|
||||||
|
import org.teavm.backend.wasm.generate.WasmGenerationContext;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmExpressionVisitor;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFloat32Constant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
|
|
||||||
|
public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
|
private WasmGenerationContext context;
|
||||||
|
private WasmType result;
|
||||||
|
|
||||||
|
public WasmTypeInference(WasmGenerationContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmType getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmBlock expression) {
|
||||||
|
result = expression.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmBranch expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmBreak expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmSwitch expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmConditional expression) {
|
||||||
|
result = expression.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmReturn expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmUnreachable expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt32Constant expression) {
|
||||||
|
result = WasmType.INT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt64Constant expression) {
|
||||||
|
result = WasmType.INT64;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFloat32Constant expression) {
|
||||||
|
result = WasmType.FLOAT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFloat64Constant expression) {
|
||||||
|
result = WasmType.FLOAT64;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmGetLocal expression) {
|
||||||
|
result = expression.getLocal().getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmSetLocal expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIntBinary expression) {
|
||||||
|
result = map(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFloatBinary expression) {
|
||||||
|
result = map(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIntUnary expression) {
|
||||||
|
result = map(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFloatUnary expression) {
|
||||||
|
result = map(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmConversion expression) {
|
||||||
|
result = expression.getTargetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCall expression) {
|
||||||
|
WasmFunction function = context.getFunction(expression.getFunctionName());
|
||||||
|
result = function == null ? null : function.getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIndirectCall expression) {
|
||||||
|
result = expression.getReturnType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmDrop expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmLoadInt32 expression) {
|
||||||
|
result = WasmType.INT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmLoadInt64 expression) {
|
||||||
|
result = WasmType.INT64;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmLoadFloat32 expression) {
|
||||||
|
result = WasmType.FLOAT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmLoadFloat64 expression) {
|
||||||
|
result = WasmType.FLOAT64;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStoreInt32 expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStoreInt64 expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStoreFloat32 expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStoreFloat64 expression) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WasmType map(WasmIntType type) {
|
||||||
|
switch (type) {
|
||||||
|
case INT32:
|
||||||
|
return WasmType.INT32;
|
||||||
|
case INT64:
|
||||||
|
return WasmType.INT64;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(type.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WasmType map(WasmFloatType type) {
|
||||||
|
switch (type) {
|
||||||
|
case FLOAT32:
|
||||||
|
return WasmType.FLOAT32;
|
||||||
|
case FLOAT64:
|
||||||
|
return WasmType.FLOAT64;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(type.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import org.apache.commons.cli.*;
|
import org.apache.commons.cli.*;
|
||||||
|
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||||
import org.teavm.tooling.RuntimeCopyOperation;
|
import org.teavm.tooling.RuntimeCopyOperation;
|
||||||
import org.teavm.tooling.TeaVMTargetType;
|
import org.teavm.tooling.TeaVMTargetType;
|
||||||
import org.teavm.tooling.TeaVMTool;
|
import org.teavm.tooling.TeaVMTool;
|
||||||
|
@ -105,6 +106,12 @@ public final class TeaVMRunner {
|
||||||
.withDescription("Additional classpath that will be reloaded by TeaVM each time in wait mode")
|
.withDescription("Additional classpath that will be reloaded by TeaVM each time in wait mode")
|
||||||
.withLongOpt("classpath")
|
.withLongOpt("classpath")
|
||||||
.create('p'));
|
.create('p'));
|
||||||
|
options.addOption(OptionBuilder
|
||||||
|
.withArgName("wasm-version")
|
||||||
|
.hasArg()
|
||||||
|
.withDescription("WebAssembly binary version (11, 12)")
|
||||||
|
.withLongOpt("version")
|
||||||
|
.create());
|
||||||
|
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
printUsage(options);
|
printUsage(options);
|
||||||
|
@ -209,6 +216,8 @@ public final class TeaVMRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean interactive = commandLine.hasOption('w');
|
boolean interactive = commandLine.hasOption('w');
|
||||||
|
setupWasm(tool, commandLine, options);
|
||||||
|
|
||||||
args = commandLine.getArgs();
|
args = commandLine.getArgs();
|
||||||
if (args.length > 1) {
|
if (args.length > 1) {
|
||||||
System.err.println("Unexpected arguments");
|
System.err.println("Unexpected arguments");
|
||||||
|
@ -275,6 +284,29 @@ public final class TeaVMRunner {
|
||||||
System.out.println("Build complete for " + ((System.currentTimeMillis() - startTime) / 1000.0) + " seconds");
|
System.out.println("Build complete for " + ((System.currentTimeMillis() - startTime) / 1000.0) + " seconds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void setupWasm(TeaVMTool tool, CommandLine commandLine, Options options) {
|
||||||
|
if (commandLine.hasOption("wasm-version")) {
|
||||||
|
String value = commandLine.getOptionValue("wasm-version");
|
||||||
|
try {
|
||||||
|
int version = Integer.parseInt(value);
|
||||||
|
switch (version) {
|
||||||
|
case 11:
|
||||||
|
tool.setWasmVersion(WasmBinaryVersion.V_0xB);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
tool.setWasmVersion(WasmBinaryVersion.V_0xC);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.err.print("Wrong version value");
|
||||||
|
printUsage(options);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
System.err.print("Wrong version value");
|
||||||
|
printUsage(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void resetClassLoader(TeaVMTool tool) {
|
private static void resetClassLoader(TeaVMTool tool) {
|
||||||
if (classPath == null || classPath.length == 0) {
|
if (classPath == null || classPath.length == 0) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.commons.io.IOUtils;
|
||||||
import org.teavm.backend.javascript.JavaScriptTarget;
|
import org.teavm.backend.javascript.JavaScriptTarget;
|
||||||
import org.teavm.backend.javascript.rendering.RenderingManager;
|
import org.teavm.backend.javascript.rendering.RenderingManager;
|
||||||
import org.teavm.backend.wasm.WasmTarget;
|
import org.teavm.backend.wasm.WasmTarget;
|
||||||
|
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||||
import org.teavm.cache.DiskCachedClassHolderSource;
|
import org.teavm.cache.DiskCachedClassHolderSource;
|
||||||
import org.teavm.cache.DiskProgramCache;
|
import org.teavm.cache.DiskProgramCache;
|
||||||
import org.teavm.cache.DiskRegularMethodNodeCache;
|
import org.teavm.cache.DiskRegularMethodNodeCache;
|
||||||
|
@ -98,6 +99,7 @@ public class TeaVMTool implements BaseTeaVMTool {
|
||||||
private DebugInformationBuilder debugEmitter;
|
private DebugInformationBuilder debugEmitter;
|
||||||
private JavaScriptTarget javaScriptTarget;
|
private JavaScriptTarget javaScriptTarget;
|
||||||
private WasmTarget webAssemblyTarget;
|
private WasmTarget webAssemblyTarget;
|
||||||
|
private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0xC;
|
||||||
|
|
||||||
public File getTargetDirectory() {
|
public File getTargetDirectory() {
|
||||||
return targetDirectory;
|
return targetDirectory;
|
||||||
|
@ -245,6 +247,14 @@ public class TeaVMTool implements BaseTeaVMTool {
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmBinaryVersion getWasmVersion() {
|
||||||
|
return wasmVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWasmVersion(WasmBinaryVersion wasmVersion) {
|
||||||
|
this.wasmVersion = wasmVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public void setProgressListener(TeaVMProgressListener progressListener) {
|
public void setProgressListener(TeaVMProgressListener progressListener) {
|
||||||
this.progressListener = progressListener;
|
this.progressListener = progressListener;
|
||||||
}
|
}
|
||||||
|
@ -332,6 +342,7 @@ public class TeaVMTool implements BaseTeaVMTool {
|
||||||
webAssemblyTarget.setDebugging(debugInformationGenerated);
|
webAssemblyTarget.setDebugging(debugInformationGenerated);
|
||||||
webAssemblyTarget.setCEmitted(debugInformationGenerated);
|
webAssemblyTarget.setCEmitted(debugInformationGenerated);
|
||||||
webAssemblyTarget.setWastEmitted(debugInformationGenerated);
|
webAssemblyTarget.setWastEmitted(debugInformationGenerated);
|
||||||
|
webAssemblyTarget.setVersion(wasmVersion);
|
||||||
return webAssemblyTarget;
|
return webAssemblyTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
|
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||||
import org.teavm.tooling.ClassAlias;
|
import org.teavm.tooling.ClassAlias;
|
||||||
import org.teavm.tooling.MethodAlias;
|
import org.teavm.tooling.MethodAlias;
|
||||||
import org.teavm.tooling.RuntimeCopyOperation;
|
import org.teavm.tooling.RuntimeCopyOperation;
|
||||||
|
@ -76,6 +77,9 @@ public class TeaVMCompileMojo extends AbstractTeaVMMojo {
|
||||||
|
|
||||||
private TeaVMTool tool = new TeaVMTool();
|
private TeaVMTool tool = new TeaVMTool();
|
||||||
|
|
||||||
|
@Parameter
|
||||||
|
private WasmBinaryVersion wasmVersion;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File getTargetDirectory() {
|
protected File getTargetDirectory() {
|
||||||
return targetDirectory;
|
return targetDirectory;
|
||||||
|
@ -102,6 +106,7 @@ public class TeaVMCompileMojo extends AbstractTeaVMMojo {
|
||||||
}
|
}
|
||||||
tool.setCacheDirectory(cacheDirectory);
|
tool.setCacheDirectory(cacheDirectory);
|
||||||
tool.setTargetType(targetType);
|
tool.setTargetType(targetType);
|
||||||
|
tool.setWasmVersion(wasmVersion);
|
||||||
tool.generate();
|
tool.generate();
|
||||||
if (stopOnErrors && !tool.getProblemProvider().getSevereProblems().isEmpty()) {
|
if (stopOnErrors && !tool.getProblemProvider().getSevereProblems().isEmpty()) {
|
||||||
throw new MojoExecutionException("Build error");
|
throw new MojoExecutionException("Build error");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user