home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- */
- #include "top.h"
-
- BLOCK *fhead; /* head of the current function */
-
- /*
- * dofunc() - process one function
- *
- * Returns FALSE on end of file
- */
- bool
- dofunc()
- {
- BLOCK *getfunc();
-
- clrvar();
-
- #ifdef DEBUG
- if (debug)
- fprintf(stderr, "dofunc() - calling getfunc()\n");
- #endif
- if ((fhead = getfunc()) == NULL)
- return FALSE;
-
- /*
- * Process the function we just read
- */
- bopt(fhead); /* perform branch optimization */
-
- if (do_regs)
- setreg(fhead); /* try to assign locals to registers */
-
- if (do_peep) {
- rhealth(fhead, TRUE); /* live/dead register analysis */
- peep(fhead); /* peephole optimizations */
- }
-
- /*
- * Now dump out the modified tree
- */
- #ifdef DEBUG
- if (debug)
- fprintf(stderr, "dofunc() - calling putfunc()\n");
- #endif
- putfunc(fhead);
-
- freesym(); /* free the symbol table */
-
- return TRUE;
- }
-
- static bool saw_eof = FALSE;
-
- /*
- * getfunc() - get a function and return a pointer to its starting block
- *
- * Returns NULL on end of file.
- */
- BLOCK *
- getfunc()
- {
- register BLOCK *head; /* starting block for this function */
- register BLOCK *cb; /* the block we're currently reading */
- register BLOCK *ob; /* the last block we read */
-
- if (saw_eof)
- return NULL;
-
- head = NULL;
-
- /*
- * Starting a global function
- */
- if (strcmp(t_op, ".globl") == 0) {
- /*
- * Enter the symbol and mark it global.
- */
- head = mksym(t_arg);
- head->flags |= B_GLOBAL;
-
- readline();
- }
-
- ob = NULL;
-
- for (;;) {
- if (ob == NULL) {
- if (t_lab[0] != '_') {
- fprintf(stderr, "top: expected function label\n");
- exit(1);
- }
- if (head == NULL)
- head = mksym(t_lab);
-
- } else if (t_lab[0] == '\0') {
- fprintf(stderr, "top: expected block label\n");
- exit(1);
- }
-
- if ((cb = getsym(t_lab)) == NULL)
- cb = mksym(t_lab);
-
- /*
- * The last block falls through to this one.
- */
- if (ob != NULL) {
- ob->chain = cb;
- ob->next = cb;
- ob->bfall = cb;
- }
-
- t_lab[0] = '\0';
-
- /*
- * Now read lines until we hit a new block or another
- * function.
- */
- for (;;) {
- /*
- * If we see a global, we're done with the function
- */
- if (strcmp(t_op, ".globl") == 0)
- return head;
- /*
- * If we see a function label, we're done too.
- */
- if (t_lab[0] == '_')
- return head;
- /*
- * If we see any other label, we're done with the block.
- */
- if (t_lab[0])
- break;
-
- addinst(cb, t_op, t_arg);
-
- /*
- * If we're at EOF, note that we've hit the end of
- * file, but return the function we just read.
- */
- if (!readline()) {
- saw_eof = TRUE;
- return head;
- }
- }
- ob = cb;
- }
- }
-
- /*
- * putfunc(sb) - print out the function starting at block 'sb'
- *
- * The 'next' pointers determine the order in which things are placed
- * in the file. Branch instructions have been removed so they need to
- * be replaced here on output. Conditional branches are generated if
- * indicated (by non-null 'bcond'). Unconditional branches are generated
- * at the end of a block if it's "fall through" block isn't going to
- * be the next thing in the file.
- */
- putfunc(sb)
- register BLOCK *sb;
- {
- register BLOCK *cb;
- register INST *ci;
-
- fprintf(ofp, "\t.text\n");
-
- for (cb = sb; cb != NULL ;cb = cb->next) {
- if (cb->flags & B_GLOBAL)
- fprintf(ofp, "\t.globl\t%s\n", cb->name);
-
- if (*cb->name == '_')
- fprintf(ofp, "%s:\n", cb->name);
-
- else if (cb->flags & B_LABEL)
- fprintf(ofp, "%s:\n", cb->name);
- #ifdef DEBUG
- if (debug) {
- fprintf(ofp, "*\n");
- fprintf(ofp, "* %s, ref:%04x set:%04x\n",
- cb->name, cb->rref, cb->rset);
- fprintf(ofp, "*\n");
- }
- #endif
-
- for (ci = cb->first; ci != NULL ;ci = ci->next)
- putinst(ci);
- /*
- * If there's a conditional branch, put out the
- * appropriate instruction for it.
- */
- if (cb->bcond != NULL && cb->bcode >= 0)
- fprintf(ofp, "\t%s\t%s\n",
- opnames[cb->bcode], cb->bcond->name);
- /*
- * If there's a "fall through" label, and the destination
- * block doesn't come next, put out a branch.
- */
- if (cb->bfall != NULL && cb->bfall != cb->next) {
- s_badd++;
- fprintf(ofp, "\tbra\t%s\n", cb->bfall->name);
- }
- }
- }
-