diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TDate.java b/classlib/src/main/java/org/teavm/classlib/java/util/TDate.java index 561f86594..42dabe755 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TDate.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TDate.java @@ -16,6 +16,7 @@ package org.teavm.classlib.java.util; import java.util.TimeZone; +import org.teavm.classlib.PlatformDetector; import org.teavm.classlib.java.lang.TComparable; import org.teavm.classlib.java.lang.TSystem; import org.teavm.jso.core.JSDate; @@ -184,7 +185,11 @@ public class TDate implements TComparable { @Override public String toString() { - return JSDate.create(value).stringValue(); + if (PlatformDetector.isLowLevel()) { + return ""; + } else { + return JSDate.create(value).stringValue(); + } } @Deprecated diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java b/classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java index 1bf516650..a4b1b62c8 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java @@ -15,6 +15,7 @@ */ package org.teavm.classlib.java.util.logging; +import org.teavm.classlib.PlatformDetector; import org.teavm.classlib.java.lang.TInteger; import org.teavm.classlib.java.lang.TObject; import org.teavm.classlib.java.lang.TThrowable; @@ -58,12 +59,19 @@ public class TLogger { public void log(TLogRecord record) { String message = format(record.getMessage(), record.getParameters()); - if (record.getLevel().intValue() >= TLevel.SEVERE.intValue()) { - error(message); - } else if (record.getLevel().intValue() >= TLevel.WARNING.intValue()) { - warn(message); + if (PlatformDetector.isLowLevel()) { + System.out.print("["); + System.out.print(record.getLevel().getName()); + System.out.print("] "); + System.out.println(message); } else { - infoImpl(message); + if (record.getLevel().intValue() >= TLevel.SEVERE.intValue()) { + error(message); + } else if (record.getLevel().intValue() >= TLevel.WARNING.intValue()) { + warn(message); + } else { + infoImpl(message); + } } } diff --git a/core/src/main/java/org/teavm/backend/c/CTarget.java b/core/src/main/java/org/teavm/backend/c/CTarget.java index c3de9c33c..9d8dcf0a0 100644 --- a/core/src/main/java/org/teavm/backend/c/CTarget.java +++ b/core/src/main/java/org/teavm/backend/c/CTarget.java @@ -63,6 +63,7 @@ import org.teavm.backend.c.intrinsic.PlatformIntrinsic; import org.teavm.backend.c.intrinsic.PlatformObjectIntrinsic; import org.teavm.backend.c.intrinsic.RuntimeClassIntrinsic; import org.teavm.backend.c.intrinsic.ShadowStackIntrinsic; +import org.teavm.backend.c.intrinsic.StringsIntrinsic; import org.teavm.backend.c.intrinsic.StructureIntrinsic; import org.teavm.backend.lowlevel.dependency.ExceptionHandlingDependencyListener; import org.teavm.backend.lowlevel.transform.CoroutineTransformation; @@ -195,6 +196,9 @@ public class CTarget implements TeaVMTarget, TeaVMCHost { void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(ExceptionHandling.class, "throwNullPointerException", void.class)).use(); + dependencyAnalyzer.linkMethod(new MethodReference(NullPointerException.class, "", void.class)) + .propagate(0, NullPointerException.class.getName()) + .use(); dependencyAnalyzer.linkMethod(new MethodReference(ExceptionHandling.class, "catchException", Throwable.class)).use(); @@ -287,6 +291,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost { intrinsics.add(new FiberIntrinsic()); intrinsics.add(new LongIntrinsic()); intrinsics.add(new IntegerIntrinsic()); + intrinsics.add(new StringsIntrinsic()); List generators = new ArrayList<>(); generators.add(new ArrayGenerator()); diff --git a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java index 82902bff3..da210fe33 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java @@ -15,8 +15,17 @@ */ package org.teavm.backend.c.generate; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.nio.ShortBuffer; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import org.teavm.ast.ArrayType; import org.teavm.ast.AssignmentStatement; @@ -97,6 +106,8 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { private static final MethodReference MONITOR_EXIT_SYNC = new MethodReference(Object.class, "monitorExitSync", Object.class, void.class); + private static final Map BUFFER_TYPES = new HashMap<>(); + private GenerationContext context; private NameProvider names; private CodeWriter writer; @@ -107,6 +118,16 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { private boolean end; private boolean async; + static { + BUFFER_TYPES.put(ByteBuffer.class.getName(), "int8_t"); + BUFFER_TYPES.put(ShortBuffer.class.getName(), "int16_t"); + BUFFER_TYPES.put(CharBuffer.class.getName(), "char16_t"); + BUFFER_TYPES.put(IntBuffer.class.getName(), "int32_t"); + BUFFER_TYPES.put(LongBuffer.class.getName(), "int64_t"); + BUFFER_TYPES.put(FloatBuffer.class.getName(), "float"); + BUFFER_TYPES.put(DoubleBuffer.class.getName(), "double"); + } + public CodeGenerationVisitor(GenerationContext context, CodeWriter writer, Set includes) { this.context = context; this.writer = writer; @@ -469,7 +490,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { } for (int i = 0; i < expr.getArguments().size(); ++i) { - temporaries.add(allocTemporaryVariable(CVariableType.PTR)); + temporaries.add(allocTemporaryVariable(parameterTypeForCall(method, i))); } boolean stringResult = method.getResultType().isObject(String.class); @@ -489,6 +510,13 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { writer.print("ARRAY_DATA("); expr.getArguments().get(i).acceptVisitor(this); writer.print(", ").printStrictType(((ValueType.Array) type).getItemType()).print(")"); + } else if (isPrimitiveBuffer(type)) { + writer.print("ARRAY_DATA(FIELD("); + String typeName = ((ValueType.Object) type).getClassName(); + expr.getArguments().get(i).acceptVisitor(this); + writer.print(", ").print(names.forClass(typeName)).print(", ") + .print(names.forMemberField(new FieldReference(typeName, "array"))).print(")"); + writer.print(", ").print(BUFFER_TYPES.get(typeName)).print(")"); } else { expr.getArguments().get(i).acceptVisitor(this); } @@ -507,7 +535,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { writer.print(", "); } writer.print(temporaries.get(i)); - freeTemporaryVariable(CVariableType.PTR); + freeTemporaryVariable(parameterTypeForCall(method, i)); } writer.print(")"); } else if (method.parameterCount() > 0 || method.getResultType() == ValueType.VOID) { @@ -534,6 +562,14 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { writer.print(")"); } + private CVariableType parameterTypeForCall(MethodReader method, int index) { + if (method.hasModifier(ElementModifier.STATIC)) { + return typeToCType(method.parameterType(index)); + } else { + return index == 0 ? CVariableType.PTR : typeToCType(method.parameterType(index - 1)); + } + } + private static boolean isPrimitiveArray(ValueType type) { if (!(type instanceof ValueType.Array)) { return false; @@ -542,15 +578,28 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { return ((ValueType.Array) type).getItemType() instanceof ValueType.Primitive; } + private static boolean isPrimitiveBuffer(ValueType type) { + if (!(type instanceof ValueType.Object)) { + return false; + } + return BUFFER_TYPES.containsKey(((ValueType.Object) type).getClassName()); + } + private boolean isWrappedNativeCall(MethodReader method) { if (!method.hasModifier(ElementModifier.NATIVE)) { return false; } + if (method.getAnnotations().get(Variable.class.getName()) != null) { + return true; + } for (ValueType type : method.getParameterTypes()) { - if (type.isObject(String.class)) { + if (type.isObject(String.class) || isPrimitiveArray(type) || isPrimitiveBuffer(type)) { return true; } } + if (method.getResultType().isObject(String.class)) { + return true; + } return false; } diff --git a/core/src/main/resources/org/teavm/backend/c/runtime.c b/core/src/main/resources/org/teavm/backend/c/runtime.c index c95c03aba..a44e42a12 100644 --- a/core/src/main/resources/org/teavm/backend/c/runtime.c +++ b/core/src/main/resources/org/teavm/backend/c/runtime.c @@ -305,6 +305,7 @@ static int32_t teavm_timeZoneOffset() { } static char* teavm_stringToC(void*); +static JavaString* teavm_cToString(char*); static inline void teavm_free(void*); static inline int64_t teavm_reinterpretDoubleToLong(double v) {