X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=e081b1d9b2be6b7609e4ad63b71ac7049bbc64f5;hb=315d496108eb191418160aea57f3ab916e5770dc;hp=d8e33e54fa76ca4dcc8877076a454069d43c19da;hpb=34b3a147bf445fa2744f3fa1ad64b4f742078aad;p=cparser diff --git a/ast2firm.c b/ast2firm.c index d8e33e5..e081b1d 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -77,7 +77,7 @@ unsigned dbg_snprint(char *buf, unsigned len, const dbg_info *dbg) pos->linenr); } -const char *retrieve_dbg(const dbg_info *dbg, unsigned *line) +const char *dbg_retrieve(const dbg_info *dbg, unsigned *line) { const source_position_t *pos = (const source_position_t*) dbg; if(pos == NULL) @@ -120,6 +120,7 @@ static ir_mode *get_atomic_mode(const atomic_type_t* atomic_type) return mode_Hs; case ATOMIC_TYPE_USHORT: return mode_Hu; + case ATOMIC_TYPE_BOOL: case ATOMIC_TYPE_LONG: case ATOMIC_TYPE_INT: return mode_Is; @@ -136,8 +137,6 @@ static ir_mode *get_atomic_mode(const atomic_type_t* atomic_type) return mode_D; case ATOMIC_TYPE_LONG_DOUBLE: return mode_E; - case ATOMIC_TYPE_BOOL: - return mode_b; #ifdef PROVIDE_COMPLEX case ATOMIC_TYPE_FLOAT_COMPLEX: case ATOMIC_TYPE_DOUBLE_COMPLEX: @@ -263,6 +262,10 @@ static ir_type *create_atomic_type(const atomic_type_t *type) ident *id = get_mode_ident(mode); ir_type *irtype = new_type_primitive(id, mode); + if(type->atype == ATOMIC_TYPE_LONG_DOUBLE) { + set_type_alignment_bytes(irtype, 4); + } + return irtype; } @@ -564,6 +567,7 @@ static ir_entity* get_function_entity(declaration_t *declaration) } else { set_entity_visibility(entity, visibility_external_allocated); } + set_entity_allocation(entity, allocation_static); declaration->declaration_type = DECLARATION_TYPE_FUNCTION; declaration->v.entity = entity; @@ -619,6 +623,7 @@ static ir_node *string_to_firm(const source_position_t *const src_pos, ir_entity *const entity = new_entity(global_type, id, type); set_entity_ld_ident(entity, id); set_entity_variability(entity, variability_constant); + set_entity_allocation(entity, allocation_static); ir_type *const elem_type = ir_type_const_char; ir_mode *const mode = get_type_mode(elem_type); @@ -662,6 +667,7 @@ static ir_node *wide_string_literal_to_firm( ir_entity *const entity = new_entity(global_type, id, type); set_entity_ld_ident(entity, id); set_entity_variability(entity, variability_constant); + set_entity_allocation(entity, allocation_static); ir_mode *const mode = get_type_mode(elem_type); @@ -1534,10 +1540,53 @@ static ir_node *sizeof_to_firm(const sizeof_expression_t *expression) return size_node; } +static tarval *try_fold_constant(const expression_t *expression) +{ + ir_graph *old_current_ir_graph = current_ir_graph; + if(current_ir_graph == NULL) { + current_ir_graph = get_const_code_irg(); + } + + ir_node *cnst = expression_to_firm(expression); + current_ir_graph = old_current_ir_graph; + + if(!is_Const(cnst)) { + return NULL; + } + + tarval *tv = get_Const_tarval(cnst); + if(!tarval_is_long(tv)) { + return NULL; + } + + return tv; +} + +static long fold_constant(const expression_t *expression) +{ + tarval *tv = try_fold_constant(expression); + if(tv == NULL) { + panic("couldn't fold constantl"); + } + + return get_tarval_long(tv); +} + static ir_node *conditional_to_firm(const conditional_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); + /* first try to fold a constant condition */ + tarval *tv = try_fold_constant(expression->condition); + if(tv != NULL) { + long val = get_tarval_long(tv); + if(val) { + return expression_to_firm(expression->true_expression); + } else { + return expression_to_firm(expression->false_expression); + } + } + ir_node *cur_block = get_cur_block(); /* create the true block */ @@ -1918,461 +1967,169 @@ static void create_condition_evaluation(const expression_t *expression, set_cur_block(NULL); } -static void return_statement_to_firm(return_statement_t *statement) + + +static void create_declaration_entity(declaration_t *declaration, + declaration_type_t declaration_type, + ir_type *parent_type) { - if(get_cur_block() == NULL) - return; + ident *id = new_id_from_str(declaration->symbol->string); + ir_type *irtype = get_ir_type(declaration->type); + ir_entity *entity = new_entity(parent_type, id, irtype); + set_entity_ld_ident(entity, id); - ir_type *func_irtype = get_ir_type(current_function_decl->type); + declaration->declaration_type = (unsigned char) declaration_type; + declaration->v.entity = entity; + set_entity_variability(entity, variability_uninitialized); + if(parent_type == get_tls_type()) + set_entity_allocation(entity, allocation_automatic); + else if(declaration_type == DECLARATION_TYPE_GLOBAL_VARIABLE) + set_entity_allocation(entity, allocation_static); + /* TODO: visibility? */ +} - dbg_info *dbgi = get_dbg_info(&statement->statement.source_position); +typedef struct compound_graph_path_entry_t compound_graph_path_entry_t; - ir_node *in[1]; - int in_len; - if(get_method_n_ress(func_irtype) > 0) { - ir_type *res_type = get_method_res_type(func_irtype, 0); +enum compound_graph_entry_type_t { + COMPOUND_GRAPH_ENTRY_ARRAY, + COMPOUND_GRAPH_ENTRY_COMPOUND +}; - if(statement->return_value != NULL) { - ir_node *node = expression_to_firm(statement->return_value); - node = do_strict_conv(dbgi, node); - in[0] = node; +struct compound_graph_path_entry_t { + int type; + union { + ir_entity *entity; + int array_index; + } v; + compound_graph_path_entry_t *prev; +}; + +static void create_initializer_object(initializer_t *initializer, type_t *type, + ir_entity *entity, compound_graph_path_entry_t *entry, int len); + +static compound_graph_path *create_compound_path(ir_type *type, + compound_graph_path_entry_t *entry, int len) +{ + compound_graph_path *path = new_compound_graph_path(type, len); + + int i = len - 1; + for( ; entry != NULL; entry = entry->prev, --i) { + assert(i >= 0); + if(entry->type == COMPOUND_GRAPH_ENTRY_COMPOUND) { + set_compound_graph_path_node(path, i, entry->v.entity); } else { - ir_mode *mode; - if(is_compound_type(res_type)) { - mode = mode_P_data; - } else { - mode = get_type_mode(res_type); - } - in[0] = new_Unknown(mode); - } - in_len = 1; - } else { - /* build return_value for its side effects */ - if(statement->return_value != NULL) { - expression_to_firm(statement->return_value); + assert(entry->type == COMPOUND_GRAPH_ENTRY_ARRAY); + set_compound_graph_path_array_index(path, i, entry->v.array_index); } - in_len = 0; } + assert(i == -1); - ir_node *store = get_store(); - ir_node *ret = new_d_Return(dbgi, store, in_len, in); - - ir_node *end_block = get_irg_end_block(current_ir_graph); - add_immBlock_pred(end_block, ret); - - set_cur_block(NULL); + return path; } -static ir_node *expression_statement_to_firm(expression_statement_t *statement) +static void create_initializer_value(initializer_value_t *initializer, + ir_entity *entity, + compound_graph_path_entry_t *entry, + int len) { - if(get_cur_block() == NULL) - return NULL; - - return expression_to_firm(statement->expression); + ir_node *node = expression_to_firm(initializer->value); + ir_type *type = get_entity_type(entity); + compound_graph_path *path = create_compound_path(type, entry, len); + add_compound_ent_value_w_path(entity, node, path); } -static ir_node *compound_statement_to_firm(compound_statement_t *compound) +static void create_initializer_compound(initializer_list_t *initializer, + compound_type_t *type, + ir_entity *entity, + compound_graph_path_entry_t *last_entry, + int len) { - ir_node *result = NULL; - statement_t *statement = compound->statements; - for( ; statement != NULL; statement = statement->base.next) { - //context2firm(&statement->context); + declaration_t *compound_declaration = type->declaration; - if(statement->base.next == NULL - && statement->type == STATEMENT_EXPRESSION) { - result = expression_statement_to_firm( - (expression_statement_t*) statement); + declaration_t *compound_entry = compound_declaration->context.declarations; + + compound_graph_path_entry_t entry; + entry.type = COMPOUND_GRAPH_ENTRY_COMPOUND; + entry.prev = last_entry; + ++len; + + size_t i = 0; + for( ; compound_entry != NULL; compound_entry = compound_entry->next) { + if(compound_entry->symbol == NULL) + continue; + if(compound_entry->namespc != NAMESPACE_NORMAL) + continue; + + if(i >= initializer->len) break; + + entry.v.entity = compound_entry->v.entity; + + initializer_t *sub_initializer = initializer->initializers[i]; + + assert(compound_entry != NULL); + assert(compound_entry->declaration_type + == DECLARATION_TYPE_COMPOUND_MEMBER); + + if(sub_initializer->type == INITIALIZER_VALUE) { + create_initializer_value(&sub_initializer->value, + entity, &entry, len); + } else { + type_t *entry_type = skip_typeref(compound_entry->type); + create_initializer_object(sub_initializer, entry_type, entity, + &entry, len); } - statement_to_firm(statement); - } - return result; + ++i; + } } -static void if_statement_to_firm(if_statement_t *statement) +static void create_initializer_array(initializer_list_t *initializer, + array_type_t *type, ir_entity *entity, + compound_graph_path_entry_t *last_entry, + int len) { - ir_node *cur_block = get_cur_block(); + type_t *element_type = type->element_type; + element_type = skip_typeref(element_type); - ir_node *fallthrough_block = new_immBlock(); + compound_graph_path_entry_t entry; + entry.type = COMPOUND_GRAPH_ENTRY_ARRAY; + entry.prev = last_entry; + ++len; - /* the true (blocks) */ - 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; - } + size_t i; + for(i = 0; i < initializer->len; ++i) { + entry.v.array_index = i; - /* the false (blocks) */ - ir_node *false_block; - if(statement->false_statement != NULL) { - false_block = new_immBlock(); + initializer_t *sub_initializer = initializer->initializers[i]; - statement_to_firm(statement->false_statement); - if(get_cur_block() != NULL) { - ir_node *jmp = new_Jmp(); - add_immBlock_pred(fallthrough_block, jmp); + if(sub_initializer->type == INITIALIZER_VALUE) { + create_initializer_value(&sub_initializer->value, + entity, &entry, len); + } else { + create_initializer_object(sub_initializer, element_type, entity, + &entry, len); } - } else { - 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); - } +#if 0 + /* TODO: initialize rest... */ + if(type->size_expression != NULL) { + size_t array_len = fold_constant(type->size_expression); + for( ; i < array_len; ++i) { - mature_immBlock(true_block); - if(false_block != fallthrough_block) { - mature_immBlock(false_block); + } } - mature_immBlock(fallthrough_block); - - set_cur_block(fallthrough_block); +#endif } -static void while_statement_to_firm(while_statement_t *statement) +static void create_initializer_string(initializer_string_t *initializer, + array_type_t *type, ir_entity *entity, + compound_graph_path_entry_t *last_entry, + int len) { - ir_node *jmp = NULL; - if(get_cur_block() != NULL) { - jmp = new_Jmp(); - } - - /* create the header block */ - ir_node *header_block = new_immBlock(); - if(jmp != NULL) { - add_immBlock_pred(header_block, jmp); - } - - /* the false block */ - ir_node *false_block = new_immBlock(); - - /* the loop body */ - 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; - - 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; - - if(get_cur_block() != NULL) { - jmp = new_Jmp(); - add_immBlock_pred(header_block, jmp); - } - } else { - body_block = 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) -{ - ir_node *jmp = NULL; - if(get_cur_block() != NULL) { - jmp = new_Jmp(); - } - - /* create the header block */ - ir_node *header_block = new_immBlock(); - - /* the false block */ - ir_node *false_block = new_immBlock(); - - /* the loop body */ - ir_node *body_block = new_immBlock(); - if(jmp != NULL) { - add_immBlock_pred(body_block, jmp); - } - - 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); - - 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; - } - } - - ir_node *body_jmp = new_Jmp(); - add_immBlock_pred(header_block, body_jmp); - 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 for_statement_to_firm(for_statement_t *statement) -{ - ir_node *jmp = NULL; - if (get_cur_block() != NULL) { - if(statement->initialisation != NULL) { - expression_to_firm(statement->initialisation); - } - jmp = new_Jmp(); - } - - /* create the step block */ - ir_node *const step_block = new_immBlock(); - if (statement->step != NULL) { - expression_to_firm(statement->step); - } - ir_node *const step_jmp = new_Jmp(); - - /* create the header block */ - ir_node *const header_block = new_immBlock(); - if (jmp != NULL) { - add_immBlock_pred(header_block, jmp); - } - add_immBlock_pred(header_block, step_jmp); - - /* the false block */ - ir_node *const false_block = new_immBlock(); - - /* the loop body */ - 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) { - jmp = new_Jmp(); - add_immBlock_pred(step_block, jmp); - } - } else { - body_block = step_block; - } - - /* 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); - 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); - - set_cur_block(false_block); -} - -static void create_declaration_entity(declaration_t *declaration, - declaration_type_t declaration_type, - ir_type *parent_type) -{ - ident *id = new_id_from_str(declaration->symbol->string); - ir_type *irtype = get_ir_type(declaration->type); - ir_entity *entity = new_entity(parent_type, id, irtype); - set_entity_ld_ident(entity, id); - - declaration->declaration_type = (unsigned char) declaration_type; - declaration->v.entity = entity; - set_entity_variability(entity, variability_uninitialized); - /* TODO: visibility? */ -} - -typedef struct compound_graph_path_entry_t compound_graph_path_entry_t; - -enum compound_graph_entry_type_t { - COMPOUND_GRAPH_ENTRY_ARRAY, - COMPOUND_GRAPH_ENTRY_COMPOUND -}; - -struct compound_graph_path_entry_t { - int type; - union { - ir_entity *entity; - int array_index; - } v; - compound_graph_path_entry_t *prev; -}; - -static void create_initializer_object(initializer_t *initializer, type_t *type, - ir_entity *entity, compound_graph_path_entry_t *entry, int len); - -static compound_graph_path *create_compound_path(ir_type *type, - compound_graph_path_entry_t *entry, int len) -{ - compound_graph_path *path = new_compound_graph_path(type, len); - - int i = len - 1; - for( ; entry != NULL; entry = entry->prev, --i) { - assert(i >= 0); - if(entry->type == COMPOUND_GRAPH_ENTRY_COMPOUND) { - set_compound_graph_path_node(path, i, entry->v.entity); - } else { - assert(entry->type == COMPOUND_GRAPH_ENTRY_ARRAY); - set_compound_graph_path_array_index(path, i, entry->v.array_index); - } - } - assert(i == -1); - - return path; -} - -static void create_initializer_value(initializer_value_t *initializer, - ir_entity *entity, - compound_graph_path_entry_t *entry, - int len) -{ - ir_node *node = expression_to_firm(initializer->value); - ir_type *type = get_entity_type(entity); - compound_graph_path *path = create_compound_path(type, entry, len); - add_compound_ent_value_w_path(entity, node, path); -} - -static void create_initializer_compound(initializer_list_t *initializer, - compound_type_t *type, - ir_entity *entity, - compound_graph_path_entry_t *last_entry, - int len) -{ - declaration_t *compound_declaration = type->declaration; - - declaration_t *compound_entry = compound_declaration->context.declarations; - - compound_graph_path_entry_t entry; - entry.type = COMPOUND_GRAPH_ENTRY_COMPOUND; - entry.prev = last_entry; - ++len; - - size_t i = 0; - for( ; compound_entry != NULL; compound_entry = compound_entry->next) { - if(compound_entry->symbol == NULL) - continue; - if(compound_entry->namespc != NAMESPACE_NORMAL) - continue; - - if(i >= initializer->len) - break; - - entry.v.entity = compound_entry->v.entity; - - initializer_t *sub_initializer = initializer->initializers[i]; - - assert(compound_entry != NULL); - assert(compound_entry->declaration_type - == DECLARATION_TYPE_COMPOUND_MEMBER); - - if(sub_initializer->type == INITIALIZER_VALUE) { - create_initializer_value(&sub_initializer->value, - entity, &entry, len); - } else { - type_t *entry_type = skip_typeref(compound_entry->type); - create_initializer_object(sub_initializer, entry_type, entity, - &entry, len); - } - - ++i; - } -} - -static void create_initializer_array(initializer_list_t *initializer, - array_type_t *type, ir_entity *entity, - compound_graph_path_entry_t *last_entry, - int len) -{ - type_t *element_type = type->element_type; - element_type = skip_typeref(element_type); - - compound_graph_path_entry_t entry; - entry.type = COMPOUND_GRAPH_ENTRY_ARRAY; - entry.prev = last_entry; - ++len; - - size_t i; - for(i = 0; i < initializer->len; ++i) { - entry.v.array_index = i; - - initializer_t *sub_initializer = initializer->initializers[i]; - - if(sub_initializer->type == INITIALIZER_VALUE) { - create_initializer_value(&sub_initializer->value, - entity, &entry, len); - } else { - create_initializer_object(sub_initializer, element_type, entity, - &entry, len); - } - } - -#if 0 - /* TODO: initialize rest... */ - if(type->size_expression != NULL) { - size_t array_len = fold_constant(type->size_expression); - for( ; i < array_len; ++i) { - - } - } -#endif -} - -static void create_initializer_string(initializer_string_t *initializer, - array_type_t *type, ir_entity *entity, - compound_graph_path_entry_t *last_entry, - int len) -{ - type_t *element_type = type->element_type; - element_type = skip_typeref(element_type); + type_t *element_type = type->element_type; + element_type = skip_typeref(element_type); compound_graph_path_entry_t entry; entry.type = COMPOUND_GRAPH_ENTRY_ARRAY; @@ -2488,6 +2245,7 @@ static void create_initializer_local_variable_entity(declaration_t *declaration) set_entity_variability(init_entity, variability_initialized); set_entity_visibility(init_entity, visibility_local); + set_entity_allocation(init_entity, allocation_static); ir_graph *old_current_ir_graph = current_ir_graph; current_ir_graph = get_const_code_irg(); @@ -2498,136 +2256,449 @@ static void create_initializer_local_variable_entity(declaration_t *declaration) assert(current_ir_graph == get_const_code_irg()); current_ir_graph = old_current_ir_graph; - ir_node *src_addr = create_symconst(dbgi, init_entity); - ir_node *copyb = new_d_CopyB(dbgi, memory, addr, src_addr, irtype); + ir_node *src_addr = create_symconst(dbgi, init_entity); + ir_node *copyb = new_d_CopyB(dbgi, memory, addr, src_addr, irtype); + + ir_node *copyb_mem = new_Proj(copyb, mode_M, pn_CopyB_M_regular); + set_store(copyb_mem); +} + +static void create_initializer(declaration_t *declaration) +{ + initializer_t *initializer = declaration->init.initializer; + if(initializer == NULL) + return; + + declaration_type_t declaration_type + = (declaration_type_t) declaration->declaration_type; + if(declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY) { + create_initializer_local_variable_entity(declaration); + return; + } + + if(initializer->type == INITIALIZER_VALUE) { + initializer_value_t *initializer_value = &initializer->value; + + ir_node *value = expression_to_firm(initializer_value->value); + + if(declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE) { + set_value(declaration->v.value_number, value); + } else { + assert(declaration_type == DECLARATION_TYPE_GLOBAL_VARIABLE); + + ir_entity *entity = declaration->v.entity; + + set_entity_variability(entity, variability_initialized); + set_atomic_ent_value(entity, value); + } + } else { + assert(declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY + || declaration_type == DECLARATION_TYPE_GLOBAL_VARIABLE); + + ir_entity *entity = declaration->v.entity; + set_entity_variability(entity, variability_initialized); + + type_t *type = skip_typeref(declaration->type); + create_initializer_object(initializer, type, entity, NULL, 0); + } +} + +static void create_local_variable(declaration_t *declaration) +{ + assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN); + + bool needs_entity = declaration->address_taken; + type_t *type = skip_typeref(declaration->type); + + if(is_type_array(type) || is_type_compound(type)) { + needs_entity = true; + } + + if(needs_entity) { + ir_type *frame_type = get_irg_frame_type(current_ir_graph); + create_declaration_entity(declaration, + DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY, + frame_type); + } else { + declaration->declaration_type = DECLARATION_TYPE_LOCAL_VARIABLE; + declaration->v.value_number = next_value_number_function; + ++next_value_number_function; + } + + create_initializer(declaration); +} + +static void create_local_static_variable(declaration_t *declaration) +{ + assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN); + + type_t *type = skip_typeref(declaration->type); + ir_type *global_type = get_glob_type(); + ident *id = unique_ident(declaration->symbol->string); + ir_type *irtype = get_ir_type(type); + ir_entity *entity = new_entity(global_type, id, irtype); + set_entity_ld_ident(entity, id); + + declaration->declaration_type = DECLARATION_TYPE_GLOBAL_VARIABLE; + declaration->v.entity = entity; + set_entity_variability(entity, variability_uninitialized); + set_entity_visibility(entity, visibility_local); + set_entity_allocation(entity, allocation_static); + + ir_graph *old_current_ir_graph = current_ir_graph; + current_ir_graph = get_const_code_irg(); + + create_initializer(declaration); + + assert(current_ir_graph == get_const_code_irg()); + current_ir_graph = old_current_ir_graph; +} + + + +static void return_statement_to_firm(return_statement_t *statement) +{ + if(get_cur_block() == NULL) + return; + + ir_type *func_irtype = get_ir_type(current_function_decl->type); + + dbg_info *dbgi = get_dbg_info(&statement->statement.source_position); + + ir_node *in[1]; + int in_len; + if(get_method_n_ress(func_irtype) > 0) { + ir_type *res_type = get_method_res_type(func_irtype, 0); + + if(statement->return_value != NULL) { + ir_node *node = expression_to_firm(statement->return_value); + node = do_strict_conv(dbgi, node); + in[0] = node; + } else { + ir_mode *mode; + if(is_compound_type(res_type)) { + mode = mode_P_data; + } else { + mode = get_type_mode(res_type); + } + in[0] = new_Unknown(mode); + } + in_len = 1; + } else { + /* build return_value for its side effects */ + if(statement->return_value != NULL) { + expression_to_firm(statement->return_value); + } + in_len = 0; + } + + ir_node *store = get_store(); + ir_node *ret = new_d_Return(dbgi, store, in_len, in); + + ir_node *end_block = get_irg_end_block(current_ir_graph); + add_immBlock_pred(end_block, ret); + + set_cur_block(NULL); +} + +static ir_node *expression_statement_to_firm(expression_statement_t *statement) +{ + if(get_cur_block() == NULL) + return NULL; + + return expression_to_firm(statement->expression); +} + +static ir_node *compound_statement_to_firm(compound_statement_t *compound) +{ + ir_node *result = NULL; + statement_t *statement = compound->statements; + for( ; statement != NULL; statement = statement->base.next) { + //context2firm(&statement->context); + + if(statement->base.next == NULL + && statement->type == STATEMENT_EXPRESSION) { + result = expression_statement_to_firm( + (expression_statement_t*) statement); + break; + } + statement_to_firm(statement); + } + + return result; +} + +static void create_local_declaration(declaration_t *declaration) +{ + type_t *type = skip_typeref(declaration->type); + + switch ((storage_class_tag_t) declaration->storage_class) { + case STORAGE_CLASS_STATIC: + create_local_static_variable(declaration); + return; + case STORAGE_CLASS_ENUM_ENTRY: + panic("enum entry declaration in local block found"); + case STORAGE_CLASS_EXTERN: + panic("extern declaration in local block found"); + case STORAGE_CLASS_NONE: + case STORAGE_CLASS_AUTO: + case STORAGE_CLASS_REGISTER: + if(is_type_function(type)) { + panic("nested functions not supported yet"); + } else { + create_local_variable(declaration); + } + return; + case STORAGE_CLASS_TYPEDEF: + case STORAGE_CLASS_THREAD: + case STORAGE_CLASS_THREAD_EXTERN: + case STORAGE_CLASS_THREAD_STATIC: + return; + } + panic("invalid storage class found"); +} + +static void declaration_statement_to_firm(declaration_statement_t *statement) +{ + declaration_t *declaration = statement->declarations_begin; + declaration_t *end = statement->declarations_end->next; + for( ; declaration != end; declaration = declaration->next) { + create_local_variable(declaration); + } +} + +static void if_statement_to_firm(if_statement_t *statement) +{ + ir_node *cur_block = get_cur_block(); + + ir_node *fallthrough_block = new_immBlock(); + + /* the true (blocks) */ + 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) { + false_block = new_immBlock(); + + statement_to_firm(statement->false_statement); + if(get_cur_block() != NULL) { + ir_node *jmp = new_Jmp(); + add_immBlock_pred(fallthrough_block, jmp); + } + } else { + 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); - ir_node *copyb_mem = new_Proj(copyb, mode_M, pn_CopyB_M_regular); - set_store(copyb_mem); + set_cur_block(fallthrough_block); } -static void create_initializer(declaration_t *declaration) +static void while_statement_to_firm(while_statement_t *statement) { - initializer_t *initializer = declaration->init.initializer; - if(initializer == NULL) - return; + ir_node *jmp = NULL; + if(get_cur_block() != NULL) { + jmp = new_Jmp(); + } - declaration_type_t declaration_type - = (declaration_type_t) declaration->declaration_type; - if(declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY) { - create_initializer_local_variable_entity(declaration); - return; + /* create the header block */ + ir_node *header_block = new_immBlock(); + if(jmp != NULL) { + add_immBlock_pred(header_block, jmp); } - if(initializer->type == INITIALIZER_VALUE) { - initializer_value_t *initializer_value = &initializer->value; + /* the false block */ + ir_node *false_block = new_immBlock(); - ir_node *value = expression_to_firm(initializer_value->value); + /* the loop body */ + 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; - if(declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE) { - set_value(declaration->v.value_number, value); - } else { - assert(declaration_type == DECLARATION_TYPE_GLOBAL_VARIABLE); + body_block = new_immBlock(); + statement_to_firm(statement->body); - ir_entity *entity = declaration->v.entity; + assert(continue_label == header_block); + assert(break_label == false_block); + continue_label = old_continue_label; + break_label = old_break_label; - set_entity_variability(entity, variability_initialized); - set_atomic_ent_value(entity, value); + if(get_cur_block() != NULL) { + jmp = new_Jmp(); + add_immBlock_pred(header_block, jmp); } } else { - assert(declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY - || declaration_type == DECLARATION_TYPE_GLOBAL_VARIABLE); + body_block = header_block; + } - ir_entity *entity = declaration->v.entity; - set_entity_variability(entity, variability_initialized); + /* create the condition */ + set_cur_block(header_block); - type_t *type = skip_typeref(declaration->type); - create_initializer_object(initializer, type, entity, NULL, 0); - } + 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 create_local_variable(declaration_t *declaration) +static void do_while_statement_to_firm(do_while_statement_t *statement) { - assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN); + ir_node *jmp = NULL; + if(get_cur_block() != NULL) { + jmp = new_Jmp(); + } - bool needs_entity = declaration->address_taken; - type_t *type = skip_typeref(declaration->type); + /* create the header block */ + ir_node *header_block = new_immBlock(); - if(is_type_array(type) || is_type_compound(type)) { - needs_entity = true; + /* the false block */ + ir_node *false_block = new_immBlock(); + + /* the loop body */ + ir_node *body_block = new_immBlock(); + if(jmp != NULL) { + add_immBlock_pred(body_block, jmp); } - if(needs_entity) { - ir_type *frame_type = get_irg_frame_type(current_ir_graph); - create_declaration_entity(declaration, - DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY, - frame_type); - } else { - declaration->declaration_type = DECLARATION_TYPE_LOCAL_VARIABLE; - declaration->v.value_number = next_value_number_function; - ++next_value_number_function; + 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); + + 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; + } } - create_initializer(declaration); + ir_node *body_jmp = new_Jmp(); + add_immBlock_pred(header_block, body_jmp); + 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 create_local_static_variable(declaration_t *declaration) +static void for_statement_to_firm(for_statement_t *statement) { - assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN); + ir_node *jmp = NULL; + if (get_cur_block() != NULL) { + if(statement->initialisation != NULL) { + expression_to_firm(statement->initialisation); + } - type_t *type = skip_typeref(declaration->type); - ir_type *global_type = get_glob_type(); - ident *id = unique_ident(declaration->symbol->string); - ir_type *irtype = get_ir_type(type); - ir_entity *entity = new_entity(global_type, id, irtype); - set_entity_ld_ident(entity, id); + /* create declarations */ + declaration_t *declaration = statement->context.declarations; + for( ; declaration != NULL; declaration = declaration->next) { + create_local_declaration(declaration); + } - declaration->declaration_type = DECLARATION_TYPE_GLOBAL_VARIABLE; - declaration->v.entity = entity; - set_entity_variability(entity, variability_uninitialized); - set_entity_visibility(entity, visibility_local); + jmp = new_Jmp(); + } - ir_graph *old_current_ir_graph = current_ir_graph; - current_ir_graph = get_const_code_irg(); - create_initializer(declaration); + /* create the step block */ + ir_node *const step_block = new_immBlock(); + if (statement->step != NULL) { + expression_to_firm(statement->step); + } + ir_node *const step_jmp = new_Jmp(); - assert(current_ir_graph == get_const_code_irg()); - current_ir_graph = old_current_ir_graph; -} + /* create the header block */ + ir_node *const header_block = new_immBlock(); + if (jmp != NULL) { + add_immBlock_pred(header_block, jmp); + } + add_immBlock_pred(header_block, step_jmp); -static void declaration_statement_to_firm(declaration_statement_t *statement) -{ - declaration_t *declaration = statement->declarations_begin; - declaration_t *end = statement->declarations_end->next; - for( ; declaration != end; declaration = declaration->next) { - type_t *type = skip_typeref(declaration->type); + /* the false block */ + ir_node *const false_block = new_immBlock(); - switch ((storage_class_tag_t) declaration->storage_class) { - case STORAGE_CLASS_TYPEDEF: - continue; - case STORAGE_CLASS_STATIC: - create_local_static_variable(declaration); - continue; - case STORAGE_CLASS_ENUM_ENTRY: - panic("enum entry declaration in local block found"); - case STORAGE_CLASS_EXTERN: - panic("extern declaration in local block found"); - case STORAGE_CLASS_NONE: - case STORAGE_CLASS_AUTO: - case STORAGE_CLASS_REGISTER: - if(is_type_function(type)) { - panic("nested functions not supported yet"); - } else { - create_local_variable(declaration); - } - continue; - case STORAGE_CLASS_THREAD: - case STORAGE_CLASS_THREAD_EXTERN: - case STORAGE_CLASS_THREAD_STATIC: - break; + /* the loop body */ + 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) { + jmp = new_Jmp(); + add_immBlock_pred(step_block, jmp); } - panic("invalid storage class found"); + } else { + body_block = step_block; + } + + /* 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); + 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); + + set_cur_block(false_block); } static void create_jump_statement(const statement_t *statement, @@ -2683,26 +2754,6 @@ static void switch_statement_to_firm(const switch_statement_t *statement) set_cur_block(break_block); } -static long fold_constant(const expression_t *expression) -{ - ir_graph *old_current_ir_graph = current_ir_graph; - current_ir_graph = get_const_code_irg(); - - ir_node *cnst = expression_to_firm(expression); - if(!is_Const(cnst)) { - panic("couldn't fold constantl"); - } - tarval *tv = get_Const_tarval(cnst); - if(!tarval_is_long(tv)) { - panic("folded constant not an integer"); - } - - long res = get_tarval_long(tv); - - current_ir_graph = old_current_ir_graph; - return res; -} - static void case_label_to_firm(const case_label_statement_t *statement) { dbg_info *dbgi = get_dbg_info(&statement->statement.source_position);