📄 x86.c
字号:
/** * for backend without generate ast forest. */#define X86_DOS#include <stdio.h>#include "common.h"#include "symtab.h"#include "error.h"#include "x86.h"#ifdef _MSDOS_#include <dos.h>#elif defined __linux__#include <time.h>#endif#include _YTAB_H_#define MAX_LOOP_LEVEL 16#define STMT_STACK_SIZE 64#define MAX_CALL_LEVEL 16#ifdef GENERATE_AST#define STATIC static#else#define STATIC#endif/*static Symbol p;static Symtab ptab;*/static symtab *rtn =NULL;static symbol *arg = NULL;STATIC int sym_tos = MAX_LOOP_LEVEL-1;STATIC int direc_stk[MAX_LOOP_LEVEL];STATIC int dir_tos = MAX_LOOP_LEVEL-1;STATIC int stmt_tos = STMT_STACK_SIZE - 1;STATIC int stmt_stack[STMT_STACK_SIZE];STATIC symbol *sym_stk[MAX_LOOP_LEVEL];STATIC int stmt_index = 0;STATIC int call_tos = MAX_CALL_LEVEL-1;STATIC symbol *call_sym[MAX_CALL_LEVEL];STATIC symtab *call_stk[MAX_CALL_LEVEL];STATIC void emit_write1(int arg_type);STATIC void emit_sqrt(int arg_type);STATIC void emit_odd(int arg_type);STATIC void emit_abs(int arg_type);STATIC void emit_sqr(int arg_type);STATIC void emit_read1(int arg_type);STATIC void emit_writeln(int arg_type);STATIC symbol *do_function_call(symtab *);STATIC void emit_program_head();STATIC void emit_program_prologue(symtab *);STATIC void emit_program_epilogue(symtab *);STATIC void emit_main_prologue(symtab *);STATIC void emit_main_epilogue(symtab *);STATIC void emit_routine_prologue(symtab *);STATIC void emit_routine_epilogue(symtab *);STATIC void emit_local_args(symtab *);STATIC void emit_push_op(int);STATIC void emit_load_value(symbol *);STATIC void do_function_assign(symtab *,int);STATIC void do_procedure_call(symtab *);STATIC void do_assign(symbol *, int);STATIC void do_if_test();STATIC void do_if_caluse();STATIC void do_if_exit();STATIC void do_repeat_start();STATIC void do_repeat_exit();STATIC void do_while_start();STATIC void do_while_expr();STATIC void do_while_exit();STATIC void do_for_start(symbol *);STATIC void do_for_test(int);STATIC void do_for_exit();STATIC void do_expression(symbol *, int);STATIC void do_negate(symbol *);STATIC void do_expr(symbol *, int);STATIC void do_term(symbol *, int);STATIC void do_factor(symbol *);STATIC void do_no_factor(symbol *);STATIC void do_array_factor(symbol *);STATIC void do_record_factor(symbol *, symbol *);STATIC void do_first_arg(int);STATIC void reset_args(symtab *);STATIC void push_stmt_stack(int);STATIC int pop_stmt_stack();STATIC int top_stmt_stack();STATIC int rout_index = 0;STATIC void do_sys_routine(int routine_id, int arg_type){ switch(routine_id) { case fABS: emit_abs(arg_type); break; case fODD: emit_odd(arg_type); break; case fPRED: fprintf(codfp, "\t\tdec\tax\n"); break; case fSQR: emit_sqr(arg_type); break; case fSQRT: emit_sqrt(arg_type); break; case fSUCC: fprintf(codfp, "\t\tinc\tax\n"); break; case pREAD: emit_read1(arg_type); break; case pREADLN: emit_read1(arg_type); break; case pWRITE: emit_write1(arg_type); break; case pWRITELN: emit_writeln(arg_type); break; default: break; }}STATIC void emit_read1(int arg_type){ fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_REAL: break; case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_read_int\n"); break; case TYPE_STRING: fprintf(codfp, "\t\tcall\t_read_string\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\tcall\t_read_char\n"); break; case TYPE_BOOLEAN: default: parse_error("operand type do not match operator.", ""); break; }}STATIC void emit_write1(int arg_type){ switch(arg_type) { case TYPE_INTEGER: case TYPE_BOOLEAN: fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); fprintf(codfp, "\t\tcall\t_write_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\tmov\tdl,al\n"); fprintf(codfp, "\t\tmov\tah,2\n"); fprintf(codfp, "\t\tint\t21h\n"); break; case TYPE_STRING: fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); fprintf(codfp, "\t\tcall\t_write_string\n"); break; default: break; }}STATIC void emit_writeln(int arg_type){ switch(arg_type) { case TYPE_INTEGER: case TYPE_BOOLEAN: fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); fprintf(codfp, "\t\tcall\t_writeln_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\tmov\tdl,al\n"); fprintf(codfp, "\t\tmov\tah,2\n"); fprintf(codfp, "\t\tint\t21h\n"); fprintf(codfp, "\t\tmov\tdl,13\n"); fprintf(codfp, "\t\tint\t21h\n"); fprintf(codfp, "\t\tmov\tdl,10\n"); fprintf(codfp, "\t\tint\t21h\n"); break; case TYPE_STRING: fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); fprintf(codfp, "\t\tcall\t_writeln_string\n"); break; default: break; }}STATIC void emit_abs(int arg_type){ fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_abs_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\txor\tah,ah\n"); fprintf(codfp, "\t\tcall\t_abs_int\n"); break; default: break; }}STATIC void emit_sqr(int arg_type){ fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_sqr_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\txor\tah,ah\n"); fprintf(codfp, "\t\tcall\t_sqr_int\n"); break; default: break; }}STATIC void emit_odd(int arg_type){ fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_odd_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\txor\tah,ah\n"); fprintf(codfp, "\t\tcall\t_odd_int\n"); break; default: break; }}STATIC void emit_sqrt(int arg_type){ fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_sqrt_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\txor\tah,ah\n"); fprintf(codfp, "\t\tcall\t_sqrt_int\n"); break; default: break; }}STATIC void emit_program_prologue(symtab *ptab){ fprintf(codfp, " \n;alloc stack space\n"); fprintf(codfp, " \t\tdb\t0%xh dup(?)\n" ,STACK_SEG_SIZE); fprintf(codfp,"\n_DATA\t\tends"); fprintf(codfp,"\n\n;---program %s ---",ptab->name); fprintf(codfp,"\n\n_TEXT\t\tsegment\tpublic\n\n"); fprintf(codfp,"\t\tinclude\tx86rtl.inc\n\n"); fprintf(codfp,"%s\tequ\tword ptr [bp+04h]\n" ,LABEL_SLINK); fprintf(codfp,"%s\tequ\tword ptr [bp-04h]\n", LABEL_RETVAL); fprintf(codfp,"%s\tequ\tword ptr [bp-02h]\n", LABEL_HIRETVAL); emit_program_head(); fprintf(datfp, " \n_DATA\t\tsegment\tpublic\n");}/* char datname[]; */STATIC void emit_program_head(){#ifdef _MSDOS_ struct dosdate_t d; struct dosdate_t t; _dos_getdate(&d); _dos_gettime(&t); fprintf(datfp,";%s\n;%02d:%02d:%02d/%d/%d/%d\n", t.hour,t.minute,t.second,d.month,d.day,d.year);#elif defined __linux__ time_t now; struct tm *tv; time(&now); tv = gmtime(&now); fprintf(datfp, ";%04d/%02d/%02d\n;%02d:%02d:%02d\n", tv->tm_year + 100, tv->tm_mon, tv->tm_mday, tv->tm_hour, tv->tm_min, tv->tm_sec);#endif fprintf(datfp,";\n"); fprintf(datfp,";SPL Compiler Ver %s\n",_PC_VER_); fprintf(datfp, "\n\n.MODEL SMALL\n");}STATIC void emit_program_epilogue(symtab *ptab){ symbol *p; fprintf(codfp,"\n_TEXT\t\tends\n"); fprintf(codfp,"\t\tend\tstart\n\n"); fprintf(datfp,"\n;global variables\n"); for(p = ptab->locals; p; p = p->next) { switch (p->type->type_id) { case TYPE_CHAR: fprintf(datfp,"%s\t\tdb\t",p->rname); break; case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(datfp,"%s\t\tdw\t",p->rname); break; case TYPE_REAL: fprintf(datfp,"%s\t\tdd\t",p->rname); break; case TYPE_STRING: fprintf(datfp,"%s\t\tdb\t%s\n",p->rname, p->v.s); fprintf(datfp,"\t\tdb\t'$'\n"); break; case TYPE_ARRAY: if(p->type_link->last->type->type_id == TYPE_INTEGER || p->type_link->last->type->type_id == TYPE_BOOLEAN) fprintf(datfp,"%s\t\tdw\t0%xh dup (?)\n" ,p->rname,p->type_link->num_ele); else if(p->type_link->last->type->type_id == TYPE_CHAR) fprintf(datfp,"%s\t\tdb\t0%xh dup (?)\n" ,p->rname,p->type_link->num_ele); else parse_error("complex array element not supported",""); if(p->defn != DEF_CONST) continue; break; case TYPE_RECORD: fprintf(datfp,"%s\t\tdb\t0%xh dup (?)\n" ,p->rname,p->type_link->size); continue; default: break; } if (p->defn == DEF_CONST) { switch(p->type->type_id) { case TYPE_CHAR: fprintf(datfp,"'%c'\n",p->v.c); break; case TYPE_INTEGER: if (p->v.i >= 0) fprintf(datfp, "0%xh\n", p->v.i); break; case TYPE_REAL: fprintf(datfp, "%g\n", p->v.f); break; case TYPE_STRING: break; default: fprintf(datfp,"?\n"); } } else fprintf(datfp,"?\n"); }}STATIC void emit_main_prologue(symtab *ptab){ fprintf(codfp,"\n\n; --- main routine ----\n"); fprintf(codfp,"_main\t\tproc\tfar\n"); fprintf(codfp,"\t\tassume\tcs:_TEXT,ds:_DATA\n"); fprintf(codfp,"start:\n"); fprintf(codfp,"\t\tpush\tds\n"); fprintf(codfp,"\t\tsub\tax,ax\n"); fprintf(codfp,"\t\tpush\tax\n"); fprintf(codfp,"\t\tmov\tax,_DATA\n"); fprintf(codfp,"\t\tmov\tds,ax\n");}STATIC void emit_main_epilogue(symtab *ptab){ fprintf(codfp,"\t\tret\n"); fprintf(codfp,"_main\t\tendp\n");}STATIC void emit_routine_prologue(symtab *ptab){ if(ptab->defn == DEF_PROG) return; fprintf(codfp,"\n\n; routine : %s \n",ptab->name); emit_local_args(ptab); fprintf(codfp,";routine code\n"); fprintf(codfp,"%s\t\tproc\n", ptab->rname); fprintf(codfp,"\t\tassume\tcs:_TEXT,ds:_DATA\n"); fprintf(codfp,"\t\tmov\tax,_DATA\n"); fprintf(codfp,"\t\tmov\tds,ax\n"); fprintf(codfp,"\t\tpush\tbp\n"); fprintf(codfp,"\t\tmov\tbp,sp\n"); if(ptab->defn == DEF_FUNCT) fprintf(codfp,"\t\tsub\tsp, 4\n"); fprintf(codfp,"\t\tsub\tsp,%04xh\n",ptab->local_size);}STATIC void emit_local_args(symtab *ptab){ symbol *p; char tp[10]; fprintf(codfp,";local variables in %s\n",ptab->name); for(p = ptab->locals; p->next; p = p->next) { switch(p->type->type_id) { case TYPE_CHAR: sprintf(tp, "byte ptr"); break; case TYPE_INTEGER: case TYPE_BOOLEAN: sprintf(tp, "word ptr"); break; case TYPE_REAL: sprintf(tp, "dword ptr"); break; case TYPE_ARRAY: if(p->type_link->last->type->type_id == TYPE_INTEGER || p->type_link->last->type->type_id == TYPE_BOOLEAN) sprintf(tp, "word ptr"); else if (p->type_link->last->type->type_id == TYPE_CHAR) sprintf(tp, "byte ptr"); break; case TYPE_RECORD: sprintf(tp, "byte ptr"); break; default: break; } fprintf(codfp," %s\t\tequ\t%s [bp-%04xh]\n", p->rname,tp,p->offset); } fprintf(codfp,"; arguments in %s\n", ptab->name); for(p =ptab->args;p ;p = p->next) { switch(p->type->type_id) { case TYPE_CHAR: sprintf(tp, "byte ptr"); break; case TYPE_INTEGER: case TYPE_BOOLEAN: sprintf(tp, "word ptr"); break; case TYPE_REAL: sprintf(tp, "dword ptr"); break; default: break; } fprintf(codfp,"%s\t\tequ\t%s [bp+%04xh]\n", p->rname,tp,p->offset); }}STATIC void emit_routine_epilogue(symtab *ptab){ if(ptab->defn == DEF_PROG) return; if(ptab->defn == DEF_FUNCT) { switch(ptab->type->type_id) { case TYPE_INTEGER: case TYPE_BOOLEAN: fprintf(codfp,"\n\t\tmov\tax, word ptr %s\n",LABEL_RETVAL); break; case TYPE_CHAR: fprintf(codfp,"\n\t\tmov\tah, 0\n"); fprintf(codfp,"\n\t\tmov\tax, byte ptr %s\n", LABEL_RETVAL); break; case TYPE_REAL: fprintf(codfp,"\n\t\tmov\tax,%s\n", LABEL_RETVAL); fprintf(codfp,"\n\t\tmov\tdx,%s\n", LABEL_HIRETVAL); break; } } fprintf(codfp,"\t\tmov\tsp,bp\n"); fprintf(codfp,"\t\tpop\tbp\n"); fprintf(codfp,"\t\tret\t%04xh\n",ptab->args_size + 2); fprintf(codfp,"\n%s\t\tendp\n",ptab->rname);}STATIC void emit_push_op(int ptype){ switch(ptype) { case TYPE_CHAR: case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp,"\t\tpush\tax\n"); break; case TYPE_REAL: fprintf(codfp,"\t\tpush\tdx\n"); fprintf(codfp,"\t\tpush\tax\n"); break; }}STATIC void emit_load_value(symbol *p){ if(p->defn==DEF_VARPARA) { fprintf(codfp,"\t\tmov\tbx,word ptr [bp+4]\n"); switch(p->type->type_id) { case TYPE_CHAR: fprintf(codfp,"\t\txor\tah, ah\n"); fprintf(codfp,"\t\tmov\tal, byte ptr [bx]\n"); break; case TYPE_REAL: fprintf(codfp,"\t\tmov\tax,word ptr [bx]\n"); fprintf(codfp,"\t\tmov\tdx,word ptr [bx+2]\n"); break; case TYPE_INTEGER: case TYPE_BOOLEAN: fprintf(codfp,"\t\tmov\tax,word ptr [bx]\n"); break; } } else if (p->tab->level==0 ||p->tab==top_symtab_stack()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -