1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Sparse - a semantic source parser.
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * Copyright (C) 2003 Transmeta Corp.
5f08c3bdfSopenharmony_ci *               2003-2004 Linus Torvalds
6f08c3bdfSopenharmony_ci *
7f08c3bdfSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
8f08c3bdfSopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
9f08c3bdfSopenharmony_ci * in the Software without restriction, including without limitation the rights
10f08c3bdfSopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11f08c3bdfSopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
12f08c3bdfSopenharmony_ci * furnished to do so, subject to the following conditions:
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * The above copyright notice and this permission notice shall be included in
15f08c3bdfSopenharmony_ci * all copies or substantial portions of the Software.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f08c3bdfSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f08c3bdfSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20f08c3bdfSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f08c3bdfSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22f08c3bdfSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23f08c3bdfSopenharmony_ci * THE SOFTWARE.
24f08c3bdfSopenharmony_ci */
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_ci#include <stdlib.h>
27f08c3bdfSopenharmony_ci#include <stdio.h>
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci#include "lib.h"
30f08c3bdfSopenharmony_ci#include "allocate.h"
31f08c3bdfSopenharmony_ci#include "token.h"
32f08c3bdfSopenharmony_ci#include "parse.h"
33f08c3bdfSopenharmony_ci#include "symbol.h"
34f08c3bdfSopenharmony_ci#include "expression.h"
35f08c3bdfSopenharmony_ci#include "evaluate.h"
36f08c3bdfSopenharmony_ci
37f08c3bdfSopenharmony_cistatic void copy_statement(struct statement *src, struct statement *dst);
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_cistatic struct expression * dup_expression(struct expression *expr)
40f08c3bdfSopenharmony_ci{
41f08c3bdfSopenharmony_ci	struct expression *dup = alloc_expression(expr->pos, expr->type);
42f08c3bdfSopenharmony_ci	*dup = *expr;
43f08c3bdfSopenharmony_ci	return dup;
44f08c3bdfSopenharmony_ci}
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cistatic struct statement * dup_statement(struct statement *stmt)
47f08c3bdfSopenharmony_ci{
48f08c3bdfSopenharmony_ci	struct statement *dup = alloc_statement(stmt->pos, stmt->type);
49f08c3bdfSopenharmony_ci	*dup = *stmt;
50f08c3bdfSopenharmony_ci	return dup;
51f08c3bdfSopenharmony_ci}
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_cistatic struct symbol *copy_symbol(struct position pos, struct symbol *sym)
54f08c3bdfSopenharmony_ci{
55f08c3bdfSopenharmony_ci	if (!sym)
56f08c3bdfSopenharmony_ci		return sym;
57f08c3bdfSopenharmony_ci	if (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN | MOD_TOPLEVEL | MOD_INLINE))
58f08c3bdfSopenharmony_ci		return sym;
59f08c3bdfSopenharmony_ci	if (!sym->replace) {
60f08c3bdfSopenharmony_ci		warning(pos, "unreplaced symbol '%s'", show_ident(sym->ident));
61f08c3bdfSopenharmony_ci		return sym;
62f08c3bdfSopenharmony_ci	}
63f08c3bdfSopenharmony_ci	return sym->replace;
64f08c3bdfSopenharmony_ci}
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_cistatic struct symbol_list *copy_symbol_list(struct symbol_list *src)
67f08c3bdfSopenharmony_ci{
68f08c3bdfSopenharmony_ci	struct symbol_list *dst = NULL;
69f08c3bdfSopenharmony_ci	struct symbol *sym;
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_ci	FOR_EACH_PTR(src, sym) {
72f08c3bdfSopenharmony_ci		struct symbol *newsym = copy_symbol(sym->pos, sym);
73f08c3bdfSopenharmony_ci		add_symbol(&dst, newsym);
74f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(sym);
75f08c3bdfSopenharmony_ci	return dst;
76f08c3bdfSopenharmony_ci}
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_cistatic struct expression * copy_expression(struct expression *expr)
79f08c3bdfSopenharmony_ci{
80f08c3bdfSopenharmony_ci	if (!expr)
81f08c3bdfSopenharmony_ci		return NULL;
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci	switch (expr->type) {
84f08c3bdfSopenharmony_ci	/*
85f08c3bdfSopenharmony_ci	 * EXPR_SYMBOL is the interesting case, we may need to replace the
86f08c3bdfSopenharmony_ci	 * symbol to the new copy.
87f08c3bdfSopenharmony_ci	 */
88f08c3bdfSopenharmony_ci	case EXPR_SYMBOL: {
89f08c3bdfSopenharmony_ci		struct symbol *sym = copy_symbol(expr->pos, expr->symbol);
90f08c3bdfSopenharmony_ci		if (sym == expr->symbol)
91f08c3bdfSopenharmony_ci			break;
92f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
93f08c3bdfSopenharmony_ci		expr->symbol = sym;
94f08c3bdfSopenharmony_ci		break;
95f08c3bdfSopenharmony_ci	}
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	/* Atomics, never change, just return the expression directly */
98f08c3bdfSopenharmony_ci	case EXPR_VALUE:
99f08c3bdfSopenharmony_ci	case EXPR_STRING:
100f08c3bdfSopenharmony_ci	case EXPR_FVALUE:
101f08c3bdfSopenharmony_ci	case EXPR_TYPE:
102f08c3bdfSopenharmony_ci		break;
103f08c3bdfSopenharmony_ci
104f08c3bdfSopenharmony_ci	/* Unops: check if the subexpression is unique */
105f08c3bdfSopenharmony_ci	case EXPR_PREOP:
106f08c3bdfSopenharmony_ci	case EXPR_POSTOP: {
107f08c3bdfSopenharmony_ci		struct expression *unop = copy_expression(expr->unop);
108f08c3bdfSopenharmony_ci		if (expr->unop == unop)
109f08c3bdfSopenharmony_ci			break;
110f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
111f08c3bdfSopenharmony_ci		expr->unop = unop;
112f08c3bdfSopenharmony_ci		break;
113f08c3bdfSopenharmony_ci	}
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_ci	case EXPR_SLICE: {
116f08c3bdfSopenharmony_ci		struct expression *base = copy_expression(expr->base);
117f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
118f08c3bdfSopenharmony_ci		expr->base = base;
119f08c3bdfSopenharmony_ci		break;
120f08c3bdfSopenharmony_ci	}
121f08c3bdfSopenharmony_ci
122f08c3bdfSopenharmony_ci	/* Binops: copy left/right expressions */
123f08c3bdfSopenharmony_ci	case EXPR_BINOP:
124f08c3bdfSopenharmony_ci	case EXPR_COMMA:
125f08c3bdfSopenharmony_ci	case EXPR_COMPARE:
126f08c3bdfSopenharmony_ci	case EXPR_LOGICAL: {
127f08c3bdfSopenharmony_ci		struct expression *left = copy_expression(expr->left);
128f08c3bdfSopenharmony_ci		struct expression *right = copy_expression(expr->right);
129f08c3bdfSopenharmony_ci		if (left == expr->left && right == expr->right)
130f08c3bdfSopenharmony_ci			break;
131f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
132f08c3bdfSopenharmony_ci		expr->left = left;
133f08c3bdfSopenharmony_ci		expr->right = right;
134f08c3bdfSopenharmony_ci		break;
135f08c3bdfSopenharmony_ci	}
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_ci	case EXPR_ASSIGNMENT: {
138f08c3bdfSopenharmony_ci		struct expression *left = copy_expression(expr->left);
139f08c3bdfSopenharmony_ci		struct expression *right = copy_expression(expr->right);
140f08c3bdfSopenharmony_ci		if (expr->op == '=' && left == expr->left && right == expr->right)
141f08c3bdfSopenharmony_ci			break;
142f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
143f08c3bdfSopenharmony_ci		expr->left = left;
144f08c3bdfSopenharmony_ci		expr->right = right;
145f08c3bdfSopenharmony_ci		break;
146f08c3bdfSopenharmony_ci	}
147f08c3bdfSopenharmony_ci
148f08c3bdfSopenharmony_ci	/* Dereference */
149f08c3bdfSopenharmony_ci	case EXPR_DEREF: {
150f08c3bdfSopenharmony_ci		struct expression *deref = copy_expression(expr->deref);
151f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
152f08c3bdfSopenharmony_ci		expr->deref = deref;
153f08c3bdfSopenharmony_ci		break;
154f08c3bdfSopenharmony_ci	}
155f08c3bdfSopenharmony_ci
156f08c3bdfSopenharmony_ci	/* Cast/sizeof/__alignof__ */
157f08c3bdfSopenharmony_ci	case EXPR_CAST:
158f08c3bdfSopenharmony_ci		if (expr->cast_expression->type == EXPR_INITIALIZER) {
159f08c3bdfSopenharmony_ci			struct expression *cast = expr->cast_expression;
160f08c3bdfSopenharmony_ci			struct symbol *sym = expr->cast_type;
161f08c3bdfSopenharmony_ci			expr = dup_expression(expr);
162f08c3bdfSopenharmony_ci			expr->cast_expression = copy_expression(cast);
163f08c3bdfSopenharmony_ci			expr->cast_type = alloc_symbol(sym->pos, sym->type);
164f08c3bdfSopenharmony_ci			*expr->cast_type = *sym;
165f08c3bdfSopenharmony_ci			break;
166f08c3bdfSopenharmony_ci		}
167f08c3bdfSopenharmony_ci	case EXPR_FORCE_CAST:
168f08c3bdfSopenharmony_ci	case EXPR_IMPLIED_CAST:
169f08c3bdfSopenharmony_ci	case EXPR_SIZEOF:
170f08c3bdfSopenharmony_ci	case EXPR_PTRSIZEOF:
171f08c3bdfSopenharmony_ci	case EXPR_ALIGNOF: {
172f08c3bdfSopenharmony_ci		struct expression *cast = copy_expression(expr->cast_expression);
173f08c3bdfSopenharmony_ci		if (cast == expr->cast_expression)
174f08c3bdfSopenharmony_ci			break;
175f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
176f08c3bdfSopenharmony_ci		expr->cast_expression = cast;
177f08c3bdfSopenharmony_ci		break;
178f08c3bdfSopenharmony_ci	}
179f08c3bdfSopenharmony_ci
180f08c3bdfSopenharmony_ci	/* Conditional expression */
181f08c3bdfSopenharmony_ci	case EXPR_SELECT:
182f08c3bdfSopenharmony_ci	case EXPR_CONDITIONAL: {
183f08c3bdfSopenharmony_ci		struct expression *cond = copy_expression(expr->conditional);
184f08c3bdfSopenharmony_ci		struct expression *valt = copy_expression(expr->cond_true);
185f08c3bdfSopenharmony_ci		struct expression *valf = copy_expression(expr->cond_false);
186f08c3bdfSopenharmony_ci		if (cond == expr->conditional && valt == expr->cond_true && valf == expr->cond_false)
187f08c3bdfSopenharmony_ci			break;
188f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
189f08c3bdfSopenharmony_ci		expr->conditional = cond;
190f08c3bdfSopenharmony_ci		expr->cond_true = valt;
191f08c3bdfSopenharmony_ci		expr->cond_false = valf;
192f08c3bdfSopenharmony_ci		break;
193f08c3bdfSopenharmony_ci	}
194f08c3bdfSopenharmony_ci
195f08c3bdfSopenharmony_ci	/* Statement expression */
196f08c3bdfSopenharmony_ci	case EXPR_STATEMENT: {
197f08c3bdfSopenharmony_ci		struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
198f08c3bdfSopenharmony_ci		copy_statement(expr->statement, stmt);
199f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
200f08c3bdfSopenharmony_ci		expr->statement = stmt;
201f08c3bdfSopenharmony_ci		break;
202f08c3bdfSopenharmony_ci	}
203f08c3bdfSopenharmony_ci
204f08c3bdfSopenharmony_ci	/* Call expression */
205f08c3bdfSopenharmony_ci	case EXPR_CALL: {
206f08c3bdfSopenharmony_ci		struct expression *fn = copy_expression(expr->fn);
207f08c3bdfSopenharmony_ci		struct expression_list *list = expr->args;
208f08c3bdfSopenharmony_ci		struct expression *arg;
209f08c3bdfSopenharmony_ci
210f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
211f08c3bdfSopenharmony_ci		expr->fn = fn;
212f08c3bdfSopenharmony_ci		expr->args = NULL;
213f08c3bdfSopenharmony_ci		FOR_EACH_PTR(list, arg) {
214f08c3bdfSopenharmony_ci			add_expression(&expr->args, copy_expression(arg));
215f08c3bdfSopenharmony_ci		} END_FOR_EACH_PTR(arg);
216f08c3bdfSopenharmony_ci		break;
217f08c3bdfSopenharmony_ci	}
218f08c3bdfSopenharmony_ci
219f08c3bdfSopenharmony_ci	/* Initializer list statement */
220f08c3bdfSopenharmony_ci	case EXPR_INITIALIZER: {
221f08c3bdfSopenharmony_ci		struct expression_list *list = expr->expr_list;
222f08c3bdfSopenharmony_ci		struct expression *entry;
223f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
224f08c3bdfSopenharmony_ci		expr->expr_list = NULL;
225f08c3bdfSopenharmony_ci		FOR_EACH_PTR(list, entry) {
226f08c3bdfSopenharmony_ci			add_expression(&expr->expr_list, copy_expression(entry));
227f08c3bdfSopenharmony_ci		} END_FOR_EACH_PTR(entry);
228f08c3bdfSopenharmony_ci		break;
229f08c3bdfSopenharmony_ci	}
230f08c3bdfSopenharmony_ci
231f08c3bdfSopenharmony_ci	/* Label in inline function - hmm. */
232f08c3bdfSopenharmony_ci	case EXPR_LABEL: {
233f08c3bdfSopenharmony_ci		struct symbol *label_symbol = copy_symbol(expr->pos, expr->label_symbol);
234f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
235f08c3bdfSopenharmony_ci		expr->label_symbol = label_symbol;
236f08c3bdfSopenharmony_ci		break;
237f08c3bdfSopenharmony_ci	}
238f08c3bdfSopenharmony_ci
239f08c3bdfSopenharmony_ci	case EXPR_INDEX: {
240f08c3bdfSopenharmony_ci		struct expression *sub_expr = copy_expression(expr->idx_expression);
241f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
242f08c3bdfSopenharmony_ci		expr->idx_expression = sub_expr;
243f08c3bdfSopenharmony_ci		break;
244f08c3bdfSopenharmony_ci	}
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ci	case EXPR_IDENTIFIER: {
247f08c3bdfSopenharmony_ci		struct expression *sub_expr = copy_expression(expr->ident_expression);
248f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
249f08c3bdfSopenharmony_ci		expr->ident_expression = sub_expr;
250f08c3bdfSopenharmony_ci		break;
251f08c3bdfSopenharmony_ci	}
252f08c3bdfSopenharmony_ci
253f08c3bdfSopenharmony_ci	/* Position in initializer.. */
254f08c3bdfSopenharmony_ci	case EXPR_POS: {
255f08c3bdfSopenharmony_ci		struct expression *val = copy_expression(expr->init_expr);
256f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
257f08c3bdfSopenharmony_ci		expr->init_expr = val;
258f08c3bdfSopenharmony_ci		break;
259f08c3bdfSopenharmony_ci	}
260f08c3bdfSopenharmony_ci	case EXPR_OFFSETOF: {
261f08c3bdfSopenharmony_ci		struct expression *val = copy_expression(expr->down);
262f08c3bdfSopenharmony_ci		if (expr->op == '.') {
263f08c3bdfSopenharmony_ci			if (expr->down != val) {
264f08c3bdfSopenharmony_ci				expr = dup_expression(expr);
265f08c3bdfSopenharmony_ci				expr->down = val;
266f08c3bdfSopenharmony_ci			}
267f08c3bdfSopenharmony_ci		} else {
268f08c3bdfSopenharmony_ci			struct expression *idx = copy_expression(expr->index);
269f08c3bdfSopenharmony_ci			if (expr->down != val || expr->index != idx) {
270f08c3bdfSopenharmony_ci				expr = dup_expression(expr);
271f08c3bdfSopenharmony_ci				expr->down = val;
272f08c3bdfSopenharmony_ci				expr->index = idx;
273f08c3bdfSopenharmony_ci			}
274f08c3bdfSopenharmony_ci		}
275f08c3bdfSopenharmony_ci		break;
276f08c3bdfSopenharmony_ci	}
277f08c3bdfSopenharmony_ci	case EXPR_GENERIC:
278f08c3bdfSopenharmony_ci		expr = dup_expression(expr);
279f08c3bdfSopenharmony_ci		expr->control = copy_expression(expr->control);
280f08c3bdfSopenharmony_ci		if (!evaluate_expression(expr))
281f08c3bdfSopenharmony_ci			return NULL;
282f08c3bdfSopenharmony_ci		expr = copy_expression(expr);
283f08c3bdfSopenharmony_ci		break;
284f08c3bdfSopenharmony_ci
285f08c3bdfSopenharmony_ci	default:
286f08c3bdfSopenharmony_ci		warning(expr->pos, "trying to copy expression type %d", expr->type);
287f08c3bdfSopenharmony_ci	}
288f08c3bdfSopenharmony_ci	return expr;
289f08c3bdfSopenharmony_ci}
290f08c3bdfSopenharmony_ci
291f08c3bdfSopenharmony_cistatic struct asm_operand_list *copy_asm_operands(struct asm_operand_list *in)
292f08c3bdfSopenharmony_ci{
293f08c3bdfSopenharmony_ci	struct asm_operand_list *out = NULL;
294f08c3bdfSopenharmony_ci	struct asm_operand *old;
295f08c3bdfSopenharmony_ci
296f08c3bdfSopenharmony_ci	FOR_EACH_PTR(in, old) {
297f08c3bdfSopenharmony_ci		struct asm_operand *new = __alloc_asm_operand(0);
298f08c3bdfSopenharmony_ci		new->name = old->name;
299f08c3bdfSopenharmony_ci		new->constraint = copy_expression(old->constraint);
300f08c3bdfSopenharmony_ci		new->expr = copy_expression(old->expr);
301f08c3bdfSopenharmony_ci		add_ptr_list(&out, new);
302f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(old);
303f08c3bdfSopenharmony_ci	return out;
304f08c3bdfSopenharmony_ci}
305f08c3bdfSopenharmony_ci
306f08c3bdfSopenharmony_cistatic void set_replace(struct symbol *old, struct symbol *new)
307f08c3bdfSopenharmony_ci{
308f08c3bdfSopenharmony_ci	new->replace = old;
309f08c3bdfSopenharmony_ci	old->replace = new;
310f08c3bdfSopenharmony_ci}
311f08c3bdfSopenharmony_ci
312f08c3bdfSopenharmony_cistatic void unset_replace(struct symbol *sym)
313f08c3bdfSopenharmony_ci{
314f08c3bdfSopenharmony_ci	struct symbol *r = sym->replace;
315f08c3bdfSopenharmony_ci	if (!r) {
316f08c3bdfSopenharmony_ci		warning(sym->pos, "symbol '%s' not replaced?", show_ident(sym->ident));
317f08c3bdfSopenharmony_ci		return;
318f08c3bdfSopenharmony_ci	}
319f08c3bdfSopenharmony_ci	r->replace = NULL;
320f08c3bdfSopenharmony_ci	sym->replace = NULL;
321f08c3bdfSopenharmony_ci}
322f08c3bdfSopenharmony_ci
323f08c3bdfSopenharmony_cistatic void unset_replace_list(struct symbol_list *list)
324f08c3bdfSopenharmony_ci{
325f08c3bdfSopenharmony_ci	struct symbol *sym;
326f08c3bdfSopenharmony_ci	FOR_EACH_PTR(list, sym) {
327f08c3bdfSopenharmony_ci		unset_replace(sym);
328f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(sym);
329f08c3bdfSopenharmony_ci}
330f08c3bdfSopenharmony_ci
331f08c3bdfSopenharmony_cistatic struct statement *copy_one_statement(struct statement *stmt)
332f08c3bdfSopenharmony_ci{
333f08c3bdfSopenharmony_ci	if (!stmt)
334f08c3bdfSopenharmony_ci		return NULL;
335f08c3bdfSopenharmony_ci	switch(stmt->type) {
336f08c3bdfSopenharmony_ci	case STMT_NONE:
337f08c3bdfSopenharmony_ci		break;
338f08c3bdfSopenharmony_ci	case STMT_DECLARATION: {
339f08c3bdfSopenharmony_ci		struct symbol *sym;
340f08c3bdfSopenharmony_ci		struct statement *newstmt = dup_statement(stmt);
341f08c3bdfSopenharmony_ci		newstmt->declaration = NULL;
342f08c3bdfSopenharmony_ci		FOR_EACH_PTR(stmt->declaration, sym) {
343f08c3bdfSopenharmony_ci			struct symbol *newsym = copy_symbol(stmt->pos, sym);
344f08c3bdfSopenharmony_ci			if (newsym != sym)
345f08c3bdfSopenharmony_ci				newsym->initializer = copy_expression(sym->initializer);
346f08c3bdfSopenharmony_ci			add_symbol(&newstmt->declaration, newsym);
347f08c3bdfSopenharmony_ci		} END_FOR_EACH_PTR(sym);
348f08c3bdfSopenharmony_ci		stmt = newstmt;
349f08c3bdfSopenharmony_ci		break;
350f08c3bdfSopenharmony_ci	}
351f08c3bdfSopenharmony_ci	case STMT_CONTEXT:
352f08c3bdfSopenharmony_ci	case STMT_EXPRESSION: {
353f08c3bdfSopenharmony_ci		struct expression *expr = copy_expression(stmt->expression);
354f08c3bdfSopenharmony_ci		if (expr == stmt->expression)
355f08c3bdfSopenharmony_ci			break;
356f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
357f08c3bdfSopenharmony_ci		stmt->expression = expr;
358f08c3bdfSopenharmony_ci		break;
359f08c3bdfSopenharmony_ci	}
360f08c3bdfSopenharmony_ci	case STMT_RANGE: {
361f08c3bdfSopenharmony_ci		struct expression *expr = copy_expression(stmt->range_expression);
362f08c3bdfSopenharmony_ci		if (expr == stmt->expression)
363f08c3bdfSopenharmony_ci			break;
364f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
365f08c3bdfSopenharmony_ci		stmt->range_expression = expr;
366f08c3bdfSopenharmony_ci		break;
367f08c3bdfSopenharmony_ci	}
368f08c3bdfSopenharmony_ci	case STMT_COMPOUND: {
369f08c3bdfSopenharmony_ci		struct statement *new = alloc_statement(stmt->pos, STMT_COMPOUND);
370f08c3bdfSopenharmony_ci		copy_statement(stmt, new);
371f08c3bdfSopenharmony_ci		stmt = new;
372f08c3bdfSopenharmony_ci		break;
373f08c3bdfSopenharmony_ci	}
374f08c3bdfSopenharmony_ci	case STMT_IF: {
375f08c3bdfSopenharmony_ci		struct expression *cond = stmt->if_conditional;
376f08c3bdfSopenharmony_ci		struct statement *valt = stmt->if_true;
377f08c3bdfSopenharmony_ci		struct statement *valf = stmt->if_false;
378f08c3bdfSopenharmony_ci
379f08c3bdfSopenharmony_ci		cond = copy_expression(cond);
380f08c3bdfSopenharmony_ci		valt = copy_one_statement(valt);
381f08c3bdfSopenharmony_ci		valf = copy_one_statement(valf);
382f08c3bdfSopenharmony_ci		if (stmt->if_conditional == cond &&
383f08c3bdfSopenharmony_ci		    stmt->if_true == valt &&
384f08c3bdfSopenharmony_ci		    stmt->if_false == valf)
385f08c3bdfSopenharmony_ci			break;
386f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
387f08c3bdfSopenharmony_ci		stmt->if_conditional = cond;
388f08c3bdfSopenharmony_ci		stmt->if_true = valt;
389f08c3bdfSopenharmony_ci		stmt->if_false = valf;
390f08c3bdfSopenharmony_ci		break;
391f08c3bdfSopenharmony_ci	}
392f08c3bdfSopenharmony_ci	case STMT_RETURN: {
393f08c3bdfSopenharmony_ci		struct expression *retval = copy_expression(stmt->ret_value);
394f08c3bdfSopenharmony_ci		struct symbol *sym = copy_symbol(stmt->pos, stmt->ret_target);
395f08c3bdfSopenharmony_ci
396f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
397f08c3bdfSopenharmony_ci		stmt->ret_value = retval;
398f08c3bdfSopenharmony_ci		stmt->ret_target = sym;
399f08c3bdfSopenharmony_ci		break;
400f08c3bdfSopenharmony_ci	}
401f08c3bdfSopenharmony_ci	case STMT_CASE: {
402f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
403f08c3bdfSopenharmony_ci		stmt->case_label = copy_symbol(stmt->pos, stmt->case_label);
404f08c3bdfSopenharmony_ci		stmt->case_label->stmt = stmt;
405f08c3bdfSopenharmony_ci		stmt->case_expression = copy_expression(stmt->case_expression);
406f08c3bdfSopenharmony_ci		stmt->case_to = copy_expression(stmt->case_to);
407f08c3bdfSopenharmony_ci		stmt->case_statement = copy_one_statement(stmt->case_statement);
408f08c3bdfSopenharmony_ci		break;
409f08c3bdfSopenharmony_ci	}
410f08c3bdfSopenharmony_ci	case STMT_SWITCH: {
411f08c3bdfSopenharmony_ci		struct symbol *switch_break = copy_symbol(stmt->pos, stmt->switch_break);
412f08c3bdfSopenharmony_ci		struct symbol *switch_case = copy_symbol(stmt->pos, stmt->switch_case);
413f08c3bdfSopenharmony_ci		struct expression *expr = copy_expression(stmt->switch_expression);
414f08c3bdfSopenharmony_ci		struct statement *switch_stmt = copy_one_statement(stmt->switch_statement);
415f08c3bdfSopenharmony_ci
416f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
417f08c3bdfSopenharmony_ci		switch_case->symbol_list = copy_symbol_list(switch_case->symbol_list);
418f08c3bdfSopenharmony_ci		stmt->switch_break = switch_break;
419f08c3bdfSopenharmony_ci		stmt->switch_case = switch_case;
420f08c3bdfSopenharmony_ci		stmt->switch_expression = expr;
421f08c3bdfSopenharmony_ci		stmt->switch_statement = switch_stmt;
422f08c3bdfSopenharmony_ci		break;
423f08c3bdfSopenharmony_ci	}
424f08c3bdfSopenharmony_ci	case STMT_ITERATOR: {
425f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
426f08c3bdfSopenharmony_ci		stmt->iterator_break = copy_symbol(stmt->pos, stmt->iterator_break);
427f08c3bdfSopenharmony_ci		stmt->iterator_continue = copy_symbol(stmt->pos, stmt->iterator_continue);
428f08c3bdfSopenharmony_ci		stmt->iterator_syms = copy_symbol_list(stmt->iterator_syms);
429f08c3bdfSopenharmony_ci
430f08c3bdfSopenharmony_ci		stmt->iterator_pre_statement = copy_one_statement(stmt->iterator_pre_statement);
431f08c3bdfSopenharmony_ci		stmt->iterator_pre_condition = copy_expression(stmt->iterator_pre_condition);
432f08c3bdfSopenharmony_ci
433f08c3bdfSopenharmony_ci		stmt->iterator_statement = copy_one_statement(stmt->iterator_statement);
434f08c3bdfSopenharmony_ci
435f08c3bdfSopenharmony_ci		stmt->iterator_post_statement = copy_one_statement(stmt->iterator_post_statement);
436f08c3bdfSopenharmony_ci		stmt->iterator_post_condition = copy_expression(stmt->iterator_post_condition);
437f08c3bdfSopenharmony_ci		break;
438f08c3bdfSopenharmony_ci	}
439f08c3bdfSopenharmony_ci	case STMT_LABEL: {
440f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
441f08c3bdfSopenharmony_ci		stmt->label_identifier = copy_symbol(stmt->pos, stmt->label_identifier);
442f08c3bdfSopenharmony_ci		stmt->label_statement = copy_one_statement(stmt->label_statement);
443f08c3bdfSopenharmony_ci		break;
444f08c3bdfSopenharmony_ci	}
445f08c3bdfSopenharmony_ci	case STMT_GOTO: {
446f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
447f08c3bdfSopenharmony_ci		stmt->goto_label = copy_symbol(stmt->pos, stmt->goto_label);
448f08c3bdfSopenharmony_ci		stmt->goto_expression = copy_expression(stmt->goto_expression);
449f08c3bdfSopenharmony_ci		stmt->target_list = copy_symbol_list(stmt->target_list);
450f08c3bdfSopenharmony_ci		break;
451f08c3bdfSopenharmony_ci	}
452f08c3bdfSopenharmony_ci	case STMT_ASM: {
453f08c3bdfSopenharmony_ci		stmt = dup_statement(stmt);
454f08c3bdfSopenharmony_ci		stmt->asm_inputs = copy_asm_operands(stmt->asm_inputs);
455f08c3bdfSopenharmony_ci		stmt->asm_outputs = copy_asm_operands(stmt->asm_outputs);
456f08c3bdfSopenharmony_ci		/* no need to dup "clobbers", since they are all constant strings */
457f08c3bdfSopenharmony_ci		break;
458f08c3bdfSopenharmony_ci	}
459f08c3bdfSopenharmony_ci	default:
460f08c3bdfSopenharmony_ci		warning(stmt->pos, "trying to copy statement type %d", stmt->type);
461f08c3bdfSopenharmony_ci		break;
462f08c3bdfSopenharmony_ci	}
463f08c3bdfSopenharmony_ci	return stmt;
464f08c3bdfSopenharmony_ci}
465f08c3bdfSopenharmony_ci
466f08c3bdfSopenharmony_ci/*
467f08c3bdfSopenharmony_ci * Copy a statement tree from 'src' to 'dst', where both
468f08c3bdfSopenharmony_ci * source and destination are of type STMT_COMPOUND.
469f08c3bdfSopenharmony_ci *
470f08c3bdfSopenharmony_ci * We do this for the tree-level inliner.
471f08c3bdfSopenharmony_ci *
472f08c3bdfSopenharmony_ci * This doesn't do the symbol replacement right: it's not
473f08c3bdfSopenharmony_ci * re-entrant.
474f08c3bdfSopenharmony_ci */
475f08c3bdfSopenharmony_cistatic void copy_statement(struct statement *src, struct statement *dst)
476f08c3bdfSopenharmony_ci{
477f08c3bdfSopenharmony_ci	struct statement *stmt;
478f08c3bdfSopenharmony_ci
479f08c3bdfSopenharmony_ci	FOR_EACH_PTR(src->stmts, stmt) {
480f08c3bdfSopenharmony_ci		add_statement(&dst->stmts, copy_one_statement(stmt));
481f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(stmt);
482f08c3bdfSopenharmony_ci	dst->args = copy_one_statement(src->args);
483f08c3bdfSopenharmony_ci	dst->ret = copy_symbol(src->pos, src->ret);
484f08c3bdfSopenharmony_ci	dst->inline_fn = src->inline_fn;
485f08c3bdfSopenharmony_ci}
486f08c3bdfSopenharmony_ci
487f08c3bdfSopenharmony_cistatic struct symbol *create_copy_symbol(struct symbol *orig)
488f08c3bdfSopenharmony_ci{
489f08c3bdfSopenharmony_ci	struct symbol *sym = orig;
490f08c3bdfSopenharmony_ci	if (orig) {
491f08c3bdfSopenharmony_ci		sym = alloc_symbol(orig->pos, orig->type);
492f08c3bdfSopenharmony_ci		*sym = *orig;
493f08c3bdfSopenharmony_ci		sym->bb_target = NULL;
494f08c3bdfSopenharmony_ci		sym->pseudo = NULL;
495f08c3bdfSopenharmony_ci		set_replace(orig, sym);
496f08c3bdfSopenharmony_ci		orig = sym;
497f08c3bdfSopenharmony_ci	}
498f08c3bdfSopenharmony_ci	return orig;
499f08c3bdfSopenharmony_ci}
500f08c3bdfSopenharmony_ci
501f08c3bdfSopenharmony_cistatic struct symbol_list *create_symbol_list(struct symbol_list *src)
502f08c3bdfSopenharmony_ci{
503f08c3bdfSopenharmony_ci	struct symbol_list *dst = NULL;
504f08c3bdfSopenharmony_ci	struct symbol *sym;
505f08c3bdfSopenharmony_ci
506f08c3bdfSopenharmony_ci	FOR_EACH_PTR(src, sym) {
507f08c3bdfSopenharmony_ci		struct symbol *newsym = create_copy_symbol(sym);
508f08c3bdfSopenharmony_ci		add_symbol(&dst, newsym);
509f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(sym);
510f08c3bdfSopenharmony_ci	return dst;
511f08c3bdfSopenharmony_ci}
512f08c3bdfSopenharmony_ci
513f08c3bdfSopenharmony_ciint inline_function(struct expression *expr, struct symbol *sym)
514f08c3bdfSopenharmony_ci{
515f08c3bdfSopenharmony_ci	struct symbol_list * fn_symbol_list;
516f08c3bdfSopenharmony_ci	struct symbol *fn = sym->ctype.base_type;
517f08c3bdfSopenharmony_ci	struct expression_list *arg_list = expr->args;
518f08c3bdfSopenharmony_ci	struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
519f08c3bdfSopenharmony_ci	struct symbol_list *name_list, *arg_decl;
520f08c3bdfSopenharmony_ci	struct symbol *name;
521f08c3bdfSopenharmony_ci	struct expression *arg;
522f08c3bdfSopenharmony_ci
523f08c3bdfSopenharmony_ci	if (!fn->inline_stmt) {
524f08c3bdfSopenharmony_ci		sparse_error(fn->pos, "marked inline, but without a definition");
525f08c3bdfSopenharmony_ci		return 0;
526f08c3bdfSopenharmony_ci	}
527f08c3bdfSopenharmony_ci	if (fn->expanding)
528f08c3bdfSopenharmony_ci		return 0;
529f08c3bdfSopenharmony_ci
530f08c3bdfSopenharmony_ci	name_list = fn->arguments;
531f08c3bdfSopenharmony_ci
532f08c3bdfSopenharmony_ci	expr->type = EXPR_STATEMENT;
533f08c3bdfSopenharmony_ci	expr->statement = stmt;
534f08c3bdfSopenharmony_ci	expr->ctype = fn->ctype.base_type;
535f08c3bdfSopenharmony_ci
536f08c3bdfSopenharmony_ci	fn_symbol_list = create_symbol_list(sym->inline_symbol_list);
537f08c3bdfSopenharmony_ci
538f08c3bdfSopenharmony_ci	arg_decl = NULL;
539f08c3bdfSopenharmony_ci	PREPARE_PTR_LIST(name_list, name);
540f08c3bdfSopenharmony_ci	FOR_EACH_PTR(arg_list, arg) {
541f08c3bdfSopenharmony_ci		struct symbol *a = alloc_symbol(arg->pos, SYM_NODE);
542f08c3bdfSopenharmony_ci
543f08c3bdfSopenharmony_ci		a->ctype.base_type = arg->ctype;
544f08c3bdfSopenharmony_ci		if (name) {
545f08c3bdfSopenharmony_ci			*a = *name;
546f08c3bdfSopenharmony_ci			set_replace(name, a);
547f08c3bdfSopenharmony_ci			add_symbol(&fn_symbol_list, a);
548f08c3bdfSopenharmony_ci		}
549f08c3bdfSopenharmony_ci		a->initializer = arg;
550f08c3bdfSopenharmony_ci		add_symbol(&arg_decl, a);
551f08c3bdfSopenharmony_ci
552f08c3bdfSopenharmony_ci		NEXT_PTR_LIST(name);
553f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(arg);
554f08c3bdfSopenharmony_ci	FINISH_PTR_LIST(name);
555f08c3bdfSopenharmony_ci
556f08c3bdfSopenharmony_ci	copy_statement(fn->inline_stmt, stmt);
557f08c3bdfSopenharmony_ci
558f08c3bdfSopenharmony_ci	if (arg_decl) {
559f08c3bdfSopenharmony_ci		struct statement *decl = alloc_statement(expr->pos, STMT_DECLARATION);
560f08c3bdfSopenharmony_ci		decl->declaration = arg_decl;
561f08c3bdfSopenharmony_ci		stmt->args = decl;
562f08c3bdfSopenharmony_ci	}
563f08c3bdfSopenharmony_ci	stmt->inline_fn = sym;
564f08c3bdfSopenharmony_ci
565f08c3bdfSopenharmony_ci	unset_replace_list(fn_symbol_list);
566f08c3bdfSopenharmony_ci
567f08c3bdfSopenharmony_ci	return 1;
568f08c3bdfSopenharmony_ci}
569f08c3bdfSopenharmony_ci
570f08c3bdfSopenharmony_civoid uninline(struct symbol *sym)
571f08c3bdfSopenharmony_ci{
572f08c3bdfSopenharmony_ci	struct symbol *fn = sym->ctype.base_type;
573f08c3bdfSopenharmony_ci	struct symbol_list *arg_list = fn->arguments;
574f08c3bdfSopenharmony_ci	struct symbol *p;
575f08c3bdfSopenharmony_ci
576f08c3bdfSopenharmony_ci	sym->symbol_list = create_symbol_list(sym->inline_symbol_list);
577f08c3bdfSopenharmony_ci	FOR_EACH_PTR(arg_list, p) {
578f08c3bdfSopenharmony_ci		p->replace = p;
579f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(p);
580f08c3bdfSopenharmony_ci	fn->stmt = alloc_statement(fn->pos, STMT_COMPOUND);
581f08c3bdfSopenharmony_ci	copy_statement(fn->inline_stmt, fn->stmt);
582f08c3bdfSopenharmony_ci	unset_replace_list(sym->symbol_list);
583f08c3bdfSopenharmony_ci	unset_replace_list(arg_list);
584f08c3bdfSopenharmony_ci}
585