diff --git a/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayCopy.java b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayCopy.java new file mode 100644 index 000000000..297a3c93b --- /dev/null +++ b/core/src/main/java/org/teavm/backend/wasm/model/expression/WasmArrayCopy.java @@ -0,0 +1,103 @@ +/* + * 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 org.teavm.backend.wasm.model.WasmArray; + +public class WasmArrayCopy extends WasmExpression { + private WasmArray targetArrayType; + private WasmExpression targetArray; + private WasmExpression targetIndex; + private WasmArray sourceArrayType; + private WasmExpression sourceArray; + private WasmExpression sourceIndex; + private WasmExpression size; + + public WasmArrayCopy( + WasmArray targetArrayType, WasmExpression targetArray, WasmExpression targetIndex, + WasmArray sourceArrayType, WasmExpression sourceArray, WasmExpression sourceIndex, + WasmExpression size + ) { + this.targetArrayType = targetArrayType; + this.targetArray = targetArray; + this.targetIndex = targetIndex; + this.sourceArrayType = sourceArrayType; + this.sourceArray = sourceArray; + this.sourceIndex = sourceIndex; + this.size = size; + } + + public WasmArray getTargetArrayType() { + return targetArrayType; + } + + public void setTargetArrayType(WasmArray targetArrayType) { + this.targetArrayType = targetArrayType; + } + + public WasmExpression getTargetArray() { + return targetArray; + } + + public void setTargetArray(WasmExpression targetArray) { + this.targetArray = targetArray; + } + + public WasmExpression getTargetIndex() { + return targetIndex; + } + + public void setTargetIndex(WasmExpression targetIndex) { + this.targetIndex = targetIndex; + } + + public WasmArray getSourceArrayType() { + return sourceArrayType; + } + + public void setSourceArrayType(WasmArray sourceArrayType) { + this.sourceArrayType = sourceArrayType; + } + + public WasmExpression getSourceArray() { + return sourceArray; + } + + public void setSourceArray(WasmExpression sourceArray) { + this.sourceArray = sourceArray; + } + + public WasmExpression getSourceIndex() { + return sourceIndex; + } + + public void setSourceIndex(WasmExpression sourceIndex) { + this.sourceIndex = sourceIndex; + } + + public WasmExpression getSize() { + return size; + } + + public void setSize(WasmExpression size) { + this.size = size; + } + + @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 4585d2307..ba53b7e34 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 @@ -296,6 +296,15 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor { expression.getInstance().acceptVisitor(this); } + @Override + public void visit(WasmArrayCopy expression) { + expression.getTargetArray().acceptVisitor(this); + expression.getTargetIndex().acceptVisitor(this); + expression.getSourceArray().acceptVisitor(this); + expression.getSourceIndex().acceptVisitor(this); + expression.getSize().acceptVisitor(this); + } + @Override public void visit(WasmFunctionReference expression) { } 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 cc6ec3089..09751950f 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 @@ -112,5 +112,7 @@ public interface WasmExpressionVisitor { void visit(WasmArrayLength expression); + void visit(WasmArrayCopy expression); + void visit(WasmFunctionReference expression); } 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 23357ffab..21a709244 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 @@ -357,6 +357,24 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor { expression.setInstance(mapper.apply(expression.getInstance())); } + @Override + public void visit(WasmArrayCopy expression) { + expression.getSourceArray().acceptVisitor(this); + expression.setSourceArray(mapper.apply(expression.getSourceArray())); + + expression.getSourceIndex().acceptVisitor(this); + expression.setSourceIndex(mapper.apply(expression.getSourceIndex())); + + expression.getTargetArray().acceptVisitor(this); + expression.setTargetArray(mapper.apply(expression.getTargetArray())); + + expression.getTargetIndex().acceptVisitor(this); + expression.setTargetIndex(mapper.apply(expression.getTargetIndex())); + + expression.getSize().acceptVisitor(this); + expression.setSize(mapper.apply(expression.getSize())); + } + @Override public void visit(WasmFunctionReference expression) { } diff --git a/core/src/main/java/org/teavm/backend/wasm/optimization/UnusedTypeElimination.java b/core/src/main/java/org/teavm/backend/wasm/optimization/UnusedTypeElimination.java index 3c58ca51d..e7fd4125a 100644 --- a/core/src/main/java/org/teavm/backend/wasm/optimization/UnusedTypeElimination.java +++ b/core/src/main/java/org/teavm/backend/wasm/optimization/UnusedTypeElimination.java @@ -27,6 +27,7 @@ import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmStorageType; import org.teavm.backend.wasm.model.WasmStructure; import org.teavm.backend.wasm.model.WasmType; +import org.teavm.backend.wasm.model.expression.WasmArrayCopy; import org.teavm.backend.wasm.model.expression.WasmArrayGet; import org.teavm.backend.wasm.model.expression.WasmArraySet; import org.teavm.backend.wasm.model.expression.WasmCallReference; @@ -156,6 +157,13 @@ public class UnusedTypeElimination { super.visit(expression); use(expression.getType()); } + + @Override + public void visit(WasmArrayCopy expression) { + super.visit(expression); + use(expression.getSourceArrayType()); + use(expression.getTargetArrayType()); + } }; private WasmCompositeTypeVisitor typeVisitor = new WasmDefaultCompositeTypeVisitor() { diff --git a/core/src/main/java/org/teavm/backend/wasm/parser/CodeListener.java b/core/src/main/java/org/teavm/backend/wasm/parser/CodeListener.java index 2afe61efc..7c7680def 100644 --- a/core/src/main/java/org/teavm/backend/wasm/parser/CodeListener.java +++ b/core/src/main/java/org/teavm/backend/wasm/parser/CodeListener.java @@ -159,6 +159,9 @@ public interface CodeListener { default void arraySet(int typeIndex) { } + default void arrayCopy(int targetTypeIndex, int sourceTypeIndex) { + } + default void getGlobal(int globalIndex) { } diff --git a/core/src/main/java/org/teavm/backend/wasm/parser/CodeSectionParser.java b/core/src/main/java/org/teavm/backend/wasm/parser/CodeSectionParser.java index 488708d4a..f9fca4ad4 100644 --- a/core/src/main/java/org/teavm/backend/wasm/parser/CodeSectionParser.java +++ b/core/src/main/java/org/teavm/backend/wasm/parser/CodeSectionParser.java @@ -723,6 +723,10 @@ public class CodeSectionParser { codeListener.opcode(Opcode.ARRAY_LENGTH); return true; + case 17: + codeListener.arrayCopy(readLEB(), readLEB()); + return true; + case 23: codeListener.cast(readHeapType()); return true; 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 02a55666c..271c2543e 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,6 +25,7 @@ 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.WasmArrayCopy; import org.teavm.backend.wasm.model.expression.WasmArrayGet; import org.teavm.backend.wasm.model.expression.WasmArrayLength; import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault; @@ -1142,6 +1143,21 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { popLocation(); } + @Override + public void visit(WasmArrayCopy expression) { + pushLocation(expression); + expression.getTargetArray().acceptVisitor(this); + expression.getTargetIndex().acceptVisitor(this); + expression.getSourceArray().acceptVisitor(this); + expression.getSourceIndex().acceptVisitor(this); + expression.getSize().acceptVisitor(this); + writer.writeByte(0xfb); + writer.writeByte(17); + writer.writeLEB(module.types.indexOf(expression.getTargetArrayType())); + writer.writeLEB(module.types.indexOf(expression.getSourceArrayType())); + popLocation(); + } + @Override public void visit(WasmFunctionReference expression) { pushLocation(expression); 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 c2e53084d..1a0b521ee 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 @@ -27,6 +27,7 @@ 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.WasmArrayCopy; import org.teavm.backend.wasm.model.expression.WasmArrayGet; import org.teavm.backend.wasm.model.expression.WasmArrayLength; import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault; @@ -1209,6 +1210,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor { unsupported(); } + @Override + public void visit(WasmArrayCopy expression) { + unsupported(); + } + @Override public void visit(WasmFunctionReference expression) { unsupported(); 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 b0db7d305..c36390809 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 @@ -23,6 +23,7 @@ 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.WasmArrayCopy; import org.teavm.backend.wasm.model.expression.WasmArrayGet; import org.teavm.backend.wasm.model.expression.WasmArrayLength; import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault; @@ -791,6 +792,19 @@ class WasmRenderingVisitor implements WasmExpressionVisitor { close(); } + @Override + public void visit(WasmArrayCopy expression) { + open().append("array.copy"); + append(" ").append(typeName(expression.getTargetArrayType())); + append(" ").append(typeName(expression.getSourceArrayType())); + line(expression.getTargetArray()); + line(expression.getTargetIndex()); + line(expression.getSourceArray()); + line(expression.getSourceIndex()); + line(expression.getSize()); + close(); + } + @Override public void visit(WasmFunctionReference expression) { open().append("ref.func ").append(" $" + module.functions.indexOf(expression.getFunction())); 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 b70bd2f75..cf46938e5 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,6 +16,7 @@ package org.teavm.backend.wasm.render; import org.teavm.backend.wasm.model.WasmType; +import org.teavm.backend.wasm.model.expression.WasmArrayCopy; import org.teavm.backend.wasm.model.expression.WasmArrayGet; import org.teavm.backend.wasm.model.expression.WasmArrayLength; import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault; @@ -317,6 +318,11 @@ public class WasmTypeInference implements WasmExpressionVisitor { result = WasmType.INT32; } + @Override + public void visit(WasmArrayCopy expression) { + result = null; + } + @Override public void visit(WasmFunctionReference expression) { result = expression.getFunction().getType().getReference();