mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
C backend: make more tests pass
This commit is contained in:
parent
18eb3ee058
commit
ee2f389027
|
@ -29,6 +29,9 @@ public class ClassDependencyListener implements DependencyPlugin {
|
|||
.linkClass(type.getName(), location)
|
||||
.initClass(location));
|
||||
break;
|
||||
case "getSimpleNameCacheLowLevel":
|
||||
method.getResult().propagate(agent.getType("java.lang.String"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.classlib.java.lang;
|
||||
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.model.CallLocation;
|
||||
|
||||
public class ObjectDependencyPlugin implements DependencyPlugin {
|
||||
@Override
|
||||
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getMethod().getName()) {
|
||||
case "clone":
|
||||
method.getVariable(0).connect(method.getResult());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import java.util.Objects;
|
|||
import java.util.Set;
|
||||
import org.teavm.backend.javascript.spi.GeneratedBy;
|
||||
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||
import org.teavm.classlib.PlatformDetector;
|
||||
import org.teavm.classlib.impl.DeclaringClassMetadataGenerator;
|
||||
import org.teavm.classlib.impl.reflection.Flags;
|
||||
import org.teavm.classlib.impl.reflection.JSClass;
|
||||
|
@ -103,24 +104,24 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
|||
return Address.ofObject(this).<RuntimeClass>toStructure().isSupertypeOf.apply(other);
|
||||
}
|
||||
|
||||
@DelegateTo("getNameLowLevel")
|
||||
public TString getName() {
|
||||
if (name == null) {
|
||||
name = TString.wrap(Platform.getName(platformClass));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
private RuntimeObject getNameLowLevel() {
|
||||
RuntimeClass runtimeClass = Address.ofObject(this).toStructure();
|
||||
return runtimeClass.name;
|
||||
public TString getName() {
|
||||
if (PlatformDetector.isLowLevel()) {
|
||||
return TString.wrap(Platform.getName(platformClass));
|
||||
} else {
|
||||
if (name == null) {
|
||||
name = TString.wrap(Platform.getName(platformClass));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public TString getSimpleName() {
|
||||
TString simpleName = getSimpleNameCache();
|
||||
if (simpleName == null) {
|
||||
if (isArray()) {
|
||||
simpleName = getComponentType().getSimpleName().concat(TString.wrap("[]"));
|
||||
setSimpleNameCache(simpleName);
|
||||
return simpleName;
|
||||
}
|
||||
String name = Platform.getName(platformClass);
|
||||
|
@ -137,10 +138,31 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
|||
}
|
||||
}
|
||||
simpleName = TString.wrap(name);
|
||||
setSimpleNameCache(simpleName);
|
||||
}
|
||||
return simpleName;
|
||||
}
|
||||
|
||||
@DelegateTo("getSimpleNameCacheLowLevel")
|
||||
private TString getSimpleNameCache() {
|
||||
return simpleName;
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
@PluggableDependency(ClassDependencyListener.class)
|
||||
private RuntimeObject getSimpleNameCacheLowLevel() {
|
||||
return Address.ofObject(this).<RuntimeClass>toStructure().simpleName;
|
||||
}
|
||||
|
||||
private void setSimpleNameCache(TString value) {
|
||||
simpleName = value;
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
private void setSimpleNameCacheLowLevel(RuntimeObject object) {
|
||||
Address.ofObject(this).<RuntimeClass>toStructure().simpleName = object;
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return Platform.isPrimitive(platformClass);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Async;
|
||||
import org.teavm.interop.DelegateTo;
|
||||
|
@ -223,6 +224,7 @@ public class TObject {
|
|||
|
||||
@Override
|
||||
@DelegateTo("cloneLowLevel")
|
||||
@PluggableDependency(ObjectDependencyPlugin.class)
|
||||
protected Object clone() throws TCloneNotSupportedException {
|
||||
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
|
||||
.getPlatformClass().getMetadata().getArrayItem() == null) {
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.teavm.classlib.java.util.THashMap;
|
|||
import org.teavm.classlib.java.util.TLocale;
|
||||
import org.teavm.classlib.java.util.TMap;
|
||||
import org.teavm.classlib.java.util.regex.TPattern;
|
||||
import org.teavm.interop.Unmanaged;
|
||||
|
||||
public class TString extends TObject implements TSerializable, TComparable<TString>, TCharSequence {
|
||||
public static final TComparator<TString> CASE_INSENSITIVE_ORDER = (o1, o2) -> o1.compareToIgnoreCase(o2);
|
||||
|
@ -578,6 +579,7 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
|
|||
return hashCode;
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
public static TString wrap(String str) {
|
||||
return (TString) (Object) str;
|
||||
}
|
||||
|
|
|
@ -358,7 +358,9 @@ public class CTarget implements TeaVMTarget {
|
|||
writer.println("initHeap(" + minHeapSize + ");");
|
||||
generateVirtualTableHeaders(context, writer, types);
|
||||
generateStringPoolHeaders(context, writer);
|
||||
writer.println("initStaticFields();");
|
||||
generateStaticInitializerCalls(context, writer, classes);
|
||||
writer.println(context.getNames().forClassInitializer("java.lang.String") + "();");
|
||||
generateCallToMainMethod(context, writer);
|
||||
|
||||
writer.outdent().println("}");
|
||||
|
|
|
@ -75,6 +75,7 @@ public class ClassGenerator {
|
|||
private CodeWriter staticGcRootsWriter;
|
||||
private CodeWriter callSiteWriter;
|
||||
private CodeWriter codeWriter;
|
||||
private CodeWriter staticFieldInitWriter;
|
||||
|
||||
public ClassGenerator(GenerationContext context, ClassReaderSource unprocessedClassSource,
|
||||
TagRegistry tagRegistry, Decompiler decompiler, CodeWriter writer) {
|
||||
|
@ -96,6 +97,10 @@ public class ClassGenerator {
|
|||
callSiteWriter = writer.fragment();
|
||||
codeWriter = writer.fragment();
|
||||
|
||||
writer.println("static void initStaticFields() {").indent();
|
||||
staticFieldInitWriter = writer.fragment();
|
||||
writer.outdent().println("}");
|
||||
|
||||
codeGenerator = new CodeGenerator(context, codeWriter, includes);
|
||||
}
|
||||
|
||||
|
@ -236,6 +241,14 @@ public class ClassGenerator {
|
|||
if (isReferenceType(field.getType())) {
|
||||
staticFields[staticIndex++] = field.getReference();
|
||||
}
|
||||
|
||||
Object initialValue = field.getInitialValue();
|
||||
if (initialValue == null) {
|
||||
initialValue = getDefaultValue(field.getType());
|
||||
}
|
||||
staticFieldInitWriter.print(fieldName + " = ");
|
||||
CodeGeneratorUtil.writeValue(staticFieldInitWriter, context, initialValue);
|
||||
staticFieldInitWriter.println(";");
|
||||
} else {
|
||||
String fieldName = context.getNames().forMemberField(field.getReference());
|
||||
structWriter.printStrictType(field.getType()).print(" ").print(fieldName).println(";");
|
||||
|
@ -257,6 +270,31 @@ public class ClassGenerator {
|
|||
structWriter.outdent().print("} ").print(name).println(";");
|
||||
}
|
||||
|
||||
private static Object getDefaultValue(ValueType type) {
|
||||
if (type instanceof ValueType.Primitive) {
|
||||
ValueType.Primitive primitive = (ValueType.Primitive) type;
|
||||
switch (primitive.getKind()) {
|
||||
case BOOLEAN:
|
||||
return false;
|
||||
case BYTE:
|
||||
return (byte) 0;
|
||||
case SHORT:
|
||||
return (short) 0;
|
||||
case INTEGER:
|
||||
return 0;
|
||||
case CHARACTER:
|
||||
return '\0';
|
||||
case LONG:
|
||||
return 0L;
|
||||
case FLOAT:
|
||||
return 0F;
|
||||
case DOUBLE:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void generateForwardClassStructure(ClassHolder cls) {
|
||||
if (isSystemClass(cls)) {
|
||||
return;
|
||||
|
@ -418,6 +456,7 @@ public class ClassGenerator {
|
|||
vtableWriter.print(".").print(classFieldName("tag")).print(" = ").print(String.valueOf(tag)).println(",");
|
||||
vtableWriter.print(".").print(classFieldName("canary")).println(" = 0,");
|
||||
vtableWriter.print(".").print(classFieldName("name")).println(" = stringPool + " + nameRef + ",");
|
||||
vtableWriter.print(".").print(classFieldName("simpleName")).println(" = NULL,");
|
||||
vtableWriter.print(".").print(classFieldName("arrayType")).println(" = " + arrayTypeExpr + ",");
|
||||
vtableWriter.print(".").print(classFieldName("itemType")).println(" = " + itemTypeExpr + ",");
|
||||
vtableWriter.print(".").print(classFieldName("isSupertypeOf")).println(" = &" + superTypeFunction + ",");
|
||||
|
|
|
@ -266,69 +266,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(ConstantExpr expr) {
|
||||
Object value = expr.getValue();
|
||||
|
||||
if (value == null) {
|
||||
writer.print("NULL");
|
||||
} else if (value instanceof String) {
|
||||
int index = context.getStringPool().getStringIndex((String) value);
|
||||
writer.print("(stringPool + " + index + ")");
|
||||
} else if (value instanceof Integer) {
|
||||
int i = (Integer) value;
|
||||
long v = i;
|
||||
if (i < 0) {
|
||||
writer.print("-");
|
||||
v = -i;
|
||||
}
|
||||
writer.print("INT32_C(");
|
||||
writeLongConstant(v);
|
||||
writer.print(")");
|
||||
} else if (value instanceof Long) {
|
||||
long v = (Long) value;
|
||||
if (v < 0) {
|
||||
writer.print("-");
|
||||
v = -v;
|
||||
}
|
||||
writer.print("INT64_C(");
|
||||
writeLongConstant(v);
|
||||
writer.print(")");
|
||||
} else if (value instanceof Float) {
|
||||
float f = (Float) value;
|
||||
if (Float.isInfinite(f)) {
|
||||
if (f < 0) {
|
||||
writer.print("-");
|
||||
}
|
||||
writer.print("INFINITY");
|
||||
} else if (Float.isNaN(f)) {
|
||||
writer.print("NAN");
|
||||
} else {
|
||||
writer.print(f + "f");
|
||||
}
|
||||
} else if (value instanceof Double) {
|
||||
double d = (Double) value;
|
||||
if (Double.isInfinite(d)) {
|
||||
if (d < 0) {
|
||||
writer.print("-");
|
||||
}
|
||||
writer.print("INFINITY");
|
||||
} else if (Double.isNaN(d)) {
|
||||
writer.print("NAN");
|
||||
} else {
|
||||
writer.print(value.toString());
|
||||
}
|
||||
} else if (value instanceof Boolean) {
|
||||
writer.print((Boolean) value ? "1" : "0");
|
||||
} else if (value instanceof ValueType) {
|
||||
writer.print("&").print(names.forClassInstance((ValueType) value));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeLongConstant(long v) {
|
||||
if (v == Long.MIN_VALUE) {
|
||||
writer.print("0x8000000000000000");
|
||||
return;
|
||||
}
|
||||
writer.print(String.valueOf(v));
|
||||
CodeGeneratorUtil.writeValue(writer, context, expr.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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.c.generate;
|
||||
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
public final class CodeGeneratorUtil {
|
||||
private CodeGeneratorUtil() {
|
||||
}
|
||||
|
||||
public static void writeValue(CodeWriter writer, GenerationContext context, Object value) {
|
||||
if (value == null) {
|
||||
writer.print("NULL");
|
||||
} else if (value instanceof String) {
|
||||
int index = context.getStringPool().getStringIndex((String) value);
|
||||
writer.print("(stringPool + " + index + ")");
|
||||
} else if (value instanceof Integer) {
|
||||
int i = (Integer) value;
|
||||
long v = i;
|
||||
if (i < 0) {
|
||||
writer.print("-");
|
||||
v = -i;
|
||||
}
|
||||
writer.print("INT32_C(");
|
||||
writeLongConstant(writer, v);
|
||||
writer.print(")");
|
||||
} else if (value instanceof Long) {
|
||||
long v = (Long) value;
|
||||
if (v < 0) {
|
||||
writer.print("-");
|
||||
v = -v;
|
||||
}
|
||||
writer.print("INT64_C(");
|
||||
writeLongConstant(writer, v);
|
||||
writer.print(")");
|
||||
} else if (value instanceof Float) {
|
||||
float f = (Float) value;
|
||||
if (Float.isInfinite(f)) {
|
||||
if (f < 0) {
|
||||
writer.print("-");
|
||||
}
|
||||
writer.print("INFINITY");
|
||||
} else if (Float.isNaN(f)) {
|
||||
writer.print("NAN");
|
||||
} else {
|
||||
writer.print(f + "f");
|
||||
}
|
||||
} else if (value instanceof Double) {
|
||||
double d = (Double) value;
|
||||
if (Double.isInfinite(d)) {
|
||||
if (d < 0) {
|
||||
writer.print("-");
|
||||
}
|
||||
writer.print("INFINITY");
|
||||
} else if (Double.isNaN(d)) {
|
||||
writer.print("NAN");
|
||||
} else {
|
||||
writer.print(value.toString());
|
||||
}
|
||||
} else if (value instanceof Boolean) {
|
||||
writer.print((Boolean) value ? "1" : "0");
|
||||
} else if (value instanceof ValueType) {
|
||||
writer.print("&").print(context.getNames().forClassInstance((ValueType) value));
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeLongConstant(CodeWriter writer, long v) {
|
||||
if (v == Long.MIN_VALUE) {
|
||||
writer.print("0x8000000000000000");
|
||||
return;
|
||||
}
|
||||
writer.print(String.valueOf(v));
|
||||
}
|
||||
|
||||
}
|
|
@ -22,10 +22,12 @@ import org.teavm.runtime.RuntimeClass;
|
|||
|
||||
public class PlatformClassMetadataIntrinsic implements Intrinsic {
|
||||
private static final String PLATFORM_CLASS_METADATA = "org.teavm.platform.PlatformClassMetadata";
|
||||
private static final FieldReference ARRAY_TYPE_FIELD = new FieldReference(
|
||||
RuntimeClass.class.getName(), "arrayType");
|
||||
private static final FieldReference ITEM_TYPE_FIELD = new FieldReference(
|
||||
RuntimeClass.class.getName(), "itemType");
|
||||
private static final FieldReference SUPERCLASS_FIELD = new FieldReference(
|
||||
RuntimeClass.class.getName(), "parent");
|
||||
private static final FieldReference NAME_FIELD = new FieldReference(
|
||||
RuntimeClass.class.getName(), "name");
|
||||
|
||||
@Override
|
||||
public boolean canHandle(MethodReference method) {
|
||||
|
@ -35,6 +37,7 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic {
|
|||
switch (method.getName()) {
|
||||
case "getArrayItem":
|
||||
case "getSuperclass":
|
||||
case "getName":
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -44,11 +47,14 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic {
|
|||
public void apply(IntrinsicContext context, InvocationExpr invocation) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getArrayItem":
|
||||
printFieldAccess(context, invocation, ARRAY_TYPE_FIELD);
|
||||
printFieldAccess(context, invocation, ITEM_TYPE_FIELD);
|
||||
break;
|
||||
case "getSuperclass":
|
||||
printFieldAccess(context, invocation, SUPERCLASS_FIELD);
|
||||
break;
|
||||
case "getName":
|
||||
printFieldAccess(context, invocation, NAME_FIELD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -222,28 +222,15 @@ public final class Platform {
|
|||
return (cls.flags & RuntimeClass.ENUM) != 0;
|
||||
}
|
||||
|
||||
@DelegateTo("getArrayItemLowLevel")
|
||||
@Unmanaged
|
||||
public static PlatformClass getArrayItem(PlatformClass cls) {
|
||||
return cls.getMetadata().getArrayItem();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Unmanaged
|
||||
private static RuntimeClass getArrayItemLowLevel(RuntimeClass cls) {
|
||||
return cls.itemType;
|
||||
}
|
||||
|
||||
@DelegateTo("getNameLowLevel")
|
||||
public static String getName(PlatformClass cls) {
|
||||
return cls.getMetadata().getName();
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
private static RuntimeObject getNameLowLevel(RuntimeClass cls) {
|
||||
return cls.name;
|
||||
}
|
||||
|
||||
@JSBody(script = "return $rt_global;")
|
||||
private static native JSObject getGlobal();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user