/* *============================================== * Wrapper function for the traversing cGen * function *============================================== */ int codeGen(TreeBranch *head, HashTable *parent) { currentTable = parent; ff = fopen("Output/output.s", "w+"); fprintf(ff, HEADER); cGen(head); fprintf(ff, FOOTER); fclose(ff); return 0; }
void codeGen(TreeNode *syntaxTree, const char *codefile) { writeFileHeader(); writeVarSection(); cGen(syntaxTree); fillCodeSection(); writeTempVarSection(); writeVarRefSection(); fillSection(); writeTempVarRefSection(); fillSection(); updateFileHeader(); }
/* Procedure cGen recursively generates code by * tree traversal */ static void cGen( TreeNode * tree) { if (tree != NULL) { switch (tree->nodekind) { case StmtK: genStmt(tree); break; case ExpK: genExp(tree); break; default: break; } cGen(tree->sibling); } }
/* Procedure codeGen generates code to a code * file by traversal of the syntax tree. The * second parameter (codefile) is the file name * of the code file, and is used to print the * file name as a comment in the code file */ void codeGen(TreeNode * syntaxTree, char * codefile) { char * s = (char *) malloc(strlen(codefile)+7); strcpy(s,"File: "); strcat(s,codefile); emitComment("TINY Compilation to TM Code"); emitComment(s); /* generate standard prelude */ emitComment("Standard prelude:"); emitRM("LD",mp,0,ac,"load maxaddress from location 0"); emitRM("ST",ac,0,ac,"clear location 0"); emitComment("End of standard prelude."); /* generate code for TINY program */ cGen(syntaxTree); /* finish */ emitComment("End of execution."); emitRO("HALT",0,0,0,""); }
/* Procedure genExp generates code at an expression node */ static void genExp( TreeNode * tree) { int loc; TreeNode * p1, * p2; switch (tree->kind.exp) { case ConstK : if (TraceCode) emitComment("-> Const") ; /* gen code to load integer constant using LDC */ emitRM("LDC",ac,tree->attr.val,0,"load const"); if (TraceCode) emitComment("<- Const") ; break; /* ConstK */ case IdK : if (TraceCode) emitComment("-> Id") ; loc = st_lookup(tree->attr.name); emitRM("LD",ac,loc,gp,"load id value"); if (TraceCode) emitComment("<- Id") ; break; /* IdK */ case OpK : if (TraceCode) emitComment("-> Op") ; p1 = tree->child[0]; p2 = tree->child[1]; /* gen code for ac = left arg */ cGen(p1); /* gen code to push left operand */ emitRM("ST",ac,tmpOffset--,mp,"op: push left"); /* gen code for ac = right operand */ cGen(p2); /* now load left operand */ emitRM("LD",ac1,++tmpOffset,mp,"op: load left"); switch (tree->attr.op) { case PLUS : emitRO("ADD",ac,ac1,ac,"op +"); break; case MINUS : emitRO("SUB",ac,ac1,ac,"op -"); break; case TIMES : emitRO("MUL",ac,ac1,ac,"op *"); break; case OVER : emitRO("DIV",ac,ac1,ac,"op /"); break; case LT : emitRO("SUB",ac,ac1,ac,"op <") ; emitRM("JLT",ac,2,pc,"br if true") ; emitRM("LDC",ac,0,ac,"false case") ; emitRM("LDA",pc,1,pc,"unconditional jmp") ; emitRM("LDC",ac,1,ac,"true case") ; break; case EQ : emitRO("SUB",ac,ac1,ac,"op ==") ; emitRM("JEQ",ac,2,pc,"br if true"); emitRM("LDC",ac,0,ac,"false case") ; emitRM("LDA",pc,1,pc,"unconditional jmp") ; emitRM("LDC",ac,1,ac,"true case") ; break; default: emitComment("BUG: Unknown operator"); break; } /* case op */ if (TraceCode) emitComment("<- Op") ; break; /* OpK */ default: break; } } /* genExp */
/* Procedure genStmt generates code at a statement node */ static void genStmt( TreeNode * tree) { TreeNode * p1, * p2, * p3; int savedLoc1,savedLoc2,currentLoc; int loc; switch (tree->kind.stmt) { case IfK : if (TraceCode) emitComment("-> if") ; p1 = tree->child[0] ; p2 = tree->child[1] ; p3 = tree->child[2] ; /* generate code for test expression */ cGen(p1); savedLoc1 = emitSkip(1) ; emitComment("if: jump to else belongs here"); /* recurse on then part */ cGen(p2); savedLoc2 = emitSkip(1) ; emitComment("if: jump to end belongs here"); currentLoc = emitSkip(0) ; emitBackup(savedLoc1) ; emitRM_Abs("JEQ",ac,currentLoc,"if: jmp to else"); emitRestore() ; /* recurse on else part */ cGen(p3); currentLoc = emitSkip(0) ; emitBackup(savedLoc2) ; emitRM_Abs("LDA",pc,currentLoc,"jmp to end") ; emitRestore() ; if (TraceCode) emitComment("<- if") ; break; /* if_k */ case RepeatK: if (TraceCode) emitComment("-> repeat") ; p1 = tree->child[0] ; p2 = tree->child[1] ; savedLoc1 = emitSkip(0); emitComment("repeat: jump after body comes back here"); /* generate code for body */ cGen(p1); /* generate code for test */ cGen(p2); emitRM_Abs("JEQ",ac,savedLoc1,"repeat: jmp back to body"); if (TraceCode) emitComment("<- repeat") ; break; /* repeat */ case AssignK: if (TraceCode) emitComment("-> assign") ; /* generate code for rhs */ cGen(tree->child[0]); /* now store value */ loc = st_lookup(tree->attr.name); emitRM("ST",ac,loc,gp,"assign: store value"); if (TraceCode) emitComment("<- assign") ; break; /* assign_k */ case ReadK: emitRO("IN",ac,0,0,"read integer value"); loc = st_lookup(tree->attr.name); emitRM("ST",ac,loc,gp,"read: store value"); break; case WriteK: /* generate code for expression to write */ cGen(tree->child[0]); /* now output it */ emitRO("OUT",ac,0,0,"write ac"); break; default: break; } } /* genStmt */
static void genStmt(TreeNode *tree) { TreeNode *p1, *p2, *p3; switch (tree->kind.stmt) { case IfK: p1 = tree->child[0]; p2 = tree->child[1]; p3 = tree->child[2]; cGen(p1); break; case RepeatK: break; case AssignK: p1 = tree->child[0]; cGen(p1); switch (p1->nodekind) { int loc; case StmtK: switch(p1->kind.stmt) { case AssignK: break; } break; case ExpK: switch(p1->kind.exp) { case ConstK: break; case IdK: break; case OpK: loc = st_lookup(tree->attr.token.stype); emitMov_N(REG_EAX, loc); break; } break; } break; case ReadK: break; case WriteK: break; default : break; } }
/* *============================================= * recursive traversing function that generates * assembly code *============================================= */ int cGen(TreeBranch *cur) { int skip1 = 0; int skip2 = 0; int skip3 = 0; int skipSib = 0; /*===================================================================================== * Block Statements * *===================================================================================== */ if(cur->nodeT == new_blk) { /*first block*/ if(tableflag == 0) { tableflag = 1; currentTable->MaxOffset = curOffset; if(cur->child1 != NULL) cGen(cur->child1); if(cur->child2 != NULL) cGen(cur->child2); if(cur->child3 != NULL) cGen(cur->child3); skip1 = 1; skip2 = 1; skip3 = 1; skipSib = 1; } /*other blocks*/ else { currentTable->MaxOffset = curOffset; currentTable = currentTable->next; fprintf(ff, ";;; entering new stack frame\n"); if(cur->child1 != NULL) cGen(cur->child1); if(cur->child2 != NULL) cGen(cur->child2); if(cur->child3 != NULL) cGen(cur->child3); currentTable = currentTable->parent; if(currentTable->next != NULL) { if (currentTable->next->next != NULL) { currentTable->next = currentTable->next->next; } } fprintf(ff, "\tadd esp, %d ;reset stack pointer\n", curOffset-currentTable->MaxOffset); curOffset = currentTable->MaxOffset; if(cur->sibling != NULL) cGen(cur->sibling); skip1 = 1; skip2 = 1; skip3 = 1; skipSib = 1; } } /*================================================================================ * Constant Declarations *================================================================================ */ else if(cur->nodeT == const_decl) { HashElement *tmp = lookUpId(cur->child1->attribute, currentTable); tmp->val = cur->child2->num; /*fprintf(ff, "\tsub esp, %d\n", 4); fprintf(ff, "\tmov dword [ebp - %d], %d\t;cons %s\n", tmp->offset, tmp->val, tmp->identifier);*/ } /*================================================================================ * Variable Declarations *================================================================================ */ else if(cur->nodeT == var_decl) { if(cur->child2->nodeT == sing_decl) { /*================================================================================ * Non-Array Declarations *================================================================================ */ HashElement *tmp = lookUpId(cur->child1->attribute, currentTable); tmp->offset = curOffset; curOffset += 4; /*initialize all variables to zero, seems easier that way*/ fprintf(ff, "\tsub esp, 4\t;variable %s\n", tmp->identifier); //fprintf(ff, "\tmov dword [ebp - %d], %d\t;var %s\n", tmp->offset, 0, tmp->identifier); TreeBranch *ptr = cur->child1->sibling; while(ptr != NULL) { tmp = lookUpId(ptr->attribute, currentTable); tmp->offset = curOffset; curOffset +=4; /*initialize all variables to zero, seems easier that way*/ fprintf(ff, "\tsub esp, 4\t;variable %s\n", tmp->identifier); //fprintf(ff, "\tmov dword [ebp - %d], %d\t;var %s\n", tmp->offset, 0, tmp->identifier); ptr = ptr->sibling; } } /*================================================================================ * Array Declarations *================================================================================ */ if(cur->child2->nodeT == arr_decl) { HashElement *tmp = lookUpId(cur->child1->attribute, currentTable); tmp->offset = curOffset; if(tmp->indices == 0) { HashElement *tmp2 = lookUpId(cur->child2->child1->attribute, currentTable); tmp->indices = tmp2->val; } curOffset += (4*tmp->indices); fprintf(ff, "\tsub esp, %d\t;array %s\n", (4*tmp->indices), tmp->identifier); TreeBranch *ptr = cur->child1->sibling; while(ptr != NULL) { if(tmp->indices == 0) { HashElement *tmp2 = lookUpId(cur->child2->child1->attribute, currentTable); tmp->indices = tmp2->val; } tmp = lookUpId(cur->child1->attribute, currentTable); tmp->offset = curOffset; curOffset += (4*tmp->indices); fprintf(ff, "\tsub esp, %d\t;array %s\n", (4*tmp->indices), tmp->identifier); ptr = ptr->sibling; } } } /*===================================================================================== * Assignment statements * *===================================================================================== */ if(cur->nodeT == assign) { int prevOffset = curOffset; fprintf(ff, "\t;; Assignment Statement\n"); HashElement *tmp = lookUpId(cur->child1->attribute, currentTable); generateExpression(cur->child2); fprintf(ff, "\tmov [ebp - %d], eax\t;assigning\n", tmp->offset); fprintf(ff, "\tadd esp, %d\t;end of assignment\n", curOffset-prevOffset); curOffset = prevOffset; } /*===================================================================================== * Write statements * *===================================================================================== */ if(cur->nodeT == write_stmt) { int wrcount = 0; TreeBranch *ptr = cur->child1; fprintf(ff, "\t;; Write Statement\n"); while(ptr != NULL) { generateExpression(ptr); fprintf(ff, "\tsub esp, 4\n"); fprintf(ff, "\tmov [ebp - %d], eax\n", curOffset); curOffset += 4; wrcount++; ptr = ptr->sibling; } fprintf(ff, "\tsub esp, 4\n"); fprintf(ff, "\tmov dword [ebp - %d], %d\n", curOffset, wrcount); fprintf(ff, "\tcall write\n"); fprintf(ff, "\tadd esp, %d\n", (wrcount*4 + 4)); curOffset -= (wrcount*4); skip1 = 1; skip2 = 1; skip3 = 1; } /*===================================================================================== * Read Statements * *===================================================================================== */ if(cur->nodeT == read_stmt) { int rdcount = 0; TreeBranch *ptr = cur->child1; fprintf(ff, "\t;; Write Statement\n"); while(ptr != NULL) { generateExpression(ptr); fprintf(ff, "\tsub esp, 4\n"); fprintf(ff, "\tmov [ebp - %d], eax\n", curOffset); curOffset += 4; rdcount++; ptr = ptr->sibling; } fprintf(ff, "\tsub esp, 4\n"); fprintf(ff, "\tmov dword [ebp - %d], %d\n", curOffset, rdcount); fprintf(ff, "\tcall read\n"); fprintf(ff, "\tadd esp, %d\n", (rdcount*4 + 4)); curOffset -= (rdcount*4); skip1 = 1; skip2 = 1; skip3 = 1; } /*===================================================================================== * While statements * *===================================================================================== */ if(cur->nodeT == while_stmt) { fprintf(ff, "\t;; While Statement\n"); int prevOffset = curOffset; generateExpression(cur->child1); int iterlabel = labelnum; labelnum++; int endlabel = labelnum; labelnum++; fprintf(ff, "L%d:\n", iterlabel); generateExpression(cur->child1); /*generate the necessary jump after the comparison*/ if(strcmp(cur->child1->attribute, "=")==0) { fprintf(ff, "\tje L%d\n", endlabel); } if(strcmp(cur->child1->attribute, ">")==0) { fprintf(ff, "\tjg L%d\n", endlabel); } if(strcmp(cur->child1->attribute, "<")==0) { fprintf(ff, "\tjl L%d\n", endlabel); } if(strcmp(cur->child1->attribute, ">=")==0) { fprintf(ff, "\tjge L%d\n", endlabel); } if(strcmp(cur->child1->attribute, "<=")==0) { fprintf(ff, "\tjle L%d\n", endlabel); } cGen(cur->child2); fprintf(ff, "\tjmp L%d\t;iterate\n", iterlabel); fprintf(ff, "L%d:\n", endlabel); fprintf(ff, "\tadd esp, %d\n;;;end of while statement\n", curOffset-prevOffset); curOffset = prevOffset; } /*===================================================================================== * if statements * *===================================================================================== */ if((cur->nodeT == if_stmt) || (cur->nodeT == ifelse_stmt)) { int prevOffset = curOffset; fprintf(ff, "\t;; If Statement\n"); int iflabel = labelnum; labelnum++; generateExpression(cur->child1); /*generate the necessary jump after the comparison*/ if(strcmp(cur->child1->attribute, "=")==0) { fprintf(ff, "\tjne L%d\n", iflabel); } if(strcmp(cur->child1->attribute, ">")==0) { fprintf(ff, "\tjng L%d\n", iflabel); } if(strcmp(cur->child1->attribute, "<")==0) { fprintf(ff, "\tjnl L%d\n", iflabel); } if(strcmp(cur->child1->attribute, ">=")==0) { fprintf(ff, "\tjnge L%d\n", iflabel); } if(strcmp(cur->child1->attribute, "<=")==0) { fprintf(ff, "\tjnle L%d\n", iflabel); } cGen(cur->child2); skip2 = 1; /* *if there is no else, simply skip to the end */ if(cur->nodeT == if_stmt) { fprintf(ff, "L%d:\n", iflabel); } /* disclaimer: this is really hard to not sound confusing * * if the (if statement) has an (else statenment) then the (if statement) * will need to have a jump to miss the (else statement), otherwise the * jump from the (if statement) should jump to the beginning of the (else * statement) */ if(cur->nodeT == ifelse_stmt) { int elselabel = labelnum; labelnum++; fprintf(ff, "\tjmp L%d\t;skip else\n", elselabel); fprintf(ff, "L%d:;skip to else clause\n", iflabel); cGen(cur->child3); skip3 = 1; fprintf(ff, "L%d:\n", elselabel); } fprintf(ff, "\tadd esp, %d\n;;;end of if statement\n", curOffset-prevOffset); curOffset = prevOffset; } if(cur->child1 != NULL && skip1 == 0) cGen(cur->child1); if(cur->child2 != NULL && skip2 == 0) cGen(cur->child2); if(cur->child3 != NULL && skip3 == 0) cGen(cur->child3); if(cur->sibling != NULL && skipSib == 0) cGen(cur->sibling); return 0; }