wasm: implement global variables

They aren't used by current Wasm BE yet, but will be used by future Wasm GC BE
This commit is contained in:
Alexey Andreev 2024-07-01 19:37:04 +02:00
parent 3ba2282473
commit efcb22b639
11 changed files with 239 additions and 2 deletions

View File

@ -0,0 +1,51 @@
/*
* 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;
import java.util.Objects;
import org.teavm.backend.wasm.model.expression.WasmExpression;
public class WasmGlobal extends WasmEntity {
private String name;
private WasmType type;
private WasmExpression initialValue;
public WasmGlobal(String name, WasmType type, WasmExpression initialValue) {
this.name = name;
this.type = Objects.requireNonNull(type);
this.initialValue = Objects.requireNonNull(initialValue);
}
public String getName() {
return name;
}
public WasmType getType() {
return type;
}
public void setType(WasmType type) {
this.type = Objects.requireNonNull(type);
}
public WasmExpression getInitialValue() {
return initialValue;
}
public void setInitialValue(WasmExpression initialValue) {
this.initialValue = Objects.requireNonNull(initialValue);
}
}

View File

@ -31,6 +31,7 @@ public class WasmModule {
private Map<String, WasmCustomSection> readonlyCustomSections = Collections.unmodifiableMap(customSections); private Map<String, WasmCustomSection> readonlyCustomSections = Collections.unmodifiableMap(customSections);
public final WasmCollection<WasmFunction> functions = new WasmCollection<>(); public final WasmCollection<WasmFunction> functions = new WasmCollection<>();
public final WasmCollection<WasmGlobal> globals = new WasmCollection<>();
public final WasmCollection<WasmCompositeType> types = new WasmCollection<>(); public final WasmCollection<WasmCompositeType> types = new WasmCollection<>();
public final WasmCollection<WasmTag> tags = new WasmCollection<>(); public final WasmCollection<WasmTag> tags = new WasmCollection<>();

View File

@ -94,6 +94,15 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
expression.getValue().acceptVisitor(this); expression.getValue().acceptVisitor(this);
} }
@Override
public void visit(WasmGetGlobal expression) {
}
@Override
public void visit(WasmSetGlobal expression) {
expression.getValue().acceptVisitor(this);
}
@Override @Override
public void visit(WasmIntBinary expression) { public void visit(WasmIntBinary expression) {
expression.getFirst().acceptVisitor(this); expression.getFirst().acceptVisitor(this);

View File

@ -44,6 +44,10 @@ public interface WasmExpressionVisitor {
void visit(WasmSetLocal expression); void visit(WasmSetLocal expression);
void visit(WasmGetGlobal expression);
void visit(WasmSetGlobal expression);
void visit(WasmIntBinary expression); void visit(WasmIntBinary expression);
void visit(WasmFloatBinary expression); void visit(WasmFloatBinary expression);

View File

@ -0,0 +1,40 @@
/*
* 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.WasmGlobal;
public class WasmGetGlobal extends WasmExpression {
private WasmGlobal global;
public WasmGetGlobal(WasmGlobal global) {
this.global = Objects.requireNonNull(global);
}
public WasmGlobal getGlobal() {
return global;
}
public void setGlobal(WasmGlobal global) {
this.global = Objects.requireNonNull(global);
}
@Override
public void acceptVisitor(WasmExpressionVisitor visitor) {
visitor.visit(this);
}
}

View File

@ -118,6 +118,15 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
expression.getValue().acceptVisitor(this); expression.getValue().acceptVisitor(this);
} }
@Override
public void visit(WasmGetGlobal expression) {
}
@Override
public void visit(WasmSetGlobal expression) {
expression.getValue().acceptVisitor(this);
}
@Override @Override
public void visit(WasmIntBinary expression) { public void visit(WasmIntBinary expression) {
expression.getFirst().acceptVisitor(this); expression.getFirst().acceptVisitor(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.WasmGlobal;
public class WasmSetGlobal extends WasmExpression {
private WasmGlobal global;
private WasmExpression value;
public WasmSetGlobal(WasmGlobal global, WasmExpression value) {
this.global = Objects.requireNonNull(global);
this.value = Objects.requireNonNull(value);
}
public WasmGlobal getGlobal() {
return global;
}
public void setGlobal(WasmGlobal global) {
this.global = Objects.requireNonNull(global);
}
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

@ -45,6 +45,7 @@ import org.teavm.backend.wasm.model.expression.WasmFloat32Constant;
import org.teavm.backend.wasm.model.expression.WasmFloat64Constant; import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
import org.teavm.backend.wasm.model.expression.WasmFloatBinary; import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
import org.teavm.backend.wasm.model.expression.WasmFloatUnary; import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
import org.teavm.backend.wasm.model.expression.WasmGetLocal; import org.teavm.backend.wasm.model.expression.WasmGetLocal;
import org.teavm.backend.wasm.model.expression.WasmIndirectCall; import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant; import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
@ -59,6 +60,7 @@ import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
import org.teavm.backend.wasm.model.expression.WasmNullConstant; import org.teavm.backend.wasm.model.expression.WasmNullConstant;
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual; import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
import org.teavm.backend.wasm.model.expression.WasmReturn; import org.teavm.backend.wasm.model.expression.WasmReturn;
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmSetLocal;
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32; import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64; import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
@ -269,6 +271,23 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
popLocation(); popLocation();
} }
@Override
public void visit(WasmGetGlobal expression) {
pushLocation(expression);
writer.writeByte(0x23);
writer.writeLEB(module.globals.indexOf(expression.getGlobal()));
popLocation();
}
@Override
public void visit(WasmSetGlobal expression) {
pushLocation(expression);
expression.getValue().acceptVisitor(this);
writer.writeByte(0x24);
writer.writeLEB(module.globals.indexOf(expression.getGlobal()));
popLocation();
}
@Override @Override
public void visit(WasmIntBinary expression) { public void visit(WasmIntBinary expression) {
pushLocation(expression); pushLocation(expression);

View File

@ -22,6 +22,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.teavm.backend.wasm.model.WasmGlobal;
import org.teavm.backend.wasm.model.WasmLocal; import org.teavm.backend.wasm.model.WasmLocal;
import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmModule;
import org.teavm.backend.wasm.model.WasmNumType; import org.teavm.backend.wasm.model.WasmNumType;
@ -47,6 +48,7 @@ import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
import org.teavm.backend.wasm.model.expression.WasmFloatBinary; import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
import org.teavm.backend.wasm.model.expression.WasmFloatType; import org.teavm.backend.wasm.model.expression.WasmFloatType;
import org.teavm.backend.wasm.model.expression.WasmFloatUnary; import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
import org.teavm.backend.wasm.model.expression.WasmGetLocal; import org.teavm.backend.wasm.model.expression.WasmGetLocal;
import org.teavm.backend.wasm.model.expression.WasmIndirectCall; import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant; import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
@ -62,6 +64,7 @@ import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
import org.teavm.backend.wasm.model.expression.WasmNullConstant; import org.teavm.backend.wasm.model.expression.WasmNullConstant;
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual; import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
import org.teavm.backend.wasm.model.expression.WasmReturn; import org.teavm.backend.wasm.model.expression.WasmReturn;
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmSetLocal;
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32; import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64; import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
@ -366,6 +369,24 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
value = result; value = result;
} }
@Override
public void visit(WasmGetGlobal expression) {
value = new CExpression(getVariableName(expression.getGlobal()));
}
@Override
public void visit(WasmSetGlobal expression) {
CExpression result = new CExpression();
requiredType = expression.getGlobal().getType();
expression.getValue().acceptVisitor(this);
result.getLines().addAll(value.getLines());
result.addLine(getVariableName(expression.getGlobal()) + " = " + value.getText() + ";",
expression.getLocation());
value = result;
}
@Override @Override
public void visit(WasmIntBinary expression) { public void visit(WasmIntBinary expression) {
WasmType type = requiredType; WasmType type = requiredType;
@ -1277,4 +1298,8 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
} }
return result; return result;
} }
String getVariableName(WasmGlobal global) {
return "wasm_global_" + module.globals.indexOf(global);
}
} }

View File

@ -18,6 +18,7 @@ package org.teavm.backend.wasm.render;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.teavm.backend.wasm.model.WasmCompositeType; import org.teavm.backend.wasm.model.WasmCompositeType;
import org.teavm.backend.wasm.model.WasmGlobal;
import org.teavm.backend.wasm.model.WasmLocal; import org.teavm.backend.wasm.model.WasmLocal;
import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmModule;
import org.teavm.backend.wasm.model.WasmNumType; import org.teavm.backend.wasm.model.WasmNumType;
@ -46,6 +47,7 @@ import org.teavm.backend.wasm.model.expression.WasmFloatBinaryOperation;
import org.teavm.backend.wasm.model.expression.WasmFloatType; import org.teavm.backend.wasm.model.expression.WasmFloatType;
import org.teavm.backend.wasm.model.expression.WasmFloatUnary; import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
import org.teavm.backend.wasm.model.expression.WasmFloatUnaryOperation; import org.teavm.backend.wasm.model.expression.WasmFloatUnaryOperation;
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
import org.teavm.backend.wasm.model.expression.WasmGetLocal; import org.teavm.backend.wasm.model.expression.WasmGetLocal;
import org.teavm.backend.wasm.model.expression.WasmIndirectCall; import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant; import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
@ -63,6 +65,7 @@ import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
import org.teavm.backend.wasm.model.expression.WasmNullConstant; import org.teavm.backend.wasm.model.expression.WasmNullConstant;
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual; import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
import org.teavm.backend.wasm.model.expression.WasmReturn; import org.teavm.backend.wasm.model.expression.WasmReturn;
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmSetLocal;
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32; import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64; import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
@ -290,18 +293,32 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
@Override @Override
public void visit(WasmGetLocal expression) { public void visit(WasmGetLocal expression) {
open().append("get_local " + asString(expression.getLocal())).close(); open().append("local.get " + asString(expression.getLocal())).close();
} }
@Override @Override
public void visit(WasmSetLocal expression) { public void visit(WasmSetLocal expression) {
open().append("set_local " + asString(expression.getLocal())).line(expression.getValue()).close(); open().append("local.set " + asString(expression.getLocal())).line(expression.getValue()).close();
}
@Override
public void visit(WasmGetGlobal expression) {
open().append("global.get " + asString(expression.getGlobal())).close();
}
@Override
public void visit(WasmSetGlobal expression) {
open().append("global.set " + asString(expression.getGlobal())).line(expression.getValue()).close();
} }
private String asString(WasmLocal local) { private String asString(WasmLocal local) {
return String.valueOf(local.getIndex()); return String.valueOf(local.getIndex());
} }
private String asString(WasmGlobal global) {
return global.getName() != null ? "$" + global.getName() : String.valueOf(module.globals.indexOf(global));
}
@Override @Override
public void visit(WasmIntBinary expression) { public void visit(WasmIntBinary expression) {
open().append(type(expression.getType()) + "." + operation(expression.getOperation())); open().append(type(expression.getType()) + "." + operation(expression.getOperation()));

View File

@ -36,6 +36,7 @@ import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
import org.teavm.backend.wasm.model.expression.WasmFloatBinary; import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
import org.teavm.backend.wasm.model.expression.WasmFloatType; import org.teavm.backend.wasm.model.expression.WasmFloatType;
import org.teavm.backend.wasm.model.expression.WasmFloatUnary; import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
import org.teavm.backend.wasm.model.expression.WasmGetLocal; import org.teavm.backend.wasm.model.expression.WasmGetLocal;
import org.teavm.backend.wasm.model.expression.WasmIndirectCall; import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant; import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
@ -51,6 +52,7 @@ import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
import org.teavm.backend.wasm.model.expression.WasmNullConstant; import org.teavm.backend.wasm.model.expression.WasmNullConstant;
import org.teavm.backend.wasm.model.expression.WasmReferencesEqual; import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
import org.teavm.backend.wasm.model.expression.WasmReturn; import org.teavm.backend.wasm.model.expression.WasmReturn;
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmSetLocal;
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32; import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64; import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
@ -136,6 +138,16 @@ public class WasmTypeInference implements WasmExpressionVisitor {
result = null; result = null;
} }
@Override
public void visit(WasmGetGlobal expression) {
result = expression.getGlobal().getType();
}
@Override
public void visit(WasmSetGlobal expression) {
result = null;
}
@Override @Override
public void visit(WasmIntBinary expression) { public void visit(WasmIntBinary expression) {
result = map(expression.getType()); result = map(expression.getType());