mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: fix issie with type inference for array set, implement some intrinsics
This commit is contained in:
parent
1ba1dcfc09
commit
f19c211b2a
|
@ -263,9 +263,11 @@ public class WasmGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected WasmExpression storeArrayItem(WasmExpression array, WasmExpression index, WasmExpression value,
|
||||
protected WasmExpression storeArrayItem(WasmExpression array, WasmExpression index, Expr value,
|
||||
ArrayType type) {
|
||||
return storeArrayItem(getArrayElementPointer(array, index, type), value, type);
|
||||
accept(value);
|
||||
var wasmValue = result;
|
||||
return storeArrayItem(getArrayElementPointer(array, index, type), wasmValue, type);
|
||||
}
|
||||
|
||||
private static WasmExpression storeArrayItem(WasmExpression array, WasmExpression value, ArrayType type) {
|
||||
|
|
|
@ -513,12 +513,10 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
var array = result;
|
||||
leftValue.getIndex().acceptVisitor(this);
|
||||
var index = result;
|
||||
rightValue.acceptVisitor(this);
|
||||
var value = result;
|
||||
resultConsumer.add(storeArrayItem(array, index, value, leftValue.getType()));
|
||||
resultConsumer.add(storeArrayItem(array, index, rightValue, leftValue.getType()));
|
||||
}
|
||||
|
||||
protected abstract WasmExpression storeArrayItem(WasmExpression array, WasmExpression index, WasmExpression value,
|
||||
protected abstract WasmExpression storeArrayItem(WasmExpression array, WasmExpression index, Expr value,
|
||||
ArrayType type);
|
||||
|
||||
@Override
|
||||
|
@ -1081,9 +1079,9 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
block.getBody());
|
||||
|
||||
for (int i = 0; i < expr.getData().size(); ++i) {
|
||||
expr.getData().get(i).acceptVisitor(this);
|
||||
var arrayData = unwrapArray(new WasmGetLocal(array));
|
||||
block.getBody().add(storeArrayItem(arrayData, new WasmInt32Constant(i), result, arrayType));
|
||||
block.getBody().add(storeArrayItem(arrayData, new WasmInt32Constant(i), expr.getData().get(i),
|
||||
arrayType));
|
||||
}
|
||||
|
||||
block.getBody().add(new WasmGetLocal(array));
|
||||
|
|
|
@ -562,7 +562,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
|
||||
private WasmFunction generateArrayGetPrimitiveFunction(PrimitiveType type) {
|
||||
var function = new WasmFunction(getArrayGetType());
|
||||
arrayGetObjectFunction.setName(names.topLevel("Array<" + names.suggestForType(ValueType.primitive(type))
|
||||
function.setName(names.topLevel("Array<" + names.suggestForType(ValueType.primitive(type))
|
||||
+ ">::get"));
|
||||
module.functions.add(function);
|
||||
function.setReferenced(true);
|
||||
|
|
|
@ -151,12 +151,14 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected WasmExpression storeArrayItem(WasmExpression array, WasmExpression index, WasmExpression value,
|
||||
protected WasmExpression storeArrayItem(WasmExpression array, WasmExpression index, Expr value,
|
||||
ArrayType type) {
|
||||
array.acceptVisitor(typeInference);
|
||||
var arrayRefType = (WasmType.CompositeReference) typeInference.getResult();
|
||||
var arrayType = (WasmArray) arrayRefType.composite;
|
||||
return new WasmArraySet(arrayType, array, index, value);
|
||||
accept(value, arrayType.getElementType().asUnpackedType());
|
||||
var wasmValue = result;
|
||||
return new WasmArraySet(arrayType, array, index, wasmValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2018 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 org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||
|
||||
public class DoubleIntrinsic implements WasmGCIntrinsic {
|
||||
private static final long EXPONENT_BITS = 0x7FF0000000000000L;
|
||||
private static final long FRACTION_BITS = 0x000FFFFFFFFFFFFFL;
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getNaN":
|
||||
return new WasmFloat64Constant(Double.NaN);
|
||||
case "isNaN":
|
||||
return testNaN(context.generate(invocation.getArguments().get(0)), context);
|
||||
case "isInfinite":
|
||||
return testIsInfinite(context.generate(invocation.getArguments().get(0)));
|
||||
case "isFinite":
|
||||
return testIsFinite(context.generate(invocation.getArguments().get(0)));
|
||||
case "doubleToRawLongBits": {
|
||||
WasmConversion conversion = new WasmConversion(WasmNumType.FLOAT64, WasmNumType.INT64, false,
|
||||
context.generate(invocation.getArguments().get(0)));
|
||||
conversion.setReinterpret(true);
|
||||
return conversion;
|
||||
}
|
||||
case "longBitsToDouble": {
|
||||
WasmConversion conversion = new WasmConversion(WasmNumType.INT64, WasmNumType.FLOAT64, false,
|
||||
context.generate(invocation.getArguments().get(0)));
|
||||
conversion.setReinterpret(true);
|
||||
return conversion;
|
||||
}
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
private WasmExpression testNaN(WasmExpression expression, WasmGCIntrinsicContext context) {
|
||||
var block = new WasmBlock(false);
|
||||
block.setType(WasmType.INT32);
|
||||
var cache = context.exprCache().create(expression, WasmType.FLOAT64, expression.getLocation(),
|
||||
block.getBody());
|
||||
block.getBody().add(new WasmFloatBinary(WasmFloatType.FLOAT64, WasmFloatBinaryOperation.NE,
|
||||
cache.expr(), cache.expr()));
|
||||
cache.release();
|
||||
return block;
|
||||
}
|
||||
|
||||
private WasmExpression testIsInfinite(WasmExpression expression) {
|
||||
var conversion = new WasmConversion(WasmNumType.FLOAT64, WasmNumType.INT64, false, expression);
|
||||
conversion.setReinterpret(true);
|
||||
|
||||
var result = new WasmIntBinary(WasmIntType.INT64, WasmIntBinaryOperation.AND,
|
||||
conversion, new WasmInt64Constant(EXPONENT_BITS));
|
||||
return new WasmIntBinary(WasmIntType.INT64, WasmIntBinaryOperation.EQ, result,
|
||||
new WasmInt64Constant(EXPONENT_BITS));
|
||||
}
|
||||
|
||||
private WasmExpression testIsFinite(WasmExpression expression) {
|
||||
var conversion = new WasmConversion(WasmNumType.FLOAT64, WasmNumType.INT64, false, expression);
|
||||
conversion.setReinterpret(true);
|
||||
|
||||
var result = new WasmIntBinary(WasmIntType.INT64, WasmIntBinaryOperation.AND,
|
||||
conversion, new WasmInt64Constant(EXPONENT_BITS));
|
||||
return new WasmIntBinary(WasmIntType.INT64, WasmIntBinaryOperation.NE, result,
|
||||
new WasmInt64Constant(EXPONENT_BITS));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2018 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 org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloat32Constant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinary;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFloatType;
|
||||
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;
|
||||
|
||||
public class FloatIntrinsic implements WasmGCIntrinsic {
|
||||
private static final int EXPONENT_BITS = 0x7F800000;
|
||||
private static final int FRACTION_BITS = 0x007FFFFF;
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getNaN":
|
||||
return new WasmFloat32Constant(Float.NaN);
|
||||
case "isNaN":
|
||||
return testNaN(manager.generate(invocation.getArguments().get(0)), manager);
|
||||
case "isInfinite":
|
||||
return testIsInfinite(manager.generate(invocation.getArguments().get(0)));
|
||||
case "isFinite":
|
||||
return testIsFinite(manager.generate(invocation.getArguments().get(0)));
|
||||
case "floatToRawIntBits": {
|
||||
var conversion = new WasmConversion(WasmNumType.FLOAT32, WasmNumType.INT32, false,
|
||||
manager.generate(invocation.getArguments().get(0)));
|
||||
conversion.setReinterpret(true);
|
||||
return conversion;
|
||||
}
|
||||
case "intBitsToFloat": {
|
||||
var conversion = new WasmConversion(WasmNumType.INT32, WasmNumType.FLOAT32, false,
|
||||
manager.generate(invocation.getArguments().get(0)));
|
||||
conversion.setReinterpret(true);
|
||||
return conversion;
|
||||
}
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
private WasmExpression testNaN(WasmExpression expression, WasmGCIntrinsicContext context) {
|
||||
var block = new WasmBlock(false);
|
||||
block.setType(WasmType.INT32);
|
||||
var cache = context.exprCache().create(expression, WasmType.FLOAT32, expression.getLocation(),
|
||||
block.getBody());
|
||||
block.getBody().add(new WasmFloatBinary(WasmFloatType.FLOAT32, WasmFloatBinaryOperation.NE,
|
||||
cache.expr(), cache.expr()));
|
||||
cache.release();
|
||||
return block;
|
||||
}
|
||||
|
||||
private WasmExpression testIsInfinite(WasmExpression expression) {
|
||||
var conversion = new WasmConversion(WasmNumType.FLOAT32, WasmNumType.INT32, false, expression);
|
||||
conversion.setReinterpret(true);
|
||||
|
||||
var result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.AND,
|
||||
conversion, new WasmInt32Constant(EXPONENT_BITS));
|
||||
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ, result,
|
||||
new WasmInt32Constant(EXPONENT_BITS));
|
||||
}
|
||||
|
||||
private WasmExpression testIsFinite(WasmExpression expression) {
|
||||
var conversion = new WasmConversion(WasmNumType.FLOAT32, WasmNumType.INT32, false, expression);
|
||||
conversion.setReinterpret(true);
|
||||
|
||||
var result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.AND,
|
||||
conversion, new WasmInt32Constant(EXPONENT_BITS));
|
||||
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.NE, result,
|
||||
new WasmInt32Constant(EXPONENT_BITS));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2024 konsoletyper.
|
||||
*
|
||||
* 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 org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmNumType;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||
import org.teavm.backend.wasm.model.expression.WasmConversion;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
|
||||
public class SystemIntrinsic implements WasmGCIntrinsic {
|
||||
private WasmFunction workerFunction;
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
if (workerFunction == null) {
|
||||
workerFunction = new WasmFunction(context.functionTypes().of(WasmType.FLOAT64));
|
||||
workerFunction.setName("teavm@currentTimeMillis");
|
||||
workerFunction.setImportName("currentTimeMillis");
|
||||
workerFunction.setImportModule("teavm");
|
||||
context.module().functions.add(workerFunction);
|
||||
}
|
||||
var call = new WasmCall(workerFunction);
|
||||
return new WasmConversion(WasmNumType.FLOAT64, WasmNumType.INT64, true, call);
|
||||
}
|
||||
}
|
|
@ -34,6 +34,8 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
|||
fillClass();
|
||||
fillSystem();
|
||||
fillLongAndInteger();
|
||||
fillFloat();
|
||||
fillDouble();
|
||||
fillArray();
|
||||
}
|
||||
|
||||
|
@ -76,6 +78,8 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
|||
private void fillSystem() {
|
||||
intrinsics.put(new MethodReference(System.class, "arraycopy", Object.class, int.class, Object.class,
|
||||
int.class, int.class, void.class), new SystemArrayCopyIntrinsic());
|
||||
intrinsics.put(new MethodReference(System.class, "currentTimeMillis", long.class),
|
||||
new SystemIntrinsic());
|
||||
}
|
||||
|
||||
private void fillLongAndInteger() {
|
||||
|
@ -93,6 +97,26 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
|||
intrinsic);
|
||||
}
|
||||
|
||||
private void fillFloat() {
|
||||
var intrinsic = new FloatIntrinsic();
|
||||
intrinsics.put(new MethodReference(Float.class, "getNaN", float.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Float.class, "isNaN", float.class, boolean.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Float.class, "isInfinite", float.class, boolean.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Float.class, "isFinite", float.class, boolean.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Float.class, "floatToRawIntBits", float.class, int.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Float.class, "intBitsToFloat", int.class, float.class), intrinsic);
|
||||
}
|
||||
|
||||
private void fillDouble() {
|
||||
var intrinsic = new DoubleIntrinsic();
|
||||
intrinsics.put(new MethodReference(Double.class, "getNaN", double.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Double.class, "isNaN", double.class, boolean.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Double.class, "isInfinite", double.class, boolean.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Double.class, "isFinite", double.class, boolean.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Double.class, "doubleToRawLongBits", double.class, long.class), intrinsic);
|
||||
intrinsics.put(new MethodReference(Double.class, "longBitsToDouble", long.class, double.class), intrinsic);
|
||||
}
|
||||
|
||||
private void fillArray() {
|
||||
var intrinsic = new ArrayIntrinsic();
|
||||
intrinsics.put(new MethodReference(Array.class, "getLength", Object.class, int.class), intrinsic);
|
||||
|
|
|
@ -60,8 +60,10 @@ public class WasmFunction extends WasmEntity {
|
|||
|
||||
public void setImportName(String importName) {
|
||||
this.importName = importName;
|
||||
if (collection != null) {
|
||||
collection.invalidateIndexes();
|
||||
}
|
||||
}
|
||||
|
||||
public String getImportModule() {
|
||||
return importModule;
|
||||
|
|
Loading…
Reference in New Issue
Block a user