version 1.127, 2003/11/03 20:13:36
|
version 1.128, 2003/11/06 09:47:50
|
Line 1057 void register_branchinfo(Label source, C
|
Line 1057 void register_branchinfo(Label source, C
|
nbranchinfos++; |
nbranchinfos++; |
} |
} |
|
|
Cell *compile_prim1arg(Cell p) |
Cell *compile_prim1arg(PrimNum p) |
{ |
{ |
int l = priminfos[p].length; |
int l = priminfos[p].length; |
Address old_code_here=code_here; |
Address old_code_here=code_here; |
Line 1095 void finish_code(void)
|
Line 1095 void finish_code(void)
|
set_rel_target(bi->addressptr, *(bi->targetptr)); |
set_rel_target(bi->addressptr, *(bi->targetptr)); |
} |
} |
nbranchinfos = 0; |
nbranchinfos = 0; |
|
#else |
|
compile_prim1(NULL); |
#endif |
#endif |
flush_to_here(); |
flush_to_here(); |
} |
} |
Line 1189 void compile_prim_dyn(Cell *start)
|
Line 1191 void compile_prim_dyn(Cell *start)
|
} |
} |
#endif /* 0 */ |
#endif /* 0 */ |
|
|
Cell compile_prim_dyn(unsigned p) |
#ifdef NO_IP |
|
Cell compile_prim_dyn(PrimNum p, Cell *tcp) |
|
/* compile prim #p dynamically (mod flags etc.) and return start |
|
address of generated code for putting it into the threaded |
|
code. This function is only called if all the associated |
|
inline arguments of p are already in place (at tcp[1] etc.) */ |
|
{ |
|
PrimInfo *pi=&priminfos[p]; |
|
Cell *next_code_target=NULL; |
|
Cell codeaddr = (Cell)code_here; |
|
|
|
assert(p<npriminfos); |
|
if (p==N_execute || p==N_perform || p==N_lit_perform) { |
|
next_code_target = compile_prim1arg(N_set_next_code); |
|
} |
|
if (p==N_call) { |
|
next_code_target = compile_call2(tcp[1]); |
|
} else if (p==N_does_exec) { |
|
struct doesexecinfo *dei = &doesexecinfos[ndoesexecinfos++]; |
|
*compile_prim1arg(N_lit) = (Cell)PFA(tcp[1]); |
|
/* we cannot determine the callee now (last_start[1] may be a |
|
forward reference), so just register an arbitrary target, and |
|
register in dei that we need to fix this before resolving |
|
branches */ |
|
dei->branchinfo = nbranchinfos; |
|
dei->xt = (Cell *)(tcp[1]); |
|
next_code_target = compile_call2(0); |
|
} else if (!is_relocatable(p)) { |
|
next_code_target = compile_prim1arg(N_set_next_code); |
|
set_rel_target(compile_prim1arg(N_branch),vm_prims[p]); |
|
} else { |
|
unsigned j; |
|
Address old_code_here = append_prim(p); |
|
|
|
for (j=0; j<pi->nimmargs; j++) { |
|
struct immarg *ia = &(pi->immargs[j]); |
|
Cell argval = tcp[pi->nimmargs - j]; /* !! specific to prims */ |
|
if (ia->rel) { /* !! assumption: relative refs are branches */ |
|
register_branchinfo(old_code_here + ia->offset, argval); |
|
} else /* plain argument */ |
|
*(Cell *)(old_code_here + ia->offset) = argval; |
|
} |
|
} |
|
if (next_code_target!=NULL) |
|
*next_code_target = (Cell)code_here; |
|
return codeaddr; |
|
} |
|
#else /* !defined(NO_IP) */ |
|
Cell compile_prim_dyn(PrimNum p, Cell *tcp) |
|
/* compile prim #p dynamically (mod flags etc.) and return start |
|
address of generated code for putting it into the threaded code */ |
{ |
{ |
Cell static_prim = (Cell)vm_prims[p]; |
Cell static_prim = (Cell)vm_prims[p]; |
#if defined(NO_DYNAMIC) |
#if defined(NO_DYNAMIC) |
Line 1208 Cell compile_prim_dyn(unsigned p)
|
Line 1260 Cell compile_prim_dyn(unsigned p)
|
return (Cell)old_code_here; |
return (Cell)old_code_here; |
#endif /* !defined(NO_DYNAMIC) */ |
#endif /* !defined(NO_DYNAMIC) */ |
} |
} |
|
#endif /* !defined(NO_IP) */ |
|
|
#ifndef NO_DYNAMIC |
#ifndef NO_DYNAMIC |
int cost_codesize(int prim) |
int cost_codesize(int prim) |
Line 1363 void optimize_rewrite(Cell *instps[], Pr
|
Line 1416 void optimize_rewrite(Cell *instps[], Pr
|
struct cost *c = super_costs+p; |
struct cost *c = super_costs+p; |
assert(trans[i][nextstate].cost != INF_COST); |
assert(trans[i][nextstate].cost != INF_COST); |
assert(c->state_in==nextstate); |
assert(c->state_in==nextstate); |
tc = compile_prim_dyn(p); |
tc = compile_prim_dyn(p,NULL); |
nextstate = c->state_out; |
nextstate = c->state_out; |
} |
} |
{ |
{ |
Line 1375 void optimize_rewrite(Cell *instps[], Pr
|
Line 1428 void optimize_rewrite(Cell *instps[], Pr
|
#if defined(GFORTH_DEBUGGING) |
#if defined(GFORTH_DEBUGGING) |
assert(p == origs[i]); |
assert(p == origs[i]); |
#endif |
#endif |
tc2 = compile_prim_dyn(p); |
tc2 = compile_prim_dyn(p,instps[i]); |
if (no_transition || !is_relocatable(p)) |
if (no_transition || !is_relocatable(p)) |
/* !! actually what we care about is if and where |
/* !! actually what we care about is if and where |
* compile_prim_dyn() puts NEXTs */ |
* compile_prim_dyn() puts NEXTs */ |
Line 1399 void optimize_rewrite(Cell *instps[], Pr
|
Line 1452 void optimize_rewrite(Cell *instps[], Pr
|
assert(c->state_in==nextstate); |
assert(c->state_in==nextstate); |
assert(trans[i][nextstate].cost != INF_COST); |
assert(trans[i][nextstate].cost != INF_COST); |
assert(i==nextdyn); |
assert(i==nextdyn); |
(void)compile_prim_dyn(p); |
(void)compile_prim_dyn(p,NULL); |
nextstate = c->state_out; |
nextstate = c->state_out; |
} |
} |
assert(nextstate==CANONICAL_STATE); |
assert(nextstate==CANONICAL_STATE); |
Line 1426 void compile_prim1(Cell *start)
|
Line 1479 void compile_prim1(Cell *start)
|
#elif defined(INDIRECT_THREADED) |
#elif defined(INDIRECT_THREADED) |
return; |
return; |
#else /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
#else /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
|
#if 1 |
|
/* !! does not work, for unknown reasons; but something like this is |
|
probably needed to ensure that we don't call compile_prim_dyn |
|
before the inline arguments are there */ |
|
static Cell *instps[MAX_BB]; |
|
static PrimNum origs[MAX_BB]; |
|
static int ninsts=0; |
|
PrimNum prim_num; |
|
|
|
if (start==NULL || ninsts >= MAX_BB || |
|
(ninsts>0 && superend[origs[ninsts-1]])) { |
|
/* after bb, or at the start of the next bb */ |
|
optimize_rewrite(instps,origs,ninsts); |
|
/* fprintf(stderr,"optimize_rewrite(...,%d)\n",ninsts); */ |
|
ninsts=0; |
|
if (start==NULL) |
|
return; |
|
} |
|
prim_num = ((Xt)*start)-vm_prims; |
|
if(prim_num >= npriminfos) { |
|
optimize_rewrite(instps,origs,ninsts); |
|
fprintf(stderr,"optimize_rewrite(...,%d)\n",ninsts); |
|
ninsts=0; |
|
return; |
|
} |
|
assert(ninsts<MAX_BB); |
|
instps[ninsts] = start; |
|
origs[ninsts] = prim_num; |
|
ninsts++; |
|
#else |
static Cell *instps[MAX_BB]; |
static Cell *instps[MAX_BB]; |
static PrimNum origs[MAX_BB]; |
static PrimNum origs[MAX_BB]; |
static int ninsts=0; |
static int ninsts=0; |
Line 1440 void compile_prim1(Cell *start)
|
Line 1523 void compile_prim1(Cell *start)
|
instps[ninsts] = start; |
instps[ninsts] = start; |
origs[ninsts] = prim_num; |
origs[ninsts] = prim_num; |
ninsts++; |
ninsts++; |
if (ninsts >= MAX_BB || superend[prim_num]) { |
if (ninsts >= MAX_BB || (ninsts>0 && superend[origs[ninsts-1]])) { |
end_bb: |
end_bb: |
optimize_rewrite(instps,origs,ninsts); |
optimize_rewrite(instps,origs,ninsts); |
|
fprintf(stderr,"optimize_rewrite(...,%d)\n",ninsts); |
ninsts=0; |
ninsts=0; |
|
return; |
} |
} |
|
#endif |
#endif /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
#endif /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
} |
} |
|
|