mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Add annotations to mark classes and methods supported on some platforms
This commit is contained in:
parent
816434500c
commit
86b5daa3cf
|
@ -16,28 +16,28 @@
|
||||||
package org.teavm.classlib;
|
package org.teavm.classlib;
|
||||||
|
|
||||||
import org.teavm.interop.PlatformMarker;
|
import org.teavm.interop.PlatformMarker;
|
||||||
import org.teavm.interop.PlatformMarkers;
|
import org.teavm.interop.Platforms;
|
||||||
|
|
||||||
public final class PlatformDetector {
|
public final class PlatformDetector {
|
||||||
private PlatformDetector() {
|
private PlatformDetector() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PlatformMarker(PlatformMarkers.WEBASSEMBLY)
|
@PlatformMarker(Platforms.WEBASSEMBLY)
|
||||||
public static boolean isWebAssembly() {
|
public static boolean isWebAssembly() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PlatformMarker(PlatformMarkers.JAVASCRIPT)
|
@PlatformMarker(Platforms.JAVASCRIPT)
|
||||||
public static boolean isJavaScript() {
|
public static boolean isJavaScript() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PlatformMarker(PlatformMarkers.C)
|
@PlatformMarker(Platforms.C)
|
||||||
public static boolean isC() {
|
public static boolean isC() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PlatformMarker(PlatformMarkers.LOW_LEVEL)
|
@PlatformMarker(Platforms.LOW_LEVEL)
|
||||||
public static boolean isLowLevel() {
|
public static boolean isLowLevel() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ import org.teavm.dependency.ClassDependency;
|
||||||
import org.teavm.dependency.DependencyAnalyzer;
|
import org.teavm.dependency.DependencyAnalyzer;
|
||||||
import org.teavm.dependency.DependencyListener;
|
import org.teavm.dependency.DependencyListener;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.interop.PlatformMarkers;
|
import org.teavm.interop.Platforms;
|
||||||
import org.teavm.interop.Structure;
|
import org.teavm.interop.Structure;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.ClassHierarchy;
|
import org.teavm.model.ClassHierarchy;
|
||||||
|
@ -775,7 +775,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getPlatformTags() {
|
public String[] getPlatformTags() {
|
||||||
return new String[] { PlatformMarkers.C, PlatformMarkers.LOW_LEVEL };
|
return new String[] { Platforms.C, Platforms.LOW_LEVEL };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -72,7 +72,7 @@ import org.teavm.dependency.DependencyListener;
|
||||||
import org.teavm.dependency.DependencyType;
|
import org.teavm.dependency.DependencyType;
|
||||||
import org.teavm.dependency.MethodDependency;
|
import org.teavm.dependency.MethodDependency;
|
||||||
import org.teavm.interop.PlatformMarker;
|
import org.teavm.interop.PlatformMarker;
|
||||||
import org.teavm.interop.PlatformMarkers;
|
import org.teavm.interop.Platforms;
|
||||||
import org.teavm.model.AnnotationHolder;
|
import org.teavm.model.AnnotationHolder;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.CallLocation;
|
import org.teavm.model.CallLocation;
|
||||||
|
@ -726,7 +726,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getPlatformTags() {
|
public String[] getPlatformTags() {
|
||||||
return new String[] { PlatformMarkers.JAVASCRIPT };
|
return new String[] { Platforms.JAVASCRIPT };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -100,7 +100,7 @@ import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.interop.DelegateTo;
|
import org.teavm.interop.DelegateTo;
|
||||||
import org.teavm.interop.Import;
|
import org.teavm.interop.Import;
|
||||||
import org.teavm.interop.PlatformMarkers;
|
import org.teavm.interop.Platforms;
|
||||||
import org.teavm.interop.StaticInit;
|
import org.teavm.interop.StaticInit;
|
||||||
import org.teavm.model.AnnotationHolder;
|
import org.teavm.model.AnnotationHolder;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
|
@ -806,7 +806,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getPlatformTags() {
|
public String[] getPlatformTags() {
|
||||||
return new String[] { PlatformMarkers.WEBASSEMBLY, PlatformMarkers.LOW_LEVEL };
|
return new String[] { Platforms.WEBASSEMBLY, Platforms.LOW_LEVEL };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,11 +16,16 @@
|
||||||
package org.teavm.model.util;
|
package org.teavm.model.util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
import org.teavm.dependency.MethodDependencyInfo;
|
import org.teavm.dependency.MethodDependencyInfo;
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
|
import org.teavm.interop.SupportedOn;
|
||||||
|
import org.teavm.interop.UnsupportedOn;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.instructions.*;
|
import org.teavm.model.instructions.*;
|
||||||
import org.teavm.model.optimization.UnreachableBasicBlockEliminator;
|
import org.teavm.model.optimization.UnreachableBasicBlockEliminator;
|
||||||
|
@ -35,14 +40,17 @@ public class MissingItemsProcessor {
|
||||||
private Collection<String> reachableClasses;
|
private Collection<String> reachableClasses;
|
||||||
private Collection<MethodReference> reachableMethods;
|
private Collection<MethodReference> reachableMethods;
|
||||||
private Collection<FieldReference> reachableFields;
|
private Collection<FieldReference> reachableFields;
|
||||||
|
private Set<String> platformTags = new HashSet<>();
|
||||||
|
|
||||||
public MissingItemsProcessor(DependencyInfo dependencyInfo, ClassHierarchy hierarchy, Diagnostics diagnostics) {
|
public MissingItemsProcessor(DependencyInfo dependencyInfo, ClassHierarchy hierarchy, Diagnostics diagnostics,
|
||||||
|
String[] platformTags) {
|
||||||
this.dependencyInfo = dependencyInfo;
|
this.dependencyInfo = dependencyInfo;
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
this.hierarchy = hierarchy;
|
this.hierarchy = hierarchy;
|
||||||
reachableClasses = dependencyInfo.getReachableClasses();
|
reachableClasses = dependencyInfo.getReachableClasses();
|
||||||
reachableMethods = dependencyInfo.getReachableMethods();
|
reachableMethods = dependencyInfo.getReachableMethods();
|
||||||
reachableFields = dependencyInfo.getReachableFields();
|
reachableFields = dependencyInfo.getReachableFields();
|
||||||
|
this.platformTags.addAll(Arrays.asList(platformTags));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processClass(ClassHolder cls) {
|
public void processClass(ClassHolder cls) {
|
||||||
|
@ -132,9 +140,21 @@ public class MissingItemsProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkClass(TextLocation location, String className) {
|
private boolean checkClass(TextLocation location, String className) {
|
||||||
if (!reachableClasses.contains(className) || !dependencyInfo.getClass(className).isMissing()) {
|
if (!reachableClasses.contains(className)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dependencyInfo.getClass(className).isMissing()) {
|
||||||
|
ClassReader cls = dependencyInfo.getClassSource().get(className);
|
||||||
|
if (cls != null && !checkPlatformSupported(cls.getAnnotations())) {
|
||||||
|
diagnostics.error(new CallLocation(methodRef, location), "Class {{c0}} is not supported on "
|
||||||
|
+ "current target", className);
|
||||||
|
emitExceptionThrow(location, NoClassDefFoundError.class.getName(), "Class not found: " + className);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics.error(new CallLocation(methodRef, location), "Class {{c0}} was not found",
|
diagnostics.error(new CallLocation(methodRef, location), "Class {{c0}} was not found",
|
||||||
className);
|
className);
|
||||||
emitExceptionThrow(location, NoClassDefFoundError.class.getName(), "Class not found: " + className);
|
emitExceptionThrow(location, NoClassDefFoundError.class.getName(), "Class not found: " + className);
|
||||||
|
@ -159,14 +179,28 @@ public class MissingItemsProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
MethodDependencyInfo methodDep = dependencyInfo.getMethod(method);
|
MethodDependencyInfo methodDep = dependencyInfo.getMethod(method);
|
||||||
if (!methodDep.isMissing() || !methodDep.isUsed()) {
|
if (!methodDep.isUsed()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!methodDep.isMissing()) {
|
||||||
|
ClassReader cls = dependencyInfo.getClassSource().get(method.getClassName());
|
||||||
|
if (cls != null) {
|
||||||
|
MethodReader methodReader = cls.getMethod(method.getDescriptor());
|
||||||
|
if (methodReader != null && !checkPlatformSupported(methodReader.getAnnotations())) {
|
||||||
|
diagnostics.error(new CallLocation(methodRef, location), "Method {{m0}} is not supported on "
|
||||||
|
+ "current target", method);
|
||||||
|
emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics.error(new CallLocation(methodRef, location), "Method {{m0}} was not found",
|
diagnostics.error(new CallLocation(methodRef, location), "Method {{m0}} was not found",
|
||||||
method);
|
method);
|
||||||
emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method);
|
emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method);
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkVirtualMethod(TextLocation location, MethodReference method) {
|
private boolean checkVirtualMethod(TextLocation location, MethodReference method) {
|
||||||
|
@ -200,6 +234,28 @@ public class MissingItemsProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkPlatformSupported(AnnotationContainerReader annotations) {
|
||||||
|
AnnotationReader supportedAnnot = annotations.get(SupportedOn.class.getName());
|
||||||
|
AnnotationReader unsupportedAnnot = annotations.get(UnsupportedOn.class.getName());
|
||||||
|
if (supportedAnnot != null) {
|
||||||
|
for (AnnotationValue value : supportedAnnot.getValue("value").getList()) {
|
||||||
|
if (platformTags.contains(value.getString())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (unsupportedAnnot != null) {
|
||||||
|
for (AnnotationValue value : unsupportedAnnot.getValue("value").getList()) {
|
||||||
|
if (platformTags.contains(value.getString())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private InstructionVisitor instructionProcessor = new AbstractInstructionVisitor() {
|
private InstructionVisitor instructionProcessor = new AbstractInstructionVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassInstruction insn) {
|
public void visit(InitClassInstruction insn) {
|
||||||
|
|
|
@ -551,7 +551,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
Linker linker = new Linker(dependency);
|
Linker linker = new Linker(dependency);
|
||||||
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
||||||
MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependency,
|
MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependency,
|
||||||
dependency.getClassHierarchy(), diagnostics);
|
dependency.getClassHierarchy(), diagnostics, target.getPlatformTags());
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
return cutClasses;
|
return cutClasses;
|
||||||
}
|
}
|
||||||
|
@ -913,7 +913,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
class PostProcessingClassHolderSource implements ListableClassHolderSource {
|
class PostProcessingClassHolderSource implements ListableClassHolderSource {
|
||||||
private Linker linker = new Linker(dependencyAnalyzer);
|
private Linker linker = new Linker(dependencyAnalyzer);
|
||||||
private MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependencyAnalyzer,
|
private MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependencyAnalyzer,
|
||||||
dependencyAnalyzer.getClassHierarchy(), diagnostics);
|
dependencyAnalyzer.getClassHierarchy(), diagnostics, target.getPlatformTags());
|
||||||
private Map<String, ClassHolder> cache = new HashMap<>();
|
private Map<String, ClassHolder> cache = new HashMap<>();
|
||||||
private Set<String> classNames = Collections.unmodifiableSet(new HashSet<>(
|
private Set<String> classNames = Collections.unmodifiableSet(new HashSet<>(
|
||||||
dependencyAnalyzer.getReachableClasses().stream()
|
dependencyAnalyzer.getReachableClasses().stream()
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.interop;
|
package org.teavm.interop;
|
||||||
|
|
||||||
public final class PlatformMarkers {
|
public final class Platforms {
|
||||||
private PlatformMarkers() {
|
private Platforms() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String JAVASCRIPT = "javascript";
|
public static final String JAVASCRIPT = "javascript";
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 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.interop;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||||
|
public @interface SupportedOn {
|
||||||
|
String[] value();
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 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.interop;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||||
|
public @interface UnsupportedOn {
|
||||||
|
String[] value();
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ import org.teavm.interop.Address;
|
||||||
import org.teavm.interop.DelegateTo;
|
import org.teavm.interop.DelegateTo;
|
||||||
import org.teavm.interop.NoSideEffects;
|
import org.teavm.interop.NoSideEffects;
|
||||||
import org.teavm.interop.PlatformMarker;
|
import org.teavm.interop.PlatformMarker;
|
||||||
import org.teavm.interop.PlatformMarkers;
|
import org.teavm.interop.Platforms;
|
||||||
import org.teavm.interop.Unmanaged;
|
import org.teavm.interop.Unmanaged;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
|
@ -251,7 +251,7 @@ public final class Platform {
|
||||||
return cls.getMetadata().getName();
|
return cls.getMetadata().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PlatformMarker(PlatformMarkers.LOW_LEVEL)
|
@PlatformMarker(Platforms.LOW_LEVEL)
|
||||||
private static boolean isLowLevel() {
|
private static boolean isLowLevel() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user