/*
* Copyright (c) 2009, Ecole Polytechnique Fédérale de Lausanne
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the Ecole Polytechnique Fédérale de Lausanne nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package net.sf.orcc.backends.transform;
import java.util.List;
import net.sf.orcc.ir.BlockIf;
import net.sf.orcc.ir.BlockWhile;
import net.sf.orcc.ir.ExprBinary;
import net.sf.orcc.ir.ExprBool;
import net.sf.orcc.ir.ExprFloat;
import net.sf.orcc.ir.ExprInt;
import net.sf.orcc.ir.ExprList;
import net.sf.orcc.ir.ExprString;
import net.sf.orcc.ir.ExprUnary;
import net.sf.orcc.ir.ExprVar;
import net.sf.orcc.ir.Expression;
import net.sf.orcc.ir.InstAssign;
import net.sf.orcc.ir.InstCall;
import net.sf.orcc.ir.InstLoad;
import net.sf.orcc.ir.InstPhi;
import net.sf.orcc.ir.InstReturn;
import net.sf.orcc.ir.InstStore;
import net.sf.orcc.ir.IrFactory;
import net.sf.orcc.ir.Var;
import net.sf.orcc.ir.util.AbstractIrVisitor;
import net.sf.orcc.ir.util.IrUtil;
import net.sf.orcc.util.util.EcoreHelper;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
*
* This class defines a transformation that transforms literals used in
* instructions into variables. This transformation is needed since XLIM ports
* cannot contain literals.
*
* @author Ghislain Roquier
* @author Herve Yviquel
*
*/
public class LiteralIntegersAdder extends AbstractIrVisitor<Expression> {
@Override
public Expression caseExprBinary(ExprBinary expr) {
expr.setE1(doSwitch(expr.getE1()));
expr.setE2(doSwitch(expr.getE2()));
return expr;
}
@Override
public Expression caseExprBool(ExprBool expr) {
return createExprVarAndAssign(expr);
}
@Override
public Expression caseExprFloat(ExprFloat expr) {
return createExprVarAndAssign(expr);
}
@Override
public Expression caseExprInt(ExprInt expr) {
return createExprVarAndAssign(expr);
}
@Override
public Expression caseExprList(ExprList expr) {
List<Expression> newIndexes = transformExpressionList(expr.getValue());
expr.getValue().clear();
expr.getValue().addAll(newIndexes);
return null;
}
@Override
public Expression caseExprString(ExprString expr) {
return expr;
}
@Override
public Expression caseExprUnary(ExprUnary expr) {
expr.setExpr(doSwitch(expr.getExpr()));
return expr;
}
@Override
public Expression caseExprVar(ExprVar expr) {
return expr;
}
@Override
public Expression caseInstAssign(InstAssign assign) {
Expression value = assign.getValue();
if (value.isExprBinary() || value.isExprUnary()) {
assign.setValue(doSwitch(value));
}
return null;
}
@Override
public Expression caseInstCall(InstCall call) {
List<Expression> newArgs = transformExpressionList(EcoreHelper
.getObjects(call, Expression.class));
call.getArguments().clear();
call.getArguments().addAll(
IrFactory.eINSTANCE.createArgsByVal(newArgs));
return null;
}
@Override
public Expression caseInstLoad(InstLoad load) {
List<Expression> newIndexes = transformExpressionList(load.getIndexes());
load.getIndexes().clear();
load.getIndexes().addAll(newIndexes);
return null;
}
@Override
public Expression caseInstPhi(InstPhi phi) {
List<Expression> newIndexes = transformExpressionList(phi.getValues());
phi.getValues().clear();
phi.getValues().addAll(newIndexes);
return null;
}
@Override
public Expression caseInstReturn(InstReturn returnInstr) {
if (!procedure.getReturnType().isVoid()) {
Expression expr = returnInstr.getValue();
returnInstr.setValue(doSwitch(expr));
}
return null;
}
@Override
public Expression caseInstStore(InstStore store) {
store.setValue(doSwitch(store.getValue()));
List<Expression> newIndexes = transformExpressionList(store
.getIndexes());
store.getIndexes().clear();
store.getIndexes().addAll(newIndexes);
return null;
}
@Override
public Expression caseBlockIf(BlockIf blockIf) {
blockIf.setCondition(doSwitch(blockIf.getCondition()));
doSwitch(blockIf.getThenBlocks());
doSwitch(blockIf.getElseBlocks());
doSwitch(blockIf.getJoinBlock());
return null;
}
@Override
public Expression caseBlockWhile(BlockWhile blockWhile) {
blockWhile.setCondition(doSwitch(blockWhile.getCondition()));
doSwitch(blockWhile.getBlocks());
doSwitch(blockWhile.getJoinBlock());
return null;
}
private Expression createExprVarAndAssign(Expression expr) {
Var target = procedure.newTempLocalVariable(
EcoreUtil.copy(expr.getType()), "literal");
InstAssign assign = IrFactory.eINSTANCE.createInstAssign(target,
IrUtil.copy(expr));
IrUtil.addInstBeforeExpr(expr, assign);
return IrFactory.eINSTANCE.createExprVar(target);
}
private List<Expression> transformExpressionList(
Iterable<Expression> expressions) {
List<Expression> oldExpressions = new BasicEList<Expression>();
for (Expression expr : expressions) {
oldExpressions.add(expr);
}
EList<Expression> newExpressions = new BasicEList<Expression>();
for (int i = 0; i < oldExpressions.size();) {
Expression expression = oldExpressions.get(i);
newExpressions.add(doSwitch(expression));
if (expression != null) {
i++;
}
}
return newExpressions;
}
}