WALA/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/analysis/typeInference/AstJavaTypeInference.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());
}
}
}