X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=f5e7a5bbbfda7a657977f3185166d176c4542cfd;hb=daf112c92de1ae63e134262745d1f1d5fd955dcb;hp=5912543808170e1408764072c0fdf2f18a82aa99;hpb=a2ece61ac4936c82a30f6399f6e7f5cf407620b5;p=cparser diff --git a/ast2firm.c b/ast2firm.c index 5912543..f5e7a5b 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -360,7 +360,7 @@ static ir_type *create_struct_type(compound_type_t *type) int offset = 0; declaration_t *entry = type->declaration->context.declarations; for( ; entry != NULL; entry = entry->next) { - if(entry->namespace != NAMESPACE_NORMAL) + if(entry->namespc != NAMESPACE_NORMAL) continue; ident *ident = new_id_from_str(entry->symbol->string); @@ -413,7 +413,7 @@ static ir_type *create_union_type(compound_type_t *type) int size = 0; declaration_t *entry = declaration->context.declarations; for( ; entry != NULL; entry = entry->next) { - if(entry->namespace != NAMESPACE_NORMAL) + if(entry->namespc != NAMESPACE_NORMAL) continue; ident *ident = new_id_from_str(entry->symbol->string); @@ -540,7 +540,6 @@ static ir_entity* get_function_entity(declaration_t *declaration) static ir_node *expression_to_firm(const expression_t *expression); -static ir_node *expression_to_modeb(const expression_t *expression); static dbg_info *get_dbg_info(const source_position_t *pos) { @@ -605,19 +604,6 @@ static ir_node *string_literal_to_firm(const string_literal_t* literal) return create_symconst(dbgi, entity); } -static ir_node *load_from_expression_addr(type_t *type, ir_node *addr, - dbg_info *dbgi) -{ - ir_mode *mode = get_ir_mode(type); - ir_node *memory = get_store(); - ir_node *load = new_d_Load(dbgi, memory, addr, mode); - ir_node *load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M); - ir_node *load_res = new_d_Proj(dbgi, load, mode, pn_Load_res); - set_store(load_mem); - - return load_res; -} - static ir_node *deref_address(type_t *const type, ir_node *const addr, dbg_info *const dbgi) { @@ -627,8 +613,15 @@ static ir_node *deref_address(type_t *const type, ir_node *const addr, case TYPE_COMPOUND_UNION: return addr; - default: - return load_from_expression_addr(type, addr, dbgi); + default: { + ir_mode *const mode = get_ir_mode(type); + ir_node *const memory = get_store(); + ir_node *const load = new_d_Load(dbgi, memory, addr, mode); + ir_node *const load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M); + ir_node *const load_res = new_d_Proj(dbgi, load, mode, pn_Load_res); + set_store(load_mem); + return load_res; + } } } @@ -708,8 +701,15 @@ static ir_node *call_expression_to_firm(const call_expression_t *call) expression_t *function = call->function; ir_node *callee = expression_to_firm(function); - assert(function->datatype->type == TYPE_FUNCTION); - function_type_t *function_type = (function_type_t*) function->datatype; + function_type_t *function_type; + if (function->datatype->type == TYPE_POINTER) { + pointer_type_t *const ptr_type = (pointer_type_t*)function->datatype; + assert(ptr_type->points_to->type == TYPE_FUNCTION); + function_type = (function_type_t*)ptr_type->points_to; + } else { + assert(function->datatype->type == TYPE_FUNCTION); + function_type = (function_type_t*)function->datatype; + } int n_parameters = 0; call_argument_t *argument = call->arguments; @@ -775,6 +775,9 @@ static ir_node *call_expression_to_firm(const call_expression_t *call) } static ir_node *expression_to_addr(const expression_t *expression); +static void create_condition_evaluation(const expression_t *expression, + ir_node *true_block, + ir_node *false_block); static void set_value_for_expression(const expression_t *expression, ir_node *value) @@ -868,7 +871,6 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); type_t *type = expression->expression.datatype; - ir_mode *mode = get_ir_mode(type); if(expression->type == UNEXPR_TAKE_ADDRESS) return expression_to_addr(expression->value); @@ -878,29 +880,31 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) switch(expression->type) { case UNEXPR_NEGATE: - return new_d_Minus(dbgi, value_node, mode); + return new_d_Minus(dbgi, value_node, get_ir_mode(type)); case UNEXPR_PLUS: return value_node; case UNEXPR_BITWISE_NEGATE: - return new_d_Not(dbgi, value_node, mode); - case UNEXPR_NOT: + return new_d_Not(dbgi, value_node, get_ir_mode(type)); + case UNEXPR_NOT: { if(get_irn_mode(value_node) != mode_b) { value_node = create_conv(dbgi, value_node, mode_b); } value_node = new_d_Not(dbgi, value_node, mode_b); + ir_mode *const mode = get_ir_mode(type); if(mode != mode_b) { value_node = create_conv(dbgi, value_node, mode); } return value_node; + } case UNEXPR_DEREFERENCE: - return load_from_expression_addr(type, value_node, dbgi); + return deref_address(type, value_node, dbgi); case UNEXPR_POSTFIX_INCREMENT: case UNEXPR_POSTFIX_DECREMENT: case UNEXPR_PREFIX_INCREMENT: case UNEXPR_PREFIX_DECREMENT: return create_incdec(expression); case UNEXPR_CAST: - return create_conv(dbgi, value_node, mode); + return create_conv(dbgi, value_node, get_ir_mode(type)); case UNEXPR_TAKE_ADDRESS: case UNEXPR_INVALID: @@ -927,48 +931,32 @@ static long get_pnc(binary_expression_type_t type) static ir_node *create_lazy_op(const binary_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); + type_t *type = expression->expression.datatype; + ir_mode *mode = get_ir_mode(type); - bool is_or = (expression->type == BINEXPR_LOGICAL_OR); - assert(is_or || expression->type == BINEXPR_LOGICAL_AND); - - ir_node *val1 = expression_to_modeb(expression->left); - ir_node *cond = new_d_Cond(dbgi, val1); - ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true); - ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false); - - ir_node *fallthrough_block = new_immBlock(); - - /* the true case */ - ir_node *calc_val2_block = new_immBlock(); - if(is_or) { - add_immBlock_pred(calc_val2_block, false_proj); - } else { - add_immBlock_pred(calc_val2_block, true_proj); - } + ir_node *cur_block = get_cur_block(); - mature_immBlock(calc_val2_block); + ir_node *one_block = new_immBlock(); + ir_node *one = new_Const(mode, get_mode_one(mode)); + ir_node *jmp_one = new_d_Jmp(dbgi); - ir_node *val2 = expression_to_modeb(expression->right); - if(get_cur_block() != NULL) { - ir_node *jmp = new_d_Jmp(dbgi); - add_immBlock_pred(fallthrough_block, jmp); - } + ir_node *zero_block = new_immBlock(); + ir_node *zero = new_Const(mode, get_mode_null(mode)); + ir_node *jmp_zero = new_d_Jmp(dbgi); - /* fallthrough */ - ir_node *constb; - if(is_or) { - constb = new_d_Const(dbgi, mode_b, get_tarval_b_true()); - add_immBlock_pred(fallthrough_block, true_proj); - } else { - constb = new_d_Const(dbgi, mode_b, get_tarval_b_false()); - add_immBlock_pred(fallthrough_block, false_proj); - } - mature_immBlock(fallthrough_block); + set_cur_block(cur_block); + create_condition_evaluation((const expression_t*) expression, + one_block, zero_block); + mature_immBlock(one_block); + mature_immBlock(zero_block); - set_cur_block(fallthrough_block); + ir_node *common_block = new_immBlock(); + add_immBlock_pred(common_block, jmp_one); + add_immBlock_pred(common_block, jmp_zero); + mature_immBlock(common_block); - ir_node *in[2] = { val2, constb }; - ir_node *val = new_d_Phi(dbgi, 2, in, mode_b); + ir_node *in[2] = { one, zero }; + ir_node *val = new_d_Phi(dbgi, 2, in, mode); return val; } @@ -983,8 +971,8 @@ static ir_node *create_arithmetic_binop(const binary_expression_t *expression, ir_node *left = expression_to_firm(expression->left); ir_node *right = expression_to_firm(expression->right); type_t *type = expression->right->datatype; - /* be careful with the modes, because in asithmetic assign nodes only - * the right operand has the mode of the arithmetic alread */ + /* be careful with the modes, because in arithmetic assign nodes only + * the right operand has the mode of the arithmetic already */ ir_mode *mode = get_ir_mode(type); left = create_conv(dbgi, left, mode); ir_node *res = func(dbgi, left, right, mode); @@ -992,16 +980,44 @@ static ir_node *create_arithmetic_binop(const binary_expression_t *expression, return res; } +static ir_node *pointer_arithmetic(ir_node *const pointer, + ir_node * integer, + type_t *const type, + dbg_info *const dbgi, + const create_arithmetic_func func) +{ + pointer_type_t *const pointer_type = (pointer_type_t*)type; + type_t *const points_to = pointer_type->points_to; + const unsigned elem_size = get_type_size(points_to); + + assert(elem_size >= 1); + if (elem_size > 1) { + integer = create_conv(dbgi, integer, mode_Is); + ir_node *const cnst = new_Const_long(mode_Is, (long)elem_size); + ir_node *const mul = new_d_Mul(dbgi, integer, cnst, mode_Is); + integer = mul; + } + + ir_mode *const mode = get_ir_mode(type); + return func(dbgi, pointer, integer, mode); +} + static ir_node *create_arithmetic_assign_binop( const binary_expression_t *expression, create_arithmetic_func func) { - dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); - ir_node *value = create_arithmetic_binop(expression, func); - type_t *type = expression->expression.datatype; - ir_mode *mode = get_ir_mode(type); + dbg_info *const dbgi = get_dbg_info(&expression->expression.source_position); + type_t *const type = expression->expression.datatype; + ir_node *value; - assert(type->type != TYPE_POINTER); + if (type->type == TYPE_POINTER) { + ir_node *const pointer = expression_to_firm(expression->left); + ir_node * integer = expression_to_firm(expression->right); + value = pointer_arithmetic(pointer, integer, type, dbgi, func); + } else { + value = create_arithmetic_binop(expression, func); + } + ir_mode *const mode = get_ir_mode(type); value = create_conv(dbgi, value, mode); set_value_for_expression(expression->left, value); @@ -1014,7 +1030,6 @@ static ir_node *create_add(const binary_expression_t *expression) ir_node *left = expression_to_firm(expression->left); ir_node *right = expression_to_firm(expression->right); type_t *type = expression->expression.datatype; - ir_mode *mode = get_ir_mode(type); expression_t *expr_left = expression->left; expression_t *expr_right = expression->right; @@ -1022,76 +1037,37 @@ static ir_node *create_add(const binary_expression_t *expression) type_t *type_right = skip_typeref(expr_right->datatype); if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { + ir_mode *const mode = get_ir_mode(type); return new_d_Add(dbgi, left, right, mode); } - ir_node *pointer; - ir_node *integer; - pointer_type_t *pointer_type; - if(type_left->type == TYPE_POINTER) { - pointer = left; - integer = right; - pointer_type = (pointer_type_t*) type_left; + if (type_left->type == TYPE_POINTER || type_left->type == TYPE_ARRAY) { + return pointer_arithmetic(left, right, type, dbgi, new_d_Add); } else { - assert(type_right->type == TYPE_POINTER); - pointer = right; - integer = left; - pointer_type = (pointer_type_t*) type_right; - } - - type_t *points_to = pointer_type->points_to; - unsigned elem_size = get_type_size(points_to); - - assert(elem_size >= 1); - if(elem_size > 1) { - integer = create_conv(dbgi, integer, mode_Is); - ir_node *cnst = new_Const_long(mode_Is, (int) elem_size); - ir_node *mul = new_d_Mul(dbgi, integer, cnst, mode_Is); - integer = mul; + assert(type_right->type == TYPE_POINTER || type_right->type == TYPE_ARRAY); + return pointer_arithmetic(right, left, type, dbgi, new_d_Add); } - - ir_node *res = new_d_Add(dbgi, pointer, integer, mode); - - return res; } static ir_node *create_sub(const binary_expression_t *expression) { - dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); - ir_node *left = expression_to_firm(expression->left); - ir_node *right = expression_to_firm(expression->right); - type_t *type = expression->expression.datatype; - ir_mode *mode = get_ir_mode(type); - - expression_t *expr_left = expression->left; - expression_t *expr_right = expression->right; - type_t *type_left = skip_typeref(expr_left->datatype); - type_t *type_right = skip_typeref(expr_right->datatype); - - if((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) - || (type_left->type == TYPE_POINTER - && type_right->type == TYPE_POINTER)) { + dbg_info *const dbgi = get_dbg_info(&expression->expression.source_position); + expression_t *const expr_left = expression->left; + expression_t *const expr_right = expression->right; + ir_node *const left = expression_to_firm(expr_left); + ir_node *const right = expression_to_firm(expr_right); + type_t *const type = expression->expression.datatype; + type_t *const type_left = skip_typeref(expr_left->datatype); + type_t *const type_right = skip_typeref(expr_right->datatype); + + if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) || + (type_left->type == TYPE_POINTER && type_right->type == TYPE_POINTER)) { + ir_mode *const mode = get_ir_mode(type); return new_d_Sub(dbgi, left, right, mode); } - assert(type_right->type == TYPE_POINTER); - ir_node *pointer = left; - ir_node *integer = right; - pointer_type_t *pointer_type = (pointer_type_t*) type_right; - - type_t *points_to = pointer_type->points_to; - unsigned elem_size = get_type_size(points_to); - - assert(elem_size >= 1); - if(elem_size > 1) { - ir_node *cnst = new_Const_long(mode_Iu, elem_size); - ir_node *mul = new_d_Mul(dbgi, integer, cnst, mode_Iu); - integer = mul; - } - - ir_node *res = new_d_Sub(dbgi, pointer, integer, mode); - - return res; + assert(type_left->type == TYPE_POINTER); + return pointer_arithmetic(left, right, type_left, dbgi, new_d_Sub); } static ir_node *create_shift(const binary_expression_t *expression) @@ -1298,27 +1274,26 @@ static ir_node *conditional_to_firm(const conditional_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); - ir_node *condition = expression_to_modeb(expression->condition); - ir_node *cond = new_d_Cond(dbgi, condition); - ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true); - ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false); + ir_node *cur_block = get_cur_block(); /* create the true block */ - ir_node *true_block = new_immBlock(); - add_immBlock_pred(true_block, true_proj); - mature_immBlock(true_block); + ir_node *true_block = new_immBlock(); ir_node *true_val = expression_to_firm(expression->true_expression); ir_node *true_jmp = new_Jmp(); /* create the false block */ ir_node *false_block = new_immBlock(); - add_immBlock_pred(false_block, false_proj); - mature_immBlock(false_block); ir_node *false_val = expression_to_firm(expression->false_expression); ir_node *false_jmp = new_Jmp(); + /* create the condition evaluation */ + set_cur_block(cur_block); + create_condition_evaluation(expression->condition, true_block, false_block); + mature_immBlock(true_block); + mature_immBlock(false_block); + /* create the common block */ ir_node *common_block = new_immBlock(); add_immBlock_pred(common_block, true_jmp); @@ -1354,7 +1329,7 @@ static ir_node *select_to_firm(const select_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); ir_node *addr = select_addr(expression); - type_t *type = expression->expression.datatype; + type_t *type = skip_typeref(expression->expression.datatype); return deref_address(type, addr, dbgi); } @@ -1448,6 +1423,69 @@ static ir_node *expression_to_modeb(const expression_t *expression) return res; } +/** + * create a short-circuit expression evaluation that tries to construct + * efficient control flow structures for &&, || and ! expressions + */ +static void create_condition_evaluation(const expression_t *expression, + ir_node *true_block, + ir_node *false_block) +{ + switch(expression->type) { + case EXPR_UNARY: { + unary_expression_t *unary_expression = (unary_expression_t*) expression; + if(unary_expression->type == UNEXPR_NOT) { + create_condition_evaluation(unary_expression->value, false_block, + true_block); + return; + } + break; + } + case EXPR_BINARY: { + binary_expression_t *binary_expression + = (binary_expression_t*) expression; + if(binary_expression->type == BINEXPR_LOGICAL_AND) { + ir_node *cur_block = get_cur_block(); + ir_node *extra_block = new_immBlock(); + set_cur_block(cur_block); + create_condition_evaluation(binary_expression->left, extra_block, + false_block); + mature_immBlock(extra_block); + set_cur_block(extra_block); + create_condition_evaluation(binary_expression->right, true_block, + false_block); + return; + } + if(binary_expression->type == BINEXPR_LOGICAL_OR) { + ir_node *cur_block = get_cur_block(); + ir_node *extra_block = new_immBlock(); + set_cur_block(cur_block); + create_condition_evaluation(binary_expression->left, true_block, + extra_block); + mature_immBlock(extra_block); + set_cur_block(extra_block); + create_condition_evaluation(binary_expression->right, true_block, + false_block); + return; + } + break; + } + default: + break; + } + + dbg_info *dbgi = get_dbg_info(&expression->source_position); + ir_node *condition = expression_to_modeb(expression); + ir_node *cond = new_d_Cond(dbgi, condition); + ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true); + ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false); + + add_immBlock_pred(true_block, true_proj); + add_immBlock_pred(false_block, false_proj); + + set_cur_block(NULL); +} + static void statement_to_firm(statement_t *statement); static void return_statement_to_firm(return_statement_t *statement) @@ -1492,32 +1530,27 @@ static void expression_statement_to_firm(expression_statement_t *statement) static void if_statement_to_firm(if_statement_t *statement) { - dbg_info *dbgi = get_dbg_info(&statement->statement.source_position); - ir_node *condition = expression_to_modeb(statement->condition); - - /* make sure we have a mode_b condition */ - ir_node *cond = new_d_Cond(dbgi, condition); - ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true); - ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false); + ir_node *cur_block = get_cur_block(); ir_node *fallthrough_block = new_immBlock(); /* the true (blocks) */ - ir_node *true_block = new_immBlock(); - add_immBlock_pred(true_block, true_proj); - mature_immBlock(true_block); - - statement_to_firm(statement->true_statement); - if(get_cur_block() != NULL) { - ir_node *jmp = new_Jmp(); - add_immBlock_pred(fallthrough_block, jmp); + ir_node *true_block; + if (statement->true_statement != NULL) { + true_block = new_immBlock(); + statement_to_firm(statement->true_statement); + if(get_cur_block() != NULL) { + ir_node *jmp = new_Jmp(); + add_immBlock_pred(fallthrough_block, jmp); + } + } else { + true_block = fallthrough_block; } /* the false (blocks) */ + ir_node *false_block; if(statement->false_statement != NULL) { - ir_node *false_block = new_immBlock(); - add_immBlock_pred(false_block, false_proj); - mature_immBlock(false_block); + false_block = new_immBlock(); statement_to_firm(statement->false_statement); if(get_cur_block() != NULL) { @@ -1525,7 +1558,19 @@ static void if_statement_to_firm(if_statement_t *statement) add_immBlock_pred(fallthrough_block, jmp); } } else { - add_immBlock_pred(fallthrough_block, false_proj); + false_block = fallthrough_block; + } + + /* create the condition */ + if(cur_block != NULL) { + set_cur_block(cur_block); + create_condition_evaluation(statement->condition, true_block, + false_block); + } + + mature_immBlock(true_block); + if(false_block != fallthrough_block) { + mature_immBlock(false_block); } mature_immBlock(fallthrough_block); @@ -1534,8 +1579,6 @@ static void if_statement_to_firm(if_statement_t *statement) static void while_statement_to_firm(while_statement_t *statement) { - dbg_info *dbgi = get_dbg_info(&statement->statement.source_position); - ir_node *jmp = NULL; if(get_cur_block() != NULL) { jmp = new_Jmp(); @@ -1547,48 +1590,46 @@ static void while_statement_to_firm(while_statement_t *statement) add_immBlock_pred(header_block, jmp); } - /* create the condition */ - ir_node *condition = expression_to_modeb(statement->condition); - ir_node *cond = new_d_Cond(dbgi, condition); - ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true); - ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false); - /* the false block */ ir_node *false_block = new_immBlock(); - add_immBlock_pred(false_block, false_proj); /* the loop body */ - ir_node *body_block = new_immBlock(); - add_immBlock_pred(body_block, true_proj); - mature_immBlock(body_block); - - ir_node *old_continue_label = continue_label; - ir_node *old_break_label = break_label; - continue_label = header_block; - break_label = false_block; + ir_node *body_block; + if (statement->body != NULL) { + ir_node *old_continue_label = continue_label; + ir_node *old_break_label = break_label; + continue_label = header_block; + break_label = false_block; - statement_to_firm(statement->body); + body_block = new_immBlock(); + statement_to_firm(statement->body); - assert(continue_label == header_block); - assert(break_label == false_block); - continue_label = old_continue_label; - break_label = old_break_label; + assert(continue_label == header_block); + assert(break_label == false_block); + continue_label = old_continue_label; + break_label = old_break_label; - if(get_cur_block() != NULL) { - ir_node *jmp = new_Jmp(); - add_immBlock_pred(header_block, jmp); + if(get_cur_block() != NULL) { + ir_node *jmp = new_Jmp(); + add_immBlock_pred(header_block, jmp); + } + } else { + body_block = header_block; } - mature_immBlock(header_block); + /* create the condition */ + set_cur_block(header_block); + + create_condition_evaluation(statement->condition, body_block, false_block); + mature_immBlock(body_block); mature_immBlock(false_block); + mature_immBlock(header_block); set_cur_block(false_block); } static void do_while_statement_to_firm(do_while_statement_t *statement) { - dbg_info *dbgi = get_dbg_info(&statement->statement.source_position); - ir_node *jmp = NULL; if(get_cur_block() != NULL) { jmp = new_Jmp(); @@ -1606,23 +1647,25 @@ static void do_while_statement_to_firm(do_while_statement_t *statement) add_immBlock_pred(body_block, jmp); } - ir_node *old_continue_label = continue_label; - ir_node *old_break_label = break_label; - continue_label = header_block; - break_label = false_block; + if (statement->body != NULL) { + ir_node *old_continue_label = continue_label; + ir_node *old_break_label = break_label; + continue_label = header_block; + break_label = false_block; - statement_to_firm(statement->body); + statement_to_firm(statement->body); - assert(continue_label == header_block); - assert(break_label == false_block); - continue_label = old_continue_label; - break_label = old_break_label; + assert(continue_label == header_block); + assert(break_label == false_block); + continue_label = old_continue_label; + break_label = old_break_label; - if(get_cur_block() == NULL) { - mature_immBlock(header_block); - mature_immBlock(body_block); - mature_immBlock(false_block); - return; + if (get_cur_block() == NULL) { + mature_immBlock(header_block); + mature_immBlock(body_block); + mature_immBlock(false_block); + return; + } } ir_node *body_jmp = new_Jmp(); @@ -1631,24 +1674,17 @@ static void do_while_statement_to_firm(do_while_statement_t *statement) /* create the condition */ set_cur_block(header_block); - ir_node *condition = expression_to_modeb(statement->condition); - ir_node *cond = new_d_Cond(dbgi, condition); - ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true); - ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false); - add_immBlock_pred(body_block, true_proj); + create_condition_evaluation(statement->condition, body_block, false_block); mature_immBlock(body_block); - - add_immBlock_pred(false_block, false_proj); mature_immBlock(false_block); + mature_immBlock(header_block); set_cur_block(false_block); } static void for_statement_to_firm(for_statement_t *statement) { - dbg_info *const dbgi = get_dbg_info(&statement->statement.source_position); - ir_node *jmp = NULL; if (get_cur_block() != NULL) { if(statement->initialisation != NULL) { @@ -1662,7 +1698,7 @@ static void for_statement_to_firm(for_statement_t *statement) if (statement->step != NULL) { expression_to_firm(statement->step); } - ir_node *const step_jmp = new_Jmp(); + ir_node *const step_jmp = new_Jmp(); /* create the header block */ ir_node *const header_block = new_immBlock(); @@ -1671,48 +1707,46 @@ static void for_statement_to_firm(for_statement_t *statement) } add_immBlock_pred(header_block, step_jmp); - /* create the condition */ - ir_node *true_proj; - ir_node *false_proj; - if (statement->condition != NULL) { - ir_node *const condition = expression_to_modeb(statement->condition); - ir_node *const cond = new_d_Cond(dbgi, condition); - true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true); - false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false); - } else { - keep_alive(header_block); - true_proj = new_Jmp(); - false_proj = NULL; - } - /* the false block */ ir_node *const false_block = new_immBlock(); - if (false_proj != NULL) { - add_immBlock_pred(false_block, false_proj); - } /* the loop body */ - ir_node *const body_block = new_immBlock(); - add_immBlock_pred(body_block, true_proj); - mature_immBlock(body_block); - - ir_node *const old_continue_label = continue_label; - ir_node *const old_break_label = break_label; - continue_label = step_block; - break_label = false_block; - - statement_to_firm(statement->body); - - assert(continue_label == step_block); - assert(break_label == false_block); - continue_label = old_continue_label; - break_label = old_break_label; + ir_node * body_block; + if (statement->body != NULL) { + ir_node *const old_continue_label = continue_label; + ir_node *const old_break_label = break_label; + continue_label = step_block; + break_label = false_block; + + body_block = new_immBlock(); + statement_to_firm(statement->body); + + assert(continue_label == step_block); + assert(break_label == false_block); + continue_label = old_continue_label; + break_label = old_break_label; + + if (get_cur_block() != NULL) { + ir_node *const jmp = new_Jmp(); + add_immBlock_pred(step_block, jmp); + } + } else { + body_block = step_block; + } - if (get_cur_block() != NULL) { - ir_node *const jmp = new_Jmp(); - add_immBlock_pred(step_block, jmp); + /* create the condition */ + set_cur_block(header_block); + if (statement->condition != NULL) { + create_condition_evaluation(statement->condition, body_block, + false_block); + } else { + keep_alive(header_block); + ir_node *jmp = new_Jmp(); + add_immBlock_pred(body_block, jmp); } + mature_immBlock(body_block); + mature_immBlock(false_block); mature_immBlock(step_block); mature_immBlock(header_block); mature_immBlock(false_block); @@ -1923,7 +1957,7 @@ static void case_label_to_firm(const case_label_statement_t *statement) static ir_node *get_label_block(declaration_t *label) { - assert(label->namespace == NAMESPACE_LABEL); + assert(label->namespc == NAMESPACE_LABEL); if(label->declaration_type == DECLARATION_TYPE_LABEL_BLOCK) { return label->v.block; @@ -2020,11 +2054,112 @@ static void statement_to_firm(statement_t *statement) panic("Statement not implemented\n"); } +static int count_local_declarations(const declaration_t * decl, + const declaration_t *const end) +{ + int count = 0; + for (; decl != end; decl = decl->next) { + const type_t *type = skip_typeref(decl->type); + switch (type->type) { + case TYPE_ATOMIC: + case TYPE_ENUM: + case TYPE_POINTER: + if (!decl->address_taken) ++count; + break; + + default: break; + } + } + return count; +} + +static int count_decls_in_stmts(const statement_t *stmt) +{ + int count = 0; + for (; stmt != NULL; stmt = stmt->next) { + switch (stmt->type) { + case STATEMENT_DECLARATION: { + const declaration_statement_t *const decl_stmt = + (const declaration_statement_t*)stmt; + count += count_local_declarations(decl_stmt->declarations_begin, + decl_stmt->declarations_end->next); + break; + } + + case STATEMENT_COMPOUND: { + const compound_statement_t *const comp = + (const compound_statement_t*)stmt; + count += count_decls_in_stmts(comp->statements); + break; + } + + case STATEMENT_IF: { + const if_statement_t *const if_stmt = (const if_statement_t*)stmt; + count += count_decls_in_stmts(if_stmt->true_statement); + count += count_decls_in_stmts(if_stmt->false_statement); + break; + } + + case STATEMENT_SWITCH: { + const switch_statement_t *const switch_stmt = + (const switch_statement_t*)stmt; + count += count_decls_in_stmts(switch_stmt->body); + break; + } + + case STATEMENT_LABEL: { + const label_statement_t *const label_stmt = + (const label_statement_t*)stmt; + count += count_decls_in_stmts(label_stmt->label_statement); + break; + } + + case STATEMENT_WHILE: { + const while_statement_t *const while_stmt = + (const while_statement_t*)stmt; + count += count_decls_in_stmts(while_stmt->body); + break; + } + + case STATEMENT_DO_WHILE: { + const do_while_statement_t *const do_while_stmt = + (const do_while_statement_t*)stmt; + count += count_decls_in_stmts(do_while_stmt->body); + break; + } + + case STATEMENT_FOR: { + const for_statement_t *const for_stmt = + (const for_statement_t*)stmt; + /* TODO initialisation */ + count += count_decls_in_stmts(for_stmt->body); + break; + } + + case STATEMENT_BREAK: + case STATEMENT_CASE_LABEL: + case STATEMENT_CONTINUE: + case STATEMENT_EXPRESSION: + case STATEMENT_GOTO: + case STATEMENT_INVALID: + case STATEMENT_RETURN: + break; + } + } + return count; +} + static int get_function_n_local_vars(declaration_t *declaration) { - (void) declaration; - /* TODO */ - return 30; + int count = 0; + + /* count parameters */ + count += count_local_declarations(declaration->context.declarations, NULL); + + /* count local variables declared in body */ + count += count_decls_in_stmts(declaration->init.statement); + + return count; } static void initialize_function_parameters(declaration_t *declaration) @@ -2166,7 +2301,7 @@ static void context_to_firm(context_t *context) { declaration_t *declaration = context->declarations; for( ; declaration != NULL; declaration = declaration->next) { - if(declaration->namespace != NAMESPACE_NORMAL) + if(declaration->namespc != NAMESPACE_NORMAL) continue; if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY || declaration->storage_class == STORAGE_CLASS_TYPEDEF)