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.
This commit is contained in:
Alexey Andreev 2024-06-30 16:18:51 +02:00
parent 1e5e9d50ed
commit 3ba2282473
23 changed files with 1060 additions and 9 deletions

View File

@ -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;
});

View File

@ -22,11 +22,13 @@ public class WasmArray extends WasmCompositeType {
private WasmStorageType elementType;
private Supplier<WasmStorageType> elementTypeSupplier;
public WasmArray(WasmStorageType elementType) {
public WasmArray(String name, WasmStorageType elementType) {
super(name);
this.elementType = Objects.requireNonNull(elementType);
}
public WasmArray(Supplier<WasmStorageType> elementTypeSupplier) {
public WasmArray(String name, Supplier<WasmStorageType> elementTypeSupplier) {
super(name);
this.elementTypeSupplier = elementTypeSupplier;
}

View File

@ -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() {

View File

@ -24,13 +24,15 @@ public class WasmFunctionType extends WasmCompositeType {
private Supplier<List<? extends WasmType>> parameterTypesSupplier;
private Supplier<WasmType> returnTypeSupplier;
public WasmFunctionType(WasmType returnType, List<? extends WasmType> parameterTypes) {
public WasmFunctionType(String name, WasmType returnType, List<? extends WasmType> parameterTypes) {
super(name);
this.returnType = returnType;
this.parameterTypes = parameterTypes;
}
public WasmFunctionType(Supplier<WasmType> returnTypeSupplier,
public WasmFunctionType(String name, Supplier<WasmType> returnTypeSupplier,
Supplier<List<? extends WasmType>> parameterTypesSupplier) {
super(name);
this.returnTypeSupplier = returnTypeSupplier;
this.parameterTypesSupplier = parameterTypesSupplier;
}

View File

@ -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;
}
}
}

View File

@ -22,11 +22,13 @@ public class WasmStructure extends WasmCompositeType {
private List<? extends WasmStorageType> fields;
private Supplier<List<? extends WasmStorageType>> fieldsSupplier;
public WasmStructure(List<? extends WasmStorageType> fields) {
public WasmStructure(String name, List<? extends WasmStorageType> fields) {
super(name);
this.fields = List.copyOf(fields);
}
public WasmStructure(Supplier<List<? extends WasmStorageType>> fieldsSupplier) {
public WasmStructure(String name, Supplier<List<? extends WasmStorageType>> fieldsSupplier) {
super(name);
this.fieldsSupplier = fieldsSupplier;
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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()));
}
}

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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<WasmExpression> 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<WasmExpression> getInitializers() {
return initializers;
}
@Override
public void acceptVisitor(WasmExpressionVisitor visitor) {
visitor.visit(this);
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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;

View File

@ -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:

View File

@ -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: