| int nbranchinfos=0; |
int nbranchinfos=0; |
| |
|
| struct branchinfo { |
struct branchinfo { |
| Label *targetptr; /* *(bi->targetptr) is the target */ |
Label **targetpp; /* **(bi->targetpp) is the target */ |
| Cell *addressptr; /* store the target here */ |
Cell *addressptr; /* store the target here */ |
| } branchinfos[100000]; |
} branchinfos[100000]; |
| |
|
| int ndoesexecinfos=0; |
int ndoesexecinfos=0; |
| struct doesexecinfo { |
struct doesexecinfo { |
| int branchinfo; /* fix the targetptr of branchinfos[...->branchinfo] */ |
int branchinfo; /* fix the targetptr of branchinfos[...->branchinfo] */ |
| |
Label *targetp; /*target for branch (because this is not in threaded code)*/ |
| Cell *xt; /* cfa of word whose does-code needs calling */ |
Cell *xt; /* cfa of word whose does-code needs calling */ |
| } doesexecinfos[10000]; |
} doesexecinfos[10000]; |
| |
|
| *source = ((Cell)target)-(((Cell)source)+4); |
*source = ((Cell)target)-(((Cell)source)+4); |
| } |
} |
| |
|
| void register_branchinfo(Label source, Cell targetptr) |
void register_branchinfo(Label source, Cell *targetpp) |
| { |
{ |
| struct branchinfo *bi = &(branchinfos[nbranchinfos]); |
struct branchinfo *bi = &(branchinfos[nbranchinfos]); |
| bi->targetptr = (Label *)targetptr; |
bi->targetpp = (Label **)targetpp; |
| bi->addressptr = (Cell *)source; |
bi->addressptr = (Cell *)source; |
| nbranchinfos++; |
nbranchinfos++; |
| } |
} |
| return old_code_here; |
return old_code_here; |
| } |
} |
| |
|
| Address compile_call2(Cell targetptr, Cell **next_code_targetp) |
Address compile_call2(Cell *targetpp, Cell **next_code_targetp) |
| { |
{ |
| PrimInfo *pi = &priminfos[N_call2]; |
PrimInfo *pi = &priminfos[N_call2]; |
| Address old_code_here = append_prim(N_call2); |
Address old_code_here = append_prim(N_call2); |
| |
|
| *next_code_targetp = (Cell *)(old_code_here + pi->immargs[0].offset); |
*next_code_targetp = (Cell *)(old_code_here + pi->immargs[0].offset); |
| register_branchinfo(old_code_here + pi->immargs[1].offset, targetptr); |
register_branchinfo(old_code_here + pi->immargs[1].offset, targetpp); |
| return old_code_here; |
return old_code_here; |
| } |
} |
| #endif |
#endif |
| compile_prim1(NULL); |
compile_prim1(NULL); |
| for (i=0; i<ndoesexecinfos; i++) { |
for (i=0; i<ndoesexecinfos; i++) { |
| struct doesexecinfo *dei = &doesexecinfos[i]; |
struct doesexecinfo *dei = &doesexecinfos[i]; |
| branchinfos[dei->branchinfo].targetptr = (Label *)DOES_CODE1((dei->xt)); |
dei->targetp = (Label *)DOES_CODE1((dei->xt)); |
| |
branchinfos[dei->branchinfo].targetpp = &(dei->targetp); |
| } |
} |
| ndoesexecinfos = 0; |
ndoesexecinfos = 0; |
| for (i=0; i<nbranchinfos; i++) { |
for (i=0; i<nbranchinfos; i++) { |
| struct branchinfo *bi=&branchinfos[i]; |
struct branchinfo *bi=&branchinfos[i]; |
| set_rel_target(bi->addressptr, *(bi->targetptr)); |
set_rel_target(bi->addressptr, **(bi->targetpp)); |
| } |
} |
| nbranchinfos = 0; |
nbranchinfos = 0; |
| #else |
#else |
| primstart = append_prim(p); |
primstart = append_prim(p); |
| goto other_prim; |
goto other_prim; |
| } else if (p==N_call) { |
} else if (p==N_call) { |
| codeaddr = compile_call2(tcp[1], &next_code_target); |
codeaddr = compile_call2(tcp+1, &next_code_target); |
| } else if (p==N_does_exec) { |
} else if (p==N_does_exec) { |
| struct doesexecinfo *dei = &doesexecinfos[ndoesexecinfos++]; |
struct doesexecinfo *dei = &doesexecinfos[ndoesexecinfos++]; |
| Cell *arg; |
Cell *arg; |
| other_prim: |
other_prim: |
| for (j=0; j<pi->nimmargs; j++) { |
for (j=0; j<pi->nimmargs; j++) { |
| struct immarg *ia = &(pi->immargs[j]); |
struct immarg *ia = &(pi->immargs[j]); |
| Cell argval = tcp[pi->nimmargs - j]; /* !! specific to prims */ |
Cell *argp = tcp + pi->nimmargs - j; |
| |
Cell argval = *argp; /* !! specific to prims */ |
| if (ia->rel) { /* !! assumption: relative refs are branches */ |
if (ia->rel) { /* !! assumption: relative refs are branches */ |
| register_branchinfo(primstart + ia->offset, argval); |
register_branchinfo(primstart + ia->offset, argp); |
| } else /* plain argument */ |
} else /* plain argument */ |
| *(Cell *)(primstart + ia->offset) = argval; |
*(Cell *)(primstart + ia->offset) = argval; |
| } |
} |