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