2007-02-02 17:20:09 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* 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 java.util.Collection;
|
2014-03-16 22:05:49 +00:00
|
|
|
import java.util.Collections;
|
2013-04-11 01:09:10 +00:00
|
|
|
import java.util.Map;
|
2007-07-06 22:08:34 +00:00
|
|
|
|
2007-02-02 17:20:09 +00:00
|
|
|
import com.ibm.wala.cast.ir.translator.AstTranslator;
|
|
|
|
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
|
2007-07-06 22:08:34 +00:00
|
|
|
import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
|
2008-02-18 15:17:16 +00:00
|
|
|
import com.ibm.wala.cast.java.ssa.AstJavaNewEnclosingInstruction;
|
2007-07-06 22:08:34 +00:00
|
|
|
import com.ibm.wala.cast.java.ssa.EnclosingObjectReference;
|
2007-02-02 17:20:09 +00:00
|
|
|
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;
|
2018-06-05 19:00:31 +00:00
|
|
|
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
2007-02-02 17:20:09 +00:00
|
|
|
import com.ibm.wala.cast.tree.CAstType;
|
|
|
|
import com.ibm.wala.cast.tree.CAstType.Method;
|
2007-07-06 22:08:34 +00:00
|
|
|
import com.ibm.wala.cast.tree.visit.CAstVisitor;
|
2007-02-02 17:20:09 +00:00
|
|
|
import com.ibm.wala.cfg.AbstractCFG;
|
2013-04-11 01:09:10 +00:00
|
|
|
import com.ibm.wala.cfg.IBasicBlock;
|
2007-02-02 17:20:09 +00:00
|
|
|
import com.ibm.wala.classLoader.CallSiteReference;
|
|
|
|
import com.ibm.wala.classLoader.IClass;
|
2011-04-14 01:16:36 +00:00
|
|
|
import com.ibm.wala.classLoader.ModuleEntry;
|
2007-02-02 17:20:09 +00:00
|
|
|
import com.ibm.wala.classLoader.NewSiteReference;
|
2017-02-23 15:10:39 +00:00
|
|
|
import com.ibm.wala.ssa.SSAInstruction;
|
2007-02-02 17:20:09 +00:00
|
|
|
import com.ibm.wala.ssa.SymbolTable;
|
|
|
|
import com.ibm.wala.types.FieldReference;
|
|
|
|
import com.ibm.wala.types.TypeName;
|
|
|
|
import com.ibm.wala.types.TypeReference;
|
2007-07-06 22:08:34 +00:00
|
|
|
import com.ibm.wala.util.debug.Assertions;
|
2007-02-02 17:20:09 +00:00
|
|
|
|
|
|
|
public class JavaCAst2IRTranslator extends AstTranslator {
|
2011-04-20 23:08:17 +00:00
|
|
|
private final CAstEntity fSourceEntity;
|
|
|
|
private final ModuleEntry module;
|
|
|
|
|
|
|
|
public JavaCAst2IRTranslator(ModuleEntry module, CAstEntity sourceFileEntity, JavaSourceLoaderImpl loader) {
|
|
|
|
super(loader);
|
|
|
|
fSourceEntity = sourceFileEntity;
|
|
|
|
this.module = module;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void translate() {
|
|
|
|
translate(fSourceEntity, module);
|
|
|
|
}
|
|
|
|
|
|
|
|
public CAstEntity sourceFileEntity() {
|
|
|
|
return fSourceEntity;
|
|
|
|
}
|
|
|
|
|
|
|
|
public JavaSourceLoaderImpl loader() {
|
|
|
|
return (JavaSourceLoaderImpl) loader;
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
protected boolean hasImplicitGlobals() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
protected TypeReference defaultCatchType() {
|
2011-04-27 13:58:56 +00:00
|
|
|
return TypeReference.JavaLangThrowable;
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
protected boolean treatGlobalsAsLexicallyScoped() {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
protected void doThrow(WalkContext context, int exception) {
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(insts.ThrowInstruction(context.cfg().getCurrentInstruction(), exception));
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
public void doArrayRead(WalkContext context, int result, int arrayValue, CAstNode arrayRefNode, int[] dimValues) {
|
|
|
|
TypeReference arrayTypeRef = (TypeReference) arrayRefNode.getChild(1).getValue();
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(insts.ArrayLoadInstruction(context.cfg().getCurrentInstruction(), result, arrayValue, dimValues[0], arrayTypeRef));
|
2011-04-20 23:08:17 +00:00
|
|
|
processExceptions(arrayRefNode, context);
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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();
|
|
|
|
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(insts.ArrayStoreInstruction(context.cfg().getCurrentInstruction(), arrayValue, dimValues[0], rval, arrayTypeRef));
|
2011-04-20 23:08:17 +00:00
|
|
|
|
|
|
|
processExceptions(arrayRefNode, context);
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(insts.GetInstruction(context.cfg().getCurrentInstruction(), result, fieldRef));
|
2011-04-20 23:08:17 +00:00
|
|
|
} else {
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(insts.GetInstruction(context.cfg().getCurrentInstruction(), result, receiver, fieldRef));
|
2011-04-20 23:08:17 +00:00
|
|
|
processExceptions(parent, context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(insts.PutInstruction(context.cfg().getCurrentInstruction(), rval, fieldRef));
|
2011-04-20 23:08:17 +00:00
|
|
|
} else {
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(insts.PutInstruction(context.cfg().getCurrentInstruction(), receiver, rval, fieldRef));
|
2011-04-20 23:08:17 +00:00
|
|
|
processExceptions(parent, context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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!");
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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) {
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(new AstJavaNewEnclosingInstruction(context.cfg().getCurrentInstruction(), result, site, arguments[0]));
|
2011-04-20 23:08:17 +00:00
|
|
|
} else {
|
|
|
|
context.cfg().addInstruction(
|
2014-04-09 11:34:16 +00:00
|
|
|
(arguments == null) ? insts.NewInstruction(context.cfg().getCurrentInstruction(), result, site) : insts.NewInstruction(context.cfg().getCurrentInstruction(), result, site, arguments));
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
processExceptions(newNode, context);
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2017-05-11 15:47:19 +00:00
|
|
|
private static void processExceptions(CAstNode n, WalkContext context) {
|
2011-04-20 23:08:17 +00:00
|
|
|
context.cfg().addPreNode(n, context.getUnwindState());
|
|
|
|
context.cfg().newBlock(true);
|
2007-02-02 17:20:09 +00:00
|
|
|
|
Fix nearly all Eclipse warnings about using raw types
Along the way, I also converted many "for (;;)" loops into modern
"for (:)" loops. I didn't systematically look for all opportunities
to do this, though. I merely made this change where I was already
converting raw Iterator uses into modern Iterator<...> uses.
Better use of generics also allowed many casts to become statically
redundant. I have removed all such redundant casts.
Only three raw-types warnings remain after this batch of fixes. All
three involve raw uses of CallGraphBuilder. I've tried to fix these
too, but it quickly snowballs into a cascade of changes that may or
may not eventually reach a statically-type-save fixed point. I may
give these last few problem areas another go in the future. For now,
though, the hundreds of other fixes seem worth keeping even if there
are a few stragglers.
This commit may change some public APIs, but only by making weaker
type signatures stronger by replacing raw types with generic types.
For example, we may change something like "Set" into "Set<String>",
but we're not adding new arguments, changing any
underlying (post-generics-erasure) types, etc.
2017-07-09 18:38:35 +00:00
|
|
|
Collection<Object> labels = context.getControlFlow().getTargetLabels(n);
|
2007-02-02 17:20:09 +00:00
|
|
|
|
Fix nearly all Eclipse warnings about using raw types
Along the way, I also converted many "for (;;)" loops into modern
"for (:)" loops. I didn't systematically look for all opportunities
to do this, though. I merely made this change where I was already
converting raw Iterator uses into modern Iterator<...> uses.
Better use of generics also allowed many casts to become statically
redundant. I have removed all such redundant casts.
Only three raw-types warnings remain after this batch of fixes. All
three involve raw uses of CallGraphBuilder. I've tried to fix these
too, but it quickly snowballs into a cascade of changes that may or
may not eventually reach a statically-type-save fixed point. I may
give these last few problem areas another go in the future. For now,
though, the hundreds of other fixes seem worth keeping even if there
are a few stragglers.
This commit may change some public APIs, but only by making weaker
type signatures stronger by replacing raw types with generic types.
For example, we may change something like "Set" into "Set<String>",
but we're not adding new arguments, changing any
underlying (post-generics-erasure) types, etc.
2017-07-09 18:38:35 +00:00
|
|
|
for (Object label : labels) {
|
2011-04-20 23:08:17 +00:00
|
|
|
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);
|
2007-04-04 13:03:33 +00:00
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
2007-04-04 13:03:33 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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 pc = context.cfg().getCurrentInstruction();
|
|
|
|
boolean isStatic = (receiver == -1);
|
|
|
|
int[] realArgs = isStatic ? arguments : new int[arguments.length + 1];
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
if (!isStatic) {
|
|
|
|
realArgs[0] = receiver;
|
|
|
|
System.arraycopy(arguments, 0, realArgs, 1, arguments.length);
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
CallSiteReference realSiteRef = CallSiteReference.make(pc, dummySiteRef.getDeclaredTarget(), dummySiteRef.getInvocationCode());
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
if (realSiteRef.getDeclaredTarget().getReturnType().equals(TypeReference.Void))
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(new AstJavaInvokeInstruction(context.cfg().getCurrentInstruction(), realArgs, exception, realSiteRef));
|
2011-04-20 23:08:17 +00:00
|
|
|
else
|
2014-04-09 11:34:16 +00:00
|
|
|
context.cfg().addInstruction(new AstJavaInvokeInstruction(context.cfg().getCurrentInstruction(), result, realArgs, exception, realSiteRef));
|
2011-04-20 23:08:17 +00:00
|
|
|
processExceptions(call, context);
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2014-03-16 22:05:49 +00:00
|
|
|
protected void doGlobalWrite(WalkContext context, String name, TypeReference type, int rval) {
|
2011-04-20 23:08:17 +00:00
|
|
|
Assertions.UNREACHABLE("doGlobalWrite() called for Java code???");
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
protected void defineField(CAstEntity topEntity, WalkContext definingContext, CAstEntity n) {
|
|
|
|
assert topEntity.getKind() == CAstEntity.TYPE_ENTITY;
|
|
|
|
assert n.getKind() == CAstEntity.FIELD_ENTITY;
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
// 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.
|
|
|
|
IClass owner = loader.lookupClass(makeType(topEntity.getType()).getName());
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2017-08-06 01:54:42 +00:00
|
|
|
assert owner != null : makeType(topEntity.getType()).getName() + " not found in " + loader;
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
((JavaSourceLoaderImpl) loader).defineField(n, owner);
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
// handles abstract method declarations, which do not get defineFunction
|
|
|
|
// called for them
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
protected void declareFunction(CAstEntity N, WalkContext definingContext) {
|
|
|
|
CAstType.Method methodType = (Method) N.getType();
|
|
|
|
CAstType owningType = methodType.getDeclaringType();
|
|
|
|
IClass owner = loader.lookupClass(makeType(owningType).getName());
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2017-08-06 01:54:42 +00:00
|
|
|
assert owner != null : makeType(owningType).getName().toString() + " not found in " + loader;
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2018-02-05 23:18:37 +00:00
|
|
|
if (N.getQualifiers().contains(CAstQualifier.ABSTRACT)) {
|
|
|
|
((JavaSourceLoaderImpl) loader).defineAbstractFunction(N, owner);
|
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2017-02-23 15:10:39 +00:00
|
|
|
protected void defineFunction(CAstEntity N, WalkContext definingContext, AbstractCFG<SSAInstruction, ? extends IBasicBlock<SSAInstruction>> cfg, SymbolTable symtab,
|
|
|
|
boolean hasCatchBlock, Map<IBasicBlock<SSAInstruction>,TypeReference[]> caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo,
|
2011-04-20 23:08:17 +00:00
|
|
|
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);
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2017-08-06 01:54:42 +00:00
|
|
|
assert owner != null : typeName.toString() + " not found in " + loader;
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
symtab.getConstant(0);
|
|
|
|
symtab.getNullConstant();
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
((JavaSourceLoaderImpl) loader).defineFunction(N, owner, cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, lexicalInfo,
|
|
|
|
debugInfo);
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
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???");
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
protected String composeEntityName(WalkContext parent, CAstEntity f) {
|
|
|
|
switch (f.getKind()) {
|
|
|
|
case CAstEntity.TYPE_ENTITY: {
|
|
|
|
return (parent.getName().length() == 0) ? f.getName() : parent.getName() + "/" + f.getName();
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
case CAstEntity.FUNCTION_ENTITY: {
|
|
|
|
// TODO properly handle types with clashing names/signatures within a
|
|
|
|
// given method
|
|
|
|
return parent.getName() + "/" + f.getSignature();
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
default: {
|
|
|
|
return parent.getName();
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
private CAstEntity getEnclosingType(CAstEntity entity) {
|
|
|
|
if (entity.getQualifiers().contains(CAstQualifier.STATIC))
|
|
|
|
return null;
|
|
|
|
else
|
|
|
|
return getEnclosingTypeInternal(getParent(entity));
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2011-04-20 23:08:17 +00:00
|
|
|
protected boolean defineType(CAstEntity type, WalkContext wc) {
|
|
|
|
CAstEntity parentType = getEnclosingType(type);
|
|
|
|
// ((JavaSourceLoaderImpl)loader).defineType(type,
|
|
|
|
// composeEntityName(wc,type), parentType);
|
|
|
|
return ((JavaSourceLoaderImpl) loader).defineType(type, type.getType().getName(), parentType) != null;
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-01-27 20:15:33 +00:00
|
|
|
protected void leaveThis(CAstNode n, WalkContext c, CAstVisitor<WalkContext> visitor) {
|
2011-04-20 23:08:17 +00:00
|
|
|
if (n.getChildCount() == 0) {
|
|
|
|
super.leaveThis(n, c, visitor);
|
|
|
|
} else {
|
2012-01-27 20:15:33 +00:00
|
|
|
int result = c.currentScope().allocateTempValue();
|
|
|
|
c.setValue(n, result);
|
2014-04-09 14:29:47 +00:00
|
|
|
c.cfg().addInstruction(new EnclosingObjectReference(c.cfg().getCurrentInstruction(), result, (TypeReference) n.getChild(0).getValue()));
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-01-27 20:15:33 +00:00
|
|
|
protected boolean visitCast(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
|
2011-04-20 23:08:17 +00:00
|
|
|
int result = context.currentScope().allocateTempValue();
|
2012-01-27 20:15:33 +00:00
|
|
|
context.setValue(n, result);
|
2011-04-20 23:08:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-01-27 20:15:33 +00:00
|
|
|
protected void leaveCast(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
|
|
|
|
int result = context.getValue(n);
|
2011-04-20 23:08:17 +00:00
|
|
|
CAstType toType = (CAstType) n.getChild(0).getValue();
|
|
|
|
TypeReference toRef = makeType(toType);
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
CAstType fromType = (CAstType) n.getChild(2).getValue();
|
|
|
|
TypeReference fromRef = makeType(fromType);
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
if (toRef.isPrimitiveType()) {
|
2014-04-09 14:29:47 +00:00
|
|
|
context.cfg().addInstruction(
|
|
|
|
insts.ConversionInstruction(
|
|
|
|
context.cfg().getCurrentInstruction(),
|
2011-12-28 17:03:27 +00:00
|
|
|
result,
|
2012-01-27 20:15:33 +00:00
|
|
|
context.getValue(n.getChild(1)),
|
2011-12-28 17:03:27 +00:00
|
|
|
fromRef,
|
|
|
|
toRef,
|
|
|
|
false));
|
2011-04-20 23:08:17 +00:00
|
|
|
} else {
|
2011-12-28 17:03:27 +00:00
|
|
|
context.cfg().addInstruction(
|
|
|
|
insts.CheckCastInstruction(
|
2014-04-09 14:29:47 +00:00
|
|
|
context.cfg().getCurrentInstruction(),
|
2011-12-28 17:03:27 +00:00
|
|
|
result,
|
2012-01-27 20:15:33 +00:00
|
|
|
context.getValue(n.getChild(1)),
|
2011-12-28 17:03:27 +00:00
|
|
|
toRef,
|
|
|
|
true));
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
processExceptions(n, context);
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-01-27 20:15:33 +00:00
|
|
|
protected boolean visitInstanceOf(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
|
2011-04-20 23:08:17 +00:00
|
|
|
int result = context.currentScope().allocateTempValue();
|
2012-01-27 20:15:33 +00:00
|
|
|
context.setValue(n, result);
|
2011-04-20 23:08:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-01-27 20:15:33 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-01-27 20:15:33 +00:00
|
|
|
protected void leaveInstanceOf(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
|
|
|
|
int result = context.getValue(n);
|
2011-04-20 23:08:17 +00:00
|
|
|
CAstType type = (CAstType) n.getChild(0).getValue();
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2011-12-28 17:03:27 +00:00
|
|
|
TypeReference ref = makeType( type );
|
|
|
|
context.cfg().addInstruction(
|
|
|
|
insts.InstanceofInstruction(
|
2014-04-09 14:29:47 +00:00
|
|
|
context.cfg().getCurrentInstruction(),
|
2011-12-28 17:03:27 +00:00
|
|
|
result,
|
2012-01-27 20:15:33 +00:00
|
|
|
context.getValue(n.getChild(1)),
|
2011-12-28 17:03:27 +00:00
|
|
|
ref));
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-01-27 20:15:33 +00:00
|
|
|
protected boolean doVisit(CAstNode n, WalkContext wc, CAstVisitor<WalkContext> visitor) {
|
2011-04-20 23:08:17 +00:00
|
|
|
if (n.getKind() == CAstNode.MONITOR_ENTER) {
|
|
|
|
visitor.visit(n.getChild(0), wc, visitor);
|
2014-04-09 14:29:47 +00:00
|
|
|
wc.cfg().addInstruction(insts.MonitorInstruction(wc.cfg().getCurrentInstruction(), wc.getValue(n.getChild(0)), true));
|
2011-04-20 23:08:17 +00:00
|
|
|
processExceptions(n, wc);
|
2007-02-07 18:51:19 +00:00
|
|
|
|
2011-04-20 23:08:17 +00:00
|
|
|
return true;
|
|
|
|
} else if (n.getKind() == CAstNode.MONITOR_EXIT) {
|
|
|
|
visitor.visit(n.getChild(0), wc, visitor);
|
2014-04-09 14:29:47 +00:00
|
|
|
wc.cfg().addInstruction(insts.MonitorInstruction(wc.cfg().getCurrentInstruction(), wc.getValue(n.getChild(0)), false));
|
2011-04-20 23:08:17 +00:00
|
|
|
processExceptions(n, wc);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return super.doVisit(n, wc, visitor);
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|
2011-04-20 23:08:17 +00:00
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
|
2017-05-11 15:47:19 +00:00
|
|
|
private static CAstType getType(final String name) {
|
2014-03-16 22:05:49 +00:00
|
|
|
return new CAstType.Class() {
|
|
|
|
|
|
|
|
@Override
|
2017-01-11 13:04:37 +00:00
|
|
|
public Collection<CAstType> getSupertypes() {
|
2014-03-16 22:05:49 +00:00
|
|
|
return Collections.emptySet();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getName() {
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isInterface() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Collection<CAstQualifier> getQualifiers() {
|
|
|
|
return Collections.emptySet();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
@Override
|
|
|
|
protected CAstType topType() {
|
|
|
|
return getType("java.lang.Object");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected CAstType exceptionType() {
|
|
|
|
return getType("java.lang.Exception");
|
|
|
|
}
|
|
|
|
|
2018-06-05 19:00:31 +00:00
|
|
|
@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;
|
|
|
|
}
|
2007-02-02 17:20:09 +00:00
|
|
|
}
|