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