X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=317811b075b538247aeb286a746f3a37ae1636ba;hb=00c6e3c2ba43d99e4b448b81521311774421f907;hp=60ebd63407df1c0c2969f6fd1671a90e8897fbbf;hpb=5b462207cdf5b37ffae0daad110855815036873f;p=cparser diff --git a/ast2firm.c b/ast2firm.c index 60ebd63..317811b 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -256,6 +256,8 @@ static unsigned count_parameters(const function_type_t *function_type) +static long fold_constant(const expression_t *expression); + static ir_type *create_atomic_type(const atomic_type_t *type) { ir_mode *mode = get_atomic_mode(type); @@ -317,21 +319,23 @@ static ir_type *create_array_type(array_type_t *type) type_t *element_type = type->element_type; ir_type *ir_element_type = get_ir_type(element_type); - /* TODO... */ - int n_elements = 0; - panic("TODO arraytpye size not implemented yet"); + ident *id = unique_ident("array"); + ir_type *ir_type = new_type_array(id, 1, ir_element_type); + + if(type->size != NULL) { + int n_elements = fold_constant(type->size); - ir_type *ir_type = new_type_array(unique_ident("array"), 1, ir_element_type); - set_array_bounds_int(ir_type, 0, 0, n_elements); + set_array_bounds_int(ir_type, 0, 0, n_elements); - size_t elemsize = get_type_size_bytes(ir_element_type); - int align = get_type_alignment_bytes(ir_element_type); - if(elemsize % align > 0) { - elemsize += align - (elemsize % align); + size_t elemsize = get_type_size_bytes(ir_element_type); + int align = get_type_alignment_bytes(ir_element_type); + if(elemsize % align > 0) { + elemsize += align - (elemsize % align); + } + set_type_size_bytes(ir_type, n_elements * elemsize); + set_type_alignment_bytes(ir_type, align); + set_type_state(ir_type, layout_fixed); } - set_type_size_bytes(ir_type, n_elements * elemsize); - set_type_alignment_bytes(ir_type, align); - set_type_state(ir_type, layout_fixed); return ir_type; } @@ -491,7 +495,13 @@ static ir_type *get_ir_type(type_t *type) static inline ir_mode *get_ir_mode(type_t *type) { ir_type *irtype = get_ir_type(type); - ir_mode *mode = get_type_mode(irtype); + + /* firm doesn't report a mode for arrays somehow... */ + if(is_Array_type(irtype)) { + return mode_P; + } + + ir_mode *mode = get_type_mode(irtype); assert(mode != NULL); return mode; } @@ -509,11 +519,10 @@ static ir_entity* get_function_entity(declaration_t *declaration) ir_type *ir_type_method = get_ir_type(declaration->type); assert(is_Method_type(ir_type_method)); - type_t *type = declaration->type; ir_entity *entity = new_entity(global_type, id, ir_type_method); set_entity_ld_ident(entity, id); - if(declaration->storage_class & STORAGE_CLASS_STATIC - || type->qualifiers & TYPE_QUALIFIER_INLINE) { + if(declaration->storage_class == STORAGE_CLASS_STATIC + || declaration->is_inline) { set_entity_visibility(entity, visibility_local); } else if(declaration->init.statement != NULL) { set_entity_visibility(entity, visibility_external_visible); @@ -612,23 +621,41 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) { dbg_info *dbgi = get_dbg_info(&ref->expression.source_position); declaration_t *declaration = ref->declaration; - type_t *type = declaration->type; - ir_mode *mode = get_ir_mode(type); + type_t *type = skip_typeref(declaration->type); switch((declaration_type_t) declaration->declaration_type) { case DECLARATION_TYPE_UNKNOWN: break; - case DECLARATION_TYPE_LOCAL_VARIABLE: + case DECLARATION_TYPE_LOCAL_VARIABLE: { + ir_mode *mode = get_ir_mode(type); return get_value(declaration->v.value_number, mode); + } case DECLARATION_TYPE_FUNCTION: { return create_symconst(dbgi, declaration->v.entity); } case DECLARATION_TYPE_GLOBAL_VARIABLE: { ir_entity *entity = declaration->v.entity; ir_node *symconst = create_symconst(dbgi, entity); - return load_from_expression_addr(type, symconst, dbgi); + + if(type->type == TYPE_ARRAY) { + return symconst; + } else { + return load_from_expression_addr(type, symconst, dbgi); + } } - case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY: + case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY: { + ir_entity *entity = declaration->v.entity; + ir_node *frame = get_irg_frame(current_ir_graph); + ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, entity); + + if(type->type == TYPE_ARRAY || type->type == TYPE_COMPOUND_STRUCT + || type->type == TYPE_COMPOUND_UNION) { + return sel; + } else { + return load_from_expression_addr(type, sel, dbgi); + } + } + case DECLARATION_TYPE_COMPOUND_MEMBER: case DECLARATION_TYPE_LABEL_BLOCK: panic("not implemented reference type"); @@ -655,7 +682,13 @@ static ir_node *reference_addr(const reference_expression_t *ref) ir_node *symconst = create_symconst(dbgi, entity); return symconst; } - case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY: + case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY: { + ir_entity *entity = declaration->v.entity; + ir_node *frame = get_irg_frame(current_ir_graph); + ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, entity); + + return sel; + } case DECLARATION_TYPE_COMPOUND_MEMBER: case DECLARATION_TYPE_LABEL_BLOCK: panic("not implemented reference type"); @@ -1028,6 +1061,42 @@ static ir_node *create_sub(const binary_expression_t *expression) return res; } +static ir_node *create_shift(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); + + /* firm always wants the shift count to be unsigned */ + right = create_conv(dbgi, right, mode_Iu); + + ir_node *res; + + switch(expression->type) { + case BINEXPR_SHIFTLEFT: + res = new_d_Shl(dbgi, left, right, mode); + break; + case BINEXPR_SHIFTRIGHT: { + expression_t *expr_left = expression->left; + type_t *type_left = skip_typeref(expr_left->datatype); + + if(is_type_signed(type_left)) { + res = new_d_Shrs(dbgi, left, right, mode); + } else { + res = new_d_Shr(dbgi, left, right, mode); + } + break; + } + default: + panic("create shift op called for non-shift op"); + } + + return res; +} + + static ir_node *create_divmod(const binary_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); @@ -1095,9 +1164,8 @@ static ir_node *binary_expression_to_firm(const binary_expression_t *expression) case BINEXPR_BITWISE_XOR: return create_arithmetic_binop(expression, new_d_Eor); case BINEXPR_SHIFTLEFT: - return create_arithmetic_binop(expression, new_d_Shl); case BINEXPR_SHIFTRIGHT: - return create_arithmetic_binop(expression, new_d_Shr); + return create_shift(expression); case BINEXPR_DIV: case BINEXPR_MOD: return create_divmod(expression); @@ -1148,7 +1216,6 @@ static ir_node *array_access_addr(const array_access_expression_t *expression) static ir_node *array_access_to_firm( const array_access_expression_t *expression) { - dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); ir_node *addr = array_access_addr(expression); type_t *type = expression->expression.datatype; @@ -1210,6 +1277,38 @@ static ir_node *conditional_to_firm(const conditional_expression_t *expression) return val; } +static ir_node *select_addr(const select_expression_t *expression) +{ + dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); + + ir_node *compound_addr = expression_to_firm(expression->compound); + + declaration_t *entry = expression->compound_entry; + assert(entry->declaration_type == DECLARATION_TYPE_COMPOUND_MEMBER); + ir_entity *entity = entry->v.entity; + + assert(entity != NULL); + + ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), compound_addr, entity); + + return sel; +} + +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; + + return load_from_expression_addr(type, addr, dbgi); +} + +static ir_node *dereference_addr(const unary_expression_t *const expression) +{ + assert(expression->type == UNEXPR_DEREFERENCE); + return expression_to_firm(expression->value); +} + static ir_node *expression_to_addr(const expression_t *expression) { switch(expression->type) { @@ -1217,6 +1316,16 @@ static ir_node *expression_to_addr(const expression_t *expression) return reference_addr((const reference_expression_t*) expression); case EXPR_ARRAY_ACCESS: return array_access_addr((const array_access_expression_t*) expression); + case EXPR_SELECT: + return select_addr((const select_expression_t*) expression); + case EXPR_UNARY: { + const unary_expression_t *const unary_expr = + (const unary_expression_t*)expression; + if (unary_expr->type == UNEXPR_DEREFERENCE) { + return dereference_addr(unary_expr); + } + break; + } default: break; } @@ -1247,21 +1356,32 @@ static ir_node *_expression_to_firm(const expression_t *expression) return sizeof_to_firm((const sizeof_expression_t*) expression); case EXPR_CONDITIONAL: return conditional_to_firm((const conditional_expression_t*)expression); - default: + case EXPR_SELECT: + return select_to_firm((const select_expression_t*) expression); + case EXPR_FUNCTION: + case EXPR_OFFSETOF: + case EXPR_PRETTY_FUNCTION: + case EXPR_VA_ARG: + case EXPR_STATEMENT: + case EXPR_BUILTIN_SYMBOL: + panic("unimplemented expression found"); + + case EXPR_UNKNOWN: + case EXPR_INVALID: break; } - panic("unsupported expression found"); + panic("invalid expression found"); } static ir_node *expression_to_firm(const expression_t *expression) { - ir_node *res = _expression_to_firm(expression); + ir_node *res = _expression_to_firm(expression); - if(expression->datatype == type_void) - return NULL; + if(get_irn_mode(res) == mode_b) { + ir_mode *mode = get_ir_mode(expression->datatype); + res = create_conv(NULL, res, mode); + } - ir_mode *mode = get_ir_mode(expression->datatype); - res = create_conv(NULL, res, mode); return res; } @@ -1277,6 +1397,9 @@ static void statement_to_firm(statement_t *statement); static void return_statement_to_firm(return_statement_t *statement) { + if(get_cur_block() == NULL) + return; + dbg_info *dbgi = get_dbg_info(&statement->statement.source_position); ir_node *ret; @@ -1306,6 +1429,9 @@ static void compound_statement_to_firm(compound_statement_t *compound) static void expression_statement_to_firm(expression_statement_t *statement) { + if(get_cur_block() == NULL) + return; + expression_to_firm(statement->expression); } @@ -1440,6 +1566,7 @@ static void do_while_statement_to_firm(do_while_statement_t *statement) if(get_cur_block() == NULL) { mature_immBlock(header_block); mature_immBlock(body_block); + mature_immBlock(false_block); return; } @@ -1448,6 +1575,7 @@ static void do_while_statement_to_firm(do_while_statement_t *statement) mature_immBlock(header_block); /* 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); @@ -1579,9 +1707,16 @@ static void create_initializer(declaration_t *declaration) 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); - assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN); + if(type->type == TYPE_ARRAY + || type->type == TYPE_COMPOUND_STRUCT + || type->type == TYPE_COMPOUND_UNION) { + needs_entity = true; + } if(needs_entity) { ir_type *frame_type = get_irg_frame_type(current_ir_graph); @@ -1630,6 +1765,9 @@ static void declaration_statement_to_firm(declaration_statement_t *statement) static void create_jump_statement(const statement_t *statement, ir_node *target_block) { + if(get_cur_block() == NULL) + return; + dbg_info *dbgi = get_dbg_info(&statement->source_position); ir_node *jump = new_d_Jmp(dbgi); add_immBlock_pred(target_block, jump); @@ -1668,6 +1806,26 @@ 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); @@ -1677,16 +1835,7 @@ static void case_label_to_firm(const case_label_statement_t *statement) ir_node *proj; set_cur_block(get_nodes_block(current_switch_cond)); if(statement->expression) { - ir_node *cnst = expression_to_firm(statement->expression); - if(!is_Const(cnst)) { - panic("couldn't fold constant for case label"); - } - tarval *tv = get_Const_tarval(cnst); - if(!mode_is_int(get_tarval_mode(tv))) { - panic("case label not an integer"); - } - - long pn = get_tarval_long(tv); + long pn = fold_constant(statement->expression); if(pn == MAGIC_DEFAULT_PN_NUMBER) { /* oops someone detected our cheating... */ panic("magic default pn used"); @@ -1734,6 +1883,8 @@ static void label_to_firm(const label_statement_t *statement) set_cur_block(block); keep_alive(block); + + statement_to_firm(statement->label_statement); } static void goto_to_firm(const goto_statement_t *statement) @@ -1816,9 +1967,16 @@ static void initialize_function_parameters(declaration_t *declaration) declaration_t *parameter = declaration->context.declarations; for( ; parameter != NULL; parameter = parameter->next) { assert(parameter->declaration_type == DECLARATION_TYPE_UNKNOWN); + type_t *type = parameter->type; + + bool needs_entity = parameter->address_taken; + if(type->type == TYPE_COMPOUND_STRUCT + || type->type == TYPE_COMPOUND_UNION) { + needs_entity = true; + } - if(parameter->address_taken) { - panic("address take from parameter not implemented yet"); + if(needs_entity) { + panic("entities for function parameters not implemented yet"); } ir_mode *mode = get_ir_mode(parameter->type);