xref: /illumos-gate/usr/src/tools/smatch/src/expand.c (revision 1f5207b7)
1*1f5207b7SJohn Levon /*
2*1f5207b7SJohn Levon  * sparse/expand.c
3*1f5207b7SJohn Levon  *
4*1f5207b7SJohn Levon  * Copyright (C) 2003 Transmeta Corp.
5*1f5207b7SJohn Levon  *               2003-2004 Linus Torvalds
6*1f5207b7SJohn Levon  *
7*1f5207b7SJohn Levon  * Permission is hereby granted, free of charge, to any person obtaining a copy
8*1f5207b7SJohn Levon  * of this software and associated documentation files (the "Software"), to deal
9*1f5207b7SJohn Levon  * in the Software without restriction, including without limitation the rights
10*1f5207b7SJohn Levon  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11*1f5207b7SJohn Levon  * copies of the Software, and to permit persons to whom the Software is
12*1f5207b7SJohn Levon  * furnished to do so, subject to the following conditions:
13*1f5207b7SJohn Levon  *
14*1f5207b7SJohn Levon  * The above copyright notice and this permission notice shall be included in
15*1f5207b7SJohn Levon  * all copies or substantial portions of the Software.
16*1f5207b7SJohn Levon  *
17*1f5207b7SJohn Levon  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*1f5207b7SJohn Levon  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*1f5207b7SJohn Levon  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20*1f5207b7SJohn Levon  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*1f5207b7SJohn Levon  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*1f5207b7SJohn Levon  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23*1f5207b7SJohn Levon  * THE SOFTWARE.
24*1f5207b7SJohn Levon  *
25*1f5207b7SJohn Levon  * expand constant expressions.
26*1f5207b7SJohn Levon  */
27*1f5207b7SJohn Levon #include <stdlib.h>
28*1f5207b7SJohn Levon #include <stdarg.h>
29*1f5207b7SJohn Levon #include <stddef.h>
30*1f5207b7SJohn Levon #include <stdio.h>
31*1f5207b7SJohn Levon #include <string.h>
32*1f5207b7SJohn Levon #include <ctype.h>
33*1f5207b7SJohn Levon #include <unistd.h>
34*1f5207b7SJohn Levon #include <fcntl.h>
35*1f5207b7SJohn Levon #include <limits.h>
36*1f5207b7SJohn Levon 
37*1f5207b7SJohn Levon #include "lib.h"
38*1f5207b7SJohn Levon #include "allocate.h"
39*1f5207b7SJohn Levon #include "parse.h"
40*1f5207b7SJohn Levon #include "token.h"
41*1f5207b7SJohn Levon #include "symbol.h"
42*1f5207b7SJohn Levon #include "target.h"
43*1f5207b7SJohn Levon #include "expression.h"
44*1f5207b7SJohn Levon #include "expand.h"
45*1f5207b7SJohn Levon 
46*1f5207b7SJohn Levon 
47*1f5207b7SJohn Levon static int expand_expression(struct expression *);
48*1f5207b7SJohn Levon static int expand_statement(struct statement *);
49*1f5207b7SJohn Levon static int conservative;
50*1f5207b7SJohn Levon 
51*1f5207b7SJohn Levon static int expand_symbol_expression(struct expression *expr)
52*1f5207b7SJohn Levon {
53*1f5207b7SJohn Levon 	struct symbol *sym = expr->symbol;
54*1f5207b7SJohn Levon 
55*1f5207b7SJohn Levon 	if (sym == &zero_int) {
56*1f5207b7SJohn Levon 		if (Wundef)
57*1f5207b7SJohn Levon 			warning(expr->pos, "undefined preprocessor identifier '%s'", show_ident(expr->symbol_name));
58*1f5207b7SJohn Levon 		expr->type = EXPR_VALUE;
59*1f5207b7SJohn Levon 		expr->value = 0;
60*1f5207b7SJohn Levon 		expr->taint = 0;
61*1f5207b7SJohn Levon 		return 0;
62*1f5207b7SJohn Levon 	}
63*1f5207b7SJohn Levon 	/* The cost of a symbol expression is lower for on-stack symbols */
64*1f5207b7SJohn Levon 	return (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN)) ? 2 : 1;
65*1f5207b7SJohn Levon }
66*1f5207b7SJohn Levon 
67*1f5207b7SJohn Levon static long long get_longlong(struct expression *expr)
68*1f5207b7SJohn Levon {
69*1f5207b7SJohn Levon 	int no_expand = expr->ctype->ctype.modifiers & MOD_UNSIGNED;
70*1f5207b7SJohn Levon 	long long mask = 1ULL << (expr->ctype->bit_size - 1);
71*1f5207b7SJohn Levon 	long long value = expr->value;
72*1f5207b7SJohn Levon 	long long ormask, andmask;
73*1f5207b7SJohn Levon 
74*1f5207b7SJohn Levon 	if (!(value & mask))
75*1f5207b7SJohn Levon 		no_expand = 1;
76*1f5207b7SJohn Levon 	andmask = mask | (mask-1);
77*1f5207b7SJohn Levon 	ormask = ~andmask;
78*1f5207b7SJohn Levon 	if (no_expand)
79*1f5207b7SJohn Levon 		ormask = 0;
80*1f5207b7SJohn Levon 	return (value & andmask) | ormask;
81*1f5207b7SJohn Levon }
82*1f5207b7SJohn Levon 
83*1f5207b7SJohn Levon void cast_value(struct expression *expr, struct symbol *newtype,
84*1f5207b7SJohn Levon 		struct expression *old, struct symbol *oldtype)
85*1f5207b7SJohn Levon {
86*1f5207b7SJohn Levon 	int old_size = oldtype->bit_size;
87*1f5207b7SJohn Levon 	int new_size = newtype->bit_size;
88*1f5207b7SJohn Levon 	long long value, mask, signmask;
89*1f5207b7SJohn Levon 	long long oldmask, oldsignmask, dropped;
90*1f5207b7SJohn Levon 
91*1f5207b7SJohn Levon 	if (is_float_type(newtype) || is_float_type(oldtype))
92*1f5207b7SJohn Levon 		goto Float;
93*1f5207b7SJohn Levon 
94*1f5207b7SJohn Levon 	// For pointers and integers, we can just move the value around
95*1f5207b7SJohn Levon 	expr->type = EXPR_VALUE;
96*1f5207b7SJohn Levon 	expr->taint = old->taint;
97*1f5207b7SJohn Levon 	if (old_size == new_size) {
98*1f5207b7SJohn Levon 		expr->value = old->value;
99*1f5207b7SJohn Levon 		return;
100*1f5207b7SJohn Levon 	}
101*1f5207b7SJohn Levon 
102*1f5207b7SJohn Levon 	// expand it to the full "long long" value
103*1f5207b7SJohn Levon 	value = get_longlong(old);
104*1f5207b7SJohn Levon 
105*1f5207b7SJohn Levon Int:
106*1f5207b7SJohn Levon 	// _Bool requires a zero test rather than truncation.
107*1f5207b7SJohn Levon 	if (is_bool_type(newtype)) {
108*1f5207b7SJohn Levon 		expr->value = !!value;
109*1f5207b7SJohn Levon 		if (!conservative && value != 0 && value != 1)
110*1f5207b7SJohn Levon 			warning(old->pos, "odd constant _Bool cast (%llx becomes 1)", value);
111*1f5207b7SJohn Levon 		return;
112*1f5207b7SJohn Levon 	}
113*1f5207b7SJohn Levon 
114*1f5207b7SJohn Levon 	// Truncate it to the new size
115*1f5207b7SJohn Levon 	signmask = 1ULL << (new_size-1);
116*1f5207b7SJohn Levon 	mask = signmask | (signmask-1);
117*1f5207b7SJohn Levon 	expr->value = value & mask;
118*1f5207b7SJohn Levon 
119*1f5207b7SJohn Levon 	// Stop here unless checking for truncation
120*1f5207b7SJohn Levon 	if (!Wcast_truncate || conservative)
121*1f5207b7SJohn Levon 		return;
122*1f5207b7SJohn Levon 
123*1f5207b7SJohn Levon 	// Check if we dropped any bits..
124*1f5207b7SJohn Levon 	oldsignmask = 1ULL << (old_size-1);
125*1f5207b7SJohn Levon 	oldmask = oldsignmask | (oldsignmask-1);
126*1f5207b7SJohn Levon 	dropped = oldmask & ~mask;
127*1f5207b7SJohn Levon 
128*1f5207b7SJohn Levon 	// OK if the bits were (and still are) purely sign bits
129*1f5207b7SJohn Levon 	if (value & dropped) {
130*1f5207b7SJohn Levon 		if (!(value & oldsignmask) || !(value & signmask) || (value & dropped) != dropped)
131*1f5207b7SJohn Levon 			warning(old->pos, "cast truncates bits from constant value (%llx becomes %llx)",
132*1f5207b7SJohn Levon 				value & oldmask,
133*1f5207b7SJohn Levon 				value & mask);
134*1f5207b7SJohn Levon 	}
135*1f5207b7SJohn Levon 	return;
136*1f5207b7SJohn Levon 
137*1f5207b7SJohn Levon Float:
138*1f5207b7SJohn Levon 	if (!is_float_type(newtype)) {
139*1f5207b7SJohn Levon 		value = (long long)old->fvalue;
140*1f5207b7SJohn Levon 		expr->type = EXPR_VALUE;
141*1f5207b7SJohn Levon 		expr->taint = 0;
142*1f5207b7SJohn Levon 		goto Int;
143*1f5207b7SJohn Levon 	}
144*1f5207b7SJohn Levon 
145*1f5207b7SJohn Levon 	if (!is_float_type(oldtype))
146*1f5207b7SJohn Levon 		expr->fvalue = (long double)get_longlong(old);
147*1f5207b7SJohn Levon 	else
148*1f5207b7SJohn Levon 		expr->fvalue = old->fvalue;
149*1f5207b7SJohn Levon 
150*1f5207b7SJohn Levon 	if (!(newtype->ctype.modifiers & MOD_LONGLONG) && \
151*1f5207b7SJohn Levon 	    !(newtype->ctype.modifiers & MOD_LONGLONGLONG)) {
152*1f5207b7SJohn Levon 		if ((newtype->ctype.modifiers & MOD_LONG))
153*1f5207b7SJohn Levon 			expr->fvalue = (double)expr->fvalue;
154*1f5207b7SJohn Levon 		else
155*1f5207b7SJohn Levon 			expr->fvalue = (float)expr->fvalue;
156*1f5207b7SJohn Levon 	}
157*1f5207b7SJohn Levon 	expr->type = EXPR_FVALUE;
158*1f5207b7SJohn Levon }
159*1f5207b7SJohn Levon 
160*1f5207b7SJohn Levon static int check_shift_count(struct expression *expr, struct symbol *ctype, unsigned int count)
161*1f5207b7SJohn Levon {
162*1f5207b7SJohn Levon 	warning(expr->pos, "shift too big (%u) for type %s", count, show_typename(ctype));
163*1f5207b7SJohn Levon 	count &= ctype->bit_size-1;
164*1f5207b7SJohn Levon 	return count;
165*1f5207b7SJohn Levon }
166*1f5207b7SJohn Levon 
167*1f5207b7SJohn Levon /*
168*1f5207b7SJohn Levon  * CAREFUL! We need to get the size and sign of the
169*1f5207b7SJohn Levon  * result right!
170*1f5207b7SJohn Levon  */
171*1f5207b7SJohn Levon #define CONVERT(op,s)	(((op)<<1)+(s))
172*1f5207b7SJohn Levon #define SIGNED(op)	CONVERT(op, 1)
173*1f5207b7SJohn Levon #define UNSIGNED(op)	CONVERT(op, 0)
174*1f5207b7SJohn Levon static int simplify_int_binop(struct expression *expr, struct symbol *ctype)
175*1f5207b7SJohn Levon {
176*1f5207b7SJohn Levon 	struct expression *left = expr->left, *right = expr->right;
177*1f5207b7SJohn Levon 	unsigned long long v, l, r, mask;
178*1f5207b7SJohn Levon 	signed long long sl, sr;
179*1f5207b7SJohn Levon 	int is_signed;
180*1f5207b7SJohn Levon 
181*1f5207b7SJohn Levon 	if (right->type != EXPR_VALUE)
182*1f5207b7SJohn Levon 		return 0;
183*1f5207b7SJohn Levon 	r = right->value;
184*1f5207b7SJohn Levon 	if (expr->op == SPECIAL_LEFTSHIFT || expr->op == SPECIAL_RIGHTSHIFT) {
185*1f5207b7SJohn Levon 		if (r >= ctype->bit_size) {
186*1f5207b7SJohn Levon 			if (conservative)
187*1f5207b7SJohn Levon 				return 0;
188*1f5207b7SJohn Levon 			r = check_shift_count(expr, ctype, r);
189*1f5207b7SJohn Levon 			right->value = r;
190*1f5207b7SJohn Levon 		}
191*1f5207b7SJohn Levon 	}
192*1f5207b7SJohn Levon 	if (left->type != EXPR_VALUE)
193*1f5207b7SJohn Levon 		return 0;
194*1f5207b7SJohn Levon 	l = left->value; r = right->value;
195*1f5207b7SJohn Levon 	is_signed = !(ctype->ctype.modifiers & MOD_UNSIGNED);
196*1f5207b7SJohn Levon 	mask = 1ULL << (ctype->bit_size-1);
197*1f5207b7SJohn Levon 	sl = l; sr = r;
198*1f5207b7SJohn Levon 	if (is_signed && (sl & mask))
199*1f5207b7SJohn Levon 		sl |= ~(mask-1);
200*1f5207b7SJohn Levon 	if (is_signed && (sr & mask))
201*1f5207b7SJohn Levon 		sr |= ~(mask-1);
202*1f5207b7SJohn Levon 
203*1f5207b7SJohn Levon 	switch (CONVERT(expr->op,is_signed)) {
204*1f5207b7SJohn Levon 	case SIGNED('+'):
205*1f5207b7SJohn Levon 	case UNSIGNED('+'):
206*1f5207b7SJohn Levon 		v = l + r;
207*1f5207b7SJohn Levon 		break;
208*1f5207b7SJohn Levon 
209*1f5207b7SJohn Levon 	case SIGNED('-'):
210*1f5207b7SJohn Levon 	case UNSIGNED('-'):
211*1f5207b7SJohn Levon 		v = l - r;
212*1f5207b7SJohn Levon 		break;
213*1f5207b7SJohn Levon 
214*1f5207b7SJohn Levon 	case SIGNED('&'):
215*1f5207b7SJohn Levon 	case UNSIGNED('&'):
216*1f5207b7SJohn Levon 		v = l & r;
217*1f5207b7SJohn Levon 		break;
218*1f5207b7SJohn Levon 
219*1f5207b7SJohn Levon 	case SIGNED('|'):
220*1f5207b7SJohn Levon 	case UNSIGNED('|'):
221*1f5207b7SJohn Levon 		v = l | r;
222*1f5207b7SJohn Levon 		break;
223*1f5207b7SJohn Levon 
224*1f5207b7SJohn Levon 	case SIGNED('^'):
225*1f5207b7SJohn Levon 	case UNSIGNED('^'):
226*1f5207b7SJohn Levon 		v = l ^ r;
227*1f5207b7SJohn Levon 		break;
228*1f5207b7SJohn Levon 
229*1f5207b7SJohn Levon 	case SIGNED('*'):
230*1f5207b7SJohn Levon 		v = sl * sr;
231*1f5207b7SJohn Levon 		break;
232*1f5207b7SJohn Levon 
233*1f5207b7SJohn Levon 	case UNSIGNED('*'):
234*1f5207b7SJohn Levon 		v = l * r;
235*1f5207b7SJohn Levon 		break;
236*1f5207b7SJohn Levon 
237*1f5207b7SJohn Levon 	case SIGNED('/'):
238*1f5207b7SJohn Levon 		if (!r)
239*1f5207b7SJohn Levon 			goto Div;
240*1f5207b7SJohn Levon 		if (l == mask && sr == -1)
241*1f5207b7SJohn Levon 			goto Overflow;
242*1f5207b7SJohn Levon 		v = sl / sr;
243*1f5207b7SJohn Levon 		break;
244*1f5207b7SJohn Levon 
245*1f5207b7SJohn Levon 	case UNSIGNED('/'):
246*1f5207b7SJohn Levon 		if (!r) goto Div;
247*1f5207b7SJohn Levon 		v = l / r;
248*1f5207b7SJohn Levon 		break;
249*1f5207b7SJohn Levon 
250*1f5207b7SJohn Levon 	case SIGNED('%'):
251*1f5207b7SJohn Levon 		if (!r)
252*1f5207b7SJohn Levon 			goto Div;
253*1f5207b7SJohn Levon 		if (l == mask && sr == -1)
254*1f5207b7SJohn Levon 			goto Overflow;
255*1f5207b7SJohn Levon 		v = sl % sr;
256*1f5207b7SJohn Levon 		break;
257*1f5207b7SJohn Levon 
258*1f5207b7SJohn Levon 	case UNSIGNED('%'):
259*1f5207b7SJohn Levon 		if (!r) goto Div;
260*1f5207b7SJohn Levon 		v = l % r;
261*1f5207b7SJohn Levon 		break;
262*1f5207b7SJohn Levon 
263*1f5207b7SJohn Levon 	case SIGNED(SPECIAL_LEFTSHIFT):
264*1f5207b7SJohn Levon 	case UNSIGNED(SPECIAL_LEFTSHIFT):
265*1f5207b7SJohn Levon 		v = l << r;
266*1f5207b7SJohn Levon 		break;
267*1f5207b7SJohn Levon 
268*1f5207b7SJohn Levon 	case SIGNED(SPECIAL_RIGHTSHIFT):
269*1f5207b7SJohn Levon 		v = sl >> r;
270*1f5207b7SJohn Levon 		break;
271*1f5207b7SJohn Levon 
272*1f5207b7SJohn Levon 	case UNSIGNED(SPECIAL_RIGHTSHIFT):
273*1f5207b7SJohn Levon 		v = l >> r;
274*1f5207b7SJohn Levon 		break;
275*1f5207b7SJohn Levon 
276*1f5207b7SJohn Levon 	default:
277*1f5207b7SJohn Levon 		return 0;
278*1f5207b7SJohn Levon 	}
279*1f5207b7SJohn Levon 	mask = mask | (mask-1);
280*1f5207b7SJohn Levon 	expr->value = v & mask;
281*1f5207b7SJohn Levon 	expr->type = EXPR_VALUE;
282*1f5207b7SJohn Levon 	expr->taint = left->taint | right->taint;
283*1f5207b7SJohn Levon 	return 1;
284*1f5207b7SJohn Levon Div:
285*1f5207b7SJohn Levon 	if (!conservative)
286*1f5207b7SJohn Levon 		warning(expr->pos, "division by zero");
287*1f5207b7SJohn Levon 	return 0;
288*1f5207b7SJohn Levon Overflow:
289*1f5207b7SJohn Levon 	if (!conservative)
290*1f5207b7SJohn Levon 		warning(expr->pos, "constant integer operation overflow");
291*1f5207b7SJohn Levon 	return 0;
292*1f5207b7SJohn Levon }
293*1f5207b7SJohn Levon 
294*1f5207b7SJohn Levon static int simplify_cmp_binop(struct expression *expr, struct symbol *ctype)
295*1f5207b7SJohn Levon {
296*1f5207b7SJohn Levon 	struct expression *left = expr->left, *right = expr->right;
297*1f5207b7SJohn Levon 	unsigned long long l, r, mask;
298*1f5207b7SJohn Levon 	signed long long sl, sr;
299*1f5207b7SJohn Levon 
300*1f5207b7SJohn Levon 	if (left->type != EXPR_VALUE || right->type != EXPR_VALUE)
301*1f5207b7SJohn Levon 		return 0;
302*1f5207b7SJohn Levon 	l = left->value; r = right->value;
303*1f5207b7SJohn Levon 	mask = 1ULL << (ctype->bit_size-1);
304*1f5207b7SJohn Levon 	sl = l; sr = r;
305*1f5207b7SJohn Levon 	if (sl & mask)
306*1f5207b7SJohn Levon 		sl |= ~(mask-1);
307*1f5207b7SJohn Levon 	if (sr & mask)
308*1f5207b7SJohn Levon 		sr |= ~(mask-1);
309*1f5207b7SJohn Levon 	switch (expr->op) {
310*1f5207b7SJohn Levon 	case '<':		expr->value = sl < sr; break;
311*1f5207b7SJohn Levon 	case '>':		expr->value = sl > sr; break;
312*1f5207b7SJohn Levon 	case SPECIAL_LTE:	expr->value = sl <= sr; break;
313*1f5207b7SJohn Levon 	case SPECIAL_GTE:	expr->value = sl >= sr; break;
314*1f5207b7SJohn Levon 	case SPECIAL_EQUAL:	expr->value = l == r; break;
315*1f5207b7SJohn Levon 	case SPECIAL_NOTEQUAL:	expr->value = l != r; break;
316*1f5207b7SJohn Levon 	case SPECIAL_UNSIGNED_LT:expr->value = l < r; break;
317*1f5207b7SJohn Levon 	case SPECIAL_UNSIGNED_GT:expr->value = l > r; break;
318*1f5207b7SJohn Levon 	case SPECIAL_UNSIGNED_LTE:expr->value = l <= r; break;
319*1f5207b7SJohn Levon 	case SPECIAL_UNSIGNED_GTE:expr->value = l >= r; break;
320*1f5207b7SJohn Levon 	}
321*1f5207b7SJohn Levon 	expr->type = EXPR_VALUE;
322*1f5207b7SJohn Levon 	expr->taint = left->taint | right->taint;
323*1f5207b7SJohn Levon 	return 1;
324*1f5207b7SJohn Levon }
325*1f5207b7SJohn Levon 
326*1f5207b7SJohn Levon static int simplify_float_binop(struct expression *expr)
327*1f5207b7SJohn Levon {
328*1f5207b7SJohn Levon 	struct expression *left = expr->left, *right = expr->right;
329*1f5207b7SJohn Levon 	unsigned long mod = expr->ctype->ctype.modifiers;
330*1f5207b7SJohn Levon 	long double l, r, res;
331*1f5207b7SJohn Levon 
332*1f5207b7SJohn Levon 	if (left->type != EXPR_FVALUE || right->type != EXPR_FVALUE)
333*1f5207b7SJohn Levon 		return 0;
334*1f5207b7SJohn Levon 
335*1f5207b7SJohn Levon 	l = left->fvalue;
336*1f5207b7SJohn Levon 	r = right->fvalue;
337*1f5207b7SJohn Levon 
338*1f5207b7SJohn Levon 	if (mod & MOD_LONGLONG) {
339*1f5207b7SJohn Levon 		switch (expr->op) {
340*1f5207b7SJohn Levon 		case '+':	res = l + r; break;
341*1f5207b7SJohn Levon 		case '-':	res = l - r; break;
342*1f5207b7SJohn Levon 		case '*':	res = l * r; break;
343*1f5207b7SJohn Levon 		case '/':	if (!r) goto Div;
344*1f5207b7SJohn Levon 				res = l / r; break;
345*1f5207b7SJohn Levon 		default: return 0;
346*1f5207b7SJohn Levon 		}
347*1f5207b7SJohn Levon 	} else if (mod & MOD_LONG) {
348*1f5207b7SJohn Levon 		switch (expr->op) {
349*1f5207b7SJohn Levon 		case '+':	res = (double) l + (double) r; break;
350*1f5207b7SJohn Levon 		case '-':	res = (double) l - (double) r; break;
351*1f5207b7SJohn Levon 		case '*':	res = (double) l * (double) r; break;
352*1f5207b7SJohn Levon 		case '/':	if (!r) goto Div;
353*1f5207b7SJohn Levon 				res = (double) l / (double) r; break;
354*1f5207b7SJohn Levon 		default: return 0;
355*1f5207b7SJohn Levon 		}
356*1f5207b7SJohn Levon 	} else {
357*1f5207b7SJohn Levon 		switch (expr->op) {
358*1f5207b7SJohn Levon 		case '+':	res = (float)l + (float)r; break;
359*1f5207b7SJohn Levon 		case '-':	res = (float)l - (float)r; break;
360*1f5207b7SJohn Levon 		case '*':	res = (float)l * (float)r; break;
361*1f5207b7SJohn Levon 		case '/':	if (!r) goto Div;
362*1f5207b7SJohn Levon 				res = (float)l / (float)r; break;
363*1f5207b7SJohn Levon 		default: return 0;
364*1f5207b7SJohn Levon 		}
365*1f5207b7SJohn Levon 	}
366*1f5207b7SJohn Levon 	expr->type = EXPR_FVALUE;
367*1f5207b7SJohn Levon 	expr->fvalue = res;
368*1f5207b7SJohn Levon 	return 1;
369*1f5207b7SJohn Levon Div:
370*1f5207b7SJohn Levon 	if (!conservative)
371*1f5207b7SJohn Levon 		warning(expr->pos, "division by zero");
372*1f5207b7SJohn Levon 	return 0;
373*1f5207b7SJohn Levon }
374*1f5207b7SJohn Levon 
375*1f5207b7SJohn Levon static int simplify_float_cmp(struct expression *expr, struct symbol *ctype)
376*1f5207b7SJohn Levon {
377*1f5207b7SJohn Levon 	struct expression *left = expr->left, *right = expr->right;
378*1f5207b7SJohn Levon 	long double l, r;
379*1f5207b7SJohn Levon 
380*1f5207b7SJohn Levon 	if (left->type != EXPR_FVALUE || right->type != EXPR_FVALUE)
381*1f5207b7SJohn Levon 		return 0;
382*1f5207b7SJohn Levon 
383*1f5207b7SJohn Levon 	l = left->fvalue;
384*1f5207b7SJohn Levon 	r = right->fvalue;
385*1f5207b7SJohn Levon 	switch (expr->op) {
386*1f5207b7SJohn Levon 	case '<':		expr->value = l < r; break;
387*1f5207b7SJohn Levon 	case '>':		expr->value = l > r; break;
388*1f5207b7SJohn Levon 	case SPECIAL_LTE:	expr->value = l <= r; break;
389*1f5207b7SJohn Levon 	case SPECIAL_GTE:	expr->value = l >= r; break;
390*1f5207b7SJohn Levon 	case SPECIAL_EQUAL:	expr->value = l == r; break;
391*1f5207b7SJohn Levon 	case SPECIAL_NOTEQUAL:	expr->value = l != r; break;
392*1f5207b7SJohn Levon 	}
393*1f5207b7SJohn Levon 	expr->type = EXPR_VALUE;
394*1f5207b7SJohn Levon 	expr->taint = 0;
395*1f5207b7SJohn Levon 	return 1;
396*1f5207b7SJohn Levon }
397*1f5207b7SJohn Levon 
398*1f5207b7SJohn Levon static int expand_binop(struct expression *expr)
399*1f5207b7SJohn Levon {
400*1f5207b7SJohn Levon 	int cost;
401*1f5207b7SJohn Levon 
402*1f5207b7SJohn Levon 	cost = expand_expression(expr->left);
403*1f5207b7SJohn Levon 	cost += expand_expression(expr->right);
404*1f5207b7SJohn Levon 	if (simplify_int_binop(expr, expr->ctype))
405*1f5207b7SJohn Levon 		return 0;
406*1f5207b7SJohn Levon 	if (simplify_float_binop(expr))
407*1f5207b7SJohn Levon 		return 0;
408*1f5207b7SJohn Levon 	return cost + 1;
409*1f5207b7SJohn Levon }
410*1f5207b7SJohn Levon 
411*1f5207b7SJohn Levon static int expand_logical(struct expression *expr)
412*1f5207b7SJohn Levon {
413*1f5207b7SJohn Levon 	struct expression *left = expr->left;
414*1f5207b7SJohn Levon 	struct expression *right;
415*1f5207b7SJohn Levon 	int cost, rcost;
416*1f5207b7SJohn Levon 
417*1f5207b7SJohn Levon 	/* Do immediate short-circuiting ... */
418*1f5207b7SJohn Levon 	cost = expand_expression(left);
419*1f5207b7SJohn Levon 	if (left->type == EXPR_VALUE) {
420*1f5207b7SJohn Levon 		if (expr->op == SPECIAL_LOGICAL_AND) {
421*1f5207b7SJohn Levon 			if (!left->value) {
422*1f5207b7SJohn Levon 				expr->type = EXPR_VALUE;
423*1f5207b7SJohn Levon 				expr->value = 0;
424*1f5207b7SJohn Levon 				expr->taint = left->taint;
425*1f5207b7SJohn Levon 				return 0;
426*1f5207b7SJohn Levon 			}
427*1f5207b7SJohn Levon 		} else {
428*1f5207b7SJohn Levon 			if (left->value) {
429*1f5207b7SJohn Levon 				expr->type = EXPR_VALUE;
430*1f5207b7SJohn Levon 				expr->value = 1;
431*1f5207b7SJohn Levon 				expr->taint = left->taint;
432*1f5207b7SJohn Levon 				return 0;
433*1f5207b7SJohn Levon 			}
434*1f5207b7SJohn Levon 		}
435*1f5207b7SJohn Levon 	}
436*1f5207b7SJohn Levon 
437*1f5207b7SJohn Levon 	right = expr->right;
438*1f5207b7SJohn Levon 	rcost = expand_expression(right);
439*1f5207b7SJohn Levon 	if (left->type == EXPR_VALUE && right->type == EXPR_VALUE) {
440*1f5207b7SJohn Levon 		/*
441*1f5207b7SJohn Levon 		 * We know the left value doesn't matter, since
442*1f5207b7SJohn Levon 		 * otherwise we would have short-circuited it..
443*1f5207b7SJohn Levon 		 */
444*1f5207b7SJohn Levon 		expr->type = EXPR_VALUE;
445*1f5207b7SJohn Levon 		expr->value = right->value != 0;
446*1f5207b7SJohn Levon 		expr->taint = left->taint | right->taint;
447*1f5207b7SJohn Levon 		return 0;
448*1f5207b7SJohn Levon 	}
449*1f5207b7SJohn Levon 
450*1f5207b7SJohn Levon 	/*
451*1f5207b7SJohn Levon 	 * If the right side is safe and cheaper than a branch,
452*1f5207b7SJohn Levon 	 * just avoid the branch and turn it into a regular binop
453*1f5207b7SJohn Levon 	 * style SAFELOGICAL.
454*1f5207b7SJohn Levon 	 */
455*1f5207b7SJohn Levon 	if (rcost < BRANCH_COST) {
456*1f5207b7SJohn Levon 		expr->type = EXPR_BINOP;
457*1f5207b7SJohn Levon 		rcost -= BRANCH_COST - 1;
458*1f5207b7SJohn Levon 	}
459*1f5207b7SJohn Levon 
460*1f5207b7SJohn Levon 	return cost + BRANCH_COST + rcost;
461*1f5207b7SJohn Levon }
462*1f5207b7SJohn Levon 
463*1f5207b7SJohn Levon static int expand_comma(struct expression *expr)
464*1f5207b7SJohn Levon {
465*1f5207b7SJohn Levon 	int cost;
466*1f5207b7SJohn Levon 
467*1f5207b7SJohn Levon 	cost = expand_expression(expr->left);
468*1f5207b7SJohn Levon 	cost += expand_expression(expr->right);
469*1f5207b7SJohn Levon 	if (expr->left->type == EXPR_VALUE || expr->left->type == EXPR_FVALUE) {
470*1f5207b7SJohn Levon 		unsigned flags = expr->flags;
471*1f5207b7SJohn Levon 		unsigned taint;
472*1f5207b7SJohn Levon 		taint = expr->left->type == EXPR_VALUE ? expr->left->taint : 0;
473*1f5207b7SJohn Levon 		*expr = *expr->right;
474*1f5207b7SJohn Levon 		expr->flags = flags;
475*1f5207b7SJohn Levon 		if (expr->type == EXPR_VALUE)
476*1f5207b7SJohn Levon 			expr->taint |= Taint_comma | taint;
477*1f5207b7SJohn Levon 	}
478*1f5207b7SJohn Levon 	return cost;
479*1f5207b7SJohn Levon }
480*1f5207b7SJohn Levon 
481*1f5207b7SJohn Levon #define MOD_IGN (MOD_VOLATILE | MOD_CONST)
482*1f5207b7SJohn Levon 
483*1f5207b7SJohn Levon static int compare_types(int op, struct symbol *left, struct symbol *right)
484*1f5207b7SJohn Levon {
485*1f5207b7SJohn Levon 	struct ctype c1 = {.base_type = left};
486*1f5207b7SJohn Levon 	struct ctype c2 = {.base_type = right};
487*1f5207b7SJohn Levon 	switch (op) {
488*1f5207b7SJohn Levon 	case SPECIAL_EQUAL:
489*1f5207b7SJohn Levon 		return !type_difference(&c1, &c2, MOD_IGN, MOD_IGN);
490*1f5207b7SJohn Levon 	case SPECIAL_NOTEQUAL:
491*1f5207b7SJohn Levon 		return type_difference(&c1, &c2, MOD_IGN, MOD_IGN) != NULL;
492*1f5207b7SJohn Levon 	case '<':
493*1f5207b7SJohn Levon 		return left->bit_size < right->bit_size;
494*1f5207b7SJohn Levon 	case '>':
495*1f5207b7SJohn Levon 		return left->bit_size > right->bit_size;
496*1f5207b7SJohn Levon 	case SPECIAL_LTE:
497*1f5207b7SJohn Levon 		return left->bit_size <= right->bit_size;
498*1f5207b7SJohn Levon 	case SPECIAL_GTE:
499*1f5207b7SJohn Levon 		return left->bit_size >= right->bit_size;
500*1f5207b7SJohn Levon 	}
501*1f5207b7SJohn Levon 	return 0;
502*1f5207b7SJohn Levon }
503*1f5207b7SJohn Levon 
504*1f5207b7SJohn Levon static int expand_compare(struct expression *expr)
505*1f5207b7SJohn Levon {
506*1f5207b7SJohn Levon 	struct expression *left = expr->left, *right = expr->right;
507*1f5207b7SJohn Levon 	int cost;
508*1f5207b7SJohn Levon 
509*1f5207b7SJohn Levon 	cost = expand_expression(left);
510*1f5207b7SJohn Levon 	cost += expand_expression(right);
511*1f5207b7SJohn Levon 
512*1f5207b7SJohn Levon 	if (left && right) {
513*1f5207b7SJohn Levon 		/* Type comparison? */
514*1f5207b7SJohn Levon 		if (left->type == EXPR_TYPE && right->type == EXPR_TYPE) {
515*1f5207b7SJohn Levon 			int op = expr->op;
516*1f5207b7SJohn Levon 			expr->type = EXPR_VALUE;
517*1f5207b7SJohn Levon 			expr->value = compare_types(op, left->symbol, right->symbol);
518*1f5207b7SJohn Levon 			expr->taint = 0;
519*1f5207b7SJohn Levon 			return 0;
520*1f5207b7SJohn Levon 		}
521*1f5207b7SJohn Levon 		if (simplify_cmp_binop(expr, left->ctype))
522*1f5207b7SJohn Levon 			return 0;
523*1f5207b7SJohn Levon 		if (simplify_float_cmp(expr, left->ctype))
524*1f5207b7SJohn Levon 			return 0;
525*1f5207b7SJohn Levon 	}
526*1f5207b7SJohn Levon 	return cost + 1;
527*1f5207b7SJohn Levon }
528*1f5207b7SJohn Levon 
529*1f5207b7SJohn Levon static int expand_conditional(struct expression *expr)
530*1f5207b7SJohn Levon {
531*1f5207b7SJohn Levon 	struct expression *cond = expr->conditional;
532*1f5207b7SJohn Levon 	struct expression *true = expr->cond_true;
533*1f5207b7SJohn Levon 	struct expression *false = expr->cond_false;
534*1f5207b7SJohn Levon 	int cost, cond_cost;
535*1f5207b7SJohn Levon 
536*1f5207b7SJohn Levon 	cond_cost = expand_expression(cond);
537*1f5207b7SJohn Levon 	if (cond->type == EXPR_VALUE) {
538*1f5207b7SJohn Levon 		unsigned flags = expr->flags;
539*1f5207b7SJohn Levon 		if (!cond->value)
540*1f5207b7SJohn Levon 			true = false;
541*1f5207b7SJohn Levon 		if (!true)
542*1f5207b7SJohn Levon 			true = cond;
543*1f5207b7SJohn Levon 		cost = expand_expression(true);
544*1f5207b7SJohn Levon 		*expr = *true;
545*1f5207b7SJohn Levon 		expr->flags = flags;
546*1f5207b7SJohn Levon 		if (expr->type == EXPR_VALUE)
547*1f5207b7SJohn Levon 			expr->taint |= cond->taint;
548*1f5207b7SJohn Levon 		return cost;
549*1f5207b7SJohn Levon 	}
550*1f5207b7SJohn Levon 
551*1f5207b7SJohn Levon 	cost = expand_expression(true);
552*1f5207b7SJohn Levon 	cost += expand_expression(false);
553*1f5207b7SJohn Levon 
554*1f5207b7SJohn Levon 	if (cost < SELECT_COST) {
555*1f5207b7SJohn Levon 		expr->type = EXPR_SELECT;
556*1f5207b7SJohn Levon 		cost -= BRANCH_COST - 1;
557*1f5207b7SJohn Levon 	}
558*1f5207b7SJohn Levon 
559*1f5207b7SJohn Levon 	return cost + cond_cost + BRANCH_COST;
560*1f5207b7SJohn Levon }
561*1f5207b7SJohn Levon 
562*1f5207b7SJohn Levon static int expand_assignment(struct expression *expr)
563*1f5207b7SJohn Levon {
564*1f5207b7SJohn Levon 	expand_expression(expr->left);
565*1f5207b7SJohn Levon 	expand_expression(expr->right);
566*1f5207b7SJohn Levon 	return SIDE_EFFECTS;
567*1f5207b7SJohn Levon }
568*1f5207b7SJohn Levon 
569*1f5207b7SJohn Levon static int expand_addressof(struct expression *expr)
570*1f5207b7SJohn Levon {
571*1f5207b7SJohn Levon 	return expand_expression(expr->unop);
572*1f5207b7SJohn Levon }
573*1f5207b7SJohn Levon 
574*1f5207b7SJohn Levon /*
575*1f5207b7SJohn Levon  * Look up a trustable initializer value at the requested offset.
576*1f5207b7SJohn Levon  *
577*1f5207b7SJohn Levon  * Return NULL if no such value can be found or statically trusted.
578*1f5207b7SJohn Levon  *
579*1f5207b7SJohn Levon  * FIXME!! We should check that the size is right!
580*1f5207b7SJohn Levon  */
581*1f5207b7SJohn Levon static struct expression *constant_symbol_value(struct symbol *sym, int offset)
582*1f5207b7SJohn Levon {
583*1f5207b7SJohn Levon 	struct expression *value;
584*1f5207b7SJohn Levon 
585*1f5207b7SJohn Levon 	if (sym->ctype.modifiers & (MOD_ASSIGNED | MOD_ADDRESSABLE))
586*1f5207b7SJohn Levon 		return NULL;
587*1f5207b7SJohn Levon 	value = sym->initializer;
588*1f5207b7SJohn Levon 	if (!value)
589*1f5207b7SJohn Levon 		return NULL;
590*1f5207b7SJohn Levon 	if (value->type == EXPR_INITIALIZER) {
591*1f5207b7SJohn Levon 		struct expression *entry;
592*1f5207b7SJohn Levon 		FOR_EACH_PTR(value->expr_list, entry) {
593*1f5207b7SJohn Levon 			if (entry->type != EXPR_POS) {
594*1f5207b7SJohn Levon 				if (offset)
595*1f5207b7SJohn Levon 					continue;
596*1f5207b7SJohn Levon 				return entry;
597*1f5207b7SJohn Levon 			}
598*1f5207b7SJohn Levon 			if (entry->init_offset < offset)
599*1f5207b7SJohn Levon 				continue;
600*1f5207b7SJohn Levon 			if (entry->init_offset > offset)
601*1f5207b7SJohn Levon 				return NULL;
602*1f5207b7SJohn Levon 			return entry->init_expr;
603*1f5207b7SJohn Levon 		} END_FOR_EACH_PTR(entry);
604*1f5207b7SJohn Levon 		return NULL;
605*1f5207b7SJohn Levon 	}
606*1f5207b7SJohn Levon 	return value;
607*1f5207b7SJohn Levon }
608*1f5207b7SJohn Levon 
609*1f5207b7SJohn Levon static int expand_dereference(struct expression *expr)
610*1f5207b7SJohn Levon {
611*1f5207b7SJohn Levon 	struct expression *unop = expr->unop;
612*1f5207b7SJohn Levon 	unsigned int offset;
613*1f5207b7SJohn Levon 
614*1f5207b7SJohn Levon 	expand_expression(unop);
615*1f5207b7SJohn Levon 
616*1f5207b7SJohn Levon 	/*
617*1f5207b7SJohn Levon 	 * NOTE! We get a bogus warning right now for some special
618*1f5207b7SJohn Levon 	 * cases: apparently I've screwed up the optimization of
619*1f5207b7SJohn Levon 	 * a zero-offset dereference, and the ctype is wrong.
620*1f5207b7SJohn Levon 	 *
621*1f5207b7SJohn Levon 	 * Leave the warning in anyway, since this is also a good
622*1f5207b7SJohn Levon 	 * test for me to get the type evaluation right..
623*1f5207b7SJohn Levon 	 */
624*1f5207b7SJohn Levon 	if (expr->ctype->ctype.modifiers & MOD_NODEREF)
625*1f5207b7SJohn Levon 		warning(unop->pos, "dereference of noderef expression");
626*1f5207b7SJohn Levon 
627*1f5207b7SJohn Levon 	/*
628*1f5207b7SJohn Levon 	 * Is it "symbol" or "symbol + offset"?
629*1f5207b7SJohn Levon 	 */
630*1f5207b7SJohn Levon 	offset = 0;
631*1f5207b7SJohn Levon 	if (unop->type == EXPR_BINOP && unop->op == '+') {
632*1f5207b7SJohn Levon 		struct expression *right = unop->right;
633*1f5207b7SJohn Levon 		if (right->type == EXPR_VALUE) {
634*1f5207b7SJohn Levon 			offset = right->value;
635*1f5207b7SJohn Levon 			unop = unop->left;
636*1f5207b7SJohn Levon 		}
637*1f5207b7SJohn Levon 	}
638*1f5207b7SJohn Levon 
639*1f5207b7SJohn Levon 	if (unop->type == EXPR_SYMBOL) {
640*1f5207b7SJohn Levon 		struct symbol *sym = unop->symbol;
641*1f5207b7SJohn Levon 		struct expression *value = constant_symbol_value(sym, offset);
642*1f5207b7SJohn Levon 
643*1f5207b7SJohn Levon 		/* Const symbol with a constant initializer? */
644*1f5207b7SJohn Levon 		if (value) {
645*1f5207b7SJohn Levon 			/* FIXME! We should check that the size is right! */
646*1f5207b7SJohn Levon 			if (value->type == EXPR_VALUE) {
647*1f5207b7SJohn Levon 				expr->type = EXPR_VALUE;
648*1f5207b7SJohn Levon 				expr->value = value->value;
649*1f5207b7SJohn Levon 				expr->taint = 0;
650*1f5207b7SJohn Levon 				return 0;
651*1f5207b7SJohn Levon 			} else if (value->type == EXPR_FVALUE) {
652*1f5207b7SJohn Levon 				expr->type = EXPR_FVALUE;
653*1f5207b7SJohn Levon 				expr->fvalue = value->fvalue;
654*1f5207b7SJohn Levon 				return 0;
655*1f5207b7SJohn Levon 			}
656*1f5207b7SJohn Levon 		}
657*1f5207b7SJohn Levon 
658*1f5207b7SJohn Levon 		/* Direct symbol dereference? Cheap and safe */
659*1f5207b7SJohn Levon 		return (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN)) ? 2 : 1;
660*1f5207b7SJohn Levon 	}
661*1f5207b7SJohn Levon 
662*1f5207b7SJohn Levon 	return UNSAFE;
663*1f5207b7SJohn Levon }
664*1f5207b7SJohn Levon 
665*1f5207b7SJohn Levon static int simplify_preop(struct expression *expr)
666*1f5207b7SJohn Levon {
667*1f5207b7SJohn Levon 	struct expression *op = expr->unop;
668*1f5207b7SJohn Levon 	unsigned long long v, mask;
669*1f5207b7SJohn Levon 
670*1f5207b7SJohn Levon 	if (op->type != EXPR_VALUE)
671*1f5207b7SJohn Levon 		return 0;
672*1f5207b7SJohn Levon 
673*1f5207b7SJohn Levon 	mask = 1ULL << (expr->ctype->bit_size-1);
674*1f5207b7SJohn Levon 	v = op->value;
675*1f5207b7SJohn Levon 	switch (expr->op) {
676*1f5207b7SJohn Levon 	case '+': break;
677*1f5207b7SJohn Levon 	case '-':
678*1f5207b7SJohn Levon 		if (v == mask && !(expr->ctype->ctype.modifiers & MOD_UNSIGNED))
679*1f5207b7SJohn Levon 			goto Overflow;
680*1f5207b7SJohn Levon 		v = -v;
681*1f5207b7SJohn Levon 		break;
682*1f5207b7SJohn Levon 	case '!': v = !v; break;
683*1f5207b7SJohn Levon 	case '~': v = ~v; break;
684*1f5207b7SJohn Levon 	default: return 0;
685*1f5207b7SJohn Levon 	}
686*1f5207b7SJohn Levon 	mask = mask | (mask-1);
687*1f5207b7SJohn Levon 	expr->value = v & mask;
688*1f5207b7SJohn Levon 	expr->type = EXPR_VALUE;
689*1f5207b7SJohn Levon 	expr->taint = op->taint;
690*1f5207b7SJohn Levon 	return 1;
691*1f5207b7SJohn Levon 
692*1f5207b7SJohn Levon Overflow:
693*1f5207b7SJohn Levon 	if (!conservative)
694*1f5207b7SJohn Levon 		warning(expr->pos, "constant integer operation overflow");
695*1f5207b7SJohn Levon 	return 0;
696*1f5207b7SJohn Levon }
697*1f5207b7SJohn Levon 
698*1f5207b7SJohn Levon static int simplify_float_preop(struct expression *expr)
699*1f5207b7SJohn Levon {
700*1f5207b7SJohn Levon 	struct expression *op = expr->unop;
701*1f5207b7SJohn Levon 	long double v;
702*1f5207b7SJohn Levon 
703*1f5207b7SJohn Levon 	if (op->type != EXPR_FVALUE)
704*1f5207b7SJohn Levon 		return 0;
705*1f5207b7SJohn Levon 	v = op->fvalue;
706*1f5207b7SJohn Levon 	switch (expr->op) {
707*1f5207b7SJohn Levon 	case '+': break;
708*1f5207b7SJohn Levon 	case '-': v = -v; break;
709*1f5207b7SJohn Levon 	default: return 0;
710*1f5207b7SJohn Levon 	}
711*1f5207b7SJohn Levon 	expr->fvalue = v;
712*1f5207b7SJohn Levon 	expr->type = EXPR_FVALUE;
713*1f5207b7SJohn Levon 	return 1;
714*1f5207b7SJohn Levon }
715*1f5207b7SJohn Levon 
716*1f5207b7SJohn Levon /*
717*1f5207b7SJohn Levon  * Unary post-ops: x++ and x--
718*1f5207b7SJohn Levon  */
719*1f5207b7SJohn Levon static int expand_postop(struct expression *expr)
720*1f5207b7SJohn Levon {
721*1f5207b7SJohn Levon 	expand_expression(expr->unop);
722*1f5207b7SJohn Levon 	return SIDE_EFFECTS;
723*1f5207b7SJohn Levon }
724*1f5207b7SJohn Levon 
725*1f5207b7SJohn Levon static int expand_preop(struct expression *expr)
726*1f5207b7SJohn Levon {
727*1f5207b7SJohn Levon 	int cost;
728*1f5207b7SJohn Levon 
729*1f5207b7SJohn Levon 	switch (expr->op) {
730*1f5207b7SJohn Levon 	case '*':
731*1f5207b7SJohn Levon 		return expand_dereference(expr);
732*1f5207b7SJohn Levon 
733*1f5207b7SJohn Levon 	case '&':
734*1f5207b7SJohn Levon 		return expand_addressof(expr);
735*1f5207b7SJohn Levon 
736*1f5207b7SJohn Levon 	case SPECIAL_INCREMENT:
737*1f5207b7SJohn Levon 	case SPECIAL_DECREMENT:
738*1f5207b7SJohn Levon 		/*
739*1f5207b7SJohn Levon 		 * From a type evaluation standpoint the preops are
740*1f5207b7SJohn Levon 		 * the same as the postops
741*1f5207b7SJohn Levon 		 */
742*1f5207b7SJohn Levon 		return expand_postop(expr);
743*1f5207b7SJohn Levon 
744*1f5207b7SJohn Levon 	default:
745*1f5207b7SJohn Levon 		break;
746*1f5207b7SJohn Levon 	}
747*1f5207b7SJohn Levon 	cost = expand_expression(expr->unop);
748*1f5207b7SJohn Levon 
749*1f5207b7SJohn Levon 	if (simplify_preop(expr))
750*1f5207b7SJohn Levon 		return 0;
751*1f5207b7SJohn Levon 	if (simplify_float_preop(expr))
752*1f5207b7SJohn Levon 		return 0;
753*1f5207b7SJohn Levon 	return cost + 1;
754*1f5207b7SJohn Levon }
755*1f5207b7SJohn Levon 
756*1f5207b7SJohn Levon static int expand_arguments(struct expression_list *head)
757*1f5207b7SJohn Levon {
758*1f5207b7SJohn Levon 	int cost = 0;
759*1f5207b7SJohn Levon 	struct expression *expr;
760*1f5207b7SJohn Levon 
761*1f5207b7SJohn Levon 	FOR_EACH_PTR (head, expr) {
762*1f5207b7SJohn Levon 		cost += expand_expression(expr);
763*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(expr);
764*1f5207b7SJohn Levon 	return cost;
765*1f5207b7SJohn Levon }
766*1f5207b7SJohn Levon 
767*1f5207b7SJohn Levon static int expand_cast(struct expression *expr)
768*1f5207b7SJohn Levon {
769*1f5207b7SJohn Levon 	int cost;
770*1f5207b7SJohn Levon 	struct expression *target = expr->cast_expression;
771*1f5207b7SJohn Levon 
772*1f5207b7SJohn Levon 	cost = expand_expression(target);
773*1f5207b7SJohn Levon 
774*1f5207b7SJohn Levon 	/* Simplify normal integer casts.. */
775*1f5207b7SJohn Levon 	if (target->type == EXPR_VALUE || target->type == EXPR_FVALUE) {
776*1f5207b7SJohn Levon 		cast_value(expr, expr->ctype, target, target->ctype);
777*1f5207b7SJohn Levon 		return 0;
778*1f5207b7SJohn Levon 	}
779*1f5207b7SJohn Levon 	return cost + 1;
780*1f5207b7SJohn Levon }
781*1f5207b7SJohn Levon 
782*1f5207b7SJohn Levon /*
783*1f5207b7SJohn Levon  * expand a call expression with a symbol. This
784*1f5207b7SJohn Levon  * should expand builtins.
785*1f5207b7SJohn Levon  */
786*1f5207b7SJohn Levon static int expand_symbol_call(struct expression *expr, int cost)
787*1f5207b7SJohn Levon {
788*1f5207b7SJohn Levon 	struct expression *fn = expr->fn;
789*1f5207b7SJohn Levon 	struct symbol *ctype = fn->ctype;
790*1f5207b7SJohn Levon 
791*1f5207b7SJohn Levon 	if (fn->type != EXPR_PREOP)
792*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
793*1f5207b7SJohn Levon 
794*1f5207b7SJohn Levon 	if (ctype->op && ctype->op->expand)
795*1f5207b7SJohn Levon 		return ctype->op->expand(expr, cost);
796*1f5207b7SJohn Levon 
797*1f5207b7SJohn Levon 	if (ctype->ctype.modifiers & MOD_PURE)
798*1f5207b7SJohn Levon 		return cost + 1;
799*1f5207b7SJohn Levon 
800*1f5207b7SJohn Levon 	return SIDE_EFFECTS;
801*1f5207b7SJohn Levon }
802*1f5207b7SJohn Levon 
803*1f5207b7SJohn Levon static int expand_call(struct expression *expr)
804*1f5207b7SJohn Levon {
805*1f5207b7SJohn Levon 	int cost;
806*1f5207b7SJohn Levon 	struct symbol *sym;
807*1f5207b7SJohn Levon 	struct expression *fn = expr->fn;
808*1f5207b7SJohn Levon 
809*1f5207b7SJohn Levon 	cost = expand_arguments(expr->args);
810*1f5207b7SJohn Levon 	sym = fn->ctype;
811*1f5207b7SJohn Levon 	if (!sym) {
812*1f5207b7SJohn Levon 		expression_error(expr, "function has no type");
813*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
814*1f5207b7SJohn Levon 	}
815*1f5207b7SJohn Levon 	if (sym->type == SYM_NODE)
816*1f5207b7SJohn Levon 		return expand_symbol_call(expr, cost);
817*1f5207b7SJohn Levon 
818*1f5207b7SJohn Levon 	return SIDE_EFFECTS;
819*1f5207b7SJohn Levon }
820*1f5207b7SJohn Levon 
821*1f5207b7SJohn Levon static int expand_expression_list(struct expression_list *list)
822*1f5207b7SJohn Levon {
823*1f5207b7SJohn Levon 	int cost = 0;
824*1f5207b7SJohn Levon 	struct expression *expr;
825*1f5207b7SJohn Levon 
826*1f5207b7SJohn Levon 	FOR_EACH_PTR(list, expr) {
827*1f5207b7SJohn Levon 		cost += expand_expression(expr);
828*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(expr);
829*1f5207b7SJohn Levon 	return cost;
830*1f5207b7SJohn Levon }
831*1f5207b7SJohn Levon 
832*1f5207b7SJohn Levon /*
833*1f5207b7SJohn Levon  * We can simplify nested position expressions if
834*1f5207b7SJohn Levon  * this is a simple (single) positional expression.
835*1f5207b7SJohn Levon  */
836*1f5207b7SJohn Levon static int expand_pos_expression(struct expression *expr)
837*1f5207b7SJohn Levon {
838*1f5207b7SJohn Levon 	struct expression *nested = expr->init_expr;
839*1f5207b7SJohn Levon 	unsigned long offset = expr->init_offset;
840*1f5207b7SJohn Levon 	int nr = expr->init_nr;
841*1f5207b7SJohn Levon 
842*1f5207b7SJohn Levon 	if (nr == 1) {
843*1f5207b7SJohn Levon 		switch (nested->type) {
844*1f5207b7SJohn Levon 		case EXPR_POS:
845*1f5207b7SJohn Levon 			offset += nested->init_offset;
846*1f5207b7SJohn Levon 			*expr = *nested;
847*1f5207b7SJohn Levon 			expr->init_offset = offset;
848*1f5207b7SJohn Levon 			nested = expr;
849*1f5207b7SJohn Levon 			break;
850*1f5207b7SJohn Levon 
851*1f5207b7SJohn Levon 		case EXPR_INITIALIZER: {
852*1f5207b7SJohn Levon 			struct expression *reuse = nested, *entry;
853*1f5207b7SJohn Levon 			*expr = *nested;
854*1f5207b7SJohn Levon 			FOR_EACH_PTR(expr->expr_list, entry) {
855*1f5207b7SJohn Levon 				if (entry->type == EXPR_POS) {
856*1f5207b7SJohn Levon 					entry->init_offset += offset;
857*1f5207b7SJohn Levon 				} else {
858*1f5207b7SJohn Levon 					if (!reuse) {
859*1f5207b7SJohn Levon 						/*
860*1f5207b7SJohn Levon 						 * This happens rarely, but it can happen
861*1f5207b7SJohn Levon 						 * with bitfields that are all at offset
862*1f5207b7SJohn Levon 						 * zero..
863*1f5207b7SJohn Levon 						 */
864*1f5207b7SJohn Levon 						reuse = alloc_expression(entry->pos, EXPR_POS);
865*1f5207b7SJohn Levon 					}
866*1f5207b7SJohn Levon 					reuse->type = EXPR_POS;
867*1f5207b7SJohn Levon 					reuse->ctype = entry->ctype;
868*1f5207b7SJohn Levon 					reuse->init_offset = offset;
869*1f5207b7SJohn Levon 					reuse->init_nr = 1;
870*1f5207b7SJohn Levon 					reuse->init_expr = entry;
871*1f5207b7SJohn Levon 					REPLACE_CURRENT_PTR(entry, reuse);
872*1f5207b7SJohn Levon 					reuse = NULL;
873*1f5207b7SJohn Levon 				}
874*1f5207b7SJohn Levon 			} END_FOR_EACH_PTR(entry);
875*1f5207b7SJohn Levon 			nested = expr;
876*1f5207b7SJohn Levon 			break;
877*1f5207b7SJohn Levon 		}
878*1f5207b7SJohn Levon 
879*1f5207b7SJohn Levon 		default:
880*1f5207b7SJohn Levon 			break;
881*1f5207b7SJohn Levon 		}
882*1f5207b7SJohn Levon 	}
883*1f5207b7SJohn Levon 	return expand_expression(nested);
884*1f5207b7SJohn Levon }
885*1f5207b7SJohn Levon 
886*1f5207b7SJohn Levon static unsigned long bit_offset(const struct expression *expr)
887*1f5207b7SJohn Levon {
888*1f5207b7SJohn Levon 	unsigned long offset = 0;
889*1f5207b7SJohn Levon 	while (expr->type == EXPR_POS) {
890*1f5207b7SJohn Levon 		offset += bytes_to_bits(expr->init_offset);
891*1f5207b7SJohn Levon 		expr = expr->init_expr;
892*1f5207b7SJohn Levon 	}
893*1f5207b7SJohn Levon 	if (expr && expr->ctype)
894*1f5207b7SJohn Levon 		offset += expr->ctype->bit_offset;
895*1f5207b7SJohn Levon 	return offset;
896*1f5207b7SJohn Levon }
897*1f5207b7SJohn Levon 
898*1f5207b7SJohn Levon static unsigned long bit_range(const struct expression *expr)
899*1f5207b7SJohn Levon {
900*1f5207b7SJohn Levon 	unsigned long range = 0;
901*1f5207b7SJohn Levon 	unsigned long size = 0;
902*1f5207b7SJohn Levon 	while (expr->type == EXPR_POS) {
903*1f5207b7SJohn Levon 		unsigned long nr = expr->init_nr;
904*1f5207b7SJohn Levon 		size = expr->ctype->bit_size;
905*1f5207b7SJohn Levon 		range += (nr - 1) * size;
906*1f5207b7SJohn Levon 		expr = expr->init_expr;
907*1f5207b7SJohn Levon 	}
908*1f5207b7SJohn Levon 	range += size;
909*1f5207b7SJohn Levon 	return range;
910*1f5207b7SJohn Levon }
911*1f5207b7SJohn Levon 
912*1f5207b7SJohn Levon static int compare_expressions(const void *_a, const void *_b)
913*1f5207b7SJohn Levon {
914*1f5207b7SJohn Levon 	const struct expression *a = _a;
915*1f5207b7SJohn Levon 	const struct expression *b = _b;
916*1f5207b7SJohn Levon 	unsigned long a_pos = bit_offset(a);
917*1f5207b7SJohn Levon 	unsigned long b_pos = bit_offset(b);
918*1f5207b7SJohn Levon 
919*1f5207b7SJohn Levon 	return (a_pos < b_pos) ? -1 : (a_pos == b_pos) ? 0 : 1;
920*1f5207b7SJohn Levon }
921*1f5207b7SJohn Levon 
922*1f5207b7SJohn Levon static void sort_expression_list(struct expression_list **list)
923*1f5207b7SJohn Levon {
924*1f5207b7SJohn Levon 	sort_list((struct ptr_list **)list, compare_expressions);
925*1f5207b7SJohn Levon }
926*1f5207b7SJohn Levon 
927*1f5207b7SJohn Levon static void verify_nonoverlapping(struct expression_list **list, struct expression *expr)
928*1f5207b7SJohn Levon {
929*1f5207b7SJohn Levon 	struct expression *a = NULL;
930*1f5207b7SJohn Levon 	unsigned long max = 0;
931*1f5207b7SJohn Levon 	unsigned long whole = expr->ctype->bit_size;
932*1f5207b7SJohn Levon 	struct expression *b;
933*1f5207b7SJohn Levon 
934*1f5207b7SJohn Levon 	if (!Woverride_init)
935*1f5207b7SJohn Levon 		return;
936*1f5207b7SJohn Levon 
937*1f5207b7SJohn Levon 	FOR_EACH_PTR(*list, b) {
938*1f5207b7SJohn Levon 		unsigned long off, end;
939*1f5207b7SJohn Levon 		if (!b->ctype || !b->ctype->bit_size)
940*1f5207b7SJohn Levon 			continue;
941*1f5207b7SJohn Levon 		off = bit_offset(b);
942*1f5207b7SJohn Levon 		if (a && off < max) {
943*1f5207b7SJohn Levon 			warning(a->pos, "Initializer entry defined twice");
944*1f5207b7SJohn Levon 			info(b->pos, "  also defined here");
945*1f5207b7SJohn Levon 			if (!Woverride_init_all)
946*1f5207b7SJohn Levon 				return;
947*1f5207b7SJohn Levon 		}
948*1f5207b7SJohn Levon 		end = off + bit_range(b);
949*1f5207b7SJohn Levon 		if (!a && !Woverride_init_whole_range) {
950*1f5207b7SJohn Levon 			// If first entry is the whole range, do not let
951*1f5207b7SJohn Levon 			// any warning about it (this allow to initialize
952*1f5207b7SJohn Levon 			// an array with some default value and then override
953*1f5207b7SJohn Levon 			// some specific entries).
954*1f5207b7SJohn Levon 			if (off == 0 && end == whole)
955*1f5207b7SJohn Levon 				continue;
956*1f5207b7SJohn Levon 		}
957*1f5207b7SJohn Levon 		if (end > max) {
958*1f5207b7SJohn Levon 			max = end;
959*1f5207b7SJohn Levon 			a = b;
960*1f5207b7SJohn Levon 		}
961*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(b);
962*1f5207b7SJohn Levon }
963*1f5207b7SJohn Levon 
964*1f5207b7SJohn Levon static int expand_expression(struct expression *expr)
965*1f5207b7SJohn Levon {
966*1f5207b7SJohn Levon 	if (!expr)
967*1f5207b7SJohn Levon 		return 0;
968*1f5207b7SJohn Levon 	if (!expr->ctype || expr->ctype == &bad_ctype)
969*1f5207b7SJohn Levon 		return UNSAFE;
970*1f5207b7SJohn Levon 
971*1f5207b7SJohn Levon 	switch (expr->type) {
972*1f5207b7SJohn Levon 	case EXPR_VALUE:
973*1f5207b7SJohn Levon 	case EXPR_FVALUE:
974*1f5207b7SJohn Levon 	case EXPR_STRING:
975*1f5207b7SJohn Levon 		return 0;
976*1f5207b7SJohn Levon 	case EXPR_TYPE:
977*1f5207b7SJohn Levon 	case EXPR_SYMBOL:
978*1f5207b7SJohn Levon 		return expand_symbol_expression(expr);
979*1f5207b7SJohn Levon 	case EXPR_BINOP:
980*1f5207b7SJohn Levon 		return expand_binop(expr);
981*1f5207b7SJohn Levon 
982*1f5207b7SJohn Levon 	case EXPR_LOGICAL:
983*1f5207b7SJohn Levon 		return expand_logical(expr);
984*1f5207b7SJohn Levon 
985*1f5207b7SJohn Levon 	case EXPR_COMMA:
986*1f5207b7SJohn Levon 		return expand_comma(expr);
987*1f5207b7SJohn Levon 
988*1f5207b7SJohn Levon 	case EXPR_COMPARE:
989*1f5207b7SJohn Levon 		return expand_compare(expr);
990*1f5207b7SJohn Levon 
991*1f5207b7SJohn Levon 	case EXPR_ASSIGNMENT:
992*1f5207b7SJohn Levon 		return expand_assignment(expr);
993*1f5207b7SJohn Levon 
994*1f5207b7SJohn Levon 	case EXPR_PREOP:
995*1f5207b7SJohn Levon 		return expand_preop(expr);
996*1f5207b7SJohn Levon 
997*1f5207b7SJohn Levon 	case EXPR_POSTOP:
998*1f5207b7SJohn Levon 		return expand_postop(expr);
999*1f5207b7SJohn Levon 
1000*1f5207b7SJohn Levon 	case EXPR_CAST:
1001*1f5207b7SJohn Levon 	case EXPR_FORCE_CAST:
1002*1f5207b7SJohn Levon 	case EXPR_IMPLIED_CAST:
1003*1f5207b7SJohn Levon 		return expand_cast(expr);
1004*1f5207b7SJohn Levon 
1005*1f5207b7SJohn Levon 	case EXPR_CALL:
1006*1f5207b7SJohn Levon 		return expand_call(expr);
1007*1f5207b7SJohn Levon 
1008*1f5207b7SJohn Levon 	case EXPR_DEREF:
1009*1f5207b7SJohn Levon 		warning(expr->pos, "we should not have an EXPR_DEREF left at expansion time");
1010*1f5207b7SJohn Levon 		return UNSAFE;
1011*1f5207b7SJohn Levon 
1012*1f5207b7SJohn Levon 	case EXPR_SELECT:
1013*1f5207b7SJohn Levon 	case EXPR_CONDITIONAL:
1014*1f5207b7SJohn Levon 		return expand_conditional(expr);
1015*1f5207b7SJohn Levon 
1016*1f5207b7SJohn Levon 	case EXPR_STATEMENT: {
1017*1f5207b7SJohn Levon 		struct statement *stmt = expr->statement;
1018*1f5207b7SJohn Levon 		int cost = expand_statement(stmt);
1019*1f5207b7SJohn Levon 
1020*1f5207b7SJohn Levon 		if (stmt->type == STMT_EXPRESSION && stmt->expression)
1021*1f5207b7SJohn Levon 			*expr = *stmt->expression;
1022*1f5207b7SJohn Levon 		return cost;
1023*1f5207b7SJohn Levon 	}
1024*1f5207b7SJohn Levon 
1025*1f5207b7SJohn Levon 	case EXPR_LABEL:
1026*1f5207b7SJohn Levon 		return 0;
1027*1f5207b7SJohn Levon 
1028*1f5207b7SJohn Levon 	case EXPR_INITIALIZER:
1029*1f5207b7SJohn Levon 		sort_expression_list(&expr->expr_list);
1030*1f5207b7SJohn Levon 		verify_nonoverlapping(&expr->expr_list, expr);
1031*1f5207b7SJohn Levon 		return expand_expression_list(expr->expr_list);
1032*1f5207b7SJohn Levon 
1033*1f5207b7SJohn Levon 	case EXPR_IDENTIFIER:
1034*1f5207b7SJohn Levon 		return UNSAFE;
1035*1f5207b7SJohn Levon 
1036*1f5207b7SJohn Levon 	case EXPR_INDEX:
1037*1f5207b7SJohn Levon 		return UNSAFE;
1038*1f5207b7SJohn Levon 
1039*1f5207b7SJohn Levon 	case EXPR_SLICE:
1040*1f5207b7SJohn Levon 		return expand_expression(expr->base) + 1;
1041*1f5207b7SJohn Levon 
1042*1f5207b7SJohn Levon 	case EXPR_POS:
1043*1f5207b7SJohn Levon 		return expand_pos_expression(expr);
1044*1f5207b7SJohn Levon 
1045*1f5207b7SJohn Levon 	case EXPR_SIZEOF:
1046*1f5207b7SJohn Levon 	case EXPR_PTRSIZEOF:
1047*1f5207b7SJohn Levon 	case EXPR_ALIGNOF:
1048*1f5207b7SJohn Levon 	case EXPR_OFFSETOF:
1049*1f5207b7SJohn Levon 		expression_error(expr, "internal front-end error: sizeof in expansion?");
1050*1f5207b7SJohn Levon 		return UNSAFE;
1051*1f5207b7SJohn Levon 	}
1052*1f5207b7SJohn Levon 	return SIDE_EFFECTS;
1053*1f5207b7SJohn Levon }
1054*1f5207b7SJohn Levon 
1055*1f5207b7SJohn Levon static void expand_const_expression(struct expression *expr, const char *where)
1056*1f5207b7SJohn Levon {
1057*1f5207b7SJohn Levon 	if (expr) {
1058*1f5207b7SJohn Levon 		expand_expression(expr);
1059*1f5207b7SJohn Levon 		if (expr->type != EXPR_VALUE)
1060*1f5207b7SJohn Levon 			expression_error(expr, "Expected constant expression in %s", where);
1061*1f5207b7SJohn Levon 	}
1062*1f5207b7SJohn Levon }
1063*1f5207b7SJohn Levon 
1064*1f5207b7SJohn Levon int expand_symbol(struct symbol *sym)
1065*1f5207b7SJohn Levon {
1066*1f5207b7SJohn Levon 	int retval;
1067*1f5207b7SJohn Levon 	struct symbol *base_type;
1068*1f5207b7SJohn Levon 
1069*1f5207b7SJohn Levon 	if (!sym)
1070*1f5207b7SJohn Levon 		return 0;
1071*1f5207b7SJohn Levon 	base_type = sym->ctype.base_type;
1072*1f5207b7SJohn Levon 	if (!base_type)
1073*1f5207b7SJohn Levon 		return 0;
1074*1f5207b7SJohn Levon 
1075*1f5207b7SJohn Levon 	retval = expand_expression(sym->initializer);
1076*1f5207b7SJohn Levon 	/* expand the body of the symbol */
1077*1f5207b7SJohn Levon 	if (base_type->type == SYM_FN) {
1078*1f5207b7SJohn Levon 		if (base_type->stmt)
1079*1f5207b7SJohn Levon 			expand_statement(base_type->stmt);
1080*1f5207b7SJohn Levon 	}
1081*1f5207b7SJohn Levon 	return retval;
1082*1f5207b7SJohn Levon }
1083*1f5207b7SJohn Levon 
1084*1f5207b7SJohn Levon static void expand_return_expression(struct statement *stmt)
1085*1f5207b7SJohn Levon {
1086*1f5207b7SJohn Levon 	expand_expression(stmt->expression);
1087*1f5207b7SJohn Levon }
1088*1f5207b7SJohn Levon 
1089*1f5207b7SJohn Levon static int expand_if_statement(struct statement *stmt)
1090*1f5207b7SJohn Levon {
1091*1f5207b7SJohn Levon 	struct expression *expr = stmt->if_conditional;
1092*1f5207b7SJohn Levon 
1093*1f5207b7SJohn Levon 	if (!expr || !expr->ctype || expr->ctype == &bad_ctype)
1094*1f5207b7SJohn Levon 		return UNSAFE;
1095*1f5207b7SJohn Levon 
1096*1f5207b7SJohn Levon 	expand_expression(expr);
1097*1f5207b7SJohn Levon 
1098*1f5207b7SJohn Levon /* This is only valid if nobody jumps into the "dead" side */
1099*1f5207b7SJohn Levon #if 0
1100*1f5207b7SJohn Levon 	/* Simplify constant conditionals without even evaluating the false side */
1101*1f5207b7SJohn Levon 	if (expr->type == EXPR_VALUE) {
1102*1f5207b7SJohn Levon 		struct statement *simple;
1103*1f5207b7SJohn Levon 		simple = expr->value ? stmt->if_true : stmt->if_false;
1104*1f5207b7SJohn Levon 
1105*1f5207b7SJohn Levon 		/* Nothing? */
1106*1f5207b7SJohn Levon 		if (!simple) {
1107*1f5207b7SJohn Levon 			stmt->type = STMT_NONE;
1108*1f5207b7SJohn Levon 			return 0;
1109*1f5207b7SJohn Levon 		}
1110*1f5207b7SJohn Levon 		expand_statement(simple);
1111*1f5207b7SJohn Levon 		*stmt = *simple;
1112*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
1113*1f5207b7SJohn Levon 	}
1114*1f5207b7SJohn Levon #endif
1115*1f5207b7SJohn Levon 	expand_statement(stmt->if_true);
1116*1f5207b7SJohn Levon 	expand_statement(stmt->if_false);
1117*1f5207b7SJohn Levon 	return SIDE_EFFECTS;
1118*1f5207b7SJohn Levon }
1119*1f5207b7SJohn Levon 
1120*1f5207b7SJohn Levon /*
1121*1f5207b7SJohn Levon  * Expanding a compound statement is really just
1122*1f5207b7SJohn Levon  * about adding up the costs of each individual
1123*1f5207b7SJohn Levon  * statement.
1124*1f5207b7SJohn Levon  *
1125*1f5207b7SJohn Levon  * We also collapse a simple compound statement:
1126*1f5207b7SJohn Levon  * this would trigger for simple inline functions,
1127*1f5207b7SJohn Levon  * except we would have to check the "return"
1128*1f5207b7SJohn Levon  * symbol usage. Next time.
1129*1f5207b7SJohn Levon  */
1130*1f5207b7SJohn Levon static int expand_compound(struct statement *stmt)
1131*1f5207b7SJohn Levon {
1132*1f5207b7SJohn Levon 	struct statement *s, *last;
1133*1f5207b7SJohn Levon 	int cost, statements;
1134*1f5207b7SJohn Levon 
1135*1f5207b7SJohn Levon 	if (stmt->ret)
1136*1f5207b7SJohn Levon 		expand_symbol(stmt->ret);
1137*1f5207b7SJohn Levon 
1138*1f5207b7SJohn Levon 	last = stmt->args;
1139*1f5207b7SJohn Levon 	cost = expand_statement(last);
1140*1f5207b7SJohn Levon 	statements = last != NULL;
1141*1f5207b7SJohn Levon 	FOR_EACH_PTR(stmt->stmts, s) {
1142*1f5207b7SJohn Levon 		statements++;
1143*1f5207b7SJohn Levon 		last = s;
1144*1f5207b7SJohn Levon 		cost += expand_statement(s);
1145*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(s);
1146*1f5207b7SJohn Levon 
1147*1f5207b7SJohn Levon 	if (statements == 1 && !stmt->ret)
1148*1f5207b7SJohn Levon 		*stmt = *last;
1149*1f5207b7SJohn Levon 
1150*1f5207b7SJohn Levon 	return cost;
1151*1f5207b7SJohn Levon }
1152*1f5207b7SJohn Levon 
1153*1f5207b7SJohn Levon static int expand_statement(struct statement *stmt)
1154*1f5207b7SJohn Levon {
1155*1f5207b7SJohn Levon 	if (!stmt)
1156*1f5207b7SJohn Levon 		return 0;
1157*1f5207b7SJohn Levon 
1158*1f5207b7SJohn Levon 	switch (stmt->type) {
1159*1f5207b7SJohn Levon 	case STMT_DECLARATION: {
1160*1f5207b7SJohn Levon 		struct symbol *sym;
1161*1f5207b7SJohn Levon 		FOR_EACH_PTR(stmt->declaration, sym) {
1162*1f5207b7SJohn Levon 			expand_symbol(sym);
1163*1f5207b7SJohn Levon 		} END_FOR_EACH_PTR(sym);
1164*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
1165*1f5207b7SJohn Levon 	}
1166*1f5207b7SJohn Levon 
1167*1f5207b7SJohn Levon 	case STMT_RETURN:
1168*1f5207b7SJohn Levon 		expand_return_expression(stmt);
1169*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
1170*1f5207b7SJohn Levon 
1171*1f5207b7SJohn Levon 	case STMT_EXPRESSION:
1172*1f5207b7SJohn Levon 		return expand_expression(stmt->expression);
1173*1f5207b7SJohn Levon 
1174*1f5207b7SJohn Levon 	case STMT_COMPOUND:
1175*1f5207b7SJohn Levon 		return expand_compound(stmt);
1176*1f5207b7SJohn Levon 
1177*1f5207b7SJohn Levon 	case STMT_IF:
1178*1f5207b7SJohn Levon 		return expand_if_statement(stmt);
1179*1f5207b7SJohn Levon 
1180*1f5207b7SJohn Levon 	case STMT_ITERATOR:
1181*1f5207b7SJohn Levon 		expand_expression(stmt->iterator_pre_condition);
1182*1f5207b7SJohn Levon 		expand_expression(stmt->iterator_post_condition);
1183*1f5207b7SJohn Levon 		expand_statement(stmt->iterator_pre_statement);
1184*1f5207b7SJohn Levon 		expand_statement(stmt->iterator_statement);
1185*1f5207b7SJohn Levon 		expand_statement(stmt->iterator_post_statement);
1186*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
1187*1f5207b7SJohn Levon 
1188*1f5207b7SJohn Levon 	case STMT_SWITCH:
1189*1f5207b7SJohn Levon 		expand_expression(stmt->switch_expression);
1190*1f5207b7SJohn Levon 		expand_statement(stmt->switch_statement);
1191*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
1192*1f5207b7SJohn Levon 
1193*1f5207b7SJohn Levon 	case STMT_CASE:
1194*1f5207b7SJohn Levon 		expand_const_expression(stmt->case_expression, "case statement");
1195*1f5207b7SJohn Levon 		expand_const_expression(stmt->case_to, "case statement");
1196*1f5207b7SJohn Levon 		expand_statement(stmt->case_statement);
1197*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
1198*1f5207b7SJohn Levon 
1199*1f5207b7SJohn Levon 	case STMT_LABEL:
1200*1f5207b7SJohn Levon 		expand_statement(stmt->label_statement);
1201*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
1202*1f5207b7SJohn Levon 
1203*1f5207b7SJohn Levon 	case STMT_GOTO:
1204*1f5207b7SJohn Levon 		expand_expression(stmt->goto_expression);
1205*1f5207b7SJohn Levon 		return SIDE_EFFECTS;
1206*1f5207b7SJohn Levon 
1207*1f5207b7SJohn Levon 	case STMT_NONE:
1208*1f5207b7SJohn Levon 		break;
1209*1f5207b7SJohn Levon 	case STMT_ASM:
1210*1f5207b7SJohn Levon 		/* FIXME! Do the asm parameter evaluation! */
1211*1f5207b7SJohn Levon 		break;
1212*1f5207b7SJohn Levon 	case STMT_CONTEXT:
1213*1f5207b7SJohn Levon 		expand_expression(stmt->expression);
1214*1f5207b7SJohn Levon 		break;
1215*1f5207b7SJohn Levon 	case STMT_RANGE:
1216*1f5207b7SJohn Levon 		expand_expression(stmt->range_expression);
1217*1f5207b7SJohn Levon 		expand_expression(stmt->range_low);
1218*1f5207b7SJohn Levon 		expand_expression(stmt->range_high);
1219*1f5207b7SJohn Levon 		break;
1220*1f5207b7SJohn Levon 	}
1221*1f5207b7SJohn Levon 	return SIDE_EFFECTS;
1222*1f5207b7SJohn Levon }
1223*1f5207b7SJohn Levon 
1224*1f5207b7SJohn Levon static inline int bad_integer_constant_expression(struct expression *expr)
1225*1f5207b7SJohn Levon {
1226*1f5207b7SJohn Levon 	if (!(expr->flags & CEF_ICE))
1227*1f5207b7SJohn Levon 		return 1;
1228*1f5207b7SJohn Levon 	if (expr->taint & Taint_comma)
1229*1f5207b7SJohn Levon 		return 1;
1230*1f5207b7SJohn Levon 	return 0;
1231*1f5207b7SJohn Levon }
1232*1f5207b7SJohn Levon 
1233*1f5207b7SJohn Levon static long long __get_expression_value(struct expression *expr, int strict)
1234*1f5207b7SJohn Levon {
1235*1f5207b7SJohn Levon 	long long value, mask;
1236*1f5207b7SJohn Levon 	struct symbol *ctype;
1237*1f5207b7SJohn Levon 
1238*1f5207b7SJohn Levon 	if (!expr)
1239*1f5207b7SJohn Levon 		return 0;
1240*1f5207b7SJohn Levon 	ctype = evaluate_expression(expr);
1241*1f5207b7SJohn Levon 	if (!ctype) {
1242*1f5207b7SJohn Levon 		expression_error(expr, "bad constant expression type");
1243*1f5207b7SJohn Levon 		return 0;
1244*1f5207b7SJohn Levon 	}
1245*1f5207b7SJohn Levon 	expand_expression(expr);
1246*1f5207b7SJohn Levon 	if (expr->type != EXPR_VALUE) {
1247*1f5207b7SJohn Levon 		if (strict != 2)
1248*1f5207b7SJohn Levon 			expression_error(expr, "bad constant expression");
1249*1f5207b7SJohn Levon 		return 0;
1250*1f5207b7SJohn Levon 	}
1251*1f5207b7SJohn Levon 	if ((strict == 1) && bad_integer_constant_expression(expr)) {
1252*1f5207b7SJohn Levon 		expression_error(expr, "bad integer constant expression");
1253*1f5207b7SJohn Levon 		return 0;
1254*1f5207b7SJohn Levon 	}
1255*1f5207b7SJohn Levon 
1256*1f5207b7SJohn Levon 	value = expr->value;
1257*1f5207b7SJohn Levon 	mask = 1ULL << (ctype->bit_size-1);
1258*1f5207b7SJohn Levon 
1259*1f5207b7SJohn Levon 	if (value & mask) {
1260*1f5207b7SJohn Levon 		while (ctype->type != SYM_BASETYPE)
1261*1f5207b7SJohn Levon 			ctype = ctype->ctype.base_type;
1262*1f5207b7SJohn Levon 		if (!(ctype->ctype.modifiers & MOD_UNSIGNED))
1263*1f5207b7SJohn Levon 			value = value | mask | ~(mask-1);
1264*1f5207b7SJohn Levon 	}
1265*1f5207b7SJohn Levon 	return value;
1266*1f5207b7SJohn Levon }
1267*1f5207b7SJohn Levon 
1268*1f5207b7SJohn Levon long long get_expression_value(struct expression *expr)
1269*1f5207b7SJohn Levon {
1270*1f5207b7SJohn Levon 	return __get_expression_value(expr, 0);
1271*1f5207b7SJohn Levon }
1272*1f5207b7SJohn Levon 
1273*1f5207b7SJohn Levon long long const_expression_value(struct expression *expr)
1274*1f5207b7SJohn Levon {
1275*1f5207b7SJohn Levon 	return __get_expression_value(expr, 1);
1276*1f5207b7SJohn Levon }
1277*1f5207b7SJohn Levon 
1278*1f5207b7SJohn Levon long long get_expression_value_silent(struct expression *expr)
1279*1f5207b7SJohn Levon {
1280*1f5207b7SJohn Levon 
1281*1f5207b7SJohn Levon 	return __get_expression_value(expr, 2);
1282*1f5207b7SJohn Levon }
1283*1f5207b7SJohn Levon 
1284*1f5207b7SJohn Levon int expr_truth_value(struct expression *expr)
1285*1f5207b7SJohn Levon {
1286*1f5207b7SJohn Levon 	const int saved = conservative;
1287*1f5207b7SJohn Levon 	struct symbol *ctype;
1288*1f5207b7SJohn Levon 
1289*1f5207b7SJohn Levon 	if (!expr)
1290*1f5207b7SJohn Levon 		return 0;
1291*1f5207b7SJohn Levon 
1292*1f5207b7SJohn Levon 	ctype = evaluate_expression(expr);
1293*1f5207b7SJohn Levon 	if (!ctype)
1294*1f5207b7SJohn Levon 		return -1;
1295*1f5207b7SJohn Levon 
1296*1f5207b7SJohn Levon 	conservative = 1;
1297*1f5207b7SJohn Levon 	expand_expression(expr);
1298*1f5207b7SJohn Levon 	conservative = saved;
1299*1f5207b7SJohn Levon 
1300*1f5207b7SJohn Levon redo:
1301*1f5207b7SJohn Levon 	switch (expr->type) {
1302*1f5207b7SJohn Levon 	case EXPR_COMMA:
1303*1f5207b7SJohn Levon 		expr = expr->right;
1304*1f5207b7SJohn Levon 		goto redo;
1305*1f5207b7SJohn Levon 	case EXPR_VALUE:
1306*1f5207b7SJohn Levon 		return expr->value != 0;
1307*1f5207b7SJohn Levon 	case EXPR_FVALUE:
1308*1f5207b7SJohn Levon 		return expr->fvalue != 0;
1309*1f5207b7SJohn Levon 	default:
1310*1f5207b7SJohn Levon 		return -1;
1311*1f5207b7SJohn Levon 	}
1312*1f5207b7SJohn Levon }
1313*1f5207b7SJohn Levon 
1314*1f5207b7SJohn Levon int is_zero_constant(struct expression *expr)
1315*1f5207b7SJohn Levon {
1316*1f5207b7SJohn Levon 	const int saved = conservative;
1317*1f5207b7SJohn Levon 	conservative = 1;
1318*1f5207b7SJohn Levon 	expand_expression(expr);
1319*1f5207b7SJohn Levon 	conservative = saved;
1320*1f5207b7SJohn Levon 	return expr->type == EXPR_VALUE && !expr->value;
1321*1f5207b7SJohn Levon }
1322