From 5572d4b5d7fbeea6f900b76c64715b92dca8692b Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 30 Jul 2024 20:57:36 +0200 Subject: [PATCH] wasm gc: add subtyping information to types, fix generation of expressions --- .../backend/wasm/WasmGCModuleGenerator.java | 7 ++--- .../org/teavm/backend/wasm/WasmGCTarget.java | 2 +- .../methods/BaseWasmGenerationVisitor.java | 2 +- .../gc/classes/WasmGCClassGenerator.java | 21 ++++++++++----- .../generate/gc/classes/WasmGCTypeMapper.java | 27 ++++++++++++++++++- .../gc/methods/WasmGCGenerationVisitor.java | 2 +- .../gc/methods/WasmGCMethodGenerator.java | 12 ++++----- .../backend/wasm/model/WasmStructure.java | 9 +++++++ .../wasm/model/WasmTypeGraphBuilder.java | 3 +++ .../render/WasmBinaryRenderingVisitor.java | 18 ++++++------- .../backend/wasm/render/WasmBinaryWriter.java | 4 --- .../WasmCompositeTypeBinaryRenderer.java | 10 +++++-- 12 files changed, 81 insertions(+), 36 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmGCModuleGenerator.java b/core/src/main/java/org/teavm/backend/wasm/WasmGCModuleGenerator.java index 4e2d2e18d..101df7a8a 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmGCModuleGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmGCModuleGenerator.java @@ -33,13 +33,11 @@ import org.teavm.model.MethodReference; import org.teavm.model.ValueType; public class WasmGCModuleGenerator { - private final WasmGCTarget wasmGCTarget; private WasmGCDeclarationsGenerator declarationsGenerator; private WasmFunction initializer; private WasmGlobal initializerRef; - public WasmGCModuleGenerator(WasmGCTarget wasmGCTarget, WasmGCDeclarationsGenerator declarationsGenerator) { - this.wasmGCTarget = wasmGCTarget; + public WasmGCModuleGenerator(WasmGCDeclarationsGenerator declarationsGenerator) { this.declarationsGenerator = declarationsGenerator; } @@ -64,8 +62,7 @@ public class WasmGCModuleGenerator { var tempVars = new TemporaryVariablePool(mainFunctionCaller); var genUtil = new WasmGCGenerationUtil(declarationsGenerator.classInfoProvider(), tempVars); var stringArrayType = declarationsGenerator.typeMapper() - .mapType(ValueType.parse(String[].class)) - .asUnpackedType(); + .mapType(ValueType.parse(String[].class)); var arrayVar = tempVars.acquire(stringArrayType); genUtil.allocateArray(ValueType.parse(String.class), new WasmInt32Constant(0), null, arrayVar, mainFunctionCaller.getBody()); diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmGCTarget.java b/core/src/main/java/org/teavm/backend/wasm/WasmGCTarget.java index 53b19b904..bb0f2e697 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmGCTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmGCTarget.java @@ -118,7 +118,7 @@ public class WasmGCTarget implements TeaVMTarget { customGenerators ); declarationsGenerator.setFriendlyToDebugger(controller.isFriendlyToDebugger()); - var moduleGenerator = new WasmGCModuleGenerator(this, declarationsGenerator); + var moduleGenerator = new WasmGCModuleGenerator(declarationsGenerator); var mainFunction = moduleGenerator.generateMainFunction(controller.getEntryPoint()); mainFunction.setExportName(controller.getEntryPointName()); mainFunction.setName(controller.getEntryPointName()); diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java index 6c90e22bf..3109fed6d 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java @@ -761,7 +761,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp var callSiteId = generateCallSiteId(expr.getLocation()); if (needsCallSiteId() && isManagedCall(expr.getMethod())) { var invocation = generateInvocation(expr, callSiteId); - var type = WasmGeneratorUtil.mapType(expr.getMethod().getReturnType()); + var type = mapType(expr.getMethod().getReturnType()); List targetList; WasmBlock block; diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCClassGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCClassGenerator.java index b5b0687f5..b730338cd 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCClassGenerator.java @@ -182,6 +182,14 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit ? ((ValueType.Object) type).getClassName() : null; classInfo.structure = new WasmStructure(name != null ? names.forClass(name) : null); + if (name != null) { + var classReader = classSource.get(name); + if (classReader != null && classReader.getParent() != null) { + classInfo.structure.setSupertype(getClassInfo(classReader.getParent()).structure); + } + } else { + classInfo.structure.setSupertype(standardClasses.objectClass().structure); + } module.types.add(classInfo.structure); fillFields(classInfo.structure.getFields(), type); } @@ -318,7 +326,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit call.getArguments().add(new WasmCast(new WasmGetLocal(instanceParam), castTarget)); var params = new WasmLocal[method.parameterCount()]; for (var i = 0; i < method.parameterCount(); ++i) { - params[i] = new WasmLocal(typeMapper.mapType(method.parameterType(i)).asUnpackedType()); + params[i] = new WasmLocal(typeMapper.mapType(method.parameterType(i))); call.getArguments().add(new WasmGetLocal(params[i])); } wrapperFunction.getLocalVariables().addAll(List.of(params)); @@ -333,6 +341,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit private WasmStructure initRegularClassStructure(String className) { var virtualTable = virtualTables.lookup(className); var structure = new WasmStructure(names.forClassClass(className)); + structure.setSupertype(standardClasses.classClass().getStructure()); module.types.add(structure); structure.getFields().add(standardClasses.classClass().getType().asStorage()); structure.getFields().add(WasmType.Reference.ANY.asStorage()); @@ -354,12 +363,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit } private WasmFunctionType getFunctionType(String className, MethodDescriptor methodDesc) { - var returnType = typeMapper.mapType(methodDesc.getResultType()).asUnpackedType(); + var returnType = typeMapper.mapType(methodDesc.getResultType()); var javaParamTypes = methodDesc.getParameterTypes(); var paramTypes = new WasmType[javaParamTypes.length + 1]; paramTypes[0] = getClassInfo(className).getType(); for (var i = 0; i < javaParamTypes.length; ++i) { - paramTypes[i + 1] = typeMapper.mapType(javaParamTypes[i]).asUnpackedType(); + paramTypes[i + 1] = typeMapper.mapType(javaParamTypes[i]); } return functionTypes.of(returnType, paramTypes); } @@ -414,7 +423,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit javaType = ValueType.object("java.lang.Object"); } - var type = typeMapper.mapType(javaType).asUnpackedType(); + var type = typeMapper.mapType(javaType); var global = new WasmGlobal(names.forStaticField(fieldRef), type, WasmExpression.defaultValueOfType(type)); module.globals.add(global); @@ -462,7 +471,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit continue; } fieldIndexes.putIfAbsent(field.getReference(), fields.size()); - fields.add(typeMapper.mapType(field.getType())); + fields.add(typeMapper.mapStorageType(field.getType())); } if (className.equals("java.lang.Class")) { classFlagsOffset = fields.size(); @@ -483,7 +492,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit } private void fillArrayField(List fields, ValueType elementType) { - var wasmArray = new WasmArray(null, () -> typeMapper.mapType(elementType)); + var wasmArray = new WasmArray(null, () -> typeMapper.mapStorageType(elementType)); module.types.add(wasmArray); fields.add(wasmArray.getReference().asStorage()); } diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCTypeMapper.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCTypeMapper.java index b44e537c9..26c6cfabc 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCTypeMapper.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCTypeMapper.java @@ -27,7 +27,7 @@ public class WasmGCTypeMapper { this.classInfoProvider = classInfoProvider; } - public WasmStorageType mapType(ValueType type) { + public WasmStorageType mapStorageType(ValueType type) { if (type instanceof ValueType.Primitive) { switch (((ValueType.Primitive) type).getKind()) { case BYTE: @@ -51,4 +51,29 @@ public class WasmGCTypeMapper { return classInfoProvider.getClassInfo(type).getType().asStorage(); } } + + public WasmType mapType(ValueType type) { + if (type instanceof ValueType.Primitive) { + switch (((ValueType.Primitive) type).getKind()) { + case BYTE: + case BOOLEAN: + case SHORT: + case CHARACTER: + case INTEGER: + return WasmType.INT32; + case LONG: + return WasmType.INT64; + case FLOAT: + return WasmType.FLOAT32; + case DOUBLE: + return WasmType.FLOAT64; + default: + throw new IllegalArgumentException(); + } + } else if (type instanceof ValueType.Void) { + return null; + } else { + return classInfoProvider.getClassInfo(type).getType(); + } + } } diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java index 7cb18c269..fa038d697 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java @@ -334,7 +334,7 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor { @Override protected WasmType mapType(ValueType type) { - return context.typeMapper().mapType(type).asUnpackedType(); + return context.typeMapper().mapType(type); } @Override diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java index e712852e3..2f637ee3c 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java @@ -139,10 +139,10 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository { } private WasmFunction createStaticFunction(MethodReference methodReference) { - var returnType = typeMapper.mapType(methodReference.getReturnType()).asUnpackedType(); + var returnType = typeMapper.mapType(methodReference.getReturnType()); var parameterTypes = new WasmType[methodReference.parameterCount()]; for (var i = 0; i < parameterTypes.length; ++i) { - parameterTypes[i] = typeMapper.mapType(methodReference.parameterType(i)).asUnpackedType(); + parameterTypes[i] = typeMapper.mapType(methodReference.parameterType(i)); } var function = new WasmFunction(functionTypes.of(returnType, parameterTypes)); function.setName(names.forMethod(methodReference)); @@ -166,11 +166,11 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository { } private WasmFunction createInstanceFunction(MethodReference methodReference) { - var returnType = typeMapper.mapType(methodReference.getReturnType()).asUnpackedType(); + var returnType = typeMapper.mapType(methodReference.getReturnType()); var parameterTypes = new WasmType[methodReference.parameterCount() + 1]; - parameterTypes[0] = typeMapper.mapType(ValueType.object(methodReference.getClassName())).asUnpackedType(); + parameterTypes[0] = typeMapper.mapType(ValueType.object(methodReference.getClassName())); for (var i = 0; i < methodReference.parameterCount(); ++i) { - parameterTypes[i + 1] = typeMapper.mapType(methodReference.parameterType(i)).asUnpackedType(); + parameterTypes[i + 1] = typeMapper.mapType(methodReference.parameterType(i)); } var function = new WasmFunction(functionTypes.of(returnType, parameterTypes)); function.setName(names.forMethod(methodReference)); @@ -236,7 +236,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository { for (var i = firstVar; i < ast.getVariables().size(); ++i) { var localVar = ast.getVariables().get(i); var representative = method.getProgram().variableAt(variableRepresentatives[i]); - var type = typeMapper.mapType(typeInference.typeOf(representative)).asUnpackedType(); + var type = typeMapper.mapType(typeInference.typeOf(representative)); var wasmLocal = new WasmLocal(type, localVar.getName()); function.add(wasmLocal); } 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 0b242a57d..52dc48b23 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 @@ -20,6 +20,7 @@ import java.util.List; public class WasmStructure extends WasmCompositeType { private List fields = new ArrayList<>(); + private WasmStructure supertype; public WasmStructure(String name) { super(name); @@ -29,6 +30,14 @@ public class WasmStructure extends WasmCompositeType { return fields; } + public WasmStructure getSupertype() { + return supertype; + } + + public void setSupertype(WasmStructure supertype) { + this.supertype = supertype; + } + @Override public void acceptVisitor(WasmCompositeTypeVisitor visitor) { visitor.visit(this); diff --git a/core/src/main/java/org/teavm/backend/wasm/model/WasmTypeGraphBuilder.java b/core/src/main/java/org/teavm/backend/wasm/model/WasmTypeGraphBuilder.java index 38d114cf6..da13c2833 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/WasmTypeGraphBuilder.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/WasmTypeGraphBuilder.java @@ -42,6 +42,9 @@ final class WasmTypeGraphBuilder { @Override public void visit(WasmStructure type) { + if (type.getSupertype() != null) { + addEdge(type.getSupertype().getReference()); + } for (var field : type.getFields()) { addEdge(field.asUnpackedType()); } 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 d9f60a273..9d47283bb 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 @@ -1042,7 +1042,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { } writer.writeByte(0xfb); writer.writeByte(0); - writer.writeInt32(module.types.indexOf(expression.getType())); + writer.writeLEB(module.types.indexOf(expression.getType())); popLocation(); } @@ -1051,7 +1051,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { pushLocation(expression); writer.writeByte(0xfb); writer.writeByte(1); - writer.writeInt32(module.types.indexOf(expression.getType())); + writer.writeLEB(module.types.indexOf(expression.getType())); popLocation(); } @@ -1072,8 +1072,8 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { break; } } - writer.writeInt32(module.types.indexOf(expression.getType())); - writer.writeInt32(expression.getFieldIndex()); + writer.writeLEB(module.types.indexOf(expression.getType())); + writer.writeLEB(expression.getFieldIndex()); popLocation(); } @@ -1084,8 +1084,8 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { expression.getValue().acceptVisitor(this); writer.writeByte(0xfb); writer.writeByte(5); - writer.writeInt32(module.types.indexOf(expression.getType())); - writer.writeInt32(expression.getFieldIndex()); + writer.writeLEB(module.types.indexOf(expression.getType())); + writer.writeLEB(expression.getFieldIndex()); popLocation(); } @@ -1095,7 +1095,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { expression.getLength().acceptVisitor(this); writer.writeByte(0xfb); writer.writeByte(7); - writer.writeInt32(module.types.indexOf(expression.getType())); + writer.writeLEB(module.types.indexOf(expression.getType())); popLocation(); } @@ -1117,7 +1117,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { break; } } - writer.writeInt32(module.types.indexOf(expression.getType())); + writer.writeLEB(module.types.indexOf(expression.getType())); popLocation(); } @@ -1129,7 +1129,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor { expression.getValue().acceptVisitor(this); writer.writeByte(0xfb); writer.writeByte(14); - writer.writeInt32(module.types.indexOf(expression.getType())); + writer.writeLEB(module.types.indexOf(expression.getType())); popLocation(); } diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java index a121c2c96..e14deb4da 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java @@ -30,10 +30,6 @@ public class WasmBinaryWriter { } public void writeType(WasmType type, WasmModule module) { - writeType(type, module, false); - } - - public void writeType(WasmType type, WasmModule module, boolean isRecursiveMember) { if (type == null) { writeByte(0x40); return; diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmCompositeTypeBinaryRenderer.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmCompositeTypeBinaryRenderer.java index 2b44fa5a3..4886be007 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmCompositeTypeBinaryRenderer.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmCompositeTypeBinaryRenderer.java @@ -25,7 +25,6 @@ import org.teavm.backend.wasm.model.WasmStructure; public class WasmCompositeTypeBinaryRenderer implements WasmCompositeTypeVisitor { private WasmModule module; private WasmBinaryWriter section; - private boolean reference; public WasmCompositeTypeBinaryRenderer(WasmModule module, WasmBinaryWriter section) { this.module = module; @@ -34,6 +33,13 @@ public class WasmCompositeTypeBinaryRenderer implements WasmCompositeTypeVisitor @Override public void visit(WasmStructure type) { + section.writeByte(0x50); + if (type.getSupertype() != null) { + section.writeLEB(1); // number of supertypes + section.writeLEB(module.types.indexOf(type.getSupertype())); + } else { + section.writeLEB(0); + } section.writeByte(0x5F); section.writeLEB(type.getFields().size()); for (var fieldType : type.getFields()) { @@ -75,7 +81,7 @@ public class WasmCompositeTypeBinaryRenderer implements WasmCompositeTypeVisitor break; } } else { - section.writeType(storageType.asUnpackedType(), module, true); + section.writeType(storageType.asUnpackedType(), module); } } }