Fix bugs in C emitter. Improve generation of temporary variables in WASM generation. Improve test class

This commit is contained in:
Alexey Andreev 2016-08-25 17:38:27 +03:00
parent 0ac61919d5
commit 375506e875
3 changed files with 126 additions and 62 deletions

View File

@ -24,6 +24,17 @@ public final class Example {
} }
public static void main(String[] args) { public static void main(String[] args) {
testFibonacci();
testClasses();
testVirtualCall();
testInstanceOf();
testPrimitiveArray();
testLazyInitialization();
testHashCode();
testArrayList();
}
private static void testFibonacci() {
int a = 0; int a = 0;
int b = 1; int b = 1;
println("Fibonacci numbers:"); println("Fibonacci numbers:");
@ -33,9 +44,13 @@ public final class Example {
b = c; b = c;
println(String.valueOf(a)); println(String.valueOf(a));
} }
}
private static void testClasses() {
println("A(2) + A(3) = " + (new A(2).getValue() + new A(3).getValue())); println("A(2) + A(3) = " + (new A(2).getValue() + new A(3).getValue()));
}
private static void testVirtualCall() {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
println("instance(" + i + ") = " + instance(i).foo()); println("instance(" + i + ") = " + instance(i).foo());
} }
@ -45,28 +60,38 @@ public final class Example {
for (Base elem : array) { for (Base elem : array) {
println("array[i] = " + elem.foo()); println("array[i] = " + elem.foo());
} }
}
private static void testInstanceOf() {
println("Derived2 instanceof Base = " + (new Derived2() instanceof Base)); println("Derived2 instanceof Base = " + (new Derived2() instanceof Base));
println("Derived3 instanceof Base = " + (new Derived3() instanceof Base)); println("Derived3 instanceof Base = " + (new Derived3() instanceof Base));
println("Derived2 instanceof Derived1 = " + ((Object) new Derived2() instanceof Derived1)); println("Derived2 instanceof Derived1 = " + ((Object) new Derived2() instanceof Derived1));
println("Derived2 instanceof A = " + ((Object) new Derived2() instanceof A)); println("Derived2 instanceof A = " + ((Object) new Derived2() instanceof A));
println("A instanceof Base = " + (new A(23) instanceof Base)); println("A instanceof Base = " + (new A(23) instanceof Base));
}
private static void testPrimitiveArray() {
byte[] bytes = { 5, 6, 10, 15 }; byte[] bytes = { 5, 6, 10, 15 };
for (byte bt : bytes) { for (byte bt : bytes) {
println("bytes[i] = " + bt); println("bytes[i] = " + bt);
} }
}
private static void testLazyInitialization() {
Initialized.foo(); Initialized.foo();
Initialized.foo(); Initialized.foo();
Initialized.foo(); Initialized.foo();
}
private static void testHashCode() {
Object o = new Object(); Object o = new Object();
println("hashCode1 = " + o.hashCode()); println("hashCode1 = " + o.hashCode());
println("hashCode1 = " + o.hashCode()); println("hashCode1 = " + o.hashCode());
println("hashCode2 = " + new Object().hashCode()); println("hashCode2 = " + new Object().hashCode());
println("hashCode3 = " + new Object().hashCode()); println("hashCode3 = " + new Object().hashCode());
}
private static void testArrayList() {
List<Integer> list = new ArrayList<>(Arrays.asList(333, 444, 555)); List<Integer> list = new ArrayList<>(Arrays.asList(333, 444, 555));
list.add(1234); list.add(1234);
list.remove((Integer) 444); list.remove((Integer) 444);

View File

@ -15,9 +15,12 @@
*/ */
package org.teavm.backend.wasm.generate; package org.teavm.backend.wasm.generate;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -125,7 +128,8 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private Map<IdentifiedStatement, WasmBlock> breakTargets = new HashMap<>(); private Map<IdentifiedStatement, WasmBlock> breakTargets = new HashMap<>();
private Map<IdentifiedStatement, WasmBlock> continueTargets = new HashMap<>(); private Map<IdentifiedStatement, WasmBlock> continueTargets = new HashMap<>();
private Set<WasmBlock> usedBlocks = new HashSet<>(); private Set<WasmBlock> usedBlocks = new HashSet<>();
private int temporaryInt32 = -1; private List<Deque<WasmLocal>> temporaryVariablesByType = new ArrayList<>();
private List<WasmLocal> currentTemporaries = new ArrayList<>();
WasmExpression result; WasmExpression result;
WasmGenerationVisitor(WasmGenerationContext context, WasmClassGenerator classGenerator, WasmGenerationVisitor(WasmGenerationContext context, WasmClassGenerator classGenerator,
@ -135,6 +139,18 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
this.function = function; this.function = function;
this.method = method; this.method = method;
this.firstVariable = firstVariable; this.firstVariable = firstVariable;
int typeCount = WasmType.values().length;
for (int i = 0; i < typeCount; ++i) {
temporaryVariablesByType.add(new ArrayDeque<>());
}
}
private void accept(Expr expr) {
expr.acceptVisitor(this);
}
private void accept(Statement statement) {
statement.acceptVisitor(this);
} }
@Override @Override
@ -162,10 +178,13 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
Class<?> type = convertType(expr.getType()); Class<?> type = convertType(expr.getType());
MethodReference method = new MethodReference(WasmRuntime.class, "remainder", type, type, type); MethodReference method = new MethodReference(WasmRuntime.class, "remainder", type, type, type);
WasmCall call = new WasmCall(WasmMangling.mangleMethod(method), false); WasmCall call = new WasmCall(WasmMangling.mangleMethod(method), false);
expr.getFirstOperand().acceptVisitor(this);
accept(expr.getFirstOperand());
call.getArguments().add(result); call.getArguments().add(result);
expr.getSecondOperand().acceptVisitor(this);
accept(expr.getSecondOperand());
call.getArguments().add(result); call.getArguments().add(result);
call.setLocation(expr.getLocation()); call.setLocation(expr.getLocation());
result = call; result = call;
break; break;
@ -213,10 +232,13 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
Class<?> type = convertType(expr.getType()); Class<?> type = convertType(expr.getType());
MethodReference method = new MethodReference(WasmRuntime.class, "compare", type, type, int.class); MethodReference method = new MethodReference(WasmRuntime.class, "compare", type, type, int.class);
WasmCall call = new WasmCall(WasmMangling.mangleMethod(method), false); WasmCall call = new WasmCall(WasmMangling.mangleMethod(method), false);
expr.getFirstOperand().acceptVisitor(this);
accept(expr.getFirstOperand());
call.getArguments().add(result); call.getArguments().add(result);
expr.getSecondOperand().acceptVisitor(this);
accept(expr.getSecondOperand());
call.getArguments().add(result); call.getArguments().add(result);
call.setLocation(expr.getLocation()); call.setLocation(expr.getLocation());
result = call; result = call;
break; break;
@ -231,9 +253,9 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
} }
private void generateBinary(WasmIntBinaryOperation intOp, WasmFloatBinaryOperation floatOp, BinaryExpr expr) { private void generateBinary(WasmIntBinaryOperation intOp, WasmFloatBinaryOperation floatOp, BinaryExpr expr) {
expr.getFirstOperand().acceptVisitor(this); accept(expr.getFirstOperand());
WasmExpression first = result; WasmExpression first = result;
expr.getSecondOperand().acceptVisitor(this); accept(expr.getSecondOperand());
WasmExpression second = result; WasmExpression second = result;
if (expr.getType() == null) { if (expr.getType() == null) {
@ -258,9 +280,9 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
} }
private void generateBinary(WasmIntBinaryOperation intOp, BinaryExpr expr) { private void generateBinary(WasmIntBinaryOperation intOp, BinaryExpr expr) {
expr.getFirstOperand().acceptVisitor(this); accept(expr.getFirstOperand());
WasmExpression first = result; WasmExpression first = result;
expr.getSecondOperand().acceptVisitor(this); accept(expr.getSecondOperand());
WasmExpression second = result; WasmExpression second = result;
if (expr.getType() == OperationType.LONG) { if (expr.getType() == OperationType.LONG) {
@ -307,14 +329,14 @@ 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);
expr.getFirstOperand().acceptVisitor(this); accept(expr.getFirstOperand());
WasmBranch branch = new WasmBranch(negate(result), block); WasmBranch branch = new WasmBranch(negate(result), block);
branch.setResult(new WasmInt32Constant(0)); branch.setResult(new WasmInt32Constant(0));
branch.setLocation(expr.getLocation()); branch.setLocation(expr.getLocation());
branch.getResult().setLocation(expr.getLocation()); branch.getResult().setLocation(expr.getLocation());
block.getBody().add(branch); block.getBody().add(branch);
expr.getSecondOperand().acceptVisitor(this); accept(expr.getSecondOperand());
block.getBody().add(result); block.getBody().add(result);
block.setLocation(expr.getLocation()); block.setLocation(expr.getLocation());
@ -325,14 +347,14 @@ 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);
expr.getFirstOperand().acceptVisitor(this); accept(expr.getFirstOperand());
WasmBranch branch = new WasmBranch(result, block); WasmBranch branch = new WasmBranch(result, block);
branch.setResult(new WasmInt32Constant(1)); branch.setResult(new WasmInt32Constant(1));
branch.setLocation(expr.getLocation()); branch.setLocation(expr.getLocation());
branch.getResult().setLocation(expr.getLocation()); branch.getResult().setLocation(expr.getLocation());
block.getBody().add(branch); block.getBody().add(branch);
expr.getSecondOperand().acceptVisitor(this); accept(expr.getSecondOperand());
block.getBody().add(result); block.getBody().add(result);
block.setLocation(expr.getLocation()); block.setLocation(expr.getLocation());
@ -344,7 +366,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
public void visit(UnaryExpr expr) { public void visit(UnaryExpr expr) {
switch (expr.getOperation()) { switch (expr.getOperation()) {
case INT_TO_BYTE: case INT_TO_BYTE:
expr.getOperand().acceptVisitor(this); accept(expr.getOperand());
result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL, result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL,
result, new WasmInt32Constant(24)); result, new WasmInt32Constant(24));
result.setLocation(expr.getLocation()); result.setLocation(expr.getLocation());
@ -353,7 +375,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
result.setLocation(expr.getLocation()); result.setLocation(expr.getLocation());
break; break;
case INT_TO_SHORT: case INT_TO_SHORT:
expr.getOperand().acceptVisitor(this); accept(expr.getOperand());
result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL, result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL,
result, new WasmInt32Constant(16)); result, new WasmInt32Constant(16));
result.setLocation(expr.getLocation()); result.setLocation(expr.getLocation());
@ -362,7 +384,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
result.setLocation(expr.getLocation()); result.setLocation(expr.getLocation());
break; break;
case INT_TO_CHAR: case INT_TO_CHAR:
expr.getOperand().acceptVisitor(this); accept(expr.getOperand());
result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL, result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL,
result, new WasmInt32Constant(16)); result, new WasmInt32Constant(16));
result.setLocation(expr.getLocation()); result.setLocation(expr.getLocation());
@ -371,15 +393,15 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
result.setLocation(expr.getLocation()); result.setLocation(expr.getLocation());
break; break;
case LENGTH: case LENGTH:
expr.getOperand().acceptVisitor(this); accept(expr.getOperand());
result = generateArrayLength(result); result = generateArrayLength(result);
break; break;
case NOT: case NOT:
expr.getOperand().acceptVisitor(this); accept(expr.getOperand());
result = negate(result); result = negate(result);
break; break;
case NEGATE: case NEGATE:
expr.getOperand().acceptVisitor(this); accept(expr.getOperand());
switch (expr.getType()) { switch (expr.getType()) {
case INT: case INT:
result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SUB, result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SUB,
@ -404,7 +426,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
} }
break; break;
case NULL_CHECK: case NULL_CHECK:
expr.getOperand().acceptVisitor(this); accept(expr.getOperand());
break; break;
} }
} }
@ -425,13 +447,13 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
public void visit(AssignmentStatement statement) { public void visit(AssignmentStatement statement) {
Expr left = statement.getLeftValue(); Expr left = statement.getLeftValue();
if (left == null) { if (left == null) {
statement.getRightValue().acceptVisitor(this); accept(statement.getRightValue());
result = new WasmDrop(result); result = new WasmDrop(result);
result.setLocation(statement.getLocation()); 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);
statement.getRightValue().acceptVisitor(this); accept(statement.getRightValue());
result = new WasmSetLocal(local, result); result = new WasmSetLocal(local, result);
result.setLocation(statement.getLocation()); result.setLocation(statement.getLocation());
} else if (left instanceof QualificationExpr) { } else if (left instanceof QualificationExpr) {
@ -448,7 +470,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private void storeField(Expr qualified, FieldReference field, Expr value, TextLocation location) { private void storeField(Expr qualified, FieldReference field, Expr value, TextLocation location) {
WasmExpression address = getAddress(qualified, field, location); WasmExpression address = getAddress(qualified, field, location);
ValueType type = context.getFieldType(field); ValueType type = context.getFieldType(field);
value.acceptVisitor(this); accept(value);
if (type instanceof ValueType.Primitive) { if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) { switch (((ValueType.Primitive) type).getKind()) {
case BOOLEAN: case BOOLEAN:
@ -482,7 +504,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private void storeArrayItem(SubscriptExpr leftValue, Expr rightValue) { private void storeArrayItem(SubscriptExpr leftValue, Expr rightValue) {
WasmExpression ptr = getArrayElementPointer(leftValue); WasmExpression ptr = getArrayElementPointer(leftValue);
rightValue.acceptVisitor(this); accept(rightValue);
switch (leftValue.getType()) { switch (leftValue.getType()) {
case BYTE: case BYTE:
@ -512,12 +534,15 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(ConditionalExpr expr) { public void visit(ConditionalExpr expr) {
expr.getCondition().acceptVisitor(this); accept(expr.getCondition());
WasmConditional conditional = new WasmConditional(forCondition(result)); WasmConditional conditional = new WasmConditional(forCondition(result));
expr.getConsequent().acceptVisitor(this);
accept(expr.getConsequent());
conditional.getThenBlock().getBody().add(result); conditional.getThenBlock().getBody().add(result);
expr.getAlternative().acceptVisitor(this);
accept(expr.getAlternative());
conditional.getElseBlock().getBody().add(result); conditional.getElseBlock().getBody().add(result);
result = conditional; result = conditional;
} }
@ -525,7 +550,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
public void visit(SequentialStatement statement) { public void visit(SequentialStatement statement) {
WasmBlock block = new WasmBlock(false); WasmBlock block = new WasmBlock(false);
for (Statement part : statement.getSequence()) { for (Statement part : statement.getSequence()) {
part.acceptVisitor(this); accept(part);
if (result != null) { if (result != null) {
block.getBody().add(result); block.getBody().add(result);
} }
@ -555,16 +580,17 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(ConditionalStatement statement) { public void visit(ConditionalStatement statement) {
statement.getCondition().acceptVisitor(this); accept(statement.getCondition());
WasmConditional conditional = new WasmConditional(forCondition(result)); WasmConditional conditional = new WasmConditional(forCondition(result));
for (Statement part : statement.getConsequent()) { for (Statement part : statement.getConsequent()) {
part.acceptVisitor(this); accept(part);
if (result != null) { if (result != null) {
conditional.getThenBlock().getBody().add(result); conditional.getThenBlock().getBody().add(result);
} }
} }
for (Statement part : statement.getAlternative()) { for (Statement part : statement.getAlternative()) {
part.acceptVisitor(this); accept(part);
if (result != null) { if (result != null) {
conditional.getElseBlock().getBody().add(result); conditional.getElseBlock().getBody().add(result);
} }
@ -607,9 +633,10 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
} }
private WasmExpression getArrayElementPointer(SubscriptExpr expr) { private WasmExpression getArrayElementPointer(SubscriptExpr expr) {
expr.getArray().acceptVisitor(this); accept(expr.getArray());
WasmExpression array = result; WasmExpression array = result;
expr.getIndex().acceptVisitor(this);
accept(expr.getIndex());
WasmExpression index = result; WasmExpression index = result;
int size = -1; int size = -1;
@ -658,7 +685,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
currentBreakTarget = statement; currentBreakTarget = statement;
WasmBlock wrapper = new WasmBlock(false); WasmBlock wrapper = new WasmBlock(false);
statement.getValue().acceptVisitor(this); accept(statement.getValue());
if (min > 0) { if (min > 0) {
result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SUB, result, result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SUB, result,
new WasmInt32Constant(min)); new WasmInt32Constant(min));
@ -677,7 +704,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
} }
for (Statement part : clause.getBody()) { for (Statement part : clause.getBody()) {
part.acceptVisitor(this); accept(part);
if (result != null) { if (result != null) {
caseBlock.getBody().add(result); caseBlock.getBody().add(result);
} }
@ -687,7 +714,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
defaultBlock.getBody().add(wrapper); defaultBlock.getBody().add(wrapper);
for (Statement part : statement.getDefaultClause()) { for (Statement part : statement.getDefaultClause()) {
part.acceptVisitor(this); accept(part);
if (result != null) { if (result != null) {
defaultBlock.getBody().add(result); defaultBlock.getBody().add(result);
} }
@ -707,7 +734,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(UnwrapArrayExpr expr) { public void visit(UnwrapArrayExpr expr) {
expr.getArray().acceptVisitor(this); accept(expr.getArray());
} }
@Override @Override
@ -723,13 +750,13 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
currentContinueTarget = statement; currentContinueTarget = statement;
if (statement.getCondition() != null) { if (statement.getCondition() != null) {
statement.getCondition().acceptVisitor(this); accept(statement.getCondition());
loop.getBody().add(new WasmBranch(negate(result), wrapper)); loop.getBody().add(new WasmBranch(negate(result), wrapper));
usedBlocks.add(wrapper); usedBlocks.add(wrapper);
} }
for (Statement part : statement.getBody()) { for (Statement part : statement.getBody()) {
part.acceptVisitor(this); accept(part);
if (result != null) { if (result != null) {
loop.getBody().add(result); loop.getBody().add(result);
} }
@ -765,13 +792,13 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
call.setImported(true); call.setImported(true);
} }
for (Expr argument : expr.getArguments()) { for (Expr argument : expr.getArguments()) {
argument.acceptVisitor(this); accept(argument);
call.getArguments().add(result); call.getArguments().add(result);
} }
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);
WasmLocal tmp = function.getLocalVariables().get(getTemporaryInt32()); 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())));
@ -779,19 +806,21 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
WasmCall call = new WasmCall(methodName); WasmCall call = new WasmCall(methodName);
call.getArguments().add(new WasmGetLocal(tmp)); call.getArguments().add(new WasmGetLocal(tmp));
for (Expr argument : expr.getArguments()) { for (Expr argument : expr.getArguments()) {
argument.acceptVisitor(this); accept(argument);
call.getArguments().add(result); call.getArguments().add(result);
} }
block.getBody().add(call); block.getBody().add(call);
block.getBody().add(new WasmGetLocal(tmp)); block.getBody().add(new WasmGetLocal(tmp));
releaseTemporary(tmp);
result = block; result = block;
} else { } else {
expr.getArguments().get(0).acceptVisitor(this); accept(expr.getArguments().get(0));
WasmExpression instance = result; WasmExpression instance = result;
WasmBlock block = new WasmBlock(false); WasmBlock block = new WasmBlock(false);
WasmLocal instanceVar = function.getLocalVariables().get(getTemporaryInt32());
WasmLocal instanceVar = getTemporary(WasmType.INT32);
block.getBody().add(new WasmSetLocal(instanceVar, instance)); block.getBody().add(new WasmSetLocal(instanceVar, instance));
instance = new WasmGetLocal(instanceVar); instance = new WasmGetLocal(instanceVar);
@ -824,11 +853,12 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
call.getArguments().add(instance); call.getArguments().add(instance);
for (int i = 1; i < expr.getArguments().size(); ++i) { for (int i = 1; i < expr.getArguments().size(); ++i) {
expr.getArguments().get(i).acceptVisitor(this); accept(expr.getArguments().get(i));
call.getArguments().add(result); call.getArguments().add(result);
} }
block.getBody().add(call); block.getBody().add(call);
releaseTemporary(instanceVar);
result = block; result = block;
} }
} }
@ -842,7 +872,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
} }
for (Statement part : statement.getBody()) { for (Statement part : statement.getBody()) {
part.acceptVisitor(this); accept(part);
if (result != null) { if (result != null) {
block.getBody().add(result); block.getBody().add(result);
} }
@ -897,7 +927,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
result.setLocation(location); result.setLocation(location);
return result; return result;
} else { } else {
qualified.acceptVisitor(this); accept(qualified);
if (offset != 0) { if (offset != 0) {
WasmExpression offsetExpr = new WasmInt32Constant(offset); WasmExpression offsetExpr = new WasmInt32Constant(offset);
offsetExpr.setLocation(qualified.getLocation()); offsetExpr.setLocation(qualified.getLocation());
@ -960,7 +990,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
RuntimeClass.class, int.class, Address.class)); RuntimeClass.class, int.class, Address.class));
WasmCall call = new WasmCall(allocName); WasmCall call = new WasmCall(allocName);
call.getArguments().add(new WasmInt32Constant(classPointer)); call.getArguments().add(new WasmInt32Constant(classPointer));
expr.getLength().acceptVisitor(this); accept(expr.getLength());
call.getArguments().add(result); call.getArguments().add(result);
call.setLocation(expr.getLocation()); call.setLocation(expr.getLocation());
@ -974,7 +1004,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(ReturnStatement statement) { public void visit(ReturnStatement statement) {
if (statement.getResult() != null) { if (statement.getResult() != null) {
statement.getResult().acceptVisitor(this); accept(statement.getResult());
} else { } else {
result = null; result = null;
} }
@ -984,7 +1014,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(InstanceOfExpr expr) { public void visit(InstanceOfExpr expr) {
expr.getExpr().acceptVisitor(this); accept(expr.getExpr());
if (expr.getType() instanceof ValueType.Object) { if (expr.getType() instanceof ValueType.Object) {
ValueType.Object cls = (ValueType.Object) expr.getType(); ValueType.Object cls = (ValueType.Object) expr.getType();
@ -993,7 +1023,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
WasmBlock block = new WasmBlock(false); WasmBlock block = new WasmBlock(false);
block.setLocation(expr.getLocation()); block.setLocation(expr.getLocation());
WasmLocal tagVar = function.getLocalVariables().get(getTemporaryInt32()); 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,
getReferenceToClass(result), new WasmInt32Constant(tagOffset)); getReferenceToClass(result), new WasmInt32Constant(tagOffset));
@ -1028,6 +1058,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
} }
block.getBody().add(new WasmInt32Constant(1)); block.getBody().add(new WasmInt32Constant(1));
releaseTemporary(tagVar);
result = block; result = block;
} else if (expr.getType() instanceof ValueType.Array) { } else if (expr.getType() instanceof ValueType.Array) {
@ -1041,7 +1072,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
public void visit(ThrowStatement statement) { public void visit(ThrowStatement statement) {
WasmBlock block = new WasmBlock(false); WasmBlock block = new WasmBlock(false);
block.setLocation(statement.getLocation()); block.setLocation(statement.getLocation());
statement.getException().acceptVisitor(this); accept(statement.getException());
block.getBody().add(result); block.getBody().add(result);
block.getBody().add(new WasmUnreachable()); block.getBody().add(new WasmUnreachable());
@ -1051,7 +1082,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(CastExpr expr) { public void visit(CastExpr expr) {
expr.getValue().acceptVisitor(this); accept(expr.getValue());
} }
@Override @Override
@ -1066,7 +1097,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(PrimitiveCastExpr expr) { public void visit(PrimitiveCastExpr expr) {
expr.getValue().acceptVisitor(this); accept(expr.getValue());
result = new WasmConversion(WasmGeneratorUtil.mapType(expr.getSource()), result = new WasmConversion(WasmGeneratorUtil.mapType(expr.getSource()),
WasmGeneratorUtil.mapType(expr.getTarget()), true, result); WasmGeneratorUtil.mapType(expr.getTarget()), true, result);
result.setLocation(expr.getLocation()); result.setLocation(expr.getLocation());
@ -1232,17 +1263,25 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private WasmIntrinsicManager intrinsicManager = new WasmIntrinsicManager() { private WasmIntrinsicManager intrinsicManager = new WasmIntrinsicManager() {
@Override @Override
public WasmExpression generate(Expr expr) { public WasmExpression generate(Expr expr) {
expr.acceptVisitor(WasmGenerationVisitor.this); accept(expr);
return result; return result;
} }
}; };
private int getTemporaryInt32() { private WasmLocal getTemporary(WasmType type) {
if (temporaryInt32 < 0) { Deque<WasmLocal> stack = temporaryVariablesByType.get(type.ordinal());
temporaryInt32 = function.getLocalVariables().size(); WasmLocal variable = stack.pollFirst();
function.add(new WasmLocal(WasmType.INT32)); if (variable == null) {
variable = new WasmLocal(type);
function.add(variable);
} }
return temporaryInt32; currentTemporaries.add(variable);
return variable;
}
private void releaseTemporary(WasmLocal variable) {
Deque<WasmLocal> stack = temporaryVariablesByType.get(variable.getType().ordinal());
stack.push(variable);
} }
private WasmExpression getReferenceToClass(WasmExpression instance) { private WasmExpression getReferenceToClass(WasmExpression instance) {

View File

@ -303,7 +303,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
@Override @Override
public void visit(WasmGetLocal expression) { public void visit(WasmGetLocal expression) {
value = CExpression.relocatable("var_" + expression.getLocal().getIndex()); value = new CExpression("var_" + expression.getLocal().getIndex());
} }
@Override @Override
@ -713,7 +713,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = signature.get(i); requiredType = signature.get(i);
wasmArguments.get(i).acceptVisitor(this); wasmArguments.get(i).acceptVisitor(this);
arguments.add(value); arguments.add(value);
if (!result.getLines().isEmpty() && needsCachingUntil == 0) { if (!value.getLines().isEmpty() && needsCachingUntil == 0) {
needsCachingUntil = i; needsCachingUntil = i;
} }
} }