static void stmt_walk2(stmt *base, stmt_walk_enter enter, stmt_walk_leave leave, void *data, int *stop) { int descend = 1; enter(base, stop, &descend, data); if(*stop) return; #define WALK_IF(sub) if(sub){ stmt_walk2(sub, enter, leave, data, stop); if(*stop) return; } if(!descend) goto fin; WALK_IF(base->lhs); WALK_IF(base->rhs); if(stmt_kind(base, code) && base->bits.code.stmts){ int i; for(i = 0; base->bits.code.stmts[i]; i++){ stmt_walk2(base->bits.code.stmts[i], enter, leave, data, stop); if(*stop) break; } } fin: if(leave) leave(base, data); }
/* checks case duplicates, not default */ static void fold_switch_dups(stmt *sw) { typedef int (*qsort_f)(const void *, const void *); struct { numeric start, end; stmt *cse; } *vals; size_t n = dynarray_count(sw->bits.switch_.cases); size_t i = 0; stmt **titer; if(n == 0) return; vals = malloc(n * sizeof *vals); /* gather all switch values */ ITER_SWITCH(sw, titer){ stmt *cse = *titer; vals[i].cse = cse; const_fold_integral(cse->expr, &vals[i].start); if(stmt_kind(cse, case_range)) const_fold_integral(cse->expr2, &vals[i].end); else memcpy(&vals[i].end, &vals[i].start, sizeof vals[i].end); i++; }
void print_stmt(stmt *t) { idt_printf("statement: %s\n", t->f_str()); if(t->flow){ gen_str_indent++; print_stmt_flow(t->flow); gen_str_indent--; } PRINT_IF(t, expr, print_expr); PRINT_IF(t, lhs, print_stmt); PRINT_IF(t, rhs, print_stmt); PRINT_IF(t, rhs, print_stmt); if(stmt_kind(t, code)){ idt_printf("structs/unions/enums:\n"); gen_str_indent++; print_sues_static_asserts(t->symtab); gen_str_indent--; if(t->symtab){ decl **iter; idt_printf("stack space %d\n", t->symtab->auto_total_size); idt_printf("decls:\n"); for(iter = t->symtab->decls; iter && *iter; iter++){ decl *d = *iter; gen_str_indent++; print_decl(d, PDECL_INDENT | PDECL_NEWLINE | PDECL_SYM_OFFSET | PDECL_ATTR | PDECL_PINIT); gen_str_indent--; } } if(t->bits.code.stmts){ stmt **iter; idt_printf("code:\n"); for(iter = t->bits.code.stmts; *iter; iter++){ gen_str_indent++; print_stmt(*iter); gen_str_indent--; } } } }
const out_val *gen_expr_stmt(const expr *e, out_ctx *octx) { size_t n; const out_val *ret; struct out_dbg_lbl *pushed_lbls[2]; gen_stmt_code_m1(e->code, 1, pushed_lbls, octx); n = dynarray_count(e->code->bits.code.stmts); if(n > 0 && stmt_kind(e->code->bits.code.stmts[n-1], expr)) ret = gen_expr(e->code->bits.code.stmts[n - 1]->expr, octx); else ret = out_new_noop(octx); /* this is skipped by gen_stmt_code_m1( ... 1, ... ) */ gen_stmt_code_m1_finish(e->code, pushed_lbls, octx); return ret; }
void fold_expr_stmt(expr *e, symtable *stab) { stmt *last_stmt; int last; (void)stab; last = dynarray_count(e->code->bits.code.stmts); if(last){ last_stmt = e->code->bits.code.stmts[last - 1]; last_stmt->freestanding = 1; /* allow the final to be freestanding */ last_stmt->expr_no_pop = 1; } fold_stmt(e->code); /* symtab should've been set by parse */ if(last && stmt_kind(last_stmt, expr)){ expr *last_expr = last_stmt->expr; e->tree_type = last_expr->tree_type; if(fold_check_expr(e, FOLD_CHK_ALLOW_VOID, "({ ... }) statement")) { return; } switch(expr_is_lval(last_expr)){ case LVALUE_NO: break; case LVALUE_STRUCT: case LVALUE_USER_ASSIGNABLE: e->f_islval = expr_is_lval_struct; } }else{ e->tree_type = type_nav_btype(cc1_type_nav, type_void); } e->freestanding = 1; /* ({ ... }) on its own is freestanding */ }