mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: support type nullability and global mutability
This commit is contained in:
parent
9b601ac002
commit
1dc7bc653d
|
@ -180,7 +180,7 @@ public class WasmGCModuleGenerator {
|
|||
initializer = new WasmFunction(functionType);
|
||||
initializer.setReferenced(true);
|
||||
declarationsGenerator.module.functions.add(initializer);
|
||||
initializerRef = new WasmGlobal("teavm@initializer", functionType.getReference(),
|
||||
initializerRef = new WasmGlobal("teavm@initializer", functionType.getNonNullReference(),
|
||||
new WasmFunctionReference(initializer));
|
||||
declarationsGenerator.module.globals.add(initializerRef);
|
||||
initializer.getBody().add(new WasmSetGlobal(initializerRef,
|
||||
|
|
|
@ -69,7 +69,9 @@ public abstract class BaseDisassemblyListener {
|
|||
break;
|
||||
}
|
||||
} else if (type instanceof WasmHollowType.SpecialReference) {
|
||||
switch (((WasmHollowType.SpecialReference) type).kind) {
|
||||
var refType = (WasmHollowType.SpecialReference) type;
|
||||
if (refType.isNullable()) {
|
||||
switch (refType.kind) {
|
||||
case ANY:
|
||||
writer.write("anyref");
|
||||
return;
|
||||
|
@ -91,9 +93,38 @@ public abstract class BaseDisassemblyListener {
|
|||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
} else {
|
||||
writer.write("(ref ");
|
||||
switch (refType.kind) {
|
||||
case ANY:
|
||||
writer.write("any");
|
||||
return;
|
||||
case FUNC:
|
||||
writer.write("func");
|
||||
return;
|
||||
case ARRAY:
|
||||
writer.write("array");
|
||||
return;
|
||||
case EXTERN:
|
||||
writer.write("extern");
|
||||
return;
|
||||
case STRUCT:
|
||||
writer.write("struct");
|
||||
return;
|
||||
case I31:
|
||||
writer.write("i31");
|
||||
return;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
} else if (type instanceof WasmHollowType.CompositeReference) {
|
||||
writer.write("(ref null ");
|
||||
writeTypeRef(((WasmHollowType.CompositeReference) type).index);
|
||||
var refType = (WasmHollowType.CompositeReference) type;
|
||||
writer.write("(ref ");
|
||||
if (refType.isNullable()) {
|
||||
writer.write("null");
|
||||
}
|
||||
writeTypeRef(refType.index);
|
||||
writer.write(")");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -755,23 +755,17 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void cast(WasmHollowType.Reference type, boolean nullable) {
|
||||
public void cast(WasmHollowType.Reference type) {
|
||||
writer.address().write("ref.cast (ref ");
|
||||
if (!nullable) {
|
||||
writer.write("null ");
|
||||
}
|
||||
writeType(type);
|
||||
writer.write(")").eol();
|
||||
writer.eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void test(WasmHollowType.Reference type, boolean nullable) {
|
||||
writer.address().write("ref.test (ref ");
|
||||
if (!nullable) {
|
||||
writer.write("null ");
|
||||
}
|
||||
public void test(WasmHollowType.Reference type) {
|
||||
writer.address().write("ref.test ");
|
||||
writeType(type);
|
||||
writer.write(")").eol();
|
||||
writer.eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -281,8 +281,9 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
}
|
||||
|
||||
var classStructure = classInfo.virtualTableStructure;
|
||||
classInfo.pointer = new WasmGlobal(pointerName, classStructure.getReference(),
|
||||
classInfo.pointer = new WasmGlobal(pointerName, classStructure.getNonNullReference(),
|
||||
new WasmStructNewDefault(classStructure));
|
||||
classInfo.pointer.setImmutable(true);
|
||||
module.globals.add(classInfo.pointer);
|
||||
if (type instanceof ValueType.Primitive) {
|
||||
initPrimitiveClass(classInfo, (ValueType.Primitive) type);
|
||||
|
@ -390,10 +391,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
if (cls != null && cls.getMethod(CLINIT_METHOD_DESC) != null) {
|
||||
var clinitType = functionTypes.of(null);
|
||||
var wasmName = names.topLevel(names.suggestForClass(name) + "@initializer");
|
||||
var initFunction = functionProvider.forStaticMethod(new MethodReference(name, CLINIT_METHOD_DESC));
|
||||
initFunction.setReferenced(true);
|
||||
var ref = new WasmFunctionReference(initFunction);
|
||||
classInfo.initializerPointer = new WasmGlobal(wasmName, clinitType.getReference(), ref);
|
||||
classInfo.initializerPointer = new WasmGlobal(wasmName, clinitType.getReference(),
|
||||
new WasmNullConstant(clinitType.getReference()));
|
||||
module.globals.add(classInfo.initializerPointer);
|
||||
}
|
||||
}
|
||||
|
@ -420,6 +419,11 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
if (virtualTable != null && virtualTable.isConcrete()) {
|
||||
fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable);
|
||||
}
|
||||
if (classInfo.initializerPointer != null) {
|
||||
var initFunction = functionProvider.forStaticMethod(new MethodReference(name, CLINIT_METHOD_DESC));
|
||||
initFunction.setReferenced(true);
|
||||
classInfo.initializerPointer.setInitialValue(new WasmFunctionReference(initFunction));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -490,7 +494,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
var objectLocal = new WasmLocal(standardClasses.objectClass().getType(), "object");
|
||||
function.add(objectLocal);
|
||||
|
||||
var castObject = new WasmCast(new WasmGetLocal(objectLocal), objectStructure.getReference());
|
||||
var castObject = new WasmCast(new WasmGetLocal(objectLocal), objectStructure.getNonNullReference());
|
||||
var arrayField = new WasmStructGet(objectStructure, castObject, ARRAY_DATA_FIELD_OFFSET);
|
||||
var result = new WasmArrayLength(arrayField);
|
||||
function.getBody().add(new WasmReturn(result));
|
||||
|
@ -521,7 +525,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
arrayGetObjectFunction.add(objectLocal);
|
||||
arrayGetObjectFunction.add(indexLocal);
|
||||
|
||||
var array = new WasmCast(new WasmGetLocal(objectLocal), arrayStruct.getReference());
|
||||
var array = new WasmCast(new WasmGetLocal(objectLocal), arrayStruct.getNonNullReference());
|
||||
var arrayData = new WasmStructGet(arrayStruct, array, ARRAY_DATA_FIELD_OFFSET);
|
||||
var result = new WasmArrayGet(arrayDataType, arrayData, new WasmGetLocal(indexLocal));
|
||||
arrayGetObjectFunction.getBody().add(new WasmReturn(result));
|
||||
|
@ -545,7 +549,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
function.add(objectLocal);
|
||||
function.add(indexLocal);
|
||||
|
||||
var array = new WasmCast(new WasmGetLocal(objectLocal), arrayStruct.getReference());
|
||||
var array = new WasmCast(new WasmGetLocal(objectLocal), arrayStruct.getNonNullReference());
|
||||
var arrayData = new WasmStructGet(arrayStruct, array, ARRAY_DATA_FIELD_OFFSET);
|
||||
var result = new WasmArrayGet(arrayDataType, arrayData, new WasmGetLocal(indexLocal));
|
||||
Class<?> primitiveType;
|
||||
|
@ -626,7 +630,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
var call = new WasmCall(function);
|
||||
var instanceParam = new WasmLocal(getClassInfo(virtualTable.getClassName()).getType());
|
||||
wrapperFunction.add(instanceParam);
|
||||
var castTarget = getClassInfo(implementor.getClassName()).getType();
|
||||
var castTarget = getClassInfo(implementor.getClassName()).getStructure().getNonNullReference();
|
||||
call.getArguments().add(new WasmCast(new WasmGetLocal(instanceParam), castTarget));
|
||||
var params = new WasmLocal[entry.getMethod().parameterCount()];
|
||||
for (var i = 0; i < entry.getMethod().parameterCount(); ++i) {
|
||||
|
@ -664,7 +668,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
function.add(dataCopyLocal);
|
||||
|
||||
function.getBody().add(new WasmSetLocal(originalLocal,
|
||||
new WasmCast(new WasmGetLocal(instanceLocal), objectStructure.getReference())));
|
||||
new WasmCast(new WasmGetLocal(instanceLocal), objectStructure.getNonNullReference())));
|
||||
function.getBody().add(new WasmSetLocal(resultLocal, new WasmStructNewDefault(objectStructure)));
|
||||
|
||||
var classValue = new WasmStructGet(objectStructure, new WasmGetLocal(originalLocal),
|
||||
|
|
|
@ -279,7 +279,7 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
var index = context.classInfoProvider().getVirtualMethodsOffset() + entry.getIndex();
|
||||
var expectedInstanceClassInfo = context.classInfoProvider().getClassInfo(vtable.getClassName());
|
||||
var vtableStruct = expectedInstanceClassInfo.getVirtualTableStructure();
|
||||
classRef = new WasmCast(classRef, vtableStruct.getReference());
|
||||
classRef = new WasmCast(classRef, vtableStruct.getNonNullReference());
|
||||
|
||||
var functionRef = new WasmStructGet(vtableStruct, classRef, index);
|
||||
var functionTypeRef = (WasmType.CompositeReference) vtableStruct.getFields().get(index).getUnpackedType();
|
||||
|
@ -288,7 +288,7 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
var instanceType = (WasmType.CompositeReference) instance.getType();
|
||||
var instanceStruct = (WasmStructure) instanceType.composite;
|
||||
if (!expectedInstanceClassInfo.getStructure().isSupertypeOf(instanceStruct)) {
|
||||
instanceRef = new WasmCast(instanceRef, expectedInstanceClassInfo.getType());
|
||||
instanceRef = new WasmCast(instanceRef, expectedInstanceClassInfo.getStructure().getNonNullReference());
|
||||
}
|
||||
|
||||
invoke.getArguments().add(instanceRef);
|
||||
|
@ -381,7 +381,7 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
WasmExpression exception = new WasmGetGlobal(context.exceptionGlobal());
|
||||
if (exceptionClass != null && !exceptionClass.equals("java.lang.Throwable")) {
|
||||
exception = new WasmCast(exception, context.classInfoProvider().getClassInfo(exceptionClass)
|
||||
.getStructure().getReference());
|
||||
.getStructure().getNonNullReference());
|
||||
}
|
||||
var save = new WasmSetLocal(local, exception);
|
||||
save.setLocation(location);
|
||||
|
|
|
@ -86,9 +86,10 @@ public class WasmGCStringPool implements WasmGCStringProvider, WasmGCInitializer
|
|||
var brief = string.length() > 16 ? string.substring(0, 16) : string;
|
||||
var globalName = names.topLevel("teavm@string<" + stringMap.size() + ">"
|
||||
+ WasmGCNameProvider.sanitize(brief));
|
||||
var globalType = standardClasses.stringClass().getType();
|
||||
var globalType = standardClasses.stringClass().getStructure().getNonNullReference();
|
||||
var global = new WasmGlobal(globalName, globalType,
|
||||
new WasmStructNewDefault(standardClasses.stringClass().getStructure()));
|
||||
global.setImmutable(true);
|
||||
module.globals.add(global);
|
||||
return new WasmGCStringConstant(stringMap.size(), global);
|
||||
});
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ArrayIntrinsic implements WasmGCIntrinsic {
|
|||
var object = context.exprCache().create(originalObject, objectStruct.getReference(),
|
||||
invocation.getLocation(), block.getBody());
|
||||
var classRef = new WasmStructGet(objectStruct, object.expr(), WasmGCClassInfoProvider.CLASS_FIELD_OFFSET);
|
||||
var vt = new WasmCast(classRef, vtStruct.getReference());
|
||||
var vt = new WasmCast(classRef, vtStruct.getNonNullReference());
|
||||
var function = new WasmStructGet(vtStruct, vt, offset);
|
||||
var call = new WasmCallReference(function, functionType);
|
||||
call.getArguments().add(object.expr());
|
||||
|
|
|
@ -66,8 +66,10 @@ public class ObjectIntrinsic implements WasmGCIntrinsic {
|
|||
}
|
||||
|
||||
private WasmExpression generateGetMonitor(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
var monitorType = context.classInfoProvider().getClassInfo(ValueType.object("java.lang.Object$Monitor"))
|
||||
.getStructure().getReference();
|
||||
var monitorStruct = context.classInfoProvider().getClassInfo(ValueType.object("java.lang.Object$Monitor"))
|
||||
.getStructure();
|
||||
var monitorType = monitorStruct.getReference();
|
||||
var monitorNotNullType = monitorStruct.getNonNullReference();
|
||||
var objectStruct = context.classInfoProvider().getClassInfo(ValueType.object("java.lang.Object"))
|
||||
.getStructure();
|
||||
var block = new WasmBlock(false);
|
||||
|
@ -77,13 +79,13 @@ public class ObjectIntrinsic implements WasmGCIntrinsic {
|
|||
block.getBody().add(new WasmSetLocal(tmpVar, new WasmStructGet(objectStruct, instance,
|
||||
WasmGCClassInfoProvider.MONITOR_FIELD_OFFSET)));
|
||||
|
||||
WasmExpression test = new WasmTest(new WasmGetLocal(tmpVar), monitorType, false);
|
||||
WasmExpression test = new WasmTest(new WasmGetLocal(tmpVar), monitorNotNullType);
|
||||
test = new WasmIntUnary(WasmIntType.INT32, WasmIntUnaryOperation.EQZ, test);
|
||||
var branch = new WasmBranch(test, block);
|
||||
branch.setResult(new WasmNullConstant(monitorType));
|
||||
block.getBody().add(new WasmDrop(branch));
|
||||
|
||||
block.getBody().add(new WasmCast(new WasmGetLocal(tmpVar), monitorType));
|
||||
block.getBody().add(new WasmCast(new WasmGetLocal(tmpVar), monitorNotNullType));
|
||||
context.tempVars().release(tmpVar);
|
||||
return block;
|
||||
}
|
||||
|
@ -106,13 +108,14 @@ public class ObjectIntrinsic implements WasmGCIntrinsic {
|
|||
block.getBody().add(new WasmSetLocal(tmpVar, new WasmStructGet(objectStruct, instance,
|
||||
WasmGCClassInfoProvider.MONITOR_FIELD_OFFSET)));
|
||||
|
||||
WasmExpression test = new WasmTest(new WasmGetLocal(tmpVar), WasmType.Reference.I31, false);
|
||||
WasmExpression test = new WasmTest(new WasmGetLocal(tmpVar),
|
||||
WasmType.SpecialReferenceKind.I31.asNonNullType());
|
||||
test = new WasmIntUnary(WasmIntType.INT32, WasmIntUnaryOperation.EQZ, test);
|
||||
var branch = new WasmBranch(test, block);
|
||||
branch.setResult(new WasmInt32Constant(-1));
|
||||
block.getBody().add(new WasmDrop(branch));
|
||||
|
||||
var i31ref = new WasmCast(new WasmGetLocal(tmpVar), WasmType.Reference.I31);
|
||||
var i31ref = new WasmCast(new WasmGetLocal(tmpVar), WasmType.SpecialReferenceKind.I31.asNonNullType());
|
||||
block.getBody().add(new WasmInt31Get(i31ref, WasmSignedType.UNSIGNED));
|
||||
context.tempVars().release(tmpVar);
|
||||
return block;
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.backend.wasm.model;
|
|||
public abstract class WasmCompositeType extends WasmEntity {
|
||||
private String name;
|
||||
private WasmType.CompositeReference reference;
|
||||
private WasmType.CompositeReference nonNullReference;
|
||||
int recursiveTypeCount = -1;
|
||||
|
||||
WasmCompositeType(String name) {
|
||||
|
@ -30,11 +31,18 @@ public abstract class WasmCompositeType extends WasmEntity {
|
|||
|
||||
public WasmType.CompositeReference getReference() {
|
||||
if (reference == null) {
|
||||
reference = new WasmType.CompositeReference(this);
|
||||
reference = new WasmType.CompositeReference(this, true);
|
||||
}
|
||||
return reference;
|
||||
}
|
||||
|
||||
public WasmType.CompositeReference getNonNullReference() {
|
||||
if (nonNullReference == null) {
|
||||
nonNullReference = new WasmType.CompositeReference(this, false);
|
||||
}
|
||||
return nonNullReference;
|
||||
}
|
||||
|
||||
public int getRecursiveTypeCount() {
|
||||
return recursiveTypeCount;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ public class WasmGlobal extends WasmEntity {
|
|||
private String name;
|
||||
private WasmType type;
|
||||
private WasmExpression initialValue;
|
||||
private boolean immutable;
|
||||
|
||||
public WasmGlobal(String name, WasmType type, WasmExpression initialValue) {
|
||||
this.name = name;
|
||||
|
@ -48,4 +49,12 @@ public class WasmGlobal extends WasmEntity {
|
|||
public void setInitialValue(WasmExpression initialValue) {
|
||||
this.initialValue = Objects.requireNonNull(initialValue);
|
||||
}
|
||||
|
||||
public boolean isImmutable() {
|
||||
return immutable;
|
||||
}
|
||||
|
||||
public void setImmutable(boolean immutable) {
|
||||
this.immutable = immutable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,12 +63,23 @@ public abstract class WasmType {
|
|||
public static final SpecialReference STRUCT = SpecialReferenceKind.STRUCT.asType();
|
||||
public static final SpecialReference ARRAY = SpecialReferenceKind.ARRAY.asType();
|
||||
public static final SpecialReference I31 = SpecialReferenceKind.I31.asType();
|
||||
|
||||
private final boolean nullable;
|
||||
|
||||
public Reference(boolean nullable) {
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class CompositeReference extends Reference {
|
||||
public final WasmCompositeType composite;
|
||||
|
||||
CompositeReference(WasmCompositeType composite) {
|
||||
CompositeReference(WasmCompositeType composite, boolean nullable) {
|
||||
super(nullable);
|
||||
this.composite = composite;
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +87,8 @@ public abstract class WasmType {
|
|||
public static final class SpecialReference extends Reference {
|
||||
public final SpecialReferenceKind kind;
|
||||
|
||||
private SpecialReference(SpecialReferenceKind kind) {
|
||||
private SpecialReference(SpecialReferenceKind kind, boolean nullable) {
|
||||
super(nullable);
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
|
@ -90,12 +102,20 @@ public abstract class WasmType {
|
|||
I31;
|
||||
|
||||
private SpecialReference type;
|
||||
private SpecialReference nonNullType;
|
||||
|
||||
final SpecialReference asType() {
|
||||
public final SpecialReference asType() {
|
||||
if (type == null) {
|
||||
type = new SpecialReference(this);
|
||||
type = new SpecialReference(this, true);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public final SpecialReference asNonNullType() {
|
||||
if (nonNullType == null) {
|
||||
nonNullType = new SpecialReference(this, false);
|
||||
}
|
||||
return nonNullType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,16 +21,10 @@ import org.teavm.backend.wasm.model.WasmType;
|
|||
public class WasmCast extends WasmExpression {
|
||||
private WasmExpression value;
|
||||
private WasmType.Reference targetType;
|
||||
private boolean nullable;
|
||||
|
||||
public WasmCast(WasmExpression value, WasmType.Reference targetType) {
|
||||
this(value, targetType, true);
|
||||
}
|
||||
|
||||
public WasmCast(WasmExpression value, WasmType.Reference targetType, boolean nullable) {
|
||||
this.value = Objects.requireNonNull(value);
|
||||
this.targetType = Objects.requireNonNull(targetType);
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
public WasmExpression getValue() {
|
||||
|
@ -49,14 +43,6 @@ public class WasmCast extends WasmExpression {
|
|||
this.targetType = Objects.requireNonNull(targetType);
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
public void setNullable(boolean nullable) {
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
|
|
|
@ -21,16 +21,10 @@ import org.teavm.backend.wasm.model.WasmType;
|
|||
public class WasmTest extends WasmExpression {
|
||||
private WasmExpression value;
|
||||
private WasmType.Reference testType;
|
||||
private boolean nullable;
|
||||
|
||||
public WasmTest(WasmExpression value, WasmType.Reference testType) {
|
||||
this(value, testType, true);
|
||||
}
|
||||
|
||||
public WasmTest(WasmExpression value, WasmType.Reference testType, boolean nullable) {
|
||||
this.value = Objects.requireNonNull(value);
|
||||
this.testType = Objects.requireNonNull(testType);
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
public WasmExpression getValue() {
|
||||
|
@ -49,13 +43,6 @@ public class WasmTest extends WasmExpression {
|
|||
this.testType = Objects.requireNonNull(testType);
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
public void setNullable(boolean nullable) {
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||
|
|
|
@ -135,10 +135,10 @@ public interface CodeListener {
|
|||
default void nullConstant(WasmHollowType.Reference type) {
|
||||
}
|
||||
|
||||
default void cast(WasmHollowType.Reference type, boolean nullable) {
|
||||
default void cast(WasmHollowType.Reference type) {
|
||||
}
|
||||
|
||||
default void test(WasmHollowType.Reference type, boolean nullable) {
|
||||
default void test(WasmHollowType.Reference type) {
|
||||
}
|
||||
|
||||
default void structNew(int typeIndex) {
|
||||
|
|
|
@ -589,7 +589,7 @@ public class CodeParser extends BaseSectionParser {
|
|||
break;
|
||||
|
||||
case 0xD0:
|
||||
codeListener.nullConstant(reader.readHeapType());
|
||||
codeListener.nullConstant(reader.readHeapType(true));
|
||||
break;
|
||||
|
||||
case 0xD2:
|
||||
|
@ -684,19 +684,19 @@ public class CodeParser extends BaseSectionParser {
|
|||
return true;
|
||||
|
||||
case 20:
|
||||
codeListener.test(reader.readHeapType(), false);
|
||||
codeListener.test(reader.readHeapType(false));
|
||||
return true;
|
||||
|
||||
case 21:
|
||||
codeListener.test(reader.readHeapType(), true);
|
||||
codeListener.test(reader.readHeapType(true));
|
||||
return true;
|
||||
|
||||
case 22:
|
||||
codeListener.cast(reader.readHeapType(), false);
|
||||
codeListener.cast(reader.readHeapType(false));
|
||||
return true;
|
||||
|
||||
case 23:
|
||||
codeListener.cast(reader.readHeapType(), true);
|
||||
codeListener.cast(reader.readHeapType(true));
|
||||
return true;
|
||||
|
||||
case 28:
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.backend.wasm.parser;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
|
||||
public class WasmBinaryReader {
|
||||
private final AddressListener addressListener;
|
||||
|
@ -63,43 +64,51 @@ public class WasmBinaryReader {
|
|||
case 0x7C:
|
||||
return WasmHollowType.FLOAT64;
|
||||
case 0x63:
|
||||
return readHeapType();
|
||||
return readHeapType(true);
|
||||
case 0x64:
|
||||
return readHeapType(false);
|
||||
case 0x40:
|
||||
return null;
|
||||
default:
|
||||
return readAbsHeapType(typeId);
|
||||
return readAbsHeapType(typeId, true);
|
||||
}
|
||||
}
|
||||
|
||||
public WasmHollowType.Reference readHeapType() {
|
||||
public WasmHollowType.Reference readHeapType(boolean nullable) {
|
||||
var typeId = data[ptr];
|
||||
if ((typeId & 0xC0) == 0x40) {
|
||||
var result = readAbsHeapType(typeId);
|
||||
var result = readAbsHeapType(typeId, nullable);
|
||||
++ptr;
|
||||
return result;
|
||||
}
|
||||
return new WasmHollowType.CompositeReference(readLEB());
|
||||
return new WasmHollowType.CompositeReference(readLEB(), nullable);
|
||||
}
|
||||
|
||||
public WasmHollowType.SpecialReference readAbsHeapType(int typeId) {
|
||||
public WasmHollowType.SpecialReference readAbsHeapType(int typeId, boolean nullable) {
|
||||
switch (typeId) {
|
||||
case 0x70:
|
||||
return WasmHollowType.Reference.FUNC;
|
||||
return special(WasmType.SpecialReferenceKind.FUNC, nullable);
|
||||
case 0x6F:
|
||||
return WasmHollowType.Reference.EXTERN;
|
||||
return special(WasmType.SpecialReferenceKind.EXTERN, nullable);
|
||||
case 0x6E:
|
||||
return WasmHollowType.Reference.ANY;
|
||||
return special(WasmType.SpecialReferenceKind.ANY, nullable);
|
||||
case 0x6C:
|
||||
return WasmHollowType.Reference.I31;
|
||||
return special(WasmType.SpecialReferenceKind.I31, nullable);
|
||||
case 0x6B:
|
||||
return WasmHollowType.Reference.STRUCT;
|
||||
return special(WasmType.SpecialReferenceKind.STRUCT, nullable);
|
||||
case 0x6A:
|
||||
return WasmHollowType.Reference.ARRAY;
|
||||
return special(WasmType.SpecialReferenceKind.ARRAY, nullable);
|
||||
default:
|
||||
throw new ParseException("Unknown type", ptr);
|
||||
}
|
||||
}
|
||||
|
||||
private static WasmHollowType.SpecialReference special(WasmType.SpecialReferenceKind kind, boolean nullable) {
|
||||
return nullable
|
||||
? WasmHollowType.Reference.special(kind)
|
||||
: WasmHollowType.SpecialReference.nonNullSpecial(kind);
|
||||
}
|
||||
|
||||
public int readSignedLEB() {
|
||||
var result = 0;
|
||||
var shift = 0;
|
||||
|
|
|
@ -17,7 +17,6 @@ package org.teavm.backend.wasm.parser;
|
|||
|
||||
import java.util.Objects;
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.WasmStorageType;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
|
||||
public class WasmHollowType {
|
||||
|
@ -26,8 +25,6 @@ public class WasmHollowType {
|
|||
public static final Number FLOAT32 = new Number(WasmNumType.FLOAT32);
|
||||
public static final Number FLOAT64 = new Number(WasmNumType.FLOAT64);
|
||||
|
||||
private WasmStorageType.Regular storageType;
|
||||
|
||||
private WasmHollowType() {
|
||||
}
|
||||
|
||||
|
@ -56,18 +53,45 @@ public class WasmHollowType {
|
|||
|
||||
|
||||
public static abstract class Reference extends WasmHollowType {
|
||||
public static final SpecialReference FUNC = new SpecialReference(WasmType.SpecialReferenceKind.FUNC);
|
||||
public static final SpecialReference ANY = new SpecialReference(WasmType.SpecialReferenceKind.ANY);
|
||||
public static final SpecialReference EXTERN = new SpecialReference(WasmType.SpecialReferenceKind.EXTERN);
|
||||
public static final SpecialReference STRUCT = new SpecialReference(WasmType.SpecialReferenceKind.STRUCT);
|
||||
public static final SpecialReference ARRAY = new SpecialReference(WasmType.SpecialReferenceKind.ARRAY);
|
||||
public static final SpecialReference I31 = new SpecialReference(WasmType.SpecialReferenceKind.I31);
|
||||
private static final SpecialReference[] references = new SpecialReference[
|
||||
WasmType.SpecialReferenceKind.values().length];
|
||||
private static final SpecialReference[] nonNullReferences = new SpecialReference[
|
||||
WasmType.SpecialReferenceKind.values().length];
|
||||
|
||||
private final boolean nullable;
|
||||
|
||||
public Reference(boolean nullable) {
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
public static SpecialReference special(WasmType.SpecialReferenceKind kind) {
|
||||
var result = references[kind.ordinal()];
|
||||
if (result == null) {
|
||||
result = new SpecialReference(kind, true);
|
||||
references[kind.ordinal()] = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SpecialReference nonNullSpecial(WasmType.SpecialReferenceKind kind) {
|
||||
var result = nonNullReferences[kind.ordinal()];
|
||||
if (result == null) {
|
||||
result = new SpecialReference(kind, false);
|
||||
nonNullReferences[kind.ordinal()] = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class CompositeReference extends WasmHollowType.Reference {
|
||||
public final int index;
|
||||
|
||||
public CompositeReference(int index) {
|
||||
public CompositeReference(int index, boolean nullable) {
|
||||
super(nullable);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
|
@ -80,19 +104,20 @@ public class WasmHollowType {
|
|||
return false;
|
||||
}
|
||||
CompositeReference that = (CompositeReference) o;
|
||||
return index == that.index;
|
||||
return index == that.index && isNullable() == that.isNullable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(index);
|
||||
return Objects.hash(index, isNullable());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SpecialReference extends WasmHollowType.Reference {
|
||||
public final WasmType.SpecialReferenceKind kind;
|
||||
|
||||
SpecialReference(WasmType.SpecialReferenceKind kind) {
|
||||
SpecialReference(WasmType.SpecialReferenceKind kind, boolean nullable) {
|
||||
super(nullable);
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ public class WasmBinaryRenderer {
|
|||
section.writeLEB(module.globals.size());
|
||||
for (var global : module.globals) {
|
||||
section.writeType(global.getType(), module);
|
||||
section.writeByte(1); // mutable
|
||||
section.writeByte(global.isImmutable() ? 0 : 1); // mutable
|
||||
global.getInitialValue().acceptVisitor(visitor);
|
||||
section.writeByte(0x0b);
|
||||
}
|
||||
|
|
|
@ -1075,7 +1075,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
|||
pushLocation(expression);
|
||||
expression.getValue().acceptVisitor(this);
|
||||
writer.writeByte(0xfb);
|
||||
writer.writeByte(expression.isNullable() ? 23 : 22);
|
||||
writer.writeByte(expression.getTargetType().isNullable() ? 23 : 22);
|
||||
writer.writeHeapType(expression.getTargetType(), module);
|
||||
popLocation();
|
||||
}
|
||||
|
@ -1085,7 +1085,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
|||
pushLocation(expression);
|
||||
expression.getValue().acceptVisitor(this);
|
||||
writer.writeByte(0xfb);
|
||||
writer.writeByte(expression.isNullable() ? 21 : 20);
|
||||
writer.writeByte(expression.getTestType().isNullable() ? 21 : 20);
|
||||
writer.writeHeapType(expression.getTestType(), module);
|
||||
popLocation();
|
||||
}
|
||||
|
|
|
@ -37,11 +37,15 @@ public class WasmBinaryWriter {
|
|||
if (type instanceof WasmType.Number) {
|
||||
writeType(((WasmType.Number) type).number);
|
||||
} else if (type instanceof WasmType.SpecialReference) {
|
||||
writeSpecialHeapType(((WasmType.SpecialReference) type).kind);
|
||||
var refType = (WasmType.SpecialReference) type;
|
||||
if (!refType.isNullable()) {
|
||||
writeByte(0x64);
|
||||
}
|
||||
writeSpecialHeapType(refType.kind);
|
||||
} else if (type instanceof WasmType.CompositeReference) {
|
||||
writeByte(0x63);
|
||||
var composite = ((WasmType.CompositeReference) type).composite;
|
||||
var index = module.types.indexOf(composite);
|
||||
var refType = (WasmType.CompositeReference) type;
|
||||
writeByte(refType.isNullable() ? 0x63 : 0x64);
|
||||
var index = module.types.indexOf(refType.composite);
|
||||
writeSignedLEB(index);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user