1 /* $Id: trees.c,v 1.23 2016/09/26 16:45:43 ragge Exp $ */
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
30 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
36 * Redistributions of source code and documentation must retain the above
37 * copyright notice, this list of conditions and the following disclaimer.
38 * Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditionsand the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed or owned by Caldera
45 * Neither the name of Caldera International, Inc. nor the names of other
46 * contributors may be used to endorse or promote products derived from
47 * this software without specific prior written permission.
49 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
50 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
54 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
58 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
59 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
63 * Some of the changes from 32V include:
64 * - Understand "void" as type.
65 * - Handle enums as ints everywhere.
66 * - Convert some C-specific ops into branches.
75 static void chkpun(NODE
*p
);
76 static int opact(NODE
*p
);
77 static int moditype(TWORD
);
78 static NODE
*strargs(NODE
*);
79 static void rmcops(NODE
*p
);
80 static NODE
*tymatch(NODE
*p
);
81 void putjops(NODE
*, void *);
82 static void p2tree(NODE
*);
83 static struct symtab
*findmember(struct symtab
*, char *);
84 int inftn
; /* currently between epilog/prolog */
86 static char *tnames
[] = {
107 "signed", /* pass1 */
112 "fcomplex", /* pass1 */
113 "dcomplex", /* pass1 */
114 "lcomplex", /* pass1 */
115 "enumty", /* pass1 */
119 /* some special actions, used in finding the type of nodes */
129 # define PTMATCH 02000
131 # define NCVTR 010000
132 # define PROML 020000 /* promote left operand */
136 NAME: rval>0 is stab index for external
137 rval<0 is -inlabel number
138 lval is offset in bits
139 ICON: lval has the value
140 rval has the STAB index, or - label number,
141 if a name whose address is in the constant
142 rval = NONAME means no name
143 REG: rval is reg. identification cookie
149 /* Have some defaults for most common targets */
150 #ifndef WORD_ADDRESSED
151 #define offcon(o,t,d,ap) xbcon((o/SZCHAR), NULL, INTPTR)
152 #define VBLOCK(p,b,t,d,a) buildtree(DIV, p, b)
153 #define MBLOCK(p,b,t,d,a) buildtree(MUL, p, b)
155 #define VBLOCK(p,b,t,d,a) block(PVCONV, p, b, t, d, a)
156 #define MBLOCK(p,b,t,d,a) block(PMCONV, p, b, t, d, a)
160 buildtree(int o
, NODE
*l
, NODE
*r
)
165 struct symtab
*sp
= NULL
; /* XXX gcc */
170 printf("buildtree(%s, %p, %p)\n", copst(o
), l
, r
);
171 if (l
) fwalk(l
, eprint
, 0);
172 if (r
) fwalk(r
, eprint
, 0);
177 /* check for constants */
179 if (o
== ANDAND
|| o
== OROR
|| o
== NOT
) {
180 if (l
->n_op
== FCON
) {
181 p
= bcon(!FLOAT_ISZERO(FCAST(l
->n_dcon
)));
185 if (o
!= NOT
&& r
->n_op
== FCON
) {
186 p
= bcon(!FLOAT_ISZERO(FCAST(r
->n_dcon
)));
192 if( opty
== UTYPE
&& l
->n_op
== ICON
){
199 if( conval( l
, o
, l
) ) return(l
);
202 } else if (o
== NOT
&& l
->n_op
== FCON
) {
203 l
= clocal(block(SCONV
, l
, NIL
, INT
, 0, 0));
204 } else if( o
== UMINUS
&& l
->n_op
== FCON
){
205 FLOAT_NEG(FCAST(l
->n_dcon
));
208 } else if( o
==QUEST
&&
209 (l
->n_op
==ICON
|| (l
->n_op
==NAME
&& ISARY(l
->n_type
)))) {
212 c
= 1; /* will become constant later */
215 walkf(r
->n_right
, putjops
, 0);
219 walkf(r
->n_left
, putjops
, 0);
225 } else if( opty
== BITYPE
&& l
->n_op
== ICON
&& r
->n_op
== ICON
){
235 * Do type propagation for simple types here.
236 * The constant value is correct anyway.
237 * Maybe this op shortcut should be removed?
239 if (l
->n_sp
== NULL
&& r
->n_sp
== NULL
&&
240 l
->n_type
< BTMASK
&& r
->n_type
< BTMASK
) {
241 if (l
->n_type
> r
->n_type
)
242 r
->n_type
= l
->n_type
;
244 l
->n_type
= r
->n_type
;
264 if (!ISPTR(l
->n_type
) && !ISPTR(r
->n_type
)) {
265 if( conval( l
, o
, r
) ) {
272 } else if (opty
== BITYPE
&& (l
->n_op
== FCON
|| l
->n_op
== ICON
) &&
273 (r
->n_op
== FCON
|| r
->n_op
== ICON
) && (o
== PLUS
|| o
== MINUS
||
274 o
== MUL
|| o
== DIV
|| (o
>= EQ
&& o
<= GT
) )) {
275 #define D(x) ((FLT *)x)
278 ((r
->n_op
== ICON
&& glval(r
) == 0) ||
279 (r
->n_op
== FCON
&& FLOAT_EQ(D(r
->n_dcon
), FLOAT_ZERO
))))
280 goto runtime
; /* HW dependent */
282 if (l
->n_op
== ICON
) {
283 if (!concast(l
, r
->n_type
))
284 cerror("fail cast const");
285 } else if (r
->n_op
== ICON
) {
286 if (!concast(r
, l
->n_type
))
287 cerror("fail cast const");
319 n
= FLOAT_EQ(D(l
->n_dcon
), D(r
->n_dcon
));
322 n
= FLOAT_NE(D(l
->n_dcon
), D(r
->n_dcon
));
325 n
= FLOAT_LE(D(l
->n_dcon
), D(r
->n_dcon
));
328 n
= FLOAT_LT(D(l
->n_dcon
), D(r
->n_dcon
));
331 n
= FLOAT_GE(D(l
->n_dcon
), D(r
->n_dcon
));
334 n
= FLOAT_GT(D(l
->n_dcon
), D(r
->n_dcon
));
337 n
= 0; /* XXX flow analysis */
347 /* its real; we must make a new node */
349 p
= block(o
, l
, r
, INT
, 0, 0);
354 p
->n_left
= intprom(p
->n_left
);
356 if (actions
& LVAL
) { /* check left descendent */
357 if (notlval(p
->n_left
)) {
358 uerror("lvalue required");
363 if ((l
->n_type
> BTMASK
&& ISCON(l
->n_qual
)) ||
364 (l
->n_type
<= BTMASK
&& ISCON(l
->n_qual
<< TSHIFT
)))
366 uerror("lvalue is declared const");
371 if( actions
& NCVTR
){
372 p
->n_left
= pconvert( p
->n_left
);
374 else if( !(actions
& NCVT
) ){
378 p
->n_right
= pconvert( p
->n_right
);
381 p
->n_left
= pconvert( p
->n_left
);
386 if ((actions
&PUN
) && (o
!=CAST
))
389 if( actions
& (TYPL
|TYPR
) ){
391 q
= (actions
&TYPL
) ? p
->n_left
: p
->n_right
;
393 p
->n_type
= q
->n_type
;
394 p
->n_qual
= q
->n_qual
;
399 if( actions
& CVTL
) p
= convert( p
, CVTL
);
400 if( actions
& CVTR
) p
= convert( p
, CVTR
);
401 if( actions
& TYMATCH
) p
= tymatch(p
);
402 if( actions
& PTMATCH
) p
= ptmatch(p
);
404 if( actions
& OTHER
){
413 cerror("buildtree NAME");
416 /* p->x turned into *(p+offset) */
417 /* rhs must be a name; check correctness */
419 /* Find member symbol struct */
420 if (l
->n_type
!= PTR
+STRTY
&& l
->n_type
!= PTR
+UNIONTY
){
421 uerror("struct or union required");
425 if ((sp1
= strmemb(l
->n_ap
)) == NULL
) {
426 uerror("undefined struct or union");
430 if ((sp
= findmember(sp1
, r
->n_name
)) == NULL
) {
431 uerror("member '%s' not declared", r
->n_name
);
440 if (l
->n_op
== ADDROF
) {
444 if( !ISPTR(l
->n_type
))uerror("illegal indirection");
445 p
->n_type
= DECREF(l
->n_type
);
446 p
->n_qual
= DECREF(l
->n_qual
);
460 p
->n_type
= INCREF(l
->n_type
);
461 p
->n_qual
= INCQAL(l
->n_qual
);
468 lr
= buildtree(ADDROF
, l
->n_right
, NIL
);
469 p
= buildtree( COMOP
, l
->n_left
, lr
);
474 lr
= buildtree( ADDROF
, l
->n_right
->n_right
, NIL
);
475 ll
= buildtree( ADDROF
, l
->n_right
->n_left
, NIL
);
476 nfree(p
); nfree(l
->n_right
);
477 p
= buildtree( QUEST
, l
->n_left
, buildtree( COLON
, ll
, lr
) );
482 uerror("unacceptable operand of &: %d", l
->n_op
);
488 case RS
: /* must make type size at least int... */
489 if (p
->n_type
== CHAR
|| p
->n_type
== SHORT
) {
490 p
->n_left
= makety(l
, INT
, 0, 0, 0);
491 } else if (p
->n_type
== UCHAR
|| p
->n_type
== USHORT
) {
492 p
->n_left
= makety(l
, UNSIGNED
, 0, 0, 0);
495 p
->n_type
= l
->n_type
;
496 p
->n_qual
= l
->n_qual
;
502 case RSEQ
: /* ...but not for assigned types */
503 if(tsize(r
->n_type
, r
->n_df
, r
->n_ap
) > SZINT
)
504 p
->n_right
= makety(r
, INT
, 0, 0, 0);
510 /* structure assignment */
511 /* take the addresses of the two sides; then make an
512 * operator using STASG and
513 * the addresses of left and right */
515 if (strmemb(l
->n_ap
) != strmemb(r
->n_ap
))
516 uerror("assignment of different structures");
518 r
= buildtree(ADDROF
, r
, NIL
);
520 l
= block(STASG
, l
, r
, r
->n_type
, r
->n_df
, r
->n_ap
);
534 case QUEST
: /* fixup types of : */
535 if (r
->n_left
->n_type
!= p
->n_type
)
536 r
->n_left
= makety(r
->n_left
, p
->n_type
,
537 p
->n_qual
, p
->n_df
, p
->n_ap
);
538 if (r
->n_right
->n_type
!= p
->n_type
)
539 r
->n_right
= makety(r
->n_right
, p
->n_type
,
540 p
->n_qual
, p
->n_df
, p
->n_ap
);
544 /* structure colon */
546 if (strmemb(l
->n_ap
) != strmemb(r
->n_ap
))
547 uerror( "type clash in conditional" );
551 p
->n_right
= r
= strargs(p
->n_right
);
555 if (!ISPTR(l
->n_type
))
556 uerror("illegal function");
557 p
->n_type
= DECREF(l
->n_type
);
558 if (!ISFTN(p
->n_type
))
559 uerror("illegal function");
560 p
->n_type
= DECREF(p
->n_type
);
561 p
->n_df
= l
->n_df
+1; /* add one for prototypes */
563 if (p
->n_type
== STRTY
|| p
->n_type
== UNIONTY
) {
564 /* function returning structure */
565 /* make function really return ptr to str., with * */
567 p
->n_op
+= STCALL
-CALL
;
568 p
->n_type
= INCREF(p
->n_type
);
569 p
= clocal(p
); /* before recursing */
570 p
= buildtree(UMUL
, p
, NIL
);
576 cerror( "other code %d", o
);
582 * Allow (void)0 casts.
583 * XXX - anything on the right side must be possible to cast.
584 * XXX - remove void types further on.
586 if (p
->n_op
== CAST
&& p
->n_type
== VOID
&&
587 p
->n_right
->n_op
== ICON
)
588 p
->n_right
->n_type
= VOID
;
596 printf("End of buildtree:\n");
605 /* Find a member in a struct or union. May be an unnamed member */
606 static struct symtab
*
607 findmember(struct symtab
*sp
, char *s
)
609 struct symtab
*sp2
, *sp3
;
611 for (; sp
!= NULL
; sp
= sp
->snext
) {
612 if (sp
->sname
[0] == '*') {
613 /* unnamed member, recurse down */
614 if ((sp2
= findmember(strmemb(sp
->sap
), s
))) {
615 sp3
= tmpalloc(sizeof (struct symtab
));
617 sp3
->soffset
+= sp
->soffset
;
620 } else if (sp
->sname
== s
)
628 * Check if there will be a lost label destination inside of a ?:
629 * It cannot be reached so just print it out.
632 putjops(NODE
*p
, void *arg
)
634 if (p
->n_op
== COMOP
&& p
->n_left
->n_op
== GOTO
)
635 plabel((int)glval(p
->n_left
->n_left
)+1);
639 * Build a name node based on a symtab entry.
640 * broken out from buildtree().
643 nametree(struct symtab
*sp
)
647 p
= block(NAME
, NIL
, NIL
, sp
->stype
, sp
->sdf
, sp
->sap
);
648 p
->n_qual
= sp
->squal
;
651 #ifndef NO_C_BUILTINS
652 if (sp
->sname
[0] == '_' && strncmp(sp
->sname
, "__builtin_", 10) == 0)
653 return p
; /* do not touch builtins here */
657 if (sp
->sflags
& STNODE
) {
658 /* Generated for optimizer */
660 p
->n_rval
= sp
->soffset
;
664 /* Get a label name */
665 if (sp
->sflags
== SLBLNAME
) {
669 if (sp
->stype
== UNDEF
) {
670 uerror("%s undefined", sp
->sname
);
671 /* make p look reasonable */
676 if (sp
->sclass
== MOE
) {
678 glval(p
) = sp
->soffset
;
686 * Cast a node to another type by inserting a cast.
687 * Just a nicer interface to buildtree.
688 * Returns the new tree.
691 cast(NODE
*p
, TWORD t
, TWORD u
)
695 q
= block(NAME
, NIL
, NIL
, t
, 0, 0);
697 q
= buildtree(CAST
, q
, p
);
705 * Cast and complain if necessary by not inserining a cast.
708 ccast(NODE
*p
, TWORD t
, TWORD u
, union dimfun
*df
, struct attr
*ap
)
712 /* let buildtree do typechecking (and casting) */
713 q
= block(NAME
, NIL
, NIL
, t
, df
, ap
);
714 p
= buildtree(ASSIGN
, q
, p
);
716 q
= optim(p
->n_right
);
722 * Do an actual cast of a constant (if possible).
723 * Routine assumes 2-complement (is there anything else today?)
724 * Returns 1 if handled, 0 otherwise.
727 concast(NODE
*p
, TWORD t
)
729 extern short sztable
[];
732 if (p
->n_op
!= ICON
&& p
->n_op
!= FCON
) /* only constants */
734 if (p
->n_op
== ICON
&& p
->n_sp
!= NULL
) { /* no addresses */
736 glval(p
) = 1, p
->n_type
= BOOL
, p
->n_sp
= NULL
;
741 if ((p
->n_type
& TMASK
) || (t
& TMASK
)) /* no cast of pointers */
744 //printf("concast till %d\n", t);
745 //fwalk(p, eprint, 0);
747 #define TYPMSK(y) ((((1LL << (y-1))-1) << 1) | 1)
748 if (p
->n_op
== ICON
) {
754 } else if (t
<= ULONGLONG
) {
755 glval(p
) = val
& TYPMSK(sztable
[t
]);
756 if (!ISUNSIGNED(t
)) {
757 if (val
& (1LL << (sztable
[t
]-1)))
758 glval(p
) |= ~TYPMSK(sztable
[t
]);
760 } else if (t
<= LDOUBLE
) {
762 FLOAT_INT2FP(D(p
->n_dcon
), val
, p
->n_type
);
764 } else { /* p->n_op == FCON */
767 glval(p
) = FLOAT_NE(D(p
->n_dcon
),FLOAT_ZERO
);
769 } else if (t
<= ULONGLONG
) {
771 glval(p
) = ISUNSIGNED(t
) ? /* XXX FIXME */
772 ((U_CONSZ
)D(p
->n_dcon
)->fp
) : D(p
->n_dcon
)->fp
;
775 D(p
->n_dcon
)->fp
= t
== FLOAT
? (float)D(p
->n_dcon
)->fp
:
776 t
== DOUBLE
? (double)D(p
->n_dcon
)->fp
: D(p
->n_dcon
)->fp
;
780 //fwalk(p, eprint, 0);
785 * Do a conditional branch.
788 cbranch(NODE
*p
, NODE
*q
)
790 p
= buildtree(CBRANCH
, p
, q
);
791 if (p
->n_left
->n_op
== ICON
) {
792 if (glval(p
->n_left
) != 0) {
793 branch((int)glval(q
)); /* branch always */
804 strargs(register NODE
*p
)
806 /* rewrite structure flavored arguments */
809 p
->n_left
= strargs( p
->n_left
);
810 p
->n_right
= strargs( p
->n_right
);
814 if( p
->n_type
== STRTY
|| p
->n_type
== UNIONTY
){
815 p
= block(STARG
, p
, NIL
, p
->n_type
, p
->n_df
, p
->n_ap
);
816 p
->n_left
= buildtree( ADDROF
, p
->n_left
, NIL
);
823 * apply the op o to the lval part of p; if binary, rhs is val
826 conval(NODE
*p
, int o
, NODE
*q
)
828 TWORD tl
= p
->n_type
, tr
= q
->n_type
, td
;
835 /* make both sides same type */
836 if (tl
< BTMASK
&& tr
< BTMASK
) {
837 td
= tl
> tr
? tl
: tr
;
842 p
= makety(p
, td
, 0, 0, 0);
844 q
= makety(q
, td
, 0, 0, 0);
846 u
= ISUNSIGNED(tl
) || ISUNSIGNED(tr
);
847 if( u
&& (o
==LE
||o
==LT
||o
==GE
||o
==GT
)) o
+= (UGE
-GE
);
849 if (p
->n_sp
!= NULL
&& q
->n_sp
!= NULL
)
851 if (q
->n_sp
!= NULL
&& o
!= PLUS
)
853 if (p
->n_sp
!= NULL
&& o
!= PLUS
&& o
!= MINUS
)
858 if (v2
== 0 && (cdope(o
) & DIVFLG
))
859 return 0; /* leave division by zero to runtime */
864 if (p
->n_sp
== NULL
) {
865 p
->n_right
= q
->n_right
;
866 p
->n_type
= q
->n_type
;
900 glval(p
) = glval(p
) << i
;
908 glval(p
) = glval(p
) >> i
;
912 glval(p
) = - glval(p
);
915 glval(p
) = ~glval(p
);
918 glval(p
) = !glval(p
);
921 glval(p
) = glval(p
) < val
;
924 glval(p
) = glval(p
) <= val
;
927 glval(p
) = glval(p
) > val
;
930 glval(p
) = glval(p
) >= val
;
945 glval(p
) = glval(p
) == val
;
948 glval(p
) = glval(p
) != val
;
951 glval(p
) = glval(p
) && val
;
954 glval(p
) = glval(p
) || val
;
959 /* Do the best in making everything type correct after calc */
960 if (p
->n_sp
== NULL
&& q
->n_sp
== NULL
)
961 glval(p
) = valcast(glval(p
), p
->n_type
);
966 * Ensure that v matches the type t; sign- or zero-extended
967 * as suitable to CONSZ.
968 * Only to be used for integer types.
971 valcast(CONSZ v
, TWORD t
)
976 if (t
< CHAR
|| t
> ULONGLONG
)
977 return v
; /* cannot cast */
980 return v
; /* already largest */
982 #define M(x) ((((1ULL << ((x)-1)) - 1) << 1) + 1)
983 #define NOTM(x) (~M(x))
984 #define SBIT(x) (1ULL << ((x)-1))
986 sz
= (int)tsize(t
, NULL
, NULL
);
988 if (!ISUNSIGNED(t
) && (SBIT(sz
) & r
))
994 * Checks p for the existence of a pun. This is called when the op of p
995 * is ASSIGN, RETURN, CAST, COLON, or relational.
996 * One case is when enumerations are used: this applies only to lint.
997 * In the other case, one operand is a pointer, the other integer type
998 * we check that this integer is in fact a constant zero...
999 * in the case of ASSIGN, any assignment of pointer to integer is illegal
1000 * this falls out, because the LHS is never 0.
1001 * XXX - check for COMOPs in assignment RHS?
1006 union dimfun
*d1
, *d2
;
1010 t1
= p
->n_left
->n_type
;
1011 t2
= p
->n_right
->n_type
;
1015 /* return of void allowed but nothing else */
1016 if (t1
== VOID
&& t2
== VOID
)
1019 werror("returning value from void function");
1023 uerror("using void value");
1028 if (t1
== VOID
&& t2
== VOID
)
1032 if ((t1
== VOID
&& t2
!= VOID
) || (t1
!= VOID
&& t2
== VOID
)) {
1033 uerror("value of void expression used");
1039 /* allow void pointer assignments in any direction */
1040 if (BTYPE(t1
) == VOID
&& (t2
& TMASK
))
1042 if (BTYPE(t2
) == VOID
&& (t1
& TMASK
))
1045 /* boolean have special syntax */
1047 if (!ISARY(t2
)) /* Anything scalar */
1051 if (ISPTR(t1
) || ISARY(t1
))
1056 if (!ISPTR(q
->n_type
) && !ISARY(q
->n_type
)) {
1057 if (q
->n_op
!= ICON
|| glval(q
) != 0)
1058 werror("illegal combination of pointer and integer");
1061 if (ISSOU(BTYPE(t1
)) &&
1062 !suemeq(p
->n_left
->n_ap
, p
->n_right
->n_ap
))
1063 werror("illegal structure pointer combination");
1066 d1
= p
->n_left
->n_df
;
1067 d2
= p
->n_right
->n_df
;
1069 if (ISARY(t1
) || ISPTR(t1
)) {
1070 if (!ISARY(t2
) && !ISPTR(t2
))
1072 if (ISARY(t1
) && ISARY(t2
) && d1
->ddim
!= d2
->ddim
) {
1073 werror("illegal array size combination");
1080 } else if (ISFTN(t1
)) {
1081 if (chkftn(d1
->dfun
, d2
->dfun
)) {
1082 werror("illegal function "
1083 "pointer combination");
1093 if (DEUNSIGN(t1
) != DEUNSIGN(t2
))
1094 warner(Wpointer_sign
);
1099 offplus(NODE
*p
, int off
, TWORD t
, TWORD q
, union dimfun
*d
, struct attr
*ap
) {
1101 p
= block(PLUS
, p
, offcon(off
, t
, d
, ap
), t
, d
, ap
);
1106 return buildtree(UMUL
, p
, NIL
);
1113 struct attr
*ap
, *xap
, *yap
;
1121 /* this is also used to reference automatic variables */
1123 s
= p
->n_right
->n_sp
;
1127 xap
= attr_find(r
->n_ap
, GCC_ATYP_PACKED
);
1132 /* make p look like ptr to x */
1134 if (!ISPTR(p
->n_type
))
1135 p
->n_type
= PTR
+UNIONTY
;
1137 t
= INCREF(s
->stype
);
1138 q
= INCQAL(s
->squal
);
1142 if ((yap
= attr_find(ap
, GCC_ATYP_PACKED
)) != NULL
)
1144 else if (xap
!= NULL
)
1145 ap
= attr_add(ap
, attr_dup(xap
));
1149 /* xap set if packed struct */
1151 p
= makety(p
, t
, q
, d
, ap
);
1152 if (ISFTN(s
->stype
)) {
1153 /* direct class call */
1154 p
= block(NMLIST
, p
, nametree(s
), INT
, 0, 0);
1158 /* compute the offset to be added */
1164 TWORD ftyp
= s
->stype
;
1165 int fal
= talign(ftyp
, ap
);
1166 off
= (off
/fal
)*fal
;
1167 p
= offplus(p
, off
, t
, q
, d
, ap
);
1168 p
= block(FLD
, p
, NIL
, ftyp
, 0, ap
);
1170 p
->n_rval
= PKFIELD(dsc
&FLDSIZ
, s
->soffset
%fal
);
1172 p
= offplus(p
, off
, t
, q
, d
, ap
);
1174 /* if target cannot handle unaligned addresses, fix here */
1183 notlval(register NODE
*p
)
1185 /* return 0 if p an lvalue, 1 otherwise */
1198 if( ISARY(p
->n_type
) || ISFTN(p
->n_type
) ) return(1);
1208 /* make a constant node with value i */
1212 return xbcon(i
, NULL
, INT
);
1216 xbcon(CONSZ val
, struct symtab
*sp
, TWORD type
)
1220 p
= block(ICON
, NIL
, NIL
, type
, 0, 0);
1229 int isdyn(struct symtab
*sp
);
1235 s
.stype
= DECREF(p
->n_type
);
1239 for (t
= s
.stype
; t
> BTMASK
; t
= DECREF(t
)) {
1241 return buildtree(MUL
, q
, bcon(SZPOINT(t
)));
1243 if (s
.sdf
->ddim
< 0)
1244 r
= tempnode(-s
.sdf
->ddim
, INT
, 0, 0);
1246 r
= bcon(s
.sdf
->ddim
/SZCHAR
);
1247 q
= buildtree(MUL
, q
, r
);
1251 sz
= (int)tsize(p
->n_type
, p
->n_df
, p
->n_ap
);
1252 p
= buildtree(MUL
, q
, bcon(sz
/SZCHAR
));
1254 p
= (offcon(psize(p
), p
->n_type
, p
->n_df
, p
->n_ap
));
1259 * p is a node of type pointer; psize returns the
1260 * size of the thing pointed to
1266 if (!ISPTR(p
->n_type
)) {
1267 uerror("pointer required");
1270 /* note: no pointers to fields */
1271 return(tsize(DECREF(p
->n_type
), p
->n_df
, p
->n_ap
));
1275 * convert an operand of p
1276 * f is either CVTL or CVTR
1277 * operand has type int, and is converted by the size of the other side
1278 * convert is called when an integer is to be added to a pointer, for
1279 * example in arrays or structures.
1282 convert(NODE
*p
, int f
)
1286 NODE
*q
, *r
, *s
, *rv
;
1295 ty2
= ty
= DECREF(s
->n_type
);
1299 r
= offcon(tsize(ty
, s
->n_df
, s
->n_ap
), s
->n_type
, s
->n_df
, s
->n_ap
);
1304 rv
= buildtree(MUL
, rv
, df
->ddim
>= 0 ? bcon(df
->ddim
) :
1305 tempnode(-df
->ddim
, INT
, 0, 0));
1309 rv
= clocal(MBLOCK(rv
, r
, INT
, 0, 0));
1312 r
= MBLOCK(q
, rv
, INT
, 0, 0);
1315 * Indexing is only allowed with integer arguments, so insert
1316 * SCONV here if arg is not an integer.
1319 if (r
->n_type
!= INTPTR
)
1320 r
= clocal(makety(r
, INTPTR
, 0, 0, 0));
1329 pconvert(register NODE
*p
)
1331 /* if p should be changed into a pointer, do so */
1333 if( ISARY( p
->n_type
) ){
1334 p
->n_type
= DECREF( p
->n_type
);
1336 return( buildtree( ADDROF
, p
, NIL
) );
1338 if( ISFTN( p
->n_type
) )
1339 return( buildtree( ADDROF
, p
, NIL
) );
1345 oconvert(register NODE
*p
)
1347 /* convert the result itself: used for pointer and unsigned */
1355 if(ISUNSIGNED(p
->n_left
->n_type
) ||
1356 ISUNSIGNED(p
->n_right
->n_type
) ||
1357 ISPTR(p
->n_left
->n_type
) ||
1358 ISPTR(p
->n_right
->n_type
))
1359 p
->n_op
+= (ULE
-LE
);
1368 return(clocal(VBLOCK(p
, bpsize(p
->n_left
), INT
, 0, 0)));
1371 cerror( "illegal oconvert: %d", p
->n_op
);
1377 * makes the operands of p agree; they are
1378 * either pointers or integers, by this time
1379 * with MINUS, the sizes must be the same
1380 * with COLON, the types must be the same
1385 struct attr
*ap
, *ap2
;
1386 union dimfun
*d
, *d2
;
1387 TWORD t1
, t2
, t
, q1
, q2
, q
;
1391 t
= t1
= p
->n_left
->n_type
;
1392 q
= q1
= p
->n_left
->n_qual
;
1393 t2
= p
->n_right
->n_type
;
1394 q2
= p
->n_right
->n_qual
;
1395 d
= p
->n_left
->n_df
;
1396 d2
= p
->n_right
->n_df
;
1397 ap
= p
->n_left
->n_ap
;
1398 ap2
= p
->n_right
->n_ap
;
1408 /* just paint over */
1409 p
->n_right
= block(SCONV
, p
->n_right
, NIL
, VOID
, 0, 0);
1415 int isdyn(struct symtab
*sp
);
1416 struct symtab s1
, s2
;
1418 s1
.stype
= DECREF(t
);
1420 s2
.stype
= DECREF(t2
);
1422 if (isdyn(&s1
) || isdyn(&s2
))
1423 ; /* We don't know */
1424 else if (psize(p
->n_left
) != psize(p
->n_right
))
1425 uerror("illegal pointer subtraction");
1432 * Check for void pointer types. They are allowed
1433 * to cast to/from any pointers.
1435 if (ISPTR(t1
) && ISPTR(t2
) &&
1436 (BTYPE(t1
) == VOID
|| BTYPE(t2
) == VOID
))
1438 uerror("illegal types in :");
1442 default: /* must work harder: relationals or comparisons */
1455 /* both are pointers */
1456 if( talign(t2
,ap2
) < talign(t
,ap
) ){
1464 p
->n_left
= makety( p
->n_left
, t
, q
, d
, ap
);
1465 p
->n_right
= makety( p
->n_right
, t
, q
, d
, ap
);
1466 if( o
!=MINUS
&& !clogop(o
) ){
1478 * Satisfy the types of various arithmetic binary ops.
1481 * if assignment, type of LHS
1482 * if any doubles, make double
1483 * else if any float make float
1484 * else if any longlongs, make long long
1485 * else if any longs, make long
1488 * If the op with the highest rank is unsigned, this is the resulting type.
1489 * See: 6.3.1.1 rank order equal of signed and unsigned types
1490 * 6.3.1.8 Usual arithmetic conversions
1506 if (tl
== BOOL
) tl
= BOOL_TYPE
;
1507 if (tr
== BOOL
) tr
= BOOL_TYPE
;
1510 if (r
->n_op
!= ICON
&& tl
< FLOAT
&& tr
< FLOAT
&&
1511 DEUNSIGN(tl
) < DEUNSIGN(tr
) && o
!= CAST
)
1512 warner(Wtruncate
, tnames
[tr
], tnames
[tl
]);
1513 p
->n_right
= makety(p
->n_right
, l
->n_type
, 0, 0, 0);
1514 t
= p
->n_type
= l
->n_type
;
1517 t
= tl
> tr
? tl
: tr
; /* MAX */
1518 /* This depends on ctype() called early */
1519 if (o
!= COLON
&& t
< INT
)
1521 if (tl
!= t
) p
->n_left
= makety(p
->n_left
, t
, 0, 0, 0);
1522 if (tr
!= t
) p
->n_right
= makety(p
->n_right
, t
, 0, 0, 0);
1523 if (o
== COLON
&& l
->n_type
== BOOL
&& r
->n_type
== BOOL
)
1524 t
= p
->n_type
= BOOL
;
1525 else if (!clogop(o
))
1530 printf("tymatch(%p): ", p
);
1532 printf(" %s ", copst(o
));
1537 fwalk(p
, eprint
, 0);
1544 * make p into type t by inserting a conversion
1547 makety(NODE
*p
, TWORD t
, TWORD q
, union dimfun
*d
, struct attr
*ap
)
1550 if (t
== p
->n_type
) {
1557 if (ISITY(t
) || ISCTY(t
) || ISITY(p
->n_type
) || ISCTY(p
->n_type
))
1563 p
= block(t
& TMASK
? PCONV
: SCONV
, p
, NIL
, t
, d
, ap
);
1569 block(int o
, NODE
*l
, NODE
*r
, TWORD t
, union dimfun
*d
, struct attr
*ap
)
1576 glval(p
) = 0; /* Protect against large lval */
1583 #if !defined(MULTIPASS)
1584 /* p->n_reg = */p
->n_su
= 0;
1591 * Return the constant value from an ICON.
1596 /* if p is an integer constant, return its value */
1599 if (p
->n_op
!= ICON
|| p
->n_sp
!= NULL
) {
1600 uerror( "constant expected");
1609 * the intent of this table is to examine the
1610 * operators, and to check them for
1613 * The table is searched for the op and the
1614 * modified type (where this is one of the
1615 * types INT (includes char and short), LONG,
1616 * DOUBLE (includes FLOAT), and POINTER
1618 * The default action is to make the node type integer
1620 * The actions taken include:
1621 * PUN check for puns
1622 * CVTL convert the left operand
1623 * CVTR convert the right operand
1624 * TYPL the type is determined by the left operand
1625 * TYPR the type is determined by the right operand
1626 * TYMATCH force type of left and right to match,by inserting conversions
1627 * PTMATCH like TYMATCH, but for pointers
1628 * LVAL left operand must be lval
1629 * CVTO convert the op
1630 * NCVT do not convert the operands
1631 * OTHER handled by code
1632 * NCVTR convert the left operand, not the right...
1636 # define MINT 01 /* integer */
1637 # define MDBI 02 /* integer or double */
1638 # define MSTR 04 /* structure */
1639 # define MPTR 010 /* pointer */
1640 # define MPTI 020 /* pointer or integer */
1645 int mt12
, mt1
, mt2
, o
;
1647 mt1
= mt2
= mt12
= 0;
1649 switch (coptype(o
= p
->n_op
)) {
1651 mt12
=mt2
= moditype(p
->n_right
->n_type
);
1654 mt12
&= (mt1
= moditype(p
->n_left
->n_type
));
1666 { return( OTHER
); }
1668 if( mt1
& MDBI
) return( TYPL
+PROML
);
1672 if( mt1
& MINT
) return( TYPL
+PROML
);
1676 return( NCVT
+OTHER
);
1689 if( mt12
& MDBI
) return( TYMATCH
);
1696 if( mt12
& MINT
) return( TYMATCH
);
1701 if( mt12
& MINT
) return( TYPL
+OTHER
);
1710 if( mt12
& MDBI
) return( TYMATCH
+CVTO
);
1711 else if( mt12
& MPTR
) return( PTMATCH
+PUN
+CVTO
);
1712 else if( mt12
& MPTI
) return( PTMATCH
+PUN
);
1716 return( TYPR
+OTHER
);
1721 return( NCVTR
+OTHER
);
1727 if( mt12
& MDBI
) return( TYMATCH
);
1728 else if( mt12
& MPTR
) return( TYPL
+PTMATCH
+PUN
);
1729 else if( (mt1
&MINT
) && (mt2
&MPTR
) ) return( TYPR
+PUN
);
1730 else if( (mt1
&MPTR
) && (mt2
&MINT
) ) return( TYPL
+PUN
);
1731 else if( mt12
& MSTR
) return( NCVT
+TYPL
+OTHER
);
1736 if( mt12
& MSTR
) return( LVAL
+NCVT
+TYPL
+OTHER
);
1738 if( mt12
& MDBI
) return( TYPL
+LVAL
+TYMATCH
);
1739 else if( mt1
& MPTR
) return( LVAL
+PTMATCH
+PUN
);
1740 else if( mt12
& MPTI
) return( TYPL
+LVAL
+TYMATCH
+PUN
);
1745 if( mt12
& MINT
) return( TYPL
+LVAL
+OTHER
);
1750 if( mt12
& MDBI
) return( LVAL
+TYMATCH
);
1758 return(LVAL
+TYMATCH
);
1766 return(TYMATCH
+LVAL
);
1767 else if ((mt1
&MPTR
) && (mt2
&MINT
))
1768 return(TYPL
+LVAL
+CVTR
);
1773 return(CVTO
+PTMATCH
+PUN
);
1780 else if ((mt1
&MPTR
) && (mt2
&MINT
))
1782 else if ((mt1
&MINT
) && (mt2
&MPTR
))
1786 uerror("operands of %s have incompatible types", copst(o
));
1810 return( MINT
|MDBI
|MPTI
);
1824 return( MPTR
|MPTI
);
1829 int tvaloff
= MAXREGS
+NPERMREG
> 100 ? MAXREGS
+NPERMREG
+ 100 : 100;
1832 * Returns a TEMP node with temp number nr.
1833 * If nr == 0, return a node with a new number.
1836 tempnode(int nr
, TWORD type
, union dimfun
*df
, struct attr
*ap
)
1840 if (tvaloff
== -NOOFFSET
)
1841 tvaloff
++; /* Skip this for array indexing */
1842 r
= block(TEMP
, NIL
, NIL
, type
, df
, ap
);
1843 regno(r
) = nr
? nr
: tvaloff
;
1844 tvaloff
+= szty(type
);
1854 extern NODE
*arrstk
[10];
1862 uerror("can't apply sizeof to bit-field");
1865 * Arrays may be dynamic, may need to make computations.
1873 if (df
->ddim
== NOOFFSET
)
1874 uerror("sizeof of incomplete type");
1877 q
= arrstk
[astkp
++];
1879 q
= tempnode(-df
->ddim
, INT
, 0, 0);
1882 rv
= buildtree(MUL
, rv
, q
);
1886 rv
= buildtree(MUL
, rv
,
1887 xbcon(tsize(ty
, p
->n_df
, p
->n_ap
)/SZCHAR
, NULL
, INTPTR
));
1889 arrstkp
= 0; /* XXX - may this fail? */
1895 eprint(NODE
*p
, int down
, int *a
, int *b
)
1904 if( down
) printf( " " );
1906 ty
= coptype( p
->n_op
);
1908 printf("%p) %s, ", p
, copst(p
->n_op
));
1909 if (p
->n_op
== XARG
|| p
->n_op
== XASM
)
1910 printf("id '%s', ", p
->n_name
);
1912 printf(CONFMT
, glval(p
));
1913 if (p
->n_op
== NAME
|| p
->n_op
== ICON
)
1914 printf(", %p, ", p
->n_sp
);
1916 printf(", %d, ", p
->n_rval
);
1918 tprint(p
->n_type
, p
->n_qual
);
1919 printf( ", %p, ", p
->n_df
);
1927 * Emit everything that should be emitted on the left side
1928 * of a comma operator, and remove the operator.
1929 * Do not traverse through QUEST, ANDAND and OROR.
1930 * Enable this for all targets when stable enough.
1938 while (p
->n_op
== COMOP
) {
1939 /* XXX hack for GCC ({ }) ops */
1940 if (p
->n_left
->n_op
== GOTO
) {
1941 int v
= (int)glval(p
->n_left
->n_left
);
1945 ecomp(p
->n_left
); /* will recurse if more COMOPs */
1950 o
= coptype(p
->n_op
);
1951 if (p
->n_op
== QUEST
|| p
->n_op
== ANDAND
|| p
->n_op
== OROR
)
1960 * Walk up through the tree from the leaves,
1961 * removing constant operators.
1966 int o
= coptype(p
->n_op
);
1980 if (!clogop(p
->n_op
))
1982 if (p
->n_op
== NOT
&& l
->n_op
== ICON
) {
1983 glval(p
) = glval(l
) == 0;
1987 if (l
->n_op
== ICON
&& r
->n_op
== ICON
) {
1988 if (conval(l
, p
->n_op
, r
) == 0) {
1990 * people sometimes tend to do really odd compares,
1991 * like "if ("abc" == "def")" etc.
1992 * do it runtime instead.
1995 glval(p
) = glval(l
);
2004 * Removes redundant logical operators for branch conditions.
2007 fixbranch(NODE
*p
, int label
)
2012 if (p
->n_op
== ICON
) {
2017 if (!clogop(p
->n_op
)) /* Always conditional */
2018 p
= buildtree(NE
, p
, bcon(0));
2019 ecode(buildtree(CBRANCH
, p
, bcon(label
)));
2024 * Write out logical expressions as branches.
2027 andorbr(NODE
*p
, int true, int false)
2033 switch (o
= p
->n_op
) {
2037 * Remove redundant EQ/NE nodes.
2039 while (((o
= p
->n_left
->n_op
) == EQ
|| o
== NE
) &&
2040 p
->n_right
->n_op
== ICON
) {
2043 if (glval(p
->n_right
) == 0) {
2048 p
->n_op
= negrel
[p
->n_op
- EQ
];
2050 p
->n_op
= NE
; /* toggla */
2052 } else if (glval(p
->n_right
) == 1) {
2057 p
->n_op
= negrel
[p
->n_op
- EQ
];
2059 p
->n_op
= EQ
; /* toggla */
2062 break; /* XXX - should always be false */
2070 calc
: if (true < 0) {
2071 p
->n_op
= negrel
[p
->n_op
- EQ
];
2085 /* Convert to friendlier ops */
2086 if (nncon(p
->n_right
) && glval(p
->n_right
) == 0)
2087 p
->n_op
= o
== ULE
? EQ
: NE
;
2092 /* Already true/false by definition */
2093 if (nncon(p
->n_right
) && glval(p
->n_right
) == 0) {
2095 o
= o
== ULT
? UGE
: ULT
;
2103 if (o
== UGE
) /* true */
2110 lab
= false<0 ? getlab() : false ;
2111 andorbr(p
->n_left
, -1, lab
);
2113 andorbr(p
->n_right
, true, false);
2120 lab
= true<0 ? getlab() : true;
2121 andorbr(p
->n_left
, lab
, -1);
2123 andorbr(p
->n_right
, true, false);
2130 andorbr(p
->n_left
, false, true);
2142 fixbranch(buildtree(EQ
, p
, bcon(0)), false);
2148 * Create a node for either TEMP or on-stack storage.
2151 cstknode(TWORD t
, union dimfun
*df
, struct attr
*ap
)
2155 /* create a symtab entry suitable for this type */
2156 sp
= getsymtab("0hej", STEMP
);
2161 sp
->soffset
= NOOFFSET
;
2162 oalloc(sp
, &autooff
);
2163 return nametree(sp
);
2168 * Massage the output trees to remove C-specific nodes:
2169 * COMOPs are split into separate statements.
2170 * QUEST/COLON are rewritten to branches.
2171 * ANDAND/OROR/NOT are rewritten to branches for lazy-evaluation.
2172 * CBRANCH conditions are rewritten for lazy-evaluation.
2179 int o
, ty
, lbl
, lbl2
;
2184 if (BTYPE(p
->n_type
) == ENUMTY
) { /* fixup enum */
2185 struct symtab
*sp
= strmemb(p
->n_ap
);
2186 MODTYPE(p
->n_type
, sp
->stype
);
2188 * XXX may fail if these are true:
2189 * - variable-sized enums
2190 * - non-byte-addressed targets.
2192 if (BTYPE(p
->n_type
) == ENUMTY
&& ISPTR(p
->n_type
))
2193 MODTYPE(p
->n_type
, INT
); /* INT ok? */
2199 * Create a branch node from ?:
2200 * || and && must be taken special care of.
2203 andorbr(p
->n_left
, -1, lbl
= getlab());
2205 /* Make ASSIGN node */
2206 /* Only if type is not void */
2207 q
= p
->n_right
->n_left
;
2210 tval
= cstknode(q
->n_type
, q
->n_df
, q
->n_ap
);
2211 q
= buildtree(ASSIGN
, ccopy(tval
), q
);
2214 ecode(q
); /* Done with assign */
2215 branch(lbl2
= getlab());
2218 q
= p
->n_right
->n_right
;
2221 q
= buildtree(ASSIGN
, ccopy(tval
), q
);
2224 ecode(q
); /* Done with assign */
2229 if (p
->n_type
!= VOID
) {
2252 #ifdef SPECIAL_CCODES
2253 #error fix for private CCODES handling
2257 andorbr(r
, -1, lbl
= getlab());
2259 tval
= cstknode(p
->n_type
, p
->n_df
, p
->n_ap
);
2261 ecode(buildtree(ASSIGN
, ccopy(tval
), bcon(1)));
2262 branch(lbl2
= getlab());
2264 ecode(buildtree(ASSIGN
, ccopy(tval
), bcon(0)));
2273 andorbr(p
->n_left
, glval(p
->n_right
), -1);
2275 p
->n_op
= ICON
; p
->n_type
= VOID
;
2278 cerror("COMOP error");
2290 * Return 1 if an assignment is found.
2295 if (cdope(p
->n_op
) & ASGFLG
)
2297 if (coptype(p
->n_op
) == LTYPE
)
2299 if (has_se(p
->n_left
))
2301 if (coptype(p
->n_op
) == BITYPE
)
2302 return has_se(p
->n_right
);
2307 * Find and convert asgop's to separate statements.
2308 * Be careful about side effects.
2309 * assign tells whether ASSIGN should be considered giving
2310 * side effects or not.
2318 if (p
->n_op
== INCR
|| p
->n_op
== DECR
) {
2320 * Rewrite x++ to (x += 1) -1; and deal with it further down.
2321 * Pass2 will remove -1 if unnecessary.
2325 q
->n_op
= (p
->n_op
==INCR
)?PLUSEQ
:MINUSEQ
;
2326 p
->n_op
= (p
->n_op
==INCR
)?MINUS
:PLUS
;
2327 p
->n_left
= delasgop(q
);
2329 } else if ((cdope(p
->n_op
)&ASGOPFLG
) &&
2330 p
->n_op
!= RETURN
&& p
->n_op
!= CAST
) {
2331 NODE
*l
= p
->n_left
;
2332 NODE
*ll
= l
->n_left
;
2335 q
= tempnode(0, ll
->n_type
, ll
->n_df
, ll
->n_ap
);
2337 r
= tempnode(tval
, ll
->n_type
, ll
->n_df
,ll
->n_ap
);
2339 /* Now the left side of node p has no side effects. */
2340 /* side effects on the right side must be obeyed */
2343 r
= buildtree(ASSIGN
, r
, ll
);
2347 #if 0 /* Cannot call buildtree() here, it would invoke double add shifts */
2348 p
->n_right
= buildtree(UNASG p
->n_op
, ccopy(l
),
2351 p
->n_right
= block(UNASG p
->n_op
, ccopy(l
),
2352 p
->n_right
, p
->n_type
, p
->n_df
, p
->n_ap
);
2355 p
->n_right
= delasgop(p
->n_right
);
2356 p
->n_right
= clocal(p
->n_right
);
2360 if (coptype(p
->n_op
) == LTYPE
)
2362 p
->n_left
= delasgop(p
->n_left
);
2363 if (coptype(p
->n_op
) == BITYPE
)
2364 p
->n_right
= delasgop(p
->n_right
);
2371 /* avoid promotion to int */
2372 #define TYPMOD(o, p, n, t) clocal(block(o, p, n, t, 0, 0))
2373 #define TYPLS(p, n, t) TYPMOD(LS, p, n, t)
2374 #define TYPRS(p, n, t) TYPMOD(RS, p, n, t)
2375 #define TYPOR(p, q, t) TYPMOD(OR, p, q, t)
2376 #define TYPAND(p, q, t) TYPMOD(AND, p, q, t)
2379 * Read an unaligned bitfield from position pointed to by p starting at
2380 * off and size fsz and return a tree of type t with resulting data.
2383 rdualfld(NODE
*p
, TWORD t
, TWORD ct
, int off
, int fsz
)
2385 int t2f
, inbits
, tsz
, ctsz
;
2389 ctsz
= (int)tsize(ct
, 0, 0);
2391 /* traverse until first data byte */
2392 for (t2f
= 0; off
> ctsz
; t2f
++, off
-= ctsz
)
2394 #ifdef UNALIGNED_ACCESS
2395 /* try to squeeze it into an int */
2396 if (off
+ fsz
> ctsz
&& off
+ fsz
<= SZINT
) {
2401 p
= makety(p
, PTR
|ct
, 0, 0, 0);
2402 if (off
+ fsz
<= ctsz
) {
2403 /* only one operation needed */
2404 q
= buildtree(UMUL
, buildtree(PLUS
, p
, bcon(t2f
)), 0);
2405 if (!ISUNSIGNED(t
)) {
2407 q
= makety(q
, ct
, 0, 0, 0);
2409 q
= TYPLS(q
, bcon(ctsz
-fsz
-off
), ct
);
2410 q
= TYPRS(q
, bcon(ctsz
-fsz
), ct
);
2411 q
= makety(q
, t
, 0, 0, 0);
2413 q
= buildtree(UMUL
, buildtree(PLUS
, ccopy(p
), bcon(t2f
)), 0);
2414 q
= makety(TYPRS(q
, bcon(off
), ct
), t
, 0, 0, 0);
2415 inbits
= ctsz
- off
;
2418 while (fsz
> inbits
) {
2420 buildtree(PLUS
, ccopy(p
), bcon(t2f
)), 0);
2421 r
= makety(r
, t
, 0, 0, 0);
2422 r
= TYPLS(r
, bcon(inbits
), t
);
2427 /* sign/zero extend XXX - RS must sign extend */
2428 tsz
= (int)tsize(t
, 0, 0);
2429 if (!ISUNSIGNED(t
)) {
2431 q
= makety(q
, t
, 0, 0, 0);
2433 q
= TYPLS(q
, bcon(tsz
-fsz
), t
);
2434 q
= TYPRS(q
, bcon(tsz
-fsz
), t
);
2442 * Write val to a (unaligned) bitfield with length fsz positioned off bits
2443 * from d. Bitfield type is t, and type to use when writing is ct.
2444 * neither f nor d should have any side effects if copied.
2445 * Multiples of ct are supposed to be written without problems.
2446 * Both val and d are free'd after use.
2449 wrualfld(NODE
*val
, NODE
*d
, TWORD t
, TWORD ct
, int off
, int fsz
)
2451 NODE
*p
, *q
, *r
, *rn
, *s
;
2452 int ctsz
, t2f
, inbits
;
2454 ctsz
= (int)tsize(ct
, 0, 0);
2457 d
= makety(d
, PTR
|ct
, 0, 0, 0);
2459 for (t2f
= 0; off
> ctsz
; t2f
++, off
-= ctsz
)
2462 if (off
+ fsz
<= ctsz
) {
2463 r
= tempnode(0, ct
, 0, 0);
2465 /* only one operation needed */
2466 d
= buildtree(UMUL
, buildtree(PLUS
, d
, bcon(t2f
)), 0);
2468 p
= TYPAND(p
, xbcon(~(SZMASK(fsz
) << off
), 0, ct
), ct
);
2470 val
= makety(val
, ct
, 0, 0, 0);
2471 q
= TYPAND(val
, xbcon(SZMASK(fsz
), 0, ct
), ct
);
2472 q
= buildtree(ASSIGN
, ccopy(r
), q
);
2474 q
= TYPLS(q
, bcon(off
), ct
);
2475 p
= TYPOR(p
, q
, ct
);
2476 p
= makety(p
, t
, 0, 0, 0);
2477 rn
= buildtree(ASSIGN
, d
, p
);
2478 rn
= buildtree(COMOP
, rn
, makety(r
, t
, 0, 0, 0));
2480 s
= makety(ccopy(val
), t
, 0, 0, 0);
2481 s
= TYPAND(s
, xbcon(SZMASK(fsz
), 0, t
), t
);
2483 r
= buildtree(UMUL
, buildtree(PLUS
, ccopy(d
), bcon(t2f
)), 0);
2485 p
= TYPAND(p
, xbcon(SZMASK(off
), 0, ct
), ct
);
2487 q
= TYPLS(q
, bcon(off
), t
);
2488 q
= makety(q
, ct
, 0, 0, 0);
2489 p
= TYPOR(p
, q
, ct
);
2490 rn
= buildtree(ASSIGN
, r
, p
);
2491 inbits
= ctsz
- off
;
2494 while (fsz
> inbits
+ctsz
) {
2496 buildtree(PLUS
, ccopy(d
), bcon(t2f
)), 0);
2498 q
= TYPRS(q
, bcon(inbits
), t
);
2499 q
= makety(q
, ct
, 0, 0, 0);
2500 rn
= buildtree(COMOP
, rn
, buildtree(ASSIGN
, r
, q
));
2505 r
= buildtree(UMUL
, buildtree(PLUS
, d
, bcon(t2f
)), 0);
2507 p
= TYPAND(p
, makety(xbcon(~SZMASK(fsz
-inbits
), 0, ct
),
2509 q
= TYPRS(val
, bcon(inbits
), t
);
2510 q
= TYPAND(q
, xbcon(SZMASK(fsz
-inbits
), 0, t
), t
);
2511 q
= makety(q
, ct
, 0, 0, 0);
2512 p
= TYPOR(p
, q
, ct
);
2513 rn
= buildtree(COMOP
, rn
, buildtree(ASSIGN
, r
, p
));
2514 rn
= buildtree(COMOP
, rn
, s
);
2520 * Rewrite bitfield operations to shifts.
2526 NODE
*q
, *r
, *t1
, *t2
, *bt
, *t3
, *t4
;
2529 if (p
->n_op
== FLD
) {
2530 /* Rewrite a field read operation */
2531 fsz
= UPKFSZ(p
->n_rval
);
2532 foff
= UPKFOFF(p
->n_rval
);
2533 q
= buildtree(ADDROF
, p
->n_left
, NIL
);
2537 if (attr_find(p
->n_ap
, GCC_ATYP_PACKED
) &&
2538 coptype(q
->n_op
) != LTYPE
) {
2539 t1
= tempnode(0, q
->n_type
, 0, 0);
2540 bt
= buildtree(ASSIGN
, ccopy(t1
), q
);
2542 #ifndef UNALIGNED_ACCESS
2548 q
= rdualfld(q
, t
, ct
, foff
, fsz
);
2552 } else if (((cdope(p
->n_op
)&ASGOPFLG
) || p
->n_op
== ASSIGN
||
2553 p
->n_op
== INCR
|| p
->n_op
== DECR
) && p
->n_left
->n_op
== FLD
) {
2555 * Rewrite a field write operation
2556 * More difficult than a read op since we must care
2557 * about side effects.
2560 fsz
= UPKFSZ(q
->n_rval
);
2561 foff
= UPKFOFF(q
->n_rval
);
2562 t
= q
->n_left
->n_type
;
2563 #if TARGET_ENDIAN == TARGET_BE
2564 foff
= (int)tsize(t
, 0, 0) - fsz
- foff
;
2567 if (p
->n_right
->n_op
!= ICON
&& p
->n_right
->n_op
!= NAME
) {
2568 t2
= tempnode(0, p
->n_right
->n_type
, 0, 0);
2569 bt
= buildtree(ASSIGN
, ccopy(t2
), p
->n_right
);
2575 #ifndef UNALIGNED_ACCESS
2576 if (attr_find(q
->n_ap
, GCC_ATYP_PACKED
))
2580 /* t2 is what we have to write (RHS of ASSIGN) */
2581 /* bt is (eventually) something that must be written */
2584 if (q
->n_left
->n_op
== UMUL
) {
2585 /* LHS of assignment may have side effects */
2587 t1
= tempnode(0, q
->n_left
->n_type
, 0, 0);
2588 r
= buildtree(ASSIGN
, ccopy(t1
), q
->n_left
);
2590 bt
= bt
? block(COMOP
, bt
, r
, INT
, 0, 0) : r
;
2593 t1
= buildtree(ADDROF
, p
->n_left
->n_left
, 0);
2595 /* t1 is lval where to write (and read) */
2597 if (p
->n_op
== ASSIGN
) {
2598 q
= wrualfld(t2
, t1
, t
, ct
, foff
, fsz
);
2600 q
= block(COMOP
, bt
, q
, t
, 0, 0);
2602 p
->n_left
= bcon(0);
2605 } else if ((cdope(p
->n_op
)&ASGOPFLG
)) {
2606 /* And here is the asgop-specific code */
2607 t3
= tempnode(0, t
, 0, 0);
2608 q
= rdualfld(ccopy(t1
), t
, ct
, foff
, fsz
);
2609 q
= buildtree(UNASG p
->n_op
, q
, t2
);
2610 q
= buildtree(ASSIGN
, ccopy(t3
), q
);
2611 r
= wrualfld(ccopy(t3
), t1
, t
, ct
, foff
, fsz
);
2612 q
= buildtree(COMOP
, q
, r
);
2613 q
= buildtree(COMOP
, q
, t3
);
2616 p
->n_left
= bt
? bt
: bcon(0);
2620 t3
= tempnode(0, t
, 0, 0);
2621 t4
= tempnode(0, t
, 0, 0);
2623 q
= rdualfld(ccopy(t1
), t
, ct
, foff
, fsz
);
2624 q
= buildtree(ASSIGN
, ccopy(t3
), q
);
2625 r
= buildtree(p
->n_op
==INCR
?PLUS
:MINUS
, ccopy(t3
), t2
);
2626 r
= buildtree(ASSIGN
, ccopy(t4
), r
);
2627 q
= buildtree(COMOP
, q
, r
);
2628 r
= wrualfld(t4
, t1
, t
, ct
, foff
, fsz
);
2629 q
= buildtree(COMOP
, q
, r
);
2632 q
= block(COMOP
, bt
, q
, t
, 0, 0);
2639 if (coptype(p
->n_op
) != LTYPE
)
2640 p
->n_left
= rmfldops(p
->n_left
);
2641 if (coptype(p
->n_op
) == BITYPE
)
2642 p
->n_right
= rmfldops(p
->n_right
);
2653 fwalk(p
, eprint
, 0);
2656 warner(Wunreachable_code
);
2666 if (p
->n_op
== ICON
&& p
->n_type
== VOID
)
2673 #if defined(MULTIPASS)
2680 myp2tree(p
); /* local action can be taken here */
2682 ty
= coptype(p
->n_op
);
2684 printf("%d\t", p
->n_op
);
2687 printf(CONFMT
, glval(p
));
2691 if (p
->n_op
== NAME
|| p
->n_op
== ICON
)
2694 printf("%d\t", p
->n_rval
);
2697 printf("%o\t", p
->n_type
);
2699 /* handle special cases */
2705 /* print external name */
2706 if ((q
= p
->n_sp
) != NULL
) {
2707 if ((q
->sclass
== STATIC
&& q
->slevel
> 0)) {
2708 printf(LABFMT
, q
->soffset
);
2711 q
->soname
? q
->soname
: exname(q
->sname
));
2720 /* print out size */
2721 /* use lhs size, in order to avoid hassles
2722 * with the structure `.' operator
2725 /* note: p->left not a field... */
2726 printf(CONFMT
, (CONSZ
)tsize(STRTY
, p
->n_left
->n_df
,
2728 printf("\t%d\t\n", talign(STRTY
, p
->n_left
->n_ap
));
2746 sptostr(struct symtab
*sp
)
2748 char *cp
= inlalloc(32);
2749 int n
= sp
->soffset
;
2752 snprintf(cp
, 32, LABFMT
, n
);
2759 struct attr
*oap
, *ap
;
2763 myp2tree(p
); /* local action can be taken here */
2765 /* Fix left imaginary types */
2766 if (ISITY(BTYPE(p
->n_type
)))
2767 MODTYPE(p
->n_type
, p
->n_type
- (FIMAG
-FLOAT
));
2769 /* cleanup attributes.
2770 * copy those that are supposed to go into pass2 */
2773 for (ap
= oap
; ap
; ap
= ap
->next
)
2774 if (ap
->atype
< ATTR_MI_MAX
)
2775 p
->n_ap
= attr_add(p
->n_ap
, attr_dup(ap
));
2776 /* XXX store size of attr in itself */
2778 ty
= coptype(p
->n_op
);
2784 if ((q
= p
->n_sp
) != NULL
) {
2785 if ((q
->sclass
== STATIC
&& q
->slevel
> 0)
2787 || q
->sflags
== SLBLNAME
2790 p
->n_name
= sptostr(q
);
2792 if ((p
->n_name
= q
->soname
) == NULL
)
2793 p
->n_name
= addname(exname(q
->sname
));
2803 /* STASG used for stack array init */
2804 if (p
->n_op
== STASG
&& ISARY(p
->n_type
)) {
2805 int size1
= (int)tsize(p
->n_type
, p
->n_left
->n_df
,
2806 p
->n_left
->n_ap
)/SZCHAR
;
2807 ap
->iarg(0) = (int)tsize(p
->n_type
, p
->n_right
->n_df
,
2808 p
->n_right
->n_ap
)/SZCHAR
;
2809 if (size1
< ap
->iarg(0))
2810 ap
->iarg(0) = size1
;
2811 ap
->iarg(1) = talign(p
->n_type
,
2812 p
->n_left
->n_ap
)/SZCHAR
;
2815 /* set up size parameters */
2816 ap
->iarg(0) = (int)((tsize(STRTY
, p
->n_left
->n_df
,
2817 p
->n_left
->n_ap
)+SZCHAR
-1)/SZCHAR
);
2818 ap
->iarg(1) = talign(STRTY
,p
->n_left
->n_ap
)/SZCHAR
;
2819 if (ap
->iarg(1) == 0)
2820 ap
->iarg(1) = 1; /* At least char for packed structs */
2831 if( ty
!= LTYPE
) p2tree( p
->n_left
);
2832 if( ty
== BITYPE
) p2tree( p
->n_right
);
2838 * Change void data types into char.
2841 delvoid(NODE
*p
, void *arg
)
2843 /* Convert "PTR undef" (void *) to "PTR uchar" */
2844 if (BTYPE(p
->n_type
) == VOID
)
2845 p
->n_type
= (p
->n_type
& ~BTMASK
) | UCHAR
;
2846 if (BTYPE(p
->n_type
) == BOOL
) {
2847 if (p
->n_op
== SCONV
&& p
->n_type
== BOOL
) {
2848 /* create a jump and a set */
2852 r
= tempnode(0, BOOL_TYPE
, NULL
, 0);
2853 cbranch(buildtree(EQ
, p
->n_left
, bcon(0)),
2854 bcon(l
= getlab()));
2856 ecode(buildtree(ASSIGN
, tcopy(r
), bcon(1)));
2857 branch(l2
= getlab());
2859 ecode(buildtree(ASSIGN
, r
, bcon(0)));
2862 p
->n_type
= (p
->n_type
& ~BTMASK
) | BOOL_TYPE
;
2868 * Change calls inside calls to separate statement.
2871 deldcall(NODE
*p
, int split
)
2876 if (cdope(o
) & CALLFLG
) {
2878 q
= cstknode(p
->n_type
, p
->n_df
, p
->n_ap
);
2880 q
= block(ASSIGN
, q
, p
, p
->n_type
, p
->n_df
, p
->n_ap
);
2886 if (coptype(o
) == BITYPE
)
2887 p
->n_right
= deldcall(p
->n_right
, split
);
2888 if (coptype(o
) != LTYPE
)
2889 p
->n_left
= deldcall(p
->n_left
, split
);
2893 #ifndef WORD_ADDRESSED
2896 pprop(NODE
*p
, TWORD t
, struct attr
*ap
)
2902 if (p
->n_op
== TEMP
&& p
->n_type
!= t
&&
2903 !(ISPTR(p
->n_type
) && ISPTR(t
))) {
2904 cerror("TEMP type change: %x -> %x", p
->n_type
, t
);
2915 t2
= p
->n_left
->n_type
;
2916 if (p
->n_left
->n_op
== TEMP
) {
2917 /* Will be converted to memory in pass2 */
2918 if (!ISPTR(t2
) && DECREF(t
) != t2
)
2919 ; /* XXX cannot convert this */
2921 p
->n_left
->n_type
= DECREF(t
);
2924 if (ISPTR(t2
) && !ISPTR(DECREF(t
)))
2925 break; /* not quite correct */
2935 if (!ISPTR(p
->n_left
->n_type
)) {
2936 if (!ISPTR(p
->n_right
->n_type
))
2937 cerror("no * in PLUS");
2938 p
->n_right
= pprop(p
->n_right
, t
, ap
);
2940 p
->n_left
= pprop(p
->n_left
, t
, ap
);
2945 if (ISPTR(p
->n_left
->n_type
)) {
2946 if (ISPTR(p
->n_right
->n_type
))
2947 break; /* change both */
2948 p
->n_left
= pprop(p
->n_left
, t
, ap
);
2950 p
->n_right
= pprop(p
->n_right
, t
, ap
);
2955 case STCALL
: /* may end up here if struct passed in regs */
2959 case STASG
: /* if struct is cast to pointer */
2966 if (coptype(o
) == LTYPE
)
2970 fwalk(p
, eprint
, 0);
2972 cerror("pprop op error %d\n", o
);
2974 if (coptype(o
) == BITYPE
)
2975 p
->n_right
= pprop(p
->n_right
, t
, ap
);
2976 if (coptype(o
) != LTYPE
)
2977 p
->n_left
= pprop(p
->n_left
, t
, ap
);
2982 * Search for PCONV's that can be removed while still keeping
2983 * the type correctness.
2990 int ot
= coptype(o
);
2994 p
->n_left
= rmpconv(p
->n_left
);
2996 p
->n_right
= rmpconv(p
->n_right
);
3000 if (nncon(l
) || (cdope(l
->n_op
) & CALLFLG
))
3001 ; /* Let any nonamed constant be cast to pointer directly */
3002 else if (l
->n_type
>= INTPTR
&& l
->n_op
== ICON
) {
3003 /* named constants only if >= pointer size */
3004 /* create INTPTR type */
3009 } else if (!ISPTR(l
->n_type
))
3011 q
= pprop(p
->n_left
, p
->n_type
, p
->n_ap
);
3020 /* walk the tree and write out the nodes.. */
3029 if (q
->n_op
== UMUL
)
3031 if (cdope(q
->n_op
)&CALLFLG
&&
3032 attr_find(q
->n_ap
, GCC_ATYP_WARN_UNUSED_RESULT
))
3033 werror("return value ignored");
3036 #ifndef WORD_ADDRESSED
3042 walkf(p
, delvoid
, 0);
3045 printf("Fulltree:\n");
3046 fwalk(p
, eprint
, 0);
3050 #if !defined(MULTIPASS)
3051 send_passt(IP_NODE
, p
);
3056 * Send something further on to the next pass.
3059 send_passt(int type
, ...)
3061 struct interpass
*ip
;
3062 struct interpass_prolog
*ipp
;
3068 if (cftnsp
== NULL
&& type
!= IP_ASM
) {
3070 cerror("no function");
3072 if (type
== IP_NODE
)
3073 tfree(va_arg(ap
, NODE
*));
3076 if (type
== IP_PROLOG
|| type
== IP_EPILOG
)
3077 sz
= sizeof(struct interpass_prolog
);
3079 sz
= sizeof(struct interpass
);
3083 ip
->lineno
= lineno
;
3086 ip
->ip_node
= va_arg(ap
, NODE
*);
3087 if (ip
->ip_node
->n_op
== LABEL
) {
3088 NODE
*p
= ip
->ip_node
;
3089 ip
->ip_lbl
= (int)glval(p
->n_left
);
3090 ip
->type
= IP_DEFLAB
;
3096 locctr(PROG
, cftnsp
);
3101 inftn
= type
== IP_PROLOG
? 1 : 0;
3102 ipp
= (struct interpass_prolog
*)ip
;
3103 ipp
->ipp_autos
= va_arg(ap
, int);
3104 ipp
->ipp_name
= va_arg(ap
, char *);
3105 ipp
->ipp_type
= va_arg(ap
, TWORD
);
3106 ipp
->ipp_vis
= va_arg(ap
, int);
3107 ip
->ip_lbl
= va_arg(ap
, int);
3108 ipp
->ip_tmpnum
= va_arg(ap
, int);
3109 ipp
->ip_lblnum
= crslab
;
3110 if (type
== IP_PROLOG
)
3114 ip
->ip_lbl
= va_arg(ap
, int);
3117 if (blevel
== 0) { /* outside function */
3118 printf("%s", va_arg(ap
, char *));
3120 locctr(NOSEG
, NULL
);
3123 ip
->ip_asm
= va_arg(ap
, char *);
3126 cerror("bad send_passt type %d", type
);
3129 pass1_lastchance(ip
); /* target-specific info */
3141 #define SNAM(x,y) case x: return #y;
3143 SNAM(QUALIFIER
,QUALIFIER
)
3171 SNAM(ATTRIB
,ATTRIBUTE
)
3172 SNAM(TYMERGE
,TYMERGE
)
3177 SNAM(XREAL
,__real__
)
3178 SNAM(XIMAG
,__imag__
)
3181 cerror("bad copst %d", op
);
3183 return 0; /* XXX gcc */
3217 return BITYPE
|LOGFLG
;
3219 return UTYPE
|LOGFLG
;
3221 return BITYPE
|ASGFLG
|ASGOPFLG
;
3223 return BITYPE
|ASGFLG
|ASGOPFLG
|FLOFLG
|SIMPFLG
|COMMFLG
;
3225 return BITYPE
|FLOFLG
|SIMPFLG
|ASGFLG
|ASGOPFLG
;
3227 return BITYPE
|FLOFLG
|MULFLG
|ASGFLG
|ASGOPFLG
;
3231 return BITYPE
|SIMPFLG
|COMMFLG
|ASGFLG
|ASGOPFLG
;
3233 return BITYPE
|FLOFLG
|MULFLG
|DIVFLG
|ASGFLG
|ASGOPFLG
;
3235 return BITYPE
|DIVFLG
|ASGFLG
|ASGOPFLG
;
3238 return BITYPE
|SHFFLG
|ASGFLG
|ASGOPFLG
;
3241 return BITYPE
|ASGFLG
;
3243 cerror("cdope missing op %d", op
);
3244 return 0; /* XXX gcc */
3248 * make a fresh copy of p
3258 switch (coptype(q
->n_op
)) {
3260 q
->n_right
= ccopy(p
->n_right
);
3262 q
->n_left
= ccopy(p
->n_left
);
3271 return block(LABEL
, bcon(label
), NIL
, 0, 0, 0);
3275 * set PROG-seg label.
3280 reached
= 1; /* Will this always be correct? */
3281 send_passt(IP_NODE
, nlabel(label
));
3285 * Perform integer promotion on node n.
3290 if ((n
->n_type
>= CHAR
&& n
->n_type
< INT
) || n
->n_type
== BOOL
) {
3291 if ((n
->n_type
== UCHAR
&& MAX_UCHAR
> MAX_INT
) ||
3292 (n
->n_type
== USHORT
&& MAX_USHORT
> MAX_INT
))
3293 return makety(n
, UNSIGNED
, 0, 0, 0);
3294 return makety(n
, INT
, 0, 0, 0);
3300 * Return CON/VOL/0, whichever are active for the current type.
3303 cqual(TWORD t
, TWORD q
)
3306 t
= DECREF(t
), q
= DECQAL(q
);
3309 return q
& (CON
|VOL
);
3314 * Return a number for internal labels.