package de.fuberlin.projecta.analysis.ast; import java.util.ArrayList; import java.util.Arrays; import de.fuberlin.projecta.analysis.BasicTokenType; import de.fuberlin.projecta.analysis.SemanticException; import de.fuberlin.projecta.analysis.SymbolTableHelper; import de.fuberlin.projecta.codegen.LLVM; public class Print extends Statement { @Override /* * we use the puts function to print to screen %forprinting = load i8** * %str3 call i32 (i8*)* @puts(i8* %forprinting) */ public String genCode() { String out = ""; Block block = getHighestBlock(); Type idType = null; if (getChild(0) instanceof RecordVarCall) { idType = SymbolTableHelper .lookupRecordVarCall((RecordVarCall) getChild(0)); idType = (Type) idType.getParent().getChild(0); } else if (getChild(0) instanceof ArrayCall) { ArrayCall tmp = (ArrayCall) getChild(0); while (tmp.getChild(1) instanceof ArrayCall) { tmp = (ArrayCall) tmp.getChild(1); } if (tmp.getChild(1) instanceof Id) { String arrayId = ((Id) tmp.getChild(1)).getValue(); idType = SymbolTableHelper.lookup(arrayId, this).getType(); idType = ((Array) idType).getBasicType(); } } else { idType = SymbolTableHelper.lookup(((Id) getChild(0)).getValue(), this).getType(); } if (idType instanceof BasicType) { if (((BasicType) idType).getTokenType() == BasicTokenType.STRING) { if (LLVM.isInParams((Id) getChild(0))) { out += "%" + getHighestBlock().getNewVar() + " = " + "call i32 (i8*)* @puts(i8* %" + ((Id) getChild(0)).getValue() + ")"; } else { int reg = block.getNewVar(); out += "%" + reg + " = load i8** %" + ((Id) getChild(0)).getValue() + "\n"; out += "%" + getHighestBlock().getNewVar() + " = " + "call i32 (i8*)* @puts(i8* %" + reg + ")"; } } else { String format = ""; if (((BasicType) idType).getTokenType() == BasicTokenType.INT) { format = "%d"; out += ""; } else if (((BasicType) idType).getTokenType() == BasicTokenType.REAL) { format = "%f"; } else if (((BasicType) idType).getTokenType() == BasicTokenType.BOOL) { format = "%d"; } // format string int tempReg = block.getNewVar(); out += "%" + tempReg + " = alloca [4 x i8]\n"; out += "store [4 x i8] c\"" + format + "\\0A\\00\", [4 x i8]* %" + tempReg + "\n"; int tempReg2 = block.getNewVar(); out += "%" + tempReg2 + " = getelementptr [4 x i8]* %" + tempReg + ", i8 0, i8 0 \n"; // now we print int valReg = 0; out += LLVM.loadType((Expression) getChild(0)); valReg = block.getCurrentRegister(); out += "call i32 (i8*, ...)* @printf(i8* %" + tempReg2 + ", " + idType.genCode() + " %" + valReg + ")"; // implicit return of printf increments var counter! block.getNewVar(); } } return out; } @Override public void checkTypes() { String[] b = { BasicType.TYPE_BOOL_STRING, BasicType.TYPE_STRING_STRING, BasicType.TYPE_INT_STRING, BasicType.TYPE_REAL_STRING }; String argumentType = ((Expression) getChild(0)).toTypeString(); ArrayList<String> validTypes = new ArrayList<String>(Arrays.asList(b)); if (!validTypes.contains(argumentType)) throw new SemanticException( "Invalid argument to print-function of type " + argumentType, this); } }