1 /* Id: local.c,v 1.22 2015/08/18 10:15:08 ragge Exp */
2 /* $NetBSD: local.c,v 1.1.1.6 2016/02/09 20:28:19 plunky Exp $ */
3 /*
4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29 # include "pass1.h"
30
31 /* this file contains code which is dependent on the target machine */
32
33 NODE *
clocal(NODE * p)34 clocal(NODE *p)
35 {
36 /* this is called to do local transformations on
37 an expression tree preparitory to its being
38 written out in intermediate code.
39 */
40
41 /* the major essential job is rewriting the
42 automatic variables and arguments in terms of
43 REG and OREG nodes */
44 /* conversion ops which are not necessary are also clobbered here */
45 /* in addition, any special features (such as rewriting
46 exclusive or) are easily handled here as well */
47
48 struct symtab *q;
49 NODE *l, *r;
50 int o;
51 TWORD ml;
52
53 switch( o = p->n_op ){
54
55 case NAME:
56 if ((q = p->n_sp) == NULL)
57 return p; /* Nothing to care about */
58
59 switch (q->sclass) {
60
61 case PARAM:
62 case AUTO:
63 /* fake up a structure reference */
64 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
65 r->n_lval = 0;
66 r->n_rval = FPREG;
67 p = stref(block(STREF, r, p, 0, 0, 0));
68 break;
69
70 case STATIC:
71 if (q->slevel == 0)
72 break;
73 p->n_lval = 0;
74 p->n_sp = q;
75 break;
76
77 case REGISTER:
78 p->n_op = REG;
79 p->n_lval = 0;
80 p->n_rval = q->soffset;
81 break;
82
83 }
84 break;
85
86 case PCONV:
87 ml = p->n_left->n_type;
88 l = p->n_left;
89 if ((ml == CHAR || ml == UCHAR) && l->n_op != ICON)
90 break;
91 l->n_type = p->n_type;
92 l->n_qual = p->n_qual;
93 l->n_df = p->n_df;
94 l->n_sue = p->n_sue;
95 nfree(p);
96 p = l;
97 break;
98
99 case SCONV:
100 l = p->n_left;
101 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT) {
102 nfree(p);
103 return l;
104 }
105 if (l->n_op == ICON) {
106 CONSZ val = l->n_lval;
107 switch (p->n_type) {
108 case CHAR:
109 l->n_lval = (char)val;
110 break;
111 case UCHAR:
112 l->n_lval = val & 0377;
113 break;
114 case SHORT:
115 case INT:
116 l->n_lval = (short)val;
117 break;
118 case USHORT:
119 case UNSIGNED:
120 l->n_lval = val & 0177777;
121 break;
122 case ULONG:
123 case ULONGLONG:
124 l->n_lval = val & 0xffffffff;
125 break;
126 case LONG:
127 case LONGLONG:
128 l->n_lval = (int)val;
129 break;
130 case VOID:
131 break;
132 case LDOUBLE:
133 case DOUBLE:
134 case FLOAT:
135 l->n_op = FCON;
136 l->n_dcon = val;
137 break;
138 default:
139 cerror("unknown type %d", p->n_type);
140 }
141 l->n_type = p->n_type;
142 nfree(p);
143 return l;
144 }
145 break;
146
147
148 }
149
150 return(p);
151 }
152
153 /*ARGSUSED*/
154 int
andable(NODE * p)155 andable(NODE *p)
156 {
157 return(1); /* all names can have & taken on them */
158 }
159
160 /*
161 * is an automatic variable of type t OK for a register variable
162 */
163 int
cisreg(TWORD t)164 cisreg(TWORD t)
165 {
166 if (t == INT || t == UNSIGNED || t == CHAR || t == UCHAR ||
167 ISPTR(t))
168 return(1);
169 return 0; /* XXX - fix reg assignment in pftn.c */
170 }
171
172
173 /*
174 * Allocate off bits on the stack. p is a tree that when evaluated
175 * is the multiply count for off, t is a NAME node where to write
176 * the allocated address.
177 */
178 void
spalloc(NODE * t,NODE * p,OFFSZ off)179 spalloc(NODE *t, NODE *p, OFFSZ off)
180 {
181 NODE *sp;
182
183 if ((off % SZINT) == 0)
184 p = buildtree(MUL, p, bcon(off/SZINT));
185 else if ((off % SZSHORT) == 0) {
186 p = buildtree(MUL, p, bcon(off/SZSHORT));
187 p = buildtree(PLUS, p, bcon(1));
188 p = buildtree(RS, p, bcon(1));
189 } else if ((off % SZCHAR) == 0) {
190 p = buildtree(MUL, p, bcon(off/SZCHAR));
191 p = buildtree(PLUS, p, bcon(3));
192 p = buildtree(RS, p, bcon(2));
193 } else
194 cerror("roundsp");
195
196 /* save the address of sp */
197 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
198 sp->n_lval = 0;
199 sp->n_rval = STKREG;
200 t->n_type = sp->n_type;
201 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
202
203 /* add the size to sp */
204 sp = block(REG, NIL, NIL, p->n_type, 0, 0);
205 sp->n_lval = 0;
206 sp->n_rval = STKREG;
207 ecomp(buildtree(PLUSEQ, sp, p));
208 }
209
210 /*
211 * print out a constant node
212 * mat be associated with a label
213 */
214 int
ninval(NODE * p)215 ninval(NODE *p)
216 {
217 struct symtab *q;
218 TWORD t;
219
220 p = p->n_left;
221 t = p->n_type;
222 if (t > BTMASK)
223 t = p->n_type = INT; /* pointer */
224
225 switch (t) {
226 case LONGLONG:
227 case ULONGLONG:
228 inval(p->n_lval & 0xffffffff);
229 inval(p->n_lval >> 32);
230 break;
231 case LONG:
232 case ULONG:
233 case INT:
234 case UNSIGNED:
235 printf("\t.long 0x%x", (int)p->n_lval);
236 if ((q = p->n_sp) != NULL) {
237 if ((q->sclass == STATIC && q->slevel > 0)) {
238 printf("+" LABFMT, q->soffset);
239 } else
240 printf("+%s", exname(q->soname));
241 }
242 printf("\n");
243 break;
244 default:
245 fwalk(p, eprint, 0);
246 return 0;
247 }
248 return 1;
249 }
250
251 /* make a name look like an external name in the local machine */
252 char *
exname(char * p)253 exname(char *p)
254 {
255 if (p == NULL)
256 return "";
257 return p;
258 }
259
260 /*
261 * map types which are not defined on the local machine
262 */
263 TWORD
ctype(TWORD type)264 ctype(TWORD type)
265 {
266 switch (BTYPE(type)) {
267 case SHORT:
268 MODTYPE(type,INT);
269 break;
270
271 case USHORT:
272 MODTYPE(type,UNSIGNED);
273 break;
274
275 case LONGLONG:
276 MODTYPE(type,LONG);
277 break;
278
279 case ULONGLONG:
280 MODTYPE(type,ULONG);
281 break;
282
283 case LDOUBLE:
284 MODTYPE(type,DOUBLE);
285 break;
286 }
287 return (type);
288 }
289
290 /* curid is a variable which is defined but
291 * is not initialized (and not a function );
292 * This routine returns the storage class for an uninitialized declaration
293 */
294 int
noinit()295 noinit()
296 {
297 return(EXTERN);
298 }
299
300 /*
301 * Extern variable not necessary common.
302 */
303 void
extdec(struct symtab * q)304 extdec(struct symtab *q)
305 {
306 extern void addsym(struct symtab *);
307 addsym(q);
308 }
309
310 /*
311 * Call to a function
312 */
313 void
calldec(NODE * p,NODE * r)314 calldec(NODE *p, NODE *r)
315 {
316 struct symtab *q = p->n_sp;
317 extern void addsym(struct symtab *);
318 addsym(q);
319 }
320
321 /* make a common declaration for id, if reasonable */
322 void
commdec(struct symtab * q)323 commdec(struct symtab *q)
324 {
325 int off;
326 char *c = q->soname;
327
328 off = tsize(q->stype, q->sdf, q->ssue);
329 off = (off+(SZCHAR-1))/SZCHAR;
330
331 printf(" PUBLIC %s\n", c);
332 /* XXX - NOROOT??? */
333 printf(" RSEG DATA16_Z:NEARDATA:SORT:NOROOT(1)\n");
334 printf("%s:\n", c);
335 printf(" DS8 %d\n", off);
336 printf(" REQUIRE __data16_zero\n");
337 }
338
339 /* make a local common declaration for id, if reasonable */
340 void
lcommdec(struct symtab * q)341 lcommdec(struct symtab *q)
342 {
343 int off;
344
345 off = tsize(q->stype, q->sdf, q->ssue);
346 off = (off+(SZCHAR-1))/SZCHAR;
347 if (q->slevel == 0)
348 printf(" .lcomm %s,0%o\n", exname(q->soname), off);
349 else
350 printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
351 }
352
353 /*
354 * print a (non-prog) label.
355 */
356 void
deflab1(int label)357 deflab1(int label)
358 {
359 printf(LABFMT ":\n", label);
360 }
361
362 void
setloc1(int locc)363 setloc1(int locc)
364 {
365 if (locc == lastloc)
366 return;
367 lastloc = locc;
368 }
369
370 /*
371 * special handling before tree is written out.
372 */
373 void
myp2tree(NODE * p)374 myp2tree(NODE *p)
375 {
376 struct symtab *sp;
377 union dimfun *df;
378 union arglist *al;
379 NODE *q;
380 int i;
381
382 switch (p->n_op) {
383 case MOD:
384 case DIV:
385 if (p->n_type == LONG || p->n_type == ULONG) {
386 /* Swap arguments for hardops() later */
387 q = p->n_left;
388 p->n_left = p->n_right;
389 p->n_right = q;
390 }
391 break;
392
393 case CALL:
394 case STCALL:
395 /*
396 * inform pass2 about varargs.
397 * store first variadic argument number in n_stalign
398 * in the CM node.
399 */
400 if (p->n_right->n_op != CM)
401 break; /* nothing to care about */
402 df = p->n_left->n_df;
403 if (df && (al = df->dfun)) {
404 for (i = 0; i < 6; i++, al++) {
405 if (al->type == TELLIPSIS || al->type == TNULL)
406 break;
407 }
408 p->n_right->n_stalign = al->type == TELLIPSIS ? i : 0;
409 } else
410 p->n_right->n_stalign = 0;
411 break;
412
413 case FCON:
414 /* Write float constants to memory */
415 sp = tmpalloc(sizeof(struct symtab));
416 sp->sclass = STATIC;
417 sp->ssue = 0;
418 sp->slevel = 1; /* fake numeric label */
419 sp->soffset = getlab();
420 sp->sflags = 0;
421 sp->stype = p->n_type;
422 sp->squal = (CON >> TSHIFT);
423
424 defloc(sp);
425 ninval(0, sp->ssue->suesize, p);
426
427 p->n_op = NAME;
428 p->n_lval = 0;
429 p->n_sp = sp;
430 break;
431 }
432
433 }
434
435 /*
436 * Give target the opportunity of handling pragmas.
437 */
438 int
mypragma(char ** ary)439 mypragma(char **ary)
440 {
441 return 0;
442 }
443
444 /*
445 * Called when a identifier has been declared, to give target last word.
446 */
447 void
fixdef(struct symtab * sp)448 fixdef(struct symtab *sp)
449 {
450 }
451
452 void
pass1_lastchance(struct interpass * ip)453 pass1_lastchance(struct interpass *ip)
454 {
455 }
456