mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Type analyzer complete
This commit is contained in:
parent
ee10986d05
commit
3e7dc295a1
|
@ -30,6 +30,7 @@ class DependencyGraphBuilder {
|
|||
private DependencyNode resultNode;
|
||||
private Program program;
|
||||
private ValueType resultType;
|
||||
private TypeAnalyzer typeAnalyzer;
|
||||
|
||||
public DependencyGraphBuilder(DependencyChecker dependencyChecker) {
|
||||
this.dependencyChecker = dependencyChecker;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package org.teavm.dependency;
|
||||
|
||||
import org.teavm.model.ClassHolderSource;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.instructions.*;
|
||||
|
||||
/**
|
||||
|
@ -13,9 +12,9 @@ import org.teavm.model.instructions.*;
|
|||
class TypeAnalyzer implements InstructionVisitor {
|
||||
private ClassHolderSource classSource;
|
||||
private ValueType[] types;
|
||||
private int[] definedVars;
|
||||
|
||||
public TypeAnalyzer(ClassHolderSource classSource, int variableCount) {
|
||||
this.classSource = classSource;
|
||||
types = new ValueType[variableCount];
|
||||
}
|
||||
|
||||
|
@ -23,9 +22,74 @@ class TypeAnalyzer implements InstructionVisitor {
|
|||
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;
|
||||
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
|
||||
|
@ -116,6 +180,7 @@ class TypeAnalyzer implements InstructionVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(CastNumberInstruction insn) {
|
||||
define(insn.getReceiver(), map(insn.getTargetType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -144,18 +209,62 @@ class TypeAnalyzer implements InstructionVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(ConstructArrayInstruction insn) {
|
||||
define(insn.getReceiver(), ValueType.arrayOf(insn.getItemType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructInstruction insn) {
|
||||
define(insn.getReceiver(), ValueType.object(insn.getType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
|
@ -164,14 +273,22 @@ class TypeAnalyzer implements InstructionVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(ArrayLengthInstruction insn) {
|
||||
define(insn.getReceiver(), ValueType.INTEGER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CloneArrayInstruction insn) {
|
||||
define(insn.getReceiver(), types[insn.getArray().getIndex()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
|
@ -180,9 +297,17 @@ class TypeAnalyzer implements InstructionVisitor {
|
|||
|
||||
@Override
|
||||
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
|
||||
public void visit(IsInstanceInstruction insn) {
|
||||
define(insn.getReceiver(), ValueType.BOOLEAN);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user