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 *tacArrayJoin(int numTacs, TAC **tacs) { int i; TAC *acc = NULL; for(i = 0; i < numTacs; i++) acc = tacJoin(acc, tacs[i]); return acc; }
TAC *tacMultiJoin(int numTacs, ...) { int i; va_list args; TAC *acc = NULL, *t; va_start(args, numTacs); for(i = 0; i < numTacs; i++) { t = va_arg(args, TAC*); acc = tacJoin(acc, t); } return acc; }
// 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 *tacReturn(TAC **code) { TAC *retExp = code[0]; TAC *retTac = tacCreate(TAC_RET, NULL, retExp?retExp->res:NULL, NULL); return tacJoin(retExp, retTac); }
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 *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); }