mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: draft first parts of Wasm GC backend
* class metadata generator * string pool generator
This commit is contained in:
parent
efcb22b639
commit
7efb3c97a0
|
@ -73,6 +73,7 @@ import org.teavm.model.instructions.IsInstanceInstruction;
|
||||||
import org.teavm.model.instructions.StringConstantInstruction;
|
import org.teavm.model.instructions.StringConstantInstruction;
|
||||||
import org.teavm.model.lowlevel.CallSiteDescriptor;
|
import org.teavm.model.lowlevel.CallSiteDescriptor;
|
||||||
import org.teavm.model.lowlevel.Characteristics;
|
import org.teavm.model.lowlevel.Characteristics;
|
||||||
|
import org.teavm.model.util.ReflectionUtil;
|
||||||
import org.teavm.runtime.CallSite;
|
import org.teavm.runtime.CallSite;
|
||||||
import org.teavm.runtime.RuntimeArray;
|
import org.teavm.runtime.RuntimeArray;
|
||||||
import org.teavm.runtime.RuntimeClass;
|
import org.teavm.runtime.RuntimeClass;
|
||||||
|
@ -1295,26 +1296,7 @@ public class ClassGenerator {
|
||||||
|
|
||||||
public String nameOfType(ValueType type) {
|
public String nameOfType(ValueType type) {
|
||||||
if (type instanceof ValueType.Primitive) {
|
if (type instanceof ValueType.Primitive) {
|
||||||
switch (((ValueType.Primitive) type).getKind()) {
|
return ReflectionUtil.typeName(((ValueType.Primitive) type).getKind());
|
||||||
case BOOLEAN:
|
|
||||||
return "boolean";
|
|
||||||
case BYTE:
|
|
||||||
return "byte";
|
|
||||||
case SHORT:
|
|
||||||
return "short";
|
|
||||||
case CHARACTER:
|
|
||||||
return "char";
|
|
||||||
case INTEGER:
|
|
||||||
return "int";
|
|
||||||
case LONG:
|
|
||||||
return "long";
|
|
||||||
case FLOAT:
|
|
||||||
return "float";
|
|
||||||
case DOUBLE:
|
|
||||||
return "double";
|
|
||||||
default:
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
} else if (type instanceof ValueType.Array) {
|
} else if (type instanceof ValueType.Array) {
|
||||||
if (isArrayOfPrimitives(type)) {
|
if (isArrayOfPrimitives(type)) {
|
||||||
return type.toString().replace('/', '.');
|
return type.toString().replace('/', '.');
|
||||||
|
|
|
@ -55,6 +55,7 @@ import org.teavm.model.classes.VirtualTable;
|
||||||
import org.teavm.model.classes.VirtualTableEntry;
|
import org.teavm.model.classes.VirtualTableEntry;
|
||||||
import org.teavm.model.classes.VirtualTableProvider;
|
import org.teavm.model.classes.VirtualTableProvider;
|
||||||
import org.teavm.model.lowlevel.Characteristics;
|
import org.teavm.model.lowlevel.Characteristics;
|
||||||
|
import org.teavm.model.util.ReflectionUtil;
|
||||||
import org.teavm.runtime.RuntimeClass;
|
import org.teavm.runtime.RuntimeClass;
|
||||||
import org.teavm.runtime.RuntimeObject;
|
import org.teavm.runtime.RuntimeObject;
|
||||||
|
|
||||||
|
@ -250,34 +251,7 @@ public class WasmClassGenerator {
|
||||||
if (type == ValueType.VOID) {
|
if (type == ValueType.VOID) {
|
||||||
name = "void";
|
name = "void";
|
||||||
} else {
|
} else {
|
||||||
switch (((ValueType.Primitive) type).getKind()) {
|
name = ReflectionUtil.typeName(((ValueType.Primitive) type).getKind());
|
||||||
case BOOLEAN:
|
|
||||||
name = "boolean";
|
|
||||||
break;
|
|
||||||
case BYTE:
|
|
||||||
name = "byte";
|
|
||||||
break;
|
|
||||||
case SHORT:
|
|
||||||
name = "short";
|
|
||||||
break;
|
|
||||||
case CHARACTER:
|
|
||||||
name = "char";
|
|
||||||
break;
|
|
||||||
case INTEGER:
|
|
||||||
name = "int";
|
|
||||||
break;
|
|
||||||
case LONG:
|
|
||||||
name = "long";
|
|
||||||
break;
|
|
||||||
case FLOAT:
|
|
||||||
name = "float";
|
|
||||||
break;
|
|
||||||
case DOUBLE:
|
|
||||||
name = "double";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
name = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value.setAddress(CLASS_NAME, stringPool.getStringPointer(name));
|
value.setAddress(CLASS_NAME, stringPool.getStringPointer(name));
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.classes;
|
||||||
|
|
||||||
|
public final class WasmGCClassFlags {
|
||||||
|
public static final int ABSTRACT = 1;
|
||||||
|
public static final int INTERFACE = 1 << 1;
|
||||||
|
public static final int FINAL = 1 << 2;
|
||||||
|
public static final int ENUM = 1 << 3;
|
||||||
|
public static final int ANNOTATION = 1 << 4;
|
||||||
|
public static final int SYNTHETIC = 1 << 5;
|
||||||
|
public static final int BRIDGE = 1 << 6;
|
||||||
|
public static final int DEPRECATED = 1 << 7;
|
||||||
|
public static final int NATIVE = 1 << 8;
|
||||||
|
public static final int STATIC = 1 << 9;
|
||||||
|
public static final int STRICT = 1 << 10;
|
||||||
|
public static final int SYNCHRONIZED = 1 << 11;
|
||||||
|
public static final int TRANSIENT = 1 << 12;
|
||||||
|
public static final int VARARGS = 1 << 13;
|
||||||
|
public static final int VOLATILE = 1 << 14;
|
||||||
|
public static final int PRIMITIVE = 1 << 15;
|
||||||
|
|
||||||
|
public static final int PRIMITIVE_KIND_SHIFT = 16;
|
||||||
|
public static final int PRIMITIVE_BOOLEAN = 0;
|
||||||
|
public static final int PRIMITIVE_BYTE = 1;
|
||||||
|
public static final int PRIMITIVE_SHORT = 2;
|
||||||
|
public static final int PRIMITIVE_CHAR = 3;
|
||||||
|
public static final int PRIMITIVE_INT = 4;
|
||||||
|
public static final int PRIMITIVE_LONG = 5;
|
||||||
|
public static final int PRIMITIVE_FLOAT = 6;
|
||||||
|
public static final int PRIMITIVE_DOUBLE = 7;
|
||||||
|
public static final int PRIMITIVE_VOID = 8;
|
||||||
|
|
||||||
|
private WasmGCClassFlags() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,538 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.classes;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||||
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.backend.lowlevel.generate.NameProvider;
|
||||||
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.initialization.WasmGCInitializerContributor;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.method.WasmGCFunctionProvider;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringPool;
|
||||||
|
import org.teavm.backend.wasm.model.WasmArray;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunctionType;
|
||||||
|
import org.teavm.backend.wasm.model.WasmGlobal;
|
||||||
|
import org.teavm.backend.wasm.model.WasmLocal;
|
||||||
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
|
import org.teavm.backend.wasm.model.WasmStorageType;
|
||||||
|
import org.teavm.backend.wasm.model.WasmStructure;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.ElementModifier;
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.analysis.ClassMetadataRequirements;
|
||||||
|
import org.teavm.model.classes.TagRegistry;
|
||||||
|
import org.teavm.model.classes.VirtualTable;
|
||||||
|
import org.teavm.model.classes.VirtualTableProvider;
|
||||||
|
import org.teavm.model.util.ReflectionUtil;
|
||||||
|
|
||||||
|
public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInitializerContributor {
|
||||||
|
public static final int CLASS_FIELD_OFFSET = 0;
|
||||||
|
|
||||||
|
private final WasmModule module;
|
||||||
|
private ClassReaderSource classSource;
|
||||||
|
private WasmFunctionTypes functionTypes;
|
||||||
|
private TagRegistry tagRegistry;
|
||||||
|
private ClassMetadataRequirements metadataRequirements;
|
||||||
|
private VirtualTableProvider virtualTables;
|
||||||
|
private WasmGCFunctionProvider functionProvider;
|
||||||
|
private Map<ValueType, WasmGCClassInfo> classInfoMap = new LinkedHashMap<>();
|
||||||
|
private ObjectIntMap<FieldReference> fieldIndexes = new ObjectIntHashMap<>();
|
||||||
|
private ObjectIntMap<MethodReference> methodIndexes = new ObjectIntHashMap<>();
|
||||||
|
|
||||||
|
public final WasmGCStringPool strings;
|
||||||
|
public final WasmGCStandardClasses standardClasses;
|
||||||
|
private final WasmGCTypeMapper typeMapper;
|
||||||
|
private final NameProvider names;
|
||||||
|
private WasmFunction initializer;
|
||||||
|
private WasmFunction createPrimitiveClassFunction;
|
||||||
|
private WasmFunction createArrayClassFunction;
|
||||||
|
private final WasmGCSupertypeFunctionGenerator supertypeGenerator;
|
||||||
|
|
||||||
|
private int classTagOffset;
|
||||||
|
private int classFlagsOffset;
|
||||||
|
private int classNameOffset;
|
||||||
|
private int classParentOffset;
|
||||||
|
private int classArrayOffset;
|
||||||
|
private int classArrayItemOffset;
|
||||||
|
private int classSupertypeFunctionOffset;
|
||||||
|
private int virtualTableFieldOffset;
|
||||||
|
|
||||||
|
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
|
||||||
|
WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
|
||||||
|
ClassMetadataRequirements metadataRequirements, VirtualTableProvider virtualTables,
|
||||||
|
WasmGCFunctionProvider functionProvider, NameProvider names) {
|
||||||
|
this.module = module;
|
||||||
|
this.classSource = classSource;
|
||||||
|
this.functionTypes = functionTypes;
|
||||||
|
this.tagRegistry = tagRegistry;
|
||||||
|
this.metadataRequirements = metadataRequirements;
|
||||||
|
this.virtualTables = virtualTables;
|
||||||
|
this.functionProvider = functionProvider;
|
||||||
|
this.names = names;
|
||||||
|
standardClasses = new WasmGCStandardClasses(this);
|
||||||
|
strings = new WasmGCStringPool(standardClasses, module, functionProvider);
|
||||||
|
supertypeGenerator = new WasmGCSupertypeFunctionGenerator(module, this, names, tagRegistry, functionTypes);
|
||||||
|
typeMapper = new WasmGCTypeMapper(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contributeToInitializerDefinitions(WasmFunction function) {
|
||||||
|
for (var classInfo : classInfoMap.values()) {
|
||||||
|
var newStruct = new WasmStructNewDefault(standardClasses.classClass().getStructure());
|
||||||
|
function.getBody().add(new WasmSetGlobal(classInfo.pointer, newStruct));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contributeToInitializer(WasmFunction function) {
|
||||||
|
var classClass = standardClasses.classClass();
|
||||||
|
for (var classInfo : classInfoMap.values()) {
|
||||||
|
classInfo.initializer.accept(function.getBody());
|
||||||
|
var supertypeFunction = supertypeGenerator.getIsSupertypeFunction(classInfo.getValueType());
|
||||||
|
function.getBody().add(setClassField(classInfo, classSupertypeFunctionOffset,
|
||||||
|
new WasmFunctionReference(supertypeFunction)));
|
||||||
|
function.getBody().add(setClassField(classInfo, CLASS_FIELD_OFFSET,
|
||||||
|
new WasmGetGlobal(classClass.pointer)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WasmGCClassInfo getClassInfo(ValueType type) {
|
||||||
|
var classInfo = classInfoMap.get(type);
|
||||||
|
if (classInfo == null) {
|
||||||
|
classInfo = new WasmGCClassInfo(type);
|
||||||
|
classInfoMap.put(type, classInfo);
|
||||||
|
if (!(type instanceof ValueType.Primitive)) {
|
||||||
|
var name = type instanceof ValueType.Object
|
||||||
|
? ((ValueType.Object) type).getClassName()
|
||||||
|
: null;
|
||||||
|
classInfo.structure = new WasmStructure(name);
|
||||||
|
classInfo.structure.getFields().add(standardClasses.classClass().getType().asStorage());
|
||||||
|
fillFields(classInfo.structure.getFields(), type);
|
||||||
|
}
|
||||||
|
var pointerName = names.forClassInstance(type);
|
||||||
|
var classStructure = type instanceof ValueType.Object
|
||||||
|
? initRegularClassStructure(((ValueType.Object) type).getClassName())
|
||||||
|
: standardClasses.classClass().getStructure();
|
||||||
|
classInfo.virtualTableStructure = classStructure;
|
||||||
|
classInfo.pointer = new WasmGlobal(pointerName, classStructure.getReference(),
|
||||||
|
new WasmNullConstant(classStructure.getReference()));
|
||||||
|
module.globals.add(classInfo.pointer);
|
||||||
|
if (type instanceof ValueType.Primitive) {
|
||||||
|
initPrimitiveClass(classInfo, (ValueType.Primitive) type);
|
||||||
|
} else if (type instanceof ValueType.Void) {
|
||||||
|
initVoidClass(classInfo);
|
||||||
|
} else if (type instanceof ValueType.Array) {
|
||||||
|
initArrayClass(classInfo, (ValueType.Array) type);
|
||||||
|
} else if (type instanceof ValueType.Object) {
|
||||||
|
initRegularClass(classInfo, classStructure, ((ValueType.Object) type).getClassName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return classInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getClassTagOffset() {
|
||||||
|
return classTagOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getClassArrayItemOffset() {
|
||||||
|
return classArrayItemOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPrimitiveClass(WasmGCClassInfo classInfo, ValueType.Primitive type) {
|
||||||
|
classInfo.initializer = target -> {
|
||||||
|
int kind;
|
||||||
|
switch (type.getKind()) {
|
||||||
|
case BOOLEAN:
|
||||||
|
kind = WasmGCClassFlags.PRIMITIVE_BOOLEAN;
|
||||||
|
break;
|
||||||
|
case BYTE:
|
||||||
|
kind = WasmGCClassFlags.PRIMITIVE_BYTE;
|
||||||
|
break;
|
||||||
|
case SHORT:
|
||||||
|
kind = WasmGCClassFlags.PRIMITIVE_SHORT;
|
||||||
|
break;
|
||||||
|
case CHARACTER:
|
||||||
|
kind = WasmGCClassFlags.PRIMITIVE_CHAR;
|
||||||
|
break;
|
||||||
|
case INTEGER:
|
||||||
|
kind = WasmGCClassFlags.PRIMITIVE_INT;
|
||||||
|
break;
|
||||||
|
case LONG:
|
||||||
|
kind = WasmGCClassFlags.PRIMITIVE_LONG;
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
kind = WasmGCClassFlags.PRIMITIVE_FLOAT;
|
||||||
|
break;
|
||||||
|
case DOUBLE:
|
||||||
|
kind = WasmGCClassFlags.PRIMITIVE_DOUBLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
target.add(fillPrimitiveClass(
|
||||||
|
classInfo.pointer,
|
||||||
|
ReflectionUtil.typeName(type.getKind()),
|
||||||
|
kind
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initVoidClass(WasmGCClassInfo classInfo) {
|
||||||
|
classInfo.initializer = target -> {
|
||||||
|
target.add(fillPrimitiveClass(
|
||||||
|
classInfo.pointer,
|
||||||
|
"void",
|
||||||
|
WasmGCClassFlags.PRIMITIVE_VOID
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initRegularClass(WasmGCClassInfo classInfo, WasmStructure classStructure, String name) {
|
||||||
|
classInfo.initializer = target -> {
|
||||||
|
var ranges = tagRegistry.getRanges(name);
|
||||||
|
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
|
||||||
|
target.add(setClassField(classInfo, classTagOffset, new WasmInt32Constant(tag)));
|
||||||
|
var metadataReg = metadataRequirements.getInfo(name);
|
||||||
|
if (metadataReg.name()) {
|
||||||
|
var namePtr = strings.getStringConstant(name).global;
|
||||||
|
target.add(setClassField(classInfo, classNameOffset, new WasmGetGlobal(namePtr)));
|
||||||
|
}
|
||||||
|
var cls = classSource.get(name);
|
||||||
|
if (cls != null) {
|
||||||
|
if (metadataReg.simpleName() && cls.getSimpleName() != null) {
|
||||||
|
var namePtr = strings.getStringConstant(cls.getSimpleName()).global;
|
||||||
|
target.add(setClassField(classInfo, classNameOffset, new WasmGetGlobal(namePtr)));
|
||||||
|
}
|
||||||
|
if (cls.getParent() != null) {
|
||||||
|
var parent = getClassInfo(cls.getParent());
|
||||||
|
target.add(setClassField(classInfo, classParentOffset, new WasmGetGlobal(parent.pointer)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var virtualTable = virtualTables.lookup(name);
|
||||||
|
fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable, virtualTableFieldOffset,
|
||||||
|
name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private int fillVirtualTableMethods(List<WasmExpression> target, WasmStructure structure, WasmGlobal global,
|
||||||
|
VirtualTable virtualTable, int index, String origin) {
|
||||||
|
if (virtualTable.getParent() != null) {
|
||||||
|
index = fillVirtualTableMethods(target, structure, global, virtualTable.getParent(), index, origin);
|
||||||
|
}
|
||||||
|
for (var method : virtualTable.getMethods()) {
|
||||||
|
var entry = virtualTable.getEntry(method);
|
||||||
|
if (entry != null && entry.getImplementor() != null) {
|
||||||
|
var function = functionProvider.getMemberFunction(entry.getImplementor());
|
||||||
|
if (!origin.equals(entry.getImplementor().getClassName())) {
|
||||||
|
var functionType = getFunctionType(virtualTable.getClassName(), method);
|
||||||
|
var wrapperFunction = new WasmFunction(functionType);
|
||||||
|
module.functions.add(wrapperFunction);
|
||||||
|
var call = new WasmCall(function);
|
||||||
|
var instanceParam = new WasmLocal(getClassInfo(virtualTable.getClassName()).getType());
|
||||||
|
wrapperFunction.getLocalVariables().add(instanceParam);
|
||||||
|
var castTarget = getClassInfo(entry.getImplementor().getClassName()).getType();
|
||||||
|
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());
|
||||||
|
call.getArguments().add(new WasmGetLocal(params[i]));
|
||||||
|
}
|
||||||
|
wrapperFunction.getLocalVariables().addAll(List.of(params));
|
||||||
|
}
|
||||||
|
var ref = new WasmFunctionReference(function);
|
||||||
|
target.add(new WasmStructSet(structure, new WasmGetGlobal(global), index, ref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmStructure initRegularClassStructure(String className) {
|
||||||
|
var virtualTable = virtualTables.lookup(className);
|
||||||
|
var structure = new WasmStructure(names.forClassClass(className));
|
||||||
|
module.types.add(structure);
|
||||||
|
addVirtualTableFields(structure, virtualTable);
|
||||||
|
fillClassFields(structure.getFields(), "java.lang.Class");
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addVirtualTableFields(WasmStructure structure, VirtualTable virtualTable) {
|
||||||
|
if (virtualTable.getParent() != null) {
|
||||||
|
addVirtualTableFields(structure, virtualTable.getParent());
|
||||||
|
}
|
||||||
|
for (var methodDesc : virtualTable.getMethods()) {
|
||||||
|
var functionType = getFunctionType(virtualTable.getClassName(), methodDesc);
|
||||||
|
var methodRef = new MethodReference(virtualTable.getClassName(), methodDesc);
|
||||||
|
methodIndexes.put(methodRef, structure.getFields().size());
|
||||||
|
structure.getFields().add(functionType.getReference().asStorage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmFunctionType getFunctionType(String className, MethodDescriptor methodDesc) {
|
||||||
|
var returnType = typeMapper.mapType(methodDesc.getResultType()).asUnpackedType();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
return functionTypes.of(returnType, paramTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initArrayClass(WasmGCClassInfo classInfo, ValueType.Array type) {
|
||||||
|
classInfo.initializer = target -> {
|
||||||
|
var itemTypeInfo = getClassInfo(type.getItemType());
|
||||||
|
target.add(new WasmCall(
|
||||||
|
getCreateArrayClassFunction(),
|
||||||
|
new WasmGetGlobal(classInfo.pointer),
|
||||||
|
new WasmGetGlobal(itemTypeInfo.pointer)
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmExpression fillPrimitiveClass(WasmGlobal global, String name, int kind) {
|
||||||
|
return new WasmCall(
|
||||||
|
getCreatePrimitiveClassFunction(),
|
||||||
|
new WasmGetGlobal(global),
|
||||||
|
new WasmGetGlobal(strings.getStringConstant(name).global),
|
||||||
|
new WasmInt32Constant(kind)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFieldIndex(FieldReference fieldRef) {
|
||||||
|
var result = fieldIndexes.getOrDefault(fieldRef, -1);
|
||||||
|
if (result < 0) {
|
||||||
|
throw new IllegalStateException("Can't get offset of field " + fieldRef);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVirtualMethodIndex(MethodReference methodRef) {
|
||||||
|
var result = methodIndexes.getOrDefault(methodRef, -1);
|
||||||
|
if (result < 0) {
|
||||||
|
throw new IllegalStateException("Can't get offset of method " + methodRef);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillFields(List<WasmStorageType> fields, ValueType type) {
|
||||||
|
fields.add(standardClasses.classClass().getType().asStorage());
|
||||||
|
if (type instanceof ValueType.Object) {
|
||||||
|
fillClassFields(fields, ((ValueType.Object) type).getClassName());
|
||||||
|
} else if (type instanceof ValueType.Array) {
|
||||||
|
fillArrayField(fields, ((ValueType.Array) type).getItemType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillClassFields(List<WasmStorageType> fields, String className) {
|
||||||
|
var classReader = classSource.get(className);
|
||||||
|
if (classReader.hasModifier(ElementModifier.INTERFACE)) {
|
||||||
|
fillSimpleClassFields(fields, "java.lang.Object");
|
||||||
|
} else {
|
||||||
|
fillSimpleClassFields(fields, className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillSimpleClassFields(List<WasmStorageType> fields, String className) {
|
||||||
|
var classReader = classSource.get(className);
|
||||||
|
if (classReader.getParent() != null) {
|
||||||
|
fillClassFields(fields, classReader.getParent());
|
||||||
|
} else {
|
||||||
|
fields.add(standardClasses.classClass().getType().asStorage());
|
||||||
|
}
|
||||||
|
for (var field : classReader.getFields()) {
|
||||||
|
if (field.hasModifier(ElementModifier.STATIC)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fieldIndexes.putIfAbsent(field.getReference(), fields.size());
|
||||||
|
fields.add(typeMapper.mapType(field.getType()));
|
||||||
|
}
|
||||||
|
if (className.equals("java.lang.Class")) {
|
||||||
|
classFlagsOffset = fields.size();
|
||||||
|
fields.add(WasmType.INT32.asStorage());
|
||||||
|
classTagOffset = fields.size();
|
||||||
|
fields.add(WasmType.INT32.asStorage());
|
||||||
|
classParentOffset = fields.size();
|
||||||
|
fields.add(standardClasses.classClass().getType().asStorage());
|
||||||
|
classArrayItemOffset = fields.size();
|
||||||
|
fields.add(standardClasses.classClass().getType().asStorage());
|
||||||
|
classArrayOffset = fields.size();
|
||||||
|
fields.add(standardClasses.classClass().getType().asStorage());
|
||||||
|
classSupertypeFunctionOffset = fields.size();
|
||||||
|
fields.add(supertypeGenerator.getFunctionType().getReference().asStorage());
|
||||||
|
virtualTableFieldOffset = fields.size();
|
||||||
|
classNameOffset = fieldIndexes.get(new FieldReference(className, "name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillArrayField(List<WasmStorageType> fields, ValueType elementType) {
|
||||||
|
var wasmArray = new WasmArray(null, () -> typeMapper.mapType(elementType));
|
||||||
|
module.types.add(wasmArray);
|
||||||
|
fields.add(wasmArray.getReference().asStorage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmFunction getCreatePrimitiveClassFunction() {
|
||||||
|
if (createPrimitiveClassFunction == null) {
|
||||||
|
createPrimitiveClassFunction = createCreatePrimitiveClassFunction();
|
||||||
|
}
|
||||||
|
return createPrimitiveClassFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmFunction createCreatePrimitiveClassFunction() {
|
||||||
|
var functionType = functionTypes.of(
|
||||||
|
null,
|
||||||
|
standardClasses.classClass().getType(),
|
||||||
|
standardClasses.stringClass().getType(),
|
||||||
|
WasmType.INT32
|
||||||
|
);
|
||||||
|
var function = new WasmFunction(functionType);
|
||||||
|
function.setName("_teavm_fill_primitive_class_");
|
||||||
|
|
||||||
|
var targetVar = new WasmLocal(standardClasses.classClass().getType(), "target");
|
||||||
|
var nameVar = new WasmLocal(standardClasses.objectClass().getType(), "name");
|
||||||
|
var kindVar = new WasmLocal(WasmType.INT32, "kind");
|
||||||
|
function.getLocalVariables().add(targetVar);
|
||||||
|
function.getLocalVariables().add(nameVar);
|
||||||
|
function.getLocalVariables().add(kindVar);
|
||||||
|
|
||||||
|
var flagsExpr = new WasmIntBinary(
|
||||||
|
WasmIntType.INT32,
|
||||||
|
WasmIntBinaryOperation.SHL,
|
||||||
|
new WasmGetLocal(kindVar),
|
||||||
|
new WasmInt32Constant(WasmGCClassFlags.PRIMITIVE_KIND_SHIFT)
|
||||||
|
);
|
||||||
|
flagsExpr = new WasmIntBinary(
|
||||||
|
WasmIntType.INT32,
|
||||||
|
WasmIntBinaryOperation.OR,
|
||||||
|
flagsExpr,
|
||||||
|
new WasmInt32Constant(WasmGCClassFlags.FINAL | WasmGCClassFlags.PRIMITIVE)
|
||||||
|
);
|
||||||
|
function.getBody().add(new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetLocal(targetVar),
|
||||||
|
classFlagsOffset,
|
||||||
|
flagsExpr
|
||||||
|
));
|
||||||
|
function.getBody().add(new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetLocal(targetVar),
|
||||||
|
classNameOffset,
|
||||||
|
new WasmGetLocal(nameVar)
|
||||||
|
));
|
||||||
|
function.getBody().add(new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetLocal(targetVar),
|
||||||
|
classTagOffset,
|
||||||
|
new WasmInt32Constant(Integer.MAX_VALUE)
|
||||||
|
));
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmFunction getCreateArrayClassFunction() {
|
||||||
|
if (createArrayClassFunction == null) {
|
||||||
|
createArrayClassFunction = createCreateArrayClassFunction();
|
||||||
|
}
|
||||||
|
return createCreateArrayClassFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmFunction createCreateArrayClassFunction() {
|
||||||
|
var functionType = functionTypes.of(
|
||||||
|
null,
|
||||||
|
standardClasses.classClass().getType(),
|
||||||
|
standardClasses.classClass().getType()
|
||||||
|
);
|
||||||
|
var function = new WasmFunction(functionType);
|
||||||
|
function.setName("_teavm_fill_array_class_");
|
||||||
|
|
||||||
|
var targetVar = new WasmLocal(standardClasses.classClass().getType(), "target");
|
||||||
|
var itemVar = new WasmLocal(standardClasses.classClass().getType(), "item");
|
||||||
|
function.getLocalVariables().add(targetVar);
|
||||||
|
function.getLocalVariables().add(itemVar);
|
||||||
|
|
||||||
|
function.getBody().add(new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetLocal(targetVar),
|
||||||
|
classFlagsOffset,
|
||||||
|
new WasmInt32Constant(WasmGCClassFlags.FINAL)
|
||||||
|
));
|
||||||
|
function.getBody().add(new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetLocal(targetVar),
|
||||||
|
classArrayItemOffset,
|
||||||
|
new WasmGetLocal(itemVar)
|
||||||
|
));
|
||||||
|
function.getBody().add(new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetLocal(itemVar),
|
||||||
|
classArrayOffset,
|
||||||
|
new WasmGetLocal(targetVar)
|
||||||
|
));
|
||||||
|
function.getBody().add(new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetLocal(targetVar),
|
||||||
|
classTagOffset,
|
||||||
|
new WasmInt32Constant(0)
|
||||||
|
));
|
||||||
|
function.getBody().add(new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetLocal(targetVar),
|
||||||
|
classParentOffset,
|
||||||
|
new WasmGetGlobal(standardClasses.classClass().pointer)
|
||||||
|
));
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private WasmFunction getInitializer() {
|
||||||
|
if (initializer == null) {
|
||||||
|
initializer = new WasmFunction(functionTypes.of(null));
|
||||||
|
initializer.setName("_teavm_init_classes_");
|
||||||
|
module.functions.add(initializer);
|
||||||
|
}
|
||||||
|
return initializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmExpression setClassField(WasmGCClassInfo classInfo, int fieldIndex, WasmExpression value) {
|
||||||
|
return new WasmStructSet(
|
||||||
|
standardClasses.classClass().getStructure(),
|
||||||
|
new WasmGetGlobal(classInfo.pointer),
|
||||||
|
fieldIndex,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.classes;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import org.teavm.backend.wasm.model.WasmGlobal;
|
||||||
|
import org.teavm.backend.wasm.model.WasmStructure;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
|
public class WasmGCClassInfo {
|
||||||
|
private ValueType valueType;
|
||||||
|
WasmStructure structure;
|
||||||
|
WasmStructure virtualTableStructure;
|
||||||
|
WasmGlobal pointer;
|
||||||
|
Consumer<List<WasmExpression>> initializer;
|
||||||
|
|
||||||
|
WasmGCClassInfo(ValueType valueType) {
|
||||||
|
this.valueType = valueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueType getValueType() {
|
||||||
|
return valueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmStructure getStructure() {
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmStructure getVirtualTableStructure() {
|
||||||
|
return virtualTableStructure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmType.CompositeReference getType() {
|
||||||
|
return getStructure().getReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmGlobal getPointer() {
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.classes;
|
||||||
|
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
|
public interface WasmGCClassInfoProvider {
|
||||||
|
WasmGCClassInfo getClassInfo(ValueType type);
|
||||||
|
|
||||||
|
default WasmGCClassInfo getClassInfo(String name) {
|
||||||
|
return getClassInfo(ValueType.object(name));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.classes;
|
||||||
|
|
||||||
|
public class WasmGCStandardClasses {
|
||||||
|
private WasmGCClassInfoProvider classGenerator;
|
||||||
|
private WasmGCClassInfo classClassInfo;
|
||||||
|
private WasmGCClassInfo stringClassInfo;
|
||||||
|
private WasmGCClassInfo objectClassInfo;
|
||||||
|
|
||||||
|
public WasmGCStandardClasses(WasmGCClassInfoProvider classGenerator) {
|
||||||
|
this.classGenerator = classGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmGCClassInfo classClass() {
|
||||||
|
if (classClassInfo == null) {
|
||||||
|
classClassInfo = classGenerator.getClassInfo("java.lang.Class");
|
||||||
|
}
|
||||||
|
return classClassInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmGCClassInfo stringClass() {
|
||||||
|
if (stringClassInfo == null) {
|
||||||
|
stringClassInfo = classGenerator.getClassInfo("java.lang.Class");
|
||||||
|
}
|
||||||
|
return stringClassInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmGCClassInfo objectClass() {
|
||||||
|
if (objectClassInfo == null) {
|
||||||
|
objectClassInfo = classGenerator.getClassInfo("java.lang.Object");
|
||||||
|
}
|
||||||
|
return objectClassInfo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.classes;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||||
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.backend.lowlevel.generate.NameProvider;
|
||||||
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunctionType;
|
||||||
|
import org.teavm.backend.wasm.model.WasmLocal;
|
||||||
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.classes.TagRegistry;
|
||||||
|
|
||||||
|
public class WasmGCSupertypeFunctionGenerator {
|
||||||
|
private ObjectIntMap<ValueType> tableIndexes = new ObjectIntHashMap<>();
|
||||||
|
private Map<ValueType, WasmFunction> functions = new HashMap<>();
|
||||||
|
private WasmModule module;
|
||||||
|
private WasmGCClassGenerator classGenerator;
|
||||||
|
private NameProvider nameProvider;
|
||||||
|
private TagRegistry tagRegistry;
|
||||||
|
private WasmFunctionTypes functionTypes;
|
||||||
|
private WasmFunctionType functionType;
|
||||||
|
|
||||||
|
WasmGCSupertypeFunctionGenerator(
|
||||||
|
WasmModule module,
|
||||||
|
WasmGCClassGenerator classGenerator,
|
||||||
|
NameProvider nameProvider,
|
||||||
|
TagRegistry tagRegistry,
|
||||||
|
WasmFunctionTypes functionTypes
|
||||||
|
) {
|
||||||
|
this.module = module;
|
||||||
|
this.classGenerator = classGenerator;
|
||||||
|
this.nameProvider = nameProvider;
|
||||||
|
this.tagRegistry = tagRegistry;
|
||||||
|
this.functionTypes = functionTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmFunction getIsSupertypeFunction(ValueType type) {
|
||||||
|
var result = functions.get(type);
|
||||||
|
if (result == null) {
|
||||||
|
result = generateIsSupertypeFunction(type);
|
||||||
|
functions.put(type, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmFunction generateIsSupertypeFunction(ValueType type) {
|
||||||
|
var function = new WasmFunction(getFunctionType());
|
||||||
|
function.setName(nameProvider.forSupertypeFunction(type));
|
||||||
|
var subtypeVar = new WasmLocal(WasmType.INT32, "subtype");
|
||||||
|
function.add(subtypeVar);
|
||||||
|
module.functions.add(function);
|
||||||
|
|
||||||
|
if (type instanceof ValueType.Object) {
|
||||||
|
var className = ((ValueType.Object) type).getClassName();
|
||||||
|
generateIsClass(subtypeVar, className, function.getBody());
|
||||||
|
} else if (type instanceof ValueType.Array) {
|
||||||
|
ValueType itemType = ((ValueType.Array) type).getItemType();
|
||||||
|
generateIsArray(subtypeVar, itemType, function.getBody());
|
||||||
|
} else {
|
||||||
|
var expected = classGenerator.getClassInfo(type).pointer;
|
||||||
|
var condition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmGetGlobal(expected));
|
||||||
|
function.getBody().add(new WasmReturn(condition));
|
||||||
|
}
|
||||||
|
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateIsClass(WasmLocal subtypeVar, String className, List<WasmExpression> body) {
|
||||||
|
var ranges = tagRegistry.getRanges(className);
|
||||||
|
if (ranges.isEmpty()) {
|
||||||
|
body.add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tagOffset = classGenerator.getClassTagOffset();
|
||||||
|
|
||||||
|
var tagExpression = getClassField(new WasmGetLocal(subtypeVar), tagOffset);
|
||||||
|
body.add(new WasmSetLocal(subtypeVar, tagExpression));
|
||||||
|
|
||||||
|
ranges.sort(Comparator.comparingInt(range -> range.lower));
|
||||||
|
|
||||||
|
int lower = ranges.get(0).lower;
|
||||||
|
int upper = ranges.get(ranges.size() - 1).upper;
|
||||||
|
|
||||||
|
var lowerCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.LT_SIGNED,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(lower));
|
||||||
|
var testLower = new WasmConditional(lowerCondition);
|
||||||
|
testLower.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
|
body.add(testLower);
|
||||||
|
|
||||||
|
var upperCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.GE_SIGNED,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(upper));
|
||||||
|
var testUpper = new WasmConditional(upperCondition);
|
||||||
|
testUpper.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
|
body.add(testUpper);
|
||||||
|
|
||||||
|
for (int i = 1; i < ranges.size(); ++i) {
|
||||||
|
int lowerHole = ranges.get(i - 1).upper;
|
||||||
|
int upperHole = ranges.get(i).lower;
|
||||||
|
|
||||||
|
lowerCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.GE_SIGNED,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(lowerHole));
|
||||||
|
testLower = new WasmConditional(lowerCondition);
|
||||||
|
body.add(testLower);
|
||||||
|
|
||||||
|
upperCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.LT_SIGNED,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(upperHole));
|
||||||
|
testUpper = new WasmConditional(upperCondition);
|
||||||
|
testUpper.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
|
|
||||||
|
testLower.getThenBlock().getBody().add(testUpper);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.add(new WasmReturn(new WasmInt32Constant(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateIsArray(WasmLocal subtypeVar, ValueType itemType, List<WasmExpression> body) {
|
||||||
|
int itemOffset = classGenerator.getClassArrayItemOffset();
|
||||||
|
|
||||||
|
var itemExpression = getClassField(new WasmGetLocal(subtypeVar), itemOffset);
|
||||||
|
body.add(new WasmSetLocal(subtypeVar, itemExpression));
|
||||||
|
|
||||||
|
var itemTest = new WasmConditional(new WasmIntUnary(WasmIntType.INT32, WasmIntUnaryOperation.EQZ,
|
||||||
|
new WasmGetLocal(subtypeVar)));
|
||||||
|
itemTest.setType(WasmType.INT32);
|
||||||
|
itemTest.getThenBlock().getBody().add(new WasmInt32Constant(0));
|
||||||
|
|
||||||
|
var delegateToItem = new WasmCall(getIsSupertypeFunction(itemType));
|
||||||
|
delegateToItem.getArguments().add(new WasmGetLocal(subtypeVar));
|
||||||
|
itemTest.getElseBlock().getBody().add(delegateToItem);
|
||||||
|
|
||||||
|
body.add(new WasmReturn(itemTest));
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmFunctionType getFunctionType() {
|
||||||
|
if (functionType == null) {
|
||||||
|
functionType = functionTypes.of(WasmType.INT32, classGenerator.standardClasses.classClass().getType());
|
||||||
|
}
|
||||||
|
return functionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private WasmExpression getClassField(WasmExpression instance, int fieldIndex) {
|
||||||
|
return new WasmStructGet(
|
||||||
|
classGenerator.standardClasses.classClass().getStructure(),
|
||||||
|
instance,
|
||||||
|
fieldIndex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.classes;
|
||||||
|
|
||||||
|
import org.teavm.backend.wasm.model.WasmPackedType;
|
||||||
|
import org.teavm.backend.wasm.model.WasmStorageType;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
|
public class WasmGCTypeMapper {
|
||||||
|
private WasmGCClassInfoProvider classInfoProvider;
|
||||||
|
|
||||||
|
WasmGCTypeMapper(WasmGCClassInfoProvider classInfoProvider) {
|
||||||
|
this.classInfoProvider = classInfoProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmStorageType mapType(ValueType type) {
|
||||||
|
if (type instanceof ValueType.Primitive) {
|
||||||
|
switch (((ValueType.Primitive) type).getKind()) {
|
||||||
|
case BYTE:
|
||||||
|
case BOOLEAN:
|
||||||
|
return WasmStorageType.packed(WasmPackedType.INT8);
|
||||||
|
case SHORT:
|
||||||
|
case CHARACTER:
|
||||||
|
return WasmStorageType.packed(WasmPackedType.INT8);
|
||||||
|
case INTEGER:
|
||||||
|
return WasmType.INT32.asStorage();
|
||||||
|
case LONG:
|
||||||
|
return WasmType.INT64.asStorage();
|
||||||
|
case FLOAT:
|
||||||
|
return WasmType.FLOAT32.asStorage();
|
||||||
|
case DOUBLE:
|
||||||
|
return WasmType.FLOAT64.asStorage();
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return classInfoProvider.getClassInfo(type).getType().asStorage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.initialization;
|
||||||
|
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
|
||||||
|
public interface WasmGCInitializerContributor {
|
||||||
|
void contributeToInitializerDefinitions(WasmFunction function);
|
||||||
|
|
||||||
|
void contributeToInitializer(WasmFunction function);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.method;
|
||||||
|
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
public interface WasmGCFunctionProvider {
|
||||||
|
WasmFunction getMemberFunction(MethodReference methodRef);
|
||||||
|
|
||||||
|
WasmFunction getStaticFunction(MethodReference methodRef);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.strings;
|
||||||
|
|
||||||
|
import org.teavm.backend.wasm.model.WasmGlobal;
|
||||||
|
|
||||||
|
public class WasmGCStringConstant {
|
||||||
|
public final int index;
|
||||||
|
public final WasmGlobal global;
|
||||||
|
|
||||||
|
public WasmGCStringConstant(int index, WasmGlobal global) {
|
||||||
|
this.index = index;
|
||||||
|
this.global = global;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.strings;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.initialization.WasmGCInitializerContributor;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.method.WasmGCFunctionProvider;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
import org.teavm.backend.wasm.model.WasmGlobal;
|
||||||
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
|
import org.teavm.backend.wasm.render.WasmBinaryWriter;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
public class WasmGCStringPool implements WasmGCStringProvider, WasmGCInitializerContributor {
|
||||||
|
private WasmGCStandardClasses standardClasses;
|
||||||
|
private WasmModule module;
|
||||||
|
private WasmBinaryWriter binaryWriter = new WasmBinaryWriter();
|
||||||
|
private Map<String, WasmGCStringConstant> stringMap = new LinkedHashMap<>();
|
||||||
|
private WasmGCFunctionProvider functionProvider;
|
||||||
|
|
||||||
|
public WasmGCStringPool(WasmGCStandardClasses standardClasses, WasmModule module,
|
||||||
|
WasmGCFunctionProvider functionProvider) {
|
||||||
|
this.standardClasses = standardClasses;
|
||||||
|
this.module = module;
|
||||||
|
this.functionProvider = functionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contributeToInitializerDefinitions(WasmFunction function) {
|
||||||
|
for (var str : stringMap.values()) {
|
||||||
|
var newStruct = new WasmStructNewDefault(standardClasses.stringClass().getStructure());
|
||||||
|
function.getBody().add(new WasmSetGlobal(str.global, newStruct));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contributeToInitializer(WasmFunction function) {
|
||||||
|
var nextCharArrayFunction = functionProvider.getStaticFunction(new MethodReference(WasmGCStringPool.class,
|
||||||
|
"nextCharArray", char[].class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WasmGCStringConstant getStringConstant(String string) {
|
||||||
|
return stringMap.computeIfAbsent(string, s -> {
|
||||||
|
binaryWriter.writeInt32(string.length());
|
||||||
|
binaryWriter.writeBytes(string.getBytes(StandardCharsets.UTF_8));
|
||||||
|
var globalName = "_teavm_java_string_" + stringMap.size();
|
||||||
|
var globalType = standardClasses.stringClass().getType();
|
||||||
|
var global = new WasmGlobal(globalName, globalType, WasmExpression.defaultValueOfType(globalType));
|
||||||
|
module.globals.add(global);
|
||||||
|
return new WasmGCStringConstant(stringMap.size(), global);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static char[] nextCharArray() {
|
||||||
|
var length = nextLEB();
|
||||||
|
var result = new char[length];
|
||||||
|
var pos = 0;
|
||||||
|
while (pos < length) {
|
||||||
|
var b = nextByte();
|
||||||
|
if ((b & 0x80) == 0) {
|
||||||
|
result[pos++] = (char) b;
|
||||||
|
} else if ((b & 0xE0) == 0xC0) {
|
||||||
|
var b2 = nextByte();
|
||||||
|
result[pos++] = (char) (((b & 0x1F) << 6) | (b2 & 0x3F));
|
||||||
|
} else if ((b & 0xF0) == 0xE0) {
|
||||||
|
var b2 = nextByte();
|
||||||
|
var b3 = nextByte();
|
||||||
|
var c = (char) (((b & 0x0F) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3F));
|
||||||
|
result[pos++] = c;
|
||||||
|
} else if ((b & 0xF8) == 0xF0) {
|
||||||
|
var b2 = nextByte();
|
||||||
|
var b3 = nextByte();
|
||||||
|
var b4 = nextByte();
|
||||||
|
var code = ((b & 0x07) << 18) | ((b2 & 0x3f) << 12) | ((b3 & 0x3F) << 6) | (b4 & 0x3F);
|
||||||
|
result[pos++] = Character.highSurrogate(code);
|
||||||
|
result[pos++] = Character.lowSurrogate(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int nextLEB() {
|
||||||
|
var shift = 0;
|
||||||
|
var result = 0;
|
||||||
|
while (true) {
|
||||||
|
var b = nextByte();
|
||||||
|
var digit = b & 0x7F;
|
||||||
|
result |= digit << shift;
|
||||||
|
if ((b & 0x80) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
shift += 7;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native byte nextByte();
|
||||||
|
|
||||||
|
private static native void error();
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.generate.gc.strings;
|
||||||
|
|
||||||
|
public interface WasmGCStringProvider {
|
||||||
|
WasmGCStringConstant getStringConstant(String string);
|
||||||
|
}
|
|
@ -17,7 +17,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.Reference reference;
|
private WasmType.CompositeReference reference;
|
||||||
|
|
||||||
WasmCompositeType(String name) {
|
WasmCompositeType(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -27,9 +27,9 @@ public abstract class WasmCompositeType extends WasmEntity {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmType.Reference getReference() {
|
public WasmType.CompositeReference getReference() {
|
||||||
if (reference == null) {
|
if (reference == null) {
|
||||||
reference = new WasmType.Reference(this);
|
reference = new WasmType.CompositeReference(this);
|
||||||
}
|
}
|
||||||
return reference;
|
return reference;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,27 +16,15 @@
|
||||||
package org.teavm.backend.wasm.model;
|
package org.teavm.backend.wasm.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class WasmStructure extends WasmCompositeType {
|
public class WasmStructure extends WasmCompositeType {
|
||||||
private List<? extends WasmStorageType> fields;
|
private List<WasmStorageType> fields;
|
||||||
private Supplier<List<? extends WasmStorageType>> fieldsSupplier;
|
|
||||||
|
|
||||||
public WasmStructure(String name, List<? extends WasmStorageType> fields) {
|
public WasmStructure(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
this.fields = List.copyOf(fields);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmStructure(String name, Supplier<List<? extends WasmStorageType>> fieldsSupplier) {
|
public List<WasmStorageType> getFields() {
|
||||||
super(name);
|
|
||||||
this.fieldsSupplier = fieldsSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<? extends WasmStorageType> getFields() {
|
|
||||||
if (fields == null) {
|
|
||||||
fields = List.copyOf(fieldsSupplier.get());
|
|
||||||
fieldsSupplier = null;
|
|
||||||
}
|
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,11 +56,44 @@ public abstract class WasmType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Reference extends WasmType {
|
public static abstract class Reference extends WasmType {
|
||||||
|
public static final SpecialReference FUNC = SpecialReferenceKind.FUNC.asType();
|
||||||
|
public static final SpecialReference ANY = SpecialReferenceKind.ANY.asType();
|
||||||
|
public static final SpecialReference EXTERN = SpecialReferenceKind.EXTERN.asType();
|
||||||
|
public static final SpecialReference STRUCT = SpecialReferenceKind.STRUCT.asType();
|
||||||
|
public static final SpecialReference ARRAY = SpecialReferenceKind.ARRAY.asType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class CompositeReference extends Reference {
|
||||||
public final WasmCompositeType composite;
|
public final WasmCompositeType composite;
|
||||||
|
|
||||||
Reference(WasmCompositeType composite) {
|
CompositeReference(WasmCompositeType composite) {
|
||||||
this.composite = composite;
|
this.composite = composite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class SpecialReference extends WasmType {
|
||||||
|
public final SpecialReferenceKind kind;
|
||||||
|
|
||||||
|
private SpecialReference(SpecialReferenceKind kind) {
|
||||||
|
this.kind = kind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SpecialReferenceKind {
|
||||||
|
FUNC,
|
||||||
|
ANY,
|
||||||
|
EXTERN,
|
||||||
|
STRUCT,
|
||||||
|
ARRAY;
|
||||||
|
|
||||||
|
private SpecialReference type;
|
||||||
|
|
||||||
|
final SpecialReference asType() {
|
||||||
|
if (type == null) {
|
||||||
|
type = new SpecialReference(this);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.model.expression;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunctionType;
|
||||||
|
|
||||||
|
public class WasmCallReference extends WasmExpression {
|
||||||
|
private WasmFunctionType type;
|
||||||
|
private WasmExpression functionReference;
|
||||||
|
private List<WasmExpression> arguments = new ArrayList<>();
|
||||||
|
|
||||||
|
public WasmCallReference(WasmExpression functionReference, WasmFunctionType type) {
|
||||||
|
this.functionReference = Objects.requireNonNull(functionReference);
|
||||||
|
this.type = Objects.requireNonNull(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getFunctionReference() {
|
||||||
|
return functionReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFunctionReference(WasmExpression functionReference) {
|
||||||
|
this.functionReference = Objects.requireNonNull(functionReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WasmExpression> getArguments() {
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmFunctionType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(WasmFunctionType type) {
|
||||||
|
this.type = Objects.requireNonNull(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -145,6 +145,14 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCallReference expression) {
|
||||||
|
expression.getFunctionReference().acceptVisitor(this);
|
||||||
|
for (var argument : expression.getArguments()) {
|
||||||
|
argument.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmDrop expression) {
|
public void visit(WasmDrop expression) {
|
||||||
expression.getOperand().acceptVisitor(this);
|
expression.getOperand().acceptVisitor(this);
|
||||||
|
@ -250,6 +258,10 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructNewDefault expression) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructGet expression) {
|
public void visit(WasmStructGet expression) {
|
||||||
expression.getInstance().acceptVisitor(this);
|
expression.getInstance().acceptVisitor(this);
|
||||||
|
@ -283,4 +295,8 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmArrayLength expression) {
|
public void visit(WasmArrayLength expression) {
|
||||||
expression.getInstance().acceptVisitor(this);
|
expression.getInstance().acceptVisitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFunctionReference expression) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public abstract class WasmExpression {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
} else if (type instanceof WasmType.Reference) {
|
} else if (type instanceof WasmType.Reference) {
|
||||||
return new WasmNullConstant(((WasmType.Reference) type).composite);
|
return new WasmNullConstant((WasmType.Reference) type);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,8 @@ public interface WasmExpressionVisitor {
|
||||||
|
|
||||||
void visit(WasmIndirectCall expression);
|
void visit(WasmIndirectCall expression);
|
||||||
|
|
||||||
|
void visit(WasmCallReference expression);
|
||||||
|
|
||||||
void visit(WasmDrop expression);
|
void visit(WasmDrop expression);
|
||||||
|
|
||||||
void visit(WasmLoadInt32 expression);
|
void visit(WasmLoadInt32 expression);
|
||||||
|
@ -96,6 +98,8 @@ public interface WasmExpressionVisitor {
|
||||||
|
|
||||||
void visit(WasmStructNew expression);
|
void visit(WasmStructNew expression);
|
||||||
|
|
||||||
|
void visit(WasmStructNewDefault expression);
|
||||||
|
|
||||||
void visit(WasmStructGet expression);
|
void visit(WasmStructGet expression);
|
||||||
|
|
||||||
void visit(WasmStructSet expression);
|
void visit(WasmStructSet expression);
|
||||||
|
@ -107,4 +111,6 @@ public interface WasmExpressionVisitor {
|
||||||
void visit(WasmArraySet expression);
|
void visit(WasmArraySet expression);
|
||||||
|
|
||||||
void visit(WasmArrayLength expression);
|
void visit(WasmArrayLength expression);
|
||||||
|
|
||||||
|
void visit(WasmFunctionReference expression);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.model.expression;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
|
||||||
|
public class WasmFunctionReference extends WasmExpression {
|
||||||
|
private WasmFunction function;
|
||||||
|
|
||||||
|
public WasmFunctionReference(WasmFunction function) {
|
||||||
|
this.function = Objects.requireNonNull(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmFunction getFunction() {
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFunction(WasmFunction function) {
|
||||||
|
this.function = Objects.requireNonNull(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,20 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.model.expression;
|
package org.teavm.backend.wasm.model.expression;
|
||||||
|
|
||||||
import org.teavm.backend.wasm.model.WasmCompositeType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
|
||||||
public class WasmNullConstant extends WasmExpression {
|
public class WasmNullConstant extends WasmExpression {
|
||||||
public WasmCompositeType type;
|
public WasmType.Reference type;
|
||||||
|
|
||||||
public WasmNullConstant(WasmCompositeType type) {
|
public WasmNullConstant(WasmType.Reference type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmCompositeType getType() {
|
public WasmType.Reference getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(WasmCompositeType type) {
|
public void setType(WasmType.Reference type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,13 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
|
||||||
replaceExpressions(expression.getArguments());
|
replaceExpressions(expression.getArguments());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCallReference expression) {
|
||||||
|
expression.getFunctionReference().acceptVisitor(this);
|
||||||
|
expression.setFunctionReference(mapper.apply(expression.getFunctionReference()));
|
||||||
|
replaceExpressions(expression.getArguments());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmDrop expression) {
|
public void visit(WasmDrop expression) {
|
||||||
expression.getOperand().acceptVisitor(this);
|
expression.getOperand().acceptVisitor(this);
|
||||||
|
@ -295,6 +302,11 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructNew expression) {
|
public void visit(WasmStructNew expression) {
|
||||||
|
replaceExpressions(expression.getInitializers());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructNewDefault expression) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -344,4 +356,8 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
|
||||||
expression.getInstance().acceptVisitor(this);
|
expression.getInstance().acceptVisitor(this);
|
||||||
expression.setInstance(mapper.apply(expression.getInstance()));
|
expression.setInstance(mapper.apply(expression.getInstance()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFunctionReference expression) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.wasm.model.expression;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.teavm.backend.wasm.model.WasmStructure;
|
||||||
|
|
||||||
|
public class WasmStructNewDefault extends WasmExpression {
|
||||||
|
private WasmStructure type;
|
||||||
|
private List<WasmExpression> initializers = new ArrayList<>();
|
||||||
|
|
||||||
|
public WasmStructNewDefault(WasmStructure type) {
|
||||||
|
this.type = Objects.requireNonNull(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmStructure getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(WasmStructure type) {
|
||||||
|
this.type = Objects.requireNonNull(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmDefaultExpressionVisitor;
|
import org.teavm.backend.wasm.model.expression.WasmDefaultExpressionVisitor;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpressionVisitor;
|
import org.teavm.backend.wasm.model.expression.WasmExpressionVisitor;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
|
|
||||||
public class UnusedFunctionElimination {
|
public class UnusedFunctionElimination {
|
||||||
private WasmModule module;
|
private WasmModule module;
|
||||||
|
@ -64,10 +65,13 @@ public class UnusedFunctionElimination {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmCall expression) {
|
public void visit(WasmCall expression) {
|
||||||
super.visit(expression);
|
super.visit(expression);
|
||||||
var function = expression.getFunction();
|
use(expression.getFunction());
|
||||||
if (function != null) {
|
|
||||||
use(function);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFunctionReference expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getFunction());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,19 @@ import org.teavm.backend.wasm.model.WasmModule;
|
||||||
import org.teavm.backend.wasm.model.WasmStorageType;
|
import org.teavm.backend.wasm.model.WasmStorageType;
|
||||||
import org.teavm.backend.wasm.model.WasmStructure;
|
import org.teavm.backend.wasm.model.WasmStructure;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmArrayGet;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmArraySet;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmDefaultExpressionVisitor;
|
import org.teavm.backend.wasm.model.expression.WasmDefaultExpressionVisitor;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpressionVisitor;
|
import org.teavm.backend.wasm.model.expression.WasmExpressionVisitor;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
|
|
||||||
public class UnusedTypeElimination {
|
public class UnusedTypeElimination {
|
||||||
private WasmModule module;
|
private WasmModule module;
|
||||||
|
@ -51,15 +61,27 @@ public class UnusedTypeElimination {
|
||||||
for (var tag : module.tags) {
|
for (var tag : module.tags) {
|
||||||
use(tag.getType());
|
use(tag.getType());
|
||||||
}
|
}
|
||||||
|
for (var global : module.globals) {
|
||||||
|
use(global.getType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void useFrom(WasmFunction function) {
|
private void useFrom(WasmFunction function) {
|
||||||
use(function.getType());
|
use(function.getType());
|
||||||
|
for (var local : function.getLocalVariables()) {
|
||||||
|
use(local.getType());
|
||||||
|
}
|
||||||
for (var part : function.getBody()) {
|
for (var part : function.getBody()) {
|
||||||
part.acceptVisitor(exprVisitor);
|
part.acceptVisitor(exprVisitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void use(WasmType type) {
|
||||||
|
if (type instanceof WasmType.CompositeReference) {
|
||||||
|
use(((WasmType.CompositeReference) type).composite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void use(WasmCompositeType type) {
|
private void use(WasmCompositeType type) {
|
||||||
if (!usedTypes.add(type)) {
|
if (!usedTypes.add(type)) {
|
||||||
return;
|
return;
|
||||||
|
@ -73,6 +95,67 @@ public class UnusedTypeElimination {
|
||||||
super.visit(expression);
|
super.visit(expression);
|
||||||
use(expression.getType());
|
use(expression.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCast expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getTargetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmArrayGet expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmArraySet expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructNew expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructNewDefault expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructGet expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructSet expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmNullConstant expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFunctionReference expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
useFrom(expression.getFunction());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCallReference expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getType());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private WasmCompositeTypeVisitor typeVisitor = new WasmDefaultCompositeTypeVisitor() {
|
private WasmCompositeTypeVisitor typeVisitor = new WasmDefaultCompositeTypeVisitor() {
|
||||||
|
@ -105,8 +188,8 @@ public class UnusedTypeElimination {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visit(WasmType type) {
|
private void visit(WasmType type) {
|
||||||
if (type instanceof WasmType.Reference) {
|
if (type instanceof WasmType.CompositeReference) {
|
||||||
use(((WasmType.Reference) type).composite);
|
use(((WasmType.CompositeReference) type).composite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
|
@ -45,6 +46,7 @@ import org.teavm.backend.wasm.model.expression.WasmFloat32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
|
import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
@ -68,6 +70,7 @@ import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
|
@ -250,7 +253,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmNullConstant expression) {
|
public void visit(WasmNullConstant expression) {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
writer.writeByte(0xD0);
|
writer.writeByte(0xD0);
|
||||||
writer.writeSignedLEB(module.types.indexOf(expression.getType()));
|
writeBlockType(expression.getType());
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,6 +779,18 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCallReference expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
for (var argument : expression.getArguments()) {
|
||||||
|
argument.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
expression.getFunctionReference().acceptVisitor(this);
|
||||||
|
writer.writeByte(0x14);
|
||||||
|
writer.writeLEB(module.types.indexOf(expression.getType()));
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmDrop expression) {
|
public void visit(WasmDrop expression) {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
|
@ -1031,6 +1046,15 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructNewDefault expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
writer.writeByte(0xfb);
|
||||||
|
writer.writeByte(1);
|
||||||
|
writer.writeInt32(module.types.indexOf(expression.getType()));
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructGet expression) {
|
public void visit(WasmStructGet expression) {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
|
@ -1118,6 +1142,14 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFunctionReference expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
writer.writeByte(0xd2);
|
||||||
|
writer.writeInt32(module.functions.indexOf(expression.getFunction()));
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
private int alignment(int value) {
|
private int alignment(int value) {
|
||||||
return 31 - Integer.numberOfLeadingZeros(Math.max(1, value));
|
return 31 - Integer.numberOfLeadingZeros(Math.max(1, value));
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,26 @@ 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.Reference) {
|
} else if (type instanceof WasmType.SpecialReference) {
|
||||||
writeSignedLEB(module.types.indexOf(((WasmType.Reference) type).composite));
|
switch (((WasmType.SpecialReference) type).kind) {
|
||||||
|
case ANY:
|
||||||
|
writeByte(0x6e);
|
||||||
|
break;
|
||||||
|
case EXTERN:
|
||||||
|
writeByte(0x6f);
|
||||||
|
break;
|
||||||
|
case FUNC:
|
||||||
|
writeByte(0x70);
|
||||||
|
break;
|
||||||
|
case STRUCT:
|
||||||
|
writeByte(0x6b);
|
||||||
|
break;
|
||||||
|
case ARRAY:
|
||||||
|
writeByte(0x6a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (type instanceof WasmType.CompositeReference) {
|
||||||
|
writeSignedLEB(module.types.indexOf(((WasmType.CompositeReference) type).composite));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
|
@ -48,6 +49,7 @@ import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
@ -72,6 +74,7 @@ import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
|
@ -783,6 +786,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
||||||
value = result;
|
value = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCallReference expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
private void translateArguments(List<? extends WasmExpression> wasmArguments, List<? extends WasmType> signature,
|
private void translateArguments(List<? extends WasmExpression> wasmArguments, List<? extends WasmType> signature,
|
||||||
CExpression result, StringBuilder sb) {
|
CExpression result, StringBuilder sb) {
|
||||||
if (wasmArguments.isEmpty()) {
|
if (wasmArguments.isEmpty()) {
|
||||||
|
@ -1166,6 +1174,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
||||||
unsupported();
|
unsupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructNewDefault expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructGet expression) {
|
public void visit(WasmStructGet expression) {
|
||||||
unsupported();
|
unsupported();
|
||||||
|
@ -1196,6 +1209,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
||||||
unsupported();
|
unsupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFunctionReference expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
private void unsupported() {
|
private void unsupported() {
|
||||||
value = new CExpression("/* unsupported */");
|
value = new CExpression("/* unsupported */");
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
|
@ -47,6 +48,7 @@ import org.teavm.backend.wasm.model.expression.WasmFloatBinaryOperation;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatUnaryOperation;
|
import org.teavm.backend.wasm.model.expression.WasmFloatUnaryOperation;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
@ -73,6 +75,7 @@ import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
|
@ -288,7 +291,7 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmNullConstant expression) {
|
public void visit(WasmNullConstant expression) {
|
||||||
open().append("ref.null " + module.types.indexOf(expression.getType())).close();
|
open().append("ref.null " + type(expression.getType())).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -446,6 +449,16 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCallReference expression) {
|
||||||
|
open().append("call_ref ").append(type(expression.getType().getReference()));
|
||||||
|
line(expression.getFunctionReference());
|
||||||
|
for (var argument : expression.getArguments()) {
|
||||||
|
line(argument);
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmDrop expression) {
|
public void visit(WasmDrop expression) {
|
||||||
open().append("drop").lf();
|
open().append("drop").lf();
|
||||||
|
@ -696,6 +709,11 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructNewDefault expression) {
|
||||||
|
open().append("struct.new_default ").append(expression.getType().getReference()).close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructGet expression) {
|
public void visit(WasmStructGet expression) {
|
||||||
open();
|
open();
|
||||||
|
@ -773,11 +791,32 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFunctionReference expression) {
|
||||||
|
open().append("ref.func ").append(" $" + module.functions.indexOf(expression.getFunction()));
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
private String type(WasmType type) {
|
private String type(WasmType type) {
|
||||||
if (type instanceof WasmType.Number) {
|
if (type instanceof WasmType.Number) {
|
||||||
return type(((WasmType.Number) type).number);
|
return type(((WasmType.Number) type).number);
|
||||||
} else if (type instanceof WasmType.Reference) {
|
} else if (type instanceof WasmType.SpecialReference) {
|
||||||
return "(ref " + typeName(((WasmType.Reference) type).composite) + ")";
|
switch (((WasmType.SpecialReference) type).kind) {
|
||||||
|
case ANY:
|
||||||
|
return "anyref";
|
||||||
|
case EXTERN:
|
||||||
|
return "externref";
|
||||||
|
case STRUCT:
|
||||||
|
return "structref";
|
||||||
|
case FUNC:
|
||||||
|
return "funcref";
|
||||||
|
case ARRAY:
|
||||||
|
return "arrayref";
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
} else if (type instanceof WasmType.CompositeReference) {
|
||||||
|
return "(ref " + typeName(((WasmType.CompositeReference) type).composite) + ")";
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
import org.teavm.backend.wasm.model.expression.WasmBreak;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
import org.teavm.backend.wasm.model.expression.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||||
|
@ -36,6 +37,7 @@ import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
import org.teavm.backend.wasm.model.expression.WasmFloatUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
@ -60,6 +62,7 @@ import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
|
@ -175,7 +178,7 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmNullConstant expression) {
|
public void visit(WasmNullConstant expression) {
|
||||||
result = expression.type.getReference();
|
result = expression.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -189,6 +192,11 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
result = expression.getType().getReturnType();
|
result = expression.getType().getReturnType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmCallReference expression) {
|
||||||
|
result = expression.getType().getReturnType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmDrop expression) {
|
public void visit(WasmDrop expression) {
|
||||||
result = null;
|
result = null;
|
||||||
|
@ -274,6 +282,11 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
result = expression.getType().getReference();
|
result = expression.getType().getReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmStructNewDefault expression) {
|
||||||
|
result = expression.getType().getReference();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructGet expression) {
|
public void visit(WasmStructGet expression) {
|
||||||
result = expression.getType().getFields().get(expression.getFieldIndex()).asUnpackedType();
|
result = expression.getType().getFields().get(expression.getFieldIndex()).asUnpackedType();
|
||||||
|
@ -304,6 +317,11 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
result = WasmType.INT32;
|
result = WasmType.INT32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmFunctionReference expression) {
|
||||||
|
result = expression.getFunction().getType().getReference();
|
||||||
|
}
|
||||||
|
|
||||||
private static WasmType map(WasmIntType type) {
|
private static WasmType map(WasmIntType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT32:
|
case INT32:
|
||||||
|
|
46
core/src/main/java/org/teavm/model/util/ReflectionUtil.java
Normal file
46
core/src/main/java/org/teavm/model/util/ReflectionUtil.java
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.model.util;
|
||||||
|
|
||||||
|
import org.teavm.model.PrimitiveType;
|
||||||
|
|
||||||
|
public final class ReflectionUtil {
|
||||||
|
private ReflectionUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String typeName(PrimitiveType type) {
|
||||||
|
switch (type) {
|
||||||
|
case BOOLEAN:
|
||||||
|
return "boolean";
|
||||||
|
case BYTE:
|
||||||
|
return "byte";
|
||||||
|
case SHORT:
|
||||||
|
return "short";
|
||||||
|
case CHARACTER:
|
||||||
|
return "char";
|
||||||
|
case INTEGER:
|
||||||
|
return "int";
|
||||||
|
case LONG:
|
||||||
|
return "long";
|
||||||
|
case FLOAT:
|
||||||
|
return "float";
|
||||||
|
case DOUBLE:
|
||||||
|
return "double";
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user