wasm gc: add subtyping information to types, fix generation of expressions

This commit is contained in:
Alexey Andreev 2024-07-30 20:57:36 +02:00
parent a1a776ea9b
commit 5572d4b5d7
12 changed files with 81 additions and 36 deletions

View File

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

View File

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

View File

@ -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<WasmExpression> targetList;
WasmBlock block;

View File

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

View File

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

View File

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

View File

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

View File

@ -20,6 +20,7 @@ import java.util.List;
public class WasmStructure extends WasmCompositeType {
private List<WasmStorageType> 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);

View File

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

View File

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

View File

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

View File

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