mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: fix issues in generation of types, globals and some expressions
This commit is contained in:
parent
ea29208b6c
commit
87aaa0b452
|
@ -300,6 +300,11 @@ public class WasmGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
return new WasmInt32Constant(classGenerator.getClassPointer(type));
|
return new WasmInt32Constant(classGenerator.getClassPointer(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected WasmExpression nullLiteral() {
|
||||||
|
return new WasmInt32Constant(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SubscriptExpr expr) {
|
public void visit(SubscriptExpr expr) {
|
||||||
WasmExpression ptr = getArrayElementPointer(expr);
|
WasmExpression ptr = getArrayElementPointer(expr);
|
||||||
|
|
|
@ -553,7 +553,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstantExpr expr) {
|
public void visit(ConstantExpr expr) {
|
||||||
if (expr.getValue() == null) {
|
if (expr.getValue() == null) {
|
||||||
result = new WasmInt32Constant(0);
|
result = nullLiteral();
|
||||||
} else if (expr.getValue() instanceof Integer) {
|
} else if (expr.getValue() instanceof Integer) {
|
||||||
result = new WasmInt32Constant((Integer) expr.getValue());
|
result = new WasmInt32Constant((Integer) expr.getValue());
|
||||||
} else if (expr.getValue() instanceof Long) {
|
} else if (expr.getValue() instanceof Long) {
|
||||||
|
@ -569,8 +569,11 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Constant unsupported: " + expr.getValue());
|
throw new IllegalArgumentException("Constant unsupported: " + expr.getValue());
|
||||||
}
|
}
|
||||||
|
result.setLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract WasmExpression nullLiteral();
|
||||||
|
|
||||||
protected abstract WasmExpression stringLiteral(String s);
|
protected abstract WasmExpression stringLiteral(String s);
|
||||||
|
|
||||||
protected abstract WasmExpression classLiteral(ValueType type);
|
protected abstract WasmExpression classLiteral(ValueType type);
|
||||||
|
|
|
@ -335,8 +335,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
var virtualTable = virtualTables.lookup(className);
|
var virtualTable = virtualTables.lookup(className);
|
||||||
var structure = new WasmStructure(names.forClassClass(className));
|
var structure = new WasmStructure(names.forClassClass(className));
|
||||||
module.types.add(structure);
|
module.types.add(structure);
|
||||||
addVirtualTableFields(structure, virtualTable);
|
|
||||||
fillClassFields(structure.getFields(), "java.lang.Class");
|
fillClassFields(structure.getFields(), "java.lang.Class");
|
||||||
|
addVirtualTableFields(structure, virtualTable);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.backend.wasm.generate.gc.methods;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.teavm.ast.ArrayType;
|
import org.teavm.ast.ArrayType;
|
||||||
|
import org.teavm.ast.BinaryExpr;
|
||||||
import org.teavm.ast.Expr;
|
import org.teavm.ast.Expr;
|
||||||
import org.teavm.ast.InvocationExpr;
|
import org.teavm.ast.InvocationExpr;
|
||||||
import org.teavm.ast.QualificationExpr;
|
import org.teavm.ast.QualificationExpr;
|
||||||
|
@ -40,7 +41,11 @@ import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
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.WasmIntType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
||||||
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.WasmSetGlobal;
|
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.WasmStructGet;
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
|
@ -167,11 +172,45 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
return new WasmGetGlobal(classConstant.getPointer());
|
return new WasmGetGlobal(classConstant.getPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected WasmExpression nullLiteral() {
|
||||||
|
return new WasmNullConstant(WasmType.Reference.STRUCT);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CallSiteIdentifier generateCallSiteId(TextLocation location) {
|
protected CallSiteIdentifier generateCallSiteId(TextLocation location) {
|
||||||
return new SimpleCallSite();
|
return new SimpleCallSite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr expr) {
|
||||||
|
if (expr.getType() == null) {
|
||||||
|
switch (expr.getOperation()) {
|
||||||
|
case EQUALS: {
|
||||||
|
accept(expr.getFirstOperand());
|
||||||
|
var first = result;
|
||||||
|
accept(expr.getSecondOperand());
|
||||||
|
var second = result;
|
||||||
|
result = new WasmReferencesEqual(first, second);
|
||||||
|
result.setLocation(expr.getLocation());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case NOT_EQUALS:
|
||||||
|
accept(expr.getFirstOperand());
|
||||||
|
var first = result;
|
||||||
|
accept(expr.getSecondOperand());
|
||||||
|
var second = result;
|
||||||
|
result = new WasmReferencesEqual(first, second);
|
||||||
|
result = new WasmIntUnary(WasmIntType.INT32, WasmIntUnaryOperation.EQZ, result);
|
||||||
|
result.setLocation(expr.getLocation());
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.visit(expr);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WasmExpression generateVirtualCall(WasmLocal instance, MethodReference method,
|
protected WasmExpression generateVirtualCall(WasmLocal instance, MethodReference method,
|
||||||
List<WasmExpression> arguments) {
|
List<WasmExpression> arguments) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.teavm.common.Graph;
|
||||||
import org.teavm.common.GraphUtils;
|
import org.teavm.common.GraphUtils;
|
||||||
|
|
||||||
public class WasmModule {
|
public class WasmModule {
|
||||||
|
@ -93,32 +94,70 @@ public class WasmModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepareForRendering() {
|
public void prepareForRendering() {
|
||||||
prepareRecursiveTypes();
|
prepareTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareRecursiveTypes() {
|
private void prepareTypes() {
|
||||||
var typeGraph = WasmTypeGraphBuilder.buildTypeGraph(types, types.size());
|
var typeGraph = WasmTypeGraphBuilder.buildTypeGraph(types, types.size());
|
||||||
var newList = new ArrayList<WasmCompositeType>();
|
var sccs = GraphUtils.findStronglyConnectedComponents(typeGraph);
|
||||||
var typesInScc = new boolean[types.size()];
|
var sccStartNode = new int[types.size()];
|
||||||
for (var scc : GraphUtils.findStronglyConnectedComponents(typeGraph)) {
|
for (var i = 0; i < sccStartNode.length; ++i) {
|
||||||
|
sccStartNode[i] = i;
|
||||||
|
}
|
||||||
|
var sccsByIndex = new int[types.size()][];
|
||||||
|
for (var scc : sccs) {
|
||||||
|
sccsByIndex[scc[0]] = scc;
|
||||||
var firstType = types.get(scc[0]);
|
var firstType = types.get(scc[0]);
|
||||||
firstType.recursiveTypeCount = scc.length;
|
firstType.recursiveTypeCount = scc.length;
|
||||||
for (var i = 0; i < scc.length; i++) {
|
for (var i = 0; i < scc.length; i++) {
|
||||||
var index = scc[i];
|
var index = scc[i];
|
||||||
var type = types.get(index);
|
var type = types.get(index);
|
||||||
newList.add(type);
|
|
||||||
type.indexInRecursiveType = i;
|
type.indexInRecursiveType = i;
|
||||||
typesInScc[index] = true;
|
sccStartNode[scc[i]] = sccStartNode[scc[0]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var type : types) {
|
|
||||||
if (!typesInScc[type.index]) {
|
var sorting = new TypeSorting();
|
||||||
newList.add(type);
|
sorting.original = types;
|
||||||
}
|
sorting.graph = typeGraph;
|
||||||
|
sorting.visited = new boolean[types.size()];
|
||||||
|
sorting.sccMap = sccStartNode;
|
||||||
|
sorting.sccsByIndex = sccsByIndex;
|
||||||
|
for (var i = 0; i < types.size(); ++i) {
|
||||||
|
sorting.visit(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
types.clear();
|
types.clear();
|
||||||
for (var type : newList) {
|
for (var type : sorting.sorted) {
|
||||||
types.add(type);
|
types.add(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class TypeSorting {
|
||||||
|
WasmCollection<WasmCompositeType> original;
|
||||||
|
Graph graph;
|
||||||
|
boolean[] visited;
|
||||||
|
int[] sccMap;
|
||||||
|
int[][] sccsByIndex;
|
||||||
|
List<WasmCompositeType> sorted = new ArrayList<>();
|
||||||
|
|
||||||
|
void visit(int typeIndex) {
|
||||||
|
typeIndex = sccMap[typeIndex];
|
||||||
|
if (visited[typeIndex]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visited[typeIndex] = true;
|
||||||
|
for (var outgoing : graph.outgoingEdges(typeIndex)) {
|
||||||
|
visit(outgoing);
|
||||||
|
}
|
||||||
|
var scc = sccsByIndex[typeIndex];
|
||||||
|
if (scc == null) {
|
||||||
|
sorted.add(original.get(typeIndex));
|
||||||
|
} else {
|
||||||
|
for (var index : scc) {
|
||||||
|
sorted.add(original.get(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public abstract class WasmType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class SpecialReference extends WasmType {
|
public static final class SpecialReference extends Reference {
|
||||||
public final SpecialReferenceKind kind;
|
public final SpecialReferenceKind kind;
|
||||||
|
|
||||||
private SpecialReference(SpecialReferenceKind kind) {
|
private SpecialReference(SpecialReferenceKind kind) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ public class WasmBinaryRenderer {
|
||||||
private static final int SECTION_FUNCTION = 3;
|
private static final int SECTION_FUNCTION = 3;
|
||||||
private static final int SECTION_TABLE = 4;
|
private static final int SECTION_TABLE = 4;
|
||||||
private static final int SECTION_MEMORY = 5;
|
private static final int SECTION_MEMORY = 5;
|
||||||
|
private static final int SECTION_GLOBAL = 6;
|
||||||
private static final int SECTION_EXPORT = 7;
|
private static final int SECTION_EXPORT = 7;
|
||||||
private static final int SECTION_START = 8;
|
private static final int SECTION_START = 8;
|
||||||
private static final int SECTION_ELEMENT = 9;
|
private static final int SECTION_ELEMENT = 9;
|
||||||
|
@ -88,6 +89,7 @@ public class WasmBinaryRenderer {
|
||||||
renderTable(module);
|
renderTable(module);
|
||||||
renderMemory(module);
|
renderMemory(module);
|
||||||
renderTags(module);
|
renderTags(module);
|
||||||
|
renderGlobals(module);
|
||||||
renderExport(module);
|
renderExport(module);
|
||||||
renderStart(module);
|
renderStart(module);
|
||||||
renderElement(module);
|
renderElement(module);
|
||||||
|
@ -205,6 +207,24 @@ public class WasmBinaryRenderer {
|
||||||
writeSection(SECTION_MEMORY, "memory", section.getData());
|
writeSection(SECTION_MEMORY, "memory", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void renderGlobals(WasmModule module) {
|
||||||
|
if (module.globals.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var section = new WasmBinaryWriter();
|
||||||
|
var visitor = new WasmBinaryRenderingVisitor(section, module, null, null, 0);
|
||||||
|
section.writeLEB(module.globals.size());
|
||||||
|
for (var global : module.globals) {
|
||||||
|
section.writeType(global.getType(), module);
|
||||||
|
section.writeByte(1); // mutable
|
||||||
|
global.getInitialValue().acceptVisitor(visitor);
|
||||||
|
section.writeByte(0x0b);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSection(SECTION_GLOBAL, "global", section.getData());
|
||||||
|
}
|
||||||
|
|
||||||
private void renderExport(WasmModule module) {
|
private void renderExport(WasmModule module) {
|
||||||
|
|
||||||
// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#export-section
|
// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#export-section
|
||||||
|
|
|
@ -253,7 +253,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmNullConstant expression) {
|
public void visit(WasmNullConstant expression) {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
writer.writeByte(0xD0);
|
writer.writeByte(0xD0);
|
||||||
writeBlockType(expression.getType());
|
writer.writeHeapType(expression.getType(), module);
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1146,7 +1146,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmFunctionReference expression) {
|
public void visit(WasmFunctionReference expression) {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
writer.writeByte(0xd2);
|
writer.writeByte(0xd2);
|
||||||
writer.writeInt32(module.functions.indexOf(expression.getFunction()));
|
writer.writeLEB(module.functions.indexOf(expression.getFunction()));
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,33 +41,45 @@ public class WasmBinaryWriter {
|
||||||
if (type instanceof WasmType.Number) {
|
if (type instanceof WasmType.Number) {
|
||||||
writeType(((WasmType.Number) type).number);
|
writeType(((WasmType.Number) type).number);
|
||||||
} else if (type instanceof WasmType.SpecialReference) {
|
} else if (type instanceof WasmType.SpecialReference) {
|
||||||
switch (((WasmType.SpecialReference) type).kind) {
|
writeSpecialHeapType(((WasmType.SpecialReference) type).kind);
|
||||||
case ANY:
|
|
||||||
writeByte(0x6e);
|
|
||||||
break;
|
|
||||||
case EXTERN:
|
|
||||||
writeByte(0x6f);
|
|
||||||
break;
|
|
||||||
case FUNC:
|
|
||||||
writeByte(0x70);
|
|
||||||
break;
|
|
||||||
case STRUCT:
|
|
||||||
writeByte(0x6b);
|
|
||||||
break;
|
|
||||||
case ARRAY:
|
|
||||||
writeByte(0x6a);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (type instanceof WasmType.CompositeReference) {
|
} else if (type instanceof WasmType.CompositeReference) {
|
||||||
writeByte(0x63);
|
writeByte(0x63);
|
||||||
var composite = ((WasmType.CompositeReference) type).composite;
|
var composite = ((WasmType.CompositeReference) type).composite;
|
||||||
var index = isRecursiveMember
|
var index = module.types.indexOf(composite);
|
||||||
? composite.getIndexInRecursiveType()
|
|
||||||
: module.types.indexOf(composite);
|
|
||||||
writeSignedLEB(index);
|
writeSignedLEB(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void writeHeapType(WasmType.Reference type, WasmModule module) {
|
||||||
|
if (type instanceof WasmType.CompositeReference) {
|
||||||
|
var composite = ((WasmType.CompositeReference) type).composite;
|
||||||
|
var index = module.types.indexOf(composite);
|
||||||
|
writeSignedLEB(index);
|
||||||
|
} else {
|
||||||
|
writeSpecialHeapType(((WasmType.SpecialReference) type).kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeSpecialHeapType(WasmType.SpecialReferenceKind type) {
|
||||||
|
switch (type) {
|
||||||
|
case ANY:
|
||||||
|
writeByte(0x6e);
|
||||||
|
break;
|
||||||
|
case EXTERN:
|
||||||
|
writeByte(0x6f);
|
||||||
|
break;
|
||||||
|
case FUNC:
|
||||||
|
writeByte(0x70);
|
||||||
|
break;
|
||||||
|
case STRUCT:
|
||||||
|
writeByte(0x6b);
|
||||||
|
break;
|
||||||
|
case ARRAY:
|
||||||
|
writeByte(0x6a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void writeType(WasmNumType type) {
|
public void writeType(WasmNumType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT32:
|
case INT32:
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class WasmCompositeTypeBinaryRenderer implements WasmCompositeTypeVisitor
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
section.writeType(storageType.asUnpackedType(), module);
|
section.writeType(storageType.asUnpackedType(), module, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user