Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.ibm.wala.cast.java.translator.JavaCAst2IRTranslator Maven / Gradle / Ivy
/*
* 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
*/
/*
* Created on Aug 22, 2005
*/
package com.ibm.wala.cast.java.translator;
import com.ibm.wala.cast.ir.translator.AstTranslator;
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
import com.ibm.wala.cast.java.ssa.AstJavaNewEnclosingInstruction;
import com.ibm.wala.cast.java.ssa.EnclosingObjectReference;
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.CAstQualifier;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.CAstType;
import com.ibm.wala.cast.tree.CAstType.Method;
import com.ibm.wala.cast.tree.visit.CAstVisitor;
import com.ibm.wala.cfg.AbstractCFG;
import com.ibm.wala.cfg.IBasicBlock;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.ModuleEntry;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.config.SetOfClasses;
import com.ibm.wala.util.debug.Assertions;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
public class JavaCAst2IRTranslator extends AstTranslator {
private final CAstEntity fSourceEntity;
private final ModuleEntry module;
private final SetOfClasses exclusions;
public JavaCAst2IRTranslator(
ModuleEntry module,
CAstEntity sourceFileEntity,
JavaSourceLoaderImpl loader,
SetOfClasses exclusions) {
super(loader);
fSourceEntity = sourceFileEntity;
this.module = module;
this.exclusions = exclusions;
}
public void translate() {
translate(fSourceEntity, module);
}
public CAstEntity sourceFileEntity() {
return fSourceEntity;
}
public JavaSourceLoaderImpl loader() {
return (JavaSourceLoaderImpl) loader;
}
@Override
protected boolean useDefaultInitValues() {
return true;
}
// Java does not have standalone global variables, and let's not
// adopt the nasty JavaScript practice of creating globals without
// explicit definitions
@Override
protected boolean hasImplicitGlobals() {
return false;
}
@Override
protected TypeReference defaultCatchType() {
return TypeReference.JavaLangThrowable;
}
@Override
protected TypeReference makeType(CAstType type) {
return TypeReference.findOrCreate(
loader.getReference(), TypeName.string2TypeName(type.getName()));
}
// Java globals are disguised as fields (statics), so we should never
// ask this question when parsing Java code
@Override
protected boolean treatGlobalsAsLexicallyScoped() {
Assertions.UNREACHABLE();
return false;
}
@Override
protected void doThrow(WalkContext context, int exception) {
context
.cfg()
.addInstruction(insts.ThrowInstruction(context.cfg().getCurrentInstruction(), exception));
}
@Override
public void doArrayRead(
WalkContext context, int result, int arrayValue, CAstNode arrayRefNode, int[] dimValues) {
TypeReference arrayTypeRef = (TypeReference) arrayRefNode.getChild(1).getValue();
context
.cfg()
.addInstruction(
insts.ArrayLoadInstruction(
context.cfg().getCurrentInstruction(),
result,
arrayValue,
dimValues[0],
arrayTypeRef));
processExceptions(arrayRefNode, context);
}
@Override
public void doArrayWrite(
WalkContext context, int arrayValue, CAstNode arrayRefNode, int[] dimValues, int rval) {
TypeReference arrayTypeRef =
arrayRefNode.getKind() == CAstNode.ARRAY_LITERAL
? ((TypeReference) arrayRefNode.getChild(0).getChild(0).getValue())
.getArrayElementType()
: (TypeReference) arrayRefNode.getChild(1).getValue();
context
.cfg()
.addInstruction(
insts.ArrayStoreInstruction(
context.cfg().getCurrentInstruction(),
arrayValue,
dimValues[0],
rval,
arrayTypeRef));
processExceptions(arrayRefNode, context);
}
@Override
protected void doFieldRead(
WalkContext context, int result, int receiver, CAstNode elt, CAstNode parent) {
// elt is a constant CAstNode whose value is a FieldReference.
FieldReference fieldRef = (FieldReference) elt.getValue();
if (receiver == -1) { // a static field: AstTranslator.getValue() produces
// -1 for null, we hope
context
.cfg()
.addInstruction(
insts.GetInstruction(context.cfg().getCurrentInstruction(), result, fieldRef));
} else {
context
.cfg()
.addInstruction(
insts.GetInstruction(
context.cfg().getCurrentInstruction(), result, receiver, fieldRef));
processExceptions(parent, context);
}
}
@Override
protected void doFieldWrite(
WalkContext context, int receiver, CAstNode elt, CAstNode parent, int rval) {
FieldReference fieldRef = (FieldReference) elt.getValue();
if (receiver == -1) { // a static field: AstTranslator.getValue() produces
// -1 for null, we hope
context
.cfg()
.addInstruction(
insts.PutInstruction(context.cfg().getCurrentInstruction(), rval, fieldRef));
} else {
context
.cfg()
.addInstruction(
insts.PutInstruction(
context.cfg().getCurrentInstruction(), receiver, rval, fieldRef));
processExceptions(parent, context);
}
}
@Override
protected void doMaterializeFunction(
CAstNode n, WalkContext context, int result, int exception, CAstEntity fn) {
// Not possible in Java (no free-standing functions)
Assertions.UNREACHABLE("Real functions in Java??? I don't think so!");
}
@Override
protected void doNewObject(
WalkContext context, CAstNode newNode, int result, Object type, int[] arguments) {
TypeReference typeRef = (TypeReference) type;
NewSiteReference site = NewSiteReference.make(context.cfg().getCurrentInstruction(), typeRef);
if (newNode.getKind() == CAstNode.NEW_ENCLOSING) {
context
.cfg()
.addInstruction(
new AstJavaNewEnclosingInstruction(
context.cfg().getCurrentInstruction(), result, site, arguments[0]));
} else {
context
.cfg()
.addInstruction(
(arguments == null)
? insts.NewInstruction(context.cfg().getCurrentInstruction(), result, site)
: insts.NewInstruction(
context.cfg().getCurrentInstruction(), result, site, arguments));
}
processExceptions(newNode, context);
}
private static void processExceptions(CAstNode n, WalkContext context) {
context.cfg().addPreNode(n, context.getUnwindState());
context.cfg().newBlock(true);
Collection labels = context.getControlFlow().getTargetLabels(n);
for (Object label : labels) {
CAstNode target = context.getControlFlow().getTarget(n, label);
if (target == CAstControlFlowMap.EXCEPTION_TO_EXIT) context.cfg().addPreEdgeToExit(n, true);
else context.cfg().addPreEdge(n, target, true);
}
}
@Override
protected void doCall(
WalkContext context,
CAstNode call,
int result,
int exception,
CAstNode name,
int receiver,
int[] arguments) {
assert name.getKind() == CAstNode.CONSTANT;
CallSiteReference dummySiteRef = (CallSiteReference) name.getValue();
int instNumber = context.cfg().getCurrentInstruction();
int pc = instNumber;
boolean isStatic = (receiver == -1);
int[] realArgs = isStatic ? arguments : new int[arguments.length + 1];
Position[] pos;
if (isStatic) {
pos = new Position[arguments.length];
for (int i = 0; i < arguments.length; i++) {
pos[i] = context.getSourceMap().getPosition(call.getChild(i + 2));
}
} else {
pos = new Position[arguments.length + 1];
pos[0] = context.getSourceMap().getPosition(call.getChild(0));
for (int i = 0; i < arguments.length; i++) {
pos[i + 1] = context.getSourceMap().getPosition(call.getChild(i + 2));
}
}
if (!isStatic) {
realArgs[0] = receiver;
System.arraycopy(arguments, 0, realArgs, 1, arguments.length);
}
CallSiteReference realSiteRef =
CallSiteReference.make(
pc, dummySiteRef.getDeclaredTarget(), dummySiteRef.getInvocationCode());
if (realSiteRef.getDeclaredTarget().getReturnType().equals(TypeReference.Void))
context
.cfg()
.addInstruction(
new AstJavaInvokeInstruction(instNumber, realArgs, exception, realSiteRef));
else
context
.cfg()
.addInstruction(
new AstJavaInvokeInstruction(instNumber, result, realArgs, exception, realSiteRef));
context.cfg().noteOperands(instNumber, pos);
processExceptions(call, context);
}
@Override
protected void doGlobalWrite(WalkContext context, String name, TypeReference type, int rval) {
Assertions.UNREACHABLE("doGlobalWrite() called for Java code???");
}
@Override
protected void defineField(CAstEntity topEntity, WalkContext definingContext, CAstEntity n) {
assert topEntity.getKind() == CAstEntity.TYPE_ENTITY;
assert n.getKind() == CAstEntity.FIELD_ENTITY;
// N.B.: base class may actually ask to create a synthetic type to wrap
// code bodies, so we may see other things than TYPE_ENTITY here.
TypeName ownerName = makeType(topEntity.getType()).getName();
IClass owner = loader.lookupClass(ownerName);
assert owner != null || exclusions.contains(ownerName.toString())
: ownerName + " not found in " + loader;
if (owner != null) {
((JavaSourceLoaderImpl) loader).defineField(n, owner);
}
}
// handles abstract method declarations, which do not get defineFunction
// called for them
@Override
protected void declareFunction(CAstEntity N, WalkContext definingContext) {
CAstType.Method methodType = (Method) N.getType();
CAstType owningType = methodType.getDeclaringType();
IClass owner = loader.lookupClass(makeType(owningType).getName());
assert owner != null || exclusions.contains(owningType.getName())
: makeType(owningType).getName().toString() + " not found in " + loader;
if (owner != null && N.getQualifiers().contains(CAstQualifier.ABSTRACT)) {
((JavaSourceLoaderImpl) loader).defineAbstractFunction(N, owner);
}
}
@Override
protected void defineFunction(
CAstEntity N,
WalkContext definingContext,
AbstractCFG> cfg,
SymbolTable symtab,
boolean hasCatchBlock,
Map, TypeReference[]> caughtTypes,
boolean hasMonitorOp,
AstLexicalInformation lexicalInfo,
DebuggingInformation debugInfo) {
// N.B.: base class may actually ask to create a synthetic type to wrap
// code bodies, so we may see other things than TYPE_ENTITY here.
CAstType.Method methodType = (Method) N.getType();
CAstType owningType = methodType.getDeclaringType();
TypeName typeName = makeType(owningType).getName();
IClass owner = loader.lookupClass(typeName);
assert owner != null || exclusions.contains(owningType.getName())
: typeName.toString() + " not found in " + loader;
if (owner != null) {
symtab.getConstant(0);
symtab.getNullConstant();
((JavaSourceLoaderImpl) loader)
.defineFunction(
N,
owner,
cfg,
symtab,
hasCatchBlock,
caughtTypes,
hasMonitorOp,
lexicalInfo,
debugInfo);
}
}
@Override
protected void doPrimitive(int resultVal, WalkContext context, CAstNode primitiveCall) {
// For now, no-op (no primitives in normal Java code)
Assertions.UNREACHABLE("doPrimitive() called for Java code???");
}
@Override
protected String composeEntityName(WalkContext parent, CAstEntity f) {
switch (f.getKind()) {
case CAstEntity.TYPE_ENTITY:
{
return parent.getName().isEmpty() ? f.getName() : parent.getName() + '/' + f.getName();
}
case CAstEntity.FUNCTION_ENTITY:
{
// TODO properly handle types with clashing names/signatures within a
// given method
return parent.getName() + '/' + f.getSignature();
}
default:
{
return parent.getName();
}
}
}
private CAstEntity getEnclosingType(CAstEntity entity) {
if (entity.getQualifiers().contains(CAstQualifier.STATIC)) return null;
else return getEnclosingTypeInternal(getParent(entity));
}
private CAstEntity getEnclosingTypeInternal(CAstEntity entity) {
switch (entity.getKind()) {
case CAstEntity.TYPE_ENTITY:
{
return entity;
}
case CAstEntity.FUNCTION_ENTITY:
{
if (entity.getQualifiers().contains(CAstQualifier.STATIC)) return null;
else return getEnclosingTypeInternal(getParent(entity));
}
case CAstEntity.FILE_ENTITY:
{
return null;
}
default:
{
return getEnclosingTypeInternal(getParent(entity));
}
}
}
@Override
protected boolean defineType(CAstEntity type, WalkContext wc) {
CAstEntity parentType = getEnclosingType(type);
// ((JavaSourceLoaderImpl)loader).defineType(type,
// composeEntityName(wc,type), parentType);
if (exclusions != null && exclusions.contains(type.getType().getName().substring(1))) {
return false;
} else {
return ((JavaSourceLoaderImpl) loader).defineType(type, type.getType().getName(), parentType)
!= null;
}
}
@Override
protected void leaveThis(CAstNode n, WalkContext c, CAstVisitor visitor) {
if (n.getChildCount() == 0) {
super.leaveThis(n, c, visitor);
} else {
int result = c.currentScope().allocateTempValue();
c.setValue(n, result);
c.cfg()
.addInstruction(
new EnclosingObjectReference(
c.cfg().getCurrentInstruction(),
result,
(TypeReference) n.getChild(0).getValue()));
}
}
@Override
protected boolean visitCast(CAstNode n, WalkContext context, CAstVisitor visitor) {
int result = context.currentScope().allocateTempValue();
context.setValue(n, result);
return false;
}
@Override
protected void leaveCast(CAstNode n, WalkContext context, CAstVisitor visitor) {
int result = context.getValue(n);
CAstType toType = (CAstType) n.getChild(0).getValue();
TypeReference toRef = makeType(toType);
CAstType fromType = (CAstType) n.getChild(2).getValue();
TypeReference fromRef = makeType(fromType);
if (toRef.isPrimitiveType()) {
context
.cfg()
.addInstruction(
insts.ConversionInstruction(
context.cfg().getCurrentInstruction(),
result,
context.getValue(n.getChild(1)),
fromRef,
toRef,
false));
} else {
context
.cfg()
.addInstruction(
insts.CheckCastInstruction(
context.cfg().getCurrentInstruction(),
result,
context.getValue(n.getChild(1)),
toRef,
true));
processExceptions(n, context);
}
}
@Override
protected boolean visitInstanceOf(
CAstNode n, WalkContext context, CAstVisitor visitor) {
int result = context.currentScope().allocateTempValue();
context.setValue(n, result);
return false;
}
@Override
protected void leaveInstanceOf(
CAstNode n, WalkContext context, CAstVisitor visitor) {
int result = context.getValue(n);
CAstType type = (CAstType) n.getChild(0).getValue();
TypeReference ref = makeType(type);
context
.cfg()
.addInstruction(
insts.InstanceofInstruction(
context.cfg().getCurrentInstruction(),
result,
context.getValue(n.getChild(1)),
ref));
}
@Override
protected boolean doVisit(CAstNode n, WalkContext wc, CAstVisitor visitor) {
if (n.getKind() == CAstNode.MONITOR_ENTER) {
visitor.visit(n.getChild(0), wc, visitor);
wc.cfg()
.addInstruction(
insts.MonitorInstruction(
wc.cfg().getCurrentInstruction(), wc.getValue(n.getChild(0)), true));
processExceptions(n, wc);
return true;
} else if (n.getKind() == CAstNode.MONITOR_EXIT) {
visitor.visit(n.getChild(0), wc, visitor);
wc.cfg()
.addInstruction(
insts.MonitorInstruction(
wc.cfg().getCurrentInstruction(), wc.getValue(n.getChild(0)), false));
processExceptions(n, wc);
return true;
} else {
return super.doVisit(n, wc, visitor);
}
}
private static CAstType getType(final String name) {
return new CAstType.Class() {
@Override
public Collection getSupertypes() {
return Collections.emptySet();
}
@Override
public String getName() {
return name;
}
@Override
public boolean isInterface() {
return false;
}
@Override
public Collection getQualifiers() {
return Collections.emptySet();
}
};
}
@Override
protected CAstType topType() {
return getType("java.lang.Object");
}
@Override
protected CAstType exceptionType() {
return getType("java.lang.Exception");
}
@Override
protected Position[] getParameterPositions(CAstEntity n) {
int offset = 0;
Position[] parameterPositions = new Position[n.getArgumentCount()];
if ((n.getType() instanceof CAstType.Method) && !((CAstType.Method) n.getType()).isStatic()) {
offset = 1;
}
for (int i = 0; i < n.getArgumentCount() - offset; i++) {
parameterPositions[i + offset] = n.getPosition(i);
}
return parameterPositions;
}
}