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;
|
package org.teavm.backend.wasm.intrinsics.gc;
|
||||||
|
|
||||||
import org.teavm.ast.InvocationExpr;
|
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.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
import org.teavm.backend.wasm.model.expression.WasmCopy;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
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.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.interop.DirectMalloc;
|
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.runtime.LaxMalloc;
|
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,
|
private static final MethodReference LAX_MALLOC = new MethodReference(LaxMalloc.class, "laxMalloc", int.class,
|
||||||
Address.class);
|
Address.class);
|
||||||
private static final MethodReference LAX_CALLOC = new MethodReference(LaxMalloc.class, "laxCalloc", int.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);
|
void.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isApplicable(MethodReference methodReference) {
|
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext manager) {
|
||||||
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) {
|
|
||||||
switch (invocation.getMethod().getName()) {
|
switch (invocation.getMethod().getName()) {
|
||||||
case "malloc": {
|
case "malloc": {
|
||||||
var function = manager.getFunctions().forStaticMethod(LAX_MALLOC);
|
var function = manager.functions().forStaticMethod(LAX_MALLOC);
|
||||||
var call = new WasmCall(function);
|
var call = new WasmCall(function);
|
||||||
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
case "calloc": {
|
case "calloc": {
|
||||||
var function = manager.getFunctions().forStaticMethod(LAX_CALLOC);
|
var function = manager.functions().forStaticMethod(LAX_CALLOC);
|
||||||
var call = new WasmCall(function);
|
var call = new WasmCall(function);
|
||||||
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
case "free": {
|
case "free": {
|
||||||
var function = manager.getFunctions().forStaticMethod(LAX_FREE);
|
var function = manager.functions().forStaticMethod(LAX_FREE);
|
||||||
var call = new WasmCall(function);
|
var call = new WasmCall(function);
|
||||||
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
call.getArguments().add(manager.generate(invocation.getArguments().get(0)));
|
||||||
return call;
|
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.StringInternPool;
|
||||||
import org.teavm.backend.wasm.runtime.gc.WasmGCResources;
|
import org.teavm.backend.wasm.runtime.gc.WasmGCResources;
|
||||||
import org.teavm.common.ServiceRepository;
|
import org.teavm.common.ServiceRepository;
|
||||||
|
import org.teavm.interop.Address;
|
||||||
|
import org.teavm.interop.DirectMalloc;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
@ -51,6 +53,8 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
fillArray();
|
fillArray();
|
||||||
fillString();
|
fillString();
|
||||||
fillResources();
|
fillResources();
|
||||||
|
fillDirectMalloc();
|
||||||
|
fillAddress();
|
||||||
for (var entry : customIntrinsics.entrySet()) {
|
for (var entry : customIntrinsics.entrySet()) {
|
||||||
add(entry.getKey(), entry.getValue());
|
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);
|
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) {
|
private void add(MethodReference methodRef, WasmGCIntrinsic intrinsic) {
|
||||||
intrinsics.put(methodRef, new IntrinsicContainer(intrinsic));
|
intrinsics.put(methodRef, new IntrinsicContainer(intrinsic));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user