~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/app/pcc/arch/pdp10/local.c

  • Committer: Jakub Jermar
  • Date: 2011-09-07 22:19:24 UTC
  • mfrom: (1113.1.41 devel)
  • Revision ID: jakub@jermar.eu-20110907221924-cfgktigu4e8l0uyv
Merge from lp:~helenos-posix/helenos/devel.

* Petr Koupy's port of binutils.
* Jiri Zarevucky's port of pcc.
* Petr and Jiri's libposix library.
* Changes needed to make it all work together.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $Id: local.c,v 1.72 2011/01/21 21:47:58 ragge Exp $     */
 
2
/*
 
3
 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 * 1. Redistributions of source code must retain the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer.
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in the
 
13
 *    documentation and/or other materials provided with the distribution.
 
14
 * 3. The name of the author may not be used to endorse or promote products
 
15
 *    derived from this software without specific prior written permission
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
 
 
30
# include "pass1.h"
 
31
 
 
32
/*      this file contains code which is dependent on the target machine */
 
33
 
 
34
static int pointp(TWORD t);
 
35
static struct symtab *newfun(char *name, TWORD type);
 
36
 
 
37
#define PTRNORMAL       1
 
38
#define PTRCHAR         2
 
39
#define PTRSHORT        3
 
40
static int xptype(TWORD t);
 
41
 
 
42
NODE *
 
43
clocal(NODE *p)
 
44
{
 
45
        /* this is called to do local transformations on
 
46
           an expression tree preparitory to its being
 
47
           written out in intermediate code.
 
48
        */
 
49
 
 
50
        /* the major essential job is rewriting the
 
51
           automatic variables and arguments in terms of
 
52
           REG and OREG nodes */
 
53
        /* conversion ops which are not necessary are also clobbered here */
 
54
        /* in addition, any special features (such as rewriting
 
55
           exclusive or) are easily handled here as well */
 
56
 
 
57
        register struct symtab *q;
 
58
        register NODE *r, *l, *oop;
 
59
        register int o;
 
60
        register int m, ml;
 
61
        int siz;
 
62
 
 
63
#ifdef PCC_DEBUG
 
64
        if (xdebug) {
 
65
                printf("clocal: %p\n", p);
 
66
                fwalk(p, eprint, 0);
 
67
        }
 
68
#endif
 
69
 
 
70
        switch( o = p->n_op ){
 
71
 
 
72
        case NAME:
 
73
                if ((q = p->n_sp) == NULL)
 
74
                        return p; /* Nothing to care about */
 
75
 
 
76
                switch (q->sclass) {
 
77
 
 
78
                case PARAM:
 
79
                        /* First 7 parameters are in registers */
 
80
                        /* XXX last may be double */
 
81
                        if (q->soffset/SZINT < 7) {
 
82
                                p->n_op = REG;
 
83
                                p->n_rval = q->soffset/SZINT;
 
84
                                break;
 
85
                        } else
 
86
                                q->soffset -= 7*SZINT;
 
87
                                
 
88
                case AUTO:
 
89
                        /* fake up a structure reference */
 
90
                        if (q->stype == CHAR || q->stype == UCHAR ||
 
91
                            q->stype == SHORT || q->stype == USHORT)
 
92
                                r = block(REG, NIL, NIL, PTR+q->stype, 0, 0);
 
93
                        else
 
94
                                r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
 
95
                        r->n_lval = 0;
 
96
                        r->n_rval = FPREG;
 
97
                        p = stref(block(STREF, r, p, 0, 0, 0));
 
98
                        break;
 
99
 
 
100
                case STATIC:
 
101
                        if (q->slevel == 0)
 
102
                                break;
 
103
                        p->n_lval = 0;
 
104
                        break;
 
105
 
 
106
                case REGISTER:
 
107
                        p->n_op = REG;
 
108
                        p->n_lval = 0;
 
109
                        p->n_rval = q->soffset;
 
110
                        break;
 
111
 
 
112
                        }
 
113
                break;
 
114
 
 
115
        case CALL:
 
116
                /* avoid recursive calls */
 
117
                r = tempnode(0, p->n_type, p->n_df, p->n_sue);
 
118
                l = tempnode(regno(r), p->n_type, p->n_df, p->n_sue);
 
119
                ecomp(buildtree(ASSIGN, r, p));
 
120
                p = l;
 
121
                break;
 
122
 
 
123
        case PCONV:
 
124
                l = p->n_left;
 
125
                /*
 
126
                 * Handle frame pointer directly without conversion,
 
127
                 * for efficiency.
 
128
                 */
 
129
                if (l->n_op == REG && l->n_rval == 0) {
 
130
rmpc:                   l->n_type = p->n_type;
 
131
                        l->n_df = p->n_df;
 
132
                        l->n_sue = p->n_sue;
 
133
                        nfree(p);
 
134
                        return l;
 
135
                }
 
136
                /* Convert ICON with name to new type */
 
137
                if (l->n_op == ICON && l->n_sp != NULL &&
 
138
                    l->n_type == INCREF(STRTY) && 
 
139
                    (p->n_type == INCREF(CHAR) ||
 
140
                    p->n_type == INCREF(UCHAR) ||
 
141
                    p->n_type == INCREF(SHORT) ||
 
142
                    p->n_type == INCREF(USHORT))) {
 
143
                        l->n_lval *= (BTYPE(p->n_type) == CHAR ||
 
144
                            BTYPE(p->n_type) == UCHAR ? 4 : 2);
 
145
                        goto rmpc;
 
146
                }
 
147
                /* Convert only address constants, never convert other */
 
148
                if (l->n_op == ICON) {
 
149
                        if (l->n_sp == NULL)
 
150
                                goto rmpc;
 
151
                        if (p->n_type == INCREF(CHAR) ||
 
152
                            p->n_type == INCREF(UCHAR) ||
 
153
                            p->n_type == INCREF(VOID))
 
154
                                l->n_lval = (l->n_lval & 07777777777) |
 
155
                                    0700000000000LL;
 
156
                        else if (p->n_type == INCREF(SHORT) ||
 
157
                            p->n_type == INCREF(USHORT))
 
158
                                l->n_lval = (l->n_lval & 07777777777) |
 
159
                                    0750000000000LL;
 
160
                        else
 
161
                                l->n_lval = l->n_lval & 07777777777;
 
162
                        goto rmpc;
 
163
                }
 
164
 
 
165
                /* Remove more conversions of identical pointers */
 
166
                /* Be careful! optim() may do bad things */
 
167
                if (ISPTR(DECREF(p->n_type))) {
 
168
                        if (ISPTR(DECREF(l->n_type))) {
 
169
                                if ((coptype(l->n_op) == UTYPE ||
 
170
                                    coptype(l->n_op) == BITYPE) &&
 
171
                                    (l->n_left->n_op == REG))
 
172
                                        l->n_left->n_type = p->n_type;
 
173
                                goto rmpc;
 
174
                        }
 
175
                }
 
176
 
 
177
                /* Change PCONV from int to double pointer to right shift */
 
178
                if (ISPTR(p->n_type) && ISPTR(DECREF(p->n_type)) &&
 
179
                    (l->n_type == INT || l->n_type == UNSIGNED)) {
 
180
                        p->n_op = RS;
 
181
                        p->n_right = bcon(2);
 
182
                        break;
 
183
                }
 
184
                
 
185
                /* Check for cast integral -> pointer */
 
186
                if (BTYPE(l->n_type) == l->n_type)
 
187
                        break;
 
188
 
 
189
                /* Remove conversions to identical pointers */
 
190
                switch (xptype(p->n_type)) {
 
191
                case PTRNORMAL:
 
192
                        if (xptype(l->n_type) == PTRNORMAL)
 
193
                                goto rmpc;
 
194
                        break;
 
195
 
 
196
                case PTRSHORT:
 
197
                        if (xptype(l->n_type) == PTRSHORT)
 
198
                                goto rmpc;
 
199
                        break;
 
200
 
 
201
                case PTRCHAR:
 
202
                        if (xptype(l->n_type) == PTRCHAR)
 
203
                                goto rmpc;
 
204
                        break;
 
205
                }
 
206
 
 
207
                break;
 
208
 
 
209
        case SCONV:
 
210
                l = p->n_left;
 
211
 
 
212
                if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
 
213
                    btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
 
214
                        if (p->n_type != FLOAT && p->n_type != DOUBLE &&
 
215
                             l->n_type != FLOAT && l->n_type != DOUBLE) {
 
216
                                nfree(p);
 
217
                                return l;
 
218
                        }
 
219
                }
 
220
                /* cast to (void) XXX should be removed in MI code */
 
221
                if (p->n_type == VOID) {
 
222
                        nfree(p);
 
223
                        return l;
 
224
                }
 
225
                m = p->n_type;
 
226
                ml = l->n_type;
 
227
                if (m == ml) {
 
228
                        nfree(p);
 
229
                        return l;
 
230
                }
 
231
                o = l->n_op;
 
232
                if (ml == FLOAT || ml == DOUBLE) {
 
233
                        if (o != FCON)
 
234
                                break;
 
235
                        ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */
 
236
                        r = xbcon(ml == INT ? (int)p->n_left->n_dcon :
 
237
                                              (unsigned)p->n_left->n_dcon,
 
238
                                  NULL, ml);
 
239
                        nfree(p->n_left);
 
240
                        p->n_left = r;
 
241
                        o = ICON;
 
242
                        if (m == ml) {
 
243
                                r = p->n_left;
 
244
                                nfree(p);
 
245
                                return r;
 
246
                        }
 
247
                }
 
248
                if (o == ICON) {
 
249
                        CONSZ val = l->n_lval;
 
250
 
 
251
                        switch (m) {
 
252
                        case CHAR:
 
253
                                l->n_lval = val & 0777;
 
254
                                if (val & 0400)
 
255
                                        l->n_lval |= ~((CONSZ)0777);
 
256
                                break;
 
257
                        case UCHAR:
 
258
                                l->n_lval = val & 0777;
 
259
                                break;
 
260
                        case USHORT:
 
261
                                l->n_lval = val & 0777777;
 
262
                                break;
 
263
                        case SHORT:
 
264
                                l->n_lval = val & 0777777;
 
265
                                if (val & 0400000)
 
266
                                        l->n_lval |= ~((CONSZ)0777777);
 
267
                                break;
 
268
                        case UNSIGNED:
 
269
                                l->n_lval = val & 0777777777777LL;
 
270
                                break;
 
271
                        case INT:
 
272
                                l->n_lval = val & 0777777777777LL;
 
273
                                if (val & 0400000000000LL)
 
274
                                        l->n_lval |= ~(0777777777777LL);
 
275
                                break;
 
276
                        case LONGLONG:  /* XXX */
 
277
                        case ULONGLONG:
 
278
                                l->n_lval = val;
 
279
                                break;
 
280
                        case VOID:
 
281
                                break;
 
282
                        case DOUBLE:
 
283
                        case FLOAT:
 
284
                                l->n_op = FCON;
 
285
                                l->n_dcon = 0;
 
286
                                break;
 
287
                        default:
 
288
                                cerror("unknown type %d", m);
 
289
                        }
 
290
                        l->n_type = m;
 
291
                        l->n_sue = MKSUE(m);
 
292
                        nfree(p);
 
293
                        return l;
 
294
                }
 
295
                break;
 
296
 
 
297
        case PMCONV:
 
298
        case PVCONV:
 
299
/*                if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); */
 
300
                nfree(p);
 
301
                return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
 
302
 
 
303
        case RS:
 
304
        case RSEQ:
 
305
                /* convert >> to << with negative shift count */
 
306
                /* Beware! constant shifts will be converted back in optim() */
 
307
 
 
308
                if (p->n_right->n_op != UMINUS) {
 
309
                        p->n_right = buildtree(UMINUS, p->n_right, NIL);
 
310
                } else {
 
311
                        r = p->n_right;
 
312
                        p->n_right = p->n_right->n_left;
 
313
                        nfree(r);
 
314
                }
 
315
                if (p->n_op == RS)
 
316
                        p->n_op = LS;
 
317
                else
 
318
                        p->n_op = LSEQ;
 
319
                break;
 
320
 
 
321
        case UMUL: /* Convert structure assignment to memcpy() */
 
322
                if (p->n_left->n_op == PLUS &&
 
323
                    p->n_left->n_left->n_op == PCONV &&
 
324
                    p->n_left->n_right->n_op == ICON &&
 
325
                    (p->n_type == CHAR || p->n_type == UCHAR ||
 
326
                    p->n_type == SHORT || p->n_type == USHORT)) {
 
327
                        /* Can remove the left SCONV */
 
328
                        l = p->n_left->n_left;
 
329
                        p->n_left->n_left = l->n_left;
 
330
                        nfree(l);
 
331
                        break;
 
332
 
 
333
                }
 
334
                if (p->n_left->n_op != STASG)
 
335
                        break;
 
336
                oop = p;
 
337
                p = p->n_left;
 
338
                siz = p->n_sue->suesize/SZCHAR;
 
339
                l = p->n_left;
 
340
                r = p->n_right;
 
341
                if (l->n_type == STRTY || l->n_type == UNIONTY) {
 
342
                        if (l->n_op == UMUL) {
 
343
                                p->n_left = l->n_left;
 
344
                                nfree(l);
 
345
                                l = p->n_left;
 
346
                        } else {
 
347
                                l = block(ADDROF, l, NIL, INCREF(l->n_type),
 
348
                                    0, MKSUE(INT));
 
349
                        }
 
350
                }
 
351
                if ((l->n_type != (STRTY+PTR) && l->n_type != (UNIONTY+PTR)) ||
 
352
                    (r->n_type != (STRTY+PTR) && r->n_type != (UNIONTY+PTR)))
 
353
                        cerror("bad stasg, l = %o, r = %o", l->n_type, r->n_type);
 
354
                q = newfun("__structcpy", p->n_type);
 
355
 
 
356
                /* structure pointer block */
 
357
                l = block(CM, l, r, INT, 0, MKSUE(INT));
 
358
                /* Size block */
 
359
                r = block(CM, l, bcon(siz), INT, 0, MKSUE(INT));
 
360
 
 
361
                l = xbcon(0, q, q->stype);
 
362
                p->n_left = l;
 
363
                p->n_right = r;
 
364
                p->n_op = CALL;
 
365
                oop->n_left = p;
 
366
                return oop;
 
367
 
 
368
        case FORCE:
 
369
                p->n_op = ASSIGN;
 
370
                p->n_right = p->n_left;
 
371
                p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
 
372
                p->n_left->n_rval = RETREG(p->n_type);
 
373
                break;
 
374
 
 
375
        }
 
376
 
 
377
        return(p);
 
378
}
 
379
 
 
380
void
 
381
myp2tree(NODE *p)
 
382
{
 
383
        NODE *r;
 
384
 
 
385
        switch (p->n_op) {
 
386
        case ULT: /* exor sign bit to avoid unsigned comparitions */
 
387
        case ULE:
 
388
        case UGT:
 
389
        case UGE:
 
390
                if (ISLONGLONG(p->n_left->n_type)) {
 
391
                        /* XXX */
 
392
                        r = xbcon(0x8000000000000000ULL, NULL, LONGLONG);
 
393
                } else
 
394
                        r = xbcon(0400000000000LL, NULL, INT);
 
395
                p->n_left = buildtree(ER, p->n_left, r);
 
396
                if (ISUNSIGNED(p->n_left->n_type))
 
397
                        p->n_left->n_type = DEUNSIGN(p->n_left->n_type);
 
398
 
 
399
                if (ISLONGLONG(p->n_right->n_type)) {
 
400
                        /* XXX */
 
401
                        r = xbcon(0x8000000000000000ULL, NULL, LONGLONG);
 
402
                } else
 
403
                        r = xbcon(0400000000000LL, NULL, INT);
 
404
                p->n_right = buildtree(ER, p->n_right, r);
 
405
                if (ISUNSIGNED(p->n_right->n_type))
 
406
                        p->n_right->n_type = DEUNSIGN(p->n_right->n_type);
 
407
 
 
408
                p->n_op -= (ULT-LT);
 
409
                break;
 
410
        case FCON:
 
411
                cerror("fix float constants");
 
412
        }
 
413
}
 
414
 
 
415
 
 
416
struct symtab *
 
417
newfun(char *name, TWORD type)
 
418
{
 
419
        struct symtab *sp;
 
420
 
 
421
        sp = lookup(name, 0);
 
422
        if (sp->stype == VOID) {
 
423
                sp->stype = INCREF(type | FTN);
 
424
                sp->sclass = EXTERN;
 
425
                sp->soffset = 0;
 
426
        }
 
427
#ifdef notdef
 
428
        else if (!ISFTN(DECREF(sp->stype)))
 
429
                uerror("reserved name '%s' used illegally", name);
 
430
#endif
 
431
        return sp;
 
432
}
 
433
 
 
434
/*ARGSUSED*/
 
435
int
 
436
andable(NODE *p)
 
437
{
 
438
        return(1);  /* all names can have & taken on them */
 
439
}
 
440
 
 
441
/*
 
442
 * at the end of the arguments of a ftn, set the automatic offset
 
443
 */
 
444
void
 
445
cendarg()
 
446
{
 
447
        autooff = AUTOINIT;
 
448
}
 
449
 
 
450
/*
 
451
 * is an automatic variable of type t OK for a register variable
 
452
 * Everything is trusted to be in register here.
 
453
 */
 
454
int
 
455
cisreg(TWORD t)
 
456
{
 
457
        return(1);
 
458
}
 
459
 
 
460
int
 
461
xptype(TWORD t)
 
462
{
 
463
        int tt = BTYPE(t);
 
464
        int e, rv;
 
465
 
 
466
        if (!ISPTR(t))
 
467
                cerror("not a pointer");
 
468
 
 
469
        e = t & ~BTMASK;
 
470
        rv = e;
 
471
        while (e) {
 
472
                rv = e;
 
473
                if (DECREF(e) == 0)
 
474
                        break;
 
475
                e = DECREF(e);
 
476
        }
 
477
        if (ISFTN(rv))
 
478
                return PTRNORMAL;
 
479
 
 
480
        switch (tt) {
 
481
        case INT:
 
482
        case LONG:
 
483
        case LONGLONG:
 
484
        case FLOAT:
 
485
        case DOUBLE:
 
486
        case STRTY:
 
487
        case UNIONTY:
 
488
        case UNSIGNED:
 
489
        case ULONG:
 
490
        case ULONGLONG:
 
491
                return PTRNORMAL;
 
492
        case VOID:
 
493
        case CHAR:
 
494
        case UCHAR:
 
495
                if (DECREF(t) == tt || ISARY(rv))
 
496
                        return PTRCHAR;
 
497
                return PTRNORMAL;
 
498
        case SHORT:
 
499
        case USHORT:
 
500
                if (DECREF(t) == tt || ISARY(rv))
 
501
                        return PTRSHORT;
 
502
                return PTRNORMAL;
 
503
        default:
 
504
                break;
 
505
        }
 
506
        cerror("unknown type");
 
507
        return PTRNORMAL; /* XXX */
 
508
}
 
509
 
 
510
/*
 
511
 * Help routine to the one below; return true if it's not a word pointer.
 
512
 */
 
513
static int
 
514
pointp(TWORD t)
 
515
{
 
516
        int rv = 0;
 
517
 
 
518
        if (ISPTR(t) && ((t & TMASK1) == 0))
 
519
                return 1;
 
520
 
 
521
        t &= ~BTMASK;
 
522
        while (t) {
 
523
                rv = ISARY(t);
 
524
                t = DECREF(t);
 
525
        }
 
526
        return rv;
 
527
}
 
528
 
 
529
/*
 
530
 * return a node, for structure references, which is suitable for
 
531
 * being added to a pointer of type t, in order to be off bits offset
 
532
 * into a structure
 
533
 * t, d, and s are the type, dimension offset, and sizeoffset
 
534
 * For pdp10, return the type-specific index number which calculation
 
535
 * is based on its size. For example, short a[3] would return 3.
 
536
 * Be careful about only handling first-level pointers, the following
 
537
 * indirections must be fullword.
 
538
 */
 
539
NODE *
 
540
offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
 
541
{
 
542
        register NODE *p;
 
543
 
 
544
        if (xdebug)
 
545
                printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
 
546
                    off, t, d, sue->suesize);
 
547
 
 
548
        p = bcon(0);
 
549
        p->n_lval = off/SZINT;  /* Default */
 
550
        if (ISPTR(DECREF(t)))
 
551
                return p;       /* Pointer/pointer reference */
 
552
        switch (BTMASK & t) {
 
553
        case INT:
 
554
        case UNSIGNED:
 
555
        case LONG:
 
556
        case ULONG:
 
557
        case STRTY:
 
558
        case UNIONTY:
 
559
        case LONGLONG:
 
560
        case ULONGLONG:
 
561
        case FLOAT:
 
562
        case DOUBLE:
 
563
                break;
 
564
 
 
565
        case SHORT:
 
566
        case USHORT:
 
567
                if (pointp(t))
 
568
                        p->n_lval = off/SZSHORT;
 
569
                break;
 
570
 
 
571
        case VOID: /* void pointers */
 
572
        case CHAR:
 
573
        case UCHAR:
 
574
                if (pointp(t))
 
575
                        p->n_lval = off/SZCHAR;
 
576
                break;
 
577
 
 
578
        default:
 
579
                cerror("offcon, off %llo size %d type %x", off, sue->suesize, t);
 
580
        }
 
581
        if (xdebug)
 
582
                printf("offcon return 0%llo\n", p->n_lval);
 
583
        return(p);
 
584
}
 
585
 
 
586
/*
 
587
 * Allocate off bits on the stack.  p is a tree that when evaluated
 
588
 * is the multiply count for off, t is a NAME node where to write
 
589
 * the allocated address.
 
590
 * Be aware that a pointer conversion may be needed when saving 
 
591
 * to node t!
 
592
 */
 
593
void
 
594
spalloc(NODE *t, NODE *p, OFFSZ off)
 
595
{
 
596
        NODE *sp;
 
597
 
 
598
        if ((off % SZINT) == 0)
 
599
                p =  buildtree(MUL, p, bcon(off/SZINT));
 
600
        else if ((off % SZSHORT) == 0) {
 
601
                p = buildtree(MUL, p, bcon(off/SZSHORT));
 
602
                p = buildtree(PLUS, p, bcon(1));
 
603
                p = buildtree(RS, p, bcon(1));
 
604
        } else if ((off % SZCHAR) == 0) {
 
605
                p = buildtree(MUL, p, bcon(off/SZCHAR));
 
606
                p = buildtree(PLUS, p, bcon(3));
 
607
                p = buildtree(RS, p, bcon(2));
 
608
        } else
 
609
                cerror("roundsp");
 
610
 
 
611
        /* save the address of sp */
 
612
        sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
 
613
        sp->n_lval = 0;
 
614
        sp->n_rval = STKREG;
 
615
        /* Cast sp to destination type (may be redundant) */
 
616
        sp = buildtree(CAST,
 
617
            block(NAME, NIL, NIL, t->n_type, t->n_df, t->n_sue), sp);
 
618
        nfree(sp->n_left);
 
619
        nfree(sp);
 
620
        sp = sp->n_right;
 
621
        ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
 
622
 
 
623
        /* add the size to sp */
 
624
        sp = block(REG, NIL, NIL, p->n_type, 0, 0);
 
625
        sp->n_lval = 0;
 
626
        sp->n_rval = STKREG;
 
627
        ecomp(buildtree(PLUSEQ, sp, p));
 
628
}
 
629
 
 
630
#if 0
 
631
static int inwd;        /* current bit offsed in word */
 
632
static CONSZ word;      /* word being built from fields */
 
633
 
 
634
/*
 
635
 * Generate initialization code for assigning a constant c
 
636
 * to a field of width sz
 
637
 * we assume that the proper alignment has been obtained
 
638
 * inoff is updated to have the proper final value
 
639
 * we also assume sz  < SZINT
 
640
 */
 
641
void
 
642
incode(NODE *p, int sz)
 
643
{
 
644
        char *s;
 
645
 
 
646
        inoff += sz;
 
647
        if ((sz + inwd) > SZINT)
 
648
                cerror("incode: field > int");
 
649
 
 
650
        word |= ((p->n_lval & ((1 << sz) - 1)) << (36 - inwd - sz));
 
651
 
 
652
        inwd += sz;
 
653
        if (inoff % SZINT == 0) {
 
654
                s = isinlining ? permalloc(30) : tmpalloc(30);
 
655
                sprintf(s, "    .long 0%llo", word);
 
656
                send_passt(IP_ASM, s);
 
657
                word = inwd = 0;
 
658
        }
 
659
        tfree(p);
 
660
}
 
661
 
 
662
/* output code to initialize space of size sz to the value d */
 
663
/* the proper alignment has been obtained */
 
664
/* inoff is updated to have the proper final value */
 
665
/* on the target machine, write it out in octal! */
 
666
void
 
667
fincode(NODE *p, int sz)
 
668
{
 
669
        double d = p->n_dcon;
 
670
 
 
671
        if(!nerrors)
 
672
                printf("        %s      0%c%.20e\n",
 
673
                    sz == SZDOUBLE ? ".double" : ".float",
 
674
                sz == SZDOUBLE ? 'd' : 'f', d);
 
675
        inoff += sz;
 
676
}
 
677
 
 
678
void
 
679
cinit(NODE *p, int sz)
 
680
{
 
681
        NODE *l;
 
682
 
 
683
        /*
 
684
         * as a favor (?) to people who want to write
 
685
         *     int i = 9600/134.5;
 
686
         * we will, under the proper circumstances, do
 
687
         * a coercion here.
 
688
         */
 
689
        switch (p->n_type) {
 
690
        case INT:
 
691
        case UNSIGNED:
 
692
                l = p->n_left;
 
693
                if (l->n_op != SCONV || l->n_left->n_op != FCON)
 
694
                        break;
 
695
                nfree(l);
 
696
                l = l->n_left;
 
697
                l->n_lval = (long)(l->n_dcon);
 
698
                l->n_sp = NULL;
 
699
                l->n_op = ICON;
 
700
                l->n_type = INT;
 
701
                p->n_left = l;
 
702
                break;
 
703
        }
 
704
        /* arrange for the initialization of p into a space of size sz */
 
705
        /* the proper alignment has been opbtained */
 
706
        /* inoff is updated to have the proper final value */
 
707
        ecode( p );
 
708
        inoff += sz;
 
709
}
 
710
 
 
711
/*
 
712
 * define n bits of zeros in a vfd
 
713
 */
 
714
void
 
715
vfdzero(int n)
 
716
{
 
717
        char *s;
 
718
 
 
719
        inoff += n;
 
720
        inwd += n;
 
721
        if (inoff%ALINT ==0) {
 
722
                s = isinlining ? permalloc(30) : tmpalloc(30);
 
723
                sprintf(s, "    .long 0%llo", word);
 
724
                send_passt(IP_ASM, s);
 
725
                word = inwd = 0;
 
726
        }
 
727
}
 
728
#endif
 
729
 
 
730
/* make a name look like an external name in the local machine */
 
731
char *
 
732
exname(char *p)
 
733
{
 
734
        if (p == NULL)
 
735
                return "";
 
736
        return p;
 
737
}
 
738
 
 
739
/*
 
740
 * map types which are not defined on the local machine
 
741
 */
 
742
TWORD
 
743
ctype(TWORD type)
 
744
{
 
745
        switch (BTYPE(type)) {
 
746
        case LONG:
 
747
                MODTYPE(type,INT);
 
748
                break;
 
749
        case ULONG:
 
750
                MODTYPE(type,UNSIGNED);
 
751
                break;
 
752
        case LDOUBLE:
 
753
                MODTYPE(type,DOUBLE);
 
754
                break;
 
755
        }
 
756
        return (type);
 
757
}
 
758
 
 
759
/*
 
760
 * Print out a string of characters.
 
761
 * Assume that the assembler understands C-style escape
 
762
 * sequences.
 
763
 */
 
764
void
 
765
instring(struct symtab *sp)
 
766
{
 
767
        char *s, *str;
 
768
 
 
769
        defloc(sp);
 
770
        str = sp->sname;
 
771
 
 
772
        /* be kind to assemblers and avoid long strings */
 
773
        printf("\t.ascii \"");
 
774
        for (s = str; *s != 0; ) {
 
775
                if (*s++ == '\\') {
 
776
                        (void)esccon(&s);
 
777
                }
 
778
                if (s - str > 60) {
 
779
                        fwrite(str, 1, s - str, stdout);
 
780
                        printf("\"\n\t.ascii \"");
 
781
                        str = s;
 
782
                }
 
783
        }
 
784
        fwrite(str, 1, s - str, stdout);
 
785
        printf("\\0\"\n");
 
786
}
 
787
 
 
788
/* curid is a variable which is defined but
 
789
 * is not initialized (and not a function );
 
790
 * This routine returns the stroage class for an uninitialized declaration
 
791
 */
 
792
int
 
793
noinit()
 
794
{
 
795
        return(EXTERN);
 
796
}
 
797
 
 
798
void
 
799
calldec(NODE *p, NODE *q) 
 
800
{
 
801
}
 
802
 
 
803
void
 
804
extdec(struct symtab *q)
 
805
{
 
806
}
 
807
 
 
808
/* make a common declaration for id, if reasonable */
 
809
void
 
810
defzero(struct symtab *sp)
 
811
{
 
812
        int off;
 
813
 
 
814
        off = tsize(sp->stype, sp->sdf, sp->ssue);
 
815
        off = (off+(SZINT-1))/SZINT;
 
816
        printf("        .%scomm ", sp->sclass == STATIC ? "l" : "");
 
817
        if (sp->slevel == 0)
 
818
                printf("%s,0%o\n", exname(sp->soname), off);
 
819
        else
 
820
                printf(LABFMT ",0%o\n", sp->soffset, off);
 
821
}
 
822
 
 
823
/*
 
824
 * set fsz bits in sequence to zero.
 
825
 */
 
826
void
 
827
zbits(OFFSZ off, int fsz)
 
828
{
 
829
        cerror("zbits");
 
830
}
 
831
 
 
832
/*
 
833
 * Initialize a bitfield.
 
834
 */
 
835
void
 
836
infld(CONSZ off, int fsz, CONSZ val)
 
837
{
 
838
//      if (idebug)
 
839
//              printf("infld off %lld, fsz %d, val %lld inbits %d\n",
 
840
//                  off, fsz, val, inbits);
 
841
        cerror("infld");
 
842
}
 
843
 
 
844
/*
 
845
 * print out a constant node, may be associated with a label.
 
846
 * Do not free the node after use.
 
847
 * off is bit offset from the beginning of the aggregate
 
848
 * fsz is the number of bits this is referring to
 
849
 */
 
850
void
 
851
ninval(CONSZ off, int fsz, NODE *p)
 
852
{
 
853
        cerror("ninval");
 
854
}
 
855
 
 
856
 
 
857
/*
 
858
 * Give target the opportunity of handling pragmas.
 
859
 */
 
860
int
 
861
mypragma(char *str)
 
862
{
 
863
        return 0;
 
864
}
 
865
 
 
866
/*
 
867
 * Called when a identifier has been declared, to give target last word.
 
868
 */
 
869
void
 
870
fixdef(struct symtab *sp)
 
871
{
 
872
}
 
873
 
 
874
void
 
875
pass1_lastchance(struct interpass *ip)
 
876
{
 
877
}
 
878