/*
* CanonizationVisitor.java - This file is part of the Jakstab project.
* Copyright 2007-2015 Johannes Kinder <jk@jakstab.org>
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
*/
package org.jakstab.ssl;
import org.jakstab.rtl.expressions.*;
import org.jakstab.util.Logger;
/**
* @author Johannes Kinder
*/
public class CanonizationVisitor implements ExpressionVisitor<RTLExpression> {
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(CanonizationVisitor.class);
public CanonizationVisitor() {
super();
}
/*
* @see org.jakstab.rtl.ExpressionVisitor#visit(org.jakstab.rtl.RTLBitRange)
*/
@Override
public RTLExpression visit(RTLBitRange e) {
return ExpressionFactory.createBitRange(e.getOperand().accept(this),
e.getFirstBitIndex().accept(this),
e.getLastBitIndex().accept(this));
}
/*
* @see org.jakstab.rtl.ExpressionVisitor#visit(org.jakstab.rtl.RTLConditionalExpression)
*/
@Override
public RTLExpression visit(RTLConditionalExpression e) {
RTLExpression cond = e.getCondition().accept(this);
if (cond instanceof RTLNumber) { /* static evaluation possible */
if (((RTLNumber)cond).longValue() == 0L) {
//logger.debug("Collapsing conditional expression to FALSE-branch.");
return e.getFalseExpression().accept(this);
}
else {
//logger.debug("Collapsing conditional expression to TRUE-branch.");
return e.getTrueExpression().accept(this);
}
} else return ExpressionFactory.createConditionalExpression(cond,
e.getTrueExpression().accept(this),
e.getFalseExpression().accept(this));
}
/*
* @see org.jakstab.rtl.ExpressionVisitor#visit(org.jakstab.rtl.RTLMemoryLocation)
*/
@Override
public RTLExpression visit(RTLMemoryLocation e) {
return ExpressionFactory.createMemoryLocation(
e.getSegmentRegister(), e.getAddress().accept(this), e.getBitWidth());
}
/*
* @see org.jakstab.rtl.ExpressionVisitor#visit(org.jakstab.rtl.RTLNondet)
*/
@Override
public RTLExpression visit(RTLNondet e) {
return e;
}
/*
* @see org.jakstab.rtl.ExpressionVisitor#visit(org.jakstab.rtl.RTLNumber)
*/
@Override
public RTLExpression visit(RTLNumber e) {
return e;
}
/*
* @see org.jakstab.rtl.ExpressionVisitor#visit(org.jakstab.rtl.RTLOperation)
*/
@Override
public RTLExpression visit(RTLOperation e) {
// if there is a conditional expression among the parameters, move it to the front
// and generate a copy of this operation for each branch. Canonize both copies,
// which ensures that the remaining operands are processed as well.
RTLExpression[] operands = e.getOperands();
for(int i=0; i<e.getOperandCount(); i++) {
if (operands[i] instanceof RTLConditionalExpression) {
RTLConditionalExpression cExpr = (RTLConditionalExpression)operands[i];
RTLExpression[] trueOperands = operands.clone();
RTLExpression[] falseOperands = operands.clone();
trueOperands[i] = cExpr.getTrueExpression();
falseOperands[i] = cExpr.getFalseExpression();
return ExpressionFactory.createConditionalExpression(cExpr.getCondition(),
ExpressionFactory.createOperation(e.getOperator(), trueOperands).accept(this),
ExpressionFactory.createOperation(e.getOperator(), falseOperands).accept(this));
}
}
// if no conditionals as operands, just recurse all parameters
RTLExpression[] evaldOperands = new RTLExpression[e.getOperandCount()];
for(int i=0; i<e.getOperandCount(); i++) {
evaldOperands[i] = operands[i].accept(this);
}
return ExpressionFactory.createOperation(e.getOperator(), evaldOperands);
}
/*
* @see org.jakstab.rtl.ExpressionVisitor#visit(org.jakstab.rtl.RTLSpecialExpression)
*/
@Override
public RTLExpression visit(RTLSpecialExpression e) {
// if there is a conditional expression among the parameters, move it to the front
// and generate a copy of this operation for each branch. Canonize both copies,
// which ensures that the remaining operands are processed as well.
RTLExpression[] operands = e.getOperands();
for(int i=0; i<e.getOperandCount(); i++) {
if (operands[i] instanceof RTLConditionalExpression) {
RTLConditionalExpression cExpr = (RTLConditionalExpression)operands[i];
RTLExpression[] trueOperands = operands.clone();
RTLExpression[] falseOperands = operands.clone();
trueOperands[i] = cExpr.getTrueExpression();
falseOperands[i] = cExpr.getFalseExpression();
return ExpressionFactory.createConditionalExpression(cExpr.getCondition(),
ExpressionFactory.createSpecialExpression(e.getOperator(), trueOperands).accept(this),
ExpressionFactory.createSpecialExpression(e.getOperator(), falseOperands).accept(this));
}
}
// if no conditionals as operands, just recurse all parameters
RTLExpression[] evaldOperands = new RTLExpression[e.getOperandCount()];
for(int i=0; i<e.getOperandCount(); i++) {
evaldOperands[i] = operands[i].accept(this);
}
return ExpressionFactory.createSpecialExpression(e.getOperator(), evaldOperands);
}
/*
* @see org.jakstab.rtl.ExpressionVisitor#visit(org.jakstab.rtl.RTLVariable)
*/
@Override
public RTLExpression visit(RTLVariable e) {
return e;
}
}