soot.jimple.JimpleBody Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of soot Show documentation
Show all versions of soot Show documentation
A Java Optimization Framework
package soot.jimple;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997 - 1999 Raja Vallee-Rai
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import soot.Body;
import soot.Local;
import soot.PatchingChain;
import soot.RefType;
import soot.SootClass;
import soot.SootMethod;
import soot.Type;
import soot.Unit;
import soot.jimple.validation.FieldRefValidator;
import soot.jimple.validation.IdentityStatementsValidator;
import soot.jimple.validation.IdentityValidator;
import soot.jimple.validation.InvokeArgumentValidator;
import soot.jimple.validation.JimpleTrapValidator;
import soot.jimple.validation.MethodValidator;
import soot.jimple.validation.NewValidator;
import soot.jimple.validation.ReturnStatementsValidator;
import soot.jimple.validation.TypesValidator;
import soot.options.Options;
import soot.util.Chain;
import soot.validation.BodyValidator;
import soot.validation.ValidationException;
/**
* Implementation of the Body class for the Jimple IR.
*/
public class JimpleBody extends StmtBody {
private static final Logger logger = LoggerFactory.getLogger(JimpleBody.class);
/**
* Lazy initialized array containing some validators in order to validate the JimpleBody.
*/
private static class LazyValidatorsSingleton {
static final BodyValidator[] V = new BodyValidator[] { IdentityStatementsValidator.v(), TypesValidator.v(),
ReturnStatementsValidator.v(), InvokeArgumentValidator.v(), FieldRefValidator.v(), NewValidator.v(),
JimpleTrapValidator.v(), IdentityValidator.v(), MethodValidator.v() /* InvokeValidator.v() */ };
private LazyValidatorsSingleton() {
}
}
/**
* Construct an empty JimpleBody
*
* @param m
*/
public JimpleBody(SootMethod m) {
super(m);
if (Options.v().verbose()) {
logger.debug("[" + getMethod().getName() + "] Constructing JimpleBody...");
}
}
/**
* Construct an extremely empty JimpleBody, for parsing into.
*/
public JimpleBody() {
}
/**
* Clones the current body, making deep copies of the contents.
*
* @return
*/
@Override
public Object clone() {
Body b = new JimpleBody(getMethodUnsafe());
b.importBodyContentsFrom(this);
return b;
}
@Override
public Object clone(boolean noLocalsClone) {
Body b = new JimpleBody(getMethod());
b.importBodyContentsFrom(this, true);
return b;
}
/**
* Make sure that the JimpleBody is well formed. If not, throw an exception. Right now, performs only a handful of checks.
*/
@Override
public void validate() {
final List exceptionList = new ArrayList();
validate(exceptionList);
if (!exceptionList.isEmpty()) {
throw exceptionList.get(0);
}
}
/**
* Validates the jimple body and saves a list of all validation errors
*
* @param exceptionList
* the list of validation errors
*/
@Override
public void validate(List exceptionList) {
super.validate(exceptionList);
final boolean runAllValidators = Options.v().debug() || Options.v().validate();
for (BodyValidator validator : LazyValidatorsSingleton.V) {
if (runAllValidators || validator.isBasicValidator()) {
validator.validate(this, exceptionList);
}
}
}
public void validateIdentityStatements() {
runValidation(IdentityStatementsValidator.v());
}
/**
* Inserts usual statements for handling this & parameters into body.
*/
public void insertIdentityStmts() {
insertIdentityStmts(getMethod().getDeclaringClass());
}
/**
* Inserts usual statements for handling this & parameters into body.
*
* @param declaringClass
* the class, which should be used for this references. Can be null for static methods
*/
public void insertIdentityStmts(SootClass declaringClass) {
final Jimple jimple = Jimple.v();
final PatchingChain unitChain = this.getUnits();
final Chain localChain = this.getLocals();
Unit lastUnit = null;
// add this-ref before everything else
if (!getMethod().isStatic()) {
if (declaringClass == null) {
throw new IllegalArgumentException(
String.format("No declaring class given for method %s", method.getSubSignature()));
}
Local l = jimple.newLocal("this", RefType.v(declaringClass));
Stmt s = jimple.newIdentityStmt(l, jimple.newThisRef((RefType) l.getType()));
localChain.add(l);
unitChain.addFirst(s);
lastUnit = s;
}
int i = 0;
for (Type t : getMethod().getParameterTypes()) {
Local l = jimple.newLocal("parameter" + i, t);
Stmt s = jimple.newIdentityStmt(l, jimple.newParameterRef(l.getType(), i));
localChain.add(l);
if (lastUnit == null) {
unitChain.addFirst(s);
} else {
unitChain.insertAfter(s, lastUnit);
}
lastUnit = s;
i++;
}
}
/**
* Returns the first non-identity stmt in this body.
*
* @return
*/
public Stmt getFirstNonIdentityStmt() {
Unit r = null;
for (Unit u : getUnits()) {
r = u;
if (!(r instanceof IdentityStmt)) {
break;
}
}
if (r == null) {
throw new RuntimeException("no non-id statements!");
}
return (Stmt) r;
}
}