mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Add support for array of objects
This commit is contained in:
parent
38aca08993
commit
421eca8a49
|
@ -17,15 +17,11 @@ package org.teavm.model;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class ClassHolder extends ElementHolder implements ClassReader {
|
||||
private String parent = Object.class.getName();
|
||||
private Set<String> interfaces = new HashSet<>();
|
||||
private Map<MethodDescriptor, MethodHolder> methods = new HashMap<>();
|
||||
private Map<String, FieldHolder> fields = new HashMap<>();
|
||||
private Set<String> interfaces = new LinkedHashSet<>();
|
||||
private Map<MethodDescriptor, MethodHolder> methods = new LinkedHashMap<>();
|
||||
private Map<String, FieldHolder> fields = new LinkedHashMap<>();
|
||||
private String ownerName;
|
||||
|
||||
public ClassHolder(String name) {
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.runtime;
|
|||
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.StaticInit;
|
||||
import org.teavm.interop.Structure;
|
||||
|
||||
@StaticInit
|
||||
public final class Allocator {
|
||||
|
@ -31,4 +32,18 @@ public final class Allocator {
|
|||
object.classReference = tag.toAddress().toInt() >> 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Address allocateArray(RuntimeClass tag, int size, byte depth) {
|
||||
Address result = address;
|
||||
int sizeInBytes = (size + 1) * 4 + Structure.sizeOf(RuntimeArray.class);
|
||||
address = result.add(sizeInBytes);
|
||||
|
||||
RuntimeArray array = result.toStructure();
|
||||
array.classReference = RuntimeClass.getArrayClass().toAddress().toInt() >> 3;
|
||||
array.componentClassReference = tag.toAddress().toInt() >> 3;
|
||||
array.size = size;
|
||||
address.add(Structure.sizeOf(RuntimeArray.class)).putByte(depth);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,5 +17,5 @@ package org.teavm.runtime;
|
|||
|
||||
public class RuntimeArray extends RuntimeObject {
|
||||
public int componentClassReference;
|
||||
public byte depth;
|
||||
int size;
|
||||
}
|
||||
|
|
|
@ -53,5 +53,5 @@ public class RuntimeClass extends Structure {
|
|||
return computeCanary(size, lowerTag, upperTag);
|
||||
}
|
||||
|
||||
private static native RuntimeClass getArrayClass();
|
||||
public static native RuntimeClass getArrayClass();
|
||||
}
|
||||
|
|
|
@ -34,6 +34,12 @@ public final class Example {
|
|||
WasmRuntime.print(instance(i).foo());
|
||||
}
|
||||
|
||||
Base[] array = { new Derived1(), new Derived2() };
|
||||
WasmRuntime.print(array.length);
|
||||
for (Base elem : array) {
|
||||
WasmRuntime.print(elem.foo());
|
||||
}
|
||||
|
||||
WasmRuntime.print(new Derived2() instanceof Base ? 1 : 0);
|
||||
WasmRuntime.print(new Derived3() instanceof Base ? 1 : 0);
|
||||
WasmRuntime.print((Object) new Derived2() instanceof Derived1 ? 1 : 0);
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.teavm.dependency.DependencyChecker;
|
|||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Import;
|
||||
import org.teavm.interop.StaticInit;
|
||||
import org.teavm.interop.Structure;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassHolder;
|
||||
|
@ -61,7 +60,10 @@ import org.teavm.wasm.generate.WasmClassGenerator;
|
|||
import org.teavm.wasm.generate.WasmGenerationContext;
|
||||
import org.teavm.wasm.generate.WasmGenerator;
|
||||
import org.teavm.wasm.generate.WasmMangling;
|
||||
import org.teavm.wasm.intrinsics.WasmAddressIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.WasmRuntimeClassIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.WasmRuntimeIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.WasmStructureIntrinsic;
|
||||
import org.teavm.wasm.model.WasmFunction;
|
||||
import org.teavm.wasm.model.WasmModule;
|
||||
import org.teavm.wasm.model.WasmType;
|
||||
|
@ -110,6 +112,9 @@ public class WasmTarget implements TeaVMTarget {
|
|||
|
||||
dependencyChecker.linkMethod(new MethodReference(Allocator.class, "allocate",
|
||||
RuntimeClass.class, Address.class), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(Allocator.class, "allocateArray",
|
||||
RuntimeClass.class, int.class, byte.class, Address.class), null).use();
|
||||
|
||||
dependencyChecker.linkMethod(new MethodReference(Allocator.class, "<clinit>", void.class), null).use();
|
||||
}
|
||||
|
||||
|
@ -130,12 +135,18 @@ public class WasmTarget implements TeaVMTarget {
|
|||
return;
|
||||
}
|
||||
}
|
||||
classGenerator.addArrayClass();
|
||||
address = classGenerator.getAddress();
|
||||
|
||||
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
|
||||
new HashSet<>());
|
||||
WasmGenerationContext context = new WasmGenerationContext(classes, vtableProvider, tagRegistry);
|
||||
|
||||
context.addIntrinsic(new WasmAddressIntrinsic());
|
||||
context.addIntrinsic(new WasmRuntimeClassIntrinsic(classGenerator));
|
||||
context.addIntrinsic(new WasmStructureIntrinsic(classGenerator));
|
||||
context.addIntrinsic(new WasmRuntimeIntrinsic());
|
||||
|
||||
WasmGenerator generator = new WasmGenerator(decompiler, classes, context, classGenerator);
|
||||
|
||||
module.setMemorySize(64);
|
||||
|
@ -152,10 +163,6 @@ public class WasmTarget implements TeaVMTarget {
|
|||
}
|
||||
|
||||
if (method.hasModifier(ElementModifier.NATIVE)) {
|
||||
if (method.getOwnerName().equals(Structure.class.getName())
|
||||
|| method.getOwnerName().equals(Address.class.getName())) {
|
||||
continue;
|
||||
}
|
||||
if (context.getImportedMethod(method.getReference()) == null) {
|
||||
CallLocation location = new CallLocation(method.getReference());
|
||||
controller.getDiagnostics().error(location, "Method {{m0}} is native but "
|
||||
|
|
|
@ -47,6 +47,7 @@ public class WasmClassGenerator {
|
|||
private ClassReaderSource classSource;
|
||||
private int address;
|
||||
private Map<String, ClassBinaryData> binaryDataMap = new LinkedHashMap<>();
|
||||
private ClassBinaryData arrayClassData;
|
||||
private List<WasmExpression> initializer;
|
||||
private Map<MethodReference, Integer> functions = new HashMap<>();
|
||||
private List<String> functionTable = new ArrayList<>();
|
||||
|
@ -81,6 +82,17 @@ public class WasmClassGenerator {
|
|||
contributeToInitializer(binaryData);
|
||||
}
|
||||
|
||||
public void addArrayClass() {
|
||||
if (arrayClassData != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
arrayClassData = new ClassBinaryData();
|
||||
arrayClassData.start = address;
|
||||
|
||||
address += RuntimeClass.VIRTUAL_TABLE_OFFSET;
|
||||
}
|
||||
|
||||
public int getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
@ -153,6 +165,15 @@ public class WasmClassGenerator {
|
|||
return data.fieldLayout.get(field.getFieldName());
|
||||
}
|
||||
|
||||
public int getClassSize(String className) {
|
||||
ClassBinaryData data = binaryDataMap.get(className);
|
||||
return data.size;
|
||||
}
|
||||
|
||||
public int getArrayClassPointer() {
|
||||
return arrayClassData.start;
|
||||
}
|
||||
|
||||
public boolean isStructure(String className) {
|
||||
ClassBinaryData data = binaryDataMap.get(className);
|
||||
return data.start < 0;
|
||||
|
|
|
@ -62,7 +62,6 @@ import org.teavm.ast.UnwrapArrayExpr;
|
|||
import org.teavm.ast.VariableExpr;
|
||||
import org.teavm.ast.WhileStatement;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Structure;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
|
@ -71,6 +70,7 @@ import org.teavm.model.ValueType;
|
|||
import org.teavm.model.classes.TagRegistry;
|
||||
import org.teavm.model.classes.VirtualTableEntry;
|
||||
import org.teavm.runtime.Allocator;
|
||||
import org.teavm.runtime.RuntimeArray;
|
||||
import org.teavm.runtime.RuntimeClass;
|
||||
import org.teavm.wasm.WasmRuntime;
|
||||
import org.teavm.wasm.intrinsics.WasmIntrinsic;
|
||||
|
@ -336,7 +336,8 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
result, new WasmInt32Constant(16));
|
||||
break;
|
||||
case LENGTH:
|
||||
result = new WasmInt32Constant(0);
|
||||
expr.getOperand().acceptVisitor(this);
|
||||
result = generateArrayLength(result);
|
||||
break;
|
||||
case NOT:
|
||||
expr.getOperand().acceptVisitor(this);
|
||||
|
@ -369,6 +370,14 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
private WasmExpression generateArrayLength(WasmExpression array) {
|
||||
int sizeOffset = classGenerator.getFieldOffset(new FieldReference(RuntimeArray.class.getName(), "size"));
|
||||
|
||||
WasmIntBinary ptr = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
||||
array, new WasmInt32Constant(sizeOffset));
|
||||
return new WasmLoadInt32(4, ptr, WasmInt32Subtype.INT32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignmentStatement statement) {
|
||||
Expr left = statement.getLeftValue();
|
||||
|
@ -383,6 +392,9 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
} else if (left instanceof QualificationExpr) {
|
||||
QualificationExpr lhs = (QualificationExpr) left;
|
||||
storeField(lhs.getQualified(), lhs.getField(), statement.getRightValue());
|
||||
} else if (left instanceof SubscriptExpr) {
|
||||
SubscriptExpr lhs = (SubscriptExpr) left;
|
||||
storeArrayItem(lhs.getArray(), lhs.getIndex(), statement.getRightValue());
|
||||
} else {
|
||||
throw new UnsupportedOperationException("This expression is not supported yet");
|
||||
}
|
||||
|
@ -422,6 +434,12 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
private void storeArrayItem(Expr array, Expr index, Expr rightValue) {
|
||||
WasmExpression ptr = getArrayElementPointer(array, index);
|
||||
rightValue.acceptVisitor(this);
|
||||
result = new WasmStoreInt32(4, ptr, result, WasmInt32Subtype.INT32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConditionalExpr expr) {
|
||||
expr.getCondition().acceptVisitor(this);
|
||||
|
@ -488,7 +506,22 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(SubscriptExpr expr) {
|
||||
throw new UnsupportedOperationException("Not supported yet");
|
||||
WasmExpression ptr = getArrayElementPointer(expr.getArray(), expr.getIndex());
|
||||
result = new WasmLoadInt32(4, ptr, WasmInt32Subtype.INT32);
|
||||
}
|
||||
|
||||
private WasmExpression getArrayElementPointer(Expr arrayExpr, Expr indexExpr) {
|
||||
arrayExpr.acceptVisitor(this);
|
||||
WasmExpression array = result;
|
||||
indexExpr.acceptVisitor(this);
|
||||
WasmExpression index = result;
|
||||
|
||||
classGenerator.addClass(RuntimeArray.class.getName());
|
||||
int base = classGenerator.getClassSize(RuntimeArray.class.getName());
|
||||
array = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, array, new WasmInt32Constant(base));
|
||||
index = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL, index, new WasmInt32Constant(2));
|
||||
|
||||
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, array, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -600,15 +633,6 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(InvocationExpr expr) {
|
||||
if (expr.getMethod().getClassName().equals(Address.class.getName())) {
|
||||
generateAddressInvocation(expr);
|
||||
return;
|
||||
}
|
||||
if (expr.getMethod().getClassName().equals(Structure.class.getName())) {
|
||||
generateStructureInvocation(expr);
|
||||
return;
|
||||
}
|
||||
|
||||
WasmIntrinsic intrinsic = context.getIntrinsic(expr.getMethod());
|
||||
if (intrinsic != null) {
|
||||
result = intrinsic.apply(expr, intrinsicManager);
|
||||
|
@ -661,122 +685,6 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
private void generateAddressInvocation(InvocationExpr expr) {
|
||||
switch (expr.getMethod().getName()) {
|
||||
case "toInt":
|
||||
case "toStructure":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
break;
|
||||
case "toLong":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmConversion(WasmType.INT32, WasmType.INT64, false, result);
|
||||
break;
|
||||
case "fromInt":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
break;
|
||||
case "fromLong":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmConversion(WasmType.INT64, WasmType.INT32, false, result);
|
||||
break;
|
||||
case "add": {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
WasmExpression base = result;
|
||||
expr.getArguments().get(1).acceptVisitor(this);
|
||||
WasmExpression offset = result;
|
||||
if (expr.getMethod().parameterType(0) == ValueType.LONG) {
|
||||
offset = new WasmConversion(WasmType.INT64, WasmType.INT32, false, offset);
|
||||
}
|
||||
result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, base, offset);
|
||||
break;
|
||||
}
|
||||
case "getByte":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmLoadInt32(1, result, WasmInt32Subtype.INT8);
|
||||
break;
|
||||
case "getShort":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmLoadInt32(2, result, WasmInt32Subtype.INT16);
|
||||
break;
|
||||
case "getChar":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmLoadInt32(2, result, WasmInt32Subtype.UINT16);
|
||||
break;
|
||||
case "getInt":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmLoadInt32(4, result, WasmInt32Subtype.INT32);
|
||||
break;
|
||||
case "getLong":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmLoadInt64(8, result, WasmInt64Subtype.INT64);
|
||||
break;
|
||||
case "getFloat":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmLoadFloat32(4, result);
|
||||
break;
|
||||
case "getDouble":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
result = new WasmLoadFloat64(8, result);
|
||||
break;
|
||||
case "putByte": {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
WasmExpression address = result;
|
||||
expr.getArguments().get(1).acceptVisitor(this);
|
||||
result = new WasmStoreInt32(1, address, result, WasmInt32Subtype.INT8);
|
||||
break;
|
||||
}
|
||||
case "putShort": {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
WasmExpression address = result;
|
||||
expr.getArguments().get(1).acceptVisitor(this);
|
||||
result = new WasmStoreInt32(2, address, result, WasmInt32Subtype.INT16);
|
||||
break;
|
||||
}
|
||||
case "putChar": {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
WasmExpression address = result;
|
||||
expr.getArguments().get(1).acceptVisitor(this);
|
||||
result = new WasmStoreInt32(2, address, result, WasmInt32Subtype.UINT16);
|
||||
break;
|
||||
}
|
||||
case "putInt": {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
WasmExpression address = result;
|
||||
expr.getArguments().get(1).acceptVisitor(this);
|
||||
result = new WasmStoreInt32(4, address, result, WasmInt32Subtype.INT32);
|
||||
break;
|
||||
}
|
||||
case "putLong": {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
WasmExpression address = result;
|
||||
expr.getArguments().get(1).acceptVisitor(this);
|
||||
result = new WasmStoreInt64(8, address, result, WasmInt64Subtype.INT64);
|
||||
break;
|
||||
}
|
||||
case "putFloat": {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
WasmExpression address = result;
|
||||
expr.getArguments().get(1).acceptVisitor(this);
|
||||
result = new WasmStoreFloat32(4, address, result);
|
||||
break;
|
||||
}
|
||||
case "putDouble": {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
WasmExpression address = result;
|
||||
expr.getArguments().get(1).acceptVisitor(this);
|
||||
result = new WasmStoreFloat64(8, address, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateStructureInvocation(InvocationExpr expr) {
|
||||
switch (expr.getMethod().getName()) {
|
||||
case "toAddress":
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BlockStatement statement) {
|
||||
WasmBlock block = new WasmBlock(false);
|
||||
|
@ -856,16 +764,6 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
result = new WasmBreak(wasmTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewExpr expr) {
|
||||
int tag = classGenerator.getClassPointer(expr.getConstructedClass());
|
||||
String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocate",
|
||||
RuntimeClass.class, Address.class));
|
||||
WasmCall call = new WasmCall(allocName);
|
||||
call.getArguments().add(new WasmInt32Constant(tag));
|
||||
result = call;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ContinueStatement statement) {
|
||||
IdentifiedStatement target = statement.getTarget();
|
||||
|
@ -877,8 +775,36 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
result = new WasmBreak(wasmTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewExpr expr) {
|
||||
int tag = classGenerator.getClassPointer(expr.getConstructedClass());
|
||||
String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocate",
|
||||
RuntimeClass.class, Address.class));
|
||||
WasmCall call = new WasmCall(allocName);
|
||||
call.getArguments().add(new WasmInt32Constant(tag));
|
||||
result = call;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewArrayExpr expr) {
|
||||
ValueType type = expr.getType();
|
||||
int depth = 0;
|
||||
while (type instanceof ValueType.Array) {
|
||||
++depth;
|
||||
type = ((ValueType.Array) type).getItemType();
|
||||
}
|
||||
|
||||
ValueType.Object cls = (ValueType.Object) type;
|
||||
int classPointer = classGenerator.getClassPointer(cls.getClassName());
|
||||
String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocateArray",
|
||||
RuntimeClass.class, int.class, byte.class, Address.class));
|
||||
WasmCall call = new WasmCall(allocName);
|
||||
call.getArguments().add(new WasmInt32Constant(classPointer));
|
||||
expr.getLength().acceptVisitor(this);
|
||||
call.getArguments().add(result);
|
||||
call.getArguments().add(new WasmInt32Constant(depth));
|
||||
|
||||
result = call;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright 2016 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.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.wasm.model.WasmType;
|
||||
import org.teavm.wasm.model.expression.WasmConversion;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.wasm.model.expression.WasmInt32Subtype;
|
||||
import org.teavm.wasm.model.expression.WasmInt64Subtype;
|
||||
import org.teavm.wasm.model.expression.WasmIntBinary;
|
||||
import org.teavm.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.wasm.model.expression.WasmLoadFloat32;
|
||||
import org.teavm.wasm.model.expression.WasmLoadFloat64;
|
||||
import org.teavm.wasm.model.expression.WasmLoadInt32;
|
||||
import org.teavm.wasm.model.expression.WasmLoadInt64;
|
||||
import org.teavm.wasm.model.expression.WasmStoreFloat32;
|
||||
import org.teavm.wasm.model.expression.WasmStoreFloat64;
|
||||
import org.teavm.wasm.model.expression.WasmStoreInt32;
|
||||
import org.teavm.wasm.model.expression.WasmStoreInt64;
|
||||
|
||||
public class WasmAddressIntrinsic implements WasmIntrinsic {
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
return methodReference.getClassName().equals(Address.class.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "toInt":
|
||||
case "toStructure":
|
||||
return manager.generate(invocation.getArguments().get(0));
|
||||
case "toLong": {
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(0));
|
||||
return new WasmConversion(WasmType.INT32, WasmType.INT64, false, value);
|
||||
}
|
||||
case "fromInt":
|
||||
return manager.generate(invocation.getArguments().get(0));
|
||||
case "fromLong": {
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(0));
|
||||
return new WasmConversion(WasmType.INT64, WasmType.INT32, false, value);
|
||||
}
|
||||
case "add": {
|
||||
WasmExpression base = manager.generate(invocation.getArguments().get(0));
|
||||
WasmExpression offset = manager.generate(invocation.getArguments().get(1));
|
||||
if (invocation.getMethod().parameterType(0) == ValueType.LONG) {
|
||||
offset = new WasmConversion(WasmType.INT64, WasmType.INT32, false, offset);
|
||||
}
|
||||
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, base, offset);
|
||||
}
|
||||
case "getByte":
|
||||
return new WasmLoadInt32(1, manager.generate(invocation.getArguments().get(0)),
|
||||
WasmInt32Subtype.INT8);
|
||||
case "getShort":
|
||||
return new WasmLoadInt32(2, manager.generate(invocation.getArguments().get(0)),
|
||||
WasmInt32Subtype.INT16);
|
||||
case "getChar":
|
||||
return new WasmLoadInt32(2, manager.generate(invocation.getArguments().get(0)),
|
||||
WasmInt32Subtype.UINT16);
|
||||
case "getInt":
|
||||
return new WasmLoadInt32(4, manager.generate(invocation.getArguments().get(0)),
|
||||
WasmInt32Subtype.INT32);
|
||||
case "getLong":
|
||||
return new WasmLoadInt64(8, manager.generate(invocation.getArguments().get(0)),
|
||||
WasmInt64Subtype.INT64);
|
||||
case "getFloat":
|
||||
return new WasmLoadFloat32(4, manager.generate(invocation.getArguments().get(0)));
|
||||
case "getDouble":
|
||||
return new WasmLoadFloat64(8, manager.generate(invocation.getArguments().get(0)));
|
||||
case "putByte": {
|
||||
WasmExpression address = manager.generate(invocation.getArguments().get(0));
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
||||
return new WasmStoreInt32(1, address, value, WasmInt32Subtype.INT8);
|
||||
}
|
||||
case "putShort": {
|
||||
WasmExpression address = manager.generate(invocation.getArguments().get(0));
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
||||
return new WasmStoreInt32(2, address, value, WasmInt32Subtype.INT16);
|
||||
}
|
||||
case "putChar": {
|
||||
WasmExpression address = manager.generate(invocation.getArguments().get(0));
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
||||
return new WasmStoreInt32(2, address, value, WasmInt32Subtype.UINT16);
|
||||
}
|
||||
case "putInt": {
|
||||
WasmExpression address = manager.generate(invocation.getArguments().get(0));
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
||||
return new WasmStoreInt32(4, address, value, WasmInt32Subtype.INT32);
|
||||
}
|
||||
case "putLong": {
|
||||
WasmExpression address = manager.generate(invocation.getArguments().get(0));
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
||||
return new WasmStoreInt64(8, address, value, WasmInt64Subtype.INT64);
|
||||
}
|
||||
case "putFloat": {
|
||||
WasmExpression address = manager.generate(invocation.getArguments().get(0));
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
||||
return new WasmStoreFloat32(4, address, value);
|
||||
}
|
||||
case "putDouble": {
|
||||
WasmExpression address = manager.generate(invocation.getArguments().get(0));
|
||||
WasmExpression value = manager.generate(invocation.getArguments().get(1));
|
||||
return new WasmStoreFloat64(8, address, value);
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,8 @@
|
|||
package org.teavm.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.Expr;
|
||||
import org.teavm.wasm.generate.WasmClassGenerator;
|
||||
import org.teavm.wasm.generate.WasmGenerationContext;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
|
||||
public interface WasmIntrinsicManager {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2016 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.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.runtime.RuntimeClass;
|
||||
import org.teavm.wasm.generate.WasmClassGenerator;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.wasm.model.expression.WasmInt32Constant;
|
||||
|
||||
public class WasmRuntimeClassIntrinsic implements WasmIntrinsic {
|
||||
private WasmClassGenerator classGenerator;
|
||||
|
||||
public WasmRuntimeClassIntrinsic(WasmClassGenerator classGenerator) {
|
||||
this.classGenerator = classGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
if (!methodReference.getClassName().equals(RuntimeClass.class.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (methodReference.getName()) {
|
||||
case "getArrayClass":
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getArrayClass":
|
||||
return new WasmInt32Constant(classGenerator.getArrayClassPointer());
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2016 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.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.ConstantExpr;
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.wasm.generate.WasmClassGenerator;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.wasm.model.expression.WasmInt32Constant;
|
||||
|
||||
public class WasmStructureIntrinsic implements WasmIntrinsic {
|
||||
private WasmClassGenerator classGenerator;
|
||||
|
||||
public WasmStructureIntrinsic(WasmClassGenerator classGenerator) {
|
||||
this.classGenerator = classGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
return !methodReference.getClassName().equals(Address.class.getName())
|
||||
&& classGenerator.getClassPointer(methodReference.getClassName()) < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "toAddress":
|
||||
case "cast":
|
||||
return manager.generate(invocation.getArguments().get(0));
|
||||
case "sizeOf": {
|
||||
ValueType.Object type = (ValueType.Object) ((ConstantExpr) invocation.getArguments().get(0)).getValue();
|
||||
return new WasmInt32Constant(classGenerator.getClassSize(type.getClassName()));
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -448,6 +448,7 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
|||
case INT8:
|
||||
case UINT8:
|
||||
append("i32.store8");
|
||||
break;
|
||||
case INT16:
|
||||
case UINT16:
|
||||
append("i32.store16");
|
||||
|
@ -469,6 +470,7 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
|||
case INT8:
|
||||
case UINT8:
|
||||
append("i64.store8");
|
||||
break;
|
||||
case INT16:
|
||||
case UINT16:
|
||||
append("i64.store16");
|
||||
|
|
|
@ -20,7 +20,7 @@ public class Structure {
|
|||
|
||||
public final native Address toAddress();
|
||||
|
||||
public final native int sizeOf(Class<? extends Structure> type);
|
||||
public static native int sizeOf(Class<? extends Structure> type);
|
||||
|
||||
public final native <T extends Structure> T add(T base, int offset);
|
||||
public static native <T extends Structure> T add(T base, int offset);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user