mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Type analyzer complete
This commit is contained in:
parent
ee10986d05
commit
3e7dc295a1
|
@ -30,6 +30,7 @@ class DependencyGraphBuilder {
|
||||||
private DependencyNode resultNode;
|
private DependencyNode resultNode;
|
||||||
private Program program;
|
private Program program;
|
||||||
private ValueType resultType;
|
private ValueType resultType;
|
||||||
|
private TypeAnalyzer typeAnalyzer;
|
||||||
|
|
||||||
public DependencyGraphBuilder(DependencyChecker dependencyChecker) {
|
public DependencyGraphBuilder(DependencyChecker dependencyChecker) {
|
||||||
this.dependencyChecker = dependencyChecker;
|
this.dependencyChecker = dependencyChecker;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
import org.teavm.model.ClassHolderSource;
|
import java.util.HashSet;
|
||||||
import org.teavm.model.MethodHolder;
|
import java.util.Set;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.Variable;
|
|
||||||
import org.teavm.model.instructions.*;
|
import org.teavm.model.instructions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,9 +12,9 @@ import org.teavm.model.instructions.*;
|
||||||
class TypeAnalyzer implements InstructionVisitor {
|
class TypeAnalyzer implements InstructionVisitor {
|
||||||
private ClassHolderSource classSource;
|
private ClassHolderSource classSource;
|
||||||
private ValueType[] types;
|
private ValueType[] types;
|
||||||
private int[] definedVars;
|
|
||||||
|
|
||||||
public TypeAnalyzer(ClassHolderSource classSource, int variableCount) {
|
public TypeAnalyzer(ClassHolderSource classSource, int variableCount) {
|
||||||
|
this.classSource = classSource;
|
||||||
types = new ValueType[variableCount];
|
types = new ValueType[variableCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +22,74 @@ class TypeAnalyzer implements InstructionVisitor {
|
||||||
public void visit(EmptyInstruction insn) {
|
public void visit(EmptyInstruction insn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void define(Variable var, ValueType type) {
|
public ValueType typeOf(int variable) {
|
||||||
|
return types[variable];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void define(Variable var, ValueType type) {
|
||||||
types[var.getIndex()] = type;
|
types[var.getIndex()] = type;
|
||||||
definedVars = new int[] { var.getIndex() };
|
}
|
||||||
|
|
||||||
|
public void merge(Variable var, ValueType type) {
|
||||||
|
if (types[var.getIndex()] == null) {
|
||||||
|
define(var, type);
|
||||||
|
} else {
|
||||||
|
define(var, merge(typeOf(var.getIndex()), type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueType merge(ValueType a, ValueType b) {
|
||||||
|
if (a instanceof ValueType.Array && b instanceof ValueType.Array) {
|
||||||
|
return merge(((ValueType.Array)a).getItemType(), ((ValueType.Array)b).getItemType());
|
||||||
|
} else if (a instanceof ValueType.Object && b instanceof ValueType.Object) {
|
||||||
|
String p = ((ValueType.Object)a).getClassName();
|
||||||
|
String q = ((ValueType.Object)b).getClassName();
|
||||||
|
if (p.equals(q)) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
ClassHolder firstClass = classSource.getClassHolder(p);
|
||||||
|
ClassHolder secondClass = classSource.getClassHolder(q);
|
||||||
|
if (firstClass.getModifiers().contains(ElementModifier.INTERFACE) ||
|
||||||
|
secondClass.getModifiers().contains(ElementModifier.INTERFACE)) {
|
||||||
|
return ValueType.object("java.lang.Object");
|
||||||
|
}
|
||||||
|
if (isSuper(secondClass, firstClass)) {
|
||||||
|
return ValueType.object(secondClass.getName());
|
||||||
|
}
|
||||||
|
Set<String> path = getPathToRoot(firstClass);
|
||||||
|
return ValueType.object(findAmoungSupertypes(secondClass, path));
|
||||||
|
} else {
|
||||||
|
return ValueType.object("java.lang.Object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getPathToRoot(ClassHolder cls) {
|
||||||
|
Set<String> path = new HashSet<>();
|
||||||
|
while (cls != null) {
|
||||||
|
path.add(cls.getName());
|
||||||
|
cls = cls.getParent() != null ? classSource.getClassHolder(cls.getParent()) : null;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSuper(ClassHolder cls, ClassHolder superCls) {
|
||||||
|
while (cls != null) {
|
||||||
|
if (cls == superCls) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cls = cls.getParent() != null ? classSource.getClassHolder(cls.getParent()) : null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String findAmoungSupertypes(ClassHolder cls, Set<String> supertypes) {
|
||||||
|
while (cls != null) {
|
||||||
|
if (supertypes.contains(cls.getName())) {
|
||||||
|
return cls.getName();
|
||||||
|
}
|
||||||
|
cls = cls.getParent() != null ? classSource.getClassHolder(cls.getParent()) : null;
|
||||||
|
}
|
||||||
|
return "java.lang.Object";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -116,6 +180,7 @@ class TypeAnalyzer implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastNumberInstruction insn) {
|
public void visit(CastNumberInstruction insn) {
|
||||||
|
define(insn.getReceiver(), map(insn.getTargetType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -144,18 +209,62 @@ class TypeAnalyzer implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructArrayInstruction insn) {
|
public void visit(ConstructArrayInstruction insn) {
|
||||||
|
define(insn.getReceiver(), ValueType.arrayOf(insn.getItemType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructInstruction insn) {
|
public void visit(ConstructInstruction insn) {
|
||||||
|
define(insn.getReceiver(), ValueType.object(insn.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructMultiArrayInstruction insn) {
|
public void visit(ConstructMultiArrayInstruction insn) {
|
||||||
|
ValueType type = insn.getItemType();
|
||||||
|
for (int i = 0; i < insn.getDimensions().size(); ++i) {
|
||||||
|
type = ValueType.arrayOf(type);
|
||||||
|
}
|
||||||
|
define(insn.getReceiver(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GetFieldInstruction insn) {
|
public void visit(GetFieldInstruction insn) {
|
||||||
|
FieldHolder field = getRealField(new FieldReference(insn.getClassName(), insn.getField()));
|
||||||
|
if (field == null) {
|
||||||
|
throw new RuntimeException("Field not found: " + insn.getClassName() + "." + insn.getField());
|
||||||
|
}
|
||||||
|
define(insn.getReceiver(), field.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldHolder getRealField(FieldReference ref) {
|
||||||
|
String className = ref.getClassName();
|
||||||
|
while (className != null) {
|
||||||
|
ClassHolder cls = classSource.getClassHolder(className);
|
||||||
|
if (cls == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
FieldHolder field = cls.getField(ref.getFieldName());
|
||||||
|
if (field.getLevel() == AccessLevel.PRIVATE && !className.equals(ref.getClassName())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MethodHolder getRealMethod(MethodReference ref) {
|
||||||
|
String className = ref.getClassName();
|
||||||
|
while (className != null) {
|
||||||
|
ClassHolder cls = classSource.getClassHolder(className);
|
||||||
|
if (cls == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MethodHolder method = cls.getMethod(ref.getDescriptor());
|
||||||
|
if (method.getLevel() == AccessLevel.PRIVATE && !className.equals(ref.getClassName())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -164,14 +273,22 @@ class TypeAnalyzer implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ArrayLengthInstruction insn) {
|
public void visit(ArrayLengthInstruction insn) {
|
||||||
|
define(insn.getReceiver(), ValueType.INTEGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CloneArrayInstruction insn) {
|
public void visit(CloneArrayInstruction insn) {
|
||||||
|
define(insn.getReceiver(), types[insn.getArray().getIndex()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GetElementInstruction insn) {
|
public void visit(GetElementInstruction insn) {
|
||||||
|
ValueType type = types[insn.getArray().getIndex()];
|
||||||
|
if (!(type instanceof ValueType.Array)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ValueType itemType = ((ValueType.Array)type).getItemType();
|
||||||
|
define(insn.getReceiver(), itemType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -180,9 +297,17 @@ class TypeAnalyzer implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InvokeInstruction insn) {
|
public void visit(InvokeInstruction insn) {
|
||||||
|
MethodHolder method = getRealMethod(new MethodReference(insn.getClassName(), insn.getMethod()));
|
||||||
|
if (method == null) {
|
||||||
|
throw new RuntimeException("Method not found: " + insn.getMethod());
|
||||||
|
}
|
||||||
|
if (insn.getMethod().getResultType() != ValueType.VOID) {
|
||||||
|
define(insn.getReceiver(), insn.getMethod().getResultType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IsInstanceInstruction insn) {
|
public void visit(IsInstanceInstruction insn) {
|
||||||
|
define(insn.getReceiver(), ValueType.BOOLEAN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user