pike.git/
src/
docode.c
Branch:
Tag:
Non-build tags
All tags
No tags
1996-04-13
1996-04-13 03:01:06 by Fredrik Hübinette (Hubbe) <hubbe@hubbe.net>
7a82f9d8463e441c5517aa6e298f3b6daa538d4c (
647
lines) (+
211
/-
436
)
[
Show
|
Annotate
]
Branch:
branches/E-12
now makes code through peephole optimizer
Rev: src/docode.c:1.5
19:
#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:
add_to_mem_block(area, (char *)&l, sizeof(INT16)); }
-
static
void
upd
_
short(
int
offset
,
INT16 l
)
+
/*
+
* Store an INT32.
+
*/
+
void
ins
_
int
(
INT32
l
,
int
area
)
{
-
#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
+
add
_
to
_
mem
_
block
(
area
, (char *)&
l+0
,
sizeof(
INT32
));
}
-
static
void upd_int(int offset, INT32 tmp)
+
void upd_int(int offset, INT32 tmp)
{ #ifdef HANDLES_UNALIGNED_MEMORY_ACCESS *((int *)(areas[A_PROGRAM].s.str+offset))=tmp;
63:
#endif }
-
/*
-
* Store an
INT32
.
-
*/
-
void ins
_
long
(
INT32 l,
int
area
)
+
INT32
read
_
int
(int
offset
)
{
-
add
_
to
_
mem
_
block
(
area,
(char *)&
l+0
, sizeof(
INT32
));
+
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
+
return tmp;
} int store_linenumbers=1;
-
static void low_ins_f_byte(unsigned int b)
-
{
-
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));
-
#endif
-
low_ins_f_byte(b);
-
}
-
-
static void ins_f_byte_with_numerical_arg(unsigned int a,unsigned int b)
-
{
-
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);
-
#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);
-
}
-
}
-
}
-
-
static void ins_float(FLOAT_TYPE f)
-
{
-
ins_f_byte(F_FLOAT);
-
add_to_mem_block(A_PROGRAM,(char *)&f,sizeof(FLOAT_TYPE));
-
}
-
+
/* * A mechanism to remember addresses on a stack. The size of the stack is * defined in config.h.
212:
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 */
+
static
int
label_no=0;
-
#define
JUMP
_
CONDITIONAL
1
-
#define
JUMP
_
UNSET
2
+
static
int alloc
_
label()
{
return ++label
_
no;
}
-
struct
jump
+
static
int do_
jump
(int token,INT32 lbl)
{
-
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(
lbl
==
-1
)
lbl
=
alloc_label
();
+
emit(token,
lbl
);
+
return
lbl
;
}
-
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;
-
}
+
static
int
do
_
docode2
(
node
*n,int
flags);
-
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);
-
}
+
#define
DO
_
LVALUE
1
+
#define
DO
_
NOT
_
COPY
2
+
#
define
DO
_
POP
4
-
static
void set
_
branch
(
INT32 address,INT32 whereto
)
-
{
-
low
_
set_branch
(
address
,
whereto,address
)
;
-
}
+
#define
ins
_
label
(
L
)
do
_
jump(F
_
LABEL
,
L
)
-
static
INT32
do_
jump
(int
token,INT32 whereto
)
+
static
void
do_
pop
(int
x
)
{
-
jump_ptr=
(
jump_ptr+1
)
%NELEM(jumps);
-
if(jump_ptr>max_jumps) max_jumps=jump_ptr;
-
-
jumps[jump_ptr].flags=JUMP_UNSET;
-
jumps[jump_ptr].whereto=-1;
-
jumps[jump_ptr].token=token;
-
-
if(token!=F_BRANCH)
-
jumps[jump_ptr].flags|=JUMP_CONDITIONAL;
-
-
if(token>=0)
+
switch
(
x
)
{
-
jumps[jump_ptr].wherefrom=PC
;
-
ins
_
f
_
byte(token
);
-
}else{
-
jumps[jump
_
ptr].wherefrom=-1
;
+
case
0:
return
;
+
case
1:
emit2(F
_
POP
_
VALUE
);
break;
+
default:
emit(F
_
POP_N_ELEMS,x)
;
break;
}
-
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
-
{
-
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;
-
}
-
-
static int do_docode2(node *n,int flags);
-
-
#define DO_LVALUE 1
-
#define DO_NOT_COPY 2
-
#define DO_POP 4
-
+
#define DO_CODE_BLOCK(N) do_pop(do_docode(N,DO_NOT_COPY | DO_POP)) int do_docode(node *n,INT16 flags)
402:
}
-
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:
{ default: yyerror("Illegal lvalue.");
-
ins_int
(0);
+
emit(F
_
NUMBER,
0);
return 1; case F_LVALUE_LIST:
509:
{ fatal("Internal compiler error, Yikes!\n"); }
-
ins_f_byte
(F_PUSH_ARRAY);
+
emit2
(F_PUSH_ARRAY);
return -0x7ffffff; case '?':
518:
{ tmp1=do_jump_when_zero(CAR(n), -1); DO_CODE_BLOCK(CADR(n));
-
set_branch
(
tmp1
,
PC
);
+
emit(F
_
LABEL
,
tmp1
);
return 0; }
526:
{ 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:
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:
{ 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:
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:
{ 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:
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:
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:
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:
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:
#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:
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:
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:
} 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:
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:
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:
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:
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:
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; }
967:
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:
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:
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:
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:
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:
}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")
;
+
do
_
jump
(
F
_
BRANCH
,
current
_break);
}
-
break_stack[current_break++]=do_jump(F_BRANCH,-1);
-
}
+
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
);
+
do
_
jump
(
F
_
BRANCH
,
current_
continue);
}
-
continue_stack[current_continue++]=do_jump(F_BRANCH,-1);
-
}
+
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:
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:
switch(n->u.sval.type) { case T_INT:
-
ins_int
(n->u.sval.u.integer);
+
emit(F
_
NUMBER,
n->u.sval.u.integer);
return 1;
-
case T_FLOAT:
-
ins_float(n->u.sval.u.float_number);
-
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:
{ 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:
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:
{ 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:
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;
+
}