File:  [gforth] / gforth / engine / cgen.c
Revision 1.1: download - view: text, annotated - select for diffs
Sun Sep 19 20:49:12 2010 UTC (13 years, 7 months ago) by anton
Branches: MAIN
CVS tags: HEAD
work on C-code generation

    1: /* C-code generation for Gforth
    2: 
    3:   Copyright (C) 2010 Free Software Foundation, Inc.
    4: 
    5:   This file is part of Gforth.
    6: 
    7:   Gforth is free software; you can redistribute it and/or
    8:   modify it under the terms of the GNU General Public License
    9:   as published by the Free Software Foundation, either version 3
   10:   of the License, or (at your option) any later version.
   11: 
   12:   This program is distributed in the hope that it will be useful,
   13:   but WITHOUT ANY WARRANTY; without even the implied warranty of
   14:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15:   GNU General Public License for more details.
   16: 
   17:   You should have received a copy of the GNU General Public License
   18:   along with this program; if not, see http://www.gnu.org/licenses/.
   19: */
   20: 
   21: #include "config.h"
   22: #include "forth.h"
   23: 
   24: /* Assumptions: 
   25: 
   26:    1) the function corresponding to (the first BB in) a
   27:    colon def is stored in the 2nd cell of the code field.
   28: 
   29:    2) the function corresponding to (the first BB of) a does-handler
   30:    is stored in the second cell of the code field.
   31: 
   32: */
   33: 
   34: /* run-time system */
   35: 
   36: 
   37: 
   38: 
   39: /* defined types: 
   40:    bb: basic block (or other unit fitting in C function;
   41:    doer: docol etc. called from execute
   42: */
   43: 
   44: typedef void *(*Bb)();
   45: typedef Bb (*Doer)(Bb,Cell *);
   46: typedef void (*Gen)();
   47: 
   48: Cell translate_link(Cell *);
   49: 
   50: void control_loop(Bb next)
   51: {
   52:   for (;;)
   53:     next = next();
   54: }
   55: 
   56: /* Doers */
   57: 
   58: Bb docol(Bb next, Cell *cfa)
   59: {
   60:   *--gforth_RP = (Cell)next;
   61:   return (Bb)cfa[1];
   62: }
   63: 
   64: void translate_link_colon_def(Cell *cfa)
   65: {
   66:   cfa[1] = translate_link(PFA(cfa));
   67:   cfa[0] = (Cell)docol;
   68: }
   69: 
   70: Bb docol0(Bb next, Cell *cfa)
   71: /* first invocation: compile on demand */
   72: {
   73:   translate_link_colon_def(cfa);
   74:   return docol(next, cfa);
   75: }
   76: 
   77: Bb docon(Bb next, Cell *cfa)
   78: {
   79:   *--gforth_SP = *PFA(cfa);
   80:   return next;
   81: }
   82: 
   83: Bb dovar(Bb next, Cell *cfa)
   84: {
   85:   *--gforth_SP = (Cell)PFA(cfa);
   86:   return next;
   87: }
   88: 
   89: Bb douser(Bb next, Cell *cfa)
   90: {
   91:   *--gforth_SP = (Cell)(gforth_UP + *(Cell *)PFA(cfa));
   92:   return next;
   93: }
   94: 
   95: Bb dodefer(Bb next, Cell *cfa)
   96: {
   97:   Cell *next_cfa = (Cell *)*PFA(cfa);
   98:   Doer next_doer = *(Doer *)next_cfa;
   99:   return next_doer(next, next_cfa);
  100: }
  101: 
  102: Bb dofield(Bb next, Cell *cfa)
  103: {
  104:   *gforth_SP += *PFA(cfa);
  105:   return next;
  106: }
  107: 
  108: Bb dovalue(Bb next, Cell *cfa)
  109: {
  110:   *--gforth_SP = *PFA(cfa);
  111:   return next;
  112: }
  113: 
  114: Bb dodoes(Bb next, Cell *cfa)
  115: {
  116:   *--gforth_RP = (Cell)next;
  117:   *--gforth_SP = (Cell)PFA(cfa);
  118:   return (Bb)cfa[1];
  119: }
  120: 
  121: void translate_link_does_handler(Cell *cfa)
  122: {
  123:   cfa[1] = translate_link((Cell *)cfa[1]);
  124:   cfa[0] = (Cell)dodoes;
  125: }
  126: 
  127: Bb dodoes0(Bb next, Cell *cfa)
  128: {
  129:   translate_link_does_handler(cfa);
  130:   return dodoes(next,cfa);
  131: }
  132: 
  133: Bb doabicode(Bb next, Cell *cfa)
  134: {
  135:   abifunc *f = (abifunc *)PFA(cfa);
  136:   gforth_SP = (*f)(gforth_SP, &gforth_FP);
  137:   return next;
  138: }
  139: 
  140: Bb dosemiabicode(Bb next, Cell *cfa)
  141: {
  142:   Address body = (Address)PFA(cfa);
  143:   semiabifunc *f = (semiabifunc *)DOES_CODE1(cfa);
  144:   gforth_SP = (*f)(gforth_SP, &gforth_FP, body);
  145:   return next;
  146: }
  147: 
  148: Bb cgen_symbols[] = {
  149:   docol0,
  150:   docon,
  151:   dovar,
  152:   douser,
  153:   dodefer,
  154:   dofield,
  155:   dovalue,
  156:   dodoes0,
  157:   doabicode,
  158:   dosemiabicode
  159: };
  160: /* !! actually we need all the primitives for the code fields as well.
  161:    Generate them?
  162:  */
  163:   
  164: /* Translator */
  165: 
  166: /* primitive descriptions (static) */
  167: typedef struct stack_effect {
  168:   char in;   /* stack items on input */
  169:   char out;  /* stack items on output */
  170:   char dump; /* if true, dump this stack (apart from in, out) to memory */
  171: } Stackeffect;
  172: 
  173: typedef struct prim {
  174:   Stackeffect se[MAX_STACKS];
  175:   Gen  gen;
  176:   char end_bb;
  177: } Prim;
  178: 
  179: Prim prims[] = {
  180: };
  181: 
  182: typedef struct stackpoint {
  183:   signed char depth;  /* current depth (relative to starting depth) */
  184:   char loaded_start;  /* from which depth the loading starts */
  185:   char loaded; /* how many stack items have been loaded from start to here */
  186:   char stored; /* how many stack items will be stored from here to end */
  187:   char new;    /* how many new stack items were accesses from start to here */
  188:   char old;    /* how many existing stack items were accessed */
  189: } Stackpoint;
  190: 
  191: typedef struct codepoint {
  192:   Cell *tc;
  193:   StackPoint stack[MAX_STACKS];
  194: } Codepoint;
  195: 
  196: 
  197: void forward_pass(Cell *tc, Codepoint *p, int n)
  198: {
  199:   for (j=0; j<MAX_STACKS; j++) {
  200:     Stackpoint *sp = p[0].stack;
  201:     sp->depth        = 0;
  202:     sp->loaded       = 0;
  203:     sp->loaded_start = 0;
  204:     sp->new          = 0;
  205:   }
  206:   for (i=0; i<n; i++) {
  207:     for (j=0; j<MAX_STACKS; j++) {
  208:       Stackpoint *b = p[i].stack+j; /* before */
  209:       Stackpoint *a = p[i].stack+j; /* after */
  210:       Stackeffect *s = p[PRIM_NUM(*tc)].se+j;
  211:       int depth = b->depth - s.in;
  212:       if (depth<b->old)
  213: 	a->old=depth;
  214:       if (s->dump) {
  215: 	a->loaded = 0;
  216: 	a->loaded_start = depth;
  217:       } else {
  218: 	a->loaded = min(depth,b->loaded);
  219: 	a->loaded_start = min(depth,b->loaded_start);
  220:       }
  221:       depth += s.out;
  222:       a->new = max(b->new, depth);
  223:       a->depth = depth;
  224:     }
  225:   }
  226: }
  227: 
  228: 
  229: 
  230: char *cgen(Cell *tc)
  231: {
  232:   int n = npoints(tc);
  233:   Codepoint p[n+1];
  234: 
  235:   forward_pass(tc,p,n);
  236:   backwards_pass(tc,p,n);
  237:   decl_stack_items(p,n);
  238:   gen_prims(p);
  239: }
  240: 
  241: 
  242: 
  243: 
  244: Cell translate_link(Cell *bb_tc)
  245: {
  246:   Bb bbfunc = lookup_bb(bb_tc);
  247: 
  248:   if (bbfunc == NULL) {
  249:     char *filename_c  = cgen(bb_tc);
  250:     char *filename_la = compile(filename_tc);
  251:     lt_dlhandle lib = lt_dlopen(filename_la);
  252:     bb_func = lt_dlsym(symbol(bb_tc));
  253:   }
  254:   return (Cell) bb_func;
  255: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>