| } |
} |
| #endif |
#endif |
| |
|
| |
#ifdef HAS_LIBFFI |
| |
Cell *RP; |
| |
Address LP; |
| |
|
| |
#include <ffi.h> |
| |
|
| |
void ** clist; |
| |
void * ritem; |
| |
|
| |
void ffi_callback(ffi_cif * cif, void * resp, void ** args, Xt * ip) |
| |
{ |
| |
Cell *rp = RP; |
| |
Cell *sp = SP; |
| |
Float *fp = FP; |
| |
Address lp = LP; |
| |
|
| |
clist = args; |
| |
ritem = resp; |
| |
|
| |
engine(ip, sp, rp, fp, lp); |
| |
|
| |
/* restore global variables */ |
| |
RP = rp; |
| |
SP = sp; |
| |
FP = fp; |
| |
LP = lp; |
| |
} |
| |
#endif |
| |
|
| #ifdef GFORTH_DEBUGGING |
#ifdef GFORTH_DEBUGGING |
| /* define some VM registers as global variables, so they survive exceptions; |
/* define some VM registers as global variables, so they survive exceptions; |
| global register variables are not up to the task (according to the |
global register variables are not up to the task (according to the |
| static int no_dynamic=NO_DYNAMIC_DEFAULT; /* if true, no code is generated |
static int no_dynamic=NO_DYNAMIC_DEFAULT; /* if true, no code is generated |
| dynamically */ |
dynamically */ |
| static int print_metrics=0; /* if true, print metrics on exit */ |
static int print_metrics=0; /* if true, print metrics on exit */ |
| static int static_super_number = 10000000; /* number of ss used if available */ |
static int static_super_number = 0; /*10000000;*/ /* number of ss used if available */ |
| #define MAX_STATE 4 /* maximum number of states */ |
#define MAX_STATE 9 /* maximum number of states */ |
| static int maxstates = MAX_STATE; /* number of states for stack caching */ |
static int maxstates = MAX_STATE; /* number of states for stack caching */ |
| static int ss_greedy = 0; /* if true: use greedy, not optimal ss selection */ |
static int ss_greedy = 0; /* if true: use greedy, not optimal ss selection */ |
| static int diag = 0; /* if true: print diagnostic informations */ |
static int diag = 0; /* if true: print diagnostic informations */ |
| #include PRIM_NAMES_I |
#include PRIM_NAMES_I |
| }; |
}; |
| |
|
| |
void init_ss_cost(void); |
| |
|
| static int is_relocatable(int p) |
static int is_relocatable(int p) |
| { |
{ |
| return !no_dynamic && priminfos[p].start != NULL; |
return !no_dynamic && priminfos[p].start != NULL; |
| token=image[i]; |
token=image[i]; |
| if (token>=base) { /* relocatable address */ |
if (token>=base) { /* relocatable address */ |
| UCell bitnum=(token-base)/sizeof(Cell); |
UCell bitnum=(token-base)/sizeof(Cell); |
| |
if (bitnum/RELINFOBITS < (UCell)steps) |
| result[bitnum/RELINFOBITS] |= 1U << ((~bitnum)&(RELINFOBITS-1)); |
result[bitnum/RELINFOBITS] |= 1U << ((~bitnum)&(RELINFOBITS-1)); |
| } |
} |
| } |
} |
| #if defined(HAVE_MMAP) |
#if defined(HAVE_MMAP) |
| if (offset==0) { |
if (offset==0) { |
| image=alloc_mmap(dictsize); |
image=alloc_mmap(dictsize); |
| |
if (image != (Address)MAP_FAILED) { |
| |
Address image1; |
| debugp(stderr,"try mmap($%lx, $%lx, ..., MAP_FIXED|MAP_FILE, imagefile, 0); ", (long)image, (long)imagesize); |
debugp(stderr,"try mmap($%lx, $%lx, ..., MAP_FIXED|MAP_FILE, imagefile, 0); ", (long)image, (long)imagesize); |
| image = mmap(image, imagesize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|MAP_FILE|MAP_PRIVATE, fileno(file), 0); |
image1 = mmap(image, imagesize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|MAP_FILE|MAP_PRIVATE, fileno(file), 0); |
| after_alloc(image,dictsize); |
after_alloc(image1,dictsize); |
| |
if (image1 == (Address)MAP_FAILED) |
| |
goto read_image; |
| |
} |
| } |
} |
| #endif /* defined(HAVE_MMAP) */ |
#endif /* defined(HAVE_MMAP) */ |
| if (image == (Address)MAP_FAILED) { |
if (image == (Address)MAP_FAILED) { |
| image = my_alloc(dictsize+offset)+offset; |
image = my_alloc(dictsize+offset)+offset; |
| |
read_image: |
| rewind(file); /* fseek(imagefile,0L,SEEK_SET); */ |
rewind(file); /* fseek(imagefile,0L,SEEK_SET); */ |
| fread(image, 1, imagesize, file); |
fread(image, 1, imagesize, file); |
| } |
} |
| #endif |
#endif |
| |
|
| /* ensure that the cached elements (if any) are accessible */ |
/* ensure that the cached elements (if any) are accessible */ |
| IF_spTOS(sp0--); |
#if !(defined(GFORTH_DEBUGGING) || defined(INDIRECT_THREADED) || defined(DOUBLY_INDIRECT) || defined(VM_PROFILING)) |
| |
sp0 -= 8; /* make stuff below bottom accessible for stack caching */ |
| |
#endif |
| IF_fpTOS(fp0--); |
IF_fpTOS(fp0--); |
| |
|
| for(;stack>0;stack--) |
for(;stack>0;stack--) |
| install_signal_handlers(); /* right place? */ |
install_signal_handlers(); /* right place? */ |
| |
|
| if ((throw_code=setjmp(throw_jmp_buf))) { |
if ((throw_code=setjmp(throw_jmp_buf))) { |
| static Cell signal_data_stack[8]; |
static Cell signal_data_stack[24]; |
| static Cell signal_return_stack[8]; |
static Cell signal_return_stack[16]; |
| static Float signal_fp_stack[1]; |
static Float signal_fp_stack[1]; |
| |
|
| signal_data_stack[7]=throw_code; |
signal_data_stack[15]=throw_code; |
| |
|
| #ifdef GFORTH_DEBUGGING |
#ifdef GFORTH_DEBUGGING |
| debugp(stderr,"\ncaught signal, throwing exception %d, ip=%p rp=%p\n", |
debugp(stderr,"\ncaught signal, throwing exception %d, ip=%p rp=%p\n", |
| *--rp0 = (Cell)saved_ip; |
*--rp0 = (Cell)saved_ip; |
| } |
} |
| else /* I love non-syntactic ifdefs :-) */ |
else /* I love non-syntactic ifdefs :-) */ |
| rp0 = signal_return_stack+8; |
rp0 = signal_return_stack+16; |
| #else /* !defined(GFORTH_DEBUGGING) */ |
#else /* !defined(GFORTH_DEBUGGING) */ |
| debugp(stderr,"\ncaught signal, throwing exception %d\n", throw_code); |
debugp(stderr,"\ncaught signal, throwing exception %d\n", throw_code); |
| rp0 = signal_return_stack+8; |
rp0 = signal_return_stack+16; |
| #endif /* !defined(GFORTH_DEBUGGING) */ |
#endif /* !defined(GFORTH_DEBUGGING) */ |
| /* fprintf(stderr, "rp=$%x\n",rp0);*/ |
/* fprintf(stderr, "rp=$%x\n",rp0);*/ |
| |
|
| return((int)(Cell)engine(image_header->throw_entry, signal_data_stack+7, |
return((int)(Cell)engine(image_header->throw_entry, signal_data_stack+15, |
| rp0, signal_fp_stack, 0)); |
rp0, signal_fp_stack, 0)); |
| } |
} |
| #endif |
#endif |
| |
|
| Cell npriminfos=0; |
Cell npriminfos=0; |
| |
|
| |
Label goto_start; |
| |
Cell goto_len; |
| |
|
| int compare_labels(const void *pa, const void *pb) |
int compare_labels(const void *pa, const void *pb) |
| { |
{ |
| Label a = *(Label *)pa; |
Label a = *(Label *)pa; |
| { |
{ |
| int i; |
int i; |
| #ifndef NO_DYNAMIC |
#ifndef NO_DYNAMIC |
| Label *symbols2, *symbols3, *ends1, *ends1j, *ends1jsorted; |
Label *symbols2, *symbols3, *ends1, *ends1j, *ends1jsorted, *goto_p; |
| int nends1j; |
int nends1j; |
| #endif |
#endif |
| |
|
| #endif |
#endif |
| ends1 = symbols1+i+1; |
ends1 = symbols1+i+1; |
| ends1j = ends1+i; |
ends1j = ends1+i; |
| |
goto_p = ends1j+i+1; /* goto_p[0]==before; ...[1]==after;*/ |
| nends1j = i+1; |
nends1j = i+1; |
| ends1jsorted = (Label *)alloca(nends1j*sizeof(Label)); |
ends1jsorted = (Label *)alloca(nends1j*sizeof(Label)); |
| memcpy(ends1jsorted,ends1j,nends1j*sizeof(Label)); |
memcpy(ends1jsorted,ends1j,nends1j*sizeof(Label)); |
| qsort(ends1jsorted, nends1j, sizeof(Label), compare_labels); |
qsort(ends1jsorted, nends1j, sizeof(Label), compare_labels); |
| |
|
| |
/* check whether the "goto *" is relocatable */ |
| |
goto_len = goto_p[1]-goto_p[0]; |
| |
debugp(stderr, "goto * %p %p len=%ld\n", |
| |
goto_p[0],symbols2[goto_p-symbols1],goto_len); |
| |
if (memcmp(goto_p[0],symbols2[goto_p-symbols1],goto_len)!=0) { /* unequal */ |
| |
no_dynamic=1; |
| |
debugp(stderr," not relocatable, disabling dynamic code generation\n"); |
| |
init_ss_cost(); |
| |
return; |
| |
} |
| |
goto_start = goto_p[0]; |
| |
|
| priminfos = calloc(i,sizeof(PrimInfo)); |
priminfos = calloc(i,sizeof(PrimInfo)); |
| for (i=0; symbols1[i]!=0; i++) { |
for (i=0; symbols1[i]!=0; i++) { |
| int prim_len = ends1[i]-symbols1[i]; |
int prim_len = ends1[i]-symbols1[i]; |
| PrimInfo *pi=&priminfos[i]; |
PrimInfo *pi=&priminfos[i]; |
| |
struct cost *sc=&super_costs[i]; |
| int j=0; |
int j=0; |
| char *s1 = (char *)symbols1[i]; |
char *s1 = (char *)symbols1[i]; |
| char *s2 = (char *)symbols2[i]; |
char *s2 = (char *)symbols2[i]; |
| |
|
| pi->start = s1; |
pi->start = s1; |
| pi->superend = superend[i]|no_super; |
pi->superend = superend[i]|no_super; |
| if (pi->superend) |
|
| pi->length = endlabel-symbols1[i]; |
|
| else |
|
| pi->length = prim_len; |
pi->length = prim_len; |
| pi->restlength = endlabel - symbols1[i] - pi->length; |
pi->restlength = endlabel - symbols1[i] - pi->length; |
| pi->nimmargs = 0; |
pi->nimmargs = 0; |
| relocs++; |
relocs++; |
| debugp(stderr, "%-15s %3d %p %p %p len=%3ld restlen=%2ld s-end=%1d", |
debugp(stderr, "%-15s %d-%d %4d %p %p %p len=%3ld rest=%2ld send=%1d", |
| prim_names[i], i, s1, s2, s3, (long)(pi->length), (long)(pi->restlength), pi->superend); |
prim_names[i], sc->state_in, sc->state_out, |
| |
i, s1, s2, s3, (long)(pi->length), (long)(pi->restlength), |
| |
pi->superend); |
| if (endlabel == NULL) { |
if (endlabel == NULL) { |
| pi->start = NULL; /* not relocatable */ |
pi->start = NULL; /* not relocatable */ |
| if (pi->length<0) pi->length=100; |
if (pi->length<0) pi->length=100; |
| |
|
| memcpy(code_here, pi->start+pi->length, pi->restlength); |
memcpy(code_here, pi->start+pi->length, pi->restlength); |
| code_here += pi->restlength; |
code_here += pi->restlength; |
| |
memcpy(code_here, goto_start, goto_len); |
| |
code_here += goto_len; |
| last_jump=0; |
last_jump=0; |
| } |
} |
| } |
} |
| return static_prim; |
return static_prim; |
| } |
} |
| old_code_here = append_prim(p); |
old_code_here = append_prim(p); |
| last_jump = (priminfos[p].superend) ? 0 : p; |
last_jump = p; |
| |
if (priminfos[p].superend) |
| |
append_jump(); |
| return (Cell)old_code_here; |
return (Cell)old_code_here; |
| #endif /* !defined(NO_DYNAMIC) */ |
#endif /* !defined(NO_DYNAMIC) */ |
| } |
} |
| { cost_nexts, "nexts", 0 } |
{ cost_nexts, "nexts", 0 } |
| }; |
}; |
| |
|
| |
#ifndef NO_DYNAMIC |
| |
void init_ss_cost(void) { |
| |
if (no_dynamic && ss_cost == cost_codesize) { |
| |
ss_cost = cost_nexts; |
| |
cost_sums[0] = cost_sums[1]; /* don't use cost_codesize for print-metrics */ |
| |
debugp(stderr, "--no-dynamic conflicts with --ss-min-codesize, reverting to --ss-min-nexts\n"); |
| |
} |
| |
} |
| |
#endif |
| |
|
| #define MAX_BB 128 /* maximum number of instructions in BB */ |
#define MAX_BB 128 /* maximum number of instructions in BB */ |
| #define INF_COST 1000000 /* infinite cost */ |
#define INF_COST 1000000 /* infinite cost */ |
| #define CANONICAL_STATE 0 |
#define CANONICAL_STATE 0 |
| * or this transition (does not change state) */ |
* or this transition (does not change state) */ |
| }; |
}; |
| |
|
| |
struct tpa_state { /* tree parsing automaton (like) state */ |
| |
/* labeling is back-to-front */ |
| |
struct waypoint *inst; /* in front of instruction */ |
| |
struct waypoint *trans; /* in front of instruction and transition */ |
| |
}; |
| |
|
| |
struct tpa_state *termstate = NULL; /* initialized in loader() */ |
| |
|
| void init_waypoints(struct waypoint ws[]) |
void init_waypoints(struct waypoint ws[]) |
| { |
{ |
| int k; |
int k; |
| ws[k].cost=INF_COST; |
ws[k].cost=INF_COST; |
| } |
} |
| |
|
| void transitions(struct waypoint inst[], struct waypoint trans[]) |
struct tpa_state *empty_tpa_state() |
| |
{ |
| |
struct tpa_state *s = malloc(sizeof(struct tpa_state)); |
| |
|
| |
s->inst = calloc(maxstates,sizeof(struct waypoint)); |
| |
init_waypoints(s->inst); |
| |
s->trans = calloc(maxstates,sizeof(struct waypoint)); |
| |
/* init_waypoints(s->trans);*/ |
| |
return s; |
| |
} |
| |
|
| |
void transitions(struct tpa_state *t) |
| { |
{ |
| int k; |
int k; |
| struct super_state *l; |
struct super_state *l; |
| |
|
| for (k=0; k<maxstates; k++) { |
for (k=0; k<maxstates; k++) { |
| trans[k] = inst[k]; |
t->trans[k] = t->inst[k]; |
| trans[k].no_transition = 1; |
t->trans[k].no_transition = 1; |
| } |
} |
| for (l = state_transitions; l != NULL; l = l->next) { |
for (l = state_transitions; l != NULL; l = l->next) { |
| PrimNum s = l->super; |
PrimNum s = l->super; |
| int jcost; |
int jcost; |
| struct cost *c=super_costs+s; |
struct cost *c=super_costs+s; |
| struct waypoint *wi=&(trans[c->state_in]); |
struct waypoint *wi=&(t->trans[c->state_in]); |
| struct waypoint *wo=&(inst[c->state_out]); |
struct waypoint *wo=&(t->inst[c->state_out]); |
| if (wo->cost == INF_COST) |
if (wo->cost == INF_COST) |
| continue; |
continue; |
| jcost = wo->cost + ss_cost(s); |
jcost = wo->cost + ss_cost(s); |
| } |
} |
| } |
} |
| |
|
| |
struct tpa_state *make_termstate() |
| |
{ |
| |
struct tpa_state *s = empty_tpa_state(); |
| |
|
| |
s->inst[CANONICAL_STATE].cost = 0; |
| |
transitions(s); |
| |
return s; |
| |
} |
| |
|
| |
#define TPA_SIZE 16384 |
| |
|
| |
struct tpa_entry { |
| |
struct tpa_entry *next; |
| |
PrimNum inst; |
| |
struct tpa_state *state_behind; /* note: brack-to-front labeling */ |
| |
struct tpa_state *state_infront; /* note: brack-to-front labeling */ |
| |
} *tpa_table[TPA_SIZE]; |
| |
|
| |
Cell hash_tpa(PrimNum p, struct tpa_state *t) |
| |
{ |
| |
UCell it = (UCell )t; |
| |
return (p+it+(it>>14))&(TPA_SIZE-1); |
| |
} |
| |
|
| |
struct tpa_state **lookup_tpa(PrimNum p, struct tpa_state *t2) |
| |
{ |
| |
int hash=hash_tpa(p, t2); |
| |
struct tpa_entry *te = tpa_table[hash]; |
| |
|
| |
for (; te!=NULL; te = te->next) { |
| |
if (p == te->inst && t2 == te->state_behind) |
| |
return &(te->state_infront); |
| |
} |
| |
te = (struct tpa_entry *)malloc(sizeof(struct tpa_entry)); |
| |
te->next = tpa_table[hash]; |
| |
te->inst = p; |
| |
te->state_behind = t2; |
| |
te->state_infront = NULL; |
| |
tpa_table[hash] = te; |
| |
return &(te->state_infront); |
| |
} |
| |
|
| |
void tpa_state_normalize(struct tpa_state *t) |
| |
{ |
| |
/* normalize so cost of canonical state=0; this may result in |
| |
negative states for some states */ |
| |
int d = t->inst[CANONICAL_STATE].cost; |
| |
int i; |
| |
|
| |
for (i=0; i<maxstates; i++) { |
| |
if (t->inst[i].cost != INF_COST) |
| |
t->inst[i].cost -= d; |
| |
if (t->trans[i].cost != INF_COST) |
| |
t->trans[i].cost -= d; |
| |
} |
| |
} |
| |
|
| |
int tpa_state_equivalent(struct tpa_state *t1, struct tpa_state *t2) |
| |
{ |
| |
return (memcmp(t1->inst, t2->inst, maxstates*sizeof(struct waypoint)) == 0 && |
| |
memcmp(t1->trans,t2->trans,maxstates*sizeof(struct waypoint)) == 0); |
| |
} |
| |
|
| |
struct tpa_state_entry { |
| |
struct tpa_state_entry *next; |
| |
struct tpa_state *state; |
| |
} *tpa_state_table[TPA_SIZE]; |
| |
|
| |
Cell hash_tpa_state(struct tpa_state *t) |
| |
{ |
| |
int *ti = (int *)(t->inst); |
| |
int *tt = (int *)(t->trans); |
| |
int r=0; |
| |
int i; |
| |
|
| |
for (i=0; ti+i < (int *)(t->inst+maxstates); i++) |
| |
r += ti[i]+tt[i]; |
| |
return (r+(r>>14)+(r>>22)) & (TPA_SIZE-1); |
| |
} |
| |
|
| |
struct tpa_state *lookup_tpa_state(struct tpa_state *t) |
| |
{ |
| |
Cell hash = hash_tpa_state(t); |
| |
struct tpa_state_entry *te = tpa_state_table[hash]; |
| |
struct tpa_state_entry *tn; |
| |
|
| |
for (; te!=NULL; te = te->next) { |
| |
if (tpa_state_equivalent(t, te->state)) { |
| |
free(t->inst); |
| |
free(t->trans); |
| |
free(t); |
| |
return te->state; |
| |
} |
| |
} |
| |
tn = (struct tpa_state_entry *)malloc(sizeof(struct tpa_state_entry)); |
| |
tn->next = te; |
| |
tn->state = t; |
| |
tpa_state_table[hash] = tn; |
| |
return t; |
| |
} |
| |
|
| /* use dynamic programming to find the shortest paths within the basic |
/* use dynamic programming to find the shortest paths within the basic |
| block origs[0..ninsts-1] and rewrite the instructions pointed to by |
block origs[0..ninsts-1] and rewrite the instructions pointed to by |
| instps to use it */ |
instps to use it */ |
| void optimize_rewrite(Cell *instps[], PrimNum origs[], int ninsts) |
void optimize_rewrite(Cell *instps[], PrimNum origs[], int ninsts) |
| { |
{ |
| int i,j; |
int i,j; |
| static struct waypoint inst[MAX_BB+1][MAX_STATE]; /* before instruction*/ |
struct tpa_state *ts[ninsts+1]; |
| static struct waypoint trans[MAX_BB+1][MAX_STATE]; /* before transition */ |
|
| int nextdyn, nextstate, no_transition; |
int nextdyn, nextstate, no_transition; |
| |
|
| init_waypoints(inst[ninsts]); |
ts[ninsts] = termstate; |
| inst[ninsts][CANONICAL_STATE].cost=0; |
|
| transitions(inst[ninsts],trans[ninsts]); |
|
| for (i=ninsts-1; i>=0; i--) { |
for (i=ninsts-1; i>=0; i--) { |
| init_waypoints(inst[i]); |
struct tpa_state **tp = lookup_tpa(origs[i],ts[i+1]); |
| |
struct tpa_state *t = *tp; |
| |
if (t) |
| |
ts[i] = t; |
| |
else { |
| |
ts[i] = empty_tpa_state(); |
| for (j=1; j<=max_super && i+j<=ninsts; j++) { |
for (j=1; j<=max_super && i+j<=ninsts; j++) { |
| struct super_state **superp = lookup_super(origs+i, j); |
struct super_state **superp = lookup_super(origs+i, j); |
| if (superp!=NULL) { |
if (superp!=NULL) { |
| PrimNum s = supers->super; |
PrimNum s = supers->super; |
| int jcost; |
int jcost; |
| struct cost *c=super_costs+s; |
struct cost *c=super_costs+s; |
| struct waypoint *wi=&(inst[i][c->state_in]); |
struct waypoint *wi=&(ts[i]->inst[c->state_in]); |
| struct waypoint *wo=&(trans[i+j][c->state_out]); |
struct waypoint *wo=&(ts[i+j]->trans[c->state_out]); |
| int no_transition = wo->no_transition; |
int no_transition = wo->no_transition; |
| if (!(is_relocatable(s)) && !wo->relocatable) { |
if (!(is_relocatable(s)) && !wo->relocatable) { |
| wo=&(inst[i+j][c->state_out]); |
wo=&(ts[i+j]->inst[c->state_out]); |
| no_transition=1; |
no_transition=1; |
| } |
} |
| if (wo->cost == INF_COST) |
if (wo->cost == INF_COST) |
| } |
} |
| } |
} |
| } |
} |
| transitions(inst[i],trans[i]); |
transitions(ts[i]); |
| |
tpa_state_normalize(ts[i]); |
| |
*tp = ts[i] = lookup_tpa_state(ts[i]); |
| |
} |
| } |
} |
| /* now rewrite the instructions */ |
/* now rewrite the instructions */ |
| nextdyn=0; |
nextdyn=0; |
| nextstate=CANONICAL_STATE; |
nextstate=CANONICAL_STATE; |
| no_transition = ((!trans[0][nextstate].relocatable) |
no_transition = ((!ts[0]->trans[nextstate].relocatable) |
| ||trans[0][nextstate].no_transition); |
||ts[0]->trans[nextstate].no_transition); |
| for (i=0; i<ninsts; i++) { |
for (i=0; i<ninsts; i++) { |
| Cell tc=0, tc2; |
Cell tc=0, tc2; |
| if (i==nextdyn) { |
if (i==nextdyn) { |
| if (!no_transition) { |
if (!no_transition) { |
| /* process trans */ |
/* process trans */ |
| PrimNum p = trans[i][nextstate].inst; |
PrimNum p = ts[i]->trans[nextstate].inst; |
| struct cost *c = super_costs+p; |
struct cost *c = super_costs+p; |
| assert(trans[i][nextstate].cost != INF_COST); |
assert(ts[i]->trans[nextstate].cost != INF_COST); |
| assert(c->state_in==nextstate); |
assert(c->state_in==nextstate); |
| tc = compile_prim_dyn(p,NULL); |
tc = compile_prim_dyn(p,NULL); |
| nextstate = c->state_out; |
nextstate = c->state_out; |
| } |
} |
| { |
{ |
| /* process inst */ |
/* process inst */ |
| PrimNum p = inst[i][nextstate].inst; |
PrimNum p = ts[i]->inst[nextstate].inst; |
| struct cost *c=super_costs+p; |
struct cost *c=super_costs+p; |
| assert(c->state_in==nextstate); |
assert(c->state_in==nextstate); |
| assert(inst[i][nextstate].cost != INF_COST); |
assert(ts[i]->inst[nextstate].cost != INF_COST); |
| #if defined(GFORTH_DEBUGGING) |
#if defined(GFORTH_DEBUGGING) |
| assert(p == origs[i]); |
assert(p == origs[i]); |
| #endif |
#endif |
| /* !! 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 */ |
| tc=tc2; |
tc=tc2; |
| no_transition = inst[i][nextstate].no_transition; |
no_transition = ts[i]->inst[nextstate].no_transition; |
| nextstate = c->state_out; |
nextstate = c->state_out; |
| nextdyn += c->length; |
nextdyn += c->length; |
| } |
} |
| assert(0); |
assert(0); |
| #endif |
#endif |
| tc=0; |
tc=0; |
| /* tc= (Cell)vm_prims[inst[i][CANONICAL_STATE].inst]; */ |
/* tc= (Cell)vm_prims[ts[i]->inst[CANONICAL_STATE].inst]; */ |
| } |
} |
| *(instps[i]) = tc; |
*(instps[i]) = tc; |
| } |
} |
| if (!no_transition) { |
if (!no_transition) { |
| PrimNum p = trans[i][nextstate].inst; |
PrimNum p = ts[i]->trans[nextstate].inst; |
| struct cost *c = super_costs+p; |
struct cost *c = super_costs+p; |
| assert(c->state_in==nextstate); |
assert(c->state_in==nextstate); |
| assert(trans[i][nextstate].cost != INF_COST); |
assert(ts[i]->trans[nextstate].cost != INF_COST); |
| assert(i==nextdyn); |
assert(i==nextdyn); |
| (void)compile_prim_dyn(p,NULL); |
(void)compile_prim_dyn(p,NULL); |
| nextstate = c->state_out; |
nextstate = c->state_out; |
| #else /* defined(DOUBLY_INDIRECT) */ |
#else /* defined(DOUBLY_INDIRECT) */ |
| check_sum = (UCell)vm_prims; |
check_sum = (UCell)vm_prims; |
| #endif /* defined(DOUBLY_INDIRECT) */ |
#endif /* defined(DOUBLY_INDIRECT) */ |
| |
#if !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) |
| |
termstate = make_termstate(); |
| |
#endif /* !(defined(DOUBLY_INDIRECT) || defined(INDIRECT_THREADED)) */ |
| |
|
| do { |
do { |
| if(fread(magic,sizeof(Char),8,imagefile) < 8) { |
if(fread(magic,sizeof(Char),8,imagefile) < 8) { |
| void print_diag() |
void print_diag() |
| { |
{ |
| |
|
| #if !defined(HAVE_GETRUSAGE) || !defined(HAS_FFCALL) |
#if !defined(HAVE_GETRUSAGE) || (!defined(HAS_FFCALL) && !defined(HAS_LIBFFI)) |
| fprintf(stderr, "*** missing functionality ***\n" |
fprintf(stderr, "*** missing functionality ***\n" |
| #ifndef HAVE_GETRUSAGE |
#ifndef HAVE_GETRUSAGE |
| " no getrusage -> CPUTIME broken\n" |
" no getrusage -> CPUTIME broken\n" |
| #endif |
#endif |
| #ifndef HAS_FFCALL |
#if !defined(HAS_FFCALL) && !defined(HAS_LIBFFI) |
| " no ffcall -> only old-style foreign function calls (no fflib.fs)\n" |
" no ffcall -> only old-style foreign function calls (no fflib.fs)\n" |
| #endif |
#endif |
| ); |
); |
| #ifdef HAS_OS |
#ifdef HAS_OS |
| gforth_args(argc, argv, &path, &imagename); |
gforth_args(argc, argv, &path, &imagename); |
| #ifndef NO_DYNAMIC |
#ifndef NO_DYNAMIC |
| if (no_dynamic && ss_cost == cost_codesize) { |
init_ss_cost(); |
| ss_cost = cost_nexts; |
|
| cost_sums[0] = cost_sums[1]; /* don't use cost_codesize for print-metrics */ |
|
| debugp(stderr, "--no-dynamic conflicts with --ss-min-codesize, reverting to --ss-min-nexts\n"); |
|
| } |
|
| #endif /* !defined(NO_DYNAMIC) */ |
#endif /* !defined(NO_DYNAMIC) */ |
| #endif /* defined(HAS_OS) */ |
#endif /* defined(HAS_OS) */ |
| |
|