mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Add support for functions that return true or false depending on whether they run from TeaVM
This commit is contained in:
parent
2f73272ed7
commit
44e6feef0c
|
@ -71,5 +71,7 @@ public class JCLPlugin implements TeaVMPlugin {
|
|||
ReflectionDependencyListener reflection = new ReflectionDependencyListener(reflectionSuppliers);
|
||||
host.registerService(ReflectionDependencyListener.class, reflection);
|
||||
host.add(reflection);
|
||||
|
||||
host.add(new PlatformMarkerSupport());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright 2017 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.impl;
|
||||
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.interop.PlatformMarker;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.FieldReader;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MemberReader;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.GetFieldInstruction;
|
||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.optimization.ConstantConditionElimination;
|
||||
import org.teavm.model.optimization.GlobalValueNumbering;
|
||||
import org.teavm.model.optimization.UnreachableBasicBlockElimination;
|
||||
|
||||
public class PlatformMarkerSupport implements ClassHolderTransformer {
|
||||
@Override
|
||||
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
if (method.getProgram() != null) {
|
||||
transformProgram(method.getReference(), method.getProgram(), innerSource, diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void transformProgram(MethodReference containingMethod, Program program,
|
||||
ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||
boolean hasChanges = false;
|
||||
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (Instruction instruction : block) {
|
||||
Variable receiver;
|
||||
if (instruction instanceof InvokeInstruction) {
|
||||
MethodReference methodRef = ((InvokeInstruction) instruction).getMethod();
|
||||
MethodReader method = innerSource.resolve(methodRef);
|
||||
if (method == null || !isMarker(method)) {
|
||||
continue;
|
||||
}
|
||||
if (!method.hasModifier(ElementModifier.STATIC)) {
|
||||
diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()),
|
||||
"Method '{{m0}}' is marked with '{{c1}}' and should be static",
|
||||
methodRef, PlatformMarker.class.getName());
|
||||
}
|
||||
if (method.getResultType() != ValueType.BOOLEAN) {
|
||||
diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()),
|
||||
"Method '{{m0}}' is marked with '{{c1}}' and should return boolean",
|
||||
methodRef, PlatformMarker.class.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
receiver = ((InvokeInstruction) instruction).getReceiver();
|
||||
} else if (instruction instanceof GetFieldInstruction) {
|
||||
FieldReference fieldRef = ((GetFieldInstruction) instruction).getField();
|
||||
FieldReader field = innerSource.resolve(fieldRef);
|
||||
if (field == null || !isMarker(field)) {
|
||||
continue;
|
||||
}
|
||||
if (!field.hasModifier(ElementModifier.STATIC)) {
|
||||
diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()),
|
||||
"Field '{{f0}}' is marked with '{{c1}}' and should be static",
|
||||
fieldRef, PlatformMarker.class.getName());
|
||||
}
|
||||
if (field.getType() != ValueType.BOOLEAN) {
|
||||
diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()),
|
||||
"Field '{{f0}}' is marked with '{{c1}}' and should be boolean",
|
||||
fieldRef, PlatformMarker.class.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
receiver = ((GetFieldInstruction) instruction).getReceiver();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
hasChanges = true;
|
||||
if (receiver == null) {
|
||||
instruction.delete();
|
||||
} else {
|
||||
IntegerConstantInstruction trueResult = new IntegerConstantInstruction();
|
||||
trueResult.setReceiver(receiver);
|
||||
trueResult.setConstant(1);
|
||||
trueResult.setLocation(instruction.getLocation());
|
||||
instruction.replace(trueResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChanges) {
|
||||
boolean changed;
|
||||
do {
|
||||
changed = new GlobalValueNumbering(true).optimize(program)
|
||||
| new ConstantConditionElimination().optimize(null, program)
|
||||
| new UnreachableBasicBlockElimination().optimize(null, program);
|
||||
} while (changed);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMarker(MemberReader member) {
|
||||
return member.getAnnotations().get(PlatformMarker.class.getName()) != null;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.vm;
|
||||
|
||||
import org.teavm.interop.PlatformMarker;
|
||||
import org.teavm.model.ClassHolderSource;
|
||||
import org.teavm.parsing.ClasspathClassHolderSource;
|
||||
|
||||
|
@ -26,7 +27,7 @@ public class TeaVMBuilder {
|
|||
public TeaVMBuilder(TeaVMTarget target) {
|
||||
this.target = target;
|
||||
classLoader = TeaVMBuilder.class.getClassLoader();
|
||||
classSource = new ClasspathClassHolderSource(classLoader);
|
||||
classSource = !isBootstrap() ? new ClasspathClassHolderSource(classLoader) : name -> null;
|
||||
}
|
||||
|
||||
public ClassHolderSource getClassSource() {
|
||||
|
@ -50,4 +51,9 @@ public class TeaVMBuilder {
|
|||
public TeaVM build() {
|
||||
return new TeaVM(this);
|
||||
}
|
||||
|
||||
@PlatformMarker
|
||||
private static boolean isBootstrap() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2017 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.FIELD, ElementType.METHOD })
|
||||
public @interface PlatformMarker {
|
||||
}
|
Loading…
Reference in New Issue
Block a user