📄 compiler.c
字号:
#include<stdlib.h>#include<stdio.h>#include "struct.h"#include "stack.h"char source_filename[255]; /* name of source file in new language */char assembler_filename[255]; /* name of assembler for input to as */char object_code_filename[255]; /* name of object code for as output */char literals_filename[255]; /* name of file for string literals */FILE *assembler_file; /* the destination file for the assembler */FILE *literals_file; /* the file holding the string literals */int isMain; /* 0 other function , 1 main function */int findingFuncNode; /* meet node "func" marked 1, found func node ("ID") marked 0 */int BOOLlabel=0;int IFlabel = 0; /* IF label */int FORlabel = 0; /* FOR label */int SWITCHlabel = 0; /* FOR label */int CASElabel = 0; /* CASE label */int WHILElabel = 0; /* WHILE label */int DOlabel = 0; /* WHILE label */int ANDlabel = 0; /* AND label */int loopType=-1; /* 1 while, 2 do-while, 3 for, 4 switch */int initOrder=0;void output_literal_file();void output_start( FILE *file, char *literals_filename); void output_end( FILE *file); void code_gen_print(FILE *file, int i);void gen_data(FILE *file);void func_prologue(FILE *file);void func_epilogue(FILE *file);void code_gen(FILE *file, symnode *tree);void gen_func(FILE *file, symnode *tree);symnode *get_func_name(symnode *tree);void gen_func_content(FILE *file,symnode *tree);void gen_println(FILE *file, symnode *tree);void print_char_array(FILE *file, int len);void print_nl(FILE *file);void gen_assign(FILE *file, symnode *tree);void gen_operation(FILE *file, symnode *tree);void gen_global_vals(FILE *file,symnode *tree);void getIDAddr(symrec *id, char addr[]);void gen_OffsetIDAddress( FILE *file, symnode *tree);void gen_init_vals(FILE *file, symnode *tree);void gen_init_array(FILE *file, symnode *tree, int isGlobal, int idOffset);void gen_assign(FILE *file, symnode *tree);void gen_return(FILE *file, symnode *tree);void gen_assign_op(FILE *file, symnode *tree);void gen_unary_op(FILE *file, symnode *tree);void gen_logic_and(FILE *file);void gen_logic_or(FILE *file);void gen_if(FILE *file, symnode *tree);void gen_switch(FILE *file, symnode *tree);void gen_case_condition(FILE *file, symnode *tree);void gen_case(FILE *file, symnode *tree);void gen_for(FILE *file, symnode *tree);void gen_while(FILE *file, symnode *tree);void gen_dowhile(FILE *file, symnode *tree);void gen_break(FILE *file);void gen_continue(FILE *file);void gen_relation_code(FILE *file, symnode *tree);//void getRelationOp(symnode *tree, char *label1, char *label2, char *jmp);void getOperator(const char*, char * operator);/*************************************************************//* output the string literals in the following form *//* literalN: .string "actual string\n" *//* ready for inclusion in filename.S *//* note: .string adds a trailing \0 */ void output_literal_file(FILE *literals_file, int literal_count, char literals[255][255]){ int i; fprintf(literals_file, "\t\t# this is the file of string literals\n"); for( i=0; i < literal_count ; i++ ) { fprintf( literals_file, "literal%d:\t.string %s\n", i, literals[i] ); fprintf( literals_file, "\tlen%d = . - literal%d\n", i, i ); } // fprintf( literals_file, "newline:\t.string \"\\n\"\n"); // fprintf( literals_file, "\tnl_length = . - newline\n");} // end output_literal_file/**************************************************************//* tidy up at the end of the assembler file *//* and output the exit code */ void output_end( FILE *file){ //func_epilogue(file); fprintf( file, "\t%s\n", "movl $SYS_exit,%eax\t# load the exit call number"); fprintf( file, "\t%s\n", "movl $0,%ebx\t\t# load the exit code"); fprintf( file, "\t%s\n", "int $0x80\t\t# and exit!"); fprintf( file, "\t\t\t\t# end of the file\n");} // end output_end/*************************************************************//* output the start of the assembler to file *//* include the literal file: literals_filename *//* include the defines.h system call numbers *//* declare .data and .text sections *//* declare _start global */void output_start( FILE *file, char *literals_filename){ fprintf( file, "\t\t\t\t# start of the file\n"); //fprintf( file, ".data\n"); fprintf( file, ".include \"defines.h\"\t\t# system call numbers\n"); fprintf( file, ".include \"%s\"\t# include the string literal file\n", literals_filename); //fprintf( file, "\n.text\n"); fprintf( file, "\t.global _start\t\n"); fprintf( file, "\t.bss\n"); fprintf( file, "\t.align\t%d\n",4); gen_data(file);} // end output_start //allocate the memory for global variables void gen_data(FILE *file){ int size=0; size=sizeOfVals("Global"); fprintf(file, "_data:\n"); if(size!=0) fprintf(file, "\t%s\t\t%d\t%s\n",".skip",size,"# global variables' size"); fprintf(file, "%s\n",".text"); fprintf(file, "\t%s\t%d\n",".align",4); //fprintf( file, "_start:\n"); }void code_gen(FILE *file, symnode *tree){ if (tree==NULL) return; code_gen(file, tree->next); if(strcmp(tree->name,"func")==0){ findingFuncNode = 1; gen_func(file,tree->sibling); return; } code_gen(file, tree->sibling); }symnode *get_func_name(symnode *tree){ symnode *tmp=NULL; if(tree==NULL) return NULL; if(strcmp(tree->name,"ID")==0 && tree->symTab->nameType==1) return tree; tmp=get_func_name(tree->next); if(tmp!=NULL) return tmp; tmp=get_func_name(tree->sibling); return tmp;}//the procedure prologuevoid func_prologue(FILE *file){ fprintf( file, "\t%s\n", "pushl %ebp\t\t# save the ebp address"); fprintf( file, "\t%s, %s\n", "movl %esp","%ebp"); }//procedure epiloguevoid func_epilogue(FILE *file){ fprintf( file, "\t%s, %s\n", "movl %ebp","%esp"); fprintf( file, "\t%s\n", "popl %ebp\t\t# restore the ebp address");}void gen_global_vals(FILE *file, symnode *tree){ if(tree==NULL) return; if(strcmp(tree->name,"func")==0) return; if(strcmp(tree->name,"iDecLst")==0){ gen_init_vals(file, tree); return; } gen_global_vals(file, tree->next); gen_global_vals(file, tree->sibling);}void gen_func(FILE *file, symnode *tree){ symrec *funcNode=NULL; funcNode = get_func_name(tree)->symTab; if(strcmp(funcNode->name,"main")==0) { isMain = 1; fprintf( file, "_start:\n"); }else{ isMain = 0; fprintf( file, "%s:\n", funcNode->name); } func_prologue(file); if(isMain==1) gen_func_content(file, symRoot); fprintf(file,"\t%s $%d, %s\t\t# allocate space for local variables\n", "subl",sizeOfVals(funcNode->name),"%esp"); //gen_local_val(file, funcNode->name); gen_func_content(file, tree); }// the value of the variablesvoid getIDAddr(symrec *id, char addr[]){ int size; if (strcmp(id->scope, "Global")==0){ size = offsetAtID("Global",id->order); if(id->isArray){ size=size - 4*id->numArray; }else size-=4; sprintf(addr, "_data+%d%c",size ,'\0'); return ; } if(id->isFuncArg){ sprintf(addr, "%d%s", offsetOfPara(id->scope, id->argOrder),"(%ebp)" ); return ; }else{ int offset=0; offset = offsetAtID(id->scope, id->order); if (offset ==0) sprintf(addr, "%s","%ebp"); else sprintf(addr, "-%d%s", offset,"(%ebp)"); return ; } return ; }// dynamicly calculate the address for variablesvoid gen_OffsetIDAddress( FILE *file, symnode *tree){ int offset=0; int size=0; char addr[255]; if(tree==NULL) return ; gen_OffsetIDAddress(file, tree->next); gen_OffsetIDAddress(file, tree->sibling); if(strcmp(tree->name, "ID")==0){ getIDAddr(tree->symTab, addr); if(tree->symTab->isFuncArg) fprintf(file, "\t%s %s, %s\n", "movl", addr, "%eax"); else fprintf(file, "\t%s %s, %s\n", "leal", addr, "%eax"); fprintf(file, "\t%s\n", "pushl %eax"); //printf("id: %s type: %d\n", tree->symTab->name, tree->symTab->type); switch(tree->symTab->type){ case 0: case 1: push(1.0);break; case 2: push(2.0);break; default: push(-1.0);break; } return; } if(strcmp(tree->name, "member")==0){ offset=sizeAtMember(tree->symTab->structtype, tree->value); fprintf(file, "\t%s%d\n", "pushl $", offset); pop(); switch(getMemberType(tree->symTab->structtype, tree->value)){ case 0: case 1: push(1.0);break; case 2: push(2.0);break; default: push(-1.0);break; } return; } if(strcmp(tree->name, "exp")==0){ gen_assign(file, tree); pop(); //pop(); //if((tree->symTab->isFuncArg==0) && strcmp(tree->symTab->scope, "Global")!=0) // fprintf(file,"\t%s\n", "negl %eax"); if( (strcmp(tree->value, tree->symTab->name)==0)&&(tree->symTab->type==5)){ // array of struct size=sizeOfStruct(tree->symTab->structtype); fprintf(file, "\t%s\n", "popl %eax"); fprintf(file, "\t%s%d, %s\n", "imull $",size,"%eax"); fprintf(file, "\t%s\n", "pushl %eax"); }else fprintf(file, "\t%s\n", "sall $2, (%esp)"); return; } if(strcmp(tree->name, "offset")==0){ fprintf(file, "\t%s\n", "popl %ebx"); fprintf(file, "\t%s\n", "popl %eax"); fprintf(file, "\t%s\n", "addl %ebx, %eax"); // should be subl for local variables fprintf(file, "\t%s\n", "pushl %eax"); return; } }// when meet node "iDecLst", do the followingvoid gen_init_vals(FILE *file, symnode *tree){ symnode *id; int isGlobal=0; int idOffset=0; id = tree; while(id!=NULL){ if(strcmp(id->name,"ID")==0) break; id=id->next; } if(id->symTab->type!=5 && id->symTab->isArray!=1){ gen_assign(file, tree->next); fprintf(file, "\t%s\n", "popl %eax"); pop(); }else{ idOffset=offsetAtID(id->symTab->scope, id->symTab->order); //printf("name: %s, scope: %s, order: %d,idOffset %d\n", id->symTab->name, id->symTab->scope,id->symTab->order,idOffset); if(strcmp(id->symTab->scope, "Global")==0){ idOffset=idOffset-4*id->symTab->numArray; isGlobal=1; } gen_init_array(file, tree->next->sibling, isGlobal, idOffset); }}void gen_init_array(FILE *file, symnode *tree, int isGlobal, int idOffset){ int i=0; if(tree==NULL) return; gen_init_array(file, tree->next, isGlobal, idOffset); gen_init_array(file, tree->sibling, isGlobal, idOffset); if((strcmp(tree->name, "INT_V")==0) || (strcmp(tree->name, "FLT_V")==0)){ if(isGlobal) fprintf(file, "\t%s $%s, %s%d\n", "movl", tree->value, "_data+",idOffset+initOrder*4); else fprintf(file, "\t%s $%s, %d%s\n", "movl", tree->value,(-1)*(idOffset-initOrder*4), "(%ebp)"); initOrder++; return; } if(strcmp(tree->name, "CHAR_V")==0){ if(isGlobal) fprintf(file, "\t%s $%s, %s%d\n", "movl", tree->value, "_data+",idOffset+initOrder*4); else fprintf(file, "\t%s $%s, %d%s\n", "movl", tree->value,(-1)*(idOffset-initOrder*4), "(%ebp)"); initOrder++; return; } if(strcmp(tree->name, "STRING")==0){ // printf("char: %s\n", tree->value); for(i=0;i<strlen(literals[tree->strIndex])-2; i++){ if(isGlobal) fprintf(file, "\t%s $%d, %s%d\n", "movl", (int)(literals[tree->strIndex][i+1]), "_data+",idOffset+i*4); else fprintf(file, "\t%s $%d, %d%s\n", "movl", (int)(literals[tree->strIndex][i+1]),(-1)*(idOffset-i*4), "(%ebp)"); } if(isGlobal) fprintf(file, "\t%s, %s%d\n", "movl $0", "_data+",idOffset+i*4); else fprintf(file, "\t%s, %d%s\n", "movl $0", (-1)*(idOffset-i*4), "(%ebp)"); return; } }void gen_unary_op(FILE *file, symnode *tree){ float a; if(tree==NULL) return; if(strcmp(tree->sibling->name, "unaryOp")==0){ printf("--compiling error(line %d): invalid operand with increment or decrement\n",tree->sibling->line); exit(0) ; } gen_OffsetIDAddress(file, tree->sibling);// id address already on top of stack fprintf(file, "\t%s\n","popl %eax"); a=pop(); if(strcmp(tree->value, "O+")==0){ // if it's id++ if(a!=2.0){ fprintf(file, "\t%s\n","push (%eax)"); fprintf(file, "\t%s\n","incl (%eax)"); }else{ fprintf(file, "\t%s\n","push (%eax)"); fprintf(file, "\t%s\n", "fld1"); fprintf(file, "\t%s\n", "flds (%eax)"); fprintf(file, "\t%s\n", "faddp %st, %st(1)"); fprintf(file, "\t%s\n", "fstps (%eax)"); } } if(strcmp(tree->value, "O-")==0){ // if it's id-- if(a!=2.0){ fprintf(file, "\t%s\n","push (%eax)"); fprintf(file, "\t%s\n","decl (%eax)"); }else{ fprintf(file, "\t%s\n", "push (%eax)"); fprintf(file, "\t%s\n", "fld1"); fprintf(file, "\t%s\n", "flds (%eax)"); fprintf(file, "\t%s\n", "fsubp %st, %st(1)"); fprintf(file, "\t%s\n", "fstps (%eax)"); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -