/* * Copyright (c) 2009, IETR/INSA of Rennes * 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 IETR/INSA of Rennes 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.llvm.transform; import java.util.ArrayList; import java.util.List; import net.sf.orcc.df.Actor; import net.sf.orcc.df.util.DfVisitor; import net.sf.orcc.ir.Arg; import net.sf.orcc.ir.ArgByVal; import net.sf.orcc.ir.ExprString; import net.sf.orcc.ir.ExprVar; import net.sf.orcc.ir.Expression; import net.sf.orcc.ir.InstCall; import net.sf.orcc.ir.IrFactory; import net.sf.orcc.ir.Type; import net.sf.orcc.ir.TypeInt; import net.sf.orcc.ir.TypeString; import net.sf.orcc.ir.TypeUint; import net.sf.orcc.ir.Var; import net.sf.orcc.ir.util.AbstractIrVisitor; import org.apache.commons.lang.StringUtils; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.util.EcoreUtil; /** * Change string into global constant. Parameters of println becomes state * variables into the current actor * * @author Jerome Gorin * @author Herve Yviquel * */ public class StringTransformation extends DfVisitor<Void> { protected class PrintTransformer extends AbstractIrVisitor<Void> { public PrintTransformer() { super(true); } @Override public Void caseExprString(ExprString expr) { Var variable = createStringVariable(expr.getValue()); stateVars.add(variable); ExprVar exprVar = factory.createExprVar(variable); EcoreUtil.replace(expr, exprVar); return null; } @Override public Void caseInstCall(InstCall call) { if (call.isPrint()) { transformPrint(call); } else { for (Arg arg : call.getArguments()) { if (arg.isByVal()) { Expression expr = ((ArgByVal) arg).getValue(); if (expr.isExprString()) { // Create state variable that contains println // arguments String strExprVal = (((ExprString) expr).getValue()); Var variable = createStringVariable(strExprVal); stateVars.add(variable); EcoreUtil.replace(arg, factory.createArgByVal(variable)); } } } } return null; } /** * Transform a call of 'print' function to make it compliant with LLVM * assembly language reference. * * @param call * the given call instruction of 'print' function */ protected void transformPrint(InstCall call) { String value = new String(); List<Arg> newArguments = new ArrayList<Arg>(); List<Arg> arguments = call.getArguments(); // Iterate though all the println arguments to provide an only // string value for (Arg arg : arguments) { if (arg.isByVal()) { Expression expr = ((ArgByVal) arg).getValue(); if (expr.isExprString()) { String strExprVal = (((ExprString) expr).getValue()); value += strExprVal; } else { Type type = expr.getType(); if (type.isBool()) { value += "%i"; } else if (type.isFloat()) { value += "%f"; } else if (type.isInt()) { TypeInt intType = (TypeInt) type; if (intType.isLong()) { value += "%ll"; } else { value += "%i"; } } else if (type.isList()) { value += "%p"; } else if (type.isString()) { value += "%s"; } else if (type.isUint()) { TypeUint uintType = (TypeUint) type; if (uintType.isLong()) { value += "%ll"; } else { value += "%u"; } } else if (type.isVoid()) { value += "%p"; } } } } Var variable = createStringVariable(value); stateVars.add(variable); newArguments.add(factory.createArgByVal(variable)); for (Arg arg : arguments) { if (arg.isByVal()) { Expression expr = ((ArgByVal) arg).getValue(); if (!expr.isExprString()) { newArguments.add(arg); } } } arguments.clear(); arguments.addAll(newArguments); } } protected static IrFactory factory = IrFactory.eINSTANCE; protected EList<Var> stateVars; protected int strCnt; /** * Create a transformation that make the calls of 'print' function compliant * with LLVM assembly language reference. */ public StringTransformation() { this.irVisitor = new PrintTransformer(); } @Override public Void caseActor(Actor actor) { strCnt = 0; stateVars = actor.getStateVars(); while (actor.getProcedure("print") != null) { actor.getProcs().remove(actor.getProcedure("print")); } return super.caseActor(actor); } /** * Create a variable initialized with an LLVM-compliant ExprString. * * @param str * A string * @return A variable initialized with an LLVM-compliant ExprString extract * from the given string */ protected Var createStringVariable(String str) { int size = str.length(); str = str + "\\00"; size -= StringUtils.countMatches(str, "\\n"); str = str.replaceAll("\\\\n", "\\\\0A"); size -= StringUtils.countMatches(str, "\\t"); str = str.replaceAll("\\\\t", "\\\\09"); // Create state variable that contains println arguments TypeString type = factory.createTypeString(); type.setSize(size + 1); Var variable = factory.createVar(type, "str" + strCnt++, false, 0); variable.setInitialValue(factory.createExprString(str)); return variable; } }