From 3ba2282473a4795d0f616414eedb71c18a90163b Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 30 Jun 2024 16:18:51 +0200 Subject: [PATCH] wasm: implement several instructions related to reference types These instructions will be presumably required for implementation of new Wasm GC BE. There's no tests for these changes, since there is no infrastructure to test anything like this. Instead, this code will be covered by tests for corresponding Wasm BE, when it's finally implemented. --- .../teavm/backend/wasm/WasmFunctionTypes.java | 2 +- .../teavm/backend/wasm/model/WasmArray.java | 6 +- .../backend/wasm/model/WasmCompositeType.java | 8 +- .../backend/wasm/model/WasmFunctionType.java | 6 +- .../backend/wasm/model/WasmStorageType.java | 12 ++ .../backend/wasm/model/WasmStructure.java | 6 +- .../wasm/model/expression/WasmArrayGet.java | 69 ++++++++++ .../model/expression/WasmArrayLength.java | 39 ++++++ .../model/expression/WasmArrayNewDefault.java | 50 +++++++ .../wasm/model/expression/WasmArraySet.java | 70 ++++++++++ .../wasm/model/expression/WasmCast.java | 50 +++++++ .../WasmDefaultExpressionVisitor.java | 52 +++++++ .../expression/WasmExpressionVisitor.java | 18 +++ .../model/expression/WasmReferencesEqual.java | 49 +++++++ .../WasmReplacingExpressionVisitor.java | 67 +++++++++ .../wasm/model/expression/WasmSignedType.java | 21 +++ .../wasm/model/expression/WasmStructGet.java | 69 ++++++++++ .../wasm/model/expression/WasmStructNew.java | 47 +++++++ .../wasm/model/expression/WasmStructSet.java | 70 ++++++++++ .../render/WasmBinaryRenderingVisitor.java | 128 ++++++++++++++++++ .../wasm/render/WasmCRenderingVisitor.java | 58 ++++++++ .../wasm/render/WasmRenderingVisitor.java | 118 +++++++++++++++- .../wasm/render/WasmTypeInference.java | 54 ++++++++ 23 files changed, 1060 insertions(+), 9 deletions(-) create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayGet.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayLength.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayNewDefault.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArraySet.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmCast.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmReferencesEqual.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmSignedType.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructGet.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructNew.java create mode 100644 core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructSet.java diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmFunctionTypes.java b/core/src/main/java/org/teavm/backend/wasm/WasmFunctionTypes.java index 02a5679aa..cf6a78d87 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmFunctionTypes.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmFunctionTypes.java @@ -32,7 +32,7 @@ public class WasmFunctionTypes { public WasmFunctionType get(WasmSignature signature) { return types.computeIfAbsent(signature, k -> { - var type = new WasmFunctionType(signature.getReturnType(), signature.getParameterTypes()); + var type = new WasmFunctionType(null, signature.getReturnType(), signature.getParameterTypes()); module.types.add(type); return type; }); diff --git a/core/src/main/java/org/teavm/backend/wasm/model/WasmArray.java b/core/src/main/java/org/teavm/backend/wasm/model/WasmArray.java index ea1efa9a8..746706c51 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/WasmArray.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/WasmArray.java @@ -22,11 +22,13 @@ public class WasmArray extends WasmCompositeType { private WasmStorageType elementType; private Supplier elementTypeSupplier; - public WasmArray(WasmStorageType elementType) { + public WasmArray(String name, WasmStorageType elementType) { + super(name); this.elementType = Objects.requireNonNull(elementType); } - public WasmArray(Supplier elementTypeSupplier) { + public WasmArray(String name, Supplier elementTypeSupplier) { + super(name); this.elementTypeSupplier = elementTypeSupplier; } diff --git a/core/src/main/java/org/teavm/backend/wasm/model/WasmCompositeType.java b/core/src/main/java/org/teavm/backend/wasm/model/WasmCompositeType.java index eb89b878f..e0da99d22 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/WasmCompositeType.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/WasmCompositeType.java @@ -16,9 +16,15 @@ package org.teavm.backend.wasm.model; public abstract class WasmCompositeType extends WasmEntity { + private String name; private WasmType.Reference reference; - WasmCompositeType() { + WasmCompositeType(String name) { + this.name = name; + } + + public String getName() { + return name; } public WasmType.Reference getReference() { diff --git a/core/src/main/java/org/teavm/backend/wasm/model/WasmFunctionType.java b/core/src/main/java/org/teavm/backend/wasm/model/WasmFunctionType.java index 901d210a0..3e4dcd437 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/WasmFunctionType.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/WasmFunctionType.java @@ -24,13 +24,15 @@ public class WasmFunctionType extends WasmCompositeType { private Supplier> parameterTypesSupplier; private Supplier returnTypeSupplier; - public WasmFunctionType(WasmType returnType, List parameterTypes) { + public WasmFunctionType(String name, WasmType returnType, List parameterTypes) { + super(name); this.returnType = returnType; this.parameterTypes = parameterTypes; } - public WasmFunctionType(Supplier returnTypeSupplier, + public WasmFunctionType(String name, Supplier returnTypeSupplier, Supplier> parameterTypesSupplier) { + super(name); this.returnTypeSupplier = returnTypeSupplier; this.parameterTypesSupplier = parameterTypesSupplier; } diff --git a/core/src/main/java/org/teavm/backend/wasm/model/WasmStorageType.java b/core/src/main/java/org/teavm/backend/wasm/model/WasmStorageType.java index 00ad7d9ee..523b6de65 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/WasmStorageType.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/WasmStorageType.java @@ -22,6 +22,8 @@ public abstract class WasmStorageType { private WasmStorageType() { } + public abstract WasmType asUnpackedType(); + public static WasmStorageType.Packed packed(WasmPackedType type) { switch (type) { case INT8: @@ -39,6 +41,11 @@ public abstract class WasmStorageType { Regular(WasmType type) { this.type = type; } + + @Override + public WasmType asUnpackedType() { + return type; + } } public static final class Packed extends WasmStorageType { @@ -47,5 +54,10 @@ public abstract class WasmStorageType { private Packed(WasmPackedType type) { this.type = type; } + + @Override + public WasmType asUnpackedType() { + return WasmType.INT32; + } } } diff --git a/core/src/main/java/org/teavm/backend/wasm/model/WasmStructure.java b/core/src/main/java/org/teavm/backend/wasm/model/WasmStructure.java index 645bba70a..282c0ad8e 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/WasmStructure.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/WasmStructure.java @@ -22,11 +22,13 @@ public class WasmStructure extends WasmCompositeType { private List fields; private Supplier> fieldsSupplier; - public WasmStructure(List fields) { + public WasmStructure(String name, List fields) { + super(name); this.fields = List.copyOf(fields); } - public WasmStructure(Supplier> fieldsSupplier) { + public WasmStructure(String name, Supplier> fieldsSupplier) { + super(name); this.fieldsSupplier = fieldsSupplier; } diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayGet.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayGet.java new file mode 100644 index 000000000..b1d7bd348 --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayGet.java @@ -0,0 +1,69 @@ +/* + * 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.WasmArray; + +public class WasmArrayGet extends WasmExpression { + private WasmArray type; + private WasmExpression instance; + private WasmSignedType signedType; + private WasmExpression index; + + public WasmArrayGet(WasmArray type, WasmExpression instance, WasmExpression index) { + this.type = Objects.requireNonNull(type); + this.instance = Objects.requireNonNull(instance); + this.index = Objects.requireNonNull(index); + } + + public WasmArray getType() { + return type; + } + + public void setType(WasmArray type) { + this.type = Objects.requireNonNull(type); + } + + public WasmExpression getInstance() { + return instance; + } + + public void setInstance(WasmExpression instance) { + this.instance = instance; + } + + public WasmSignedType getSignedType() { + return signedType; + } + + public void setSignedType(WasmSignedType signedType) { + this.signedType = signedType; + } + + public WasmExpression getIndex() { + return index; + } + + public void setIndex(WasmExpression index) { + this.index = Objects.requireNonNull(index); + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayLength.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayLength.java new file mode 100644 index 000000000..db25b1456 --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayLength.java @@ -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 WasmArrayLength extends WasmExpression { + private WasmExpression instance; + + public WasmArrayLength(WasmExpression instance) { + this.instance = Objects.requireNonNull(instance); + } + + public WasmExpression getInstance() { + return instance; + } + + public void setInstance(WasmExpression instance) { + this.instance = Objects.requireNonNull(instance); + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayNewDefault.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayNewDefault.java new file mode 100644 index 000000000..149884997 --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayNewDefault.java @@ -0,0 +1,50 @@ +/* + * 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.WasmArray; + +public class WasmArrayNewDefault extends WasmExpression { + private WasmArray type; + private WasmExpression length; + + public WasmArrayNewDefault(WasmArray type, WasmExpression length) { + this.type = Objects.requireNonNull(type); + this.length = Objects.requireNonNull(length); + } + + public WasmArray getType() { + return type; + } + + public void setType(WasmArray type) { + this.type = Objects.requireNonNull(type); + } + + public WasmExpression getLength() { + return length; + } + + public void setLength(WasmExpression length) { + this.length = Objects.requireNonNull(length); + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArraySet.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArraySet.java new file mode 100644 index 000000000..8e8d994ea --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArraySet.java @@ -0,0 +1,70 @@ +/* + * 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.WasmArray; + +public class WasmArraySet extends WasmExpression { + private WasmArray type; + private WasmExpression instance; + private WasmExpression index; + private WasmExpression value; + + public WasmArraySet(WasmArray type, WasmExpression instance, WasmExpression index, WasmExpression value) { + this.type = Objects.requireNonNull(type); + this.instance = Objects.requireNonNull(instance); + this.index = Objects.requireNonNull(index); + this.value = Objects.requireNonNull(value); + } + + public WasmArray getType() { + return type; + } + + public void setType(WasmArray type) { + this.type = type; + } + + public WasmExpression getInstance() { + return instance; + } + + public void setInstance(WasmExpression instance) { + this.instance = instance; + } + + public WasmExpression getIndex() { + return index; + } + + public void setIndex(WasmExpression index) { + this.index = index; + } + + public WasmExpression getValue() { + return value; + } + + public void setValue(WasmExpression value) { + this.value = value; + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmCast.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmCast.java new file mode 100644 index 000000000..cdc8cc684 --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmCast.java @@ -0,0 +1,50 @@ +/* + * 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 WasmCast extends WasmExpression { + private WasmExpression value; + private WasmType.Reference targetType; + + public WasmCast(WasmExpression value, WasmType.Reference targetType) { + this.value = Objects.requireNonNull(value); + this.targetType = Objects.requireNonNull(targetType); + } + + public WasmExpression getValue() { + return value; + } + + public void setValue(WasmExpression value) { + this.value = Objects.requireNonNull(value); + } + + public WasmType.Reference getTargetType() { + return targetType; + } + + public void setTargetType(WasmType.Reference targetType) { + this.targetType = Objects.requireNonNull(targetType); + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmDefaultExpressionVisitor.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmDefaultExpressionVisitor.java index 1ac0c0933..2a94f9ef2 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmDefaultExpressionVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmDefaultExpressionVisitor.java @@ -222,4 +222,56 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor { arg.acceptVisitor(this); } } + + @Override + public void visit(WasmReferencesEqual expression) { + expression.getFirst().acceptVisitor(this); + expression.getSecond().acceptVisitor(this); + } + + @Override + public void visit(WasmCast expression) { + expression.getValue().acceptVisitor(this); + } + + @Override + public void visit(WasmStructNew expression) { + for (var initializer : expression.getInitializers()) { + initializer.acceptVisitor(this); + } + } + + @Override + public void visit(WasmStructGet expression) { + expression.getInstance().acceptVisitor(this); + } + + @Override + public void visit(WasmStructSet expression) { + expression.getInstance().acceptVisitor(this); + expression.getValue().acceptVisitor(this); + } + + @Override + public void visit(WasmArrayNewDefault expression) { + expression.getLength().acceptVisitor(this); + } + + @Override + public void visit(WasmArrayGet expression) { + expression.getInstance().acceptVisitor(this); + expression.getIndex().acceptVisitor(this); + } + + @Override + public void visit(WasmArraySet expression) { + expression.getInstance().acceptVisitor(this); + expression.getIndex().acceptVisitor(this); + expression.getValue().acceptVisitor(this); + } + + @Override + public void visit(WasmArrayLength expression) { + expression.getInstance().acceptVisitor(this); + } } diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmExpressionVisitor.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmExpressionVisitor.java index 0fbc0fc7c..918f790c5 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmExpressionVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmExpressionVisitor.java @@ -85,4 +85,22 @@ public interface WasmExpressionVisitor { void visit(WasmTry expression); void visit(WasmThrow expression); + + void visit(WasmReferencesEqual expression); + + void visit(WasmCast expression); + + void visit(WasmStructNew expression); + + void visit(WasmStructGet expression); + + void visit(WasmStructSet expression); + + void visit(WasmArrayNewDefault expression); + + void visit(WasmArrayGet expression); + + void visit(WasmArraySet expression); + + void visit(WasmArrayLength expression); } diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmReferencesEqual.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmReferencesEqual.java new file mode 100644 index 000000000..94535572e --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmReferencesEqual.java @@ -0,0 +1,49 @@ +/* + * 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 WasmReferencesEqual extends WasmExpression { + private WasmExpression first; + private WasmExpression second; + + public WasmReferencesEqual(WasmExpression first, WasmExpression second) { + this.first = Objects.requireNonNull(first); + this.second = Objects.requireNonNull(second); + } + + public WasmExpression getFirst() { + return first; + } + + public void setFirst(WasmExpression first) { + this.first = Objects.requireNonNull(first); + } + + public WasmExpression getSecond() { + return second; + } + + public void setSecond(WasmExpression second) { + this.second = Objects.requireNonNull(second); + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmReplacingExpressionVisitor.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmReplacingExpressionVisitor.java index 60b4e4b0a..a502888ed 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmReplacingExpressionVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmReplacingExpressionVisitor.java @@ -268,4 +268,71 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor { public void visit(WasmThrow expression) { replaceExpressions(expression.getArguments()); } + + @Override + public void visit(WasmReferencesEqual expression) { + expression.getFirst().acceptVisitor(this); + expression.setFirst(mapper.apply(expression.getFirst())); + + expression.getSecond().acceptVisitor(this); + expression.setSecond(mapper.apply(expression.getSecond())); + } + + @Override + public void visit(WasmCast expression) { + expression.getValue().acceptVisitor(this); + expression.setValue(mapper.apply(expression.getValue())); + } + + @Override + public void visit(WasmStructNew expression) { + } + + @Override + public void visit(WasmStructGet expression) { + expression.getInstance().acceptVisitor(this); + expression.setInstance(mapper.apply(expression.getInstance())); + } + + @Override + public void visit(WasmStructSet expression) { + expression.getInstance().acceptVisitor(this); + expression.setInstance(mapper.apply(expression.getInstance())); + + expression.getValue().acceptVisitor(this); + expression.setValue(mapper.apply(expression.getValue())); + } + + @Override + public void visit(WasmArrayNewDefault expression) { + expression.getLength().acceptVisitor(this); + expression.setLength(mapper.apply(expression.getLength())); + } + + @Override + public void visit(WasmArrayGet expression) { + expression.getInstance().acceptVisitor(this); + expression.setInstance(mapper.apply(expression.getInstance())); + + expression.getIndex().acceptVisitor(this); + expression.setIndex(mapper.apply(expression.getIndex())); + } + + @Override + public void visit(WasmArraySet expression) { + expression.getInstance().acceptVisitor(this); + expression.setInstance(mapper.apply(expression.getInstance())); + + expression.getIndex().acceptVisitor(this); + expression.setIndex(mapper.apply(expression.getIndex())); + + expression.getValue().acceptVisitor(this); + expression.setValue(mapper.apply(expression.getIndex())); + } + + @Override + public void visit(WasmArrayLength expression) { + expression.getInstance().acceptVisitor(this); + expression.setInstance(mapper.apply(expression.getInstance())); + } } diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmSignedType.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmSignedType.java new file mode 100644 index 000000000..f40d64843 --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmSignedType.java @@ -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 WasmSignedType { + SIGNED, + UNSIGNED +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructGet.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructGet.java new file mode 100644 index 000000000..4440ca7d6 --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructGet.java @@ -0,0 +1,69 @@ +/* + * 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.WasmStructure; + +public class WasmStructGet extends WasmExpression { + private WasmStructure type; + private WasmExpression instance; + private int fieldIndex; + private WasmSignedType signedType; + + public WasmStructGet(WasmStructure type, WasmExpression instance, int fieldIndex) { + this.type = Objects.requireNonNull(type); + this.instance = Objects.requireNonNull(instance); + this.fieldIndex = fieldIndex; + } + + public WasmStructure getType() { + return type; + } + + public void setType(WasmStructure type) { + this.type = Objects.requireNonNull(type); + } + + public WasmExpression getInstance() { + return instance; + } + + public void setInstance(WasmExpression instance) { + this.instance = Objects.requireNonNull(instance); + } + + public int getFieldIndex() { + return fieldIndex; + } + + public void setFieldIndex(int fieldIndex) { + this.fieldIndex = fieldIndex; + } + + public WasmSignedType getSignedType() { + return signedType; + } + + public void setSignedType(WasmSignedType signedType) { + this.signedType = signedType; + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructNew.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructNew.java new file mode 100644 index 000000000..1ea922401 --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructNew.java @@ -0,0 +1,47 @@ +/* + * 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.ArrayList; +import java.util.List; +import java.util.Objects; +import org.teavm.backend.wasm.model.WasmStructure; + +public class WasmStructNew extends WasmExpression { + private WasmStructure type; + private List initializers = new ArrayList<>(); + + public WasmStructNew(WasmStructure type) { + this.type = Objects.requireNonNull(type); + } + + public WasmStructure getType() { + return type; + } + + public void setType(WasmStructure type) { + this.type = Objects.requireNonNull(type); + } + + public List getInitializers() { + return initializers; + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructSet.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructSet.java new file mode 100644 index 000000000..c3ad5b180 --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmStructSet.java @@ -0,0 +1,70 @@ +/* + * 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.WasmStructure; + +public class WasmStructSet extends WasmExpression { + private WasmStructure type; + private WasmExpression instance; + private int fieldIndex; + private WasmExpression value; + + public WasmStructSet(WasmStructure type, WasmExpression instance, int fieldIndex, WasmExpression value) { + this.type = Objects.requireNonNull(type); + this.instance = Objects.requireNonNull(instance); + this.fieldIndex = fieldIndex; + this.value = Objects.requireNonNull(value); + } + + public WasmStructure getType() { + return type; + } + + public void setType(WasmStructure type) { + this.type = Objects.requireNonNull(type); + } + + public WasmExpression getInstance() { + return instance; + } + + public void setInstance(WasmExpression instance) { + this.instance = Objects.requireNonNull(instance); + } + + public int getFieldIndex() { + return fieldIndex; + } + + public void setFieldIndex(int fieldIndex) { + this.fieldIndex = fieldIndex; + } + + public WasmExpression getValue() { + return value; + } + + public void setValue(WasmExpression value) { + this.value = Objects.requireNonNull(value); + } + + @Override + public void acceptVisitor(WasmExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java index 14165a652..a0fc77901 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java @@ -25,10 +25,15 @@ import org.teavm.backend.wasm.debug.DebugLines; import org.teavm.backend.wasm.generate.DwarfGenerator; import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmType; +import org.teavm.backend.wasm.model.expression.WasmArrayGet; +import org.teavm.backend.wasm.model.expression.WasmArrayLength; +import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault; +import org.teavm.backend.wasm.model.expression.WasmArraySet; import org.teavm.backend.wasm.model.expression.WasmBlock; import org.teavm.backend.wasm.model.expression.WasmBranch; import org.teavm.backend.wasm.model.expression.WasmBreak; import org.teavm.backend.wasm.model.expression.WasmCall; +import org.teavm.backend.wasm.model.expression.WasmCast; import org.teavm.backend.wasm.model.expression.WasmConditional; import org.teavm.backend.wasm.model.expression.WasmConversion; import org.teavm.backend.wasm.model.expression.WasmCopy; @@ -52,12 +57,16 @@ 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.WasmNullConstant; +import org.teavm.backend.wasm.model.expression.WasmReferencesEqual; import org.teavm.backend.wasm.model.expression.WasmReturn; import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmStoreFloat32; import org.teavm.backend.wasm.model.expression.WasmStoreFloat64; import org.teavm.backend.wasm.model.expression.WasmStoreInt32; import org.teavm.backend.wasm.model.expression.WasmStoreInt64; +import org.teavm.backend.wasm.model.expression.WasmStructGet; +import org.teavm.backend.wasm.model.expression.WasmStructNew; +import org.teavm.backend.wasm.model.expression.WasmStructSet; import org.teavm.backend.wasm.model.expression.WasmSwitch; import org.teavm.backend.wasm.model.expression.WasmThrow; import org.teavm.backend.wasm.model.expression.WasmTry; @@ -969,6 +978,125 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { pushLocation(expression); writer.writeByte(0x8); writer.writeLEB(expression.getTag().getIndex()); + popLocation(); + } + + @Override + public void visit(WasmReferencesEqual expression) { + pushLocation(expression); + expression.getFirst().acceptVisitor(this); + expression.getSecond().acceptVisitor(this); + writer.writeByte(0xd3); + popLocation(); + } + + @Override + public void visit(WasmCast expression) { + pushLocation(expression); + expression.getValue().acceptVisitor(this); + writer.writeByte(0xfb); + writer.writeByte(23); + writer.writeType(expression.getTargetType(), module); + popLocation(); + } + + @Override + public void visit(WasmStructNew expression) { + pushLocation(expression); + for (var initializer : expression.getInitializers()) { + initializer.acceptVisitor(this); + } + writer.writeByte(0xfb); + writer.writeByte(0); + writer.writeInt32(module.types.indexOf(expression.getType())); + popLocation(); + } + + @Override + public void visit(WasmStructGet expression) { + pushLocation(expression); + expression.getInstance().acceptVisitor(this); + writer.writeByte(0xfb); + if (expression.getSignedType() == null) { + writer.writeByte(2); + } else { + switch (expression.getSignedType()) { + case SIGNED: + writer.writeByte(3); + break; + case UNSIGNED: + writer.writeByte(4); + break; + } + } + writer.writeInt32(module.types.indexOf(expression.getType())); + writer.writeInt32(expression.getFieldIndex()); + popLocation(); + } + + @Override + public void visit(WasmStructSet expression) { + pushLocation(expression); + expression.getInstance().acceptVisitor(this); + expression.getValue().acceptVisitor(this); + writer.writeByte(0xfb); + writer.writeByte(5); + writer.writeInt32(module.types.indexOf(expression.getType())); + writer.writeInt32(expression.getFieldIndex()); + popLocation(); + } + + @Override + public void visit(WasmArrayNewDefault expression) { + pushLocation(expression); + expression.getLength().acceptVisitor(this); + writer.writeByte(0xfb); + writer.writeByte(7); + writer.writeInt32(module.types.indexOf(expression.getType())); + popLocation(); + } + + @Override + public void visit(WasmArrayGet expression) { + pushLocation(expression); + expression.getInstance().acceptVisitor(this); + expression.getIndex().acceptVisitor(this); + writer.writeByte(0xfb); + if (expression.getSignedType() == null) { + writer.writeByte(11); + } else { + switch (expression.getSignedType()) { + case SIGNED: + writer.writeByte(12); + break; + case UNSIGNED: + writer.writeByte(13); + break; + } + } + writer.writeInt32(module.types.indexOf(expression.getType())); + popLocation(); + } + + @Override + public void visit(WasmArraySet expression) { + pushLocation(expression); + expression.getInstance().acceptVisitor(this); + expression.getIndex().acceptVisitor(this); + expression.getValue().acceptVisitor(this); + writer.writeByte(0xfb); + writer.writeByte(14); + writer.writeInt32(module.types.indexOf(expression.getType())); + popLocation(); + } + + @Override + public void visit(WasmArrayLength expression) { + pushLocation(expression); + expression.getInstance().acceptVisitor(this); + writer.writeByte(0xfb); + writer.writeByte(15); + popLocation(); } private int alignment(int value) { diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java index 943520d7d..93232c5f1 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java @@ -26,10 +26,15 @@ import org.teavm.backend.wasm.model.WasmLocal; import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmNumType; import org.teavm.backend.wasm.model.WasmType; +import org.teavm.backend.wasm.model.expression.WasmArrayGet; +import org.teavm.backend.wasm.model.expression.WasmArrayLength; +import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault; +import org.teavm.backend.wasm.model.expression.WasmArraySet; import org.teavm.backend.wasm.model.expression.WasmBlock; import org.teavm.backend.wasm.model.expression.WasmBranch; import org.teavm.backend.wasm.model.expression.WasmBreak; import org.teavm.backend.wasm.model.expression.WasmCall; +import org.teavm.backend.wasm.model.expression.WasmCast; import org.teavm.backend.wasm.model.expression.WasmConditional; import org.teavm.backend.wasm.model.expression.WasmConversion; import org.teavm.backend.wasm.model.expression.WasmCopy; @@ -55,12 +60,16 @@ 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.WasmNullConstant; +import org.teavm.backend.wasm.model.expression.WasmReferencesEqual; import org.teavm.backend.wasm.model.expression.WasmReturn; import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmStoreFloat32; import org.teavm.backend.wasm.model.expression.WasmStoreFloat64; import org.teavm.backend.wasm.model.expression.WasmStoreInt32; import org.teavm.backend.wasm.model.expression.WasmStoreInt64; +import org.teavm.backend.wasm.model.expression.WasmStructGet; +import org.teavm.backend.wasm.model.expression.WasmStructNew; +import org.teavm.backend.wasm.model.expression.WasmStructSet; import org.teavm.backend.wasm.model.expression.WasmSwitch; import org.teavm.backend.wasm.model.expression.WasmThrow; import org.teavm.backend.wasm.model.expression.WasmTry; @@ -1121,6 +1130,55 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor { value = new CExpression("/* THROW */"); } + @Override + public void visit(WasmReferencesEqual expression) { + unsupported(); + } + + @Override + public void visit(WasmCast expression) { + unsupported(); + } + + @Override + public void visit(WasmStructNew expression) { + unsupported(); + } + + @Override + public void visit(WasmStructGet expression) { + unsupported(); + } + + @Override + public void visit(WasmStructSet expression) { + unsupported(); + } + + @Override + public void visit(WasmArrayNewDefault expression) { + unsupported(); + } + + @Override + public void visit(WasmArrayGet expression) { + unsupported(); + } + + @Override + public void visit(WasmArraySet expression) { + unsupported(); + } + + @Override + public void visit(WasmArrayLength expression) { + unsupported(); + } + + private void unsupported() { + value = new CExpression("/* unsupported */"); + } + private CExpression checkAddress(CExpression index) { if (!memoryAccessChecked) { return index; diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmRenderingVisitor.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmRenderingVisitor.java index ecf7a8138..9a0879fa4 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmRenderingVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmRenderingVisitor.java @@ -17,14 +17,20 @@ package org.teavm.backend.wasm.render; import java.util.HashMap; import java.util.Map; +import org.teavm.backend.wasm.model.WasmCompositeType; import org.teavm.backend.wasm.model.WasmLocal; import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmNumType; import org.teavm.backend.wasm.model.WasmType; +import org.teavm.backend.wasm.model.expression.WasmArrayGet; +import org.teavm.backend.wasm.model.expression.WasmArrayLength; +import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault; +import org.teavm.backend.wasm.model.expression.WasmArraySet; import org.teavm.backend.wasm.model.expression.WasmBlock; import org.teavm.backend.wasm.model.expression.WasmBranch; import org.teavm.backend.wasm.model.expression.WasmBreak; import org.teavm.backend.wasm.model.expression.WasmCall; +import org.teavm.backend.wasm.model.expression.WasmCast; import org.teavm.backend.wasm.model.expression.WasmConditional; import org.teavm.backend.wasm.model.expression.WasmConversion; import org.teavm.backend.wasm.model.expression.WasmCopy; @@ -55,12 +61,16 @@ 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.WasmNullConstant; +import org.teavm.backend.wasm.model.expression.WasmReferencesEqual; import org.teavm.backend.wasm.model.expression.WasmReturn; import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmStoreFloat32; import org.teavm.backend.wasm.model.expression.WasmStoreFloat64; import org.teavm.backend.wasm.model.expression.WasmStoreInt32; import org.teavm.backend.wasm.model.expression.WasmStoreInt64; +import org.teavm.backend.wasm.model.expression.WasmStructGet; +import org.teavm.backend.wasm.model.expression.WasmStructNew; +import org.teavm.backend.wasm.model.expression.WasmStructSet; import org.teavm.backend.wasm.model.expression.WasmSwitch; import org.teavm.backend.wasm.model.expression.WasmThrow; import org.teavm.backend.wasm.model.expression.WasmTry; @@ -644,16 +654,122 @@ class WasmRenderingVisitor implements WasmExpressionVisitor { close(); } + @Override + public void visit(WasmReferencesEqual expression) { + open().append("ref.eq "); + line(expression.getFirst()); + line(expression.getSecond()); + close(); + } + + @Override + public void visit(WasmCast expression) { + open().append("ref.cast ").append(type(expression.getTargetType())); + line(expression.getValue()); + close(); + } + + @Override + public void visit(WasmStructNew expression) { + open().append("struct.new "); + append(expression.getType().getReference()); + for (var initializer : expression.getInitializers()) { + line(initializer); + } + close(); + } + + @Override + public void visit(WasmStructGet expression) { + open(); + if (expression.getSignedType() == null) { + append("struct.get"); + } else { + switch (expression.getSignedType()) { + case SIGNED: + append("struct.get_s"); + break; + case UNSIGNED: + append("struct.get_u"); + break; + } + } + append(" ").append(typeName(expression.getType())); + append(" ").append(String.valueOf(expression.getFieldIndex())); + line(expression.getInstance()); + close(); + } + + @Override + public void visit(WasmStructSet expression) { + open().append("struct.set"); + append(" ").append(typeName(expression.getType())); + append(" ").append(String.valueOf(expression.getFieldIndex())); + line(expression.getInstance()); + line(expression.getValue()); + close(); + } + + @Override + public void visit(WasmArrayNewDefault expression) { + open().append("array.new_default"); + append(" ").append(typeName(expression.getType())); + line(expression.getLength()); + close(); + } + + @Override + public void visit(WasmArrayGet expression) { + open(); + if (expression.getSignedType() == null) { + append("array.get"); + } else { + switch (expression.getSignedType()) { + case SIGNED: + append("array.get_s"); + break; + case UNSIGNED: + append("array.get_u"); + break; + } + } + append(" ").append(typeName(expression.getType())); + line(expression.getInstance()); + line(expression.getIndex()); + close(); + } + + @Override + public void visit(WasmArraySet expression) { + open().append("array.set"); + append(" ").append(typeName(expression.getType())); + line(expression.getInstance()); + line(expression.getIndex()); + line(expression.getValue()); + close(); + } + + @Override + public void visit(WasmArrayLength expression) { + open().append("array.length"); + line(expression.getInstance()); + close(); + } + private String type(WasmType type) { if (type instanceof WasmType.Number) { return type(((WasmType.Number) type).number); } else if (type instanceof WasmType.Reference) { - return "(ref " + module.types.indexOf(((WasmType.Reference) type).composite) + ")"; + return "(ref " + typeName(((WasmType.Reference) type).composite) + ")"; } else { throw new IllegalArgumentException(); } } + private String typeName(WasmCompositeType type) { + return type.getName() != null ? "$" + type.getName() : String.valueOf(module.types.indexOf(type)); + } + private String type(WasmNumType type) { switch (type) { case INT32: diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmTypeInference.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmTypeInference.java index d4e04b6e5..908fae512 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmTypeInference.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmTypeInference.java @@ -16,10 +16,15 @@ package org.teavm.backend.wasm.render; import org.teavm.backend.wasm.model.WasmType; +import org.teavm.backend.wasm.model.expression.WasmArrayGet; +import org.teavm.backend.wasm.model.expression.WasmArrayLength; +import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault; +import org.teavm.backend.wasm.model.expression.WasmArraySet; import org.teavm.backend.wasm.model.expression.WasmBlock; import org.teavm.backend.wasm.model.expression.WasmBranch; import org.teavm.backend.wasm.model.expression.WasmBreak; import org.teavm.backend.wasm.model.expression.WasmCall; +import org.teavm.backend.wasm.model.expression.WasmCast; import org.teavm.backend.wasm.model.expression.WasmConditional; import org.teavm.backend.wasm.model.expression.WasmConversion; import org.teavm.backend.wasm.model.expression.WasmCopy; @@ -44,12 +49,16 @@ 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.WasmNullConstant; +import org.teavm.backend.wasm.model.expression.WasmReferencesEqual; import org.teavm.backend.wasm.model.expression.WasmReturn; import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmStoreFloat32; import org.teavm.backend.wasm.model.expression.WasmStoreFloat64; import org.teavm.backend.wasm.model.expression.WasmStoreInt32; import org.teavm.backend.wasm.model.expression.WasmStoreInt64; +import org.teavm.backend.wasm.model.expression.WasmStructGet; +import org.teavm.backend.wasm.model.expression.WasmStructNew; +import org.teavm.backend.wasm.model.expression.WasmStructSet; import org.teavm.backend.wasm.model.expression.WasmSwitch; import org.teavm.backend.wasm.model.expression.WasmThrow; import org.teavm.backend.wasm.model.expression.WasmTry; @@ -238,6 +247,51 @@ public class WasmTypeInference implements WasmExpressionVisitor { result = null; } + @Override + public void visit(WasmReferencesEqual expression) { + result = WasmType.INT32; + } + + @Override + public void visit(WasmCast expression) { + result = expression.getTargetType(); + } + + @Override + public void visit(WasmStructNew expression) { + result = expression.getType().getReference(); + } + + @Override + public void visit(WasmStructGet expression) { + result = expression.getType().getFields().get(expression.getFieldIndex()).asUnpackedType(); + } + + @Override + public void visit(WasmStructSet expression) { + result = null; + } + + @Override + public void visit(WasmArrayNewDefault expression) { + result = expression.getType().getReference(); + } + + @Override + public void visit(WasmArrayGet expression) { + result = expression.getType().getElementType().asUnpackedType(); + } + + @Override + public void visit(WasmArraySet expression) { + result = null; + } + + @Override + public void visit(WasmArrayLength expression) { + result = WasmType.INT32; + } + private static WasmType map(WasmIntType type) { switch (type) { case INT32: