Research V7 development
[unix-history] / usr / src / cmd / pcc / local.c
CommitLineData
3c5d933b
SJ
1# include "mfile1"
2
3
4/* this file contains code which is dependent on the target machine */
5
6NODE *
7cast( p, t ) register NODE *p; TWORD t; {
8 /* cast node p to type t */
9
10 p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p );
11 p->left->op = FREE;
12 p->op = FREE;
13 return( p->right );
14 }
15
16NODE *
17clocal(p) NODE *p; {
18
19 /* this is called to do local transformations on
20 an expression tree preparitory to its being
21 written out in intermediate code.
22 */
23
24 /* the major essential job is rewriting the
25 automatic variables and arguments in terms of
26 REG and OREG nodes */
27 /* conversion ops which are not necessary are also clobbered here */
28 /* in addition, any special features (such as rewriting
29 exclusive or) are easily handled here as well */
30
31 register struct symtab *q;
32 register NODE *r;
33 register o;
34 register m, ml;
35
36 switch( o = p->op ){
37
38 case NAME:
39 if( p->rval < 0 ) { /* already processed; ignore... */
40 return(p);
41 }
42 q = &stab[p->rval];
43 switch( q->sclass ){
44
45 case AUTO:
46 case PARAM:
47 /* fake up a structure reference */
48 r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
49 r->lval = 0;
50 r->rval = (q->sclass==AUTO?STKREG:ARGREG);
51 p = stref( block( STREF, r, p, 0, 0, 0 ) );
52 break;
53
54 case ULABEL:
55 case LABEL:
56 case STATIC:
57 if( q->slevel == 0 ) break;
58 p->lval = 0;
59 p->rval = -q->offset;
60 break;
61
62 case REGISTER:
63 p->op = REG;
64 p->lval = 0;
65 p->rval = q->offset;
66 break;
67
68 }
69 break;
70 case LT:
71 case LE:
72 case GT:
73 case GE:
74 if( ISPTR( p->left->type ) || ISPTR( p->right->type ) ){
75 p->op += (ULT-LT);
76 }
77 break;
78
79 case PCONV:
80 /* do pointer conversions for char and longs */
81 ml = p->left->type;
82 if( ( ml==CHAR || ml==UCHAR || ml==LONG || ml==ULONG ) && p->left->op != ICON ) break;
83
84 /* pointers all have the same representation; the type is inherited */
85 p->left->type = p->type;
86 p->left->cdim = p->cdim;
87 p->left->csiz = p->csiz;
88 p->op = FREE;
89 return( p->left );
90
91 case SCONV:
92 m = (p->type == FLOAT || p->type == DOUBLE );
93 ml = (p->left->type == FLOAT || p->left->type == DOUBLE );
94 if( m != ml ) break;
95
96 /* now, look for conversions downwards */
97
98 m = p->type;
99 ml = p->left->type;
100 if( p->left->op == ICON ){ /* simulate the conversion here */
101 CONSZ val;
102 val = p->left->lval;
103 switch( m ){
104 case CHAR:
105 p->left->lval = (char) val;
106 break;
107 case UCHAR:
108 p->left->lval = val & 0XFF;
109 break;
110 case UNSIGNED:
111 p->left->lval = val & 0XFFFFL;
112 break;
113 case INT:
114 p->left->lval = (int)val;
115 break;
116 }
117 p->left->type = m;
118 }
119 else {
120 /* meaningful ones are conversion of int to char, int to short,
121 and short to char, and unsigned version of them */
122 if( m==CHAR || m==UCHAR ){
123 if( ml==LONG || ml==ULONG ) break;
124 }
125 else if( m==INT || m==UNSIGNED ){
126 if( ml==LONG || ml==ULONG ) break;
127 }
128 else if( m==LONG || m==ULONG ){
129 if( ml!=LONG && ml!= ULONG ) break;
130 }
131 }
132
133 /* clobber conversion */
134 p->op = FREE;
135 return( p->left ); /* conversion gets clobbered */
136
137 case ASSIGN:
138 /* get rid of SCONV for assignments
139 from LONG -> CHAR|INT */
140 if( p->right->op == SCONV ) {
141 m = p->right->type;
142 ml = p->right->left->type;
143 if( ( m==LONG || m==ULONG ) &&
144 ml!=FLOAT && ml!=DOUBLE ) {
145 p->right->op = FREE;
146 p->right = p->right->left;
147 }
148 }
149 break;
150
151 case PVCONV:
152 case PMCONV:
153 if( p->right->op != ICON ) cerror( "bad conversion", 0);
154 p->op = FREE;
155 return( buildtree( o==PMCONV?MUL:DIV, p->left, p->right ) );
156
157 case PLUS:
158 case MINUS:
159 case LS:
160 case MUL:
161 /* optimize address calculations with long indexes */
162 if( ISPTR( p->type ) || ISARY( p->type ) ) {
163 if( p->left->type==LONG || p->left->type==ULONG )
164 p->left = cast( p->left, INT );
165 if( p->right->type==LONG || p->right->type==ULONG )
166 p->right = cast( p->right, INT );
167 }
168 break;
169
170 }
171
172 return(p);
173 }
174
175andable( p ) NODE *p; {
176 return(1); /* all names can have & taken on them */
177 }
178
179cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
180 autooff = AUTOINIT;
181 }
182
183cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
184
185 if( t==INT || t==UNSIGNED || ISPTR(t) ) return(1);
186 return(0);
187 }
188
189NODE *
190offcon( off, t, d, s ) OFFSZ off; TWORD t; {
191
192 /* return a node, for structure references, which is suitable for
193 being added to a pointer of type t, in order to be off bits offset
194 into a structure */
195
196 register NODE *p;
197
198 /* t, d, and s are the type, dimension offset, and sizeoffset */
199 /* in general they are necessary for offcon, but not on H'well */
200
201 p = bcon(0);
202 p->lval = off/SZCHAR;
203 return(p);
204
205 }
206
207static inwd /* current bit offsed in word */;
208static word /* word being built from fields */;
209
210incode( p, sz ) register NODE *p; {
211
212 /* generate initialization code for assigning a constant c
213 to a field of width sz */
214 /* we assume that the proper alignment has been obtained */
215 /* inoff is updated to have the proper final value */
216 /* we also assume sz < SZINT */
217
218 if((sz+inwd) > SZINT) cerror("incode: field > int");
219 word |= p->lval<<inwd;
220 inwd += sz;
221 inoff += sz;
222 if(inoff%SZINT == 0) {
223 printf( " %o\n", word);
224 word = inwd = 0;
225 }
226 }
227
228fincode( d, sz ) double d; {
229 /* output code to initialize space of size sz to the value d */
230 /* the proper alignment has been obtained */
231 /* inoff is updated to have the proper final value */
232 /* on the target machine, write it out in octal! */
233
234 register int *mi = (int *)&d;
235
236 if( sz==SZDOUBLE )
237 printf( " %o; %o; %o; %o\n", mi[0], mi[1], mi[2], mi[3] );
238 else
239 printf( " %o; %o\n", mi[0], mi[1] );
240 inoff += sz;
241 }
242
243cinit( p, sz ) NODE *p; {
244 /* arrange for the initialization of p into a space of
245 size sz */
246 /* the proper alignment has been opbtained */
247 /* inoff is updated to have the proper final value */
248 ecode( p );
249 inoff += sz;
250 }
251
252vfdzero( n ){ /* define n bits of zeros in a vfd */
253
254 if( n <= 0 ) return;
255
256 inwd += n;
257 inoff += n;
258 if( inoff%ALINT ==0 ) {
259 printf( " %o\n", word );
260 word = inwd = 0;
261 }
262 }
263
264
265char *
266exname( p ) char *p; {
267 /* make a name look like an external name in the local machine */
268
269 static char text[NCHNAM+1];
270
271 register i;
272
273 text[0] = '_';
274 for( i=1; *p&&i<NCHNAM; ++i ){
275 text[i] = *p++;
276 }
277
278 text[i] = '\0';
279 text[NCHNAM] = '\0'; /* truncate */
280
281 return( text );
282 }
283
284ctype( type ) TWORD type; { /* map types which are not defined on the local machine */
285 switch( BTYPE(type) ){
286 case SHORT:
287 MODTYPE(type,INT);
288 break;
289 case USHORT:
290 MODTYPE(type,UNSIGNED);
291 }
292 return( type );
293 }
294
295noinit() { /* curid is a variable which is defined but
296 is not initialized (and not a function );
297 This routine returns the stroage class for an uninitialized declaration */
298
299 return(EXTERN);
300
301 }
302
303commdec( id ){ /* make a common declaration for id, if reasonable */
304 register struct symtab *q;
305 OFFSZ off;
306
307 q = &stab[id];
308 printf( " .comm %s,", exname( q->sname ) );
309 off = tsize( q->stype, q->dimoff, q->sizoff );
310 printf( CONFMT, off/SZCHAR );
311 printf( ".\n" );
312 }
313
314isitlong( cb, ce ){ /* is lastcon to be long or short */
315 /* cb is the first character of the representation, ce the last */
316
317 if( ce == 'l' || ce == 'L' ||
318 lastcon >= (1L << (SZINT-1) ) ) return (1);
319 return(0);
320 }
321
322
323isitfloat( s ) char *s; {
324 double atof();
325 dcon = atof(s);
326 return( FCON );
327 }
328
329ecode( p ) NODE *p; {
330
331 /* walk the tree and write out the nodes.. */
332
333 if( nerrors ) return;
334 p2tree( p );
335 p2compile( p );
336 }
337