mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
wasm gc: fix bugs related to casts and implement runtime method for converting date to string
This commit is contained in:
parent
8e2cf27e94
commit
bfd2c8479c
|
@ -373,7 +373,7 @@ public class TDate implements TComparable<TDate> {
|
|||
public String toString() {
|
||||
if (PlatformDetector.isC()) {
|
||||
return toStringC(value);
|
||||
} else if (PlatformDetector.isWebAssembly()) {
|
||||
} else if (PlatformDetector.isWebAssembly() || PlatformDetector.isWebAssemblyGC()) {
|
||||
return toStringWebAssembly(value);
|
||||
} else {
|
||||
return JSDate.create(value).stringValue();
|
||||
|
|
|
@ -170,6 +170,16 @@ public class WasmGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WasmType mapCastSourceType(WasmType type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean validateCastTypes(WasmType sourceType, WasmType targetType, TextLocation location) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WasmExpression peekException() {
|
||||
return new WasmCall(context.functions().forStaticMethod(PEEK_EXCEPTION_METHOD));
|
||||
|
|
|
@ -1184,40 +1184,53 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
|
||||
@Override
|
||||
public void visit(CastExpr expr) {
|
||||
if (expr.isWeak()) {
|
||||
acceptWithType(expr.getValue(), expr.getTarget());
|
||||
result = generateCast(result, mapType(expr.getTarget()));
|
||||
return;
|
||||
}
|
||||
var block = new WasmBlock(false);
|
||||
var wasmTargetType = mapType(expr.getTarget());
|
||||
block.setType(wasmTargetType);
|
||||
block.setLocation(expr.getLocation());
|
||||
|
||||
var wasmTargetType = (WasmType.CompositeReference) mapType(expr.getTarget());
|
||||
acceptWithType(expr.getValue(), expr.getTarget());
|
||||
result.acceptVisitor(typeInference);
|
||||
var wasmSourceType = typeInference.getResult();
|
||||
var valueToCast = exprCache.create(result, wasmSourceType, expr.getLocation(), block.getBody());
|
||||
if (!expr.isWeak()) {
|
||||
result.acceptVisitor(typeInference);
|
||||
var wasmSourceType = typeInference.getResult();
|
||||
if (wasmSourceType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var nullCheck = new WasmBranch(genIsNull(valueToCast.expr()), block);
|
||||
nullCheck.setResult(nullLiteral(wasmTargetType));
|
||||
block.getBody().add(new WasmDrop(nullCheck));
|
||||
wasmSourceType = mapCastSourceType(wasmSourceType);
|
||||
|
||||
var supertypeCall = generateInstanceOf(valueToCast.expr(), expr.getTarget());
|
||||
if (!validateCastTypes(wasmSourceType, wasmTargetType, expr.getLocation())) {
|
||||
return;
|
||||
}
|
||||
|
||||
var breakIfPassed = new WasmBranch(supertypeCall, block);
|
||||
breakIfPassed.setResult(generateCast(valueToCast.expr(), wasmTargetType));
|
||||
block.getBody().add(new WasmDrop(breakIfPassed));
|
||||
var block = new WasmBlock(false);
|
||||
block.setType(wasmSourceType);
|
||||
block.setLocation(expr.getLocation());
|
||||
acceptWithType(expr.getValue(), expr.getTarget());
|
||||
var valueToCast = exprCache.create(result, wasmSourceType, expr.getLocation(), block.getBody());
|
||||
|
||||
var callSiteId = generateCallSiteId(expr.getLocation());
|
||||
callSiteId.generateRegister(block.getBody(), expr.getLocation());
|
||||
generateThrowCCE(expr.getLocation(), block.getBody());
|
||||
callSiteId.generateThrow(block.getBody(), expr.getLocation());
|
||||
var nullCheck = new WasmBranch(genIsNull(valueToCast.expr()), block);
|
||||
nullCheck.setResult(nullLiteral(wasmTargetType));
|
||||
block.getBody().add(new WasmDrop(nullCheck));
|
||||
|
||||
valueToCast.release();
|
||||
result = block;
|
||||
var supertypeCall = generateInstanceOf(valueToCast.expr(), expr.getTarget());
|
||||
|
||||
var breakIfPassed = new WasmBranch(supertypeCall, block);
|
||||
breakIfPassed.setResult(valueToCast.expr());
|
||||
block.getBody().add(new WasmDrop(breakIfPassed));
|
||||
|
||||
var callSiteId = generateCallSiteId(expr.getLocation());
|
||||
callSiteId.generateRegister(block.getBody(), expr.getLocation());
|
||||
generateThrowCCE(expr.getLocation(), block.getBody());
|
||||
callSiteId.generateThrow(block.getBody(), expr.getLocation());
|
||||
|
||||
valueToCast.release();
|
||||
result = block;
|
||||
}
|
||||
result = generateCast(result, wasmTargetType);
|
||||
result.setLocation(expr.getLocation());
|
||||
}
|
||||
|
||||
protected abstract WasmType mapCastSourceType(WasmType type);
|
||||
|
||||
protected abstract boolean validateCastTypes(WasmType sourceType, WasmType targetType, TextLocation location);
|
||||
|
||||
protected abstract WasmExpression generateCast(WasmExpression value, WasmType targetType);
|
||||
|
||||
@Override
|
||||
|
|
|
@ -222,7 +222,7 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
}
|
||||
return new WasmNullConstant(type instanceof WasmType.Reference
|
||||
? (WasmType.Reference) type
|
||||
: WasmType.Reference.STRUCT);
|
||||
: context.classInfoProvider().getClassInfo("java.lang.Object").getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -362,6 +362,39 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
return new WasmCast(value, (WasmType.Reference) targetType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WasmType mapCastSourceType(WasmType type) {
|
||||
if (!(type instanceof WasmType.CompositeReference)) {
|
||||
return type;
|
||||
}
|
||||
var refType = (WasmType.CompositeReference) type;
|
||||
return refType.isNullable() ? refType : refType.composite.getReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean validateCastTypes(WasmType sourceType, WasmType targetType, TextLocation location) {
|
||||
if (!(sourceType instanceof WasmType.CompositeReference)
|
||||
|| !(targetType instanceof WasmType.CompositeReference)) {
|
||||
return false;
|
||||
}
|
||||
var sourceRefType = (WasmType.CompositeReference) sourceType;
|
||||
var targetRefType = (WasmType.CompositeReference) targetType;
|
||||
if (sourceRefType.composite instanceof WasmStructure
|
||||
&& targetRefType.composite instanceof WasmStructure) {
|
||||
var sourceStruct = (WasmStructure) sourceRefType.composite;
|
||||
var targetStruct = (WasmStructure) targetRefType.composite;
|
||||
if (targetStruct.isSupertypeOf(sourceStruct)) {
|
||||
return false;
|
||||
}
|
||||
if (!sourceStruct.isSupertypeOf(targetStruct)) {
|
||||
result = new WasmUnreachable();
|
||||
result.setLocation(location);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsClassInitializer(String className) {
|
||||
return context.classInfoProvider().getClassInfo(className).getInitializerPointer() != null;
|
||||
|
@ -516,6 +549,11 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
|
||||
target.acceptVisitor(typeInference);
|
||||
var type = (WasmType.CompositeReference) typeInference.getResult();
|
||||
if (type == null) {
|
||||
result = new WasmUnreachable();
|
||||
result.setLocation(expr.getLocation());
|
||||
return;
|
||||
}
|
||||
var struct = (WasmStructure) type.composite;
|
||||
var fieldIndex = context.classInfoProvider().getFieldIndex(expr.getField());
|
||||
if (fieldIndex >= 0) {
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package org.teavm.backend.wasm.generate.gc.methods;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
@ -209,7 +211,11 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
|||
generateNativeMethodBody(method, function);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw new RuntimeException("Failed generating method body: " + method.getReference(), e);
|
||||
var buffer = new StringWriter();
|
||||
var printWriter = new PrintWriter(buffer);
|
||||
e.printStackTrace(printWriter);
|
||||
diagnostics.error(new CallLocation(method.getReference()),
|
||||
"Failed generating method body due to internal exception: " + buffer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ public abstract class WasmType {
|
|||
|
||||
private final boolean nullable;
|
||||
|
||||
public Reference(boolean nullable) {
|
||||
Reference(boolean nullable) {
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ TeaVM.wasm = function() {
|
|||
function defaults(imports) {
|
||||
let stderr = "";
|
||||
let stdout = "";
|
||||
let exports;
|
||||
imports.teavm = {
|
||||
putcharStderr(c) {
|
||||
if (c === 10) {
|
||||
|
@ -38,6 +39,9 @@ TeaVM.wasm = function() {
|
|||
},
|
||||
currentTimeMillis() {
|
||||
return new Date().getTime();
|
||||
},
|
||||
dateToString(timestamp, controller) {
|
||||
return stringToJava(new Date(timestamp).toString());
|
||||
}
|
||||
};
|
||||
imports.teavmMath = Math;
|
||||
|
@ -62,21 +66,25 @@ TeaVM.wasm = function() {
|
|||
}));
|
||||
}
|
||||
|
||||
function stringToJava(str) {
|
||||
let sb = exports.createStringBuilder();
|
||||
for (let i = 0; i < str.length; ++i) {
|
||||
exports.appendChar(sb, str.charCodeAt(i));
|
||||
}
|
||||
return exports.buildString(sb);
|
||||
}
|
||||
|
||||
function createMain(instance) {
|
||||
return args => {
|
||||
if (typeof args === "undefined") {
|
||||
args = [];
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let exports = instance.exports;
|
||||
exports = instance.exports;
|
||||
let javaArgs = exports.createStringArray(args.length);
|
||||
for (let i = 0; i < args.length; ++i) {
|
||||
let arg = args[i];
|
||||
let javaArg = exports.createStringBuilder();
|
||||
for (let j = 0; j < arg.length; ++j) {
|
||||
exports.appendChar(javaArg, arg.charCodeAt(j));
|
||||
}
|
||||
exports.setToStringArray(javaArgs, i, exports.buildString(javaArg));
|
||||
exports.setToStringArray(javaArgs, i, stringToJava(args[i]));
|
||||
}
|
||||
try {
|
||||
exports.main(javaArgs);
|
||||
|
|
|
@ -154,6 +154,7 @@ public class TestClockTick extends AbstractTest {
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
|
||||
public void test_tickSeconds_ZoneId() throws Exception {
|
||||
Clock test = Clock.tickSeconds(PARIS);
|
||||
assertEquals(test.getZone(), PARIS);
|
||||
|
|
Loading…
Reference in New Issue
Block a user