1 /*        Id: putscj.c,v 1.18 2008/12/19 08:08:48 ragge Exp           */
2 /*        $NetBSD: putscj.c,v 1.1.1.3 2010/06/03 18:57:52 plunky Exp $          */
3 /*
4  * Copyright(C) Caldera International Inc. 2001-2002. 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  *
10  * Redistributions of source code and documentation must retain the above
11  * copyright notice, this list of conditions and the following disclaimer.
12  * 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  * All advertising materials mentioning features or use of this software
16  * must display the following acknowledgement:
17  *        This product includes software developed or owned by Caldera
18  *        International, Inc.
19  * Neither the name of Caldera International, Inc. nor the names of other
20  * contributors may be used to endorse or promote products derived from
21  * this software without specific prior written permission.
22  *
23  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
28  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 /* INTERMEDIATE CODE GENERATION FOR S C JOHNSON C COMPILERS */
37 /* NEW VERSION USING BINARY POLISH POSTFIX INTERMEDIATE */
38 
39 #include <unistd.h>
40 #include <string.h>
41 
42 #include "defines.h"
43 #include "defs.h"
44 
45 #include "scjdefs.h"
46 
47 LOCAL struct bigblock *putcall(struct bigblock *p);
48 LOCAL NODE *putmnmx(struct bigblock *p);
49 LOCAL NODE *putmem(bigptr, int, ftnint);
50 LOCAL NODE *putaddr(struct bigblock *, int);
51 LOCAL void putct1(bigptr, struct bigblock *, struct bigblock *, int *);
52 LOCAL int ncat(bigptr p);
53 LOCAL NODE *putcat(struct bigblock *, bigptr);
54 LOCAL NODE *putchcmp(struct bigblock *p);
55 LOCAL NODE *putcheq(struct bigblock *p);
56 LOCAL NODE *putcxcmp(struct bigblock *p);
57 LOCAL struct bigblock *putcx1(bigptr);
58 LOCAL NODE *putcxop(bigptr p);
59 LOCAL struct bigblock *putcxeq(struct bigblock *p);
60 LOCAL NODE *putpower(bigptr p);
61 LOCAL NODE *putop(bigptr p);
62 LOCAL NODE *putchop(bigptr p);
63 LOCAL struct bigblock *putch1(bigptr);
64 LOCAL struct bigblock *intdouble(struct bigblock *);
65 
66 extern int ops2[];
67 extern int types2[];
68 static char *inproc;
69 static NODE *callval; /* to get return value right */
70 extern int negrel[];
71 
72 #define XINT(z)     ONEOF(z, MSKINT|MSKCHAR)
73 #define   P2TYPE(x) (types2[(x)->vtype])
74 #define   P2OP(x)             (ops2[(x)->b_expr.opcode])
75 
76 static void
sendp2(NODE * p)77 sendp2(NODE *p)
78 {
79           extern int thisline;
80 
81           p2tree(p);
82           thisline = lineno;
83           if (debugflag)
84                     fwalk(p, e2print, 0);
85           pass2_compile(ipnode(p));
86 }
87 
88 static NODE *
putassign(bigptr lp,bigptr rp)89 putassign(bigptr lp, bigptr rp)
90 {
91           return putx(fixexpr(mkexpr(OPASSIGN, lp, rp)));
92 }
93 
94 
95 void
puthead(char * s)96 puthead(char *s)
97 {
98           struct interpass_prolog *ipp = ckalloc(sizeof(struct interpass_prolog));
99           int olbl, lbl1, lbl2;
100           unsigned int i;
101 
102           if (s == NULL)
103                     return;
104           if (inproc)
105                     fatal1("puthead %s in procedure", s);
106           inproc = s;
107           olbl = lastlabno;
108           lbl1 = newlabel();
109           lbl2 = newlabel();
110 
111           for (i = 0; i < NIPPREGS; i++)
112                     ipp->ipp_regs[i] = 0;         /* no regs used yet */
113           ipp->ipp_autos = 0;           /* no autos used yet */
114           ipp->ipp_name = copys(s);               /* function name */
115           ipp->ipp_type = INT;                    /* type not known yet? */
116           ipp->ipp_vis = 1;             /* always visible */
117           ipp->ip_tmpnum = 0;                     /* no temp nodes used in F77 yet */
118           ipp->ip_lblnum = olbl;                  /* # used labels so far */
119           ipp->ipp_ip.ip_lbl = lbl1;    /* first label, for optim */
120           ipp->ipp_ip.type = IP_PROLOG;
121           pass2_compile((struct interpass *)ipp);
122 
123 }
124 
125 /* It is necessary to precede each procedure with a "left bracket"
126  * line that tells pass 2 how many register variables and how
127  * much automatic space is required for the function.  This compiler
128  * does not know how much automatic space is needed until the
129  * entire procedure has been processed.  Therefore, "puthead"
130  * is called at the begining to record the current location in textfile,
131  * then to put out a placeholder left bracket line.  This procedure
132  * repositions the file and rewrites that line, then puts the
133  * file pointer back to the end of the file.
134  */
135 
136 void
putbracket()137 putbracket()
138 {
139           struct interpass_prolog *ipp = ckalloc(sizeof(struct interpass_prolog));
140           unsigned int i;
141 
142           if (inproc == 0)
143                     fatal1("puteof outside procedure");
144           for (i = 0; i < NIPPREGS; i++)
145                     ipp->ipp_regs[i] = 0;
146           ipp->ipp_autos = autoleng;
147           ipp->ipp_name = copys(inproc);
148           ipp->ipp_type = INT; /* XXX should set the correct type */
149           ipp->ipp_vis = 1;
150           ipp->ip_tmpnum = 0;
151           ipp->ip_lblnum = lastlabno;
152           ipp->ipp_ip.ip_lbl = retlabel;
153           ipp->ipp_ip.type = IP_EPILOG;
154           printf("\t.text\n"); /* XXX */
155           pass2_compile((struct interpass *)ipp);
156           inproc = 0;
157 }
158 
159 
160 
161 void
putrbrack(int k)162 putrbrack(int k)
163 {
164 }
165 
166 
167 void
puteof()168 puteof()
169 {
170 }
171 
172 
173 /* put out code for if( ! p) goto l  */
174 void
putif(bigptr p,int l)175 putif(bigptr p, int l)
176 {
177           NODE *p1;
178           int k;
179 
180           if( ( k = (p = fixtype(p))->vtype) != TYLOGICAL) {
181                     if(k != TYERROR)
182                               err("non-logical expression in IF statement");
183                     frexpr(p);
184           } else {
185                     p1 = putex1(p);
186                     if (p1->n_op == EQ && p1->n_right->n_op == ICON &&
187                         p1->n_right->n_lval == 0 && logop(p1->n_left->n_op)) {
188                               /* created by OPOR */
189                               NODE *q = p1->n_left;
190                               q->n_op = negrel[q->n_op - EQ];
191                               nfree(p1->n_right);
192                               nfree(p1);
193                               p1 = q;
194                     }
195                     if (logop(p1->n_op) == 0)
196                               p1 = mkbinode(NE, p1, mklnode(ICON, 0, 0, INT), INT);
197                     if (p1->n_left->n_op == ICON) {
198                               /* change constants to right */
199                               NODE *p2 = p1->n_left;
200                               p1->n_left = p1->n_right;
201                               p1->n_right = p2;
202                               if (p1->n_op != EQ && p1->n_op != NE)
203                                         p1->n_op = negrel[p1->n_op - EQ];
204                     }
205                     p1->n_op = negrel[p1->n_op - EQ];
206                     p1 = mkbinode(CBRANCH, p1, mklnode(ICON, l, 0, INT), INT);
207                     sendp2(p1);
208           }
209 }
210 
211 /* Arithmetic IF  */
212 void
prarif(bigptr p,int neg,int zer,int pos)213 prarif(bigptr p, int neg, int zer, int pos)
214 {
215           bigptr x1 = fmktemp(p->vtype, NULL);
216 
217           putexpr(mkexpr(OPASSIGN, cpexpr(x1), p));
218           putif(mkexpr(OPGE, cpexpr(x1), MKICON(0)), neg);
219           putif(mkexpr(OPLE, x1, MKICON(0)), pos);
220           putgoto(zer);
221 }
222 
223 /* put out code for  goto l   */
224 void
putgoto(int label)225 putgoto(int label)
226 {
227           NODE *p;
228 
229           p = mkunode(GOTO, mklnode(ICON, label, 0, INT), 0, INT);
230           sendp2(p);
231 }
232 
233 
234 /* branch to address constant or integer variable */
235 void
putbranch(struct bigblock * q)236 putbranch(struct bigblock *q)
237 {
238           NODE *p;
239 
240           p = mkunode(GOTO, putex1(q), 0, INT);
241           sendp2(p);
242 }
243 
244 /*
245  * put out label l: in text segment
246  */
247 void
putlabel(int label)248 putlabel(int label)
249 {
250           struct interpass *ip = ckalloc(sizeof(struct interpass));
251 
252           ip->type = IP_DEFLAB;
253           ip->lineno = lineno;
254           ip->ip_lbl = label;
255           pass2_compile(ip);
256 }
257 
258 
259 /*
260  * Called from inner routines.  Generates a NODE tree and writes it out.
261  */
262 void
putexpr(bigptr q)263 putexpr(bigptr q)
264 {
265           NODE *p;
266           p = putex1(q);
267           sendp2(p);
268 }
269 
270 
271 
272 void
putcmgo(bigptr x,int nlab,struct labelblock * labels[])273 putcmgo(bigptr x, int nlab, struct labelblock *labels[])
274 {
275           bigptr y;
276           int i;
277 
278           if (!ISINT(x->vtype)) {
279                     execerr("computed goto index must be integer", NULL);
280                     return;
281           }
282 
283           y = fmktemp(x->vtype, NULL);
284           putexpr(mkexpr(OPASSIGN, cpexpr(y), x));
285 #ifdef notyet /* target-specific computed goto */
286           vaxgoto(y, nlab, labels);
287 #else
288           /*
289            * Primitive implementation, should use table here.
290            */
291           for(i = 0 ; i < nlab ; ++i)
292                     putif(mkexpr(OPNE, cpexpr(y), MKICON(i+1)), labels[i]->labelno);
293           frexpr(y);
294 #endif
295 }
296 
297 /*
298  * Convert a f77 tree statement to something that looks like a
299  * pcc expression tree.
300  */
301 NODE *
putx(bigptr q)302 putx(bigptr q)
303 {
304           struct bigblock *x1;
305           NODE *p = NULL; /* XXX */
306           int opc;
307           int type, k;
308 
309 #ifdef PCC_DEBUG
310           if (tflag) {
311                     printf("putx %p\n", q);
312                     fprint(q, 0);
313           }
314 #endif
315 
316           switch(q->tag) {
317           case TERROR:
318                     ckfree(q);
319                     break;
320 
321           case TCONST:
322                     switch(type = q->vtype) {
323                               case TYLOGICAL:
324                                         type = tyint;
325                               case TYLONG:
326                               case TYSHORT:
327                                         p = mklnode(ICON, q->b_const.fconst.ci,
328                                             0, types2[type]);
329                                         ckfree(q);
330                                         break;
331 
332                               case TYADDR:
333                                         p = mklnode(ICON, 0, 0, types2[type]);
334                                         p->n_name = copys(memname(STGCONST,
335                                             (int)q->b_const.fconst.ci));
336                                         ckfree(q);
337                                         break;
338 
339                               default:
340                                         p = putx(putconst(q));
341                                         break;
342                               }
343                     break;
344 
345           case TEXPR:
346                     switch(opc = q->b_expr.opcode) {
347                               case OPCALL:
348                               case OPCCALL:
349                                         if( ISCOMPLEX(q->vtype) )
350                                                   p = putcxop(q);
351                                         else {
352                                                   putcall(q);
353                                                   p = callval;
354                                         }
355                                         break;
356 
357                               case OPMIN:
358                               case OPMAX:
359                                         p = putmnmx(q);
360                                         break;
361 
362                               case OPASSIGN:
363                                         if (ISCOMPLEX(q->b_expr.leftp->vtype) ||
364                                             ISCOMPLEX(q->b_expr.rightp->vtype)) {
365                                                   frexpr(putcxeq(q));
366                                         } else if (ISCHAR(q))
367                                                   p = putcheq(q);
368                                         else
369                                                   goto putopp;
370                                         break;
371 
372                               case OPEQ:
373                               case OPNE:
374                                         if (ISCOMPLEX(q->b_expr.leftp->vtype) ||
375                                             ISCOMPLEX(q->b_expr.rightp->vtype) ) {
376                                                   p = putcxcmp(q);
377                                                   break;
378                                         }
379                               case OPLT:
380                               case OPLE:
381                               case OPGT:
382                               case OPGE:
383                                         if(ISCHAR(q->b_expr.leftp))
384                                                   p = putchcmp(q);
385                                         else
386                                                   goto putopp;
387                                         break;
388 
389                               case OPPOWER:
390                                         p = putpower(q);
391                                         break;
392 
393                               case OPSTAR:
394                                         /*   m * (2**k) -> m<<k   */
395                                         if (XINT(q->b_expr.leftp->vtype) &&
396                                             ISICON(q->b_expr.rightp) &&
397                                             ((k = flog2(q->b_expr.rightp->b_const.fconst.ci))>0) ) {
398                                                   q->b_expr.opcode = OPLSHIFT;
399                                                   frexpr(q->b_expr.rightp);
400                                                   q->b_expr.rightp = MKICON(k);
401                                                   goto putopp;
402                                         }
403 
404                               case OPMOD:
405                                         goto putopp;
406                               case OPPLUS:
407                               case OPMINUS:
408                               case OPSLASH:
409                               case OPNEG:
410                                         if( ISCOMPLEX(q->vtype) )
411                                                   p = putcxop(q);
412                                         else
413                                                   goto putopp;
414                                         break;
415 
416                               case OPCONV:
417                                         if( ISCOMPLEX(q->vtype) )
418                                                   p = putcxop(q);
419                                         else if (ISCOMPLEX(q->b_expr.leftp->vtype)) {
420                                                   p = putx(mkconv(q->vtype,
421                                                       realpart(putcx1(q->b_expr.leftp))));
422                                                   ckfree(q);
423                                         } else
424                                                   goto putopp;
425                                         break;
426 
427                               case OPAND:
428                                         /* Create logical AND */
429                                         x1 = fmktemp(TYLOGICAL, NULL);
430                                         putexpr(mkexpr(OPASSIGN, cpexpr(x1),
431                                             mklogcon(0)));
432                                         k = newlabel();
433                                         putif(q->b_expr.leftp, k);
434                                         putif(q->b_expr.rightp, k);
435                                         putexpr(mkexpr(OPASSIGN, cpexpr(x1),
436                                             mklogcon(1)));
437                                         putlabel(k);
438                                         p = putx(x1);
439                                         break;
440 
441                               case OPNOT: /* Logical NOT */
442                                         x1 = fmktemp(TYLOGICAL, NULL);
443                                         putexpr(mkexpr(OPASSIGN, cpexpr(x1),
444                                             mklogcon(1)));
445                                         k = newlabel();
446                                         putif(q->b_expr.leftp, k);
447                                         putexpr(mkexpr(OPASSIGN, cpexpr(x1),
448                                             mklogcon(0)));
449                                         putlabel(k);
450                                         p = putx(x1);
451                                         break;
452 
453                               case OPOR: /* Create logical OR */
454                                         x1 = fmktemp(TYLOGICAL, NULL);
455                                         putexpr(mkexpr(OPASSIGN, cpexpr(x1),
456                                             mklogcon(1)));
457                                         k = newlabel();
458                                         putif(mkexpr(OPEQ, q->b_expr.leftp,
459                                             mklogcon(0)), k);
460                                         putif(mkexpr(OPEQ, q->b_expr.rightp,
461                                             mklogcon(0)), k);
462                                         putexpr(mkexpr(OPASSIGN, cpexpr(x1),
463                                             mklogcon(0)));
464                                         putlabel(k);
465                                         p = putx(x1);
466                                         break;
467 
468                               case OPCOMMA:
469                                         for (x1 = q; x1->b_expr.opcode == OPCOMMA;
470                                             x1 = x1->b_expr.leftp)
471                                                   putexpr(x1->b_expr.rightp);
472                                         p = putx(x1);
473                                         break;
474 
475                               case OPEQV:
476                               case OPNEQV:
477                               case OPADDR:
478                               case OPBITOR:
479                               case OPBITAND:
480                               case OPBITXOR:
481                               case OPBITNOT:
482                               case OPLSHIFT:
483                               case OPRSHIFT:
484                     putopp:
485                                         p = putop(q);
486                                         break;
487 
488                               default:
489                                         fatal1("putx: invalid opcode %d", opc);
490                               }
491                     break;
492 
493           case TADDR:
494                     p = putaddr(q, YES);
495                     break;
496 
497           default:
498                     fatal1("putx: impossible tag %d", q->tag);
499           }
500           return p;
501 }
502 
503 LOCAL NODE *
putop(bigptr q)504 putop(bigptr q)
505 {
506           NODE *p;
507           int k;
508           bigptr lp, tp;
509           int pt, lt;
510 
511 #ifdef PCC_DEBUG
512           if (tflag) {
513                     printf("putop %p\n", q);
514                     fprint(q, 0);
515           }
516 #endif
517           switch(q->b_expr.opcode) { /* check for special cases and rewrite */
518           case OPCONV:
519                     pt = q->vtype;
520                     lp = q->b_expr.leftp;
521                     lt = lp->vtype;
522                     while(q->tag==TEXPR && q->b_expr.opcode==OPCONV &&
523                          ((ISREAL(pt)&&ISREAL(lt)) ||
524                               (XINT(pt)&&(ONEOF(lt,MSKINT|MSKADDR))) )) {
525                               if(lp->tag != TEXPR) {
526                                         if(pt==TYINT && lt==TYLONG)
527                                                   break;
528                                         if(lt==TYINT && pt==TYLONG)
529                                                   break;
530                               }
531                               ckfree(q);
532                               q = lp;
533                               pt = lt;
534                               lp = q->b_expr.leftp;
535                               lt = lp->vtype;
536                     }
537                     if(q->tag==TEXPR && q->b_expr.opcode==OPCONV)
538                               break;
539                     p = putx(q);
540                     return p;
541 
542           case OPADDR:
543                     lp = q->b_expr.leftp;
544                     if(lp->tag != TADDR) {
545                               tp = fmktemp(lp->vtype, lp->vleng);
546                               p = putx(mkexpr(OPASSIGN, cpexpr(tp), lp));
547                               sendp2(p);
548                               lp = tp;
549                     }
550                     p = putaddr(lp, NO);
551                     ckfree(q);
552                     return p;
553           }
554 
555           if ((k = ops2[q->b_expr.opcode]) <= 0)
556                     fatal1("putop: invalid opcode %d (%d)", q->b_expr.opcode, k);
557           p = putx(q->b_expr.leftp);
558           if(q->b_expr.rightp)
559                     p = mkbinode(k, p, putx(q->b_expr.rightp), types2[q->vtype]);
560           else
561                     p = mkunode(k, p, 0, types2[q->vtype]);
562 
563           if(q->vleng)
564                     frexpr(q->vleng);
565           ckfree(q);
566           return p;
567 }
568 
569 /*
570  * Put return values into correct register.
571  */
572 void
putforce(int t,bigptr p)573 putforce(int t, bigptr p)
574 {
575           NODE *p1;
576 
577           p = mkconv(t, fixtype(p));
578           p1 = putx(p);
579           p1 = mkunode(FORCE, p1, 0,
580                     (t==TYSHORT ? SHORT : (t==TYLONG ? LONG : LDOUBLE)));
581           sendp2(p1);
582 }
583 
584 LOCAL NODE *
putpower(bigptr p)585 putpower(bigptr p)
586 {
587           NODE *p3;
588           bigptr base;
589           struct bigblock *t1, *t2;
590           ftnint k = 0; /* XXX gcc */
591           int type;
592 
593           if(!ISICON(p->b_expr.rightp) ||
594               (k = p->b_expr.rightp->b_const.fconst.ci)<2)
595                     fatal("putpower: bad call");
596           base = p->b_expr.leftp;
597           type = base->vtype;
598           t1 = fmktemp(type, NULL);
599           t2 = NULL;
600           p3 = putassign(cpexpr(t1), cpexpr(base) );
601           sendp2(p3);
602 
603           for( ; (k&1)==0 && k>2 ; k>>=1 ) {
604                     p3 = putassign(cpexpr(t1),
605                         mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)));
606                     sendp2(p3);
607           }
608 
609           if(k == 2)
610                     p3 = putx(mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)));
611           else {
612                     t2 = fmktemp(type, NULL);
613                     p3 = putassign(cpexpr(t2), cpexpr(t1));
614                     sendp2(p3);
615 
616                     for(k>>=1 ; k>1 ; k>>=1) {
617                               p3 = putassign(cpexpr(t1),
618                                   mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)));
619                               sendp2(p3);
620                               if(k & 1) {
621                                         p3 = putassign(cpexpr(t2),
622                                             mkexpr(OPSTAR, cpexpr(t2), cpexpr(t1)));
623                                         sendp2(p3);
624                               }
625                     }
626                     p3 = putx( mkexpr(OPSTAR, cpexpr(t2),
627                     mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) ));
628           }
629           frexpr(t1);
630           if(t2)
631                     frexpr(t2);
632           frexpr(p);
633           return p3;
634 }
635 
636 LOCAL struct bigblock *
intdouble(struct bigblock * p)637 intdouble(struct bigblock *p)
638 {
639           struct bigblock *t;
640 
641           t = fmktemp(TYDREAL, NULL);
642 
643           sendp2(putassign(cpexpr(t), p));
644           return(t);
645 }
646 
647 LOCAL struct bigblock *
putcxeq(struct bigblock * q)648 putcxeq(struct bigblock *q)
649 {
650           struct bigblock *lp, *rp;
651 
652           lp = putcx1(q->b_expr.leftp);
653           rp = putcx1(q->b_expr.rightp);
654           sendp2(putassign(realpart(lp), realpart(rp)));
655           if( ISCOMPLEX(q->vtype) ) {
656                     sendp2(putassign(imagpart(lp), imagpart(rp)));
657           }
658           frexpr(rp);
659           ckfree(q);
660           return(lp);
661 }
662 
663 
664 
665 LOCAL NODE *
putcxop(bigptr q)666 putcxop(bigptr q)
667 {
668           NODE *p;
669 
670           p = putaddr(putcx1(q), NO);
671           return p;
672 }
673 
674 LOCAL struct bigblock *
putcx1(bigptr qq)675 putcx1(bigptr qq)
676 {
677           struct bigblock *q, *lp, *rp;
678           register struct bigblock *resp;
679           NODE *p;
680           int opcode;
681           int ltype, rtype;
682 
683           ltype = rtype = 0; /* XXX gcc */
684           if(qq == NULL)
685                     return(NULL);
686 
687           switch(qq->tag) {
688           case TCONST:
689                     if( ISCOMPLEX(qq->vtype) )
690                               qq = putconst(qq);
691                     return( qq );
692 
693           case TADDR:
694                     if( ! addressable(qq) ) {
695                               resp = fmktemp(tyint, NULL);
696                               p = putassign( cpexpr(resp), qq->b_addr.memoffset );
697                               sendp2(p);
698                               qq->b_addr.memoffset = resp;
699                     }
700                     return( qq );
701 
702           case TEXPR:
703                     if( ISCOMPLEX(qq->vtype) )
704                               break;
705                     resp = fmktemp(TYDREAL, NO);
706                     p = putassign( cpexpr(resp), qq);
707                     sendp2(p);
708                     return(resp);
709 
710           default:
711                     fatal1("putcx1: bad tag %d", qq->tag);
712           }
713 
714           opcode = qq->b_expr.opcode;
715           if(opcode==OPCALL || opcode==OPCCALL) {
716                     q = putcall(qq);
717                     sendp2(callval);
718                     return(q);
719           } else if(opcode == OPASSIGN) {
720                     return( putcxeq(qq) );
721           }
722 
723           resp = fmktemp(qq->vtype, NULL);
724           if((lp = putcx1(qq->b_expr.leftp) ))
725                     ltype = lp->vtype;
726           if((rp = putcx1(qq->b_expr.rightp) ))
727                     rtype = rp->vtype;
728 
729           switch(opcode) {
730           case OPCOMMA:
731                     frexpr(resp);
732                     resp = rp;
733                     rp = NULL;
734                     break;
735 
736           case OPNEG:
737                     p = putassign(realpart(resp),
738                         mkexpr(OPNEG, realpart(lp), NULL));
739                     sendp2(p);
740                     p = putassign(imagpart(resp),
741                         mkexpr(OPNEG, imagpart(lp), NULL));
742                     sendp2(p);
743                     break;
744 
745           case OPPLUS:
746           case OPMINUS:
747                     p = putassign( realpart(resp),
748                         mkexpr(opcode, realpart(lp), realpart(rp) ));
749                     sendp2(p);
750                     if(rtype < TYCOMPLEX) {
751                               p = putassign(imagpart(resp), imagpart(lp) );
752                     } else if(ltype < TYCOMPLEX) {
753                               if(opcode == OPPLUS)
754                                         p = putassign( imagpart(resp), imagpart(rp) );
755                               else
756                                         p = putassign( imagpart(resp),
757                                             mkexpr(OPNEG, imagpart(rp), NULL) );
758                     } else
759                               p = putassign( imagpart(resp),
760                                   mkexpr(opcode, imagpart(lp), imagpart(rp) ));
761                     sendp2(p);
762                     break;
763 
764           case OPSTAR:
765                     if(ltype < TYCOMPLEX) {
766                               if( ISINT(ltype) )
767                                         lp = intdouble(lp);
768                               p = putassign( realpart(resp),
769                                   mkexpr(OPSTAR, cpexpr(lp), realpart(rp) ));
770                               sendp2(p);
771                               p = putassign( imagpart(resp),
772                                   mkexpr(OPSTAR, cpexpr(lp), imagpart(rp) ));
773                     } else if(rtype < TYCOMPLEX) {
774                               if( ISINT(rtype) )
775                                         rp = intdouble(rp);
776                               p = putassign( realpart(resp),
777                                   mkexpr(OPSTAR, cpexpr(rp), realpart(lp) ));
778                               sendp2(p);
779                               p = putassign( imagpart(resp),
780                                   mkexpr(OPSTAR, cpexpr(rp), imagpart(lp) ));
781                     } else {
782                               p = putassign( realpart(resp), mkexpr(OPMINUS,
783                                         mkexpr(OPSTAR, realpart(lp), realpart(rp)),
784                                         mkexpr(OPSTAR, imagpart(lp), imagpart(rp)) ));
785                               sendp2(p);
786                               p = putassign( imagpart(resp), mkexpr(OPPLUS,
787                                         mkexpr(OPSTAR, realpart(lp), imagpart(rp)),
788                                         mkexpr(OPSTAR, imagpart(lp), realpart(rp)) ));
789                     }
790                     sendp2(p);
791                     break;
792 
793           case OPSLASH:
794                     /* fixexpr has already replaced all divisions
795                      * by a complex by a function call
796                      */
797                     if( ISINT(rtype) )
798                               rp = intdouble(rp);
799                     p = putassign( realpart(resp),
800                         mkexpr(OPSLASH, realpart(lp), cpexpr(rp)) );
801                     sendp2(p);
802                     p = putassign( imagpart(resp),
803                         mkexpr(OPSLASH, imagpart(lp), cpexpr(rp)) );
804                     sendp2(p);
805                     break;
806 
807           case OPCONV:
808                     p = putassign( realpart(resp), realpart(lp) );
809                     if( ISCOMPLEX(lp->vtype) )
810                               q = imagpart(lp);
811                     else if(rp != NULL)
812                               q = realpart(rp);
813                     else
814                               q = mkrealcon(TYDREAL, 0.0);
815                     sendp2(p);
816                     p = putassign( imagpart(resp), q);
817                     sendp2(p);
818                     break;
819 
820           default:
821                     fatal1("putcx1 of invalid opcode %d", opcode);
822           }
823 
824           frexpr(lp);
825           frexpr(rp);
826           ckfree(qq);
827           return(resp);
828 }
829 
830 
831 LOCAL NODE *
putcxcmp(struct bigblock * p)832 putcxcmp(struct bigblock *p)
833 {
834           NODE *p1;
835           int opcode;
836           struct bigblock *lp, *rp;
837           struct bigblock *q;
838 
839           opcode = p->b_expr.opcode;
840           lp = putcx1(p->b_expr.leftp);
841           rp = putcx1(p->b_expr.rightp);
842 
843           q = mkexpr( opcode==OPEQ ? OPAND : OPOR ,
844               mkexpr(opcode, realpart(lp), realpart(rp)),
845               mkexpr(opcode, imagpart(lp), imagpart(rp)) );
846           p1 = putx( fixexpr(q) );
847 
848           ckfree(lp);
849           ckfree(rp);
850           ckfree(p);
851           return p1;
852 }
853 
854 LOCAL struct bigblock *
putch1(bigptr p)855 putch1(bigptr p)
856 {
857           struct bigblock *t;
858 
859           switch(p->tag) {
860           case TCONST:
861                     return( putconst(p) );
862 
863           case TADDR:
864                     return(p);
865 
866           case TEXPR:
867                     switch(p->b_expr.opcode) {
868                               case OPCALL:
869                               case OPCCALL:
870                                         t = putcall(p);
871                                         sendp2(callval);
872                                         break;
873 
874                               case OPCONCAT:
875                                         t = fmktemp(TYCHAR, cpexpr(p->vleng) );
876                                         sendp2(putcat( cpexpr(t), p ));
877                                         break;
878 
879                               case OPCONV:
880                                         if(!ISICON(p->vleng) ||
881                                             p->vleng->b_const.fconst.ci!=1
882                                            || ! XINT(p->b_expr.leftp->vtype) )
883                                                   fatal("putch1: bad character conversion");
884                                         t = fmktemp(TYCHAR, MKICON(1) );
885                                         sendp2(putassign( cpexpr(t), p));
886                                         break;
887                               default:
888                                         fatal1("putch1: invalid opcode %d", p->b_expr.opcode);
889                                         t = NULL; /* XXX gcc */
890                               }
891                     return(t);
892 
893           default:
894                     fatal1("putch1: bad tag %d", p->tag);
895           }
896 /* NOTREACHED */
897 return NULL; /* XXX gcc */
898 }
899 
900 
901 
902 
903 LOCAL NODE *
putchop(bigptr p)904 putchop(bigptr p)
905 {
906           NODE *p1;
907 
908           p1 = putaddr( putch1(p) , NO );
909           return p1;
910 }
911 
912 
913 /*
914  * Assign a character to another.
915  */
916 LOCAL NODE *
putcheq(struct bigblock * p)917 putcheq(struct bigblock *p)
918 {
919           NODE *p1, *p2, *p3;
920 
921           if( p->b_expr.rightp->tag==TEXPR &&
922               p->b_expr.rightp->b_expr.opcode==OPCONCAT )
923                     p3 = putcat(p->b_expr.leftp, p->b_expr.rightp);
924           else if( ISONE(p->b_expr.leftp->vleng) &&
925               ISONE(p->b_expr.rightp->vleng) ) {
926                     p1 = putaddr( putch1(p->b_expr.leftp) , YES );
927                     p2 = putaddr( putch1(p->b_expr.rightp) , YES );
928                     p3 = mkbinode(ASSIGN, p1, p2, CHAR);
929           } else
930                     p3 = putx(call2(TYINT, "s_copy",
931                         p->b_expr.leftp, p->b_expr.rightp));
932 
933           frexpr(p->vleng);
934           ckfree(p);
935           return p3;
936 }
937 
938 
939 
940 /*
941  * Compare character(s) code.
942  */
943 LOCAL NODE *
putchcmp(struct bigblock * p)944 putchcmp(struct bigblock *p)
945 {
946           NODE *p1, *p2, *p3;
947 
948           if(ISONE(p->b_expr.leftp->vleng) && ISONE(p->b_expr.rightp->vleng) ) {
949                     p1 = putaddr( putch1(p->b_expr.leftp) , YES );
950                     p2 = putaddr( putch1(p->b_expr.rightp) , YES );
951                     p3 = mkbinode(ops2[p->b_expr.opcode], p1, p2, CHAR);
952                     ckfree(p);
953           } else {
954                     p->b_expr.leftp = call2(TYINT,"s_cmp",
955                         p->b_expr.leftp, p->b_expr.rightp);
956                     p->b_expr.rightp = MKICON(0);
957                     p3 = putop(p);
958           }
959           return p3;
960 }
961 
962 LOCAL NODE *
putcat(bigptr lhs,bigptr rhs)963 putcat(bigptr lhs, bigptr rhs)
964 {
965           NODE *p3;
966           int n;
967           struct bigblock *lp, *cp;
968 
969           n = ncat(rhs);
970           lp = mktmpn(n, TYLENG, NULL);
971           cp = mktmpn(n, TYADDR, NULL);
972 
973           n = 0;
974           putct1(rhs, lp, cp, &n);
975 
976           p3 = putx( call4(TYSUBR, "s_cat", lhs, cp, lp, MKICON(n) ) );
977           return p3;
978 }
979 
980 LOCAL int
ncat(bigptr p)981 ncat(bigptr p)
982 {
983           if(p->tag==TEXPR && p->b_expr.opcode==OPCONCAT)
984                     return( ncat(p->b_expr.leftp) + ncat(p->b_expr.rightp) );
985           else
986                     return(1);
987 }
988 
989 LOCAL void
putct1(bigptr q,bigptr lp,bigptr cp,int * ip)990 putct1(bigptr q, bigptr lp, bigptr cp, int *ip)
991 {
992           NODE *p;
993           int i;
994           struct bigblock *lp1, *cp1;
995 
996           if(q->tag==TEXPR && q->b_expr.opcode==OPCONCAT) {
997                     putct1(q->b_expr.leftp, lp, cp, ip);
998                     putct1(q->b_expr.rightp, lp, cp , ip);
999                     frexpr(q->vleng);
1000                     ckfree(q);
1001           } else {
1002                     i = (*ip)++;
1003                     lp1 = cpexpr(lp);
1004                     lp1->b_addr.memoffset =
1005                         mkexpr(OPPLUS, lp1->b_addr.memoffset, MKICON(i*FSZLENG));
1006                     cp1 = cpexpr(cp);
1007                     cp1->b_addr.memoffset =
1008                         mkexpr(OPPLUS, cp1->b_addr.memoffset, MKICON(i*FSZADDR));
1009                     p = putassign( lp1, cpexpr(q->vleng) );
1010                     sendp2(p);
1011                     p = putassign( cp1, addrof(putch1(q)) );
1012                     sendp2(p);
1013           }
1014 }
1015 
1016 /*
1017  * Create a tree that can later be converted to an OREG.
1018  */
1019 static NODE *
oregtree(int off,int reg,int type)1020 oregtree(int off, int reg, int type)
1021 {
1022           NODE *p, *q;
1023 
1024           p = mklnode(REG, 0, reg, INCREF(type));
1025           q = mklnode(ICON, off, 0, INT);
1026           return mkunode(UMUL, mkbinode(PLUS, p, q, INCREF(type)), 0, type);
1027 }
1028 
1029 static NODE *
putaddr(bigptr q,int indir)1030 putaddr(bigptr q, int indir)
1031 {
1032           int type, type2, funct;
1033           NODE *p, *p1, *p2;
1034           ftnint offset;
1035           bigptr offp;
1036 
1037           p = p1 = p2 = NULL; /* XXX */
1038 
1039           type = q->vtype;
1040           type2 = types2[type];
1041           funct = (q->vclass==CLPROC ? FTN<<TSHIFT : 0);
1042 
1043           offp = (q->b_addr.memoffset ? cpexpr(q->b_addr.memoffset) : NULL);
1044 
1045           offset = simoffset(&offp);
1046           if(offp)
1047                     offp = mkconv(TYINT, offp);
1048 
1049           switch(q->vstg) {
1050           case STGAUTO:
1051                     if(indir && !offp) {
1052                               p = oregtree(offset, AUTOREG, type2);
1053                               break;
1054                     }
1055 
1056                     if(!indir && !offp && !offset) {
1057                               p = mklnode(REG, 0, AUTOREG, INCREF(type2));
1058                               break;
1059                     }
1060 
1061                     p = mklnode(REG, 0, AUTOREG, INCREF(type2));
1062                     if(offp) {
1063                               p1 = putx(offp);
1064                               if(offset)
1065                                         p2 = mklnode(ICON, offset, 0, INT);
1066                     } else
1067                               p1 = mklnode(ICON, offset, 0, INT);
1068                     if (offp && offset)
1069                               p1 = mkbinode(PLUS, p1, p2, INCREF(type2));
1070                     p = mkbinode(PLUS, p, p1, INCREF(type2));
1071                     if (indir)
1072                               p = mkunode(UMUL, p, 0, type2);
1073                     break;
1074 
1075           case STGARG:
1076                     p = oregtree(ARGOFFSET + (ftnint)(q->b_addr.memno),
1077                         ARGREG, INCREF(type2)|funct);
1078 
1079                     if (offp)
1080                               p1 = putx(offp);
1081                     if (offset)
1082                               p2 = mklnode(ICON, offset, 0, INT);
1083                     if (offp && offset)
1084                               p1 = mkbinode(PLUS, p1, p2, INCREF(type2));
1085                     else if (offset)
1086                               p1 = p2;
1087                     if (offp || offset)
1088                               p = mkbinode(PLUS, p, p1, INCREF(type2));
1089                     if (indir)
1090                               p = mkunode(UMUL, p, 0, type2);
1091                     break;
1092 
1093           case STGLENG:
1094                     if(indir) {
1095                               p = oregtree(ARGOFFSET + (ftnint)(q->b_addr.memno),
1096                                   ARGREG, INCREF(type2)|funct);
1097                     } else    {
1098                               fatal1("faddrnode: STGLENG: fixme!");
1099 #if 0
1100                               p2op(P2PLUS, types2[TYLENG] | P2PTR );
1101                               p2reg(ARGREG, types2[TYLENG] | P2PTR );
1102                               p2icon( ARGOFFSET +
1103                                         (ftnint) (FUDGEOFFSET*p->b_addr.memno), P2INT);
1104 #endif
1105                     }
1106                     break;
1107 
1108 
1109           case STGBSS:
1110           case STGINIT:
1111           case STGEXT:
1112           case STGCOMMON:
1113           case STGEQUIV:
1114           case STGCONST:
1115                     if(offp) {
1116                               p1 = putx(offp);
1117                               p2 = putmem(q, ICON, offset);
1118                               p = mkbinode(PLUS, p1, p2, INCREF(type2));
1119                               if(indir)
1120                                         p = mkunode(UMUL, p, 0, type2);
1121                     } else
1122                               p = putmem(q, (indir ? NAME : ICON), offset);
1123                     break;
1124 
1125           case STGREG:
1126                     if(indir)
1127                               p = mklnode(REG, 0, q->b_addr.memno, type2);
1128                     else
1129                               fatal("attempt to take address of a register");
1130                     break;
1131 
1132           default:
1133                     fatal1("putaddr: invalid vstg %d", q->vstg);
1134           }
1135           frexpr(q);
1136           return p;
1137 }
1138 
1139 NODE *
putmem(bigptr q,int class,ftnint offset)1140 putmem(bigptr q, int class, ftnint offset)
1141 {
1142           NODE *p;
1143           int type2;
1144 
1145           type2 = types2[q->vtype];
1146           if(q->vclass == CLPROC)
1147                     type2 |= (FTN<<TSHIFT);
1148           if (class == ICON)
1149                     type2 |= PTR;
1150           p = mklnode(class, offset, 0, type2);
1151           p->n_name = copys(memname(q->vstg, q->b_addr.memno));
1152           return p;
1153 }
1154 
1155 
1156 
1157 LOCAL struct bigblock *
putcall(struct bigblock * qq)1158 putcall(struct bigblock *qq)
1159 {
1160           chainp arglist, charsp, cp;
1161           int n, first;
1162           struct bigblock *t;
1163           struct bigblock *q;
1164           struct bigblock *fval;
1165           int type, type2, ctype, indir;
1166           NODE *lp, *p1, *p2;
1167 
1168           lp = p2 = NULL; /* XXX */
1169 
1170           type2 = types2[type = qq->vtype];
1171           charsp = NULL;
1172           indir =  (qq->b_expr.opcode == OPCCALL);
1173           n = 0;
1174           first = YES;
1175 
1176           if(qq->b_expr.rightp) {
1177                     arglist = qq->b_expr.rightp->b_list.listp;
1178                     ckfree(qq->b_expr.rightp);
1179           } else
1180                     arglist = NULL;
1181 
1182           for(cp = arglist ; cp ; cp = cp->chain.nextp)
1183                     if(indir) {
1184                               ++n;
1185                     } else {
1186                               q = cp->chain.datap;
1187                               if(q->tag == TCONST)
1188                                         cp->chain.datap = q = putconst(q);
1189                               if( ISCHAR(q) ) {
1190                                         charsp = hookup(charsp,
1191                                             mkchain(cpexpr(q->vleng), 0) );
1192                                         n += 2;
1193                               } else if(q->vclass == CLPROC) {
1194                                         charsp = hookup(charsp,
1195                                             mkchain( MKICON(0) , 0));
1196                                         n += 2;
1197                               } else
1198                                         n += 1;
1199                     }
1200 
1201           if(type == TYCHAR) {
1202                     if( ISICON(qq->vleng) ) {
1203                               fval = fmktemp(TYCHAR, qq->vleng);
1204                               n += 2;
1205                     } else {
1206                               err("adjustable character function");
1207                               return NULL;
1208                     }
1209           } else if(ISCOMPLEX(type)) {
1210                     fval = fmktemp(type, NULL);
1211                     n += 1;
1212           } else
1213                     fval = NULL;
1214 
1215           ctype = (fval ? P2INT : type2);
1216           p1 = putaddr(qq->b_expr.leftp, NO);
1217 
1218           if(fval) {
1219                     first = NO;
1220                     lp = putaddr( cpexpr(fval), NO);
1221                     if(type==TYCHAR)
1222                               lp = mkbinode(CM, lp, putx(cpexpr(qq->vleng)), INT);
1223           }
1224 
1225           for(cp = arglist ; cp ; cp = cp->chain.nextp) {
1226                     q = cp->chain.datap;
1227                     if(q->tag==TADDR && (indir || q->vstg!=STGREG) )
1228                               p2 = putaddr(q, indir && q->vtype!=TYCHAR);
1229                     else if( ISCOMPLEX(q->vtype) )
1230                               p2 = putcxop(q);
1231                     else if (ISCHAR(q) ) {
1232                               p2 = putchop(q);
1233                     } else if( ! ISERROR(q) ) {
1234                               if(indir)
1235                                         p2 = putx(q);
1236                               else      {
1237                                         t = fmktemp(q->vtype, q->vleng);
1238                                         p2 = putassign( cpexpr(t), q );
1239                                         sendp2(p2);
1240                                         p2 = putaddr(t, NO);
1241                               }
1242                     }
1243                     if(first) {
1244                               first = NO;
1245                               lp = p2;
1246                     } else
1247                               lp = mkbinode(CM, lp, p2, INT);
1248           }
1249 
1250           if(arglist)
1251                     frchain(&arglist);
1252           for(cp = charsp ; cp ; cp = cp->chain.nextp) {
1253                     p2 = putx( mkconv(TYLENG,cp->chain.datap) );
1254                     lp = mkbinode(CM, lp, p2, INT);
1255           }
1256           frchain(&charsp);
1257           if (n > 0)
1258                     callval = mkbinode(CALL, p1, lp, ctype);
1259           else
1260                     callval = mkunode(UCALL, p1, 0, ctype);
1261           ckfree(qq);
1262           return(fval);
1263 }
1264 
1265 /*
1266  * Write out code to do min/max calculations.
1267  * Note that these operators may have multiple arguments in fortran.
1268  */
1269 LOCAL NODE *
putmnmx(struct bigblock * p)1270 putmnmx(struct bigblock *p)
1271 {
1272           NODE *n1, *n2;
1273           int op, type, lab;
1274           chainp p0, p1;
1275           struct bigblock *tp;
1276 
1277           type = p->vtype;
1278           op = (p->b_expr.opcode==OPMIN ? LT : GT );
1279           p0 = p->b_expr.leftp->b_list.listp;
1280           ckfree(p->b_expr.leftp);
1281           ckfree(p);
1282 
1283           /*
1284            * Store first value in a temporary, then compare it with
1285            * each following value and save that if needed.
1286            */
1287           tp = fmktemp(type, NULL);
1288           sendp2(putassign(cpexpr(tp), p0->chain.datap));
1289 
1290           for(p1 = p0->chain.nextp ; p1 ; p1 = p1->chain.nextp) {
1291                     n1 = putx(cpexpr(tp));
1292                     n2 = putx(cpexpr(p1->chain.datap));
1293                     lab = newlabel();
1294                     sendp2(mkbinode(CBRANCH, mkbinode(op, n1, n2, INT),
1295                         mklnode(ICON, lab, 0, INT), INT));
1296                     sendp2(putassign(cpexpr(tp), p1->chain.datap));
1297                     putlabel(lab);
1298           }
1299           return putx(tp);
1300 }
1301 
1302 ftnint
simoffset(bigptr * p0)1303 simoffset(bigptr *p0)
1304 {
1305           ftnint offset, prod;
1306           bigptr p, lp, rp;
1307 
1308           offset = 0;
1309           p = *p0;
1310           if(p == NULL)
1311                     return(0);
1312 
1313           if( ! ISINT(p->vtype) )
1314                     return(0);
1315 
1316           if(p->tag==TEXPR && p->b_expr.opcode==OPSTAR) {
1317                     lp = p->b_expr.leftp;
1318                     rp = p->b_expr.rightp;
1319                     if(ISICON(rp) && lp->tag==TEXPR &&
1320                         lp->b_expr.opcode==OPPLUS && ISICON(lp->b_expr.rightp)) {
1321                               p->b_expr.opcode = OPPLUS;
1322                               lp->b_expr.opcode = OPSTAR;
1323                               prod = rp->b_const.fconst.ci *
1324                                   lp->b_expr.rightp->b_const.fconst.ci;
1325                               lp->b_expr.rightp->b_const.fconst.ci =
1326                                   rp->b_const.fconst.ci;
1327                               rp->b_const.fconst.ci = prod;
1328                     }
1329           }
1330 
1331           if(p->tag==TEXPR && p->b_expr.opcode==OPPLUS &&
1332               ISICON(p->b_expr.rightp)) {
1333                     rp = p->b_expr.rightp;
1334                     lp = p->b_expr.leftp;
1335                     offset += rp->b_const.fconst.ci;
1336                     frexpr(rp);
1337                     ckfree(p);
1338                     *p0 = lp;
1339           }
1340 
1341           if(p->tag == TCONST) {
1342                     offset += p->b_const.fconst.ci;
1343                     frexpr(p);
1344                     *p0 = NULL;
1345           }
1346 
1347           return(offset);
1348 }
1349 
1350 /*
1351  * F77 uses ckalloc() (malloc) for NODEs.
1352  */
1353 NODE *
talloc()1354 talloc()
1355 {
1356           NODE *p = ckalloc(sizeof(NODE));
1357           p->n_name = "";
1358           return p;
1359 }
1360 
1361 #ifdef PCC_DEBUG
1362 static char *tagnam[] = {
1363  "NONE", "NAME", "CONST", "EXPR", "ADDR", "PRIM", "LIST", "IMPLDO", "ERROR",
1364 };
1365 static char *typnam[] = {
1366  "unknown", "addr", "short", "long", "real", "dreal", "complex", "dcomplex",
1367  "logical", "char", "subr", "error",
1368 };
1369 static char *classnam[] = {
1370  "unknown", "param", "var", "entry", "main", "block", "proc",
1371 };
1372 static char *stgnam[] = {
1373  "unknown", "arg", "auto", "bss", "init", "const", "intr", "stfunct",
1374  "common", "equiv", "reg", "leng",
1375 };
1376 
1377 
1378 /*
1379  * Print out a f77 tree, for diagnostic purposes.
1380  */
1381 void
fprint(bigptr p,int indx)1382 fprint(bigptr p, int indx)
1383 {
1384           extern char *ops[];
1385           int x = indx;
1386           bigptr lp, rp;
1387           struct chain *bp;
1388 
1389           if (p == NULL)
1390                     return;
1391 
1392           while (x >= 2) {
1393                     putchar('\t');
1394                     x -= 2;
1395           }
1396           if (x--)
1397                     printf("    " );
1398           printf("%p) %s, ", p, tagnam[p->tag]);
1399           if (p->vtype)
1400                     printf("type=%s, ", typnam[p->vtype]);
1401           if (p->vclass)
1402                     printf("class=%s, ", classnam[p->vclass]);
1403           if (p->vstg)
1404                     printf("stg=%s, ", stgnam[p->vstg]);
1405 
1406           lp = rp = NULL;
1407           switch (p->tag) {
1408           case TEXPR:
1409                     printf("OP %s\n", ops[p->b_expr.opcode]);
1410                     lp = p->b_expr.leftp;
1411                     rp = p->b_expr.rightp;
1412                     break;
1413           case TADDR:
1414                     printf("memno=%d\n", p->b_addr.memno);
1415                     lp = p->vleng;
1416                     rp = p->b_addr.memoffset;
1417                     break;
1418           case TCONST:
1419                     switch (p->vtype) {
1420                     case TYSHORT:
1421                     case TYLONG:
1422                     case TYLOGICAL:
1423                     case TYADDR:
1424                               printf("val=%ld\n", p->b_const.fconst.ci);
1425                               break;
1426                     case TYCHAR:
1427                               lp = p->vleng;
1428                               printf("\n");
1429                               break;
1430                     }
1431                     break;
1432           case TPRIM:
1433                     lp = p->b_prim.namep;
1434                     rp = p->b_prim.argsp;
1435                     printf("fcharp=%p, lcharp=%p\n", p->b_prim.fcharp, p->b_prim.lcharp);
1436                     break;
1437           case TNAME:
1438                     printf("name=%s\n", p->b_name.varname);
1439                     break;
1440           case TLIST:
1441                     printf("\n");
1442                     for (bp = &p->b_list.listp->chain; bp; bp = &bp->nextp->chain)
1443                               fprint(bp->datap, indx+1);
1444                     break;
1445           default:
1446                     printf("\n");
1447           }
1448 
1449           fprint(lp, indx+1);
1450           fprint(rp, indx+1);
1451 }
1452 #endif
1453