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