|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)local.c 1.5 (Berkeley) 1/9/87";
3: #endif
4:
5: # include "pass1.h"
6:
7: /* this file contains code which is dependent on the target machine */
8:
9: NODE *
10: clocal(p) register NODE *p; {
11:
12: /* this is called to do local transformations on
13: an expression tree preparitory to its being
14: written out in intermediate code.
15: */
16:
17: /* the major essential job is rewriting the
18: automatic variables and arguments in terms of
19: REG and OREG nodes */
20: /* conversion ops which are not necessary are also clobbered here */
21: /* in addition, any special features (such as rewriting
22: exclusive or) are easily handled here as well */
23:
24: register struct symtab *q;
25: register NODE *r;
26: register int o;
27: register int m, ml;
28:
29: switch( o = p->in.op ){
30:
31: case NAME:
32: if( p->tn.rval < 0 ) { /* already processed; ignore... */
33: return(p);
34: }
35: q = &stab[p->tn.rval];
36: switch( q->sclass ){
37:
38: case AUTO:
39: case PARAM:
40: /* fake up a structure reference */
41: r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
42: r->tn.lval = 0;
43: r->tn.rval = STKREG;
44: p = stref( block( STREF, r, p, 0, 0, 0 ) );
45: break;
46:
47: case ULABEL:
48: case LABEL:
49: case STATIC:
50: if( q->slevel == 0 ) break;
51: p->tn.lval = 0;
52: p->tn.rval = -q->offset;
53: break;
54:
55: case REGISTER:
56: p->in.op = REG;
57: p->tn.lval = 0;
58: p->tn.rval = q->offset;
59: #ifdef REG_CHAR
60: m = p->in.type;
61: if( m==CHAR || m==SHORT )
62: p->in.type = INT;
63: else if( m==UCHAR || m==USHORT )
64: p->in.type = UNSIGNED;
65: #endif
66: break;
67:
68: }
69: break;
70:
71: case LT:
72: case LE:
73: case GT:
74: case GE:
75: if( ISPTR( p->in.left->in.type ) || ISPTR( p->in.right->in.type ) ){
76: p->in.op += (ULT-LT);
77: }
78: break;
79:
80: case PCONV:
81: /* do pointer conversions for char and longs */
82: ml = p->in.left->in.type;
83: if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break;
84:
85: /* pointers all have the same representation; the type is inherited */
86:
87: inherit:
88: p->in.left->in.type = p->in.type;
89: p->in.left->fn.cdim = p->fn.cdim;
90: p->in.left->fn.csiz = p->fn.csiz;
91: p->in.op = FREE;
92: return( p->in.left );
93:
94: case SCONV:
95: m = p->in.type;
96: ml = p->in.left->in.type;
97: if(m == FLOAT || m == DOUBLE) {
98: if(p->in.left->in.op==SCONV &&
99: ml == DOUBLE &&
100: p->in.left->in.left->in.type==m) {
101: p->in.op = p->in.left->in.op = FREE;
102: return(p->in.left->in.left);
103: }
104: if(p->in.left->in.op==FCON)
105: goto inherit;
106: break;
107: }
108: if(ml == FLOAT || ml == DOUBLE){
109: if (p->in.left->in.op == FCON){
110: p->in.left->in.op = FREE;
111: p->in.op = ICON;
112: p->tn.lval = p->in.left->fpn.fval;
113: p->tn.rval = NONAME;
114: return(p);
115: }
116: break;
117: }
118: /* now, look for conversions downwards */
119:
120: if( p->in.left->in.op == ICON ){ /* simulate the conversion here */
121: CONSZ val;
122: val = p->in.left->tn.lval;
123: switch( m ){
124: case CHAR:
125: p->in.left->tn.lval = (char) val;
126: break;
127: case UCHAR:
128: p->in.left->tn.lval = val & 0XFF;
129: break;
130: case USHORT:
131: p->in.left->tn.lval = val & 0XFFFFL;
132: break;
133: case SHORT:
134: p->in.left->tn.lval = (short)val;
135: break;
136: case UNSIGNED:
137: p->in.left->tn.lval = val & 0xFFFFFFFFL;
138: break;
139: case INT:
140: p->in.left->tn.lval = (int)val;
141: break;
142: }
143: p->in.left->in.type = m;
144: } else if (tlen(p) == tlen(p->in.left))
145: goto inherit;
146: else
147: break;
148: /* clobber conversion */
149: p->in.op = FREE;
150: return( p->in.left ); /* conversion gets clobbered */
151: break;
152:
153: case QUEST: /* the right side should be COLON */
154: if((r = p->in.right)->in.op == SCONV) {
155: p->in.right = r->in.left;
156: p->in.type = r->in.left->in.type;
157: r->in.left = p;
158: return(r);
159: }
160: return(p);
161:
162: case PVCONV:
163: case PMCONV:
164: if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
165: p->in.op = FREE;
166: return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
167:
168: case FLD:
169: /* make sure that the second pass does not make the
170: descendant of a FLD operator into a doubly indexed OREG */
171:
172: if( p->in.left->in.op == UNARY MUL
173: && (r=p->in.left->in.left)->in.op == PCONV)
174: if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
175: if( ISPTR(r->in.type) ) {
176: if( ISUNSIGNED(p->in.left->in.type) )
177: p->in.left->in.type = UNSIGNED;
178: else
179: p->in.left->in.type = INT;
180: }
181: break;
182: case FORTCALL: /* arg must be FLOAT */
183: if((r = p->in.right)->in.type != FLOAT)
184: p->in.right = clocal(makety(r, FLOAT, 0, FLOAT));
185: return(p);
186: }
187:
188: /* if both sides are FLOAT, so is the op */
189: if(optype(o)!=LTYPE && p->in.left->in.type==DOUBLE &&
190: (o==UNARY MINUS || optype(o)==BITYPE && p->in.right->in.type==DOUBLE)) {
191: r = p->in.left;
192: if(r->in.op==SCONV && r->in.left->in.type==FLOAT) {
193: if(optype(o)==BITYPE) {
194: r = p->in.right;
195: if(r->in.op==SCONV && r->in.left->in.type==FLOAT) {
196: r->in.op = FREE;
197: p->in.right = r->in.left;
198: } else if(r->in.op==FCON)
199: r->in.type = FLOAT;
200: else
201: return(p);
202: }
203: r = p->in.left;
204: p->in.left = r->in.left;
205: } else if(optype(o)==BITYPE && r->in.op==FCON) {
206: r = p->in.right;
207: if(!(r->in.op==SCONV && r->in.left->in.type==FLOAT))
208: return(p);
209: p->in.right = r->in.left;
210: p->in.left->in.type = FLOAT;
211: } else
212: return(p);
213: if(p->in.type==DOUBLE) {
214: p->in.type = FLOAT;
215: r->in.left = p;
216: return(r);
217: } else { /* usually logop */
218: r->in.op = FREE;
219: return(p);
220: }
221: }
222: return(p);
223: }
224:
225: andable( p ) NODE *p; {
226: return(1); /* all names can have & taken on them */
227: }
228:
229: cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
230: autooff = AUTOINIT;
231: }
232:
233: cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
234:
235: if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */
236: #ifdef REG_CHAR
237: || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */
238: #endif
239: || ISPTR(t) || t == FLOAT) return (1); /* wnj */
240: return(0);
241: }
242:
243: NODE *
244: offcon( off, t, d, s ) OFFSZ off; TWORD t; {
245:
246: /* return a node, for structure references, which is suitable for
247: being added to a pointer of type t, in order to be off bits offset
248: into a structure */
249:
250: register NODE *p;
251:
252: /* t, d, and s are the type, dimension offset, and sizeoffset */
253: /* in general they are necessary for offcon, but not on H'well */
254:
255: p = bcon(0);
256: p->tn.lval = off/SZCHAR;
257: return(p);
258:
259: }
260:
261:
262: static inwd /* current bit offsed in word */;
263: static CONSZ word /* word being built from fields */;
264:
265: incode( p, sz ) register NODE *p; {
266:
267: /* generate initialization code for assigning a constant c
268: to a field of width sz */
269: /* we assume that the proper alignment has been obtained */
270: /* inoff is updated to have the proper final value */
271: /* we also assume sz < SZINT */
272:
273: inwd += sz;
274: if(inwd > SZINT) cerror("incode: field > int");
275: word |= (p->tn.lval&((1L<<sz)-1)) << (SZINT-inwd);
276: inoff += sz;
277: if(inoff%SZINT == 0) {
278: printf( " .long 0x%X\n", word);
279: word = inwd = 0;
280: }
281: }
282:
283: fincode( d, sz ) double d; register int sz; {
284: /*
285: * output code to initialize space of size sz to the value d
286: * the proper alignment has been obtained
287: * inoff is updated to have the proper final value.
288: */
289:
290: register struct sh4 {
291: unsigned short sh[4];
292: } *x;
293: float f;
294:
295: if(sz == SZFLOAT) { /* force rounding */
296: f = d;
297: d = f;
298: }
299:
300: x = (struct sh4 *)&d;
301: printf(" .long 0x%04x%04x", x->sh[0], x->sh[1]);
302: if(sz == SZDOUBLE) {
303: printf(", 0x%04x%04x", x->sh[2], x->sh[3]);
304: printf(" # .double %.17g\n", d);
305: } else
306: printf(" # .float %.8g\n", d);
307: inoff += sz;
308: }
309:
310: cinit( p, sz ) NODE *p; {
311: NODE *l;
312:
313: /*
314: * as a favor (?) to people who want to write
315: * int i = 9600/134.5;
316: * we will, under the proper circumstances, do
317: * a coersion here.
318: */
319: switch (p->in.type) {
320: case INT:
321: case UNSIGNED:
322: l = p->in.left;
323: if (l->in.op != SCONV ||
324: (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
325: break;
326: l->in.op = FREE;
327: l = l->in.left;
328: l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
329: (long)(l->fpn.fval);
330: l->tn.rval = NONAME;
331: l->tn.op = ICON;
332: l->tn.type = INT;
333: p->in.left = l;
334: break;
335: }
336: /* arrange for the initialization of p into a space of
337: size sz */
338: /* the proper alignment has been opbtained */
339: /* inoff is updated to have the proper final value */
340: ecode( p );
341: inoff += sz;
342: }
343:
344: vfdzero( n ){ /* define n bits of zeros in a vfd */
345:
346: if( n <= 0 ) return;
347:
348: inwd += n;
349: inoff += n;
350: if( inoff%ALINT ==0 ) {
351: printf( " .long 0x%X\n", word );
352: word = inwd = 0;
353: }
354: }
355:
356: char *
357: exname( p ) char *p; {
358: /* make a name look like an external name in the local machine */
359:
360: #ifndef FLEXNAMES
361: static char text[NCHNAM+1];
362: #else
363: static char text[BUFSIZ+1];
364: #endif
365:
366: register int i;
367:
368: text[0] = '_';
369: #ifndef FLEXNAMES
370: for( i=1; *p&&i<NCHNAM; ++i )
371: #else
372: for( i=1; *p; ++i )
373: #endif
374: text[i] = *p++;
375:
376: text[i] = '\0';
377: #ifndef FLEXNAMES
378: text[NCHNAM] = '\0'; /* truncate */
379: #endif
380:
381: return( text );
382: }
383:
384: ctype( type )TWORD type;{ /* map types which are not defined on the local machine */
385: switch( BTYPE(type) ){
386:
387: case LONG:
388: MODTYPE(type,INT);
389: break;
390:
391: case ULONG:
392: MODTYPE(type,UNSIGNED);
393: }
394: return( type );
395: }
396:
397: noinit() { /* curid is a variable which is defined but
398: is not initialized (and not a function );
399: This routine returns the stroage class for an uninitialized declaration */
400:
401: return(EXTERN);
402:
403: }
404:
405: commdec( id ){ /* make a common declaration for id, if reasonable */
406: register struct symtab *q;
407: OFFSZ off, tsize();
408:
409: q = &stab[id];
410: printf( " .comm %s,", exname( q->sname ) );
411: off = tsize( q->stype, q->dimoff, q->sizoff );
412: printf( "%d\n" /*CONFMT*/, off/SZCHAR );
413: }
414:
415: prtdcon(p)
416: register NODE *p;
417: {
418: register int o = p->in.op;
419: int i;
420:
421: if (o != DCON && o != FCON)
422: return;
423: /*
424: * Clobber constants of value zero so
425: * we can generate more efficient code.
426: */
427: if ((o == DCON && p->dpn.dval == 0) ||
428: (o == FCON && p->fpn.fval == 0)) {
429: p->in.op = ICON;
430: p->tn.rval = NONAME;
431: return;
432: }
433: locctr(DATA);
434: defalign(o == DCON ? ALDOUBLE : ALFLOAT);
435: deflab(i = getlab());
436: if (o == FCON)
437: fincode(p->fpn.fval, SZFLOAT);
438: else
439: fincode(p->dpn.dval, SZDOUBLE);
440: p->tn.lval = 0;
441: p->tn.rval = -i;
442: p->in.type = (o == DCON ? DOUBLE : FLOAT);
443: p->in.op = NAME;
444: }
445:
446: isitfloat( s ) char *s; {
447: union cvt {
448: double d;
449: int n[2];
450: } cvt;
451: double atof();
452:
453: /* avoid floating point exception for double -> float conversions */
454: dcon = cvt.d = atof(s);
455: if( cvt.n[1] == 0 ){
456: fcon = dcon;
457: return( FCON );
458: }
459: return( DCON );
460: }
461:
462: ecode( p ) NODE *p; {
463:
464: /* walk the tree and write out the nodes.. */
465:
466: if( nerrors ) return;
467: p2tree( p );
468: p2compile( p );
469: }
470:
471: #ifndef ONEPASS
472: tlen(p) NODE *p;
473: {
474: switch(p->in.type) {
475: case CHAR:
476: case UCHAR:
477: return(1);
478:
479: case SHORT:
480: case USHORT:
481: return(2);
482:
483: case DOUBLE:
484: return(8);
485:
486: default:
487: return(4);
488: }
489: }
490: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.