|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)label.c 1.1 86/02/03 Copyr 1983 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1983 by Sun Microsystems, Inc.
7: */
8:
9: #include "as.h"
10: #include "c2.h"
11:
12: /* for local labels: ``[0-9]:'', and references ``[0-9][bh]'' */
13: extern char *ll_format;
14: int ll_val[10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
15:
16:
17: /* handle definition of label */
18: slabel(t)
19: char * t;
20: {
21: register char *token = t;
22: register char *p;
23: register NODE *np;
24: struct sym_bkt *sbp;
25: char nextc;
26: static char ltoken[20];
27:
28: /* make asciz version of label */
29: p = token;
30: while (cinfo[*p] & T) p++;
31: nextc = *p; /* may be a , a + a \n ... */
32: *p = '\0';
33:
34: /* look for numeric-only labels, as opposed to numeric-$ labels */
35: if ( (p == token+1) && (cinfo[token[0]]&D)){
36: sprintf( ltoken, ll_format, token[0], ++ll_val[token[0]-'0'] );
37: token=ltoken;
38: }
39:
40: /* find/enter symbol in the symbol table */
41: sbp = lookup(token);
42:
43: /* on pass 1 look for multiply defined symbols. if ok, label
44: value is dot in current csect
45: */
46: # ifdef EBUG
47: if (debflag)
48: printf("Label %s, line %d offset 0x%X\n",sbp->name_s,line_no,dot);
49: # endif
50: if (sbp->attr_s & (S_LABEL|S_REG)) {
51: prog_error(E_MULTSYM);
52: }
53: sbp->attr_s |= S_LABEL | S_DEC | S_DEF;
54: sbp->csect_s = cur_csect_name;
55: sbp->value_s = dot;
56:
57: if (!(cinfo[t[0]] & D))
58: last_symbol = sbp;
59:
60: #if C2
61: if (cur_csect_name == C_TEXT){
62: /* make label node */
63: np = new();
64: np->op = OP_LABEL;
65: np->name = sbp;
66: sbp->where_s = np;
67: addnode(np);
68: } else {
69: /* print directly */
70: printf("%s:\n", token);
71: }
72: #endif
73:
74: *p = nextc; /* replace next character before proceeding */
75: } /* end slabel */
76:
77: void
78: newreference( l, r )
79: NODE *l, *r;
80: {
81: /*
82: * l is a label node.
83: * r is a jump node that should be made to reference it.
84: * r has already been unreferenced from wherever it pointed before.
85: */
86: r->lnext = l->luse;
87: r->luse=l;
88: l->luse=r;
89: l->nref++;
90: }
91:
92: void
93: unreference( l, r )
94: NODE *l, *r;
95: {
96: /*
97: * r is a jump that references node l.
98: * unhook r from l's use chain, and decrement l's reference count.
99: */
100: register NODE **up;
101:
102: if (l == NULL) {
103: if (r->op == OP_EXIT)
104: return;
105: sys_error("no label to unreference, op = 0x%x", r->op);
106: }
107: up = & l->luse;
108:
109: while( *up ){
110: if ( *up == r ){
111: *up = r->lnext;
112: l->nref--;
113: return;
114: }
115: up = & (*up)->lnext;
116: }
117: sys_error( "tangled usage list for label %s\n", l->name->name_s );
118: }
119:
120: relabel(){
121: /*
122: * find all unreferenced labels and delete them.
123: * find all instances (in .text) of multiple labels in a row
124: * and collapse them into one label. The difficulty here is
125: * the case where we cannot find all references to one of the labels
126: * for instance, where a reference is in a switch list, so must treat
127: * that one very carefully.
128: */
129: register NODE * n, *lastlabel;
130: register NODE *labelref;
131: NODE * nextlabel;
132: int nchanged, nuses;
133: char labelmoved;
134:
135: nchanged = 0;
136: for (n=first.forw ; n != &first; n = n->forw){
137: if (n->op != OP_LABEL) continue;
138: labelmoved = 0;
139: lastlabel = n;
140: /* find the last label of this group of labels */
141: while (lastlabel->forw->op == OP_LABEL)
142: lastlabel = lastlabel->forw;
143: while (n != lastlabel){
144: /*
145: * for all labels but the last, retarget all references
146: * to that last one.
147: */
148: if (n->nref){
149: if ( labelref = n->luse ){
150: nuses = 1;
151: while (labelref->lnext){
152: labelref=labelref->lnext;
153: nuses++;
154: }
155: } else {
156: nuses = 0;
157: }
158: /*
159: * if we couldn't find all the references, we must
160: * leave this label in place, so it can be referenced.
161: * It would be nice to emit an equate statement between
162: * this label and the one we plan on keeping, but the assembler
163: * cannot handle such a reference, so we cannot do it.
164: * try to make this label the "last" one, if this hasn't
165: * already been done.
166: */
167: if (nuses != n->nref){
168: nextlabel = n->forw;
169: n->back->forw = n->forw;
170: n->forw->back = n->back;
171: n->back = lastlabel;
172: n->forw = lastlabel->forw;
173: lastlabel->forw->back = n;
174: lastlabel->forw = n;
175: if (!labelmoved){
176: lastlabel = n;
177: labelmoved++;
178: }
179: n = nextlabel;
180: continue;
181: }
182: /*
183: * we have a chain of references to this label.
184: * n->luse addresses the first use, labelref addresses
185: * the last use. add this to lastlabel's reference chain.
186: */
187: if (labelref){
188: labelref->lnext = lastlabel->luse;
189: lastlabel->luse = n->luse;
190: lastlabel->nref+= nuses;
191: for (labelref=n->luse; labelref != 0; labelref=labelref->lnext){
192: labelref->luse = lastlabel;
193: }
194: }
195: }
196: /* this label is now useless */
197: n = deletenode( n );
198: meter.nrlab++;
199: nchanged++;
200: n=n->forw;
201: }
202: /* we are now looking at the last label in a bunch delete it if unreferenced */
203: if (lastlabel->nref==0){
204: n = deletenode( lastlabel );
205: meter.nrlab++;
206: nchanged++;
207: }
208: }
209: return nchanged;
210: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.