📄 x86linux.c
字号:
#define X86_LINUX#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 16static symtab *rtn =NULL;static symbol *arg = NULL;static Symbol p;static Symtab ptab;static void emit_linux_write1(int arg_type);static void emit_linux_sqrt(int arg_type);static void emit_linux_odd(int arg_type);static void emit_linux_abs(int arg_type);static void emit_linux_sqr(int arg_type);static void emit_linux_read1(int arg_type);static void emit_linux_writeln(int arg_type);static int gen_level = 0;static void emit_linux_program_head();static void emit_linux_program_prologue(symtab *);static void emit_linux_program_epilogue(symtab *);static void emit_linux_main_prologue(symtab *);static void emit_linux_main_epilogue(symtab *);static void emit_linux_routine_prologue(symtab *);static void emit_linux_routine_epilogue(symtab *);static void emit_linux_local_args(symtab *);static void emit_linux_dos_push_op(Type ptype);static void emit_linux_load_value(symbol *);static void do_linux_function_assign(symtab *,int);static void do_linux_procedure_call(symtab *);static void do_linux_assign(symbol *, int);static void do_linux_expression(Type, int);static void do_linux_negate(symbol *);static void do_linux_expr(Type, int);static void do_linux_term(Type, int);static void do_linux_factor(symbol *);static void do_linux_array_factor(symbol *);static void do_linux_record_factor(symbol *, symbol *);static void do_linux_first_arg(int);static int emit_linux_address = 0;extern char datname[FILE_NAME_LEN];#ifdef LABEL_RETVAL#undef LABEL_RETVAL#define LABEL_RETVAL "-4(%ebp)"#endif#ifdef LABEL_SLINK#undef LABEL_SLINK#define LABEL_SLINK "8(%ebp)"#endifstatic void do_linux_sys_routine(int routine_id, int arg_type){ switch(routine_id) { case fABS: emit_linux_abs(arg_type); break; case fODD: emit_linux_odd(arg_type); break; case fPRED: fprintf(codfp, "\t\tdecl\t%%eax\n"); break; case fSQR: emit_linux_sqr(arg_type); break; case fSQRT: emit_linux_sqrt(arg_type); break; case fSUCC: fprintf(codfp, "\t\tincl\t%%eax\n"); break; case pREAD: emit_linux_read1(arg_type); break; case pREADLN: emit_linux_read1(arg_type); break; case pWRITE: emit_linux_write1(arg_type); break; case pWRITELN: emit_linux_writeln(arg_type); break; default: break; }}static void emit_linux_read1(int arg_type){ fprintf(codfp, "\t\tpushl\t%%eax\n"); fprintf(codfp, "\t\tpushl\t%%ebp\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; } fprintf(codfp, "\t\taddl\t$8, %%esp\n");}static void emit_linux_write1(int arg_type){ switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tpushl\t%%eax\n"); fprintf(codfp, "\t\tpushl\t%%ebp\n"); fprintf(codfp, "\t\tcall\t_write_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\tpushl\t%%eax\n"); fprintf(codfp, "\t\tpushl\t%%ebp\n"); fprintf(codfp, "\t\tcall\t_write_char\n"); break; case TYPE_STRING: fprintf(codfp, "\t\tpushl\t%%eax\n"); fprintf(codfp, "\t\tpushl\t%%ebp\n"); fprintf(codfp, "\t\tcall\t_write_string\n"); break; default: break; } fprintf(codfp, "\t\taddl\t$8, %%esp\n");}static void emit_linux_writeln(int arg_type){ switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tpushl\t%%eax\n"); fprintf(codfp, "\t\tpushl\t%%ebp\n"); fprintf(codfp, "\t\tcall\t_writeln_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\tpushl\t%%eax\n"); fprintf(codfp, "\t\tpushl\t%%ebp\n"); fprintf(codfp, "\t\tcall\t_writeln_char\n"); break; case TYPE_STRING: fprintf(codfp, "\t\tpushl\t%%eax\n"); fprintf(codfp, "\t\tpushl\t%%ebp\n"); fprintf(codfp, "\t\tcall\t_writeln_string\n"); break; default: break; } fprintf(codfp, "\t\taddl\t$8, %%esp\n");}static void emit_linux_abs(int arg_type){ fprintf(codfp, "\t\tpushl\t%%ebp\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\txorb\t%%ah,%%ah\n"); fprintf(codfp, "\t\tcall\t_abs_int\n"); break; default: break; } fprintf(codfp, "\t\taddl\t$8, %%esp\n");}static void emit_linux_sqr(int arg_type){ fprintf(codfp, "\t\tpushl\t%%bp\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\txorb\t%%ah,%%ah\n"); fprintf(codfp, "\t\tcall\t_sqr_int\n"); break; default: break; } fprintf(codfp, "\t\taddl\t$8, %%esp\n");}static void emit_linux_odd(int arg_type){ fprintf(codfp, "\t\tpushl\t%%bp\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\txorb\t%%ah,%%ah\n"); fprintf(codfp, "\t\tcall\t_odd_int\n"); break; default: break; } fprintf(codfp, "\t\taddl\t$8, %%esp\n");}static void emit_linux_sqrt(int arg_type){ fprintf(codfp, "\t\tpushl\t%%ebp\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\txorb\t%%ah,%%ah\n"); fprintf(codfp, "\t\tcall\t_sqrt_int\n"); break; default: break; } fprintf(codfp, "\t\taddl\t$8, %%esp\n");}static void emit_linux_program_prologue(symtab *ptab){ fprintf(codfp,"\n\n#---program %s ---",ptab->name); emit_linux_program_head();}/* char datname[]; */static void emit_linux_program_head(){ fprintf(datfp, "#\n"); fprintf(datfp, "#SPL Compiler Ver %s\n",_PC_VER_); fprintf(datfp, "#\n"); fprintf(datfp, ".file \"%s\"\n\n", datname); fprintf(datfp, "sys_call_id = 0x80\n"); fprintf(datfp, "exit_syscall = 0x1\n\n");}static void emit_linux_program_epilogue(symtab *ptab){ symbol *p; fprintf(codfp, "\n\n.globl _start\n"); fprintf(codfp, "_start:\n"); fprintf(codfp, "\t\tcall _main\n"); fprintf(codfp, "\t\tmovl $0, %%ebx\n"); fprintf(codfp, "\t\tmovl $exit_syscall, %%eax\n"); fprintf(codfp, "\t\tint $sys_call_id\n"); fprintf(codfp, ".ident \"SPL: 0.1.5\"\n"); fprintf(codfp, "\n#.bss variables\n"); for(p = ptab->locals; p; p = p->next) { if (p->defn != DEF_CONST) { switch (p->type->type_id) { case TYPE_CHAR: fprintf(codfp, "\t\t.comm %s,%d,%d\n", p->rname, IR->charmetric.size, IR->intmetric.align); break; case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\t.comm %s,%d,%d\n", p->rname, IR->intmetric.size, IR->intmetric.align); break; case TYPE_REAL: break; case TYPE_STRING: 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); */ fprintf(codfp,"\t\t.comm %s, %d, %d\n" ,p->rname, p->type_link->num_ele * IR->intmetric.size, IR->intmetric.align); 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); */ fprintf(codfp,"\t\t.comm %s, %d, %d\n" ,p->rname,p->type_link->num_ele, IR->intmetric.align); 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); */ fprintf(codfp,"\t\t.comm %s, %d, %d\n" ,p->rname, p->type_link->size, IR->intmetric.align); continue; default: break; } } } /* global variable as .data */ fprintf(datfp, ".data\n"); for(p = ptab->locals; p; p = p->next) { if (p->defn == DEF_CONST) { switch (p->type->type_id) { case TYPE_CHAR: fprintf(datfp, ".globl %s\n", p->rname); /* fprintf(datfp, "\t\t.align %d\n", IR->charmetric.align); */ fprintf(datfp, "\t\t.type %s @object\n", p->rname); fprintf(datfp, "\t\t.size %s, %d\n", p->rname, IR->charmetric.size); fprintf(datfp, "%s:\n", p->rname); fprintf(datfp, "\t\t.byte %d\n", p->v.c); break; case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(datfp, ".globl %s\n", p->rname); fprintf(datfp, "\t\t.align %d\n", IR->intmetric.align); fprintf(datfp, "\t\t.type %s @object\n", p->rname); fprintf(datfp, "\t\t.size %s, %d\n", p->rname, IR->intmetric.size); fprintf(datfp, "%s:\n", p->rname); fprintf(datfp, "\t\t.long %d\n", p->v.i); break; case TYPE_REAL: break; case TYPE_STRING: fprintf(datfp, ".globl %s\n", p->rname); fprintf(datfp, "\t\t.section .rodata\n"); fprintf(datfp, "\t\t.align %d\n", IR->pointermetric.align); fprintf(datfp, ".LC%s:\n", p->rname); if ((p->v.s[0] == '\'') && (p->v.s[strlen(p->v.s) - 1] == '\'')) { p->v.s[strlen(p->v.s) - 1] = '\0'; fprintf(datfp, "\t\t.string \"%s\"\n", p->v.s + 1); } else fprintf(datfp, "\t\t.string \"%s\"\n", p->v.s); fprintf(datfp, "\t\t.data\n"); fprintf(datfp, "\t\t.align %d\n", IR->pointermetric.align); fprintf(datfp, "\t\t.type %s @object\n", p->rname); fprintf(datfp, "\t\t.size %s, %d\n", p->rname, IR->pointermetric.size); fprintf(datfp, "%s:\n", p->rname); fprintf(datfp, "\t\t.long .LC%s\n", p->rname); break; case TYPE_ARRAY: break; case TYPE_RECORD: break; default: break; } } }}static void emit_linux_main_prologue(symtab *ptab){ fprintf(codfp,"\n\n# --- main routine ----\n"); fprintf(codfp, "\t\t.text\n"); fprintf(codfp, ".globl _main\n"); fprintf(codfp, "\t\t.type _main, @function\n"); fprintf(codfp, "_main:\n"); fprintf(codfp, "\t\tpushl\t%%ebp\n"); fprintf(codfp, "\t\tmovl\t%%esp, %%ebp\n");}static void emit_linux_main_epilogue(symtab *ptab){ fprintf(codfp,"\t\tleave\n"); fprintf(codfp,"\t\tret\n"); fprintf(codfp,".size _main, .-main\n");}static void emit_linux_routine_prologue(symtab *ptab){ if(ptab->defn == DEF_PROG) return; fprintf(codfp,"\n\n# routine : %s \n",ptab->name); emit_linux_local_args(ptab); fprintf(codfp, "\t\t.text\n"); fprintf(codfp, ".globl %s\n", ptab->rname); fprintf(codfp, "\t\t.type %s, @function\n", ptab->rname); fprintf(codfp, "%s:\n", ptab->rname); fprintf(codfp, "\t\tpushl\t%%ebp\n"); fprintf(codfp, "\t\tmovl\t%%esp, %%ebp\n"); if(ptab->defn == DEF_FUNCT) fprintf(codfp,"\t\tsubl\t$8, %%esp\n"); fprintf(codfp,"\t\tsubl\t$%d, %%esp\n",ptab->local_size);}static void emit_linux_local_args(symtab *ptab){ symbol *p; char tp[10]; 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -