mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
wasm gc: implement branching instructions and null check instruction
This commit is contained in:
parent
5acb9a4707
commit
7029d3cff7
|
@ -120,10 +120,33 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
||||||
case BR_IF:
|
case BR_IF:
|
||||||
writer.write("br_if");
|
writer.write("br_if");
|
||||||
break;
|
break;
|
||||||
|
case BR_ON_NULL:
|
||||||
|
writer.write("br_on_null");
|
||||||
|
break;
|
||||||
|
case BR_ON_NON_NULL:
|
||||||
|
writer.write("br_on_non_null");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
writer.endLink().write(" $label_" + target).eol();
|
writer.endLink().write(" $label_" + target).eol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void castBranch(boolean success, int depth, int target, WasmHollowType.Reference sourceType,
|
||||||
|
WasmHollowType.Reference targetType) {
|
||||||
|
writer.address().startLink("start" + target);
|
||||||
|
if (success) {
|
||||||
|
writer.write("br_if_cast");
|
||||||
|
} else {
|
||||||
|
writer.write("br_if_cast_fail");
|
||||||
|
}
|
||||||
|
writer.endLink().write(" $label_" + target);
|
||||||
|
writer.write(" ");
|
||||||
|
writeType(sourceType);
|
||||||
|
writer.write(" ");
|
||||||
|
writeType(sourceType);
|
||||||
|
writer.eol();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tableBranch(int[] depths, int[] targets, int defaultDepth, int defaultTarget) {
|
public void tableBranch(int[] depths, int[] targets, int defaultDepth, int defaultTarget) {
|
||||||
writer.address();
|
writer.address();
|
||||||
|
@ -162,6 +185,9 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
||||||
case ARRAY_LENGTH:
|
case ARRAY_LENGTH:
|
||||||
writer.write("array.length");
|
writer.write("array.length");
|
||||||
break;
|
break;
|
||||||
|
case IS_NULL:
|
||||||
|
writer.write("ref.is_null");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
writer.eol();
|
writer.eol();
|
||||||
}
|
}
|
||||||
|
|
|
@ -449,7 +449,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
|
|
||||||
protected abstract boolean isManagedCall(MethodReference method);
|
protected abstract boolean isManagedCall(MethodReference method);
|
||||||
|
|
||||||
private WasmExpression nullCheck(Expr value, TextLocation location) {
|
protected WasmExpression nullCheck(Expr value, TextLocation location) {
|
||||||
var block = new WasmBlock(false);
|
var block = new WasmBlock(false);
|
||||||
block.setLocation(location);
|
block.setLocation(location);
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||||
|
@ -156,8 +156,7 @@ public class WasmGCSupertypeFunctionGenerator implements WasmGCSupertypeFunction
|
||||||
var itemExpression = getClassField(new WasmGetLocal(subtypeVar), itemOffset);
|
var itemExpression = getClassField(new WasmGetLocal(subtypeVar), itemOffset);
|
||||||
body.add(new WasmSetLocal(subtypeVar, itemExpression));
|
body.add(new WasmSetLocal(subtypeVar, itemExpression));
|
||||||
|
|
||||||
var itemTest = new WasmConditional(new WasmReferencesEqual(new WasmGetLocal(subtypeVar),
|
var itemTest = new WasmConditional(new WasmIsNull(new WasmGetLocal(subtypeVar)));
|
||||||
new WasmNullConstant(WasmType.Reference.STRUCT)));
|
|
||||||
itemTest.setType(WasmType.INT32);
|
itemTest.setType(WasmType.INT32);
|
||||||
itemTest.getThenBlock().getBody().add(new WasmInt32Constant(0));
|
itemTest.getThenBlock().getBody().add(new WasmInt32Constant(0));
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,9 @@ import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullBranch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullCondition;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||||
|
@ -232,7 +235,32 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WasmExpression genIsNull(WasmExpression value) {
|
protected WasmExpression genIsNull(WasmExpression value) {
|
||||||
return new WasmReferencesEqual(value, new WasmNullConstant(WasmType.Reference.STRUCT));
|
return new WasmIsNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WasmExpression nullCheck(Expr value, TextLocation location) {
|
||||||
|
var block = new WasmBlock(false);
|
||||||
|
block.setLocation(location);
|
||||||
|
|
||||||
|
accept(value);
|
||||||
|
if (result instanceof WasmUnreachable) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.acceptVisitor(typeInference);
|
||||||
|
block.setType(typeInference.getResult());
|
||||||
|
var cachedValue = exprCache.create(result, typeInference.getResult(), location, block.getBody());
|
||||||
|
|
||||||
|
var check = new WasmNullBranch(WasmNullCondition.NOT_NULL, cachedValue.expr(), block);
|
||||||
|
check.setResult(cachedValue.expr());
|
||||||
|
block.getBody().add(new WasmDrop(check));
|
||||||
|
|
||||||
|
var callSiteId = generateCallSiteId(location);
|
||||||
|
callSiteId.generateRegister(block.getBody(), location);
|
||||||
|
generateThrowNPE(location, block.getBody());
|
||||||
|
callSiteId.generateThrow(block.getBody(), location);
|
||||||
|
|
||||||
|
cachedValue.release();
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,8 +22,7 @@ import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
|
@ -50,8 +49,7 @@ public class ClassGenerators implements WasmGCCustomGenerator {
|
||||||
function.add(thisVar);
|
function.add(thisVar);
|
||||||
function.add(otherClassVar);
|
function.add(otherClassVar);
|
||||||
|
|
||||||
var conditional = new WasmConditional(new WasmReferencesEqual(new WasmGetLocal(otherClassVar),
|
var conditional = new WasmConditional(new WasmIsNull(new WasmGetLocal(otherClassVar)));
|
||||||
new WasmNullConstant(WasmType.Reference.STRUCT)));
|
|
||||||
function.getBody().add(conditional);
|
function.getBody().add(conditional);
|
||||||
var npe = new WasmCall(context.functions().forStaticMethod(new MethodReference(WasmGCSupport.class, "npe",
|
var npe = new WasmCall(context.functions().forStaticMethod(new MethodReference(WasmGCSupport.class, "npe",
|
||||||
NullPointerException.class)));
|
NullPointerException.class)));
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.model.expression;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
|
||||||
|
public class WasmCastBranch extends WasmExpression {
|
||||||
|
private WasmCastCondition condition;
|
||||||
|
private WasmExpression value;
|
||||||
|
private WasmType.Reference sourceType;
|
||||||
|
private WasmType.Reference type;
|
||||||
|
private WasmBlock target;
|
||||||
|
private WasmExpression result;
|
||||||
|
|
||||||
|
public WasmCastBranch(WasmCastCondition condition, WasmExpression value, WasmType.Reference sourceType,
|
||||||
|
WasmType.Reference type, WasmBlock target) {
|
||||||
|
this.condition = Objects.requireNonNull(condition);
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
this.type = Objects.requireNonNull(type);
|
||||||
|
this.target = Objects.requireNonNull(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmCastCondition getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCondition(WasmCastCondition condition) {
|
||||||
|
this.condition = Objects.requireNonNull(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(WasmExpression value) {
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmType.Reference getSourceType() {
|
||||||
|
return sourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceType(WasmType.Reference sourceType) {
|
||||||
|
this.sourceType = Objects.requireNonNull(sourceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmType.Reference getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(WasmType.Reference type) {
|
||||||
|
this.type = Objects.requireNonNull(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmBlock getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget(WasmBlock target) {
|
||||||
|
this.target = Objects.requireNonNull(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(WasmExpression result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.model.expression;
|
||||||
|
|
||||||
|
public enum WasmCastCondition {
|
||||||
|
SUCCESS,
|
||||||
|
FAILURE
|
||||||
|
}
|
|
@ -31,6 +31,22 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullBranch expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
expression.getResult().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCastBranch expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
expression.getResult().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBreak expression) {
|
public void visit(WasmBreak expression) {
|
||||||
if (expression.getResult() != null) {
|
if (expression.getResult() != null) {
|
||||||
|
@ -85,6 +101,11 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmNullConstant expression) {
|
public void visit(WasmNullConstant expression) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIsNull expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmGetLocal expression) {
|
public void visit(WasmGetLocal expression) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ public interface WasmExpressionVisitor {
|
||||||
|
|
||||||
void visit(WasmBranch expression);
|
void visit(WasmBranch expression);
|
||||||
|
|
||||||
|
void visit(WasmNullBranch expression);
|
||||||
|
|
||||||
|
void visit(WasmCastBranch expression);
|
||||||
|
|
||||||
void visit(WasmBreak expression);
|
void visit(WasmBreak expression);
|
||||||
|
|
||||||
void visit(WasmSwitch expression);
|
void visit(WasmSwitch expression);
|
||||||
|
@ -40,6 +44,8 @@ public interface WasmExpressionVisitor {
|
||||||
|
|
||||||
void visit(WasmNullConstant expression);
|
void visit(WasmNullConstant expression);
|
||||||
|
|
||||||
|
void visit(WasmIsNull expression);
|
||||||
|
|
||||||
void visit(WasmGetLocal expression);
|
void visit(WasmGetLocal expression);
|
||||||
|
|
||||||
void visit(WasmSetLocal expression);
|
void visit(WasmSetLocal expression);
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.model.expression;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class WasmIsNull extends WasmExpression {
|
||||||
|
private WasmExpression value;
|
||||||
|
|
||||||
|
public WasmIsNull(WasmExpression value) {
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(WasmExpression value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.model.expression;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class WasmNullBranch extends WasmExpression {
|
||||||
|
private WasmNullCondition condition;
|
||||||
|
private WasmExpression value;
|
||||||
|
private WasmBlock target;
|
||||||
|
private WasmExpression result;
|
||||||
|
|
||||||
|
public WasmNullBranch(WasmNullCondition condition, WasmExpression value, WasmBlock target) {
|
||||||
|
this.condition = Objects.requireNonNull(condition);
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
this.target = Objects.requireNonNull(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmNullCondition getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCondition(WasmNullCondition condition) {
|
||||||
|
this.condition = Objects.requireNonNull(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(WasmExpression value) {
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmBlock getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget(WasmBlock target) {
|
||||||
|
this.target = Objects.requireNonNull(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(WasmExpression result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.model.expression;
|
||||||
|
|
||||||
|
public enum WasmNullCondition {
|
||||||
|
NULL,
|
||||||
|
NOT_NULL
|
||||||
|
}
|
|
@ -55,6 +55,26 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullBranch expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
expression.setValue(mapper.apply(expression.getValue()));
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
expression.getResult().acceptVisitor(this);
|
||||||
|
expression.setResult(mapper.apply(expression.getResult()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCastBranch expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
expression.setValue(mapper.apply(expression.getValue()));
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
expression.getResult().acceptVisitor(this);
|
||||||
|
expression.setResult(mapper.apply(expression.getResult()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBreak expression) {
|
public void visit(WasmBreak expression) {
|
||||||
if (expression.getResult() != null) {
|
if (expression.getResult() != null) {
|
||||||
|
@ -109,6 +129,12 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmNullConstant expression) {
|
public void visit(WasmNullConstant expression) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIsNull expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
expression.setValue(mapper.apply(expression.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmGetLocal expression) {
|
public void visit(WasmGetLocal expression) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,5 +17,7 @@ package org.teavm.backend.wasm.parser;
|
||||||
|
|
||||||
public enum BranchOpcode {
|
public enum BranchOpcode {
|
||||||
BR,
|
BR,
|
||||||
BR_IF
|
BR_IF,
|
||||||
|
BR_ON_NULL,
|
||||||
|
BR_ON_NON_NULL
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,10 @@ public interface CodeListener {
|
||||||
default void branch(BranchOpcode opcode, int depth, int target) {
|
default void branch(BranchOpcode opcode, int depth, int target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void castBranch(boolean success, int depth, int target, WasmHollowType.Reference sourceType,
|
||||||
|
WasmHollowType.Reference targetType) {
|
||||||
|
}
|
||||||
|
|
||||||
default void tableBranch(int[] depths, int[] targets, int defaultDepth, int defaultTarget) {
|
default void tableBranch(int[] depths, int[] targets, int defaultDepth, int defaultTarget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -591,6 +591,9 @@ public class CodeParser extends BaseSectionParser {
|
||||||
case 0xD0:
|
case 0xD0:
|
||||||
codeListener.nullConstant(reader.readHeapType(true));
|
codeListener.nullConstant(reader.readHeapType(true));
|
||||||
break;
|
break;
|
||||||
|
case 0xD1:
|
||||||
|
codeListener.opcode(Opcode.IS_NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0xD2:
|
case 0xD2:
|
||||||
codeListener.functionReference(readLEB());
|
codeListener.functionReference(readLEB());
|
||||||
|
@ -600,6 +603,13 @@ public class CodeParser extends BaseSectionParser {
|
||||||
codeListener.opcode(Opcode.REF_EQ);
|
codeListener.opcode(Opcode.REF_EQ);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0xD5:
|
||||||
|
parseBranch(BranchOpcode.BR_ON_NULL);
|
||||||
|
break;
|
||||||
|
case 0xD6:
|
||||||
|
parseBranch(BranchOpcode.BR_ON_NON_NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0xFB:
|
case 0xFB:
|
||||||
return parseExtExpr2();
|
return parseExtExpr2();
|
||||||
case 0xFC:
|
case 0xFC:
|
||||||
|
@ -702,6 +712,13 @@ public class CodeParser extends BaseSectionParser {
|
||||||
codeListener.cast(reader.readHeapType(true));
|
codeListener.cast(reader.readHeapType(true));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case 24:
|
||||||
|
parseCastBranch(true);
|
||||||
|
return true;
|
||||||
|
case 25:
|
||||||
|
parseCastBranch(false);
|
||||||
|
return true;
|
||||||
|
|
||||||
case 28:
|
case 28:
|
||||||
codeListener.int31Reference();
|
codeListener.int31Reference();
|
||||||
return true;
|
return true;
|
||||||
|
@ -798,6 +815,15 @@ public class CodeParser extends BaseSectionParser {
|
||||||
codeListener.branch(opcode, depth, target.token);
|
codeListener.branch(opcode, depth, target.token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parseCastBranch(boolean success) {
|
||||||
|
var depth = readLEB();
|
||||||
|
var target = blockStack.get(blockStack.size() - depth - 1);
|
||||||
|
var flags = reader.data[reader.ptr++];
|
||||||
|
var sourceType = reader.readHeapType((flags & 1) != 0);
|
||||||
|
var targetType = reader.readHeapType((flags & 2) != 0);
|
||||||
|
codeListener.castBranch(success, depth, target.token, sourceType, targetType);
|
||||||
|
}
|
||||||
|
|
||||||
private void parseTableBranch() {
|
private void parseTableBranch() {
|
||||||
var count = readLEB();
|
var count = readLEB();
|
||||||
var depths = new int[count];
|
var depths = new int[count];
|
||||||
|
|
|
@ -21,5 +21,6 @@ public enum Opcode {
|
||||||
RETURN,
|
RETURN,
|
||||||
DROP,
|
DROP,
|
||||||
REF_EQ,
|
REF_EQ,
|
||||||
ARRAY_LENGTH
|
ARRAY_LENGTH,
|
||||||
|
IS_NULL
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCastBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
||||||
|
@ -61,11 +62,13 @@ import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
|
@ -122,6 +125,18 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
register(expression.getTarget());
|
register(expression.getTarget());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullBranch expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
register(expression.getTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCastBranch expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
register(expression.getTarget());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBreak expression) {
|
public void visit(WasmBreak expression) {
|
||||||
super.visit(expression);
|
super.visit(expression);
|
||||||
|
@ -186,6 +201,55 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullBranch expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
expression.getResult().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
switch (expression.getCondition()) {
|
||||||
|
case NULL:
|
||||||
|
writer.writeByte(0xD5);
|
||||||
|
break;
|
||||||
|
case NOT_NULL:
|
||||||
|
writer.writeByte(0xD6);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
writeLabel(expression.getTarget());
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCastBranch expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
expression.getResult().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
writer.writeByte(0xFB);
|
||||||
|
switch (expression.getCondition()) {
|
||||||
|
case SUCCESS:
|
||||||
|
writer.writeByte(24);
|
||||||
|
break;
|
||||||
|
case FAILURE:
|
||||||
|
writer.writeByte(25);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
writeLabel(expression.getTarget());
|
||||||
|
var flags = 0;
|
||||||
|
if (expression.getSourceType().isNullable()) {
|
||||||
|
flags |= 1;
|
||||||
|
}
|
||||||
|
if (expression.getType().isNullable()) {
|
||||||
|
flags |= 2;
|
||||||
|
}
|
||||||
|
writer.writeByte(flags);
|
||||||
|
writer.writeHeapType(expression.getSourceType(), module);
|
||||||
|
writer.writeHeapType(expression.getType(), module);
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBreak expression) {
|
public void visit(WasmBreak expression) {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
|
@ -304,6 +368,14 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIsNull expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
writer.writeByte(0xD1);
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmGetLocal expression) {
|
public void visit(WasmGetLocal expression) {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCastBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
||||||
|
@ -62,11 +63,13 @@ import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
|
@ -187,6 +190,16 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
||||||
value = result;
|
value = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullBranch expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCastBranch expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBreak expression) {
|
public void visit(WasmBreak expression) {
|
||||||
CExpression result = new CExpression();
|
CExpression result = new CExpression();
|
||||||
|
@ -359,6 +372,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
||||||
value = CExpression.relocatable("/* can't produce ref.null */");
|
value = CExpression.relocatable("/* can't produce ref.null */");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIsNull expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmGetLocal expression) {
|
public void visit(WasmGetLocal expression) {
|
||||||
value = new CExpression(getVariableName(expression.getLocal()));
|
value = new CExpression(getVariableName(expression.getLocal()));
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCastBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
||||||
|
@ -63,11 +64,13 @@ import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
|
@ -108,6 +111,18 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
register(expression.getTarget());
|
register(expression.getTarget());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCastBranch expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
register(expression.getTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullBranch expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
register(expression.getTarget());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBreak expression) {
|
public void visit(WasmBreak expression) {
|
||||||
super.visit(expression);
|
super.visit(expression);
|
||||||
|
@ -219,6 +234,46 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullBranch expression) {
|
||||||
|
String id = blockIdentifiers.get(expression.getTarget());
|
||||||
|
open();
|
||||||
|
switch (expression.getCondition()) {
|
||||||
|
case NULL:
|
||||||
|
append("br_on_null");
|
||||||
|
break;
|
||||||
|
case NOT_NULL:
|
||||||
|
append("br_on_non_null");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
append(" $" + id);
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
line(expression.getResult());
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCastBranch expression) {
|
||||||
|
String id = blockIdentifiers.get(expression.getTarget());
|
||||||
|
open();
|
||||||
|
switch (expression.getCondition()) {
|
||||||
|
case SUCCESS:
|
||||||
|
append("br_on_cast");
|
||||||
|
break;
|
||||||
|
case FAILURE:
|
||||||
|
append("br_on_cast_fail");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
append(" $").append(id);
|
||||||
|
append(" ").append(type(expression.getSourceType()));
|
||||||
|
append(" ").append(type(expression.getType()));
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
line(expression.getResult());
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBreak expression) {
|
public void visit(WasmBreak expression) {
|
||||||
String id = blockIdentifiers.get(expression.getTarget());
|
String id = blockIdentifiers.get(expression.getTarget());
|
||||||
|
@ -300,6 +355,11 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
open().append("ref.null " + type(expression.getType())).close();
|
open().append("ref.null " + type(expression.getType())).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIsNull expression) {
|
||||||
|
open().append("ref.is_null").close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmGetLocal expression) {
|
public void visit(WasmGetLocal expression) {
|
||||||
open().append("local.get " + asString(expression.getLocal())).close();
|
open().append("local.get " + asString(expression.getLocal())).close();
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCastBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
||||||
|
@ -50,11 +51,13 @@ import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
|
@ -88,7 +91,28 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmBranch expression) {
|
public void visit(WasmBranch expression) {
|
||||||
result = null;
|
if (expression.getResult() != null) {
|
||||||
|
expression.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullBranch expression) {
|
||||||
|
if (expression.getResult() != null) {
|
||||||
|
expression.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCastBranch expression) {
|
||||||
|
switch (expression.getCondition()) {
|
||||||
|
case SUCCESS:
|
||||||
|
result = expression.getSourceType();
|
||||||
|
break;
|
||||||
|
case FAILURE:
|
||||||
|
result = expression.getType();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -186,6 +210,12 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
result = expression.type;
|
result = expression.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmIsNull expression) {
|
||||||
|
result = WasmType.INT32;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmCall expression) {
|
public void visit(WasmCall expression) {
|
||||||
var function = expression.getFunction();
|
var function = expression.getFunction();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user