123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- /* $Id$ */
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /*
- * L O C A L S . C
- */
- #include <stdio.h>
- #include <em_mnem.h>
- #include <em_spec.h>
- #include <em_pseu.h>
- #include <em_mes.h>
- #include "types.h"
- #include "debug.h"
- #include "global.h"
- #include "lset.h"
- #include "cset.h"
- #include "def.h"
- #include "get.h"
- #include "aux.h"
- #include "alloc.h"
- #include "locals.h"
- short nrglobals;
- short nrlocals;
- local_p *locals; /* dynamic array */
- static void localvar(offset off, short size, local_p *locs, bool reg, offset score)
- {
- /* process a reference to a local variable.
- * A local is characterized by a (offset,size) pair.
- * We first collect all locals in a list, sorted
- * by offset. Later we will construct a table
- * out of this list.
- */
- local_p lc, x, *prevp;
- prevp = locs;
- for (lc = *locs; lc != (local_p) 0; lc = lc->lc_next) {
- if (lc->lc_off == off && lc->lc_size == size) {
- if (reg) {
- REGVAR(lc); /* register variable */
- lc->lc_score = score;
- }
- return; /* local already present */
- }
- if (lc->lc_off > off) break;
- prevp = &lc->lc_next;
- }
- /* the local was not seen before; create an entry
- * for it in the list.
- */
- x = *prevp = newlocal();
- x->lc_off = off;
- x->lc_size = size;
- x->lc_next = lc;
- if (reg) {
- REGVAR(x);
- x->lc_score = score;
- }
- }
- static void check_message(line_p l, local_p *locs)
- {
- /* See if l is a register message */
- arg_p arg;
- arg = ARG(l);
- if (aoff(arg,0) == ms_reg && arg->a_next != (arg_p) 0) {
- localvar(aoff(arg,1), (short) aoff(arg,2), locs, TRUE,
- aoff(arg,4));
- }
- }
- static void check_local_use(line_p l, local_p *locs)
- {
- short sz;
- switch(INSTR(l)) {
- case op_lol:
- case op_stl:
- case op_inl:
- case op_del:
- case op_zrl:
- sz = ws;
- break;
- case op_ldl:
- case op_sdl:
- sz = 2 * ws;
- break;
- case op_lil:
- case op_sil:
- sz = ps;
- break;
- case ps_mes:
- check_message(l,locs);
- /* fall through .. */
- default:
- return;
- }
- if (l->l_next && INSTR(l->l_next) == op_nop) {
- /* volatile */
- return;
- }
- localvar(off_set(l),sz,locs,FALSE,(offset) 0);
- }
- void make_localtab(proc_p p)
- {
- /* Make a table of local variables.
- * This table is used to associate a
- * unique number with a local. If two
- * locals overlap (e.g. LDL 4 and LDL 2)
- * none of them is considered any further,
- * i.e. we don't compute ud-info for them.
- */
- local_p prev = 0, next, lc;
- local_p locallist = (local_p) 0;
- short cnt = 0;
- offset x, ill_zone = 0;
- bblock_p b;
- line_p l;
- /* first make a list of all locals used */
- for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
- for (l = b->b_start; l != (line_p) 0; l = l->l_next) {
- check_local_use(l,&locallist);
- }
- }
- /* Now remove overlapping locals, count useful ones on the fly */
- for (lc = locallist; lc != (local_p) 0; lc = lc->lc_next) {
- if (ill_zone != 0 && lc->lc_off < ill_zone) {
- /* this local overlaps with a previous one */
- BADLC(lc);
- if (!IS_BADLC(prev)) {
- BADLC(prev);
- cnt--;
- }
- } else {
- cnt++;
- }
- x = lc->lc_off + lc->lc_size;
- if (ill_zone == 0 || x > ill_zone) {
- ill_zone = x;
- }
- prev = lc;
- }
- /* Now we know how many local variables there are */
- nrlocals = cnt;
- locals = (local_p *) newmap(cnt);
- cnt = 1;
- for (lc = locallist; lc != (local_p) 0; lc = next) {
- next = lc->lc_next;
- if (IS_BADLC(lc)) {
- oldlocal(lc);
- } else {
- locals[cnt++] = lc;
- lc->lc_next = (local_p) 0;
- }
- }
- assert (cnt == nrlocals+1);
- }
- void find_local(offset off, short *nr_out, bool *found_out)
- {
- /* Try to find the local variable at the given
- * offset. Return its local-number.
- */
- short v;
- for (v = 1; v <= nrlocals; v++) {
- if (locals[v]->lc_off > off) break;
- if (locals[v]->lc_off == off) {
- *found_out = TRUE;
- *nr_out = v;
- return;
- }
- }
- *found_out = FALSE;
- }
- void var_nr(line_p l, short *nr_out, bool *found_out)
- {
- /* Determine the number of the variable referenced
- * by EM instruction l.
- */
- offset off = 0;
- short nr;
- switch(TYPE(l)) {
- case OPOBJECT:
- /* global variable */
- if (OBJ(l)->o_globnr == 0) {
- /* We don't maintain ud-info for this var */
- *found_out = FALSE;
- } else {
- *nr_out = GLOB_TO_VARNR(OBJ(l)->o_globnr);
- *found_out = TRUE;
- }
- return;
- case OPSHORT:
- off = (offset) SHORT(l);
- break;
- case OPOFFSET:
- off = OFFSET(l);
- break;
- default:
- assert(FALSE);
- }
- /* Its's a local variable */
- find_local(off,&nr,found_out);
- if (*found_out) {
- *nr_out = LOC_TO_VARNR(nr);
- }
- }
|