11f5207b7SJohn Levon /*
21f5207b7SJohn Levon  * sparse/show-parse.c
31f5207b7SJohn Levon  *
41f5207b7SJohn Levon  * Copyright (C) 2003 Transmeta Corp.
51f5207b7SJohn Levon  *               2003-2004 Linus Torvalds
61f5207b7SJohn Levon  *
71f5207b7SJohn Levon  * Permission is hereby granted, free of charge, to any person obtaining a copy
81f5207b7SJohn Levon  * of this software and associated documentation files (the "Software"), to deal
91f5207b7SJohn Levon  * in the Software without restriction, including without limitation the rights
101f5207b7SJohn Levon  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
111f5207b7SJohn Levon  * copies of the Software, and to permit persons to whom the Software is
121f5207b7SJohn Levon  * furnished to do so, subject to the following conditions:
131f5207b7SJohn Levon  *
141f5207b7SJohn Levon  * The above copyright notice and this permission notice shall be included in
151f5207b7SJohn Levon  * all copies or substantial portions of the Software.
161f5207b7SJohn Levon  *
171f5207b7SJohn Levon  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181f5207b7SJohn Levon  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191f5207b7SJohn Levon  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
201f5207b7SJohn Levon  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
211f5207b7SJohn Levon  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
221f5207b7SJohn Levon  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
231f5207b7SJohn Levon  * THE SOFTWARE.
241f5207b7SJohn Levon  *
251f5207b7SJohn Levon  * Print out results of parsing for debugging and testing.
261f5207b7SJohn Levon  */
271f5207b7SJohn Levon #include <stdarg.h>
281f5207b7SJohn Levon #include <stdlib.h>
291f5207b7SJohn Levon #include <stdio.h>
301f5207b7SJohn Levon #include <string.h>
311f5207b7SJohn Levon #include <ctype.h>
321f5207b7SJohn Levon #include <unistd.h>
331f5207b7SJohn Levon #include <fcntl.h>
341f5207b7SJohn Levon 
351f5207b7SJohn Levon #include "lib.h"
361f5207b7SJohn Levon #include "allocate.h"
371f5207b7SJohn Levon #include "token.h"
381f5207b7SJohn Levon #include "parse.h"
391f5207b7SJohn Levon #include "symbol.h"
401f5207b7SJohn Levon #include "scope.h"
411f5207b7SJohn Levon #include "expression.h"
421f5207b7SJohn Levon #include "target.h"
431f5207b7SJohn Levon 
441f5207b7SJohn Levon static int show_symbol_expr(struct symbol *sym);
451f5207b7SJohn Levon static int show_string_expr(struct expression *expr);
461f5207b7SJohn Levon 
do_debug_symbol(struct symbol * sym,int indent)471f5207b7SJohn Levon static void do_debug_symbol(struct symbol *sym, int indent)
481f5207b7SJohn Levon {
491f5207b7SJohn Levon 	static const char indent_string[] = "                                  ";
501f5207b7SJohn Levon 	static const char *typestr[] = {
511f5207b7SJohn Levon 		[SYM_UNINITIALIZED] = "none",
521f5207b7SJohn Levon 		[SYM_PREPROCESSOR] = "cpp.",
531f5207b7SJohn Levon 		[SYM_BASETYPE] = "base",
541f5207b7SJohn Levon 		[SYM_NODE] = "node",
551f5207b7SJohn Levon 		[SYM_PTR] = "ptr.",
561f5207b7SJohn Levon 		[SYM_FN] = "fn..",
571f5207b7SJohn Levon 		[SYM_ARRAY] = "arry",
581f5207b7SJohn Levon 		[SYM_STRUCT] = "strt",
591f5207b7SJohn Levon 		[SYM_UNION] = "unin",
601f5207b7SJohn Levon 		[SYM_ENUM] = "enum",
611f5207b7SJohn Levon 		[SYM_TYPEDEF] = "tdef",
621f5207b7SJohn Levon 		[SYM_TYPEOF] = "tpof",
631f5207b7SJohn Levon 		[SYM_MEMBER] = "memb",
641f5207b7SJohn Levon 		[SYM_BITFIELD] = "bitf",
651f5207b7SJohn Levon 		[SYM_LABEL] = "labl",
661f5207b7SJohn Levon 		[SYM_RESTRICT] = "rstr",
671f5207b7SJohn Levon 		[SYM_FOULED] = "foul",
681f5207b7SJohn Levon 		[SYM_BAD] = "bad.",
691f5207b7SJohn Levon 	};
701f5207b7SJohn Levon 	struct context *context;
711f5207b7SJohn Levon 	int i;
721f5207b7SJohn Levon 
731f5207b7SJohn Levon 	if (!sym)
741f5207b7SJohn Levon 		return;
75*c85f09ccSJohn Levon 	fprintf(stderr, "%.*s%s%3d:%lu %s %s (as: %s) %p (%s:%d:%d) %s\n",
761f5207b7SJohn Levon 		indent, indent_string, typestr[sym->type],
771f5207b7SJohn Levon 		sym->bit_size, sym->ctype.alignment,
78*c85f09ccSJohn Levon 		modifier_string(sym->ctype.modifiers), show_ident(sym->ident),
79*c85f09ccSJohn Levon 		show_as(sym->ctype.as),
801f5207b7SJohn Levon 		sym, stream_name(sym->pos.stream), sym->pos.line, sym->pos.pos,
811f5207b7SJohn Levon 		builtin_typename(sym) ?: "");
821f5207b7SJohn Levon 	i = 0;
831f5207b7SJohn Levon 	FOR_EACH_PTR(sym->ctype.contexts, context) {
841f5207b7SJohn Levon 		/* FIXME: should print context expression */
851f5207b7SJohn Levon 		fprintf(stderr, "< context%d: in=%d, out=%d\n",
861f5207b7SJohn Levon 			i, context->in, context->out);
871f5207b7SJohn Levon 		fprintf(stderr, "  end context%d >\n", i);
881f5207b7SJohn Levon 		i++;
891f5207b7SJohn Levon 	} END_FOR_EACH_PTR(context);
901f5207b7SJohn Levon 	if (sym->type == SYM_FN) {
911f5207b7SJohn Levon 		struct symbol *arg;
921f5207b7SJohn Levon 		i = 0;
931f5207b7SJohn Levon 		FOR_EACH_PTR(sym->arguments, arg) {
941f5207b7SJohn Levon 			fprintf(stderr, "< arg%d:\n", i);
951f5207b7SJohn Levon 			do_debug_symbol(arg, 0);
961f5207b7SJohn Levon 			fprintf(stderr, "  end arg%d >\n", i);
971f5207b7SJohn Levon 			i++;
981f5207b7SJohn Levon 		} END_FOR_EACH_PTR(arg);
991f5207b7SJohn Levon 	}
1001f5207b7SJohn Levon 	do_debug_symbol(sym->ctype.base_type, indent+2);
1011f5207b7SJohn Levon }
1021f5207b7SJohn Levon 
debug_symbol(struct symbol * sym)1031f5207b7SJohn Levon void debug_symbol(struct symbol *sym)
1041f5207b7SJohn Levon {
1051f5207b7SJohn Levon 	do_debug_symbol(sym, 0);
1061f5207b7SJohn Levon }
1071f5207b7SJohn Levon 
1081f5207b7SJohn Levon /*
1091f5207b7SJohn Levon  * Symbol type printout. The type system is by far the most
1101f5207b7SJohn Levon  * complicated part of C - everything else is trivial.
1111f5207b7SJohn Levon  */
modifier_string(unsigned long mod)1121f5207b7SJohn Levon const char *modifier_string(unsigned long mod)
1131f5207b7SJohn Levon {
1141f5207b7SJohn Levon 	static char buffer[100];
1151f5207b7SJohn Levon 	int len = 0;
1161f5207b7SJohn Levon 	int i;
1171f5207b7SJohn Levon 	struct mod_name {
1181f5207b7SJohn Levon 		unsigned long mod;
1191f5207b7SJohn Levon 		const char *name;
1201f5207b7SJohn Levon 	} *m;
1211f5207b7SJohn Levon 
1221f5207b7SJohn Levon 	static struct mod_name mod_names[] = {
1231f5207b7SJohn Levon 		{MOD_AUTO,		"auto"},
1241f5207b7SJohn Levon 		{MOD_REGISTER,		"register"},
1251f5207b7SJohn Levon 		{MOD_STATIC,		"static"},
1261f5207b7SJohn Levon 		{MOD_EXTERN,		"extern"},
1271f5207b7SJohn Levon 		{MOD_CONST,		"const"},
1281f5207b7SJohn Levon 		{MOD_VOLATILE,		"volatile"},
129*c85f09ccSJohn Levon 		{MOD_RESTRICT,		"restrict"},
130*c85f09ccSJohn Levon 		{MOD_ATOMIC,		"[atomic]"},
1311f5207b7SJohn Levon 		{MOD_SIGNED,		"[signed]"},
1321f5207b7SJohn Levon 		{MOD_UNSIGNED,		"[unsigned]"},
1331f5207b7SJohn Levon 		{MOD_CHAR,		"[char]"},
1341f5207b7SJohn Levon 		{MOD_SHORT,		"[short]"},
1351f5207b7SJohn Levon 		{MOD_LONG,		"[long]"},
1361f5207b7SJohn Levon 		{MOD_LONGLONG,		"[long long]"},
1371f5207b7SJohn Levon 		{MOD_LONGLONGLONG,	"[long long long]"},
1381f5207b7SJohn Levon 		{MOD_TLS,		"[tls]"},
1391f5207b7SJohn Levon 		{MOD_INLINE,		"inline"},
1401f5207b7SJohn Levon 		{MOD_ADDRESSABLE,	"[addressable]"},
1411f5207b7SJohn Levon 		{MOD_NOCAST,		"[nocast]"},
1421f5207b7SJohn Levon 		{MOD_NODEREF,		"[noderef]"},
1431f5207b7SJohn Levon 		{MOD_TOPLEVEL,		"[toplevel]"},
1441f5207b7SJohn Levon 		{MOD_ASSIGNED,		"[assigned]"},
1451f5207b7SJohn Levon 		{MOD_TYPE,		"[type]"},
1461f5207b7SJohn Levon 		{MOD_SAFE,		"[safe]"},
1471f5207b7SJohn Levon 		{MOD_USERTYPE,		"[usertype]"},
1481f5207b7SJohn Levon 		{MOD_NORETURN,		"[noreturn]"},
1491f5207b7SJohn Levon 		{MOD_EXPLICITLY_SIGNED,	"[explicitly-signed]"},
1501f5207b7SJohn Levon 		{MOD_BITWISE,		"[bitwise]"},
1511f5207b7SJohn Levon 		{MOD_PURE,		"[pure]"},
1521f5207b7SJohn Levon 	};
1531f5207b7SJohn Levon 
1541f5207b7SJohn Levon 	for (i = 0; i < ARRAY_SIZE(mod_names); i++) {
1551f5207b7SJohn Levon 		m = mod_names + i;
1561f5207b7SJohn Levon 		if (mod & m->mod) {
1571f5207b7SJohn Levon 			char c;
1581f5207b7SJohn Levon 			const char *name = m->name;
1591f5207b7SJohn Levon 			while ((c = *name++) != '\0' && len + 2 < sizeof buffer)
1601f5207b7SJohn Levon 				buffer[len++] = c;
1611f5207b7SJohn Levon 			buffer[len++] = ' ';
1621f5207b7SJohn Levon 		}
1631f5207b7SJohn Levon 	}
1641f5207b7SJohn Levon 	buffer[len] = 0;
1651f5207b7SJohn Levon 	return buffer;
1661f5207b7SJohn Levon }
1671f5207b7SJohn Levon 
show_struct_member(struct symbol * sym)1681f5207b7SJohn Levon static void show_struct_member(struct symbol *sym)
1691f5207b7SJohn Levon {
1701f5207b7SJohn Levon 	printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
1711f5207b7SJohn Levon 	printf("\n");
1721f5207b7SJohn Levon }
1731f5207b7SJohn Levon 
show_symbol_list(struct symbol_list * list,const char * sep)1741f5207b7SJohn Levon void show_symbol_list(struct symbol_list *list, const char *sep)
1751f5207b7SJohn Levon {
1761f5207b7SJohn Levon 	struct symbol *sym;
1771f5207b7SJohn Levon 	const char *prepend = "";
1781f5207b7SJohn Levon 
1791f5207b7SJohn Levon 	FOR_EACH_PTR(list, sym) {
1801f5207b7SJohn Levon 		puts(prepend);
1811f5207b7SJohn Levon 		prepend = ", ";
1821f5207b7SJohn Levon 		show_symbol(sym);
1831f5207b7SJohn Levon 	} END_FOR_EACH_PTR(sym);
1841f5207b7SJohn Levon }
1851f5207b7SJohn Levon 
show_as(struct ident * as)186*c85f09ccSJohn Levon const char *show_as(struct ident *as)
187*c85f09ccSJohn Levon {
188*c85f09ccSJohn Levon 	if (!as)
189*c85f09ccSJohn Levon 		return "";
190*c85f09ccSJohn Levon 	return show_ident(as);
191*c85f09ccSJohn Levon }
192*c85f09ccSJohn Levon 
1931f5207b7SJohn Levon struct type_name {
1941f5207b7SJohn Levon 	char *start;
1951f5207b7SJohn Levon 	char *end;
1961f5207b7SJohn Levon };
1971f5207b7SJohn Levon 
prepend(struct type_name * name,const char * fmt,...)1981f5207b7SJohn Levon static void FORMAT_ATTR(2) prepend(struct type_name *name, const char *fmt, ...)
1991f5207b7SJohn Levon {
2001f5207b7SJohn Levon 	static char buffer[512];
2011f5207b7SJohn Levon 	int n;
2021f5207b7SJohn Levon 
2031f5207b7SJohn Levon 	va_list args;
2041f5207b7SJohn Levon 	va_start(args, fmt);
2051f5207b7SJohn Levon 	n = vsprintf(buffer, fmt, args);
2061f5207b7SJohn Levon 	va_end(args);
2071f5207b7SJohn Levon 
2081f5207b7SJohn Levon 	name->start -= n;
2091f5207b7SJohn Levon 	memcpy(name->start, buffer, n);
2101f5207b7SJohn Levon }
2111f5207b7SJohn Levon 
append(struct type_name * name,const char * fmt,...)2121f5207b7SJohn Levon static void FORMAT_ATTR(2) append(struct type_name *name, const char *fmt, ...)
2131f5207b7SJohn Levon {
2141f5207b7SJohn Levon 	static char buffer[512];
2151f5207b7SJohn Levon 	int n;
2161f5207b7SJohn Levon 
2171f5207b7SJohn Levon 	va_list args;
2181f5207b7SJohn Levon 	va_start(args, fmt);
2191f5207b7SJohn Levon 	n = vsprintf(buffer, fmt, args);
2201f5207b7SJohn Levon 	va_end(args);
2211f5207b7SJohn Levon 
2221f5207b7SJohn Levon 	memcpy(name->end, buffer, n);
2231f5207b7SJohn Levon 	name->end += n;
2241f5207b7SJohn Levon }
2251f5207b7SJohn Levon 
2261f5207b7SJohn Levon static struct ctype_name {
2271f5207b7SJohn Levon 	struct symbol *sym;
2281f5207b7SJohn Levon 	const char *name;
229*c85f09ccSJohn Levon 	const char *suffix;
2301f5207b7SJohn Levon } typenames[] = {
231*c85f09ccSJohn Levon 	{ & char_ctype,  "char", "" },
232*c85f09ccSJohn Levon 	{ &schar_ctype,  "signed char", "" },
233*c85f09ccSJohn Levon 	{ &uchar_ctype,  "unsigned char", "" },
234*c85f09ccSJohn Levon 	{ & short_ctype, "short", "" },
235*c85f09ccSJohn Levon 	{ &sshort_ctype, "signed short", "" },
236*c85f09ccSJohn Levon 	{ &ushort_ctype, "unsigned short", "" },
237*c85f09ccSJohn Levon 	{ & int_ctype,   "int", "" },
238*c85f09ccSJohn Levon 	{ &sint_ctype,   "signed int", "" },
239*c85f09ccSJohn Levon 	{ &uint_ctype,   "unsigned int", "U" },
240*c85f09ccSJohn Levon 	{ & long_ctype,  "long", "L" },
241*c85f09ccSJohn Levon 	{ &slong_ctype,  "signed long", "L" },
242*c85f09ccSJohn Levon 	{ &ulong_ctype,  "unsigned long", "UL" },
243*c85f09ccSJohn Levon 	{ & llong_ctype, "long long", "LL" },
244*c85f09ccSJohn Levon 	{ &sllong_ctype, "signed long long", "LL" },
245*c85f09ccSJohn Levon 	{ &ullong_ctype, "unsigned long long", "ULL" },
246*c85f09ccSJohn Levon 	{ & lllong_ctype, "long long long", "LLL" },
247*c85f09ccSJohn Levon 	{ &slllong_ctype, "signed long long long", "LLL" },
248*c85f09ccSJohn Levon 	{ &ulllong_ctype, "unsigned long long long", "ULLL" },
249*c85f09ccSJohn Levon 
250*c85f09ccSJohn Levon 	{ &void_ctype,   "void", "" },
251*c85f09ccSJohn Levon 	{ &bool_ctype,   "bool", "" },
252*c85f09ccSJohn Levon 
253*c85f09ccSJohn Levon 	{ &float_ctype,  "float", "F" },
254*c85f09ccSJohn Levon 	{ &double_ctype, "double", "" },
255*c85f09ccSJohn Levon 	{ &ldouble_ctype,"long double", "L" },
256*c85f09ccSJohn Levon 	{ &incomplete_ctype, "incomplete type", "" },
257*c85f09ccSJohn Levon 	{ &int_type, "abstract int", "" },
258*c85f09ccSJohn Levon 	{ &fp_type, "abstract fp", "" },
259*c85f09ccSJohn Levon 	{ &label_ctype, "label type", "" },
260*c85f09ccSJohn Levon 	{ &bad_ctype, "bad type", "" },
2611f5207b7SJohn Levon };
2621f5207b7SJohn Levon 
builtin_typename(struct symbol * sym)2631f5207b7SJohn Levon const char *builtin_typename(struct symbol *sym)
2641f5207b7SJohn Levon {
2651f5207b7SJohn Levon 	int i;
2661f5207b7SJohn Levon 
2671f5207b7SJohn Levon 	for (i = 0; i < ARRAY_SIZE(typenames); i++)
2681f5207b7SJohn Levon 		if (typenames[i].sym == sym)
2691f5207b7SJohn Levon 			return typenames[i].name;
2701f5207b7SJohn Levon 	return NULL;
2711f5207b7SJohn Levon }
2721f5207b7SJohn Levon 
builtin_type_suffix(struct symbol * sym)273*c85f09ccSJohn Levon const char *builtin_type_suffix(struct symbol *sym)
274*c85f09ccSJohn Levon {
275*c85f09ccSJohn Levon 	int i;
276*c85f09ccSJohn Levon 
277*c85f09ccSJohn Levon 	for (i = 0; i < ARRAY_SIZE(typenames); i++)
278*c85f09ccSJohn Levon 		if (typenames[i].sym == sym)
279*c85f09ccSJohn Levon 			return typenames[i].suffix;
280*c85f09ccSJohn Levon 	return NULL;
281*c85f09ccSJohn Levon }
282*c85f09ccSJohn Levon 
builtin_ctypename(struct ctype * ctype)2831f5207b7SJohn Levon const char *builtin_ctypename(struct ctype *ctype)
2841f5207b7SJohn Levon {
2851f5207b7SJohn Levon 	int i;
2861f5207b7SJohn Levon 
2871f5207b7SJohn Levon 	for (i = 0; i < ARRAY_SIZE(typenames); i++)
2881f5207b7SJohn Levon 		if (&typenames[i].sym->ctype == ctype)
2891f5207b7SJohn Levon 			return typenames[i].name;
2901f5207b7SJohn Levon 	return NULL;
2911f5207b7SJohn Levon }
2921f5207b7SJohn Levon 
do_show_type(struct symbol * sym,struct type_name * name)2931f5207b7SJohn Levon static void do_show_type(struct symbol *sym, struct type_name *name)
2941f5207b7SJohn Levon {
2951f5207b7SJohn Levon 	const char *typename;
2961f5207b7SJohn Levon 	unsigned long mod = 0;
297*c85f09ccSJohn Levon 	struct ident *as = NULL;
2981f5207b7SJohn Levon 	int was_ptr = 0;
2991f5207b7SJohn Levon 	int restr = 0;
3001f5207b7SJohn Levon 	int fouled = 0;
3011f5207b7SJohn Levon 
3021f5207b7SJohn Levon deeper:
3031f5207b7SJohn Levon 	if (!sym || (sym->type != SYM_NODE && sym->type != SYM_ARRAY &&
3041f5207b7SJohn Levon 		     sym->type != SYM_BITFIELD)) {
3051f5207b7SJohn Levon 		const char *s;
3061f5207b7SJohn Levon 		size_t len;
3071f5207b7SJohn Levon 
3081f5207b7SJohn Levon 		if (as)
309*c85f09ccSJohn Levon 			prepend(name, "%s ", show_as(as));
3101f5207b7SJohn Levon 
311*c85f09ccSJohn Levon 		if (sym->type == SYM_BASETYPE || sym->type == SYM_ENUM)
312*c85f09ccSJohn Levon 			mod &= ~MOD_SPECIFIER;
3131f5207b7SJohn Levon 		s = modifier_string(mod);
3141f5207b7SJohn Levon 		len = strlen(s);
3151f5207b7SJohn Levon 		name->start -= len;
3161f5207b7SJohn Levon 		memcpy(name->start, s, len);
3171f5207b7SJohn Levon 		mod = 0;
318*c85f09ccSJohn Levon 		as = NULL;
3191f5207b7SJohn Levon 	}
3201f5207b7SJohn Levon 
3211f5207b7SJohn Levon 	if (!sym)
3221f5207b7SJohn Levon 		goto out;
3231f5207b7SJohn Levon 
3241f5207b7SJohn Levon 	if ((typename = builtin_typename(sym))) {
3251f5207b7SJohn Levon 		int len = strlen(typename);
3261f5207b7SJohn Levon 		if (name->start != name->end)
3271f5207b7SJohn Levon 			*--name->start = ' ';
3281f5207b7SJohn Levon 		name->start -= len;
3291f5207b7SJohn Levon 		memcpy(name->start, typename, len);
3301f5207b7SJohn Levon 		goto out;
3311f5207b7SJohn Levon 	}
3321f5207b7SJohn Levon 
3331f5207b7SJohn Levon 	/* Prepend */
3341f5207b7SJohn Levon 	switch (sym->type) {
3351f5207b7SJohn Levon 	case SYM_PTR:
3361f5207b7SJohn Levon 		prepend(name, "*");
3371f5207b7SJohn Levon 		mod = sym->ctype.modifiers;
3381f5207b7SJohn Levon 		as = sym->ctype.as;
3391f5207b7SJohn Levon 		was_ptr = 1;
3401f5207b7SJohn Levon 		break;
3411f5207b7SJohn Levon 
3421f5207b7SJohn Levon 	case SYM_FN:
3431f5207b7SJohn Levon 		if (was_ptr) {
3441f5207b7SJohn Levon 			prepend(name, "( ");
3451f5207b7SJohn Levon 			append(name, " )");
3461f5207b7SJohn Levon 			was_ptr = 0;
3471f5207b7SJohn Levon 		}
3481f5207b7SJohn Levon 		append(name, "( ... )");
3491f5207b7SJohn Levon 		break;
3501f5207b7SJohn Levon 
3511f5207b7SJohn Levon 	case SYM_STRUCT:
3521f5207b7SJohn Levon 		if (name->start != name->end)
3531f5207b7SJohn Levon 			*--name->start = ' ';
3541f5207b7SJohn Levon 		prepend(name, "struct %s", show_ident(sym->ident));
3551f5207b7SJohn Levon 		goto out;
3561f5207b7SJohn Levon 
3571f5207b7SJohn Levon 	case SYM_UNION:
3581f5207b7SJohn Levon 		if (name->start != name->end)
3591f5207b7SJohn Levon 			*--name->start = ' ';
3601f5207b7SJohn Levon 		prepend(name, "union %s", show_ident(sym->ident));
3611f5207b7SJohn Levon 		goto out;
3621f5207b7SJohn Levon 
3631f5207b7SJohn Levon 	case SYM_ENUM:
3641f5207b7SJohn Levon 		prepend(name, "enum %s ", show_ident(sym->ident));
3651f5207b7SJohn Levon 		break;
3661f5207b7SJohn Levon 
3671f5207b7SJohn Levon 	case SYM_NODE:
368*c85f09ccSJohn Levon 		if (sym->ident)
369*c85f09ccSJohn Levon 			append(name, "%s", show_ident(sym->ident));
3701f5207b7SJohn Levon 		mod |= sym->ctype.modifiers;
371*c85f09ccSJohn Levon 		combine_address_space(sym->pos, &as, sym->ctype.as);
3721f5207b7SJohn Levon 		break;
3731f5207b7SJohn Levon 
3741f5207b7SJohn Levon 	case SYM_BITFIELD:
3751f5207b7SJohn Levon 		mod |= sym->ctype.modifiers;
376*c85f09ccSJohn Levon 		combine_address_space(sym->pos, &as, sym->ctype.as);
3771f5207b7SJohn Levon 		append(name, ":%d", sym->bit_size);
3781f5207b7SJohn Levon 		break;
3791f5207b7SJohn Levon 
3801f5207b7SJohn Levon 	case SYM_LABEL:
3811f5207b7SJohn Levon 		append(name, "label(%s:%p)", show_ident(sym->ident), sym);
3821f5207b7SJohn Levon 		return;
3831f5207b7SJohn Levon 
3841f5207b7SJohn Levon 	case SYM_ARRAY:
3851f5207b7SJohn Levon 		mod |= sym->ctype.modifiers;
386*c85f09ccSJohn Levon 		combine_address_space(sym->pos, &as, sym->ctype.as);
3871f5207b7SJohn Levon 		if (was_ptr) {
3881f5207b7SJohn Levon 			prepend(name, "( ");
3891f5207b7SJohn Levon 			append(name, " )");
3901f5207b7SJohn Levon 			was_ptr = 0;
3911f5207b7SJohn Levon 		}
3921f5207b7SJohn Levon 		append(name, "[%lld]", get_expression_value(sym->array_size));
3931f5207b7SJohn Levon 		break;
3941f5207b7SJohn Levon 
3951f5207b7SJohn Levon 	case SYM_RESTRICT:
3961f5207b7SJohn Levon 		if (!sym->ident) {
3971f5207b7SJohn Levon 			restr = 1;
3981f5207b7SJohn Levon 			break;
3991f5207b7SJohn Levon 		}
4001f5207b7SJohn Levon 		if (name->start != name->end)
4011f5207b7SJohn Levon 			*--name->start = ' ';
4021f5207b7SJohn Levon 		prepend(name, "restricted %s", show_ident(sym->ident));
4031f5207b7SJohn Levon 		goto out;
4041f5207b7SJohn Levon 
4051f5207b7SJohn Levon 	case SYM_FOULED:
4061f5207b7SJohn Levon 		fouled = 1;
4071f5207b7SJohn Levon 		break;
4081f5207b7SJohn Levon 
4091f5207b7SJohn Levon 	default:
4101f5207b7SJohn Levon 		if (name->start != name->end)
4111f5207b7SJohn Levon 			*--name->start = ' ';
4121f5207b7SJohn Levon 		prepend(name, "unknown type %d", sym->type);
4131f5207b7SJohn Levon 		goto out;
4141f5207b7SJohn Levon 	}
4151f5207b7SJohn Levon 
4161f5207b7SJohn Levon 	sym = sym->ctype.base_type;
4171f5207b7SJohn Levon 	goto deeper;
4181f5207b7SJohn Levon 
4191f5207b7SJohn Levon out:
4201f5207b7SJohn Levon 	if (restr)
4211f5207b7SJohn Levon 		prepend(name, "restricted ");
4221f5207b7SJohn Levon 	if (fouled)
4231f5207b7SJohn Levon 		prepend(name, "fouled ");
424*c85f09ccSJohn Levon 
425*c85f09ccSJohn Levon 	// strip trailing space
426*c85f09ccSJohn Levon 	if (name->end > name->start && name->end[-1] == ' ')
427*c85f09ccSJohn Levon 		name->end--;
4281f5207b7SJohn Levon }
4291f5207b7SJohn Levon 
show_type(struct symbol * sym)4301f5207b7SJohn Levon void show_type(struct symbol *sym)
4311f5207b7SJohn Levon {
4321f5207b7SJohn Levon 	char array[200];
4331f5207b7SJohn Levon 	struct type_name name;
4341f5207b7SJohn Levon 
4351f5207b7SJohn Levon 	name.start = name.end = array+100;
4361f5207b7SJohn Levon 	do_show_type(sym, &name);
4371f5207b7SJohn Levon 	*name.end = 0;
4381f5207b7SJohn Levon 	printf("%s", name.start);
4391f5207b7SJohn Levon }
4401f5207b7SJohn Levon 
show_typename(struct symbol * sym)4411f5207b7SJohn Levon const char *show_typename(struct symbol *sym)
4421f5207b7SJohn Levon {
4431f5207b7SJohn Levon 	static char array[200];
4441f5207b7SJohn Levon 	struct type_name name;
4451f5207b7SJohn Levon 
4461f5207b7SJohn Levon 	name.start = name.end = array+100;
4471f5207b7SJohn Levon 	do_show_type(sym, &name);
4481f5207b7SJohn Levon 	*name.end = 0;
4491f5207b7SJohn Levon 	return name.start;
4501f5207b7SJohn Levon }
4511f5207b7SJohn Levon 
show_symbol(struct symbol * sym)4521f5207b7SJohn Levon void show_symbol(struct symbol *sym)
4531f5207b7SJohn Levon {
4541f5207b7SJohn Levon 	struct symbol *type;
4551f5207b7SJohn Levon 
4561f5207b7SJohn Levon 	if (!sym)
4571f5207b7SJohn Levon 		return;
4581f5207b7SJohn Levon 
4591f5207b7SJohn Levon 	if (sym->ctype.alignment)
4601f5207b7SJohn Levon 		printf(".align %ld\n", sym->ctype.alignment);
4611f5207b7SJohn Levon 
4621f5207b7SJohn Levon 	show_type(sym);
4631f5207b7SJohn Levon 	type = sym->ctype.base_type;
4641f5207b7SJohn Levon 	if (!type) {
4651f5207b7SJohn Levon 		printf("\n");
4661f5207b7SJohn Levon 		return;
4671f5207b7SJohn Levon 	}
4681f5207b7SJohn Levon 
4691f5207b7SJohn Levon 	/*
4701f5207b7SJohn Levon 	 * Show actual implementation information
4711f5207b7SJohn Levon 	 */
4721f5207b7SJohn Levon 	switch (type->type) {
4731f5207b7SJohn Levon 		struct symbol *member;
4741f5207b7SJohn Levon 
4751f5207b7SJohn Levon 	case SYM_STRUCT:
4761f5207b7SJohn Levon 	case SYM_UNION:
4771f5207b7SJohn Levon 		printf(" {\n");
4781f5207b7SJohn Levon 		FOR_EACH_PTR(type->symbol_list, member) {
4791f5207b7SJohn Levon 			show_struct_member(member);
4801f5207b7SJohn Levon 		} END_FOR_EACH_PTR(member);
4811f5207b7SJohn Levon 		printf("}\n");
4821f5207b7SJohn Levon 		break;
4831f5207b7SJohn Levon 
4841f5207b7SJohn Levon 	case SYM_FN: {
4851f5207b7SJohn Levon 		struct statement *stmt = type->stmt;
4861f5207b7SJohn Levon 		printf("\n");
4871f5207b7SJohn Levon 		if (stmt) {
4881f5207b7SJohn Levon 			int val;
4891f5207b7SJohn Levon 			val = show_statement(stmt);
4901f5207b7SJohn Levon 			if (val)
4911f5207b7SJohn Levon 				printf("\tmov.%d\t\tretval,%d\n", stmt->ret->bit_size, val);
4921f5207b7SJohn Levon 			printf("\tret\n");
4931f5207b7SJohn Levon 		}
4941f5207b7SJohn Levon 		break;
4951f5207b7SJohn Levon 	}
4961f5207b7SJohn Levon 
4971f5207b7SJohn Levon 	default:
4981f5207b7SJohn Levon 		printf("\n");
4991f5207b7SJohn Levon 		break;
5001f5207b7SJohn Levon 	}
5011f5207b7SJohn Levon 
5021f5207b7SJohn Levon 	if (sym->initializer) {
5031f5207b7SJohn Levon 		printf(" = \n");
5041f5207b7SJohn Levon 		show_expression(sym->initializer);
5051f5207b7SJohn Levon 	}
5061f5207b7SJohn Levon }
5071f5207b7SJohn Levon 
5081f5207b7SJohn Levon static int show_symbol_init(struct symbol *sym);
5091f5207b7SJohn Levon 
new_pseudo(void)5101f5207b7SJohn Levon static int new_pseudo(void)
5111f5207b7SJohn Levon {
5121f5207b7SJohn Levon 	static int nr = 0;
5131f5207b7SJohn Levon 	return ++nr;
5141f5207b7SJohn Levon }
5151f5207b7SJohn Levon 
new_label(void)5161f5207b7SJohn Levon static int new_label(void)
5171f5207b7SJohn Levon {
5181f5207b7SJohn Levon 	static int label = 0;
5191f5207b7SJohn Levon 	return ++label;
5201f5207b7SJohn Levon }
5211f5207b7SJohn Levon 
show_switch_statement(struct statement * stmt)5221f5207b7SJohn Levon static void show_switch_statement(struct statement *stmt)
5231f5207b7SJohn Levon {
5241f5207b7SJohn Levon 	int val = show_expression(stmt->switch_expression);
5251f5207b7SJohn Levon 	struct symbol *sym;
5261f5207b7SJohn Levon 	printf("\tswitch v%d\n", val);
5271f5207b7SJohn Levon 
5281f5207b7SJohn Levon 	/*
5291f5207b7SJohn Levon 	 * Debugging only: Check that the case list is correct
5301f5207b7SJohn Levon 	 * by printing it out.
5311f5207b7SJohn Levon 	 *
5321f5207b7SJohn Levon 	 * This is where a _real_ back-end would go through the
5331f5207b7SJohn Levon 	 * cases to decide whether to use a lookup table or a
5341f5207b7SJohn Levon 	 * series of comparisons etc
5351f5207b7SJohn Levon 	 */
5361f5207b7SJohn Levon 	printf("# case table:\n");
5371f5207b7SJohn Levon 	FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
5381f5207b7SJohn Levon 		struct statement *case_stmt = sym->stmt;
5391f5207b7SJohn Levon 		struct expression *expr = case_stmt->case_expression;
5401f5207b7SJohn Levon 		struct expression *to = case_stmt->case_to;
5411f5207b7SJohn Levon 
5421f5207b7SJohn Levon 		if (!expr) {
5431f5207b7SJohn Levon 			printf("    default");
5441f5207b7SJohn Levon 		} else {
5451f5207b7SJohn Levon 			if (expr->type == EXPR_VALUE) {
5461f5207b7SJohn Levon 				printf("    case %lld", expr->value);
5471f5207b7SJohn Levon 				if (to) {
5481f5207b7SJohn Levon 					if (to->type == EXPR_VALUE) {
5491f5207b7SJohn Levon 						printf(" .. %lld", to->value);
5501f5207b7SJohn Levon 					} else {
5511f5207b7SJohn Levon 						printf(" .. what?");
5521f5207b7SJohn Levon 					}
5531f5207b7SJohn Levon 				}
5541f5207b7SJohn Levon 			} else
5551f5207b7SJohn Levon 				printf("    what?");
5561f5207b7SJohn Levon 		}
5571f5207b7SJohn Levon 		printf(": .L%p\n", sym);
5581f5207b7SJohn Levon 	} END_FOR_EACH_PTR(sym);
5591f5207b7SJohn Levon 	printf("# end case table\n");
5601f5207b7SJohn Levon 
5611f5207b7SJohn Levon 	show_statement(stmt->switch_statement);
5621f5207b7SJohn Levon 
5631f5207b7SJohn Levon 	if (stmt->switch_break->used)
5641f5207b7SJohn Levon 		printf(".L%p:\n", stmt->switch_break);
5651f5207b7SJohn Levon }
5661f5207b7SJohn Levon 
show_symbol_decl(struct symbol_list * syms)5671f5207b7SJohn Levon static void show_symbol_decl(struct symbol_list *syms)
5681f5207b7SJohn Levon {
5691f5207b7SJohn Levon 	struct symbol *sym;
5701f5207b7SJohn Levon 	FOR_EACH_PTR(syms, sym) {
5711f5207b7SJohn Levon 		show_symbol_init(sym);
5721f5207b7SJohn Levon 	} END_FOR_EACH_PTR(sym);
5731f5207b7SJohn Levon }
5741f5207b7SJohn Levon 
5751f5207b7SJohn Levon static int show_return_stmt(struct statement *stmt);
5761f5207b7SJohn Levon 
5771f5207b7SJohn Levon /*
5781f5207b7SJohn Levon  * Print out a statement
5791f5207b7SJohn Levon  */
show_statement(struct statement * stmt)5801f5207b7SJohn Levon int show_statement(struct statement *stmt)
5811f5207b7SJohn Levon {
5821f5207b7SJohn Levon 	if (!stmt)
5831f5207b7SJohn Levon 		return 0;
5841f5207b7SJohn Levon 	switch (stmt->type) {
5851f5207b7SJohn Levon 	case STMT_DECLARATION:
5861f5207b7SJohn Levon 		show_symbol_decl(stmt->declaration);
5871f5207b7SJohn Levon 		return 0;
5881f5207b7SJohn Levon 	case STMT_RETURN:
5891f5207b7SJohn Levon 		return show_return_stmt(stmt);
5901f5207b7SJohn Levon 	case STMT_COMPOUND: {
5911f5207b7SJohn Levon 		struct statement *s;
5921f5207b7SJohn Levon 		int last = 0;
5931f5207b7SJohn Levon 
5941f5207b7SJohn Levon 		if (stmt->inline_fn) {
5951f5207b7SJohn Levon 			show_statement(stmt->args);
5961f5207b7SJohn Levon 			printf("\tbegin_inline \t%s\n", show_ident(stmt->inline_fn->ident));
5971f5207b7SJohn Levon 		}
5981f5207b7SJohn Levon 		FOR_EACH_PTR(stmt->stmts, s) {
5991f5207b7SJohn Levon 			last = show_statement(s);
6001f5207b7SJohn Levon 		} END_FOR_EACH_PTR(s);
6011f5207b7SJohn Levon 		if (stmt->ret) {
6021f5207b7SJohn Levon 			int addr, bits;
6031f5207b7SJohn Levon 			printf(".L%p:\n", stmt->ret);
6041f5207b7SJohn Levon 			addr = show_symbol_expr(stmt->ret);
6051f5207b7SJohn Levon 			bits = stmt->ret->bit_size;
6061f5207b7SJohn Levon 			last = new_pseudo();
6071f5207b7SJohn Levon 			printf("\tld.%d\t\tv%d,[v%d]\n", bits, last, addr);
6081f5207b7SJohn Levon 		}
6091f5207b7SJohn Levon 		if (stmt->inline_fn)
6101f5207b7SJohn Levon 			printf("\tend_inlined\t%s\n", show_ident(stmt->inline_fn->ident));
6111f5207b7SJohn Levon 		return last;
6121f5207b7SJohn Levon 	}
6131f5207b7SJohn Levon 
6141f5207b7SJohn Levon 	case STMT_EXPRESSION:
6151f5207b7SJohn Levon 		return show_expression(stmt->expression);
6161f5207b7SJohn Levon 	case STMT_IF: {
6171f5207b7SJohn Levon 		int val, target;
6181f5207b7SJohn Levon 		struct expression *cond = stmt->if_conditional;
6191f5207b7SJohn Levon 
6201f5207b7SJohn Levon /* This is only valid if nobody can jump into the "dead" statement */
6211f5207b7SJohn Levon #if 0
6221f5207b7SJohn Levon 		if (cond->type == EXPR_VALUE) {
6231f5207b7SJohn Levon 			struct statement *s = stmt->if_true;
6241f5207b7SJohn Levon 			if (!cond->value)
6251f5207b7SJohn Levon 				s = stmt->if_false;
6261f5207b7SJohn Levon 			show_statement(s);
6271f5207b7SJohn Levon 			break;
6281f5207b7SJohn Levon 		}
6291f5207b7SJohn Levon #endif
6301f5207b7SJohn Levon 		val = show_expression(cond);
6311f5207b7SJohn Levon 		target = new_label();
6321f5207b7SJohn Levon 		printf("\tje\t\tv%d,.L%d\n", val, target);
6331f5207b7SJohn Levon 		show_statement(stmt->if_true);
6341f5207b7SJohn Levon 		if (stmt->if_false) {
6351f5207b7SJohn Levon 			int last = new_label();
6361f5207b7SJohn Levon 			printf("\tjmp\t\t.L%d\n", last);
6371f5207b7SJohn Levon 			printf(".L%d:\n", target);
6381f5207b7SJohn Levon 			target = last;
6391f5207b7SJohn Levon 			show_statement(stmt->if_false);
6401f5207b7SJohn Levon 		}
6411f5207b7SJohn Levon 		printf(".L%d:\n", target);
6421f5207b7SJohn Levon 		break;
6431f5207b7SJohn Levon 	}
6441f5207b7SJohn Levon 	case STMT_SWITCH:
6451f5207b7SJohn Levon 		show_switch_statement(stmt);
6461f5207b7SJohn Levon 		break;
6471f5207b7SJohn Levon 
6481f5207b7SJohn Levon 	case STMT_CASE:
6491f5207b7SJohn Levon 		printf(".L%p:\n", stmt->case_label);
6501f5207b7SJohn Levon 		show_statement(stmt->case_statement);
6511f5207b7SJohn Levon 		break;
6521f5207b7SJohn Levon 
6531f5207b7SJohn Levon 	case STMT_ITERATOR: {
6541f5207b7SJohn Levon 		struct statement  *pre_statement = stmt->iterator_pre_statement;
6551f5207b7SJohn Levon 		struct expression *pre_condition = stmt->iterator_pre_condition;
6561f5207b7SJohn Levon 		struct statement  *statement = stmt->iterator_statement;
6571f5207b7SJohn Levon 		struct statement  *post_statement = stmt->iterator_post_statement;
6581f5207b7SJohn Levon 		struct expression *post_condition = stmt->iterator_post_condition;
6591f5207b7SJohn Levon 		int val, loop_top = 0, loop_bottom = 0;
6601f5207b7SJohn Levon 
6611f5207b7SJohn Levon 		show_symbol_decl(stmt->iterator_syms);
6621f5207b7SJohn Levon 		show_statement(pre_statement);
6631f5207b7SJohn Levon 		if (pre_condition) {
6641f5207b7SJohn Levon 			if (pre_condition->type == EXPR_VALUE) {
6651f5207b7SJohn Levon 				if (!pre_condition->value) {
6661f5207b7SJohn Levon 					loop_bottom = new_label();
6671f5207b7SJohn Levon 					printf("\tjmp\t\t.L%d\n", loop_bottom);
6681f5207b7SJohn Levon 				}
6691f5207b7SJohn Levon 			} else {
6701f5207b7SJohn Levon 				loop_bottom = new_label();
6711f5207b7SJohn Levon 				val = show_expression(pre_condition);
6721f5207b7SJohn Levon 				printf("\tje\t\tv%d, .L%d\n", val, loop_bottom);
6731f5207b7SJohn Levon 			}
6741f5207b7SJohn Levon 		}
6751f5207b7SJohn Levon 		if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
6761f5207b7SJohn Levon 			loop_top = new_label();
6771f5207b7SJohn Levon 			printf(".L%d:\n", loop_top);
6781f5207b7SJohn Levon 		}
6791f5207b7SJohn Levon 		show_statement(statement);
6801f5207b7SJohn Levon 		if (stmt->iterator_continue->used)
6811f5207b7SJohn Levon 			printf(".L%p:\n", stmt->iterator_continue);
6821f5207b7SJohn Levon 		show_statement(post_statement);
6831f5207b7SJohn Levon 		if (!post_condition) {
6841f5207b7SJohn Levon 			printf("\tjmp\t\t.L%d\n", loop_top);
6851f5207b7SJohn Levon 		} else if (post_condition->type == EXPR_VALUE) {
6861f5207b7SJohn Levon 			if (post_condition->value)
6871f5207b7SJohn Levon 				printf("\tjmp\t\t.L%d\n", loop_top);
6881f5207b7SJohn Levon 		} else {
6891f5207b7SJohn Levon 			val = show_expression(post_condition);
6901f5207b7SJohn Levon 			printf("\tjne\t\tv%d, .L%d\n", val, loop_top);
6911f5207b7SJohn Levon 		}
6921f5207b7SJohn Levon 		if (stmt->iterator_break->used)
6931f5207b7SJohn Levon 			printf(".L%p:\n", stmt->iterator_break);
6941f5207b7SJohn Levon 		if (loop_bottom)
6951f5207b7SJohn Levon 			printf(".L%d:\n", loop_bottom);
6961f5207b7SJohn Levon 		break;
6971f5207b7SJohn Levon 	}
6981f5207b7SJohn Levon 	case STMT_NONE:
6991f5207b7SJohn Levon 		break;
7001f5207b7SJohn Levon 
7011f5207b7SJohn Levon 	case STMT_LABEL:
7021f5207b7SJohn Levon 		printf(".L%p:\n", stmt->label_identifier);
7031f5207b7SJohn Levon 		show_statement(stmt->label_statement);
7041f5207b7SJohn Levon 		break;
7051f5207b7SJohn Levon 
7061f5207b7SJohn Levon 	case STMT_GOTO:
7071f5207b7SJohn Levon 		if (stmt->goto_expression) {
7081f5207b7SJohn Levon 			int val = show_expression(stmt->goto_expression);
7091f5207b7SJohn Levon 			printf("\tgoto\t\t*v%d\n", val);
7101f5207b7SJohn Levon 		} else {
7111f5207b7SJohn Levon 			printf("\tgoto\t\t.L%p\n", stmt->goto_label);
7121f5207b7SJohn Levon 		}
7131f5207b7SJohn Levon 		break;
7141f5207b7SJohn Levon 	case STMT_ASM:
7151f5207b7SJohn Levon 		printf("\tasm( .... )\n");
7161f5207b7SJohn Levon 		break;
7171f5207b7SJohn Levon 	case STMT_CONTEXT: {
7181f5207b7SJohn Levon 		int val = show_expression(stmt->expression);
7191f5207b7SJohn Levon 		printf("\tcontext( %d )\n", val);
7201f5207b7SJohn Levon 		break;
7211f5207b7SJohn Levon 	}
7221f5207b7SJohn Levon 	case STMT_RANGE: {
7231f5207b7SJohn Levon 		int val = show_expression(stmt->range_expression);
7241f5207b7SJohn Levon 		int low = show_expression(stmt->range_low);
7251f5207b7SJohn Levon 		int high = show_expression(stmt->range_high);
7261f5207b7SJohn Levon 		printf("\trange( %d %d-%d)\n", val, low, high);
7271f5207b7SJohn Levon 		break;
7281f5207b7SJohn Levon 	}
7291f5207b7SJohn Levon 	}
7301f5207b7SJohn Levon 	return 0;
7311f5207b7SJohn Levon }
7321f5207b7SJohn Levon 
show_call_expression(struct expression * expr)7331f5207b7SJohn Levon static int show_call_expression(struct expression *expr)
7341f5207b7SJohn Levon {
7351f5207b7SJohn Levon 	struct symbol *direct;
7361f5207b7SJohn Levon 	struct expression *arg, *fn;
7371f5207b7SJohn Levon 	int fncall, retval;
7381f5207b7SJohn Levon 	int framesize;
7391f5207b7SJohn Levon 
7401f5207b7SJohn Levon 	if (!expr->ctype) {
7411f5207b7SJohn Levon 		warning(expr->pos, "\tcall with no type!");
7421f5207b7SJohn Levon 		return 0;
7431f5207b7SJohn Levon 	}
7441f5207b7SJohn Levon 
7451f5207b7SJohn Levon 	framesize = 0;
7461f5207b7SJohn Levon 	FOR_EACH_PTR_REVERSE(expr->args, arg) {
7471f5207b7SJohn Levon 		int new = show_expression(arg);
7481f5207b7SJohn Levon 		int size = arg->ctype->bit_size;
7491f5207b7SJohn Levon 		printf("\tpush.%d\t\tv%d\n", size, new);
7501f5207b7SJohn Levon 		framesize += bits_to_bytes(size);
7511f5207b7SJohn Levon 	} END_FOR_EACH_PTR_REVERSE(arg);
7521f5207b7SJohn Levon 
7531f5207b7SJohn Levon 	fn = expr->fn;
7541f5207b7SJohn Levon 
7551f5207b7SJohn Levon 	/* Remove dereference, if any */
7561f5207b7SJohn Levon 	direct = NULL;
7571f5207b7SJohn Levon 	if (fn->type == EXPR_PREOP) {
7581f5207b7SJohn Levon 		if (fn->unop->type == EXPR_SYMBOL) {
7591f5207b7SJohn Levon 			struct symbol *sym = fn->unop->symbol;
7601f5207b7SJohn Levon 			if (sym->ctype.base_type->type == SYM_FN)
7611f5207b7SJohn Levon 				direct = sym;
7621f5207b7SJohn Levon 		}
7631f5207b7SJohn Levon 	}
7641f5207b7SJohn Levon 	if (direct) {
7651f5207b7SJohn Levon 		printf("\tcall\t\t%s\n", show_ident(direct->ident));
7661f5207b7SJohn Levon 	} else {
7671f5207b7SJohn Levon 		fncall = show_expression(fn);
7681f5207b7SJohn Levon 		printf("\tcall\t\t*v%d\n", fncall);
7691f5207b7SJohn Levon 	}
7701f5207b7SJohn Levon 	if (framesize)
7711f5207b7SJohn Levon 		printf("\tadd.%d\t\tvSP,vSP,$%d\n", bits_in_pointer, framesize);
7721f5207b7SJohn Levon 
7731f5207b7SJohn Levon 	retval = new_pseudo();
7741f5207b7SJohn Levon 	printf("\tmov.%d\t\tv%d,retval\n", expr->ctype->bit_size, retval);
7751f5207b7SJohn Levon 	return retval;
7761f5207b7SJohn Levon }
7771f5207b7SJohn Levon 
show_comma(struct expression * expr)7781f5207b7SJohn Levon static int show_comma(struct expression *expr)
7791f5207b7SJohn Levon {
7801f5207b7SJohn Levon 	show_expression(expr->left);
7811f5207b7SJohn Levon 	return show_expression(expr->right);
7821f5207b7SJohn Levon }
7831f5207b7SJohn Levon 
show_binop(struct expression * expr)7841f5207b7SJohn Levon static int show_binop(struct expression *expr)
7851f5207b7SJohn Levon {
7861f5207b7SJohn Levon 	int left = show_expression(expr->left);
7871f5207b7SJohn Levon 	int right = show_expression(expr->right);
7881f5207b7SJohn Levon 	int new = new_pseudo();
7891f5207b7SJohn Levon 	const char *opname;
7901f5207b7SJohn Levon 	static const char *name[] = {
7911f5207b7SJohn Levon 		['+'] = "add", ['-'] = "sub",
7921f5207b7SJohn Levon 		['*'] = "mul", ['/'] = "div",
7931f5207b7SJohn Levon 		['%'] = "mod", ['&'] = "and",
7941f5207b7SJohn Levon 		['|'] = "lor", ['^'] = "xor"
7951f5207b7SJohn Levon 	};
7961f5207b7SJohn Levon 	unsigned int op = expr->op;
7971f5207b7SJohn Levon 
7981f5207b7SJohn Levon 	opname = show_special(op);
7991f5207b7SJohn Levon 	if (op < ARRAY_SIZE(name))
8001f5207b7SJohn Levon 		opname = name[op];
8011f5207b7SJohn Levon 	printf("\t%s.%d\t\tv%d,v%d,v%d\n", opname,
8021f5207b7SJohn Levon 		expr->ctype->bit_size,
8031f5207b7SJohn Levon 		new, left, right);
8041f5207b7SJohn Levon 	return new;
8051f5207b7SJohn Levon }
8061f5207b7SJohn Levon 
show_slice(struct expression * expr)8071f5207b7SJohn Levon static int show_slice(struct expression *expr)
8081f5207b7SJohn Levon {
8091f5207b7SJohn Levon 	int target = show_expression(expr->base);
8101f5207b7SJohn Levon 	int new = new_pseudo();
8111f5207b7SJohn Levon 	printf("\tslice.%d\t\tv%d,v%d,%d\n", expr->r_nrbits, target, new, expr->r_bitpos);
8121f5207b7SJohn Levon 	return new;
8131f5207b7SJohn Levon }
8141f5207b7SJohn Levon 
show_regular_preop(struct expression * expr)8151f5207b7SJohn Levon static int show_regular_preop(struct expression *expr)
8161f5207b7SJohn Levon {
8171f5207b7SJohn Levon 	int target = show_expression(expr->unop);
8181f5207b7SJohn Levon 	int new = new_pseudo();
8191f5207b7SJohn Levon 	static const char *name[] = {
8201f5207b7SJohn Levon 		['!'] = "nonzero", ['-'] = "neg",
8211f5207b7SJohn Levon 		['~'] = "not",
8221f5207b7SJohn Levon 	};
8231f5207b7SJohn Levon 	unsigned int op = expr->op;
8241f5207b7SJohn Levon 	const char *opname;
8251f5207b7SJohn Levon 
8261f5207b7SJohn Levon 	opname = show_special(op);
8271f5207b7SJohn Levon 	if (op < ARRAY_SIZE(name))
8281f5207b7SJohn Levon 		opname = name[op];
8291f5207b7SJohn Levon 	printf("\t%s.%d\t\tv%d,v%d\n", opname, expr->ctype->bit_size, new, target);
8301f5207b7SJohn Levon 	return new;
8311f5207b7SJohn Levon }
8321f5207b7SJohn Levon 
8331f5207b7SJohn Levon /*
8341f5207b7SJohn Levon  * FIXME! Not all accesses are memory loads. We should
8351f5207b7SJohn Levon  * check what kind of symbol is behind the dereference.
8361f5207b7SJohn Levon  */
show_address_gen(struct expression * expr)8371f5207b7SJohn Levon static int show_address_gen(struct expression *expr)
8381f5207b7SJohn Levon {
8391f5207b7SJohn Levon 	return show_expression(expr->unop);
8401f5207b7SJohn Levon }
8411f5207b7SJohn Levon 
show_load_gen(int bits,struct expression * expr,int addr)8421f5207b7SJohn Levon static int show_load_gen(int bits, struct expression *expr, int addr)
8431f5207b7SJohn Levon {
8441f5207b7SJohn Levon 	int new = new_pseudo();
8451f5207b7SJohn Levon 
8461f5207b7SJohn Levon 	printf("\tld.%d\t\tv%d,[v%d]\n", bits, new, addr);
8471f5207b7SJohn Levon 	return new;
8481f5207b7SJohn Levon }
8491f5207b7SJohn Levon 
show_store_gen(int bits,int value,struct expression * expr,int addr)8501f5207b7SJohn Levon static void show_store_gen(int bits, int value, struct expression *expr, int addr)
8511f5207b7SJohn Levon {
8521f5207b7SJohn Levon 	/* FIXME!!! Bitfield store! */
8531f5207b7SJohn Levon 	printf("\tst.%d\t\tv%d,[v%d]\n", bits, value, addr);
8541f5207b7SJohn Levon }
8551f5207b7SJohn Levon 
show_assignment(struct expression * expr)8561f5207b7SJohn Levon static int show_assignment(struct expression *expr)
8571f5207b7SJohn Levon {
8581f5207b7SJohn Levon 	struct expression *target = expr->left;
8591f5207b7SJohn Levon 	int val, addr, bits;
8601f5207b7SJohn Levon 
8611f5207b7SJohn Levon 	if (!expr->ctype)
8621f5207b7SJohn Levon 		return 0;
8631f5207b7SJohn Levon 
8641f5207b7SJohn Levon 	bits = expr->ctype->bit_size;
8651f5207b7SJohn Levon 	val = show_expression(expr->right);
8661f5207b7SJohn Levon 	addr = show_address_gen(target);
8671f5207b7SJohn Levon 	show_store_gen(bits, val, target, addr);
8681f5207b7SJohn Levon 	return val;
8691f5207b7SJohn Levon }
8701f5207b7SJohn Levon 
show_return_stmt(struct statement * stmt)8711f5207b7SJohn Levon static int show_return_stmt(struct statement *stmt)
8721f5207b7SJohn Levon {
8731f5207b7SJohn Levon 	struct expression *expr = stmt->ret_value;
8741f5207b7SJohn Levon 	struct symbol *target = stmt->ret_target;
8751f5207b7SJohn Levon 
8761f5207b7SJohn Levon 	if (expr && expr->ctype) {
8771f5207b7SJohn Levon 		int val = show_expression(expr);
8781f5207b7SJohn Levon 		int bits = expr->ctype->bit_size;
8791f5207b7SJohn Levon 		int addr = show_symbol_expr(target);
8801f5207b7SJohn Levon 		show_store_gen(bits, val, NULL, addr);
8811f5207b7SJohn Levon 	}
8821f5207b7SJohn Levon 	printf("\tret\t\t(%p)\n", target);
8831f5207b7SJohn Levon 	return 0;
8841f5207b7SJohn Levon }
8851f5207b7SJohn Levon 
show_initialization(struct symbol * sym,struct expression * expr)8861f5207b7SJohn Levon static int show_initialization(struct symbol *sym, struct expression *expr)
8871f5207b7SJohn Levon {
8881f5207b7SJohn Levon 	int val, addr, bits;
8891f5207b7SJohn Levon 
8901f5207b7SJohn Levon 	if (!expr->ctype)
8911f5207b7SJohn Levon 		return 0;
8921f5207b7SJohn Levon 
8931f5207b7SJohn Levon 	bits = expr->ctype->bit_size;
8941f5207b7SJohn Levon 	val = show_expression(expr);
8951f5207b7SJohn Levon 	addr = show_symbol_expr(sym);
8961f5207b7SJohn Levon 	// FIXME! The "target" expression is for bitfield store information.
8971f5207b7SJohn Levon 	// Leave it NULL, which works fine.
8981f5207b7SJohn Levon 	show_store_gen(bits, val, NULL, addr);
8991f5207b7SJohn Levon 	return 0;
9001f5207b7SJohn Levon }
9011f5207b7SJohn Levon 
show_access(struct expression * expr)9021f5207b7SJohn Levon static int show_access(struct expression *expr)
9031f5207b7SJohn Levon {
9041f5207b7SJohn Levon 	int addr = show_address_gen(expr);
9051f5207b7SJohn Levon 	return show_load_gen(expr->ctype->bit_size, expr, addr);
9061f5207b7SJohn Levon }
9071f5207b7SJohn Levon 
show_inc_dec(struct expression * expr,int postop)9081f5207b7SJohn Levon static int show_inc_dec(struct expression *expr, int postop)
9091f5207b7SJohn Levon {
9101f5207b7SJohn Levon 	int addr = show_address_gen(expr->unop);
9111f5207b7SJohn Levon 	int retval, new;
9121f5207b7SJohn Levon 	const char *opname = expr->op == SPECIAL_INCREMENT ? "add" : "sub";
9131f5207b7SJohn Levon 	int bits = expr->ctype->bit_size;
9141f5207b7SJohn Levon 
9151f5207b7SJohn Levon 	retval = show_load_gen(bits, expr->unop, addr);
9161f5207b7SJohn Levon 	new = retval;
9171f5207b7SJohn Levon 	if (postop)
9181f5207b7SJohn Levon 		new = new_pseudo();
9191f5207b7SJohn Levon 	printf("\t%s.%d\t\tv%d,v%d,$1\n", opname, bits, new, retval);
9201f5207b7SJohn Levon 	show_store_gen(bits, new, expr->unop, addr);
9211f5207b7SJohn Levon 	return retval;
9221f5207b7SJohn Levon }
9231f5207b7SJohn Levon 
show_preop(struct expression * expr)9241f5207b7SJohn Levon static int show_preop(struct expression *expr)
9251f5207b7SJohn Levon {
9261f5207b7SJohn Levon 	/*
9271f5207b7SJohn Levon 	 * '*' is an lvalue access, and is fundamentally different
9281f5207b7SJohn Levon 	 * from an arithmetic operation. Maybe it should have an
9291f5207b7SJohn Levon 	 * expression type of its own..
9301f5207b7SJohn Levon 	 */
9311f5207b7SJohn Levon 	if (expr->op == '*')
9321f5207b7SJohn Levon 		return show_access(expr);
9331f5207b7SJohn Levon 	if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
9341f5207b7SJohn Levon 		return show_inc_dec(expr, 0);
9351f5207b7SJohn Levon 	return show_regular_preop(expr);
9361f5207b7SJohn Levon }
9371f5207b7SJohn Levon 
show_postop(struct expression * expr)9381f5207b7SJohn Levon static int show_postop(struct expression *expr)
9391f5207b7SJohn Levon {
9401f5207b7SJohn Levon 	return show_inc_dec(expr, 1);
9411f5207b7SJohn Levon }
9421f5207b7SJohn Levon 
show_symbol_expr(struct symbol * sym)9431f5207b7SJohn Levon static int show_symbol_expr(struct symbol *sym)
9441f5207b7SJohn Levon {
9451f5207b7SJohn Levon 	int new = new_pseudo();
9461f5207b7SJohn Levon 
9471f5207b7SJohn Levon 	if (sym->initializer && sym->initializer->type == EXPR_STRING)
9481f5207b7SJohn Levon 		return show_string_expr(sym->initializer);
9491f5207b7SJohn Levon 
9501f5207b7SJohn Levon 	if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
9511f5207b7SJohn Levon 		printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new, show_ident(sym->ident));
9521f5207b7SJohn Levon 		return new;
9531f5207b7SJohn Levon 	}
9541f5207b7SJohn Levon 	if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
955*c85f09ccSJohn Levon 		printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new, 0LL);
9561f5207b7SJohn Levon 		return new;
9571f5207b7SJohn Levon 	}
9581f5207b7SJohn Levon 	printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new, show_ident(sym->ident), sym);
9591f5207b7SJohn Levon 	return new;
9601f5207b7SJohn Levon }
9611f5207b7SJohn Levon 
show_symbol_init(struct symbol * sym)9621f5207b7SJohn Levon static int show_symbol_init(struct symbol *sym)
9631f5207b7SJohn Levon {
9641f5207b7SJohn Levon 	struct expression *expr = sym->initializer;
9651f5207b7SJohn Levon 
9661f5207b7SJohn Levon 	if (expr) {
9671f5207b7SJohn Levon 		int val, addr, bits;
9681f5207b7SJohn Levon 
9691f5207b7SJohn Levon 		bits = expr->ctype->bit_size;
9701f5207b7SJohn Levon 		val = show_expression(expr);
9711f5207b7SJohn Levon 		addr = show_symbol_expr(sym);
9721f5207b7SJohn Levon 		show_store_gen(bits, val, NULL, addr);
9731f5207b7SJohn Levon 	}
9741f5207b7SJohn Levon 	return 0;
9751f5207b7SJohn Levon }
9761f5207b7SJohn Levon 
show_cast_expr(struct expression * expr)9771f5207b7SJohn Levon static int show_cast_expr(struct expression *expr)
9781f5207b7SJohn Levon {
9791f5207b7SJohn Levon 	struct symbol *old_type, *new_type;
9801f5207b7SJohn Levon 	int op = show_expression(expr->cast_expression);
9811f5207b7SJohn Levon 	int oldbits, newbits;
9821f5207b7SJohn Levon 	int new, is_signed;
9831f5207b7SJohn Levon 
9841f5207b7SJohn Levon 	old_type = expr->cast_expression->ctype;
9851f5207b7SJohn Levon 	new_type = expr->cast_type;
9861f5207b7SJohn Levon 
9871f5207b7SJohn Levon 	oldbits = old_type->bit_size;
9881f5207b7SJohn Levon 	newbits = new_type->bit_size;
9891f5207b7SJohn Levon 	if (oldbits >= newbits)
9901f5207b7SJohn Levon 		return op;
9911f5207b7SJohn Levon 	new = new_pseudo();
992*c85f09ccSJohn Levon 	is_signed = is_signed_type(old_type);
9931f5207b7SJohn Levon 	if (is_signed) {
9941f5207b7SJohn Levon 		printf("\tsext%d.%d\tv%d,v%d\n", oldbits, newbits, new, op);
9951f5207b7SJohn Levon 	} else {
9961f5207b7SJohn Levon 		printf("\tandl.%d\t\tv%d,v%d,$%lu\n", newbits, new, op, (1UL << oldbits)-1);
9971f5207b7SJohn Levon 	}
9981f5207b7SJohn Levon 	return new;
9991f5207b7SJohn Levon }
10001f5207b7SJohn Levon 
show_value(struct expression * expr)10011f5207b7SJohn Levon static int show_value(struct expression *expr)
10021f5207b7SJohn Levon {
10031f5207b7SJohn Levon 	int new = new_pseudo();
10041f5207b7SJohn Levon 	unsigned long long value = expr->value;
10051f5207b7SJohn Levon 
10061f5207b7SJohn Levon 	printf("\tmovi.%d\t\tv%d,$%llu\n", expr->ctype->bit_size, new, value);
10071f5207b7SJohn Levon 	return new;
10081f5207b7SJohn Levon }
10091f5207b7SJohn Levon 
show_fvalue(struct expression * expr)10101f5207b7SJohn Levon static int show_fvalue(struct expression *expr)
10111f5207b7SJohn Levon {
10121f5207b7SJohn Levon 	int new = new_pseudo();
10131f5207b7SJohn Levon 	long double value = expr->fvalue;
10141f5207b7SJohn Levon 
1015*c85f09ccSJohn Levon 	printf("\tmovf.%d\t\tv%d,$%Le\n", expr->ctype->bit_size, new, value);
10161f5207b7SJohn Levon 	return new;
10171f5207b7SJohn Levon }
10181f5207b7SJohn Levon 
show_string_expr(struct expression * expr)10191f5207b7SJohn Levon static int show_string_expr(struct expression *expr)
10201f5207b7SJohn Levon {
10211f5207b7SJohn Levon 	int new = new_pseudo();
10221f5207b7SJohn Levon 
10231f5207b7SJohn Levon 	printf("\tmovi.%d\t\tv%d,&%s\n", bits_in_pointer, new, show_string(expr->string));
10241f5207b7SJohn Levon 	return new;
10251f5207b7SJohn Levon }
10261f5207b7SJohn Levon 
show_label_expr(struct expression * expr)10271f5207b7SJohn Levon static int show_label_expr(struct expression *expr)
10281f5207b7SJohn Levon {
10291f5207b7SJohn Levon 	int new = new_pseudo();
10301f5207b7SJohn Levon 	printf("\tmovi.%d\t\tv%d,.L%p\n",bits_in_pointer, new, expr->label_symbol);
10311f5207b7SJohn Levon 	return new;
10321f5207b7SJohn Levon }
10331f5207b7SJohn Levon 
show_conditional_expr(struct expression * expr)10341f5207b7SJohn Levon static int show_conditional_expr(struct expression *expr)
10351f5207b7SJohn Levon {
10361f5207b7SJohn Levon 	int cond = show_expression(expr->conditional);
1037*c85f09ccSJohn Levon 	int valt = show_expression(expr->cond_true);
1038*c85f09ccSJohn Levon 	int valf = show_expression(expr->cond_false);
10391f5207b7SJohn Levon 	int new = new_pseudo();
10401f5207b7SJohn Levon 
1041*c85f09ccSJohn Levon 	printf("[v%d]\tcmov.%d\t\tv%d,v%d,v%d\n", cond, expr->ctype->bit_size, new, valt, valf);
10421f5207b7SJohn Levon 	return new;
10431f5207b7SJohn Levon }
10441f5207b7SJohn Levon 
show_statement_expr(struct expression * expr)10451f5207b7SJohn Levon static int show_statement_expr(struct expression *expr)
10461f5207b7SJohn Levon {
10471f5207b7SJohn Levon 	return show_statement(expr->statement);
10481f5207b7SJohn Levon }
10491f5207b7SJohn Levon 
show_position_expr(struct expression * expr,struct symbol * base)10501f5207b7SJohn Levon static int show_position_expr(struct expression *expr, struct symbol *base)
10511f5207b7SJohn Levon {
10521f5207b7SJohn Levon 	int new = show_expression(expr->init_expr);
10531f5207b7SJohn Levon 	struct symbol *ctype = expr->init_expr->ctype;
10541f5207b7SJohn Levon 	int bit_offset;
10551f5207b7SJohn Levon 
10561f5207b7SJohn Levon 	bit_offset = ctype ? ctype->bit_offset : -1;
10571f5207b7SJohn Levon 
10581f5207b7SJohn Levon 	printf("\tinsert v%d at [%d:%d] of %s\n", new,
10591f5207b7SJohn Levon 		expr->init_offset, bit_offset,
10601f5207b7SJohn Levon 		show_ident(base->ident));
10611f5207b7SJohn Levon 	return 0;
10621f5207b7SJohn Levon }
10631f5207b7SJohn Levon 
show_initializer_expr(struct expression * expr,struct symbol * ctype)10641f5207b7SJohn Levon static int show_initializer_expr(struct expression *expr, struct symbol *ctype)
10651f5207b7SJohn Levon {
10661f5207b7SJohn Levon 	struct expression *entry;
10671f5207b7SJohn Levon 
10681f5207b7SJohn Levon 	FOR_EACH_PTR(expr->expr_list, entry) {
10691f5207b7SJohn Levon 
10701f5207b7SJohn Levon again:
10711f5207b7SJohn Levon 		// Nested initializers have their positions already
10721f5207b7SJohn Levon 		// recursively calculated - just output them too
10731f5207b7SJohn Levon 		if (entry->type == EXPR_INITIALIZER) {
10741f5207b7SJohn Levon 			show_initializer_expr(entry, ctype);
10751f5207b7SJohn Levon 			continue;
10761f5207b7SJohn Levon 		}
10771f5207b7SJohn Levon 
10781f5207b7SJohn Levon 		// Initializer indexes and identifiers should
10791f5207b7SJohn Levon 		// have been evaluated to EXPR_POS
10801f5207b7SJohn Levon 		if (entry->type == EXPR_IDENTIFIER) {
10811f5207b7SJohn Levon 			printf(" AT '%s':\n", show_ident(entry->expr_ident));
10821f5207b7SJohn Levon 			entry = entry->ident_expression;
10831f5207b7SJohn Levon 			goto again;
10841f5207b7SJohn Levon 		}
10851f5207b7SJohn Levon 
10861f5207b7SJohn Levon 		if (entry->type == EXPR_INDEX) {
10871f5207b7SJohn Levon 			printf(" AT '%d..%d:\n", entry->idx_from, entry->idx_to);
10881f5207b7SJohn Levon 			entry = entry->idx_expression;
10891f5207b7SJohn Levon 			goto again;
10901f5207b7SJohn Levon 		}
10911f5207b7SJohn Levon 		if (entry->type == EXPR_POS) {
10921f5207b7SJohn Levon 			show_position_expr(entry, ctype);
10931f5207b7SJohn Levon 			continue;
10941f5207b7SJohn Levon 		}
10951f5207b7SJohn Levon 		show_initialization(ctype, entry);
10961f5207b7SJohn Levon 	} END_FOR_EACH_PTR(entry);
10971f5207b7SJohn Levon 	return 0;
10981f5207b7SJohn Levon }
10991f5207b7SJohn Levon 
show_symbol_expr_init(struct symbol * sym)11001f5207b7SJohn Levon int show_symbol_expr_init(struct symbol *sym)
11011f5207b7SJohn Levon {
11021f5207b7SJohn Levon 	struct expression *expr = sym->initializer;
11031f5207b7SJohn Levon 
11041f5207b7SJohn Levon 	if (expr)
11051f5207b7SJohn Levon 		show_expression(expr);
11061f5207b7SJohn Levon 	return show_symbol_expr(sym);
11071f5207b7SJohn Levon }
11081f5207b7SJohn Levon 
11091f5207b7SJohn Levon /*
11101f5207b7SJohn Levon  * Print out an expression. Return the pseudo that contains the
11111f5207b7SJohn Levon  * variable.
11121f5207b7SJohn Levon  */
show_expression(struct expression * expr)11131f5207b7SJohn Levon int show_expression(struct expression *expr)
11141f5207b7SJohn Levon {
11151f5207b7SJohn Levon 	if (!expr)
11161f5207b7SJohn Levon 		return 0;
11171f5207b7SJohn Levon 
11181f5207b7SJohn Levon 	if (!expr->ctype) {
11191f5207b7SJohn Levon 		struct position *pos = &expr->pos;
11201f5207b7SJohn Levon 		printf("\tno type at %s:%d:%d\n",
11211f5207b7SJohn Levon 			stream_name(pos->stream),
11221f5207b7SJohn Levon 			pos->line, pos->pos);
11231f5207b7SJohn Levon 		return 0;
11241f5207b7SJohn Levon 	}
11251f5207b7SJohn Levon 
11261f5207b7SJohn Levon 	switch (expr->type) {
11271f5207b7SJohn Levon 	case EXPR_CALL:
11281f5207b7SJohn Levon 		return show_call_expression(expr);
11291f5207b7SJohn Levon 
11301f5207b7SJohn Levon 	case EXPR_ASSIGNMENT:
11311f5207b7SJohn Levon 		return show_assignment(expr);
11321f5207b7SJohn Levon 
11331f5207b7SJohn Levon 	case EXPR_COMMA:
11341f5207b7SJohn Levon 		return show_comma(expr);
11351f5207b7SJohn Levon 	case EXPR_BINOP:
11361f5207b7SJohn Levon 	case EXPR_COMPARE:
11371f5207b7SJohn Levon 	case EXPR_LOGICAL:
11381f5207b7SJohn Levon 		return show_binop(expr);
11391f5207b7SJohn Levon 	case EXPR_PREOP:
11401f5207b7SJohn Levon 		return show_preop(expr);
11411f5207b7SJohn Levon 	case EXPR_POSTOP:
11421f5207b7SJohn Levon 		return show_postop(expr);
11431f5207b7SJohn Levon 	case EXPR_SYMBOL:
11441f5207b7SJohn Levon 		return show_symbol_expr(expr->symbol);
11451f5207b7SJohn Levon 	case EXPR_DEREF:
11461f5207b7SJohn Levon 	case EXPR_SIZEOF:
11471f5207b7SJohn Levon 	case EXPR_PTRSIZEOF:
11481f5207b7SJohn Levon 	case EXPR_ALIGNOF:
11491f5207b7SJohn Levon 	case EXPR_OFFSETOF:
11501f5207b7SJohn Levon 		warning(expr->pos, "invalid expression after evaluation");
11511f5207b7SJohn Levon 		return 0;
11521f5207b7SJohn Levon 	case EXPR_CAST:
11531f5207b7SJohn Levon 	case EXPR_FORCE_CAST:
11541f5207b7SJohn Levon 	case EXPR_IMPLIED_CAST:
11551f5207b7SJohn Levon 		return show_cast_expr(expr);
11561f5207b7SJohn Levon 	case EXPR_VALUE:
11571f5207b7SJohn Levon 		return show_value(expr);
11581f5207b7SJohn Levon 	case EXPR_FVALUE:
11591f5207b7SJohn Levon 		return show_fvalue(expr);
11601f5207b7SJohn Levon 	case EXPR_STRING:
11611f5207b7SJohn Levon 		return show_string_expr(expr);
11621f5207b7SJohn Levon 	case EXPR_INITIALIZER:
11631f5207b7SJohn Levon 		return show_initializer_expr(expr, expr->ctype);
11641f5207b7SJohn Levon 	case EXPR_SELECT:
11651f5207b7SJohn Levon 	case EXPR_CONDITIONAL:
11661f5207b7SJohn Levon 		return show_conditional_expr(expr);
11671f5207b7SJohn Levon 	case EXPR_STATEMENT:
11681f5207b7SJohn Levon 		return show_statement_expr(expr);
11691f5207b7SJohn Levon 	case EXPR_LABEL:
11701f5207b7SJohn Levon 		return show_label_expr(expr);
11711f5207b7SJohn Levon 	case EXPR_SLICE:
11721f5207b7SJohn Levon 		return show_slice(expr);
11731f5207b7SJohn Levon 
11741f5207b7SJohn Levon 	// None of these should exist as direct expressions: they are only
11751f5207b7SJohn Levon 	// valid as sub-expressions of initializers.
11761f5207b7SJohn Levon 	case EXPR_POS:
11771f5207b7SJohn Levon 		warning(expr->pos, "unable to show plain initializer position expression");
11781f5207b7SJohn Levon 		return 0;
11791f5207b7SJohn Levon 	case EXPR_IDENTIFIER:
11801f5207b7SJohn Levon 		warning(expr->pos, "unable to show identifier expression");
11811f5207b7SJohn Levon 		return 0;
11821f5207b7SJohn Levon 	case EXPR_INDEX:
11831f5207b7SJohn Levon 		warning(expr->pos, "unable to show index expression");
11841f5207b7SJohn Levon 		return 0;
11851f5207b7SJohn Levon 	case EXPR_TYPE:
11861f5207b7SJohn Levon 		warning(expr->pos, "unable to show type expression");
11871f5207b7SJohn Levon 		return 0;
1188*c85f09ccSJohn Levon 	case EXPR_ASM_OPERAND:
1189*c85f09ccSJohn Levon 		warning(expr->pos, "unable to show asm operand expression");
1190*c85f09ccSJohn Levon 		return 0;
11911f5207b7SJohn Levon 	}
11921f5207b7SJohn Levon 	return 0;
11931f5207b7SJohn Levon }
1194