| 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_codesize=0; /* if true, print code size on exit */ |
static int print_codesize=0; /* if true, print code size on exit */ |
| |
static int static_super_number = 10000000; /* number of ss used if available */ |
| |
|
| #ifdef HAS_DEBUG |
#ifdef HAS_DEBUG |
| int debug=0; |
int debug=0; |
| void prepare_super_table() |
void prepare_super_table() |
| { |
{ |
| int i; |
int i; |
| |
int nsupers = 0; |
| |
|
| for (i=0; i<sizeof(super_costs)/sizeof(super_costs[0]); i++) { |
for (i=0; i<sizeof(super_costs)/sizeof(super_costs[0]); i++) { |
| struct cost *c = &super_costs[i]; |
struct cost *c = &super_costs[i]; |
| if (c->length > 1) { |
if (c->length > 1 && nsupers < static_super_number) { |
| int hash = hash_super(super2+c->offset, c->length); |
int hash = hash_super(super2+c->offset, c->length); |
| struct super_table_entry **p = &super_table[hash]; |
struct super_table_entry **p = &super_table[hash]; |
| struct super_table_entry *e = malloc(sizeof(struct super_table_entry)); |
struct super_table_entry *e = malloc(sizeof(struct super_table_entry)); |
| *p = e; |
*p = e; |
| if (c->length > max_super) |
if (c->length > max_super) |
| max_super = c->length; |
max_super = c->length; |
| |
nsupers++; |
| } |
} |
| } |
} |
| } |
if (debug) |
| |
fprintf(stderr, "Using %d static superinsts\n", nsupers); |
| int mycost(int prim) |
|
| { |
|
| return 1; |
|
| } |
} |
| |
|
| /* dynamic replication/superinstruction stuff */ |
/* dynamic replication/superinstruction stuff */ |
| #endif /* !defined(NO_DYNAMIC) */ |
#endif /* !defined(NO_DYNAMIC) */ |
| } |
} |
| |
|
| |
#ifndef NO_DYNAMIC |
| |
int cost_codesize(int prim) |
| |
{ |
| |
return priminfos[prim+DOESJUMP+1].length; |
| |
} |
| |
#endif |
| |
|
| |
int cost_ls(int prim) |
| |
{ |
| |
struct cost *c = super_costs+prim; |
| |
|
| |
return c->loads + c->stores; |
| |
} |
| |
|
| |
int cost_lsu(int prim) |
| |
{ |
| |
struct cost *c = super_costs+prim; |
| |
|
| |
return c->loads + c->stores + c->updates; |
| |
} |
| |
|
| |
int cost_nexts(int prim) |
| |
{ |
| |
return 1; |
| |
} |
| |
|
| |
typedef int Costfunc(int); |
| |
Costfunc *ss_cost = /* cost function for optimize_bb */ |
| |
#ifdef NO_DYNAMIC |
| |
cost_lsu; |
| |
#else |
| |
cost_codesize; |
| |
#endif |
| |
|
| #define MAX_BB 128 /* maximum number of instructions in BB */ |
#define MAX_BB 128 /* maximum number of instructions in BB */ |
| |
|
| /* use dynamic programming to find the shortest paths within the basic |
/* use dynamic programming to find the shortest paths within the basic |
| costs[ninsts]=0; |
costs[ninsts]=0; |
| for (i=ninsts-1; i>=0; i--) { |
for (i=ninsts-1; i>=0; i--) { |
| optimals[i] = origs[i]; |
optimals[i] = origs[i]; |
| costs[i] = costs[i+1] + mycost(optimals[i]); |
costs[i] = costs[i+1] + ss_cost(optimals[i]); |
| for (j=2; j<=max_super && i+j<=ninsts ; j++) { |
for (j=2; j<=max_super && i+j<=ninsts ; j++) { |
| int super, jcost; |
int super, jcost; |
| |
|
| super = lookup_super(origs+i,j); |
super = lookup_super(origs+i,j); |
| if (super >= 0) { |
if (super >= 0) { |
| jcost = costs[i+j] + mycost(super); |
jcost = costs[i+j] + ss_cost(super); |
| if (jcost <= costs[i]) { |
if (jcost <= costs[i]) { |
| optimals[i] = super; |
optimals[i] = super; |
| costs[i] = jcost; |
costs[i] = jcost; |
| nextdyn += super_costs[optimals[i]].length; |
nextdyn += super_costs[optimals[i]].length; |
| inst = compile_prim_dyn(optimals[i]); |
inst = compile_prim_dyn(optimals[i]); |
| } else { /* compile statically */ |
} else { /* compile statically */ |
| inst = vm_prims[optimals[i]+DOESJUMP+1]; |
inst = (Cell)vm_prims[optimals[i]+DOESJUMP+1]; |
| } |
} |
| *(instps[i]) = inst; |
*(instps[i]) = inst; |
| } |
} |
| return n*m; |
return n*m; |
| } |
} |
| |
|
| |
enum { |
| |
ss_number = 256, |
| |
ss_min_codesize, |
| |
ss_min_ls, |
| |
ss_min_lsu, |
| |
ss_min_nexts, |
| |
}; |
| |
|
| void gforth_args(int argc, char ** argv, char ** path, char ** imagename) |
void gforth_args(int argc, char ** argv, char ** path, char ** imagename) |
| { |
{ |
| int c; |
int c; |
| {"no-dynamic", no_argument, &no_dynamic, 1}, |
{"no-dynamic", no_argument, &no_dynamic, 1}, |
| {"dynamic", no_argument, &no_dynamic, 0}, |
{"dynamic", no_argument, &no_dynamic, 0}, |
| {"print-codesize", no_argument, &print_codesize, 1}, |
{"print-codesize", no_argument, &print_codesize, 1}, |
| |
{"ss-number", required_argument, NULL, ss_number}, |
| |
#ifndef NO_DYNAMIC |
| |
{"ss-min-codesize", no_argument, NULL, ss_min_codesize}, |
| |
#endif |
| |
{"ss-min-ls", no_argument, NULL, ss_min_ls}, |
| |
{"ss-min-lsu", no_argument, NULL, ss_min_lsu}, |
| |
{"ss-min-nexts", no_argument, NULL, ss_min_nexts}, |
| {0,0,0,0} |
{0,0,0,0} |
| /* no-init-file, no-rc? */ |
/* no-init-file, no-rc? */ |
| }; |
}; |
| case 's': die_on_signal = 1; break; |
case 's': die_on_signal = 1; break; |
| case 'x': debug = 1; break; |
case 'x': debug = 1; break; |
| case 'v': fputs(PACKAGE_STRING"\n", stderr); exit(0); |
case 'v': fputs(PACKAGE_STRING"\n", stderr); exit(0); |
| |
case ss_number: static_super_number = atoi(optarg); break; |
| |
#ifndef NO_DYNAMIC |
| |
case ss_min_codesize: ss_cost = cost_codesize; break; |
| |
#endif |
| |
case ss_min_ls: ss_cost = cost_ls; break; |
| |
case ss_min_lsu: ss_cost = cost_lsu; break; |
| |
case ss_min_nexts: ss_cost = cost_nexts; break; |
| case 'h': |
case 'h': |
| fprintf(stderr, "Usage: %s [engine options] ['--'] [image arguments]\n\ |
fprintf(stderr, "Usage: %s [engine options] ['--'] [image arguments]\n\ |
| Engine Options:\n\ |
Engine Options:\n\ |
| -p PATH, --path=PATH Search path for finding image and sources\n\ |
-p PATH, --path=PATH Search path for finding image and sources\n\ |
| --print-codesize Print size of generated native code on exit\n\ |
--print-codesize Print size of generated native code on exit\n\ |
| -r SIZE, --return-stack-size=SIZE Specify return stack size\n\ |
-r SIZE, --return-stack-size=SIZE Specify return stack size\n\ |
| |
--ss-number=N use N static superinsts (default max)\n |
| |
--ss-min-codesize select superinsts for smallest native code\n |
| |
--ss-min-ls minimize loads and stores\n |
| |
--ss-min-lsu minimize loads, stores, and pointer updates\n |
| |
--ss-min-nexts minimize the number of static superinsts\n |
| -v, --version Print engine version and exit\n\ |
-v, --version Print engine version and exit\n\ |
| SIZE arguments consist of an integer followed by a unit. The unit can be\n\ |
SIZE arguments consist of an integer followed by a unit. The unit can be\n\ |
| `b' (byte), `e' (element; default), `k' (KB), `M' (MB), `G' (GB) or `T' (TB).\n", |
`b' (byte), `e' (element; default), `k' (KB), `M' (MB), `G' (GB) or `T' (TB).\n", |
| |
|
| #ifdef HAS_OS |
#ifdef HAS_OS |
| gforth_args(argc, argv, &path, &imagename); |
gforth_args(argc, argv, &path, &imagename); |
| #endif |
#ifndef NO_DYNAMIC |
| |
if (no_dynamic && ss_cost == cost_codesize) { |
| |
ss_cost = cost_lsu; |
| |
if (debug) |
| |
fprintf(stderr, "--no-dynamic conflicts with --ss-min-codesize, reverting to --ss-min-lsu\n"); |
| |
} |
| |
#endif /* !defined(NO_DYNAMIC) */ |
| |
#endif /* defined(HAS_OS) */ |
| |
|
| #ifdef INCLUDE_IMAGE |
#ifdef INCLUDE_IMAGE |
| set_stack_sizes((ImageHeader *)image); |
set_stack_sizes((ImageHeader *)image); |