package de.fuberlin.projecta.codegen; import de.fuberlin.commons.parser.ISyntaxTree; import de.fuberlin.projecta.analysis.SemanticException; import de.fuberlin.projecta.analysis.SymbolTableHelper; import de.fuberlin.projecta.analysis.ast.AbstractSyntaxTree; import de.fuberlin.projecta.analysis.ast.Args; import de.fuberlin.projecta.analysis.ast.Array; import de.fuberlin.projecta.analysis.ast.ArrayCall; import de.fuberlin.projecta.analysis.ast.BasicType; import de.fuberlin.projecta.analysis.ast.Block; import de.fuberlin.projecta.analysis.ast.Declaration; import de.fuberlin.projecta.analysis.ast.Expression; import de.fuberlin.projecta.analysis.ast.FuncCall; import de.fuberlin.projecta.analysis.ast.FuncDef; import de.fuberlin.projecta.analysis.ast.Id; import de.fuberlin.projecta.analysis.ast.Literal; import de.fuberlin.projecta.analysis.ast.Record; import de.fuberlin.projecta.analysis.ast.RecordVarCall; import de.fuberlin.projecta.analysis.ast.Statement; import de.fuberlin.projecta.analysis.ast.Type; public class LLVM { /** * This class should hold all the methods to generate LLVM code */ public static String genBranch(Statement current, AbstractSyntaxTree block1, AbstractSyntaxTree block2, boolean not, boolean loop) { String ret = ""; Block block = current.getHighestBlock(); if (block != null) { String s1 = "", s2 = ""; int varDecision, labelTrue, labelFalse, labelBehind; varDecision = block.getCurrentRegister(); labelTrue = block.getNewVar(); if (block1 != null) s1 = block1.genCode(); labelFalse = block.getNewVar(); if (block2 != null) s2 = block2.genCode(); labelBehind = block.getNewVar(); if (!not) { ret += "br i1 %" + varDecision + ", label %" + labelTrue + ", label %" + labelFalse + "\n\n"; } else { ret += "br i1 %" + varDecision + ", label %" + labelFalse + ", label %" + labelTrue + "\n\n"; } ret += "; <label>:" + labelTrue + "\n"; ret += s1 + "\n"; if (!loop) ret += "br label %" + labelBehind + "\n\n"; else ret += "br label %" + current.getBeginLabel() + "\n\n"; ret += "; <label>:" + labelFalse + "\n"; ret += s2 + "\n"; ret += "br label %" + labelBehind + "\n\n"; ret += "; <label>:" + labelBehind + "\n"; } return ret; } private static String loadVar(Id id) { String ret = ""; if (id != null && !isInParams(id) && id.getVar() == 0) { int memory = id.getHighestBlock().getNewVar(); id.setValMemory(memory); ret += "%" + memory + " = load " + SymbolTableHelper.lookup(id.getValue(), id).getType() .genCode() + "* %" + id.getValue() + "\n"; } else if (id != null && isInParams(id) && id.getVar() == 0) { int memory = id.getHighestBlock().getNewVar(); id.setValMemory(memory); String value = "0"; String op = "= add "; if(id.toTypeString().equals(BasicType.TYPE_REAL_STRING)){ value += ".0"; op = "= fadd "; } ret += "%" + memory + op + SymbolTableHelper.lookup(id.getValue(), id).getType() .genCode() + " %" + id.getValue() + ", "+ value +"\n"; } return ret; } public static String loadParams(Args args) { String ret = ""; if (args != null) { for (ISyntaxTree child : args.getChildren()) { Expression expr = (Expression) child; ret += loadType(expr); } } return ret; } public static boolean isInParams(Id id) { FuncDef fDef = searchUpFuncDef(id); if (fDef != null) { if (fDef.getChild(2).getChildrenCount() > 0) { for (int i = 0; i < fDef.getChild(2).getChildrenCount(); i += 2) { Type typeO = (Type) fDef.getChild(2).getChild(i); Id idO = (Id) fDef.getChild(2).getChild(i + 1); if (idO.getValue().equals(id.getValue()) && typeO.equals(id.getType())) return true; } } } return false; } private static FuncDef searchUpFuncDef(AbstractSyntaxTree node) { if (node.getParent() != null) { ISyntaxTree parent = node.getParent(); while (parent != null) { if (parent instanceof FuncDef) { return (FuncDef) parent; } parent = parent.getParent(); } } return null; } /** * genCode must be called before for this to work properly !!! * * @param expr * @return the memory address of the loaded expression */ public static String getMem(Expression expr) { String ret = ""; if (expr instanceof Id) { Id id = (Id) expr; if (LLVM.isInParams(id)) { ret = id.getValue(); } else { ret = "" + id.getVar(); } } else { ret = "" + expr.getVar(); } return ret; } /** * Gets number * * * @param rec * @param recordVar * @return */ public static int findNumberOfRecordVar(Record rec, String recordVar) { for (int i = 0; i < rec.getChildrenCount(); i++) { Declaration decl = (Declaration) rec.getChild(i); if (((Id) decl.getChild(1)).getValue().equals(recordVar)) { return i; } } throw new SemanticException("Entry " + recordVar + " not found in record " + ((Id) rec.getParent().getChild(1)).getValue(), null); } /** * The idea is to load the value into a register, even if it is a literal or * a funcCall in order to statically take the valMemory after calling this * function * * @param expr * the node to load the value into a new memory * @return the code for loading it */ public static String loadType(Expression expr) { String ret = ""; // If getVar is 0 it must be loaded, otherwise it is already loaded if (expr != null && expr.getVar() == 0) { Block block = expr.getHighestBlock(); if (expr instanceof Literal) { int n = block.getNewVar(), m = block.getNewVar(); String t = expr.genCode().split(" ")[0]; String v = expr.genCode().split(" ")[1]; ret += "%" + n + " = alloca " + t + "\n"; ret += "store " + t + " " + v + ", " + t + "* %" + n + "\n"; ret += "%" + m + " = load " + t + "* %" + n + "\n"; expr.setValMemory(m); } else if (expr instanceof Id) { ret += loadVar((Id) expr); } else if (expr instanceof FuncCall) { if (expr.getChildrenCount() > 1) { ret += LLVM.loadParams((Args) expr.getChild(1)); } int n = block.getNewVar(); ret += "%" + n + " = " + expr.genCode() + "\n"; expr.setValMemory(n); } else if (expr instanceof ArrayCall) { ArrayCall array = (ArrayCall) expr; ret += getArrayCallPointer(array); int pointer = array.getVar(); Id id = array.getVarId(); Type t = SymbolTableHelper.lookup(id.getValue(), array) .getType(); int val = block.getNewVar(); ret += "%" + val + " = load " + ((Array) t).getBasicType().fromTypeStringToLLVMType() + "* %" + pointer; expr.setValMemory(val); ret += "\n"; } else if (expr instanceof RecordVarCall) { int n = -1; RecordVarCall recVarCall = (RecordVarCall) expr; Record rec = (Record) SymbolTableHelper.lookup( recVarCall.getRecordId().getValue(), expr).getType(); if (recVarCall.getChild(0) instanceof RecordVarCall) { String currentMemory = recVarCall.getRecordId().getValue(); // start by searching child 1 of innermost recordVarCall Id currentSearchNode = null; // this is used for searching the correct node in the // record, starting in the innermost node RecordVarCall currentRecVarCall = (RecordVarCall) recVarCall .getRecordId().getParent(); Type retType = null; do { n = block.getNewVar(); // move up in RecordVar-Tree currentSearchNode = (Id) currentRecVarCall.getChild(1); int index = findNumberOfRecordVar(rec, currentSearchNode.getValue()); retType = ((Type) rec.getChild(index).getChild(0)); ret += "%" + n + " = getelementptr inbounds %struct." + ((Id) rec.getParent().getChild(1)).getValue() + "* %" + currentMemory + ", i32 0, i32 " + index + "\n"; currentMemory = "" + n; if ((currentRecVarCall.getParent() instanceof RecordVarCall) && rec.getChildrenCount() > index && rec.getChild(index).getChildrenCount() > 0) { if (rec.getChild(index).getChild(0) instanceof Record) rec = (Record) rec.getChild(index).getChild(0); } else { break; } currentRecVarCall = (RecordVarCall) currentRecVarCall .getParent(); } while (rec instanceof Record); // before returning, load the actual value into new memory n = block.getNewVar(); ret += "%" + n + " = load " + retType.fromTypeStringToLLVMType() + "* %" + (n - 1) + "\n"; // save the memory in the outermost recordVarCall node recVarCall.setValMemory(n); return ret; } else { int index = findNumberOfRecordVar(rec, recVarCall .getVarId().getValue()); n = block.getNewVar(); recVarCall.setValMemory(n); ret += "%" + n + " = getelementptr inbounds %struct." + ((Id) rec.getParent().getChild(1)).getValue() + "* %" + recVarCall.getRecordId().getValue() + ", i32 0, i32 " + index + "\n"; n = block.getNewVar(); Type retType = ((Type) rec.getChild(index).getChild(0)); ret += "%" + n + " = load " + retType.fromTypeStringToLLVMType() + "* %" + (n - 1) + "\n"; expr.setValMemory(n); } } else { // TODO: is this already calling setValMemory always? ret += expr.genCode(); } } return ret; } public static String getArrayCallPointer(ArrayCall array) { String ret = ""; Expression t1 = (Expression) array.getChild(0); ret += LLVM.loadType(t1); int num = t1.getVar(); String index = ", i32 %" + num; ArrayCall tmpT2 = array; // collect all array references. unlike declaration we have to go bottom // up for arrayCall // thus we build index in reverse order... while (tmpT2.getChild(1) instanceof ArrayCall) { tmpT2 = (ArrayCall) tmpT2.getChild(1); Expression tmpT1 = (Expression) tmpT2.getChild(0); ret += LLVM.loadType(tmpT1); index = ", i32 %" + tmpT1.getVar() + index; } // first resolve the array pointer than append remaining indexes index = ", i32 0" + index; // last ArrayCall contains the id of the array! (weird, but we deal with // it) Id id = (Id) tmpT2.getChild(1); Type t = SymbolTableHelper.lookup(id.getValue(), array).getType(); int pointer = array.getHighestBlock().getNewVar(); ret += "%" + pointer + " = getelementptr inbounds " + ((Array) t).genCode() + "* %" + id.getValue(); ret += index + "\n"; array.setValMemory(pointer); return ret; } public static String getRecordVarCallPointer(RecordVarCall expr) { String ret = ""; Block block = expr.getHighestBlock(); int n = -1; RecordVarCall recVarCall = (RecordVarCall) expr; Record rec = (Record) SymbolTableHelper.lookup( recVarCall.getRecordId().getValue(), expr).getType(); if (recVarCall.getChild(0) instanceof RecordVarCall) { String currentMemory = recVarCall.getRecordId().getValue(); // start by searching child 1 of innermost recordVarCall Id currentSearchNode = null; // this is used for searching the correct node in the // record, starting in the innermost node RecordVarCall currentRecVarCall = (RecordVarCall) recVarCall .getRecordId().getParent(); do { n = block.getNewVar(); // move up in RecordVar-Tree currentSearchNode = (Id) currentRecVarCall.getChild(1); int index = findNumberOfRecordVar(rec, currentSearchNode.getValue()); ret += "%" + n + " = getelementptr inbounds %struct." + ((Id) rec.getParent().getChild(1)).getValue() + "* %" + currentMemory + ", i32 0, i32 " + index + "\n"; currentMemory = "" + n; if ((currentRecVarCall.getParent() instanceof RecordVarCall) && rec.getChildrenCount() > index && rec.getChild(index).getChildrenCount() > 0) { if (rec.getChild(index).getChild(0) instanceof Record) rec = (Record) rec.getChild(index).getChild(0); } else { break; } currentRecVarCall = (RecordVarCall) currentRecVarCall .getParent(); } while (rec instanceof Record); // save the memory in the outermost recordVarCall node recVarCall.setValMemory(n); return ret; } else { int index = findNumberOfRecordVar(rec, recVarCall.getVarId() .getValue()); n = block.getNewVar(); recVarCall.setValMemory(n); ret += "%" + n + " = getelementptr inbounds %struct." + ((Id) rec.getParent().getChild(1)).getValue() + "* %" + recVarCall.getRecordId().getValue() + ", i32 0, i32 " + index + "\n"; } return ret; } }