mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Add WASM s-expr emitter
This commit is contained in:
parent
1484e970dd
commit
e5356fae27
|
@ -20,10 +20,6 @@ import java.util.*;
|
|||
import org.teavm.model.*;
|
||||
import org.teavm.parsing.ClassDateProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DiskCachedClassHolderSource implements ClassHolderSource {
|
||||
private static AccessLevel[] accessLevels = AccessLevel.values();
|
||||
private static ElementModifier[] elementModifiers = ElementModifier.values();
|
||||
|
@ -31,7 +27,7 @@ public class DiskCachedClassHolderSource implements ClassHolderSource {
|
|||
private SymbolTable symbolTable;
|
||||
private ClassHolderSource innerSource;
|
||||
private ClassDateProvider classDateProvider;
|
||||
private Map<String, Item> cache = new HashMap<>();
|
||||
private Map<String, Item> cache = new LinkedHashMap<>();
|
||||
private Set<String> newClasses = new HashSet<>();
|
||||
private ProgramIO programIO;
|
||||
|
||||
|
|
|
@ -17,16 +17,9 @@ package org.teavm.common;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*
|
||||
* @param <T> which type this mapper takes.
|
||||
* @param <R> which type this mapper produces.
|
||||
*/
|
||||
public class CachedMapper<T, R> implements Mapper<T, R> {
|
||||
private Mapper<T, R> innerMapper;
|
||||
private Map<T, Wrapper<R>> cache = new HashMap<>();
|
||||
private Map<T, Wrapper<R>> cache = new LinkedHashMap<>();
|
||||
private List<KeyListener<T>> keyListeners = new ArrayList<>();
|
||||
|
||||
private static class Wrapper<S> {
|
||||
|
|
|
@ -17,7 +17,7 @@ package org.teavm.dependency;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
|
@ -30,16 +30,12 @@ import org.teavm.model.MethodHolder;
|
|||
import org.teavm.model.util.ModelUtils;
|
||||
import org.teavm.optimization.UnreachableBasicBlockEliminator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class DependencyClassSource implements ClassHolderSource {
|
||||
private ClassReaderSource innerSource;
|
||||
private Diagnostics diagnostics;
|
||||
private Map<String, ClassHolder> generatedClasses = new HashMap<>();
|
||||
private Map<String, ClassHolder> generatedClasses = new LinkedHashMap<>();
|
||||
private List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||
private Map<String, ClassHolder> cache = new HashMap<>();
|
||||
private Map<String, ClassHolder> cache = new LinkedHashMap<>();
|
||||
|
||||
public DependencyClassSource(ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||
this.innerSource = innerSource;
|
||||
|
|
|
@ -18,10 +18,6 @@ package org.teavm.model;
|
|||
import org.teavm.model.util.ModelUtils;
|
||||
import org.teavm.resource.MapperClassHolderSource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class CopyClassHolderSource implements ClassHolderSource {
|
||||
private ClassReaderSource innerSource;
|
||||
private MapperClassHolderSource mapperSource = new MapperClassHolderSource(this::copyClass);
|
||||
|
|
|
@ -15,9 +15,5 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface ListableClassHolderSource extends ClassHolderSource, ListableClassReaderSource {
|
||||
}
|
||||
|
|
|
@ -15,16 +15,12 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class MutableClassHolderSource implements ListableClassHolderSource {
|
||||
private ConcurrentMap<String, ClassHolder> classes = new ConcurrentHashMap<>();
|
||||
private Map<String, ClassHolder> classes = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
public Set<String> getClassNames() {
|
||||
|
|
|
@ -15,14 +15,14 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.optimization.GlobalValueNumbering;
|
||||
import org.teavm.optimization.UnusedVariableElimination;
|
||||
|
||||
public class PreOptimizingClassHolderSource implements ClassHolderSource {
|
||||
private ClassHolderSource innerClassSource;
|
||||
private Map<String, ClassHolder> cache = new HashMap<>();
|
||||
private Map<String, ClassHolder> cache = new LinkedHashMap<>();
|
||||
|
||||
public PreOptimizingClassHolderSource(ClassHolderSource innerClassSource) {
|
||||
this.innerClassSource = innerClassSource;
|
||||
|
|
|
@ -22,10 +22,6 @@ import org.teavm.resource.ClasspathResourceReader;
|
|||
import org.teavm.resource.MapperClassHolderSource;
|
||||
import org.teavm.resource.ResourceClassHolderMapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class ClasspathClassHolderSource implements ClassHolderSource, ClassDateProvider {
|
||||
private MapperClassHolderSource innerClassSource;
|
||||
private ClasspathResourceMapper classPathMapper;
|
||||
|
|
|
@ -20,10 +20,6 @@ import org.teavm.common.Mapper;
|
|||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderSource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class MapperClassHolderSource implements ClassHolderSource {
|
||||
private Mapper<String, ClassHolder> mapper;
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package org.teavm.wasm;
|
||||
|
||||
import org.teavm.wasm.runtime.WasmRuntime;
|
||||
|
||||
public final class Example {
|
||||
private Example() {
|
||||
}
|
||||
|
@ -27,5 +29,6 @@ public final class Example {
|
|||
a = b;
|
||||
b = c;
|
||||
}
|
||||
WasmRuntime.print(a);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,29 +61,31 @@ import org.teavm.ast.VariableExpr;
|
|||
import org.teavm.ast.WhileStatement;
|
||||
import org.teavm.wasm.model.WasmFunction;
|
||||
import org.teavm.wasm.model.WasmLocal;
|
||||
import org.teavm.wasm.model.expression.WasmAssignment;
|
||||
import org.teavm.wasm.model.expression.WasmBlock;
|
||||
import org.teavm.wasm.model.expression.WasmBranch;
|
||||
import org.teavm.wasm.model.expression.WasmBreak;
|
||||
import org.teavm.wasm.model.expression.WasmCall;
|
||||
import org.teavm.wasm.model.expression.WasmConditional;
|
||||
import org.teavm.wasm.model.expression.WasmConversion;
|
||||
import org.teavm.wasm.model.expression.WasmDrop;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.wasm.model.expression.WasmFloat32Constant;
|
||||
import org.teavm.wasm.model.expression.WasmFloat64Constant;
|
||||
import org.teavm.wasm.model.expression.WasmFloatBinary;
|
||||
import org.teavm.wasm.model.expression.WasmFloatBinaryOperation;
|
||||
import org.teavm.wasm.model.expression.WasmFloatType;
|
||||
import org.teavm.wasm.model.expression.WasmGetLocal;
|
||||
import org.teavm.wasm.model.expression.WasmInt32Constant;
|
||||
import org.teavm.wasm.model.expression.WasmInt64Constant;
|
||||
import org.teavm.wasm.model.expression.WasmIntBinary;
|
||||
import org.teavm.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.wasm.model.expression.WasmLocalReference;
|
||||
import org.teavm.wasm.model.expression.WasmReturn;
|
||||
import org.teavm.wasm.model.expression.WasmSetLocal;
|
||||
import org.teavm.wasm.model.expression.WasmSwitch;
|
||||
|
||||
class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||
private int firstVariable;
|
||||
private WasmFunction function;
|
||||
private IdentifiedStatement currentContinueTarget;
|
||||
private IdentifiedStatement currentBreakTarget;
|
||||
|
@ -92,8 +94,9 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
private Set<WasmBlock> usedBlocks = new HashSet<>();
|
||||
WasmExpression result;
|
||||
|
||||
public WasmGenerationVisitor(WasmFunction function) {
|
||||
public WasmGenerationVisitor(WasmFunction function, int firstVariable) {
|
||||
this.function = function;
|
||||
this.firstVariable = firstVariable;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -331,11 +334,14 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
@Override
|
||||
public void visit(AssignmentStatement statement) {
|
||||
Expr left = statement.getLeftValue();
|
||||
if (left instanceof VariableExpr) {
|
||||
VariableExpr varExpr = (VariableExpr) left;
|
||||
WasmLocal local = function.getLocalVariables().get(varExpr.getIndex());
|
||||
if (left == null) {
|
||||
statement.getRightValue().acceptVisitor(this);
|
||||
result = new WasmAssignment(local, result);
|
||||
result = new WasmDrop(result);
|
||||
} else if (left instanceof VariableExpr) {
|
||||
VariableExpr varExpr = (VariableExpr) left;
|
||||
WasmLocal local = function.getLocalVariables().get(varExpr.getIndex() - firstVariable);
|
||||
statement.getRightValue().acceptVisitor(this);
|
||||
result = new WasmSetLocal(local, result);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("This expression is not supported yet");
|
||||
}
|
||||
|
@ -396,7 +402,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(VariableExpr expr) {
|
||||
result = new WasmLocalReference(function.getLocalVariables().get(expr.getIndex()));
|
||||
result = new WasmGetLocal(function.getLocalVariables().get(expr.getIndex() - firstVariable));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -457,6 +463,12 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
currentBreakTarget = statement;
|
||||
currentContinueTarget = statement;
|
||||
|
||||
if (statement.getCondition() != null) {
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
loop.getBody().add(new WasmBranch(result, wrapper));
|
||||
usedBlocks.add(wrapper);
|
||||
}
|
||||
|
||||
for (Statement part : statement.getBody()) {
|
||||
part.acceptVisitor(this);
|
||||
loop.getBody().add(result);
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.teavm.ast.RegularMethodNode;
|
|||
import org.teavm.ast.decompilation.Decompiler;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderSource;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
|
@ -47,20 +48,21 @@ public class WasmGenerator {
|
|||
inferer.inferTypes(program, methodReference);
|
||||
|
||||
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(methodReference));
|
||||
for (int i = 0; i < methodAst.getVariables().size(); ++i) {
|
||||
int firstVariable = method.hasModifier(ElementModifier.STATIC) ? 1 : 0;
|
||||
for (int i = firstVariable; i < methodAst.getVariables().size(); ++i) {
|
||||
int varIndex = methodAst.getVariables().get(i);
|
||||
VariableType type = inferer.typeOf(varIndex);
|
||||
function.add(new WasmLocal(WasmGeneratorUtil.mapType(type)));
|
||||
}
|
||||
|
||||
for (int i = 0; i <= methodReference.parameterCount(); ++i) {
|
||||
function.getParameters().add(function.getLocalVariables().get(i).getType());
|
||||
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(function);
|
||||
WasmGenerationVisitor visitor = new WasmGenerationVisitor(function, firstVariable);
|
||||
methodAst.getBody().acceptVisitor(visitor);
|
||||
function.getBody().add(visitor.result);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public final class WasmMangling {
|
|||
}
|
||||
|
||||
public static String mangleMethod(MethodReference method) {
|
||||
StringBuilder sb = new StringBuilder("method$" + mangleString(method.getClassName()) + "$");
|
||||
StringBuilder sb = new StringBuilder("method_" + mangleString(method.getClassName()) + "_");
|
||||
String name = mangleString(method.getName());
|
||||
sb.append(mangleType(method.getReturnType()));
|
||||
sb.append(name.length() + "_" + name);
|
||||
|
@ -41,8 +41,6 @@ public final class WasmMangling {
|
|||
char c = string.charAt(i);
|
||||
switch (c) {
|
||||
case '$':
|
||||
case '.':
|
||||
case '-':
|
||||
sb.append(c);
|
||||
break;
|
||||
case '_':
|
||||
|
|
|
@ -37,4 +37,9 @@ public class WasmBlock extends WasmExpression {
|
|||
public List<WasmExpression> getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,4 +54,9 @@ public class WasmBranch extends WasmExpression {
|
|||
public void setResult(WasmExpression result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,4 +42,9 @@ public class WasmBreak extends WasmExpression {
|
|||
public void setResult(WasmExpression result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,4 +54,9 @@ public class WasmCall extends WasmExpression {
|
|||
public void setImported(boolean imported) {
|
||||
this.imported = imported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,4 +43,9 @@ public class WasmConditional extends WasmExpression {
|
|||
public WasmBlock getElseBlock() {
|
||||
return elseBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,4 +68,9 @@ public class WasmConversion extends WasmExpression {
|
|||
Objects.requireNonNull(operand);
|
||||
this.operand = operand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,4 +33,9 @@ public class WasmDrop extends WasmExpression {
|
|||
Objects.requireNonNull(operand);
|
||||
this.operand = operand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,6 @@ package org.teavm.wasm.model.expression;
|
|||
public abstract class WasmExpression {
|
||||
WasmExpression() {
|
||||
}
|
||||
|
||||
public abstract void acceptVisitor(WasmExpressionVisitor visitor);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.wasm.model.expression;
|
||||
|
||||
public interface WasmExpressionVisitor {
|
||||
void visit(WasmBlock expression);
|
||||
|
||||
void visit(WasmBranch expression);
|
||||
|
||||
void visit(WasmBreak expression);
|
||||
|
||||
void visit(WasmSwitch expression);
|
||||
|
||||
void visit(WasmConditional expression);
|
||||
|
||||
void visit(WasmReturn expression);
|
||||
|
||||
void visit(WasmUnreachable expression);
|
||||
|
||||
void visit(WasmInt32Constant expression);
|
||||
|
||||
void visit(WasmInt64Constant expression);
|
||||
|
||||
void visit(WasmFloat32Constant expression);
|
||||
|
||||
void visit(WasmFloat64Constant expression);
|
||||
|
||||
void visit(WasmGetLocal expression);
|
||||
|
||||
void visit(WasmSetLocal expression);
|
||||
|
||||
void visit(WasmIntBinary expression);
|
||||
|
||||
void visit(WasmFloatBinary expression);
|
||||
|
||||
void visit(WasmIntUnary expression);
|
||||
|
||||
void visit(WasmFloatUnary expression);
|
||||
|
||||
void visit(WasmConversion expression);
|
||||
|
||||
void visit(WasmCall expression);
|
||||
|
||||
void visit(WasmIndirectCall expression);
|
||||
|
||||
void visit(WasmDrop expression);
|
||||
|
||||
void visit(WasmLoadInt32 expression);
|
||||
|
||||
void visit(WasmLoadInt64 expression);
|
||||
|
||||
void visit(WasmLoadFloat32 expression);
|
||||
|
||||
void visit(WasmLoadFloat64 expression);
|
||||
|
||||
void visit(WasmStoreInt32 expression);
|
||||
|
||||
void visit(WasmStoreInt64 expression);
|
||||
|
||||
void visit(WasmStoreFloat32 expression);
|
||||
|
||||
void visit(WasmStoreFloat64 expression);
|
||||
}
|
|
@ -29,4 +29,9 @@ public class WasmFloat32Constant extends WasmExpression {
|
|||
public void setValue(float value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,4 +29,9 @@ public class WasmFloat64Constant extends WasmExpression {
|
|||
public void setValue(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,4 +70,9 @@ public class WasmFloatBinary extends WasmExpression {
|
|||
Objects.requireNonNull(second);
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,5 +25,7 @@ public enum WasmFloatBinaryOperation {
|
|||
LT,
|
||||
LE,
|
||||
GT,
|
||||
GE
|
||||
GE,
|
||||
MIN,
|
||||
MAX
|
||||
}
|
||||
|
|
|
@ -57,4 +57,9 @@ public class WasmFloatUnary extends WasmExpression {
|
|||
Objects.requireNonNull(operand);
|
||||
this.operand = operand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,5 @@ public enum WasmFloatUnaryOperation {
|
|||
FLOOR,
|
||||
TRUNC,
|
||||
NEAREST,
|
||||
MIN,
|
||||
MAX,
|
||||
SQRT,
|
||||
EQ,
|
||||
NE,
|
||||
LT,
|
||||
LE,
|
||||
GT,
|
||||
GE
|
||||
SQRT
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ package org.teavm.wasm.model.expression;
|
|||
import java.util.Objects;
|
||||
import org.teavm.wasm.model.WasmLocal;
|
||||
|
||||
public class WasmLocalReference extends WasmExpression {
|
||||
public class WasmGetLocal extends WasmExpression {
|
||||
private WasmLocal local;
|
||||
|
||||
public WasmLocalReference(WasmLocal local) {
|
||||
public WasmGetLocal(WasmLocal local) {
|
||||
Objects.requireNonNull(local);
|
||||
this.local = local;
|
||||
}
|
||||
|
@ -34,4 +34,9 @@ public class WasmLocalReference extends WasmExpression {
|
|||
Objects.requireNonNull(local);
|
||||
this.local = local;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
|
@ -15,15 +15,19 @@
|
|||
*/
|
||||
package org.teavm.wasm.model.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class WasmIndirectCall extends WasmExpression {
|
||||
private String typeName;
|
||||
private WasmExpression selector;
|
||||
private List<WasmExpression> arguments;
|
||||
private List<WasmExpression> arguments = new ArrayList<>();
|
||||
|
||||
public WasmIndirectCall(WasmExpression selector) {
|
||||
public WasmIndirectCall(String typeName, WasmExpression selector) {
|
||||
Objects.requireNonNull(typeName);
|
||||
Objects.requireNonNull(selector);
|
||||
this.typeName = typeName;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
|
@ -36,7 +40,21 @@ public class WasmIndirectCall extends WasmExpression {
|
|||
this.selector = selector;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public void setTypeName(String typeName) {
|
||||
Objects.requireNonNull(typeName);
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public List<WasmExpression> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,4 +29,9 @@ public class WasmInt32Constant extends WasmExpression {
|
|||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,4 +29,9 @@ public class WasmInt64Constant extends WasmExpression {
|
|||
public void setValue(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,4 +70,9 @@ public class WasmIntBinary extends WasmExpression {
|
|||
Objects.requireNonNull(second);
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,9 @@ public class WasmIntUnary extends WasmExpression {
|
|||
Objects.requireNonNull(operand);
|
||||
this.operand = operand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,4 +43,9 @@ public class WasmLoadFloat32 extends WasmExpression {
|
|||
Objects.requireNonNull(index);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,4 +43,9 @@ public class WasmLoadFloat64 extends WasmExpression {
|
|||
Objects.requireNonNull(index);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,4 +55,9 @@ public class WasmLoadInt32 extends WasmExpression {
|
|||
Objects.requireNonNull(convertFrom);
|
||||
this.convertFrom = convertFrom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,4 +55,9 @@ public class WasmLoadInt64 extends WasmExpression {
|
|||
Objects.requireNonNull(convertFrom);
|
||||
this.convertFrom = convertFrom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,4 +33,9 @@ public class WasmReturn extends WasmExpression {
|
|||
public void setValue(WasmExpression value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@ package org.teavm.wasm.model.expression;
|
|||
import java.util.Objects;
|
||||
import org.teavm.wasm.model.WasmLocal;
|
||||
|
||||
public class WasmAssignment extends WasmExpression {
|
||||
public class WasmSetLocal extends WasmExpression {
|
||||
private WasmLocal local;
|
||||
private WasmExpression value;
|
||||
|
||||
public WasmAssignment(WasmLocal local, WasmExpression value) {
|
||||
public WasmSetLocal(WasmLocal local, WasmExpression value) {
|
||||
Objects.requireNonNull(local);
|
||||
Objects.requireNonNull(value);
|
||||
this.local = local;
|
||||
|
@ -46,4 +46,9 @@ public class WasmAssignment extends WasmExpression {
|
|||
Objects.requireNonNull(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
|
@ -55,4 +55,9 @@ public class WasmStoreFloat32 extends WasmExpression {
|
|||
Objects.requireNonNull(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,4 +55,9 @@ public class WasmStoreFloat64 extends WasmExpression {
|
|||
Objects.requireNonNull(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,4 +68,9 @@ public class WasmStoreInt32 extends WasmExpression {
|
|||
Objects.requireNonNull(convertTo);
|
||||
this.convertTo = convertTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,4 +68,9 @@ public class WasmStoreInt64 extends WasmExpression {
|
|||
Objects.requireNonNull(convertTo);
|
||||
this.convertTo = convertTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,4 +50,9 @@ public class WasmSwitch extends WasmExpression {
|
|||
public List<WasmBlock> getTargets() {
|
||||
return targets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,11 @@
|
|||
package org.teavm.wasm.model.expression;
|
||||
|
||||
public class WasmUnreachable extends WasmExpression {
|
||||
public static final WasmUnreachable INSTANCE = new WasmUnreachable();
|
||||
public WasmUnreachable() {
|
||||
}
|
||||
|
||||
private WasmUnreachable() {
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
56
core/src/main/java/org/teavm/wasm/render/WasmRenderer.java
Normal file
56
core/src/main/java/org/teavm/wasm/render/WasmRenderer.java
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.wasm.render;
|
||||
|
||||
import java.util.List;
|
||||
import org.teavm.wasm.model.WasmFunction;
|
||||
import org.teavm.wasm.model.WasmLocal;
|
||||
import org.teavm.wasm.model.WasmType;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
|
||||
public class WasmRenderer {
|
||||
private WasmRenderingVisitor visitor = new WasmRenderingVisitor();
|
||||
|
||||
public void render(WasmFunction function) {
|
||||
visitor.open().append("func " + function.getName());
|
||||
for (WasmType type : function.getParameters()) {
|
||||
visitor.append(" ").open().append("param ").append(type).close();
|
||||
}
|
||||
if (function.getResult() != null) {
|
||||
visitor.append(" ").open().append("result ").append(function.getResult()).close();
|
||||
}
|
||||
|
||||
int firstLocalVariable = function.getParameters().size();
|
||||
if (firstLocalVariable > function.getLocalVariables().size()) {
|
||||
visitor.open().append("local");
|
||||
List<WasmLocal> locals = function.getLocalVariables().subList(firstLocalVariable,
|
||||
function.getLocalVariables().size());
|
||||
for (WasmLocal local : locals) {
|
||||
visitor.append(" " + local.getType());
|
||||
}
|
||||
visitor.close();
|
||||
}
|
||||
for (WasmExpression part : function.getBody()) {
|
||||
visitor.line(part);
|
||||
}
|
||||
visitor.close().lf().lf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return visitor.sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,569 @@
|
|||
/*
|
||||
* 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.wasm.render;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.teavm.wasm.model.WasmLocal;
|
||||
import org.teavm.wasm.model.WasmType;
|
||||
import org.teavm.wasm.model.expression.WasmBlock;
|
||||
import org.teavm.wasm.model.expression.WasmBranch;
|
||||
import org.teavm.wasm.model.expression.WasmBreak;
|
||||
import org.teavm.wasm.model.expression.WasmCall;
|
||||
import org.teavm.wasm.model.expression.WasmConditional;
|
||||
import org.teavm.wasm.model.expression.WasmConversion;
|
||||
import org.teavm.wasm.model.expression.WasmDrop;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.wasm.model.expression.WasmExpressionVisitor;
|
||||
import org.teavm.wasm.model.expression.WasmFloat32Constant;
|
||||
import org.teavm.wasm.model.expression.WasmFloat64Constant;
|
||||
import org.teavm.wasm.model.expression.WasmFloatBinary;
|
||||
import org.teavm.wasm.model.expression.WasmFloatBinaryOperation;
|
||||
import org.teavm.wasm.model.expression.WasmFloatType;
|
||||
import org.teavm.wasm.model.expression.WasmFloatUnary;
|
||||
import org.teavm.wasm.model.expression.WasmFloatUnaryOperation;
|
||||
import org.teavm.wasm.model.expression.WasmGetLocal;
|
||||
import org.teavm.wasm.model.expression.WasmIndirectCall;
|
||||
import org.teavm.wasm.model.expression.WasmInt32Constant;
|
||||
import org.teavm.wasm.model.expression.WasmInt64Constant;
|
||||
import org.teavm.wasm.model.expression.WasmIntBinary;
|
||||
import org.teavm.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.wasm.model.expression.WasmIntUnary;
|
||||
import org.teavm.wasm.model.expression.WasmIntUnaryOperation;
|
||||
import org.teavm.wasm.model.expression.WasmLoadFloat32;
|
||||
import org.teavm.wasm.model.expression.WasmLoadFloat64;
|
||||
import org.teavm.wasm.model.expression.WasmLoadInt32;
|
||||
import org.teavm.wasm.model.expression.WasmLoadInt64;
|
||||
import org.teavm.wasm.model.expression.WasmReturn;
|
||||
import org.teavm.wasm.model.expression.WasmSetLocal;
|
||||
import org.teavm.wasm.model.expression.WasmStoreFloat32;
|
||||
import org.teavm.wasm.model.expression.WasmStoreFloat64;
|
||||
import org.teavm.wasm.model.expression.WasmStoreInt32;
|
||||
import org.teavm.wasm.model.expression.WasmStoreInt64;
|
||||
import org.teavm.wasm.model.expression.WasmSwitch;
|
||||
import org.teavm.wasm.model.expression.WasmUnreachable;
|
||||
|
||||
class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||
private Set<String> usedIdentifiers = new HashSet<>();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
private Map<WasmBlock, String> blockIdentifiers = new HashMap<>();
|
||||
private Map<WasmLocal, String> localIdentifiers = new HashMap<>();
|
||||
private int indentLevel;
|
||||
private boolean lfDeferred;
|
||||
|
||||
void clear() {
|
||||
blockIdentifiers.clear();
|
||||
localIdentifiers.clear();
|
||||
usedIdentifiers.clear();
|
||||
}
|
||||
|
||||
WasmRenderingVisitor append(String text) {
|
||||
if (lfDeferred) {
|
||||
lfDeferred = false;
|
||||
sb.append("\n");
|
||||
for (int i = 0; i < indentLevel; ++i) {
|
||||
sb.append(" ");
|
||||
}
|
||||
}
|
||||
sb.append(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
WasmRenderingVisitor append(WasmType type) {
|
||||
return append(type(type));
|
||||
}
|
||||
|
||||
WasmRenderingVisitor append(WasmExpression expression) {
|
||||
expression.acceptVisitor(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
WasmRenderingVisitor line(WasmExpression expression) {
|
||||
return lf().append(expression);
|
||||
}
|
||||
|
||||
WasmRenderingVisitor indent() {
|
||||
indentLevel++;
|
||||
return this;
|
||||
}
|
||||
|
||||
WasmRenderingVisitor outdent() {
|
||||
indentLevel--;
|
||||
return this;
|
||||
}
|
||||
|
||||
WasmRenderingVisitor lf() {
|
||||
if (lfDeferred) {
|
||||
sb.append("\n");
|
||||
}
|
||||
lfDeferred = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
WasmRenderingVisitor open() {
|
||||
append("(").indent();
|
||||
return this;
|
||||
}
|
||||
|
||||
WasmRenderingVisitor close() {
|
||||
outdent().append(")");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmBlock expression) {
|
||||
renderBlock(expression, expression.isLoop() ? "loop" : "block");
|
||||
}
|
||||
|
||||
private void renderBlock(WasmBlock block, String name) {
|
||||
String id = getIdentifier("@block");
|
||||
blockIdentifiers.put(block, id);
|
||||
open().append(name + " " + id);
|
||||
for (WasmExpression part : block.getBody()) {
|
||||
line(part);
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmBranch expression) {
|
||||
String id = blockIdentifiers.get(expression.getTarget());
|
||||
open().append("br_if " + id);
|
||||
if (expression.getResult() != null) {
|
||||
line(expression.getResult());
|
||||
}
|
||||
line(expression.getCondition());
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmBreak expression) {
|
||||
String id = blockIdentifiers.get(expression.getTarget());
|
||||
open().append("br ").append(id);
|
||||
if (expression.getResult() != null) {
|
||||
line(expression.getResult());
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmSwitch expression) {
|
||||
open().append("br_table ");
|
||||
for (WasmBlock target : expression.getTargets()) {
|
||||
append(blockIdentifiers.get(target)).append(" ");
|
||||
}
|
||||
append(blockIdentifiers.get(expression.getDefaultTarget()));
|
||||
line(expression.getSelector());
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmConditional expression) {
|
||||
open().append("if");
|
||||
line(expression.getCondition());
|
||||
|
||||
lf();
|
||||
renderBlock(expression.getThenBlock(), "then");
|
||||
|
||||
lf();
|
||||
renderBlock(expression.getThenBlock(), "else");
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmReturn expression) {
|
||||
open().append("return");
|
||||
if (expression.getValue() != null) {
|
||||
line(expression.getValue());
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmUnreachable expression) {
|
||||
open().append("unreachable").close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmInt32Constant expression) {
|
||||
open().append("i32.const " + expression.getValue()).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmInt64Constant expression) {
|
||||
open().append("i64.const " + expression.getValue()).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmFloat32Constant expression) {
|
||||
open().append("f32.const " + Float.toHexString(expression.getValue())).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmFloat64Constant expression) {
|
||||
open().append("f64.const " + Double.toHexString(expression.getValue())).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmGetLocal expression) {
|
||||
open().append("get_local " + asString(expression.getLocal())).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmSetLocal expression) {
|
||||
open().append("set_local " + asString(expression.getLocal())).line(expression.getValue()).close();
|
||||
}
|
||||
|
||||
private String asString(WasmLocal local) {
|
||||
return localIdentifiers.computeIfAbsent(local, l -> {
|
||||
String suggested = l.getName() != null ? l.getName() : "@local" + local.getIndex();
|
||||
return getIdentifier(suggested);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmIntBinary expression) {
|
||||
open().append(type(expression.getType()) + "." + operation(expression.getOperation()));
|
||||
line(expression.getFirst());
|
||||
line(expression.getSecond());
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmFloatBinary expression) {
|
||||
open().append(type(expression.getType()) + "." + operation(expression.getOperation()));
|
||||
line(expression.getFirst());
|
||||
line(expression.getSecond());
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmIntUnary expression) {
|
||||
open().append(type(expression.getType()) + "." + operation(expression.getOperation()));
|
||||
line(expression.getOperand());
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmFloatUnary expression) {
|
||||
open().append(type(expression.getType()) + "." + operation(expression.getOperation()));
|
||||
line(expression.getOperand());
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmConversion expression) {
|
||||
String name = null;
|
||||
switch (expression.getSourceType()) {
|
||||
case INT32:
|
||||
switch (expression.getTargetType()) {
|
||||
case INT32:
|
||||
break;
|
||||
case INT64:
|
||||
name = expression.isSigned() ? "extend_s" : "extend_u";
|
||||
break;
|
||||
case FLOAT32:
|
||||
case FLOAT64:
|
||||
name = expression.isSigned() ? "convert_s" : "convert_u";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INT64:
|
||||
switch (expression.getTargetType()) {
|
||||
case INT32:
|
||||
name = "wrap";
|
||||
break;
|
||||
case INT64:
|
||||
break;
|
||||
case FLOAT32:
|
||||
case FLOAT64:
|
||||
name = expression.isSigned() ? "convert_s" : "convert_u";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLOAT32:
|
||||
switch (expression.getTargetType()) {
|
||||
case INT32:
|
||||
case INT64:
|
||||
name = expression.isSigned() ? "trunc_s" : "trunc_u";
|
||||
break;
|
||||
case FLOAT32:
|
||||
break;
|
||||
case FLOAT64:
|
||||
name = "promote";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLOAT64:
|
||||
switch (expression.getTargetType()) {
|
||||
case INT32:
|
||||
case INT64:
|
||||
name = expression.isSigned() ? "trunc_s" : "trunc_u";
|
||||
break;
|
||||
case FLOAT32:
|
||||
name = "demote";
|
||||
break;
|
||||
case FLOAT64:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
append(expression.getOperand());
|
||||
} else {
|
||||
open().append(type(expression.getTargetType()) + "." + name + "/" + type(expression.getSourceType()));
|
||||
line(expression.getOperand());
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmCall expression) {
|
||||
open().append(expression.isImported() ? "call_import" : "call").append(" " + expression.getFunctionName());
|
||||
for (WasmExpression argument : expression.getArguments()) {
|
||||
line(argument);
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmIndirectCall expression) {
|
||||
open().append("call_indirect").append(" " + expression.getTypeName());
|
||||
line(expression.getSelector());
|
||||
for (WasmExpression argument : expression.getArguments()) {
|
||||
line(argument);
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmDrop expression) {
|
||||
open().append("drop").line(expression.getOperand()).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmLoadInt32 expression) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmLoadInt64 expression) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmLoadFloat32 expression) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmLoadFloat64 expression) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmStoreInt32 expression) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmStoreInt64 expression) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmStoreFloat32 expression) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmStoreFloat64 expression) {
|
||||
|
||||
}
|
||||
|
||||
private String getIdentifier(String suggested) {
|
||||
if (usedIdentifiers.add(suggested)) {
|
||||
return suggested;
|
||||
}
|
||||
int index = 1;
|
||||
while (true) {
|
||||
String id = suggested + "#" + index;
|
||||
if (usedIdentifiers.add(id)) {
|
||||
return id;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
private String type(WasmType type) {
|
||||
switch (type) {
|
||||
case INT32:
|
||||
return "i32";
|
||||
case INT64:
|
||||
return "i64";
|
||||
case FLOAT32:
|
||||
return "f32";
|
||||
case FLOAT64:
|
||||
return "f64";
|
||||
}
|
||||
throw new AssertionError(type.toString());
|
||||
}
|
||||
|
||||
private String type(WasmIntType type) {
|
||||
switch (type) {
|
||||
case INT32:
|
||||
return "i32";
|
||||
case INT64:
|
||||
return "i64";
|
||||
}
|
||||
throw new AssertionError(type.toString());
|
||||
}
|
||||
|
||||
private String type(WasmFloatType type) {
|
||||
switch (type) {
|
||||
case FLOAT32:
|
||||
return "f32";
|
||||
case FLOAT64:
|
||||
return "f64";
|
||||
}
|
||||
throw new AssertionError(type.toString());
|
||||
}
|
||||
|
||||
private String operation(WasmIntBinaryOperation operation) {
|
||||
switch (operation) {
|
||||
case ADD:
|
||||
return "add";
|
||||
case SUB:
|
||||
return "sub";
|
||||
case MUL:
|
||||
return "mul";
|
||||
case DIV_SIGNED:
|
||||
return "div_s";
|
||||
case DIV_UNSIGNED:
|
||||
return "div_u";
|
||||
case REM_SIGNED:
|
||||
return "rem_s";
|
||||
case REM_UNSIGNED:
|
||||
return "rem_u";
|
||||
case AND:
|
||||
return "and";
|
||||
case OR:
|
||||
return "or";
|
||||
case XOR:
|
||||
return "xor";
|
||||
case EQ:
|
||||
return "eq";
|
||||
case NE:
|
||||
return "ne";
|
||||
case GT_SIGNED:
|
||||
return "gt_s";
|
||||
case GT_UNSIGNED:
|
||||
return "gt_u";
|
||||
case GE_SIGNED:
|
||||
return "ge_s";
|
||||
case GE_UNSIGNED:
|
||||
return "ge_u";
|
||||
case LT_SIGNED:
|
||||
return "lt_s";
|
||||
case LT_UNSIGNED:
|
||||
return "lt_u";
|
||||
case LE_SIGNED:
|
||||
return "le_s";
|
||||
case LE_UNSIGNED:
|
||||
return "le_u";
|
||||
case SHL:
|
||||
return "shl";
|
||||
case SHR_SIGNED:
|
||||
return "shr_s";
|
||||
case SHR_UNSIGNED:
|
||||
return "shr_u";
|
||||
case ROTL:
|
||||
return "rotl";
|
||||
case ROTR:
|
||||
return "rotr";
|
||||
}
|
||||
throw new AssertionError(operation.toString());
|
||||
}
|
||||
|
||||
private String operation(WasmIntUnaryOperation operation) {
|
||||
switch (operation) {
|
||||
case CLZ:
|
||||
return "clz";
|
||||
case CTZ:
|
||||
return "ctz";
|
||||
case POPCNT:
|
||||
return "popcnt";
|
||||
}
|
||||
throw new AssertionError(operation.toString());
|
||||
}
|
||||
|
||||
private String operation(WasmFloatBinaryOperation operation) {
|
||||
switch (operation) {
|
||||
case ADD:
|
||||
return "add";
|
||||
case SUB:
|
||||
return "sub";
|
||||
case MUL:
|
||||
return "mul";
|
||||
case DIV:
|
||||
return "div";
|
||||
case EQ:
|
||||
return "eq";
|
||||
case NE:
|
||||
return "ne";
|
||||
case GT:
|
||||
return "gt";
|
||||
case GE:
|
||||
return "ge";
|
||||
case LT:
|
||||
return "lt";
|
||||
case LE:
|
||||
return "le";
|
||||
case MIN:
|
||||
return "min";
|
||||
case MAX:
|
||||
return "max";
|
||||
}
|
||||
throw new AssertionError(operation.toString());
|
||||
}
|
||||
|
||||
private String operation(WasmFloatUnaryOperation operation) {
|
||||
switch (operation) {
|
||||
case ABS:
|
||||
return "abs";
|
||||
case NEG:
|
||||
return "neg";
|
||||
case COPYSIGN:
|
||||
break;
|
||||
case CEIL:
|
||||
return "ceil";
|
||||
case FLOOR:
|
||||
return "floor";
|
||||
case TRUNC:
|
||||
return "trunc";
|
||||
case NEAREST:
|
||||
return "nearest";
|
||||
case SQRT:
|
||||
return "sqrt";
|
||||
}
|
||||
throw new AssertionError(operation.toString());
|
||||
}
|
||||
}
|
|
@ -42,4 +42,6 @@ public final class WasmRuntime {
|
|||
public static double remainder(double a, double b) {
|
||||
return a - (double) (long) (a / b) * b;
|
||||
}
|
||||
|
||||
public static native void print(int a);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user