diff --git a/src/docode.c b/src/docode.c index 5e1c52e3f8162c8776667a383204356c9f6e5ad3..a99b16402f7fed9264e74a5ee9879bc9108e4dbc 100644 --- a/src/docode.c +++ b/src/docode.c @@ -19,11 +19,11 @@ #include "main.h" #include "lex.h" #include "builtin_efuns.h" +#include "peep.h" +#include "docode.h" -int *break_stack=0; -static int current_break,break_stack_size; -int *continue_stack=0; -static int current_continue,continue_stack_size; +INT32 current_break=-1; +INT32 current_continue=-1; static INT32 current_switch_case; static INT32 current_switch_default; @@ -45,131 +45,35 @@ void ins_short(INT16 l,int area) add_to_mem_block(area, (char *)&l, sizeof(INT16)); } -static void upd_short(int offset, INT16 l) -{ -#ifdef HANDLES_UNALIGNED_MEMORY_ACCESS - *((INT16 *)(areas[A_PROGRAM].s.str+offset))=l; -#else - MEMCPY(areas[A_PROGRAM].s.str+offset, (char *)&l,sizeof(l)); -#endif -} - -static void upd_int(int offset, INT32 tmp) -{ -#ifdef HANDLES_UNALIGNED_MEMORY_ACCESS - *((int *)(areas[A_PROGRAM].s.str+offset))=tmp; -#else - MEMCPY(areas[A_PROGRAM].s.str+offset, (char *)&tmp,sizeof(tmp)); -#endif -} - /* * Store an INT32. */ -void ins_long(INT32 l,int area) +void ins_int(INT32 l,int area) { add_to_mem_block(area, (char *)&l+0, sizeof(INT32)); } -int store_linenumbers=1; - -static void low_ins_f_byte(unsigned int b) +void upd_int(int offset, INT32 tmp) { - if(store_linenumbers) store_linenumber(); - -#if defined(LASDEBUG) - if(lasdebug>1) - if(store_linenumbers) - fprintf(stderr,"Inserting f_byte %s (%d) at %ld\n", - get_instruction_name(b), b, - (long)PC); -#endif - b-=F_OFFSET; -#ifdef OPCPROF - if(store_linenumbers) add_compiled(b); -#endif - if(b>255) - { - switch(b >> 8) - { - case 1: low_ins_f_byte(F_ADD_256); break; - case 2: low_ins_f_byte(F_ADD_512); break; - case 3: low_ins_f_byte(F_ADD_768); break; - case 4: low_ins_f_byte(F_ADD_1024); break; - default: - low_ins_f_byte(F_ADD_256X); - ins_byte(b/256,A_PROGRAM); - } - b&=255; - } - ins_byte((unsigned char)b,A_PROGRAM); -} - -void ins_f_byte(unsigned int b) -{ -#ifdef DEBUG - if(a_flag>2) - fprintf(stderr,">%6lx: %s\n",(long)PC,get_f_name(b)); +#ifdef HANDLES_UNALIGNED_MEMORY_ACCESS + *((int *)(areas[A_PROGRAM].s.str+offset))=tmp; +#else + MEMCPY(areas[A_PROGRAM].s.str+offset, (char *)&tmp,sizeof(tmp)); #endif - low_ins_f_byte(b); } -static void ins_f_byte_with_numerical_arg(unsigned int a,unsigned int b) +INT32 read_int(int offset) { - switch(b >> 8) - { - case 0 : break; - case 1 : low_ins_f_byte(F_PREFIX_256); break; - case 2 : low_ins_f_byte(F_PREFIX_512); break; - case 3 : low_ins_f_byte(F_PREFIX_768); break; - case 4 : low_ins_f_byte(F_PREFIX_1024); break; - default: - if( b < 256*256) - { - low_ins_f_byte(F_PREFIX_CHARX256); - ins_byte(b>>8, A_PROGRAM); - }else if(b < 256*256*256) { - low_ins_f_byte(F_PREFIX_WORDX256); - ins_byte(b >> 16, A_PROGRAM); - ins_byte(b >> 8, A_PROGRAM); - }else{ - low_ins_f_byte(F_PREFIX_24BITX256); - ins_byte(b >> 24, A_PROGRAM); - ins_byte(b >> 16, A_PROGRAM); - ins_byte(b >> 8, A_PROGRAM); - } - } - ins_f_byte(a); -#ifdef DEBUG - if(a_flag>2) - fprintf(stderr,">%6lx: argument = %u\n",(long)PC,b); + INT32 tmp; +#ifdef HANDLES_UNALIGNED_MEMORY_ACCESS + tmp=*((int *)(areas[A_PROGRAM].s.str+offset)); +#else + MEMCPY((char *)&tmp, areas[A_PROGRAM].s.str+offset,sizeof(tmp)); #endif - ins_byte(b, A_PROGRAM); -} - - -static void ins_int(int i) -{ - switch(i) - { - case 0: ins_f_byte(F_CONST0); break; - case 1: ins_f_byte(F_CONST1); break; - case -1: ins_f_byte(F_CONST_1); break; - default: - if(i<0) - { - ins_f_byte_with_numerical_arg(F_NEG_NUMBER,-i); - }else{ - ins_f_byte_with_numerical_arg(F_NUMBER,i); - } - } + return tmp; } -static void ins_float(FLOAT_TYPE f) -{ - ins_f_byte(F_FLOAT); - add_to_mem_block(A_PROGRAM,(char *)&f,sizeof(FLOAT_TYPE)); -} +int store_linenumbers=1; /* * A mechanism to remember addresses on a stack. The size of the stack is @@ -212,173 +116,16 @@ INT32 pop_address() return comp_stack[--comp_stackp]; } -static void do_pop(int nr) -{ - if(!nr) return; - if(nr==1) - { - ins_f_byte(F_POP_VALUE); - }else if(nr<256){ - ins_f_byte(F_POP_N_ELEMS); - ins_byte(nr,A_PROGRAM); - }else{ - ins_f_byte(F_POP_N_ELEMS); - ins_byte(255,A_PROGRAM); - do_pop(nr-255); - } -} - -/* routines to optimize jumps */ - -#define JUMP_CONDITIONAL 1 -#define JUMP_UNSET 2 - -struct jump -{ - INT32 relative; - INT32 whereto; - INT32 wherefrom; - INT32 address; - unsigned char flags; - short token; -}; - -static int jump_ptr=0, max_jumps=0; -static struct jump jumps[256]; - -static void low_set_branch(INT32 address,INT32 whereto,INT32 relative) -{ - int j,e; - - if(address<0) return; - j=jump_ptr; - e=max_jumps; - while(e>=0) - { - if(jumps[j].address==address && (jumps[j].flags & JUMP_UNSET)) - break; - if(j) j--; else j=max_jumps; - e--; - } - if(e<0) j=-1; /* not found */ - - for(e=0;e<=max_jumps;e++) - { - if(jumps[e].flags & JUMP_UNSET) continue; - if(jumps[e].flags & JUMP_CONDITIONAL) continue; - if(jumps[e].wherefrom!=whereto) continue; -#if defined(LASDEBUG) - if(lasdebug>1) printf("Optimized Jump to a jump\n"); -#endif - whereto=jumps[e].whereto; - break; - } - - if(j>=0) - { - if(!(jumps[j].flags & JUMP_CONDITIONAL)) - { - for(e=0;e<=max_jumps;e++) - { - if(jumps[e].flags & JUMP_UNSET) continue; - if(jumps[e].whereto==jumps[j].wherefrom) - { - upd_int(jumps[e].address,whereto - jumps[e].relative); - jumps[e].whereto=whereto; -#if defined(LASDEBUG) - if(lasdebug>1) printf("Optimized Jump to a jump\n"); -#endif - } - } - } - jumps[j].relative=relative; - jumps[j].whereto=whereto; - jumps[j].flags&=~JUMP_UNSET; - } - upd_int(address,whereto - relative); -} - -static void set_branch(INT32 address,INT32 whereto) -{ - low_set_branch(address,whereto,address); -} -static INT32 do_jump(int token,INT32 whereto) -{ - jump_ptr=(jump_ptr+1)%NELEM(jumps); - if(jump_ptr>max_jumps) max_jumps=jump_ptr; +static int label_no=0; - jumps[jump_ptr].flags=JUMP_UNSET; - jumps[jump_ptr].whereto=-1; - jumps[jump_ptr].token=token; +static int alloc_label() { return ++label_no; } - if(token!=F_BRANCH) - jumps[jump_ptr].flags|=JUMP_CONDITIONAL; - - if(token>=0) - { - jumps[jump_ptr].wherefrom=PC; - ins_f_byte(token); - }else{ - jumps[jump_ptr].wherefrom=-1; - } - jumps[jump_ptr].relative=PC; - jumps[jump_ptr].address=PC; - ins_long(0, A_PROGRAM); - if(whereto!=-1) set_branch(jumps[jump_ptr].address, whereto); - return jumps[jump_ptr].address; -} - -static void clean_jumptable() { max_jumps=jump_ptr=-1; } - -struct jump_list +static int do_jump(int token,INT32 lbl) { - int *stack; - int current; - int size; -}; - -static void push_break_stack(struct jump_list *x) -{ - x->stack=break_stack; - x->current=current_break; - x->size=break_stack_size; - break_stack_size=10; - break_stack=(int *)xalloc(sizeof(int)*break_stack_size); - current_break=0; -} - -static void pop_break_stack(struct jump_list *x,int jump) -{ - for(current_break--;current_break>=0;current_break--) - set_branch(break_stack[current_break],jump); - - free((char *)break_stack); - - break_stack_size=x->size; - current_break=x->current; - break_stack=x->stack; -} - -static void push_continue_stack(struct jump_list *x) -{ - x->stack=continue_stack; - x->current=current_continue; - x->size=continue_stack_size; - continue_stack_size=10; - continue_stack=(int *)xalloc(sizeof(int)*continue_stack_size); - current_continue=0; -} - -static void pop_continue_stack(struct jump_list *x,int jump) -{ - for(current_continue--;current_continue>=0;current_continue--) - set_branch(continue_stack[current_continue],jump); - - free((char *)continue_stack); - continue_stack_size=x->size; - current_continue=x->current; - continue_stack=x->stack; + if(lbl==-1) lbl=alloc_label(); + emit(token, lbl); + return lbl; } static int do_docode2(node *n,int flags); @@ -387,6 +134,17 @@ static int do_docode2(node *n,int flags); #define DO_NOT_COPY 2 #define DO_POP 4 +#define ins_label(L) do_jump(F_LABEL, L) + +static void do_pop(int x) +{ + switch(x) + { + case 0: return; + case 1: emit2(F_POP_VALUE); break; + default: emit(F_POP_N_ELEMS,x); break; + } +} #define DO_CODE_BLOCK(N) do_pop(do_docode(N,DO_NOT_COPY | DO_POP)) int do_docode(node *n,INT16 flags) @@ -402,12 +160,6 @@ int do_docode(node *n,INT16 flags) } -int docode(node *n) -{ - clean_jumptable(); - return do_docode(n,0); -} - static INT32 do_jump_when_zero(node *n,int j); static int do_jump_when_non_zero(node *n,int j) @@ -488,7 +240,7 @@ static int do_docode2(node *n,int flags) { default: yyerror("Illegal lvalue."); - ins_int(0); + emit(F_NUMBER,0); return 1; case F_LVALUE_LIST: @@ -509,7 +261,7 @@ static int do_docode2(node *n,int flags) { fatal("Internal compiler error, Yikes!\n"); } - ins_f_byte(F_PUSH_ARRAY); + emit2(F_PUSH_ARRAY); return -0x7ffffff; case '?': @@ -518,7 +270,7 @@ static int do_docode2(node *n,int flags) { tmp1=do_jump_when_zero(CAR(n), -1); DO_CODE_BLOCK(CADR(n)); - set_branch(tmp1, PC); + emit(F_LABEL, tmp1); return 0; } @@ -526,7 +278,7 @@ static int do_docode2(node *n,int flags) { tmp1=do_jump_when_non_zero(CAR(n), -1); DO_CODE_BLOCK(CDDR(n)); - set_branch(tmp1, PC); + emit(F_LABEL,tmp1); return 0; } @@ -545,12 +297,12 @@ static int do_docode2(node *n,int flags) do_pop(tmp3 - tmp1); tmp3=do_jump(F_BRANCH,-1); - set_branch(tmp2, PC); + emit(F_LABEL, tmp2); tmp2=do_docode(CDDR(n), flags); if(tmp2 < tmp1) fatal("Count arguments was wrong.\n"); do_pop(tmp2 - tmp1); - set_branch(tmp3, PC); + emit(F_LABEL, tmp3); return tmp1; } @@ -574,9 +326,9 @@ static int do_docode2(node *n,int flags) { if(do_docode(CDR(n), 0)!=1) fatal("Internal compiler error, shit happens\n"); - ins_f_byte(F_LTOSVAL2); + emit2(F_LTOSVAL2); }else{ - ins_f_byte(F_LTOSVAL); + emit2(F_LTOSVAL); if(do_docode(CDR(n), 0)!=1) fatal("Internal compiler error, shit happens (again)\n"); } @@ -584,24 +336,24 @@ static int do_docode2(node *n,int flags) switch(n->token) { - case F_ADD_EQ: ins_f_byte(F_ADD); break; - case F_AND_EQ: ins_f_byte(F_AND); break; - case F_OR_EQ: ins_f_byte(F_OR); break; - case F_XOR_EQ: ins_f_byte(F_XOR); break; - case F_LSH_EQ: ins_f_byte(F_LSH); break; - case F_RSH_EQ: ins_f_byte(F_RSH); break; - case F_SUB_EQ: ins_f_byte(F_SUBTRACT); break; - case F_MULT_EQ:ins_f_byte(F_MULTIPLY);break; - case F_MOD_EQ: ins_f_byte(F_MOD); break; - case F_DIV_EQ: ins_f_byte(F_DIVIDE); break; + case F_ADD_EQ: emit2(F_ADD); break; + case F_AND_EQ: emit2(F_AND); break; + case F_OR_EQ: emit2(F_OR); break; + case F_XOR_EQ: emit2(F_XOR); break; + case F_LSH_EQ: emit2(F_LSH); break; + case F_RSH_EQ: emit2(F_RSH); break; + case F_SUB_EQ: emit2(F_SUBTRACT); break; + case F_MULT_EQ:emit2(F_MULTIPLY);break; + case F_MOD_EQ: emit2(F_MOD); break; + case F_DIV_EQ: emit2(F_DIVIDE); break; } if(flags & DO_POP) { - ins_f_byte(F_ASSIGN_AND_POP); + emit2(F_ASSIGN_AND_POP); return 0; }else{ - ins_f_byte(F_ASSIGN); + emit2(F_ASSIGN); return 1; } @@ -625,16 +377,16 @@ static int do_docode2(node *n,int flags) { if(do_docode(CDAR(n),DO_NOT_COPY)!=1) fatal("Infernal compiler error (dumpar core |ver hela mattan).\n"); - ins_f_byte(F_LTOSVAL2); + emit2(F_LTOSVAL2); }else{ - ins_f_byte(F_LTOSVAL); + emit2(F_LTOSVAL); if(do_docode(CDAR(n),DO_NOT_COPY)!=1) fatal("Infernal compiler error (dumpar core).\n"); } - ins_f_byte(CAR(n)->token); + emit2(CAR(n)->token); - ins_f_byte(n->token); + emit2(n->token); return n->token==F_ASSIGN; } @@ -648,17 +400,17 @@ static int do_docode2(node *n,int flags) switch(CDR(n)->token) { case F_LOCAL: - ins_f_byte(flags & DO_POP ? F_ASSIGN_LOCAL_AND_POP:F_ASSIGN_LOCAL); - ins_byte(CDR(n)->u.number,A_PROGRAM); + emit(flags & DO_POP ? F_ASSIGN_LOCAL_AND_POP:F_ASSIGN_LOCAL, + CDR(n)->u.number ); break; case F_GLOBAL: - ins_f_byte(flags & DO_POP ? F_ASSIGN_GLOBAL_AND_POP:F_ASSIGN_GLOBAL); - ins_byte(CDR(n)->u.number,A_PROGRAM); + emit(flags & DO_POP ? F_ASSIGN_GLOBAL_AND_POP:F_ASSIGN_GLOBAL, + CDR(n)->u.number); break; default: - ins_f_byte(flags & DO_POP ? F_ASSIGN_AND_POP:F_ASSIGN); + emit2(flags & DO_POP ? F_ASSIGN_AND_POP:F_ASSIGN); break; } return flags & DO_POP ? 0 : 1; @@ -671,7 +423,7 @@ static int do_docode2(node *n,int flags) tmp1=do_jump(n->token,-1); if(do_docode(CDR(n),0)!=1) fatal("Compiler internal error.\n"); - set_branch(tmp1,PC); + emit(F_LABEL,tmp1); return 1; case F_EQ: @@ -699,7 +451,7 @@ static int do_docode2(node *n,int flags) tmp1=do_docode(CAR(n),DO_NOT_COPY); if(do_docode(CDR(n),DO_NOT_COPY)!=2) fatal("Compiler internal error.\n"); - ins_f_byte(n->token); + emit2(n->token); return tmp1; case F_INC: @@ -712,10 +464,10 @@ static int do_docode2(node *n,int flags) if(flags & DO_POP) { - ins_f_byte(F_INC_AND_POP); + emit2(F_INC_AND_POP); return 0; }else{ - ins_f_byte(n->token); + emit2(n->token); return 1; } @@ -728,36 +480,40 @@ static int do_docode2(node *n,int flags) #endif if(flags & DO_POP) { - ins_f_byte(F_DEC_AND_POP); + emit2(F_DEC_AND_POP); return 0; }else{ - ins_f_byte(n->token); + emit2(n->token); return 1; } case F_FOR: { - struct jump_list brk,cnt; INT32 *prev_switch_jumptable = current_switch_jumptable; + INT32 break_save = current_break; + INT32 continue_save = current_continue; + current_switch_jumptable=0; + current_break=alloc_label(); + current_continue=alloc_label(); - push_break_stack(&brk); - push_continue_stack(&cnt); if(CDR(n)) { tmp1=do_jump(F_BRANCH,-1); - tmp2=PC; + tmp2=ins_label(-1); if(CDR(n)) DO_CODE_BLOCK(CADR(n)); - pop_continue_stack(&cnt,PC); + ins_label(current_continue); if(CDR(n)) DO_CODE_BLOCK(CDDR(n)); - set_branch(tmp1,PC); + emit(F_LABEL,tmp1); }else{ tmp2=PC; } do_jump_when_non_zero(CAR(n),tmp2); - pop_break_stack(&brk,PC); + ins_label(current_break); current_switch_jumptable = prev_switch_jumptable; + current_break=break_save; + current_continue=continue_save; return 0; } @@ -766,23 +522,27 @@ static int do_docode2(node *n,int flags) case F_FOREACH: { - struct jump_list cnt,brk; INT32 *prev_switch_jumptable = current_switch_jumptable; + INT32 break_save = current_break; + INT32 continue_save = current_continue; + current_switch_jumptable=0; + current_break=alloc_label(); + current_continue=alloc_label(); tmp2=do_docode(CAR(n),DO_NOT_COPY); - ins_f_byte(F_CONST0); + emit2(F_CONST0); tmp3=do_jump(F_BRANCH,-1); - tmp1=PC; - push_break_stack(&brk); - push_continue_stack(&cnt); + tmp1=ins_label(-1); DO_CODE_BLOCK(CDR(n)); - pop_continue_stack(&cnt,PC); - set_branch(tmp3,PC); + ins_label(current_continue); + emit(F_LABEL,tmp3); do_jump(n->token,tmp1); - pop_break_stack(&brk,PC); + ins_label(current_break); current_switch_jumptable = prev_switch_jumptable; + current_break=break_save; + current_continue=continue_save; return 0; } @@ -791,40 +551,49 @@ static int do_docode2(node *n,int flags) case F_INC_LOOP: case F_DEC_LOOP: { - struct jump_list cnt,brk; INT32 *prev_switch_jumptable = current_switch_jumptable; + INT32 break_save = current_break; + INT32 continue_save = current_continue; + current_switch_jumptable=0; + current_break=alloc_label(); + current_continue=alloc_label(); tmp2=do_docode(CAR(n),0); tmp3=do_jump(F_BRANCH,-1); - tmp1=PC; - push_break_stack(&brk); - push_continue_stack(&cnt); + tmp1=ins_label(-1); + DO_CODE_BLOCK(CDR(n)); - pop_continue_stack(&cnt,PC); - set_branch(tmp3,PC); + ins_label(current_continue); + emit(F_LABEL,tmp3); do_jump(n->token,tmp1); - pop_break_stack(&brk,PC); + ins_label(current_break); current_switch_jumptable = prev_switch_jumptable; + current_break=break_save; + current_continue=continue_save; return 0; } case F_DO: { - struct jump_list cnt,brk; INT32 *prev_switch_jumptable = current_switch_jumptable; + INT32 break_save = current_break; + INT32 continue_save = current_continue; + current_switch_jumptable=0; + current_break=alloc_label(); + current_continue=alloc_label(); - tmp2=PC; - push_break_stack(&brk); - push_continue_stack(&cnt); + tmp2=ins_label(-1); DO_CODE_BLOCK(CAR(n)); - pop_continue_stack(&cnt,PC); + ins_label(current_continue); do_jump_when_non_zero(CDR(n),tmp2); - pop_break_stack(&brk,PC); + ins_label(current_break); current_switch_jumptable = prev_switch_jumptable; + current_break=break_save; + current_continue=continue_save; return 0; } @@ -836,12 +605,12 @@ static int do_docode2(node *n,int flags) } tmp1=do_docode(CAR(n),0); - if(!tmp1) { ins_f_byte(F_CONST0); tmp1=1; } + if(!tmp1) { emit2(F_CONST0); tmp1=1; } if(tmp1>1) do_pop(tmp1-1); tmp1=store_prog_string(n->type); - ins_f_byte_with_numerical_arg(F_STRING,tmp1); - ins_f_byte(F_CAST); + emit(F_STRING,tmp1); + emit2(F_CAST); return 1; case F_APPLY: @@ -854,39 +623,39 @@ static int do_docode2(node *n,int flags) if(!CAR(n)->u.sval.u.efun->docode || !CAR(n)->u.sval.u.efun->docode(n)) { - ins_f_byte(F_MARK); + emit2(F_MARK); do_docode(CDR(n),0); tmp1=store_constant(& CAR(n)->u.sval, !(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND)); - ins_f_byte(F_MAX_OPCODE + tmp1); + emit(F_APPLY,tmp1); } if(n->type == void_type_string) return 0; return 1; }else{ if(CAR(n)->u.sval.u.object == &fake_object) { - ins_f_byte(F_MARK); + emit2(F_MARK); do_docode(CDR(n),0); - ins_f_byte_with_numerical_arg(F_CALL_LFUN, CAR(n)->u.sval.subtype); + emit(F_CALL_LFUN, CAR(n)->u.sval.subtype); return 1; } } } - ins_f_byte(F_MARK); + emit2(F_MARK); do_docode(CDR(n),0); tmp1=store_constant(& CAR(n)->u.sval, !(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND)); - ins_f_byte(F_MAX_OPCODE + tmp1); + emit(F_APPLY,tmp1); return 1; } else if(CAR(n)->token == F_IDENTIFIER && ID_FROM_INT(& fake_program, CAR(n)->u.number)->flags & IDENTIFIER_FUNCTION) { - ins_f_byte(F_MARK); + emit2(F_MARK); do_docode(CDR(n),0); - ins_f_byte_with_numerical_arg(F_CALL_LFUN, CAR(n)->u.number); + emit(F_CALL_LFUN, CAR(n)->u.number); return 1; } else @@ -894,7 +663,7 @@ static int do_docode2(node *n,int flags) struct lpc_string *tmp; struct efun *fun; - ins_f_byte(F_MARK); + emit2(F_MARK); tmp=make_shared_string("call_function"); if(!tmp) yyerror("No call_function efun."); fun=lookup_efun(tmp); @@ -904,7 +673,7 @@ static int do_docode2(node *n,int flags) do_docode(CAR(n),0); do_docode(CDR(n),0); tmp1=store_constant(& fun->function, 1); - ins_f_byte(tmp1 + F_MAX_OPCODE); + emit(F_APPLY, tmp1); return 1; } @@ -929,27 +698,24 @@ static int do_docode2(node *n,int flags) case F_SWITCH: { - struct jump_list brk; INT32 e,cases,*order; INT32 *jumptable; INT32 prev_switch_values_on_stack = current_switch_values_on_stack; INT32 prev_switch_case = current_switch_case; INT32 prev_switch_default = current_switch_default; INT32 *prev_switch_jumptable = current_switch_jumptable; + INT32 break_save = current_break; if(do_docode(CAR(n),0)!=1) fatal("Internal compiler error, time to panic\n"); - push_break_stack(&brk); + current_break=alloc_label(); cases=count_cases(CDR(n)); - ins_f_byte(F_SWITCH); - tmp1=PC; - ins_short(0, A_PROGRAM); - while(PC != (unsigned INT32)MY_ALIGN(PC)) - ins_byte(0, A_PROGRAM); - tmp2=PC; + tmp1=emit(F_SWITCH,0); + emit(F_ALIGN,sizeof(INT32)); + current_switch_values_on_stack=0; current_switch_case=0; current_switch_default=-1; @@ -958,29 +724,30 @@ static int do_docode2(node *n,int flags) for(e=0; e<cases*2+1; e++) { - jumptable[e]=do_jump(-1,-1); + jumptable[e]=emit(F_POINTER, 0); current_switch_jumptable[e]=-1; } current_switch_jumptable[current_switch_case++]=-1; DO_CODE_BLOCK(CDR(n)); - + f_aggregate(cases); - sp[-1].u.array=compact_array(sp[-1].u.array); order=get_switch_order(sp[-1].u.array); - + + /* Check for cases inside a range */ for(e=0; e<cases-1; e++) { - if(current_switch_jumptable[order[e]*2+2] != -1) + if(current_switch_jumptable[ order[e]*2+2 ] != -1) { - if(current_switch_jumptable[order[e]*2+2] != - current_switch_jumptable[order[e+1]*2+1]) + if(current_switch_jumptable[ order[e]*2+2 ] != + current_switch_jumptable[ order[e+1]*2+1 ]) yyerror("Case inside range."); } } - if(current_switch_default < 0) current_switch_default = PC; + if(current_switch_default < 0) + current_switch_default = ins_label(-1); for(e=0;e<cases*2+1;e++) if(current_switch_jumptable[e]==-1) @@ -992,10 +759,9 @@ static int do_docode2(node *n,int flags) free((char *)order); for(e=0; e<cases*2+1; e++) - low_set_branch(jumptable[e], current_switch_jumptable[e],tmp2); + update_arg(jumptable[e], current_switch_jumptable[e]); - e=store_constant(sp-1,1); - upd_short(tmp1,e); + update_arg(tmp1, store_constant(sp-1,1)); pop_stack(); free((char *)jumptable); @@ -1006,8 +772,9 @@ static int do_docode2(node *n,int flags) current_switch_case = prev_switch_case; current_switch_values_on_stack = prev_switch_values_on_stack ; - pop_break_stack(&brk,PC); + emit(F_LABEL, current_break); + current_break=break_save; return 0; } @@ -1032,11 +799,17 @@ static int do_docode2(node *n,int flags) if(is_equal(sp-tmp1, sp-1)) yyerror("Duplicate case."); - current_switch_jumptable[current_switch_case++]=PC; + current_switch_jumptable[current_switch_case++]=ins_label(-1); if(CDR(n)) { - current_switch_jumptable[current_switch_case++]=PC; + if(!is_const(CDR(n))) + yyerror("Case label isn't constant."); + + current_switch_jumptable[current_switch_case+1]= + current_switch_jumptable[current_switch_case]= + current_switch_jumptable[current_switch_case-1]; + current_switch_case+=2; tmp1=eval_low(CDR(n)); if(tmp1<1) { @@ -1049,7 +822,6 @@ static int do_docode2(node *n,int flags) for(tmp1=current_switch_values_on_stack; tmp1 > 1; tmp1--) if(is_equal(sp-tmp1, sp-1)) yyerror("Duplicate case."); - current_switch_jumptable[current_switch_case++]=PC; } current_switch_jumptable[current_switch_case++]=-1; } @@ -1063,74 +835,58 @@ static int do_docode2(node *n,int flags) }else if(current_switch_default!=-1){ yyerror("Duplicate switch default."); }else{ - current_switch_default = PC; + current_switch_default = ins_label(-1); } return 0; case F_BREAK: - if(!break_stack) + if(current_break == -1) { yyerror("Break outside loop or switch."); }else{ - if(current_break>=break_stack_size) - { - break_stack_size*=2; - break_stack=(int *)realloc((char *)break_stack, - sizeof(int)*break_stack_size); - if(!break_stack) - fatal("Out of memory.\n"); - } - break_stack[current_break++]=do_jump(F_BRANCH,-1); + do_jump(F_BRANCH, current_break); } return 0; case F_CONTINUE: - if(!continue_stack) + if(current_continue == -1) { yyerror("continue outside loop or switch."); }else{ - if(current_continue>=continue_stack_size) - { - continue_stack_size*=2; - continue_stack=(int *)realloc((char *)continue_stack, - sizeof(int)*continue_stack_size); - } - continue_stack[current_continue++]=do_jump(F_BRANCH,-1); + do_jump(F_BRANCH, current_continue); } return 0; case F_RETURN: - if(!CAR(n) || - (CAR(n)->token == F_CONSTANT && IS_ZERO(&CAR(n)->u.sval)) || - do_docode(CAR(n),0)<0) - { - ins_f_byte(F_RETURN_0); - }else{ - ins_f_byte(F_RETURN); - } + do_docode(CAR(n),0); + emit2(F_RETURN); return 0; case F_SSCANF: tmp1=do_docode(CAR(n),DO_NOT_COPY); tmp2=do_docode(CDR(n),DO_NOT_COPY | DO_LVALUE); - ins_f_byte_with_numerical_arg(F_SSCANF,tmp1+tmp2); + emit(F_SSCANF,tmp1+tmp2); return 1; case F_CATCH: { - struct jump_list cnt,brk; + INT32 break_save = current_break; + INT32 continue_save = current_continue; INT32 *prev_switch_jumptable = current_switch_jumptable; + current_switch_jumptable=0; + current_break=alloc_label(); + current_continue=alloc_label(); tmp1=do_jump(F_CATCH,-1); - push_break_stack(&brk); - push_continue_stack(&cnt); DO_CODE_BLOCK(CAR(n)); - pop_continue_stack(&cnt,PC); - pop_break_stack(&brk,PC); - ins_f_byte(F_DUMB_RETURN); - set_branch(tmp1,PC); + ins_label(current_continue); + ins_label(current_break); + emit2(F_DUMB_RETURN); + emit(F_LABEL,tmp1); + current_break=break_save; + current_continue=continue_save; current_switch_jumptable = prev_switch_jumptable; return 1; } @@ -1149,12 +905,12 @@ static int do_docode2(node *n,int flags) tmp1=do_docode(CAR(n), DO_NOT_COPY); if(do_docode(CDR(n),DO_NOT_COPY) != 1) fatal("Internal compiler error, please report this (1)."); - ins_f_byte(F_INDEX); + emit2(F_INDEX); if(!(flags & DO_NOT_COPY)) { while(n && n->token==F_INDEX) n=CAR(n); if(n->token==F_CONSTANT && !(n->node_info & OPT_EXTERNAL_DEPEND)) - ins_f_byte(F_COPY_VALUE); + emit2(F_COPY_VALUE); } } return tmp1; @@ -1163,16 +919,12 @@ static int do_docode2(node *n,int flags) switch(n->u.sval.type) { case T_INT: - ins_int(n->u.sval.u.integer); - return 1; - - case T_FLOAT: - ins_float(n->u.sval.u.float_number); + emit(F_NUMBER,n->u.sval.u.integer); return 1; case T_STRING: tmp1=store_prog_string(n->u.sval.u.string); - ins_f_byte_with_numerical_arg(F_STRING,tmp1); + emit(F_STRING,tmp1); return 1; case T_FUNCTION: @@ -1180,25 +932,25 @@ static int do_docode2(node *n,int flags) { if(n->u.sval.u.object == &fake_object) { - ins_f_byte_with_numerical_arg(F_LFUN,n->u.sval.subtype); + emit(F_LFUN,n->u.sval.subtype); return 1; } } default: tmp1=store_constant(&(n->u.sval),!(n->tree_info & OPT_EXTERNAL_DEPEND)); - ins_f_byte_with_numerical_arg(F_CONSTANT,tmp1); + emit(F_CONSTANT,tmp1); return 1; case T_ARRAY: case T_MAPPING: case T_LIST: tmp1=store_constant(&(n->u.sval),!(n->tree_info & OPT_EXTERNAL_DEPEND)); - ins_f_byte_with_numerical_arg(F_CONSTANT,tmp1); + emit(F_CONSTANT,tmp1); /* copy now or later ? */ if(!(flags & DO_NOT_COPY) && !(n->tree_info & OPT_EXTERNAL_DEPEND)) - ins_f_byte(F_COPY_VALUE); + emit2(F_COPY_VALUE); return 1; } @@ -1206,10 +958,10 @@ static int do_docode2(node *n,int flags) case F_LOCAL: if(flags & DO_LVALUE) { - ins_f_byte_with_numerical_arg(F_LOCAL_LVALUE,n->u.number); + emit(F_LOCAL_LVALUE,n->u.number); return 2; }else{ - ins_f_byte_with_numerical_arg(F_LOCAL,n->u.number); + emit(F_LOCAL,n->u.number); return 1; } @@ -1220,21 +972,21 @@ static int do_docode2(node *n,int flags) { yyerror("Cannot assign functions.\n"); }else{ - ins_f_byte_with_numerical_arg(F_LFUN,n->u.number); + emit(F_LFUN,n->u.number); } }else{ if(flags & DO_LVALUE) { - ins_f_byte_with_numerical_arg(F_GLOBAL_LVALUE,n->u.number); + emit(F_GLOBAL_LVALUE,n->u.number); return 2; }else{ - ins_f_byte_with_numerical_arg(F_GLOBAL,n->u.number); + emit(F_GLOBAL,n->u.number); } } return 1; case F_EFUN: - ins_f_byte_with_numerical_arg(n->token,n->u.number); + emit(n->token,n->u.number); return 1; case F_VAL_LVAL: @@ -1248,6 +1000,28 @@ static int do_docode2(node *n,int flags) void do_code_block(node *n) { - clean_jumptable(); + init_bytecode(); + label_no=0; DO_CODE_BLOCK(n); + asm_opt(); + assemble(); +} + +int docode(node *n) +{ + int tmp; + int label_no_save = label_no; + dynamic_buffer instrbuf_save = instrbuf; + + instrbuf.s.str=0; + label_no=0; + init_bytecode(); + + tmp=do_docode(n,0); + asm_opt(); + assemble(); + + instrbuf=instrbuf_save; + label_no = label_no_save; + return tmp; }