mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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:
|
||||
writer.write("br_if");
|
||||
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();
|
||||
}
|
||||
|
||||
@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
|
||||
public void tableBranch(int[] depths, int[] targets, int defaultDepth, int defaultTarget) {
|
||||
writer.address();
|
||||
|
@ -162,6 +185,9 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
case ARRAY_LENGTH:
|
||||
writer.write("array.length");
|
||||
break;
|
||||
case IS_NULL:
|
||||
writer.write("ref.is_null");
|
||||
break;
|
||||
}
|
||||
writer.eol();
|
||||
}
|
||||
|
|
|
@ -449,7 +449,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
|
||||
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);
|
||||
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.WasmIntBinaryOperation;
|
||||
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.WasmReturn;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||
|
@ -156,8 +156,7 @@ public class WasmGCSupertypeFunctionGenerator implements WasmGCSupertypeFunction
|
|||
var itemExpression = getClassField(new WasmGetLocal(subtypeVar), itemOffset);
|
||||
body.add(new WasmSetLocal(subtypeVar, itemExpression));
|
||||
|
||||
var itemTest = new WasmConditional(new WasmReferencesEqual(new WasmGetLocal(subtypeVar),
|
||||
new WasmNullConstant(WasmType.Reference.STRUCT)));
|
||||
var itemTest = new WasmConditional(new WasmIsNull(new WasmGetLocal(subtypeVar)));
|
||||
itemTest.setType(WasmType.INT32);
|
||||
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.WasmIntUnary;
|
||||
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.WasmReferencesEqual;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||
|
@ -232,7 +235,32 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
|
||||
@Override
|
||||
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
|
||||
|
|
|
@ -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.WasmConditional;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIsNull;
|
||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||
|
@ -50,8 +49,7 @@ public class ClassGenerators implements WasmGCCustomGenerator {
|
|||
function.add(thisVar);
|
||||
function.add(otherClassVar);
|
||||
|
||||
var conditional = new WasmConditional(new WasmReferencesEqual(new WasmGetLocal(otherClassVar),
|
||||
new WasmNullConstant(WasmType.Reference.STRUCT)));
|
||||
var conditional = new WasmConditional(new WasmIsNull(new WasmGetLocal(otherClassVar)));
|
||||
function.getBody().add(conditional);
|
||||
var npe = new WasmCall(context.functions().forStaticMethod(new MethodReference(WasmGCSupport.class, "npe",
|
||||
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
|
||||
public void visit(WasmBreak expression) {
|
||||
if (expression.getResult() != null) {
|
||||
|
@ -85,6 +101,11 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
|
|||
public void visit(WasmNullConstant expression) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmIsNull expression) {
|
||||
expression.getValue().acceptVisitor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmGetLocal expression) {
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ public interface WasmExpressionVisitor {
|
|||
|
||||
void visit(WasmBranch expression);
|
||||
|
||||
void visit(WasmNullBranch expression);
|
||||
|
||||
void visit(WasmCastBranch expression);
|
||||
|
||||
void visit(WasmBreak expression);
|
||||
|
||||
void visit(WasmSwitch expression);
|
||||
|
@ -40,6 +44,8 @@ public interface WasmExpressionVisitor {
|
|||
|
||||
void visit(WasmNullConstant expression);
|
||||
|
||||
void visit(WasmIsNull expression);
|
||||
|
||||
void visit(WasmGetLocal 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
|
||||
public void visit(WasmBreak expression) {
|
||||
if (expression.getResult() != null) {
|
||||
|
@ -109,6 +129,12 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
|
|||
public void visit(WasmNullConstant expression) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmIsNull expression) {
|
||||
expression.getValue().acceptVisitor(this);
|
||||
expression.setValue(mapper.apply(expression.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmGetLocal expression) {
|
||||
}
|
||||
|
|
|
@ -17,5 +17,7 @@ package org.teavm.backend.wasm.parser;
|
|||
|
||||
public enum BranchOpcode {
|
||||
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 castBranch(boolean success, int depth, int target, WasmHollowType.Reference sourceType,
|
||||
WasmHollowType.Reference targetType) {
|
||||
}
|
||||
|
||||
default void tableBranch(int[] depths, int[] targets, int defaultDepth, int defaultTarget) {
|
||||
}
|
||||
|
||||
|
|
|
@ -591,6 +591,9 @@ public class CodeParser extends BaseSectionParser {
|
|||
case 0xD0:
|
||||
codeListener.nullConstant(reader.readHeapType(true));
|
||||
break;
|
||||
case 0xD1:
|
||||
codeListener.opcode(Opcode.IS_NULL);
|
||||
break;
|
||||
|
||||
case 0xD2:
|
||||
codeListener.functionReference(readLEB());
|
||||
|
@ -600,6 +603,13 @@ public class CodeParser extends BaseSectionParser {
|
|||
codeListener.opcode(Opcode.REF_EQ);
|
||||
break;
|
||||
|
||||
case 0xD5:
|
||||
parseBranch(BranchOpcode.BR_ON_NULL);
|
||||
break;
|
||||
case 0xD6:
|
||||
parseBranch(BranchOpcode.BR_ON_NON_NULL);
|
||||
break;
|
||||
|
||||
case 0xFB:
|
||||
return parseExtExpr2();
|
||||
case 0xFC:
|
||||
|
@ -702,6 +712,13 @@ public class CodeParser extends BaseSectionParser {
|
|||
codeListener.cast(reader.readHeapType(true));
|
||||
return true;
|
||||
|
||||
case 24:
|
||||
parseCastBranch(true);
|
||||
return true;
|
||||
case 25:
|
||||
parseCastBranch(false);
|
||||
return true;
|
||||
|
||||
case 28:
|
||||
codeListener.int31Reference();
|
||||
return true;
|
||||
|
@ -798,6 +815,15 @@ public class CodeParser extends BaseSectionParser {
|
|||
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() {
|
||||
var count = readLEB();
|
||||
var depths = new int[count];
|
||||
|
|
|
@ -21,5 +21,6 @@ public enum Opcode {
|
|||
RETURN,
|
||||
DROP,
|
||||
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.WasmCallReference;
|
||||
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.WasmConversion;
|
||||
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.WasmIntBinary;
|
||||
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.WasmLoadFloat64;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||
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.WasmReferencesEqual;
|
||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||
|
@ -122,6 +125,18 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
|||
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
|
||||
public void visit(WasmBreak expression) {
|
||||
super.visit(expression);
|
||||
|
@ -186,6 +201,55 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
|||
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
|
||||
public void visit(WasmBreak expression) {
|
||||
pushLocation(expression);
|
||||
|
@ -304,6 +368,14 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
|||
popLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmIsNull expression) {
|
||||
pushLocation(expression);
|
||||
expression.getValue().acceptVisitor(this);
|
||||
writer.writeByte(0xD1);
|
||||
popLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmGetLocal 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.WasmCallReference;
|
||||
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.WasmConversion;
|
||||
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.WasmIntType;
|
||||
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.WasmLoadFloat64;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||
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.WasmReferencesEqual;
|
||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||
|
@ -187,6 +190,16 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
|||
value = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmNullBranch expression) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmCastBranch expression) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmBreak expression) {
|
||||
CExpression result = new CExpression();
|
||||
|
@ -359,6 +372,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
|||
value = CExpression.relocatable("/* can't produce ref.null */");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmIsNull expression) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmGetLocal expression) {
|
||||
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.WasmCallReference;
|
||||
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.WasmConversion;
|
||||
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.WasmIntUnary;
|
||||
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.WasmLoadFloat64;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||
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.WasmReferencesEqual;
|
||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||
|
@ -108,6 +111,18 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
|||
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
|
||||
public void visit(WasmBreak expression) {
|
||||
super.visit(expression);
|
||||
|
@ -219,6 +234,46 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
|||
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
|
||||
public void visit(WasmBreak expression) {
|
||||
String id = blockIdentifiers.get(expression.getTarget());
|
||||
|
@ -300,6 +355,11 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
|||
open().append("ref.null " + type(expression.getType())).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmIsNull expression) {
|
||||
open().append("ref.is_null").close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmGetLocal expression) {
|
||||
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.WasmCallReference;
|
||||
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.WasmConversion;
|
||||
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.WasmIntType;
|
||||
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.WasmLoadFloat64;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||
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.WasmReferencesEqual;
|
||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||
|
@ -88,7 +91,28 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
|||
|
||||
@Override
|
||||
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
|
||||
|
@ -186,6 +210,12 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
|||
result = expression.type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visit(WasmIsNull expression) {
|
||||
result = WasmType.INT32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WasmCall expression) {
|
||||
var function = expression.getFunction();
|
||||
|
|
Loading…
Reference in New Issue
Block a user