1/*      Id: gcc_compat.c,v 1.119 2015/11/13 17:11:40 ragge Exp      */
2/*      $NetBSD: gcc_compat.c,v 1.6 2016/02/09 20:37:32 plunky Exp $     */
3/*
4 * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * Routines to support some of the gcc extensions to C.
32 */
33#ifdef GCC_COMPAT
34
35#include "pass1.h"
36#include "cgram.h"
37
38#include <string.h>
39
40#define	NODE P1ND
41#define	nfree p1nfree
42#define	tfree p1tfree
43
44static struct kw {
45	char *name, *ptr;
46	int rv;
47} kw[] = {
48/*
49 * Do NOT change the order of these entries unless you know
50 * what you're doing!
51 */
52/* 0 */	{ "__asm", NULL, C_ASM },
53/* 1 */	{ "__signed", NULL, 0 },
54/* 2 */	{ "__inline", NULL, 0 },
55/* 3 */	{ "__const", NULL, 0 },
56/* 4 */	{ "__asm__", NULL, C_ASM },
57/* 5 */	{ "__inline__", NULL, 0 },
58/* 6 */	{ "__thread", NULL, 0 },
59/* 7 */	{ "__FUNCTION__", NULL, 0 },
60/* 8 */	{ "__volatile", NULL, 0 },
61/* 9 */	{ "__volatile__", NULL, 0 },
62/* 10 */{ "__restrict", NULL, -1 },
63/* 11 */{ "__typeof__", NULL, C_TYPEOF },
64/* 12 */{ "typeof", NULL, C_TYPEOF },
65/* 13 */{ "__extension__", NULL, -1 },
66/* 14 */{ "__signed__", NULL, 0 },
67/* 15 */{ "__attribute__", NULL, 0 },
68/* 16 */{ "__attribute", NULL, 0 },
69/* 17 */{ "__real__", NULL, 0 },
70/* 18 */{ "__imag__", NULL, 0 },
71/* 19 */{ "__builtin_offsetof", NULL, PCC_OFFSETOF },
72/* 20 */{ "__PRETTY_FUNCTION__", NULL, 0 },
73/* 21 */{ "__alignof__", NULL, C_ALIGNOF },
74/* 22 */{ "__typeof", NULL, C_TYPEOF },
75/* 23 */{ "__alignof", NULL, C_ALIGNOF },
76/* 24 */{ "__restrict__", NULL, -1 },
77	{ NULL, NULL, 0 },
78};
79
80/* g77 stuff */
81#if SZFLOAT == SZLONG
82#define G77_INTEGER LONG
83#define G77_UINTEGER ULONG
84#elif SZFLOAT == SZINT
85#define G77_INTEGER INT
86#define G77_UINTEGER UNSIGNED
87#else
88#error fix g77 stuff
89#endif
90#if SZFLOAT*2 == SZLONG
91#define G77_LONGINT LONG
92#define G77_ULONGINT ULONG
93#elif SZFLOAT*2 == SZLONGLONG
94#define G77_LONGINT LONGLONG
95#define G77_ULONGINT ULONGLONG
96#else
97#error fix g77 long stuff
98#endif
99
100static TWORD g77t[] = { G77_INTEGER, G77_UINTEGER, G77_LONGINT, G77_ULONGINT };
101static char *g77n[] = { "__g77_integer", "__g77_uinteger",
102	"__g77_longint", "__g77_ulongint" };
103
104#ifdef TARGET_TIMODE
105static char *loti, *hiti, *TISTR;
106static struct symtab *tisp, *ucmpti2sp, *cmpti2sp, *subvti3sp,
107	*addvti3sp, *mulvti3sp, *divti3sp, *udivti3sp, *modti3sp, *umodti3sp,
108	*ashldi3sp, *ashrdi3sp, *lshrdi3sp, *floatuntixfsp;
109
110static struct symtab *
111addftn(char *n, TWORD t)
112{
113	NODE *p = block(TYPE, 0, 0, 0, 0, 0);
114	struct symtab *sp;
115
116	sp = lookup(addname(n), 0);
117	p->n_type = INCREF(t) + (FTN-PTR);
118	p->n_sp = sp;
119	p->n_df = memset(permalloc(sizeof(union dimfun)), 0,
120	    sizeof(union dimfun));
121	defid(p, EXTERN);
122	nfree(p);
123	return sp;
124}
125
126static struct symtab *
127addstr(char *n)
128{
129	NODE *p = block(NAME, NIL, NIL, FLOAT, 0, 0);
130	struct symtab *sp;
131	NODE *q;
132	struct attr *ap;
133	struct rstack *rp;
134	extern struct rstack *rpole;
135
136	p->n_type = ctype(ULONGLONG);
137	rpole = rp = bstruct(NULL, STNAME, NULL);
138	soumemb(p, loti, 0);
139	soumemb(p, hiti, 0);
140	q = dclstruct(rp);
141	sp = q->n_sp = lookup(addname(n), 0);
142	defid(q, TYPEDEF);
143	ap = attr_new(GCC_ATYP_MODE, 3);
144	ap->sarg(0) = addname("TI");
145	ap->iarg(1) = 0;
146	sp->sap = attr_add(sp->sap, ap);
147	nfree(q);
148	nfree(p);
149
150	return sp;
151}
152#endif
153
154void
155gcc_init(void)
156{
157	struct kw *kwp;
158	NODE *p;
159	TWORD t;
160	int i, d_debug;
161
162	d_debug = ddebug;
163	ddebug = 0;
164	for (kwp = kw; kwp->name; kwp++)
165		kwp->ptr = addname(kwp->name);
166
167	for (i = 0; i < 4; i++) {
168		struct symtab *sp;
169		t = ctype(g77t[i]);
170		p = block(NAME, NIL, NIL, t, NULL, 0);
171		sp = lookup(addname(g77n[i]), 0);
172		p->n_sp = sp;
173		defid(p, TYPEDEF);
174		nfree(p);
175	}
176	ddebug = d_debug;
177#ifdef TARGET_TIMODE
178	{
179		struct attr *ap;
180
181		loti = addname("__loti");
182		hiti = addname("__hiti");
183		TISTR = addname("TI");
184
185		tisp = addstr("0ti");
186
187		cmpti2sp = addftn("__cmpti2", INT);
188		ucmpti2sp = addftn("__ucmpti2", INT);
189
190		addvti3sp = addftn("__addvti3", STRTY);
191		addvti3sp->sap = tisp->sap;
192		subvti3sp = addftn("__subvti3", STRTY);
193		subvti3sp->sap = tisp->sap;
194		mulvti3sp = addftn("__mulvti3", STRTY);
195		mulvti3sp->sap = tisp->sap;
196		divti3sp = addftn("__divti3", STRTY);
197		divti3sp->sap = tisp->sap;
198		modti3sp = addftn("__modti3", STRTY);
199		modti3sp->sap = tisp->sap;
200
201		ap = attr_new(GCC_ATYP_MODE, 3);
202		ap->sarg(0) = TISTR;
203		ap->iarg(1) = 1;
204		ap = attr_add(tisp->sap, ap);
205		udivti3sp = addftn("__udivti3", STRTY);
206		udivti3sp->sap = ap;
207		umodti3sp = addftn("__umodti3", STRTY);
208		umodti3sp->sap = ap;
209		ashldi3sp = addftn("__ashldi3", ctype(LONGLONG));
210		ashldi3sp->sap = ap;
211		ashrdi3sp = addftn("__ashrdi3", ctype(LONGLONG));
212		ashrdi3sp->sap = ap;
213		lshrdi3sp = addftn("__lshrdi3", ctype(LONGLONG));
214		lshrdi3sp->sap = ap;
215
216		floatuntixfsp = addftn("__floatuntixf", LDOUBLE);
217	}
218#endif
219}
220
221#define	TS	"\n#pragma tls\n# %d\n"
222#define	TLLEN	sizeof(TS)+10
223/*
224 * See if a string matches a gcc keyword.
225 */
226int
227gcc_keyword(char *str)
228{
229	extern int inattr, parlvl, parbal;
230	char tlbuf[TLLEN], *tw;
231	struct kw *kwp;
232	int i;
233
234	/* XXX hack, should pass everything in expressions */
235	if (str == kw[21].ptr)
236		return kw[21].rv;
237
238	if (inattr)
239		return 0;
240
241	for (i = 0, kwp = kw; kwp->name; kwp++, i++)
242		if (str == kwp->ptr)
243			break;
244	if (kwp->name == NULL)
245		return 0;
246	if (kwp->rv)
247		return kwp->rv;
248	switch (i) {
249	case 1:  /* __signed */
250	case 14: /* __signed__ */
251		yylval.type = SIGNED;
252		return C_TYPE;
253	case 2: /* __inline */
254	case 5: /* __inline__ */
255		yylval.type = INLINE;
256		return C_FUNSPEC;
257	case 3: /* __const */
258		yylval.type = CON;
259		return C_QUALIFIER;
260	case 6: /* __thread */
261		snprintf(tlbuf, TLLEN, TS, lineno);
262		tw = &tlbuf[strlen(tlbuf)];
263		while (tw > tlbuf)
264			cunput(*--tw);
265		return -1;
266	case 7: /* __FUNCTION__ */
267	case 20: /* __PRETTY_FUNCTION__ */
268		if (cftnsp == NULL) {
269			uerror("%s outside function", kwp->name);
270			yylval.strp = "";
271		} else
272			yylval.strp = cftnsp->sname; /* XXX - not C99 */
273		return C_STRING;
274	case 8: /* __volatile */
275	case 9: /* __volatile__ */
276		yylval.type = VOL;
277		return C_QUALIFIER;
278	case 15: /* __attribute__ */
279	case 16: /* __attribute */
280		inattr = 1;
281		parlvl = parbal;
282		return C_ATTRIBUTE;
283	case 17: /* __real__ */
284		yylval.intval = XREAL;
285		return C_UNOP;
286	case 18: /* __imag__ */
287		yylval.intval = XIMAG;
288		return C_UNOP;
289	}
290	cerror("gcc_keyword");
291	return 0;
292}
293
294#ifndef TARGET_ATTR
295#define	TARGET_ATTR(p, sue)		0
296#endif
297#ifndef	ALMAX
298#define	ALMAX (ALLDOUBLE > ALLONGLONG ? ALLDOUBLE : ALLONGLONG)
299#endif
300
301/* allowed number of args */
302#define	A_0ARG	0x01
303#define	A_1ARG	0x02
304#define	A_2ARG	0x04
305#define	A_3ARG	0x08
306/* arg # is a name */
307#define	A1_NAME	0x10
308#define	A2_NAME	0x20
309#define	A3_NAME	0x40
310#define	A_MANY	0x80
311/* arg # is "string" */
312#define	A1_STR	0x100
313#define	A2_STR	0x200
314#define	A3_STR	0x400
315
316#ifdef __MSC__
317#define	CS(x)
318#else
319#define CS(x) [x] =
320#endif
321
322struct atax {
323	int typ;
324	char *name;
325} atax[GCC_ATYP_MAX] = {
326	CS(ATTR_NONE)		{ 0, NULL },
327	CS(ATTR_COMPLEX)	{ 0, NULL },
328	CS(xxxATTR_BASETYP)	{ 0, NULL },
329	CS(ATTR_QUALTYP)	{ 0, NULL },
330	CS(ATTR_STRUCT)		{ 0, NULL },
331	CS(ATTR_ALIGNED)	{ A_0ARG|A_1ARG, "aligned" },
332	CS(ATTR_NORETURN)	{ A_0ARG, "noreturn" },
333	CS(ATTR_P1LABELS)	{ A_0ARG, "p1labels" },
334	CS(ATTR_SONAME)		{ A_1ARG|A1_STR, "soname" },
335	CS(GCC_ATYP_PACKED)	{ A_0ARG|A_1ARG, "packed" },
336	CS(GCC_ATYP_SECTION)	{ A_1ARG|A1_STR, "section" },
337	CS(GCC_ATYP_TRANSP_UNION) { A_0ARG, "transparent_union" },
338	CS(GCC_ATYP_UNUSED)	{ A_0ARG, "unused" },
339	CS(GCC_ATYP_DEPRECATED)	{ A_0ARG, "deprecated" },
340	CS(GCC_ATYP_MAYALIAS)	{ A_0ARG, "may_alias" },
341	CS(GCC_ATYP_MODE)	{ A_1ARG|A1_NAME, "mode" },
342	CS(GCC_ATYP_FORMAT)	{ A_3ARG|A1_NAME, "format" },
343	CS(GCC_ATYP_NONNULL)	{ A_MANY, "nonnull" },
344	CS(GCC_ATYP_SENTINEL)	{ A_0ARG|A_1ARG, "sentinel" },
345	CS(GCC_ATYP_WEAK)	{ A_0ARG, "weak" },
346	CS(GCC_ATYP_FORMATARG)	{ A_1ARG, "format_arg" },
347	CS(GCC_ATYP_GNU_INLINE)	{ A_0ARG, "gnu_inline" },
348	CS(GCC_ATYP_MALLOC)	{ A_0ARG, "malloc" },
349	CS(GCC_ATYP_NOTHROW)	{ A_0ARG, "nothrow" },
350	CS(GCC_ATYP_CONST)	{ A_0ARG, "const" },
351	CS(GCC_ATYP_PURE)	{ A_0ARG, "pure" },
352	CS(GCC_ATYP_CONSTRUCTOR) { A_0ARG, "constructor" },
353	CS(GCC_ATYP_DESTRUCTOR)	{ A_0ARG, "destructor" },
354	CS(GCC_ATYP_VISIBILITY)	{ A_1ARG|A1_STR, "visibility" },
355	CS(GCC_ATYP_STDCALL)	{ A_0ARG, "stdcall" },
356	CS(GCC_ATYP_CDECL)	{ A_0ARG, "cdecl" },
357	CS(GCC_ATYP_WARN_UNUSED_RESULT) { A_0ARG, "warn_unused_result" },
358	CS(GCC_ATYP_USED)	{ A_0ARG, "used" },
359	CS(GCC_ATYP_NO_INSTR_FUN) { A_0ARG, "no_instrument_function" },
360	CS(GCC_ATYP_NOINLINE)	{ A_0ARG, "noinline" },
361	CS(GCC_ATYP_ALIAS)	{ A_1ARG|A1_STR, "alias" },
362	CS(GCC_ATYP_WEAKREF)	{ A_0ARG|A_1ARG|A1_STR, "weakref" },
363	CS(GCC_ATYP_ALLOCSZ)	{ A_1ARG|A_2ARG, "alloc_size" },
364	CS(GCC_ATYP_ALW_INL)	{ A_0ARG, "always_inline" },
365	CS(GCC_ATYP_TLSMODEL)	{ A_1ARG|A1_STR, "tls_model" },
366	CS(GCC_ATYP_ALIASWEAK)	{ A_1ARG|A1_STR, "aliasweak" },
367	CS(GCC_ATYP_RETURNS_TWICE) { A_0ARG, "returns_twice" },
368	CS(GCC_ATYP_WARNING)	{ A_1ARG|A1_STR, "warning" },
369	CS(GCC_ATYP_NOCLONE)	{ A_0ARG, "noclone" },
370	CS(GCC_ATYP_REGPARM)	{ A_1ARG, "regparm" },
371	CS(GCC_ATYP_FASTCALL)	{ A_0ARG, "fastcall" },
372
373	CS(GCC_ATYP_BOUNDED)	{ A_3ARG|A_MANY|A1_NAME, "bounded" },
374
375	CS(GCC_ATYP_WEAKIMPORT)	{ A_0ARG, "weak_import" },
376};
377
378#if SZPOINT(CHAR) == SZLONGLONG
379#define	GPT	LONGLONG
380#else
381#define	GPT	INT
382#endif
383
384struct atax mods[] = {
385	{ 0, NULL },
386	{ INT, "SI" },
387	{ INT, "word" },
388	{ GPT, "pointer" },
389	{ CHAR, "byte" },
390	{ CHAR, "QI" },
391	{ SHORT, "HI" },
392	{ LONGLONG, "DI" },
393	{ FLOAT, "SF" },
394	{ DOUBLE, "DF" },
395	{ LDOUBLE, "XF" },
396	{ FCOMPLEX, "SC" },
397	{ COMPLEX, "DC" },
398	{ LCOMPLEX, "XC" },
399	{ INT, "libgcc_cmp_return" },
400	{ INT, "libgcc_shift_count" },
401	{ LONG, "unwind_word" },
402#ifdef TARGET_TIMODE
403	{ 800, "TI" },
404#endif
405#ifdef TARGET_MODS
406	TARGET_MODS
407#endif
408};
409#define	ATSZ	(sizeof(mods)/sizeof(mods[0]))
410
411static int
412amatch(char *s, struct atax *at, int mx)
413{
414	int i, len;
415
416	if (s[0] == '_' && s[1] == '_')
417		s += 2;
418	len = strlen(s);
419	if (len > 2 && s[len-1] == '_' && s[len-2] == '_')
420		len -= 2;
421	for (i = 0; i < mx; i++) {
422		char *t = at[i].name;
423		if (t != NULL && strncmp(s, t, len) == 0 && t[len] == 0)
424			return i;
425	}
426	return 0;
427}
428
429static void
430setaarg(int str, union aarg *aa, NODE *p)
431{
432	if (str) {
433		if (((str & (A1_STR|A2_STR|A3_STR)) && p->n_op != STRING) ||
434		    ((str & (A1_NAME|A2_NAME|A3_NAME)) && p->n_op != NAME))
435			uerror("bad arg to attribute");
436		if (p->n_op == STRING) {
437			aa->sarg = p->n_name; /* saved in cgram.y */
438		} else
439			aa->sarg = (char *)p->n_sp;
440		nfree(p);
441	} else
442		aa->iarg = (int)icons(eve(p));
443}
444
445/*
446 * Parse attributes from an argument list.
447 */
448static struct attr *
449gcc_attribs(NODE *p)
450{
451	NODE *q, *r;
452	struct attr *ap;
453	char *name = NULL, *c;
454	int cw, attr, narg;
455
456	if (p->n_op == NAME) {
457		name = (char *)p->n_sp;
458	} else if (p->n_op == CALL || p->n_op == UCALL) {
459		name = (char *)p->n_left->n_sp;
460	} else if (p->n_op == ICON && p->n_type == STRTY) {
461		return NULL;
462	} else
463		cerror("bad variable attribute");
464
465	if ((attr = amatch(name, atax, GCC_ATYP_MAX)) == 0) {
466		warner(Wattributes, name);
467		ap = NULL;
468		goto out;
469	}
470	narg = 0;
471	if (p->n_op == CALL)
472		for (narg = 1, q = p->n_right; q->n_op == CM; q = q->n_left)
473			narg++;
474
475	cw = atax[attr].typ;
476	if (!(cw & A_MANY) && ((narg > 3) || ((cw & (1 << narg)) == 0))) {
477		uerror("wrong attribute arg count");
478		return NULL;
479	}
480	ap = attr_new(attr, 3); /* XXX should be narg */
481	q = p->n_right;
482
483	switch (narg) {
484	default:
485		/* XXX */
486		while (narg-- > 3) {
487			r = q;
488			q = q->n_left;
489			tfree(r->n_right);
490			nfree(r);
491		}
492		/* FALLTHROUGH */
493	case 3:
494		setaarg(cw & (A3_NAME|A3_STR), &ap->aa[2], q->n_right);
495		r = q;
496		q = q->n_left;
497		nfree(r);
498		/* FALLTHROUGH */
499	case 2:
500		setaarg(cw & (A2_NAME|A2_STR), &ap->aa[1], q->n_right);
501		r = q;
502		q = q->n_left;
503		nfree(r);
504		/* FALLTHROUGH */
505	case 1:
506		setaarg(cw & (A1_NAME|A1_STR), &ap->aa[0], q);
507		p->n_op = UCALL;
508		/* FALLTHROUGH */
509	case 0:
510		break;
511	}
512
513	/* some attributes must be massaged special */
514	switch (attr) {
515	case ATTR_ALIGNED:
516		if (narg == 0)
517			ap->aa[0].iarg = ALMAX;
518		else
519			ap->aa[0].iarg *= SZCHAR;
520		break;
521	case GCC_ATYP_PACKED:
522		if (narg == 0)
523			ap->aa[0].iarg = 1; /* bitwise align */
524		else
525			ap->aa[0].iarg *= SZCHAR;
526		break;
527
528	case GCC_ATYP_VISIBILITY:
529		c = ap->aa[0].sarg;
530		if (strcmp(c, "default") && strcmp(c, "hidden") &&
531		    strcmp(c, "internal") && strcmp(c, "protected"))
532			werror("unknown visibility %s", c);
533		break;
534
535	case GCC_ATYP_TLSMODEL:
536		c = ap->aa[0].sarg;
537		if (strcmp(c, "global-dynamic") && strcmp(c, "local-dynamic") &&
538		    strcmp(c, "initial-exec") && strcmp(c, "local-exec"))
539			werror("unknown tls model %s", c);
540		break;
541
542	default:
543		break;
544	}
545out:
546	return ap;
547}
548
549/*
550 * Extract attributes from a node tree and return attribute entries
551 * based on its contents.
552 */
553struct attr *
554gcc_attr_parse(NODE *p)
555{
556	struct attr *b, *c;
557
558	if (p == NIL)
559		return NULL;
560
561	if (p->n_op != CM) {
562		b = gcc_attribs(p);
563		tfree(p);
564	} else {
565		b = gcc_attr_parse(p->n_left);
566		c = gcc_attr_parse(p->n_right);
567		nfree(p);
568		b = b ? attr_add(b, c) : c;
569	}
570	return b;
571}
572
573/*
574 * Fixup struct/unions depending on attributes.
575 */
576void
577gcc_tcattrfix(NODE *p)
578{
579	struct symtab *sp;
580	struct attr *ap;
581	int sz, coff, csz, al, oal, mxal;
582
583	if (!ISSOU(p->n_type)) /* only for structs or unions */
584		return;
585	if ((ap = attr_find(p->n_ap, GCC_ATYP_PACKED)) == NULL)
586		return; /* nothing to fix */
587
588	al = ap->iarg(0);
589	mxal = 0;
590
591	/* Must repack struct */
592	coff = csz = 0;
593	for (sp = strmemb(ap); sp; sp = sp->snext) {
594		oal = talign(sp->stype, sp->sap);
595		if (oal > al)
596			oal = al;
597		if (mxal < oal)
598			mxal = oal;
599		if (sp->sclass & FIELD)
600			sz = sp->sclass&FLDSIZ;
601		else
602			sz = (int)tsize(sp->stype, sp->sdf, sp->sap);
603		sp->soffset = upoff(sz, oal, &coff);
604		if (coff > csz)
605			csz = coff;
606		if (p->n_type == UNIONTY)
607			coff = 0;
608	}
609	if (mxal < ALCHAR)
610		mxal = ALCHAR; /* for bitfields */
611	SETOFF(csz, mxal); /* Roundup to whatever */
612
613	ap = attr_find(p->n_ap, ATTR_STRUCT);
614	ap->amsize = csz;
615	ap = attr_find(p->n_ap, ATTR_ALIGNED);
616	ap->iarg(0) = mxal;
617
618}
619
620/*
621 * gcc-specific pragmas.
622 */
623int
624pragmas_gcc(char *t)
625{
626	char u;
627	extern char *pragstore;
628
629	if (strcmp((t = pragtok(NULL)), "diagnostic") == 0) {
630		int warn, err;
631
632		if (strcmp((t = pragtok(NULL)), "ignored") == 0)
633			warn = 0, err = 0;
634		else if (strcmp(t, "warning") == 0)
635			warn = 1, err = 0;
636		else if (strcmp(t, "error") == 0)
637			warn = 1, err = 1;
638		else
639			return 1;
640
641		if (eat('\"') || eat('-'))
642			return 1;
643
644		for (t = pragstore; *t && *t != '\"'; t++)
645			;
646
647		u = *t;
648		*t = 0;
649		Wset(pragstore + 1, warn, err);
650		*t = u;
651	} else if (strcmp(t, "poison") == 0) {
652		/* currently ignore */;
653	} else if (strcmp(t, "visibility") == 0) {
654		/* currently ignore */;
655	} else if (strcmp(t, "system_header") == 0) {
656		/* currently ignore */;
657	} else
658		werror("gcc pragma unsupported");
659	return 0;
660}
661
662/*
663 * Fixup types when modes given in defid().
664 */
665void
666gcc_modefix(NODE *p)
667{
668	struct attr *ap;
669#ifdef TARGET_TIMODE
670	struct attr *a2;
671#endif
672	struct symtab *sp;
673	char *s;
674	int i, u;
675
676	if ((ap = attr_find(p->n_ap, GCC_ATYP_MODE)) == NULL)
677		return;
678
679	u = ISUNSIGNED(BTYPE(p->n_type));
680	if ((i = amatch(ap->aa[0].sarg, mods, ATSZ)) == 0) {
681		werror("unknown mode arg %s", ap->aa[0].sarg);
682		return;
683	}
684	i = mods[i].typ;
685	if (i >= 1 && i <= MAXTYPES) {
686		MODTYPE(p->n_type, ctype(i));
687		if (u)
688			p->n_type = ENUNSIGN(p->n_type);
689	} else switch (i) {
690#ifdef TARGET_TIMODE
691	case 800:
692		if (BTYPE(p->n_type) == STRTY)
693			break;
694		MODTYPE(p->n_type, tisp->stype);
695		p->n_df = tisp->sdf;
696		p->n_ap = tisp->sap;
697		if (ap->iarg(1) == u)
698			break;
699		/* must add a new mode struct to avoid overwriting */
700		a2 = attr_new(GCC_ATYP_MODE, 3);
701		a2->sarg(0) = ap->sarg(0);
702		a2->iarg(1) = u;
703		p->n_ap = attr_add(p->n_ap, a2);
704		break;
705#endif
706	case FCOMPLEX:
707	case COMPLEX:
708	case LCOMPLEX:
709		/* Destination should have been converted to a struct already */
710		if (BTYPE(p->n_type) != STRTY)
711			uerror("gcc_modefix: complex not STRTY");
712		i -= (FCOMPLEX-FLOAT);
713		ap = strattr(p->n_ap);
714		sp = ap->amlist;
715		if (sp->stype == (unsigned)i)
716			return; /* Already correct type */
717		/* we must change to another struct */
718		s = i == FLOAT ? "0f" :
719		    i == DOUBLE ? "0d" :
720		    i == LDOUBLE ? "0l" : 0;
721		sp = lookup(addname(s), 0);
722		for (ap = sp->sap; ap != NULL; ap = ap->next)
723			p->n_ap = attr_add(p->n_ap, attr_dup(ap));
724		break;
725
726	default:
727		cerror("gcc_modefix");
728	}
729}
730
731#ifdef TARGET_TIMODE
732
733/*
734 * Return ap if this node is a TI node, else NULL.
735 */
736struct attr *
737isti(NODE *p)
738{
739	struct attr *ap;
740
741	if (p->n_type != STRTY)
742		return NULL;
743	if ((ap = attr_find(p->n_ap, GCC_ATYP_MODE)) == NULL)
744		return NULL;
745	if (strcmp(ap->sarg(0), TISTR))
746		return NULL;
747	return ap;
748}
749
750static char *
751tistack(void)
752{
753	struct symtab *sp, *sp2;
754	char buf[12];
755	NODE *q;
756	char *n;
757
758	/* allocate space on stack */
759	snprintf(buf, 12, "%d", getlab());
760	n = addname(buf);
761	sp = lookup(n, 0);
762	sp2 = tisp;
763	q = block(TYPE, NIL, NIL, sp2->stype, sp2->sdf, sp2->sap);
764	q->n_sp = sp;
765	nidcl2(q, AUTO, 0);
766	nfree(q);
767	return n;
768}
769
770#define	biop(x,y,z) block(x, y, z, INT, 0, 0)
771/*
772 * Create a ti node from something not a ti node.
773 * This usually means:  allocate space on stack, store val, give stack address.
774 */
775static NODE *
776ticast(NODE *p, int u)
777{
778	CONSZ val;
779	NODE *q;
780	char *n;
781	int u2;
782
783	n = tistack();
784
785	/* store val */
786	switch (p->n_op) {
787	case ICON:
788		val = 0;
789		if (u == 0 && p->n_lval < 0)
790			val = -1;
791		q = eve(biop(DOT, bdty(NAME, n), bdty(NAME, loti)));
792		q = buildtree(ASSIGN, q, p);
793		p = biop(DOT, bdty(NAME, n), bdty(NAME, hiti));
794		p = eve(biop(ASSIGN, p, bcon(val)));
795		q = buildtree(COMOP, q, p);
796		p = buildtree(COMOP, q, eve(bdty(NAME, n)));
797		break;
798
799	default:
800		u2 = ISUNSIGNED(p->n_type);
801		q = eve(biop(DOT, bdty(NAME, n), bdty(NAME, loti)));
802		q = buildtree(ASSIGN, q, p);
803		p = biop(DOT, bdty(NAME, n), bdty(NAME, hiti));
804		if (u2) {
805			p = eve(biop(ASSIGN, p, bcon(0)));
806		} else {
807			q = buildtree(ASSIGN, eve(ccopy(p)), q);
808			p = buildtree(RSEQ, eve(p), bcon(SZLONG-1));
809		}
810		q = buildtree(COMOP, q, p);
811		p = buildtree(COMOP, q, eve(bdty(NAME, n)));
812		break;
813	}
814	return p;
815}
816
817/*
818 * Check if we may have to do a cast to/from TI.
819 */
820NODE *
821gcc_eval_ticast(int op, NODE *p1, NODE *p2)
822{
823	struct attr *a1, *a2;
824	int t;
825
826	if ((a1 = isti(p1)) == NULL && (a2 = isti(p2)) == NULL)
827		return NIL;
828
829	if (op == RETURN)
830		p1 = ccopy(p1);
831	if (a1 == NULL) {
832		if (a2 == NULL)
833			cerror("gcc_eval_ticast error");
834		switch (p1->n_type) {
835		case LDOUBLE:
836			p2 = doacall(floatuntixfsp,
837			    nametree(floatuntixfsp), p2);
838			tfree(p1);
839			break;
840		case ULONG:
841		case LONG:
842			p2 = cast(structref(p2, DOT, loti), p1->n_type, 0);
843			tfree(p1);
844			break;
845		case VOID:
846			return NIL;
847		default:
848			uerror("gcc_eval_ticast: %d", p1->n_type);
849		}
850		return p2;
851	}
852	/* p2 can be anything, but we must cast it to p1 */
853	t = a1->iarg(1);
854
855	if (p2->n_type == STRTY &&
856	    (a2 = attr_find(p2->n_ap, GCC_ATYP_MODE)) &&
857	    strcmp(a2->sarg(0), TISTR) == 0) {
858		/* Already TI, just add extra mode bits */
859		a2 = attr_new(GCC_ATYP_MODE, 3);
860		a2->sarg(0) = TISTR;
861		a2->iarg(1) = t;
862		p2->n_ap = attr_add(p2->n_ap, a2);
863	} else  {
864		p2 = ticast(p2, t);
865	}
866	tfree(p1);
867	return p2;
868}
869
870/*
871 * Apply a unary op on a TI value.
872 */
873NODE *
874gcc_eval_tiuni(int op, NODE *p1)
875{
876	struct attr *a1;
877	NODE *p;
878
879	if ((a1 = isti(p1)) == NULL)
880		return NULL;
881
882	switch (op) {
883	case UMINUS:
884		p = ticast(bcon(0), 0);
885		p = buildtree(CM, p, p1);
886		p = doacall(subvti3sp, nametree(subvti3sp), p);
887		break;
888
889	case UMUL:
890		p = NULL;
891	default:
892		uerror("unsupported unary TI mode op %d", op);
893		p = NULL;
894	}
895	return p;
896}
897
898/*
899 * Evaluate AND/OR/ER.  p1 and p2 are pointers to ti struct.
900 */
901static NODE *
902gcc_andorer(int op, NODE *p1, NODE *p2)
903{
904	char *n = tistack();
905	NODE *p, *t1, *t2, *p3;
906
907	t1 = tempnode(0, p1->n_type, p1->n_df, p1->n_ap);
908	t2 = tempnode(0, p2->n_type, p2->n_df, p2->n_ap);
909
910	p1 = buildtree(ASSIGN, ccopy(t1), p1);
911	p2 = buildtree(ASSIGN, ccopy(t2), p2);
912	p = buildtree(COMOP, p1, p2);
913
914	p3 = buildtree(ADDROF, eve(bdty(NAME, n)), NIL);
915	p1 = buildtree(ASSIGN, structref(ccopy(p3), STREF, hiti),
916	    buildtree(op, structref(ccopy(t1), STREF, hiti),
917	    structref(ccopy(t2), STREF, hiti)));
918	p = buildtree(COMOP, p, p1);
919	p1 = buildtree(ASSIGN, structref(ccopy(p3), STREF, loti),
920	    buildtree(op, structref(t1, STREF, loti),
921	    structref(t2, STREF, loti)));
922	p = buildtree(COMOP, p, p1);
923	p = buildtree(COMOP, p, buildtree(UMUL, p3, NIL));
924	return p;
925}
926
927/*
928 * Ensure that a 128-bit assign succeeds.
929 * If left is not TI, make right not TI,
930 * else if left _is_ TI, make right TI,
931 * else do nothing.
932 */
933static NODE *
934timodeassign(NODE *p1, NODE *p2)
935{
936	struct attr *a1, *a2;
937
938	a1 = isti(p1);
939	a2 = isti(p2);
940	if (a1 && a2 == NULL) {
941		p2 = ticast(p2, a1->iarg(1));
942	} else if (a1 == NULL && a2) {
943		if (ISFTY(p1->n_type))
944			cerror("cannot TI float convert");
945		p2 = structref(p2, DOT, loti);
946	}
947	return buildtree(ASSIGN, p1, p2);
948}
949
950/*
951 * Evaluate 128-bit operands.
952 */
953NODE *
954gcc_eval_timode(int op, NODE *p1, NODE *p2)
955{
956	struct attr *a1, *a2;
957	struct symtab *sp;
958	NODE *p;
959	int isu = 0, gotti, isaop;
960
961	if (op == CM)
962		return buildtree(op, p1, p2);
963
964	a1 = isti(p1);
965	a2 = isti(p2);
966
967	if (a1 == NULL && a2 == NULL)
968		return NULL;
969
970	if (op == ASSIGN)
971		return timodeassign(p1, p2);
972
973	gotti = (a1 != NULL);
974	gotti += (a2 != NULL);
975
976	if (gotti == 0)
977		return NULL;
978
979	if (a1 != NULL)
980		isu = a1->iarg(1);
981	if (a2 != NULL && !isu)
982		isu = a2->iarg(1);
983
984	if (a1 == NULL) {
985		p1 = ticast(p1, isu);
986		a1 = attr_find(p1->n_ap, GCC_ATYP_MODE);
987	}
988	if (a2 == NULL && (cdope(op) & SHFFLG) == 0) {
989		p2 = ticast(p2, isu);
990		a2 = attr_find(p2->n_ap, GCC_ATYP_MODE);
991	}
992
993	switch (op) {
994	case GT:
995	case GE:
996	case LT:
997	case LE:
998	case EQ:
999	case NE:
1000		/* change to call */
1001		sp = isu ? ucmpti2sp : cmpti2sp;
1002		p = doacall(sp, nametree(sp), buildtree(CM, p1, p2));
1003		p = buildtree(op, p, bcon(1));
1004		break;
1005
1006	case AND:
1007	case ER:
1008	case OR:
1009		if (!ISPTR(p1->n_type))
1010			p1 = buildtree(ADDROF, p1, NIL);
1011		if (!ISPTR(p2->n_type))
1012			p2 = buildtree(ADDROF, p2, NIL);
1013		p = gcc_andorer(op, p1, p2);
1014		break;
1015
1016	case LSEQ:
1017	case RSEQ:
1018	case LS:
1019	case RS:
1020		sp = op == LS || op == LSEQ ? ashldi3sp :
1021		    isu ? lshrdi3sp : ashrdi3sp;
1022		p2 = cast(p2, INT, 0);
1023		/* XXX p1 ccopy may have side effects */
1024		p = doacall(sp, nametree(sp), buildtree(CM, ccopy(p1), p2));
1025		if (op == LSEQ || op == RSEQ) {
1026			p = buildtree(ASSIGN, p1, p);
1027		} else
1028			tfree(p1);
1029		break;
1030
1031	case PLUSEQ:
1032	case MINUSEQ:
1033	case MULEQ:
1034	case DIVEQ:
1035	case MODEQ:
1036	case PLUS:
1037	case MINUS:
1038	case MUL:
1039	case DIV:
1040	case MOD:
1041		isaop = (cdope(op)&ASGOPFLG);
1042		if (isaop)
1043			op = UNASG op;
1044		sp = op == PLUS ? addvti3sp :
1045		    op == MINUS ? subvti3sp :
1046		    op == MUL ? mulvti3sp :
1047		    op == DIV ? (isu ? udivti3sp : divti3sp) :
1048		    op == MOD ? (isu ? umodti3sp : modti3sp) : 0;
1049		/* XXX p1 ccopy may have side effects */
1050		p = doacall(sp, nametree(sp), buildtree(CM, ccopy(p1), p2));
1051		if (isaop)
1052			p = buildtree(ASSIGN, p1, p);
1053		else
1054			tfree(p1);
1055		break;
1056
1057	default:
1058		uerror("unsupported TImode op %d", op);
1059		p = bcon(0);
1060	}
1061	return p;
1062}
1063#endif
1064
1065#ifdef PCC_DEBUG
1066void
1067dump_attr(struct attr *ap)
1068{
1069	printf("attributes; ");
1070	for (; ap; ap = ap->next) {
1071		if (ap->atype >= GCC_ATYP_MAX) {
1072			printf("bad type %d, ", ap->atype);
1073		} else if (atax[ap->atype].name == 0) {
1074			char *c = ap->atype == ATTR_COMPLEX ? "complex" :
1075			    ap->atype == ATTR_STRUCT ? "struct" : "badtype";
1076			printf("%s, ", c);
1077		} else {
1078			printf("%s: ", atax[ap->atype].name);
1079			if (atax[ap->atype].typ & A1_STR)
1080				printf("%s ", ap->sarg(0));
1081			else
1082				printf("%d %d %d, ", ap->iarg(0),
1083				    ap->iarg(1), ap->iarg(2));
1084		}
1085	}
1086	printf("\n");
1087}
1088#endif
1089#endif
1090