TAC* makeWhile(TAC* codeTest, TAC* codeThen) { TAC *newWhile, *targetEndWhile, *targetBeginWhile; HASH *labelBeginWhile, *labelEndWhile; // Create code and label fot the test (WHILE) labelBeginWhile = hash_make_label(); labelEndWhile = hash_make_label(); targetBeginWhile = tacCreate(TAC_LABEL, labelBeginWhile, 0, 0); // temp (bool) newWhile = tacCreate(TAC_IFZ, labelEndWhile, codeTest?codeTest->res:0, 0); newWhile->prev = codeTest; //printf("AAAAAAAAAAAAAAAAAAAAAAAAAAA %d\n", codeTest->type); // type: LTZ, GEZ... op1 e op2 are the operands // Add the jump at the end of the block back to the test codeThen = tacJoin4(targetBeginWhile, newWhile, codeThen, tacCreate(TAC_JUMP, labelBeginWhile, 0, 0) ); // Add the label to jump from the conditional test WHILE targetEndWhile = tacCreate(TAC_LABEL, labelEndWhile, 0, 0); targetEndWhile->prev = codeThen; return targetEndWhile; }
TAC* makeIfThenElse(TAC* codeTest, TAC* codeThen, TAC* codeElse) { TAC *newIf, *targetElse, *targetEndIf; HASH *labelElse, *labelEndIf; // Create code and label fot the test (IFZ) labelElse = hash_make_label(); newIf = tacCreate(TAC_IFZ, labelElse, codeTest?codeTest->res:0, 0); newIf->prev = codeTest; // If there's an else, then add the jump at the end of the "then" block if (codeElse) { labelEndIf = hash_make_label(); codeThen = tacJoin3(newIf, codeThen, tacCreate(TAC_JUMP, labelEndIf, 0, 0) ); } else { codeThen = tacJoin(newIf, codeThen); } // Add the label to jump from the conditional test IFZ targetElse = tacCreate(TAC_LABEL, labelElse, 0, 0); targetElse->prev = codeThen; // If there's "else", append its code after the "then" block and create the label end-if if (codeElse) { codeElse = tacJoin(targetElse, codeElse); targetEndIf = tacCreate(TAC_LABEL, labelEndIf, 0, 0); targetEndIf->prev = codeElse; } else { targetEndIf = targetElse; } return targetEndIf; }
TAC *tacFunDec(HASH_NODE *res, TAC **code) { TAC *begin, *end; begin = tacCreate(TAC_BEGINFUN, res, NULL, NULL); end = tacCreate(TAC_ENDFUN, res, NULL, NULL); return tacMultiJoin(3, begin, code[2], end); }
TAC *tacIfThen(TAC **code) { TAC *nIf, *target; HASH_NODE *label = makeLabel(); /* ifz tac */ nIf = tacCreate(TAC_IFZ, label, code[0]?code[0]->res:NULL, NULL); /* ifz false target */ target = tacCreate(TAC_LABEL, label, NULL, NULL); return tacMultiJoin(4, code[0], nIf, code[1], target); }
// make america great again TAC *tacInputArgs(TAC **code, HASH_NODE *id) { TAC *lin = code[0]; if(!id) return NULL; // no args if(!lin) // end of tree's list return tacCreate(TAC_INPUT, NULL, id?id:NULL, NULL); // there's still args return tacJoin(tacCreate(TAC_INPUT, NULL, id?id:NULL, NULL), lin); }
// deus abencoe a america TAC *tacOutputArgs(TAC **code) { TAC *lout = code[1]; TAC *litOrExp = code[0]; if(!litOrExp) return NULL; // no args if(!lout) // end of tree's list return tacJoin(litOrExp, tacCreate(TAC_PRINT, NULL, litOrExp?litOrExp->res:NULL, NULL)); // there's still args return tacMultiJoin(3, litOrExp, tacCreate(TAC_PRINT, NULL, litOrExp?litOrExp->res:NULL, NULL), lout); }
TAC *tacFunCall(AST_NODE *funCall) { AST_NODE *funDef = funCall->symbol->declaration; AST_NODE *largs = funDef->children[1]; AST_NODE *lexp = funCall->children[0]; TAC *tacArg = tacArgs(largs, lexp); TAC *tacCall = tacCreate(TAC_CALL, makeTemp(funCall->datatype), funCall->symbol, NULL); return tacMultiJoin(2, tacArg, tacCall); }
TAC *tacWhile(TAC **code) { TAC *tacExp = code[0]; TAC *tacCmd = code[1]; // label before test expression HASH_NODE *labelPrev = makeLabel(); TAC *tacPrev = tacCreate(TAC_LABEL, labelPrev, NULL, NULL); // label after while command HASH_NODE *labelNext = makeLabel(); TAC *tacNext = tacCreate(TAC_LABEL, labelNext, NULL, NULL); // while conditional jump TAC *tacIfz = tacCreate(TAC_IFZ, labelNext, tacExp?tacExp->res:NULL, NULL); // jump back to test expression after command TAC *tacJmp = tacCreate(TAC_JUMP, labelPrev, NULL, NULL); return tacMultiJoin(6, tacPrev, tacExp, tacIfz, tacCmd, tacJmp, tacNext); }
TAC *tacIfThenElse(TAC **code) { TAC *tacExp = code[0]; TAC *tacThen = code[1]; TAC *tacElse = code[2]; // label before else HASH_NODE* labelElse = makeLabel(); TAC *tacLabelElse = tacCreate(TAC_LABEL, labelElse, NULL, NULL); // label after else HASH_NODE* labelNext = makeLabel(); TAC *tacLabelNext = tacCreate(TAC_LABEL, labelNext, NULL, NULL); // ifz conditional jump TAC *tacIfz = tacCreate(TAC_IFZ, labelElse, tacExp?tacExp->res:NULL, NULL); // jump at end of then command TAC *tacJmp = tacCreate(TAC_JUMP, labelNext, NULL, NULL); return tacMultiJoin(7, tacExp, tacIfz, tacThen, tacJmp, tacLabelElse, tacElse, tacLabelNext); }
TAC *tacArgs(AST_NODE *larg, AST_NODE *lexp) { TAC *tacAcc = NULL; while(larg && lexp) { HASH_NODE *arg = larg->symbol; AST_NODE *exp = lexp->children[0]; TAC *tacExp = tacGenerateCodeAux(exp); TAC *tacArg = tacCreate(TAC_ARG, arg, tacExp?tacExp->res:NULL, NULL); tacAcc = tacMultiJoin(3, tacAcc, tacExp, tacArg); larg = larg->children[1]; lexp = lexp->children[1]; } return tacAcc; }
TAC* makeParameters(TREE* node, int tacType) { TREE *exprList; TAC *resultCode = NULL, *generatedCode; HASH *parameterSymbol; int childNoParams; HASH *format; PARAM_LIST *currentParameter; if (node->type == TREE_EXPR_ARIT_FUNCALL) { childNoParams = 1; currentParameter = node->children[0]->symbol ? node->children[0]->symbol->dataType.params : NULL; } else { childNoParams = 0; } // Iterate over the expression list (the parameters) for (exprList = node->children[childNoParams]; exprList; exprList = exprList->children[1]) { generatedCode = generateCode(exprList->children[0]); switch(node->type) { case TREE_EXPR_ARIT_FUNCALL: if (currentParameter) { parameterSymbol = currentParameter->symbol; currentParameter = currentParameter->next; } else parameterSymbol = 0; break; case TREE_COMM_IN: case TREE_COMM_OUT: parameterSymbol = 0; if (generatedCode->res) { switch (generatedCode->res->type) { case SYMBOL_LITERAL_INT: case SYMBOL_LITERAL_BOOL: format = gbl_format_d; break; case SYMBOL_LITERAL_REAL: format = gbl_format_f; break; case SYMBOL_LITERAL_STRING: format = gbl_format_s; break; case SYMBOL_LITERAL_CHAR: format = gbl_format_c; break; case SYMBOL_IDENTIFIER: switch (generatedCode->res->dataType.valueType) { case VAL_TYPE_INT: case VAL_TYPE_BOOL: format = gbl_format_d; break; case VAL_TYPE_REAL: format = gbl_format_f; break; case VAL_TYPE_CHAR: format = gbl_format_c; break; case VAL_TYPE_STRING: format = gbl_format_s; break; default: format = gbl_format_f; } } } else { format = NULL; } } // Concatenate the expression code of the current argument to the result // along with a TAC for argument, be it TAC_ARG OR TAC_READ OR TAC_PRINT resultCode = tacJoin3(resultCode, generatedCode, tacCreate(tacType, parameterSymbol, generatedCode?generatedCode->res:0, format)); } return resultCode; }
TAC *tacUnaryOp(int type, int datatype, TAC **code) { TAC *newTac = tacCreate(type, makeTemp(datatype), code[0]?code[0]->res:NULL, NULL); return tacMultiJoin(2, code[0], newTac); }
TAC *tacGenerateCodeAux(AST_NODE *node) { TAC *code[node->size]; int i; if(node->type == AST_FUNCALL) return tacFunCall(node); for(i = 0; i < node->size; i++) if(!node->children[i]) code[i] = NULL; else code[i] = tacGenerateCodeAux(node->children[i]); switch(node->type) { case AST_LIT: case AST_VAR: return tacCreate(TAC_SYMBOL, node->symbol, NULL, NULL); case AST_ARRACCESS: return tacReadArr(node->symbol, code); case AST_ATTR: return tacAttr(node->symbol, code); case AST_ATTRARR: return tacAttrArr(node->symbol, code); case AST_FUNDEC: return tacFunDec(node->symbol, code); case AST_LOUT: return tacOutputArgs(code); case AST_LIN: return tacInputArgs(code, node->symbol); case AST_IF: return tacIfThen(code); case AST_IFTE: return tacIfThenElse(code); case AST_WHILE: return tacWhile(code); case AST_RETURN: return tacReturn(code); case AST_NOT: return tacUnaryOp(TAC_NOT, node->datatype, code); case AST_LE: return tacBinOp(TAC_LE, node->datatype, code); case AST_GE: return tacBinOp(TAC_GE, node->datatype, code); case AST_EQ: return tacBinOp(TAC_EQ, node->datatype, code); case AST_NE: return tacBinOp(TAC_NE, node->datatype, code); case AST_AND: return tacBinOp(TAC_AND, node->datatype, code); case AST_OR: return tacBinOp(TAC_OR, node->datatype, code); case AST_LESS: return tacBinOp(TAC_LESS, node->datatype, code); case AST_GREATER: return tacBinOp(TAC_GREATER, node->datatype, code); case AST_ADD: return tacBinOp(TAC_ADD, node->datatype, code); case AST_SUB: return tacBinOp(TAC_SUB, node->datatype, code); case AST_MUL: return tacBinOp(TAC_MUL, node->datatype, code); case AST_DIV: return tacBinOp(TAC_DIV, node->datatype, code); default: return tacArrayJoin(node->size, code); } }
TAC* makeLogicOp(int type, TAC* code0, TAC* code1) { return tacJoin(tacJoin(code0, code1), tacCreate(type, hash_make_temp_int(), code0 ? code0->res : 0, code1 ? code1->res : 0)); }
TAC* generateCode(TREE* node) { int i; TAC *code[MAX_CHILDREN], *generatedCode; if (!node) return NULL; for (i=0; i<MAX_CHILDREN; i++) { if (node->children[i]) code[i] = generateCode(node->children[i]); else code[i] = 0; } switch (node->type) { case TREE_SYMBOL: return tacCreate(TAC_SYMBOL, node->symbol, 0, 0); case TREE_VAL_TRUE: return tacCreate(TAC_SYMBOL, gbl_value_true, 0, 0); case TREE_VAL_FALSE: return tacCreate(TAC_SYMBOL, gbl_value_false, 0, 0); case TREE_DECL_FUNC: return tacJoin3( tacCreate(TAC_BEGINFUN, 0, node->children[1]?node->children[1]->symbol:0, 0), code[3], tacCreate(TAC_ENDFUN, 0, node->children[1]?node->children[1]->symbol:0, 0) ); case TREE_COMM_NOP: return tacCreate(TAC_NOP, 0, 0, 0); case TREE_COMM_IN: generatedCode = makeParameters(node, TAC_READ); // The code of the expressions in the parameters return generatedCode; case TREE_COMM_OUT: generatedCode = makeParameters(node, TAC_PRINT); return generatedCode; // The code of the expressions in the parameters case TREE_COMM_ASSIG: return tacJoin(code[1], tacCreate(TAC_MOVE, code[0]?code[0]->res:0, code[1]?code[1]->res:0, 0) ); case TREE_COMM_ASSIG_VEC: return tacJoin3(code[1], code[2], tacCreate(TAC_STRIDX, code[0]?code[0]->res:0, code[1]?code[1]->res:0, code[2]?code[2]->res:0) ); case TREE_COMM_IF_ELSE: return makeIfThenElse(code[0], code[1], code[2]); case TREE_COMM_WHILE: return makeWhile(code[0], code[1]); case TREE_COMM_RETURN: return tacJoin(code[0], tacCreate(TAC_RET, 0, code[0]?code[0]->res:0, 0)); case TREE_EXPR_ARIT_FUNCALL: return tacJoin(makeParameters(node, TAC_ARG), // The code of the expressions in the parameters tacCreate(TAC_CALL, hash_make_temp(), code[0]?code[0]->res:0, 0)); case TREE_EXPR_ARIT_VEC_READ: return tacJoin(code[1], tacCreate(TAC_LOADIDX, hash_make_temp(), code[0]?code[0]->res:0, code[1]?code[1]->res:0) ); break; case TREE_EXPR_ARIT_ADD: return makeBinOp(TAC_ADD, code[0], code[1]); case TREE_EXPR_ARIT_SUB: return makeBinOp(TAC_SUB, code[0], code[1]); case TREE_EXPR_ARIT_MUL: return makeBinOp(TAC_MUL, code[0], code[1]); case TREE_EXPR_ARIT_DIV: return makeBinOp(TAC_DIV, code[0], code[1]); case TREE_EXPR_BOOL_LT: return makeLogicOp(TAC_LTZ, code[0], code[1]); case TREE_EXPR_BOOL_GT: return makeLogicOp(TAC_GTZ, code[0], code[1]); case TREE_EXPR_BOOL_LE: return makeLogicOp(TAC_LEZ, code[0], code[1]); case TREE_EXPR_BOOL_GE: return makeLogicOp(TAC_GEZ, code[0], code[1]); case TREE_EXPR_BOOL_EQ: return makeLogicOp(TAC_EQZ, code[0], code[1]); case TREE_EXPR_BOOL_NE: return makeLogicOp(TAC_ANEG, code[0],code[1]); case TREE_EXPR_BOOL_AND: return makeLogicOp(TAC_AND, code[0], code[1]); case TREE_EXPR_BOOL_OR: return makeLogicOp(TAC_OR, code[0], code[1]); default: break; } return tacJoin4(code[0], code[1], code[2], code[3]); }
TAC *tacAttrArr(HASH_NODE* res, TAC **code) { TAC *newTac = tacCreate(TAC_ATTRARR, res, code[0]?code[0]->res:NULL, code[1]?code[1]->res:NULL); return tacMultiJoin(3, code[0], code[1], newTac); }
TAC *tacReadArr(HASH_NODE* vec, TAC **code) { TAC *newTac = tacCreate(TAC_READARR, makeTemp(vec->datatype), vec, code[0]?code[0]->res:NULL); return tacMultiJoin(2, code[0], newTac); }
TAC *tacReturn(TAC **code) { TAC *retExp = code[0]; TAC *retTac = tacCreate(TAC_RET, NULL, retExp?retExp->res:NULL, NULL); return tacJoin(retExp, retTac); }
TAC *tacReturn(TAC **code, HASH_NODE *funDec) { TAC *retExp = code[0]; TAC *retTac = tacCreate(TAC_RET, retExp?retExp->res:NULL, funDec, NULL); return tacJoin(retExp, retTac); }