mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
Address intrinsic (partial)
This commit is contained in:
parent
7d8f5fc9c4
commit
0d8baace3d
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* 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.intrinsics.gc;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.backend.wasm.WasmRuntime;
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmInt32Subtype;
|
||||
import org.teavm.backend.wasm.model.expression.WasmInt64Subtype;
|
||||
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.WasmLoadFloat32;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadFloat64;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt64;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt64;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
public class AddressIntrinsic implements WasmGCIntrinsic {
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext 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(WasmNumType.INT32, WasmNumType.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(WasmNumType.INT64, WasmNumType.INT32, false, value);
|
||||
}
|
||||
case "add": {
|
||||
WasmExpression base = manager.generate(invocation.getArguments().get(0));
|
||||
if (invocation.getMethod().parameterCount() == 1) {
|
||||
WasmExpression offset = manager.generate(invocation.getArguments().get(1));
|
||||
if (invocation.getMethod().parameterType(0) == ValueType.LONG) {
|
||||
offset = new WasmConversion(WasmNumType.INT64, WasmNumType.INT32, false, offset);
|
||||
}
|
||||
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, base, offset);
|
||||
} else {
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
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 "getAddress":
|
||||
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 "putAddress":
|
||||
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);
|
||||
}
|
||||
case "sizeOf":
|
||||
return new WasmInt32Constant(4);
|
||||
case "align": {
|
||||
MethodReference delegate = new MethodReference(WasmRuntime.class.getName(),
|
||||
invocation.getMethod().getDescriptor());
|
||||
WasmCall call = new WasmCall(manager.functions().forStaticMethod(delegate));
|
||||
call.getArguments().addAll(invocation.getArguments().stream()
|
||||
.map(arg -> manager.generate(arg))
|
||||
.collect(Collectors.toList()));
|
||||
return call;
|
||||
}
|
||||
case "isLessThan":
|
||||
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.LT_UNSIGNED,
|
||||
manager.generate(invocation.getArguments().get(0)),
|
||||
manager.generate(invocation.getArguments().get(1)));
|
||||
case "diff": {
|
||||
WasmExpression result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SUB,
|
||||
manager.generate(invocation.getArguments().get(0)),
|
||||
manager.generate(invocation.getArguments().get(1))
|
||||
);
|
||||
result = new WasmConversion(WasmNumType.INT32, WasmNumType.INT64, true, result);
|
||||
result.setLocation(invocation.getLocation());
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -16,8 +16,6 @@
|
|||
package org.teavm.backend.wasm.intrinsics.gc;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
|
||||
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicManager;
|
||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
|
@ -25,11 +23,10 @@ import org.teavm.backend.wasm.model.expression.WasmFill;
|
|||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.DirectMalloc;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.runtime.LaxMalloc;
|
||||
|
||||
public class DirectMallocIntrinsic implements WasmIntrinsic {
|
||||
public class DirectMallocIntrinsic implements WasmGCIntrinsic {
|
||||
private static final MethodReference LAX_MALLOC = new MethodReference(LaxMalloc.class, "laxMalloc", int.class,
|
||||
Address.class);
|
||||
private static final MethodReference LAX_CALLOC = new MethodReference(LaxMalloc.class, "laxCalloc", int.class,
|
||||
|
@ -38,41 +35,22 @@ public class DirectMallocIntrinsic implements WasmIntrinsic {
|
|||
void.class);
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
if (!methodReference.getClassName().equals(DirectMalloc.class.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (methodReference.getName()) {
|
||||
case "malloc":
|
||||
case "calloc":
|
||||
case "free":
|
||||
case "memcpy":
|
||||
case "memset":
|
||||
case "zmemset":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "malloc": {
|
||||
var function = manager.getFunctions().forStaticMethod(LAX_MALLOC);
|
||||
var function = manager.functions().forStaticMethod(LAX_MALLOC);
|
||||
var call = new WasmCall(function);
|
||||
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
||||
return call;
|
||||
}
|
||||
case "calloc": {
|
||||
var function = manager.getFunctions().forStaticMethod(LAX_CALLOC);
|
||||
var function = manager.functions().forStaticMethod(LAX_CALLOC);
|
||||
var call = new WasmCall(function);
|
||||
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
||||
return call;
|
||||
}
|
||||
case "free": {
|
||||
var function = manager.getFunctions().forStaticMethod(LAX_FREE);
|
||||
var function = manager.functions().forStaticMethod(LAX_FREE);
|
||||
var call = new WasmCall(function);
|
||||
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
||||
return call;
|
||||
|
|
|
@ -25,6 +25,8 @@ import org.teavm.backend.wasm.model.expression.WasmIntType;
|
|||
import org.teavm.backend.wasm.runtime.StringInternPool;
|
||||
import org.teavm.backend.wasm.runtime.gc.WasmGCResources;
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.DirectMalloc;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
@ -51,6 +53,8 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
|||
fillArray();
|
||||
fillString();
|
||||
fillResources();
|
||||
fillDirectMalloc();
|
||||
fillAddress();
|
||||
for (var entry : customIntrinsics.entrySet()) {
|
||||
add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
@ -166,6 +170,48 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
|||
add(new MethodReference(WasmGCResources.class, "readSingleByte", int.class, int.class), intrinsic);
|
||||
}
|
||||
|
||||
private void fillDirectMalloc() {
|
||||
var intrinsic = new DirectMallocIntrinsic();
|
||||
add(new MethodReference(DirectMalloc.class, "malloc", int.class, Address.class), intrinsic);
|
||||
add(new MethodReference(DirectMalloc.class, "calloc", int.class, Address.class), intrinsic);
|
||||
add(new MethodReference(DirectMalloc.class, "free", Address.class, void.class), intrinsic);
|
||||
add(new MethodReference(DirectMalloc.class, "memcpy", Address.class, Address.class, int.class, void.class), intrinsic);
|
||||
add(new MethodReference(DirectMalloc.class, "memset", Address.class, int.class, int.class, void.class), intrinsic);
|
||||
add(new MethodReference(DirectMalloc.class, "zmemset", Address.class, int.class, void.class), intrinsic);
|
||||
}
|
||||
|
||||
private void fillAddress() {
|
||||
var intrinsic = new AddressIntrinsic();
|
||||
add(new MethodReference(Address.class, "add", int.class, Address.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "add", long.class, Address.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "isLessThan", Address.class, boolean.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "toInt", int.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "toLong", long.class), intrinsic);
|
||||
//add(new MethodReference(Address.class, "toStructure", ?????), intrinsic); //TODO
|
||||
add(new MethodReference(Address.class, "getByte", byte.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "putByte", byte.class, void.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "getChar", char.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "putChar", char.class, void.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "getShort", short.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "putShort", short.class, void.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "getInt", int.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "putInt", int.class, void.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "getLong", long.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "putLong", long.class, void.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "getFloat", float.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "putFloat", float.class, void.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "getDouble", double.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "putDouble", double.class, void.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "getAddress", Address.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "putAddress", Address.class, void.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "fromInt", int.class, Address.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "fromLong", long.class, Address.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "align", Address.class, int.class, Address.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "sizeOf", int.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "add", Class.class, int.class), intrinsic);
|
||||
add(new MethodReference(Address.class, "diff", Address.class, long.class), intrinsic);
|
||||
}
|
||||
|
||||
private void add(MethodReference methodRef, WasmGCIntrinsic intrinsic) {
|
||||
intrinsics.put(methodRef, new IntrinsicContainer(intrinsic));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user