1 /* $Id: gcc_compat.c,v 1.124 2023/07/23 08:55:09 ragge Exp $ */
3 * Copyright (c) 2004 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 * Routines to support some of the gcc extensions to C.
55 * Do NOT change the order of these entries unless you know
58 /* 0 */ { "__asm", NULL
, C_ASM
},
59 /* 1 */ { "__signed", NULL
, 0 },
60 /* 2 */ { "__inline", NULL
, 0 },
61 /* 3 */ { "__const", NULL
, 0 },
62 /* 4 */ { "__asm__", NULL
, C_ASM
},
63 /* 5 */ { "__inline__", NULL
, 0 },
64 /* 6 */ { "__thread", NULL
, 0 },
65 /* 7 */ { "__FUNCTION__", NULL
, 0 },
66 /* 8 */ { "__volatile", NULL
, 0 },
67 /* 9 */ { "__volatile__", NULL
, 0 },
68 /* 10 */{ "__restrict", NULL
, -1 },
69 /* 11 */{ "__typeof__", NULL
, C_TYPEOF
},
70 /* 12 */{ "typeof", NULL
, C_TYPEOF
},
71 /* 13 */{ "__extension__", NULL
, -1 },
72 /* 14 */{ "__signed__", NULL
, 0 },
73 /* 15 */{ "__attribute__", NULL
, 0 },
74 /* 16 */{ "__attribute", NULL
, 0 },
75 /* 17 */{ "__real__", NULL
, 0 },
76 /* 18 */{ "__imag__", NULL
, 0 },
77 /* 19 */{ "__builtin_offsetof", NULL
, PCC_OFFSETOF
},
78 /* 20 */{ "__PRETTY_FUNCTION__", NULL
, 0 },
79 /* 21 */{ "__alignof__", NULL
, C_ALIGNOF
},
80 /* 22 */{ "__typeof", NULL
, C_TYPEOF
},
81 /* 23 */{ "__alignof", NULL
, C_ALIGNOF
},
82 /* 24 */{ "__restrict__", NULL
, -1 },
88 #define G77_INTEGER LONG
89 #define G77_UINTEGER ULONG
90 #elif SZFLOAT == SZINT
91 #define G77_INTEGER INT
92 #define G77_UINTEGER UNSIGNED
96 #if SZFLOAT*2 == SZLONG
97 #define G77_LONGINT LONG
98 #define G77_ULONGINT ULONG
99 #elif SZFLOAT*2 == SZLONGLONG
100 #define G77_LONGINT LONGLONG
101 #define G77_ULONGINT ULONGLONG
103 #error fix g77 long stuff
106 static TWORD g77t
[] = { G77_INTEGER
, G77_UINTEGER
, G77_LONGINT
, G77_ULONGINT
};
107 static char *g77n
[] = { "__g77_integer", "__g77_uinteger",
108 "__g77_longint", "__g77_ulongint" };
111 static char *loti
, *hiti
, *TISTR
;
112 static char *lotf
, *hitf
, *TFSTR
;
113 static char *loctf
, *hictf
, *loitf
, *hiitf
, *TCSTR
;
114 static struct symtab
*tisp
, *tfsp
, *tcsp
, *ucmpti2sp
, *cmpti2sp
, *subvti3sp
,
115 *addvti3sp
, *mulvti3sp
, *divti3sp
, *udivti3sp
, *modti3sp
, *umodti3sp
,
116 *ashlti3sp
, *ashrti3sp
, *lshrti3sp
, *floatuntixfsp
;
128 { &cmpti2sp
, "__cmpti2", INT
, 0 },
129 { &ucmpti2sp
, "__ucmpti2", INT
, 0 },
131 { &addvti3sp
, "__addvti3", STRTY
, 1 },
132 { &subvti3sp
, "__subvti3", STRTY
, 1 },
133 { &mulvti3sp
, "__mulvti3", STRTY
, 1 },
134 { &divti3sp
, "__divti3", STRTY
, 1 },
135 { &modti3sp
, "__modti3", STRTY
, 1 },
137 { &udivti3sp
, "__udivti3", STRTY
, 2 },
138 { &umodti3sp
, "__umodti3", STRTY
, 2 },
139 { &ashlti3sp
, "__ashlti3", STRTY
, 2 },
140 { &ashrti3sp
, "__ashrti3", STRTY
, 2 },
141 { &lshrti3sp
, "__lshrti3", STRTY
, 2 },
143 { &floatuntixfsp
, "__floatuntixf", LDOUBLE
, 0 },
147 static struct symtab
*
148 addftn(char *n
, TWORD t
)
150 NODE
*p
= block(TYPE
, 0, 0, 0, 0, 0);
153 sp
= lookup(addname(n
), 0);
154 p
->n_type
= INCREF(t
) + (FTN
-PTR
);
156 p
->n_df
= memset(permalloc(sizeof(union dimfun
)), 0,
157 sizeof(union dimfun
));
163 static struct symtab
*
164 addstr(char *n
, char *typ
)
166 NODE
*p
= block(NAME
, NIL
, NIL
, FLOAT
, 0, 0);
171 extern struct rstack
*rpole
;
173 p
->n_type
= ctype(ULONGLONG
);
174 rpole
= rp
= bstruct(NULL
, STNAME
, NULL
);
178 } else if (typ
[1] == 'F') {
182 soumemb(p
, loctf
, 0);
183 soumemb(p
, hictf
, 0);
184 soumemb(p
, loitf
, 0);
185 soumemb(p
, hiitf
, 0);
188 sp
= q
->n_sp
= lookup(addname(n
), 0);
190 ap
= attr_new(GCC_ATYP_MODE
, 3);
191 ap
->sarg(0) = addname(typ
);
193 sp
->sap
= attr_add(sp
->sap
, ap
);
211 for (kwp
= kw
; kwp
->name
; kwp
++)
212 kwp
->ptr
= addname(kwp
->name
);
214 for (i
= 0; i
< 4; i
++) {
217 p
= block(NAME
, NIL
, NIL
, t
, NULL
, 0);
218 sp
= lookup(addname(g77n
[i
]), 0);
228 loti
= addname("__loti");
229 hiti
= addname("__hiti");
230 TISTR
= addname("TI");
231 tisp
= addstr("0ti", "TI");
233 lotf
= addname("__lotf");
234 hitf
= addname("__hitf");
235 TFSTR
= addname("TF");
236 tfsp
= addstr("0tf", "TF");
238 loctf
= addname("__loctf");
239 hictf
= addname("__hictf");
240 loitf
= addname("__loitf");
241 hiitf
= addname("__hiitf");
242 TCSTR
= addname("TC");
243 tcsp
= addstr("0tc", "TC");
245 ap2
= attr_new(GCC_ATYP_MODE
, 3);
246 ap2
->sarg(0) = TISTR
;
248 ap2
= attr_add(tisp
->sap
, ap2
);
250 for (i
= 0; i
< (int)(sizeof(tifuns
)/sizeof(tifuns
[0])); i
++) {
251 *tifuns
[i
].sp
= addftn(tifuns
[i
].fun
, tifuns
[i
].type
);
252 switch (tifuns
[i
].apt
) {
253 case 0: /* nothing */
255 case 1: /* just tisp */
256 (*tifuns
[i
].sp
)->sap
= tisp
->sap
;
258 case 2: /* mode string */
259 (*tifuns
[i
].sp
)->sap
= ap2
;
268 #define TS "\n#pragma tls\n# %d\n"
269 #define TLLEN sizeof(TS)+10
271 * See if a string matches a gcc keyword.
274 gcc_keyword(char *str
)
276 extern int inattr
, parlvl
, parbal
;
277 char tlbuf
[TLLEN
], *tw
;
281 /* XXX hack, should pass everything in expressions */
282 if (str
== kw
[21].ptr
)
288 for (i
= 0, kwp
= kw
; kwp
->name
; kwp
++, i
++)
291 if (kwp
->name
== NULL
)
296 case 1: /* __signed */
297 case 14: /* __signed__ */
298 yylval
.type
= SIGNED
;
300 case 2: /* __inline */
301 case 5: /* __inline__ */
302 yylval
.type
= INLINE
;
304 case 3: /* __const */
307 case 6: /* __thread */
308 snprintf(tlbuf
, TLLEN
, TS
, lineno
);
309 tw
= &tlbuf
[strlen(tlbuf
)];
313 case 7: /* __FUNCTION__ */
314 case 20: /* __PRETTY_FUNCTION__ */
315 if (cftnsp
== NULL
) {
316 uerror("%s outside function", kwp
->name
);
319 yylval
.strp
= cftnsp
->sname
; /* XXX - not C99 */
321 case 8: /* __volatile */
322 case 9: /* __volatile__ */
325 case 15: /* __attribute__ */
326 case 16: /* __attribute */
330 case 17: /* __real__ */
331 yylval
.intval
= XREAL
;
333 case 18: /* __imag__ */
334 yylval
.intval
= XIMAG
;
337 cerror("gcc_keyword");
342 #define TARGET_ATTR(p, sue) 0
345 #define ALMAX (ALLDOUBLE > ALLONGLONG ? ALLDOUBLE : ALLONGLONG)
348 /* allowed number of args */
353 /* arg # is a name */
358 /* arg # is "string" */
372 } atax
[GCC_ATYP_MAX
] = {
373 CS(ATTR_NONE
) { 0, NULL
},
374 CS(ATTR_COMPLEX
) { 0, NULL
},
375 CS(xxxATTR_BASETYP
) { 0, NULL
},
376 CS(ATTR_QUALTYP
) { 0, NULL
},
377 CS(xxxATTR_STRUCT
) { 0, NULL
},
378 CS(xxxATTR_ALIGNED
) { A_0ARG
|A_1ARG
, "aligned" },
379 CS(ATTR_NORETURN
) { A_0ARG
, "noreturn" },
380 CS(ATTR_P1LABELS
) { A_0ARG
, "p1labels" },
381 CS(ATTR_SONAME
) { A_1ARG
|A1_STR
, "soname" },
382 CS(GCC_ATYP_PACKED
) { A_0ARG
|A_1ARG
, "packed" },
383 CS(GCC_ATYP_SECTION
) { A_1ARG
|A1_STR
, "section" },
384 CS(GCC_ATYP_TRANSP_UNION
) { A_0ARG
, "transparent_union" },
385 CS(GCC_ATYP_UNUSED
) { A_0ARG
, "unused" },
386 CS(GCC_ATYP_DEPRECATED
) { A_0ARG
, "deprecated" },
387 CS(GCC_ATYP_MAYALIAS
) { A_0ARG
, "may_alias" },
388 CS(GCC_ATYP_MODE
) { A_1ARG
|A1_NAME
, "mode" },
389 CS(GCC_ATYP_FORMAT
) { A_3ARG
|A1_NAME
, "format" },
390 CS(GCC_ATYP_NONNULL
) { A_MANY
, "nonnull" },
391 CS(GCC_ATYP_SENTINEL
) { A_0ARG
|A_1ARG
, "sentinel" },
392 CS(GCC_ATYP_WEAK
) { A_0ARG
, "weak" },
393 CS(GCC_ATYP_FORMATARG
) { A_1ARG
, "format_arg" },
394 CS(GCC_ATYP_GNU_INLINE
) { A_0ARG
, "gnu_inline" },
395 CS(GCC_ATYP_MALLOC
) { A_0ARG
, "malloc" },
396 CS(GCC_ATYP_NOTHROW
) { A_0ARG
, "nothrow" },
397 CS(GCC_ATYP_CONST
) { A_0ARG
, "const" },
398 CS(GCC_ATYP_PURE
) { A_0ARG
, "pure" },
399 CS(GCC_ATYP_CONSTRUCTOR
) { A_0ARG
, "constructor" },
400 CS(GCC_ATYP_DESTRUCTOR
) { A_0ARG
, "destructor" },
401 CS(GCC_ATYP_VISIBILITY
) { A_1ARG
|A1_STR
, "visibility" },
402 CS(GCC_ATYP_STDCALL
) { A_0ARG
, "stdcall" },
403 CS(GCC_ATYP_CDECL
) { A_0ARG
, "cdecl" },
404 CS(GCC_ATYP_WARN_UNUSED_RESULT
) { A_0ARG
, "warn_unused_result" },
405 CS(GCC_ATYP_USED
) { A_0ARG
, "used" },
406 CS(GCC_ATYP_NO_INSTR_FUN
) { A_0ARG
, "no_instrument_function" },
407 CS(GCC_ATYP_NOINLINE
) { A_0ARG
, "noinline" },
408 CS(GCC_ATYP_ALIAS
) { A_1ARG
|A1_STR
, "alias" },
409 CS(GCC_ATYP_WEAKREF
) { A_0ARG
|A_1ARG
|A1_STR
, "weakref" },
410 CS(GCC_ATYP_ALLOCSZ
) { A_1ARG
|A_2ARG
, "alloc_size" },
411 CS(GCC_ATYP_ALW_INL
) { A_0ARG
, "always_inline" },
412 CS(GCC_ATYP_TLSMODEL
) { A_1ARG
|A1_STR
, "tls_model" },
413 CS(GCC_ATYP_ALIASWEAK
) { A_1ARG
|A1_STR
, "aliasweak" },
414 CS(GCC_ATYP_RETURNS_TWICE
) { A_0ARG
, "returns_twice" },
415 CS(GCC_ATYP_WARNING
) { A_1ARG
|A1_STR
, "warning" },
416 CS(GCC_ATYP_NOCLONE
) { A_0ARG
, "noclone" },
417 CS(GCC_ATYP_REGPARM
) { A_1ARG
, "regparm" },
418 CS(GCC_ATYP_FASTCALL
) { A_0ARG
, "fastcall" },
420 CS(GCC_ATYP_BOUNDED
) { A_3ARG
|A_MANY
|A1_NAME
, "bounded" },
422 CS(GCC_ATYP_WEAKIMPORT
) { A_0ARG
, "weak_import" },
425 #if SZPOINT(CHAR) == SZLONGLONG
431 struct atax mods
[] = {
446 { INT
, "libgcc_cmp_return" },
447 { INT
, "libgcc_shift_count" },
448 { LONG
, "unwind_word" },
458 #define ATSZ (sizeof(mods)/sizeof(mods[0]))
461 amatch(char *s
, struct atax
*at
, int mx
)
466 if (s
[0] == '_' && s
[1] == '_')
469 if (len
> 2 && s
[len
-1] == '_' && s
[len
-2] == '_')
471 for (i
= 0; i
< mx
; i
++) {
472 char *t
= at
[i
].name
;
473 if (t
!= NULL
&& strncmp(s
, t
, len
) == 0 && t
[len
] == 0)
480 setaarg(int str
, union aarg
*aa
, NODE
*p
)
483 if (((str
& (A1_STR
|A2_STR
|A3_STR
)) && p
->n_op
!= STRING
) ||
484 ((str
& (A1_NAME
|A2_NAME
|A3_NAME
)) && p
->n_op
!= NAME
))
485 uerror("bad arg to attribute");
486 if (p
->n_op
== STRING
) {
487 aa
->sarg
= p
->n_name
; /* saved in cgram.y */
489 aa
->sarg
= (char *)p
->n_sp
;
492 aa
->iarg
= (int)icons(eve(p
));
496 * Parse attributes from an argument list.
503 char *name
= NULL
, *c
;
506 if (p
->n_op
== NAME
) {
507 name
= (char *)p
->n_sp
;
508 } else if (p
->n_op
== CALL
|| p
->n_op
== UCALL
) {
509 name
= (char *)p
->n_left
->n_sp
;
510 } else if (p
->n_op
== ICON
&& p
->n_type
== STRTY
) {
513 cerror("bad variable attribute");
515 if ((attr
= amatch(name
, atax
, GCC_ATYP_MAX
)) == 0) {
516 warner(Wattributes
, name
);
522 for (narg
= 1, q
= p
->n_right
; q
->n_op
== CM
; q
= q
->n_left
)
526 if (!(cw
& A_MANY
) && ((narg
> 3) || ((cw
& (1 << narg
)) == 0))) {
527 uerror("wrong attribute arg count");
530 ap
= attr_new(attr
, 3); /* XXX should be narg */
544 setaarg(cw
& (A3_NAME
|A3_STR
), &ap
->aa
[2], q
->n_right
);
550 setaarg(cw
& (A2_NAME
|A2_STR
), &ap
->aa
[1], q
->n_right
);
556 setaarg(cw
& (A1_NAME
|A1_STR
), &ap
->aa
[0], q
);
563 /* some attributes must be massaged special */
565 case xxxATTR_ALIGNED
:
567 ap
->aa
[0].iarg
= ALMAX
;
569 ap
->aa
[0].iarg
*= SZCHAR
;
571 case GCC_ATYP_PACKED
:
573 ap
->aa
[0].iarg
= 1; /* bitwise align */
575 ap
->aa
[0].iarg
*= SZCHAR
;
578 case GCC_ATYP_VISIBILITY
:
580 if (strcmp(c
, "default") && strcmp(c
, "hidden") &&
581 strcmp(c
, "internal") && strcmp(c
, "protected"))
582 werror("unknown visibility %s", c
);
585 case GCC_ATYP_TLSMODEL
:
587 if (strcmp(c
, "global-dynamic") && strcmp(c
, "local-dynamic") &&
588 strcmp(c
, "initial-exec") && strcmp(c
, "local-exec"))
589 werror("unknown tls model %s", c
);
600 * Extract attributes from a node tree and return attribute entries
601 * based on its contents.
604 gcc_attr_parse(NODE
*p
)
615 b
= gcc_attr_parse(p
->n_left
);
616 c
= gcc_attr_parse(p
->n_right
);
618 b
= b
? attr_add(b
, c
) : c
;
624 * Fixup struct/unions depending on attributes.
627 gcc_tcattrfix(NODE
*p
)
632 int sz
, coff
, csz
, al
, oal
, mxal
;
634 if (!ISSOU(p
->n_type
)) /* only for structs or unions */
636 if ((ap
= attr_find(p
->n_ap
, GCC_ATYP_PACKED
)) == NULL
)
637 return; /* nothing to fix */
642 /* Must repack struct */
644 for (sp
= strmemb(p
->n_td
->ss
); sp
; sp
= sp
->snext
) {
645 oal
= talign(sp
->stype
, sp
->sss
);
650 if (sp
->sclass
& FIELD
)
651 sz
= sp
->sclass
&FLDSIZ
;
653 sz
= (int)tsize(sp
->stype
, sp
->sdf
, sp
->sss
);
654 sp
->soffset
= upoff(sz
, oal
, &coff
);
657 if (p
->n_type
== UNIONTY
)
661 mxal
= ALCHAR
; /* for bitfields */
662 SETOFF(csz
, mxal
); /* Roundup to whatever */
670 * gcc-specific pragmas.
676 extern char *pragstore
;
678 if (strcmp((t
= pragtok(NULL
)), "diagnostic") == 0) {
681 if (strcmp((t
= pragtok(NULL
)), "ignored") == 0)
683 else if (strcmp(t
, "warning") == 0)
685 else if (strcmp(t
, "error") == 0)
690 if (eat('\"') || eat('-'))
693 for (t
= pragstore
; *t
&& *t
!= '\"'; t
++)
698 Wset(pragstore
+ 1, warn
, err
);
700 } else if (strcmp(t
, "poison") == 0) {
701 /* currently ignore */;
702 } else if (strcmp(t
, "visibility") == 0) {
703 /* currently ignore */;
704 } else if (strcmp(t
, "system_header") == 0) {
705 /* currently ignore */;
707 werror("gcc pragma unsupported");
712 * Fixup types when modes given in defid().
726 if ((ap
= attr_find(p
->n_ap
, GCC_ATYP_MODE
)) == NULL
)
729 u
= ISUNSIGNED(BTYPE(p
->n_type
));
730 if ((i
= amatch(ap
->aa
[0].sarg
, mods
, ATSZ
)) == 0) {
731 werror("unknown mode arg %s", ap
->aa
[0].sarg
);
735 if (i
>= 1 && i
<= MAXTYPES
) {
736 MODTYPE(p
->n_type
, ctype(i
));
738 p
->n_type
= ENUNSIGN(p
->n_type
);
744 if (BTYPE(p
->n_type
) == STRTY
)
746 MODTYPE(p
->n_type
, tisp
->stype
);
749 if (ap
->iarg(1) == u
)
751 /* must add a new mode struct to avoid overwriting */
752 a2
= attr_new(GCC_ATYP_MODE
, 3);
753 a2
->sarg(0) = ap
->sarg(0);
755 p
->n_ap
= attr_add(p
->n_ap
, a2
);
761 /* Destination should have been converted to a struct already */
762 if (BTYPE(p
->n_type
) != STRTY
)
763 uerror("gcc_modefix: complex not STRTY");
764 i
-= (FCOMPLEX
-FLOAT
);
765 ss
= strattr(p
->n_td
);
767 if (sp
->stype
== (unsigned)i
)
768 return; /* Already correct type */
769 /* we must change to another struct */
770 s
= i
== FLOAT
? "0f" :
772 i
== LDOUBLE
? "0l" : 0;
773 sp
= lookup(addname(s
), 0);
774 for (ap
= sp
->sap
; ap
!= NULL
; ap
= ap
->next
)
775 p
->n_ap
= attr_add(p
->n_ap
, attr_dup(ap
));
779 cerror("gcc_modefix");
786 * Return ap if this node is a TI node, else NULL.
793 if (p
->n_type
!= STRTY
)
795 if ((ap
= attr_find(p
->n_ap
, GCC_ATYP_MODE
)) == NULL
)
797 if (strcmp(ap
->sarg(0), TISTR
) && strcmp(ap
->sarg(0), TFSTR
) &&
798 strcmp(ap
->sarg(0), TCSTR
))
806 struct symtab
*sp
, *sp2
;
811 /* allocate space on stack */
812 snprintf(buf
, 12, "%d", getlab());
816 q
= block(TYPE
, NIL
, NIL
, sp2
->stype
, sp2
->sdf
, sp2
->sss
);
823 #define biop(x,y,z) block(x, y, z, INT, 0, 0)
825 * Create a ti node from something not a ti node.
826 * This usually means: allocate space on stack, store val, give stack address.
829 ticast(NODE
*p
, int u
)
842 if (u
== 0 && glval(p
) < 0)
844 q
= eve(biop(DOT
, bdty(NAME
, n
), bdty(NAME
, loti
)));
845 q
= buildtree(ASSIGN
, q
, p
);
846 p
= biop(DOT
, bdty(NAME
, n
), bdty(NAME
, hiti
));
847 p
= eve(biop(ASSIGN
, p
, bcon(val
)));
848 q
= buildtree(COMOP
, q
, p
);
849 p
= buildtree(COMOP
, q
, eve(bdty(NAME
, n
)));
853 u2
= ISUNSIGNED(p
->n_type
);
854 q
= eve(biop(DOT
, bdty(NAME
, n
), bdty(NAME
, loti
)));
855 q
= buildtree(ASSIGN
, q
, p
);
856 p
= biop(DOT
, bdty(NAME
, n
), bdty(NAME
, hiti
));
858 p
= eve(biop(ASSIGN
, p
, bcon(0)));
860 q
= buildtree(ASSIGN
, eve(p1tcopy(p
)), q
);
861 p
= buildtree(RSEQ
, eve(p
), bcon(SZLONG
-1));
863 q
= buildtree(COMOP
, q
, p
);
864 p
= buildtree(COMOP
, q
, eve(bdty(NAME
, n
)));
871 * Check if we may have to do a cast to/from TI.
874 gcc_eval_ticast(int op
, NODE
*p1
, NODE
*p2
)
876 struct attr
*a1
, *a2
;
879 a2
= NULL
; /* XXX flow analysis */
880 if ((a1
= isti(p1
)) == NULL
&& (a2
= isti(p2
)) == NULL
)
887 cerror("gcc_eval_ticast error");
888 switch (p1
->n_type
) {
890 p2
= doacall(floatuntixfsp
,
891 nametree(floatuntixfsp
), p2
);
896 p2
= cast(structref(p2
, DOT
, loti
), p1
->n_type
, 0);
902 uerror("gcc_eval_ticast: %d", p1
->n_type
);
906 /* p2 can be anything, but we must cast it to p1 */
909 if (p2
->n_type
== STRTY
&&
910 (a2
= attr_find(p2
->n_ap
, GCC_ATYP_MODE
)) &&
911 strcmp(a2
->sarg(0), TISTR
) == 0) {
912 /* Already TI, just add extra mode bits */
913 a2
= attr_new(GCC_ATYP_MODE
, 3);
916 p2
->n_ap
= attr_add(p2
->n_ap
, a2
);
925 * Apply a unary op on a TI value.
928 gcc_eval_tiuni(int op
, NODE
*p1
)
933 if ((a1
= isti(p1
)) == NULL
)
938 p
= ticast(bcon(0), 0);
939 p
= buildtree(CM
, p
, p1
);
940 p
= doacall(subvti3sp
, nametree(subvti3sp
), p
);
946 uerror("unsupported unary TI mode op %d", op
);
953 * Evaluate AND/OR/ER. p1 and p2 are pointers to ti struct.
956 gcc_andorer(int op
, NODE
*p1
, NODE
*p2
)
959 NODE
*p
, *t1
, *t2
, *p3
;
961 t1
= tempnode(0, p1
->n_type
, p1
->n_df
, p1
->pss
);
962 t2
= tempnode(0, p2
->n_type
, p2
->n_df
, p2
->pss
);
964 p1
= buildtree(ASSIGN
, p1tcopy(t1
), p1
);
965 p2
= buildtree(ASSIGN
, p1tcopy(t2
), p2
);
966 p
= buildtree(COMOP
, p1
, p2
);
968 p3
= buildtree(ADDROF
, eve(bdty(NAME
, n
)), NIL
);
969 p1
= buildtree(ASSIGN
, structref(p1tcopy(p3
), STREF
, hiti
),
970 buildtree(op
, structref(p1tcopy(t1
), STREF
, hiti
),
971 structref(p1tcopy(t2
), STREF
, hiti
)));
972 p
= buildtree(COMOP
, p
, p1
);
973 p1
= buildtree(ASSIGN
, structref(p1tcopy(p3
), STREF
, loti
),
974 buildtree(op
, structref(t1
, STREF
, loti
),
975 structref(t2
, STREF
, loti
)));
976 p
= buildtree(COMOP
, p
, p1
);
977 p
= buildtree(COMOP
, p
, buildtree(UMUL
, p3
, NIL
));
982 * Ensure that a 128-bit assign succeeds.
983 * If left is not TI, make right not TI,
984 * else if left _is_ TI, make right TI,
988 timodeassign(NODE
*p1
, NODE
*p2
)
990 struct attr
*a1
, *a2
;
994 if (a1
&& a2
== NULL
) {
995 p2
= ticast(p2
, a1
->iarg(1));
996 } else if (a1
== NULL
&& a2
) {
997 if (ISFTY(p1
->n_type
))
998 cerror("cannot TI float convert");
999 p2
= structref(p2
, DOT
, loti
);
1001 return buildtree(ASSIGN
, p1
, p2
);
1005 * Evaluate 128-bit operands.
1008 gcc_eval_timode(int op
, NODE
*p1
, NODE
*p2
)
1010 struct attr
*a1
, *a2
;
1013 int isu
= 0, gotti
, isaop
;
1016 return buildtree(op
, p1
, p2
);
1021 if (a1
== NULL
&& a2
== NULL
)
1025 return timodeassign(p1
, p2
);
1027 gotti
= (a1
!= NULL
);
1028 gotti
+= (a2
!= NULL
);
1035 if (a2
!= NULL
&& !isu
)
1039 p1
= ticast(p1
, isu
);
1040 a1
= attr_find(p1
->n_ap
, GCC_ATYP_MODE
);
1042 if (a2
== NULL
&& (cdope(op
) & SHFFLG
) == 0) {
1043 p2
= ticast(p2
, isu
);
1044 a2
= attr_find(p2
->n_ap
, GCC_ATYP_MODE
);
1054 /* change to call */
1055 sp
= isu
? ucmpti2sp
: cmpti2sp
;
1056 p
= doacall(sp
, nametree(sp
), buildtree(CM
, p1
, p2
));
1057 p
= buildtree(op
, p
, bcon(1));
1063 if (!ISPTR(p1
->n_type
))
1064 p1
= buildtree(ADDROF
, p1
, NIL
);
1065 if (!ISPTR(p2
->n_type
))
1066 p2
= buildtree(ADDROF
, p2
, NIL
);
1067 p
= gcc_andorer(op
, p1
, p2
);
1074 sp
= op
== LS
|| op
== LSEQ
? ashlti3sp
:
1075 isu
? lshrti3sp
: ashrti3sp
;
1076 p2
= cast(p2
, INT
, 0);
1077 /* XXX p1 p1tcopy may have side effects */
1078 p
= doacall(sp
, nametree(sp
), buildtree(CM
, p1tcopy(p1
), p2
));
1079 if (op
== LSEQ
|| op
== RSEQ
) {
1080 p
= buildtree(ASSIGN
, p1
, p
);
1095 isaop
= (cdope(op
)&ASGOPFLG
);
1098 sp
= op
== PLUS
? addvti3sp
:
1099 op
== MINUS
? subvti3sp
:
1100 op
== MUL
? mulvti3sp
:
1101 op
== DIV
? (isu
? udivti3sp
: divti3sp
) :
1102 op
== MOD
? (isu
? umodti3sp
: modti3sp
) : 0;
1103 /* XXX p1 p1tcopy may have side effects */
1104 p
= doacall(sp
, nametree(sp
), buildtree(CM
, p1tcopy(p1
), p2
));
1106 p
= buildtree(ASSIGN
, p1
, p
);
1112 uerror("unsupported TImode op %d", op
);
1121 dump_attr(struct attr
*ap
)
1123 printf("attributes; ");
1124 for (; ap
; ap
= ap
->next
) {
1125 if (ap
->atype
>= GCC_ATYP_MAX
) {
1126 printf("bad type %d, ", ap
->atype
);
1127 } else if (atax
[ap
->atype
].name
== 0) {
1128 char *c
= ap
->atype
== ATTR_COMPLEX
? "complex" :
1132 printf("%s: ", atax
[ap
->atype
].name
);
1133 if (atax
[ap
->atype
].typ
& A1_STR
)
1134 printf("%s ", ap
->sarg(0));
1136 printf("%d %d %d, ", ap
->iarg(0),
1137 ap
->iarg(1), ap
->iarg(2));