191 lines
6.0 KiB
Java
191 lines
6.0 KiB
Java
/******************************************************************************
|
|
* Copyright (c) 2002 - 2006 IBM Corporation.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial API and implementation
|
|
*****************************************************************************/
|
|
package com.ibm.wala.cast.java.analysis.typeInference;
|
|
|
|
import com.ibm.wala.analysis.typeInference.ConeType;
|
|
import com.ibm.wala.analysis.typeInference.JavaPrimitiveType;
|
|
import com.ibm.wala.analysis.typeInference.PointType;
|
|
import com.ibm.wala.analysis.typeInference.PrimitiveType;
|
|
import com.ibm.wala.analysis.typeInference.TypeAbstraction;
|
|
import com.ibm.wala.analysis.typeInference.TypeVariable;
|
|
import com.ibm.wala.cast.analysis.typeInference.AstTypeInference;
|
|
import com.ibm.wala.cast.ir.ssa.CAstBinaryOp;
|
|
import com.ibm.wala.cast.java.ssa.AstJavaInstructionVisitor;
|
|
import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
|
|
import com.ibm.wala.cast.java.ssa.EnclosingObjectReference;
|
|
import com.ibm.wala.classLoader.IClass;
|
|
import com.ibm.wala.fixpoint.IVariable;
|
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|
import com.ibm.wala.shrikeBT.IBinaryOpInstruction;
|
|
import com.ibm.wala.ssa.IR;
|
|
import com.ibm.wala.ssa.SSABinaryOpInstruction;
|
|
import com.ibm.wala.ssa.SymbolTable;
|
|
import com.ibm.wala.types.TypeReference;
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
|
|
public class AstJavaTypeInference extends AstTypeInference {
|
|
|
|
protected IClass stringClass;
|
|
|
|
protected class AstJavaTypeOperatorFactory extends AstTypeOperatorFactory implements AstJavaInstructionVisitor {
|
|
@Override
|
|
public void visitBinaryOp(SSABinaryOpInstruction instruction) {
|
|
if (doPrimitives) {
|
|
IBinaryOpInstruction.IOperator op = instruction.getOperator();
|
|
if (op == CAstBinaryOp.EQ || op == CAstBinaryOp.NE || op == CAstBinaryOp.LT
|
|
|| op == CAstBinaryOp.GE || op == CAstBinaryOp.GT || op == CAstBinaryOp.LE) {
|
|
result = new DeclaredTypeOperator(language.getPrimitive(language.getConstantType(Boolean.TRUE)));
|
|
} else {
|
|
result = new PrimAndStringOp();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void visitEnclosingObjectReference(EnclosingObjectReference inst) {
|
|
TypeReference type = inst.getEnclosingType();
|
|
IClass klass = cha.lookupClass(type);
|
|
if (klass == null) {
|
|
Assertions.UNREACHABLE();
|
|
} else {
|
|
result = new DeclaredTypeOperator(new ConeType(klass));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
|
|
TypeReference type = instruction.getDeclaredResultType();
|
|
if (type.isReferenceType()) {
|
|
IClass klass = cha.lookupClass(type);
|
|
if (klass == null) {
|
|
// a type that cannot be loaded.
|
|
// be pessimistic
|
|
result = new DeclaredTypeOperator(BOTTOM);
|
|
} else {
|
|
result = new DeclaredTypeOperator(new ConeType(klass));
|
|
}
|
|
} else {
|
|
if (doPrimitives && type.isPrimitiveType()) {
|
|
result = new DeclaredTypeOperator(PrimitiveType.getPrimitive(type));
|
|
} else {
|
|
result = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class AstJavaTypeVarFactory extends TypeVarFactory {
|
|
|
|
@Override
|
|
public IVariable makeVariable(int valueNumber) {
|
|
SymbolTable st = ir.getSymbolTable();
|
|
if (st.isStringConstant(valueNumber)) {
|
|
IClass klass = cha.lookupClass(TypeReference.JavaLangString);
|
|
TypeAbstraction stringTypeAbs = new PointType(klass);
|
|
return new TypeVariable(stringTypeAbs);
|
|
} else {
|
|
return super.makeVariable(valueNumber);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public AstJavaTypeInference(IR ir, IClassHierarchy cha, boolean doPrimitives) {
|
|
super(ir, cha, JavaPrimitiveType.BOOLEAN, doPrimitives);
|
|
}
|
|
|
|
IClass getStringClass() {
|
|
if (stringClass == null) {
|
|
this.stringClass = cha.lookupClass(TypeReference.JavaLangString);
|
|
}
|
|
return stringClass;
|
|
}
|
|
|
|
@Override
|
|
protected void initialize() {
|
|
init(ir, new AstJavaTypeVarFactory(), new AstJavaTypeOperatorFactory());
|
|
}
|
|
|
|
@Override
|
|
public TypeAbstraction getConstantPrimitiveType(int valueNumber) {
|
|
SymbolTable st = ir.getSymbolTable();
|
|
if (st.isBooleanConstant(valueNumber)) {
|
|
return language.getPrimitive(language.getConstantType(Boolean.TRUE));
|
|
} else {
|
|
return super.getConstantPrimitiveType(valueNumber);
|
|
}
|
|
}
|
|
|
|
protected class PrimAndStringOp extends PrimitivePropagateOperator {
|
|
|
|
private PrimAndStringOp() {
|
|
}
|
|
|
|
@Override
|
|
public byte evaluate(TypeVariable lhs, TypeVariable[] rhs) {
|
|
TypeAbstraction meet = null;
|
|
|
|
for (int i = 0; i < rhs.length; i++) {
|
|
if (rhs[i] != null) {
|
|
TypeVariable r = rhs[i];
|
|
TypeAbstraction ta = r.getType();
|
|
if (ta instanceof PointType) {
|
|
if (ta.getType().equals(getStringClass())) {
|
|
meet = new PointType(ta.getType());
|
|
break;
|
|
}
|
|
} else if (ta instanceof ConeType) {
|
|
if (ta.getType().equals(getStringClass())) {
|
|
meet = new PointType(ta.getType());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (meet == null) {
|
|
return super.evaluate(lhs, rhs);
|
|
} else {
|
|
TypeVariable L = lhs;
|
|
TypeAbstraction lhsType = L.getType();
|
|
|
|
if (lhsType.equals(meet)) {
|
|
return NOT_CHANGED;
|
|
} else {
|
|
L.setType(meet);
|
|
return CHANGED;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.wala.dataflow.Operator#hashCode()
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
return 71292;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.wala.dataflow.Operator#equals(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
return o != null && o.getClass().equals(getClass());
|
|
}
|
|
}
|
|
|
|
}
|