X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=27c82207bd096c57899853b819239d44658e0d5a;hb=f109471af0f1a95e840a66c9e136409d0973021c;hp=287c0787a1c90df7b0d4e57dccf3709fb24a0fc3;hpb=7effb0d2f160b9aba0d876bc1d687ddeb855f756;p=cparser diff --git a/ast2firm.c b/ast2firm.c index 287c078..27c8220 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -58,6 +58,9 @@ static ir_type *ir_type_int; /* architecture specific floating point arithmetic mode (if any) */ static ir_mode *mode_float_arithmetic; +/* alignment of stack parameters */ +static unsigned stack_param_align; + static int next_value_number_function; static ir_node *continue_label; static ir_node *break_label; @@ -251,6 +254,9 @@ static ir_node *get_vla_size(array_type_t *const type) return size_node; } +/** + * Return a node representing the size of a type. + */ static ir_node *get_type_size(type_t *type) { type = skip_typeref(type); @@ -1444,6 +1450,21 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) } case DECLARATION_KIND_FUNCTION: { ir_mode *const mode = get_ir_mode_storage(type); + + if (entity->function.btk != bk_none) { + /* for gcc compatibility we have to produce (dummy) addresses for some + * builtins */ + if (warning.other) { + warningf(&ref->base.source_position, + "taking address of builtin '%Y'", ref->entity->base.symbol); + } + + /* simply create a NULL pointer */ + ir_mode *mode = get_ir_mode_arithmetic(type_void_ptr); + ir_node *res = new_Const_long(mode, 0); + + return res; + } return create_symconst(dbgi, mode, entity->function.entity); } case DECLARATION_KIND_INNER_FUNCTION: { @@ -1549,9 +1570,55 @@ static ir_node *gen_unary_builtin(ir_builtin_kind kind, expression_t *op, type_t in[0] = expression_to_firm(op); ir_type *tp = get_ir_type(function_type); + ir_type *res = get_method_res_type(tp, 0); ir_node *irn = new_d_Builtin(db, get_irg_no_mem(current_ir_graph), kind, 1, in, tp); set_irn_pinned(irn, op_pin_state_floats); - return new_Proj(irn, mode_P_data, pn_Builtin_1_result); + return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result); +} + +/** + * Generate a pinned unary builtin. + * + * @param kind the builtin kind to generate + * @param op the operand + * @param function_type the function type for the GNU builtin routine + * @param db debug info + */ +static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op, type_t *function_type, dbg_info *db) +{ + ir_node *in[1]; + in[0] = expression_to_firm(op); + + ir_type *tp = get_ir_type(function_type); + ir_type *res = get_method_res_type(tp, 0); + ir_node *mem = get_store(); + ir_node *irn = new_d_Builtin(db, mem, kind, 1, in, tp); + set_store(new_Proj(irn, mode_M, pn_Builtin_M)); + return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result); +} + + +/** + * Generate an binary-void-return builtin. + * + * @param kind the builtin kind to generate + * @param op1 the first operand + * @param op2 the second operand + * @param function_type the function type for the GNU builtin routine + * @param db debug info + */ +static ir_node *gen_binary_builtin_mem(ir_builtin_kind kind, expression_t *op1, expression_t *op2, + type_t *function_type, dbg_info *db) +{ + ir_node *in[2]; + in[0] = expression_to_firm(op1); + in[1] = expression_to_firm(op2); + + ir_type *tp = get_ir_type(function_type); + ir_node *mem = get_store(); + ir_node *irn = new_d_Builtin(db, mem, kind, 2, in, tp); + set_store(new_Proj(irn, mode_M, pn_Builtin_M)); + return NULL; } /** @@ -1561,17 +1628,16 @@ static ir_node *process_builtin_call(const call_expression_t *call) { dbg_info *dbgi = get_dbg_info(&call->base.source_position); - assert(call->function->kind == EXPR_BUILTIN_SYMBOL); - builtin_symbol_expression_t *builtin = &call->function->builtin_symbol; + assert(call->function->kind == EXPR_REFERENCE); + reference_expression_t *builtin = &call->function->reference; type_t *type = skip_typeref(builtin->base.type); assert(is_type_pointer(type)); type_t *function_type = skip_typeref(type->pointer.points_to); - symbol_t *symbol = builtin->symbol; - switch(symbol->ID) { - case T___builtin_alloca: { + switch (builtin->entity->function.btk) { + case bk_gnu_builtin_alloca: { if (call->arguments == NULL || call->arguments->next != NULL) { panic("invalid number of parameters on __builtin_alloca"); } @@ -1588,19 +1654,19 @@ static ir_node *process_builtin_call(const call_expression_t *call) return res; } - case T___builtin_huge_val: - case T___builtin_inf: - case T___builtin_inff: - case T___builtin_infl: { + case bk_gnu_builtin_huge_val: + case bk_gnu_builtin_inf: + case bk_gnu_builtin_inff: + case bk_gnu_builtin_infl: { type_t *type = function_type->function.return_type; ir_mode *mode = get_ir_mode_arithmetic(type); tarval *tv = get_mode_infinite(mode); ir_node *res = new_d_Const(dbgi, tv); return res; } - case T___builtin_nan: - case T___builtin_nanf: - case T___builtin_nanl: { + case bk_gnu_builtin_nan: + case bk_gnu_builtin_nanf: + case bk_gnu_builtin_nanl: { /* Ignore string for now... */ assert(is_type_function(function_type)); type_t *type = function_type->function.return_type; @@ -1609,15 +1675,15 @@ static ir_node *process_builtin_call(const call_expression_t *call) ir_node *res = new_d_Const(dbgi, tv); return res; } - case T___builtin_expect: { + case bk_gnu_builtin_expect: { expression_t *argument = call->arguments->expression; return _expression_to_firm(argument); } - case T___builtin_va_end: + case bk_gnu_builtin_va_end: /* evaluate the argument of va_end for its side effects */ _expression_to_firm(call->arguments->expression); return NULL; - case T___builtin_frame_address: { + case bk_gnu_builtin_frame_address: { expression_t *const expression = call->arguments->expression; long val = fold_constant(expression); if (val == 0) { @@ -1634,7 +1700,7 @@ static ir_node *process_builtin_call(const call_expression_t *call) return new_Proj(irn, mode_P_data, pn_Builtin_1_result); } } - case T___builtin_return_address: { + case bk_gnu_builtin_return_address: { expression_t *const expression = call->arguments->expression; ir_node *in[2]; @@ -1644,17 +1710,18 @@ static ir_node *process_builtin_call(const call_expression_t *call) ir_node *irn = new_d_Builtin(dbgi, get_irg_no_mem(current_ir_graph), ir_bk_return_address, 2, in, tp); return new_Proj(irn, mode_P_data, pn_Builtin_1_result); } - case T___builtin_ffs: + case bk_gnu_builtin_ffs: return gen_unary_builtin(ir_bk_ffs, call->arguments->expression, function_type, dbgi); - case T___builtin_clz: + case bk_gnu_builtin_clz: return gen_unary_builtin(ir_bk_clz, call->arguments->expression, function_type, dbgi); - case T___builtin_ctz: + case bk_gnu_builtin_ctz: return gen_unary_builtin(ir_bk_ctz, call->arguments->expression, function_type, dbgi); - case T___builtin_popcount: + case bk_gnu_builtin_popcount: + case bk_ms__popcount: return gen_unary_builtin(ir_bk_popcount, call->arguments->expression, function_type, dbgi); - case T___builtin_parity: + case bk_gnu_builtin_parity: return gen_unary_builtin(ir_bk_parity, call->arguments->expression, function_type, dbgi); - case T___builtin_prefetch: { + case bk_gnu_builtin_prefetch: { call_argument_t *const args = call->arguments; expression_t *const addr = args->expression; ir_node *in[3]; @@ -1676,11 +1743,63 @@ static ir_node *process_builtin_call(const call_expression_t *call) in[1] = new_Const_long(mode_int, 0); in[2] = new_Const_long(mode_int, 3); } - ir_type *tp = get_ir_type((type_t*) function_type); + ir_type *tp = get_ir_type(function_type); ir_node *irn = new_d_Builtin(dbgi, get_store(), ir_bk_prefetch, 3, in, tp); set_store(new_Proj(irn, mode_M, pn_Builtin_M)); return NULL; } + case bk_gnu_builtin_trap: + case bk_ms__ud2: + { + ir_type *tp = get_ir_type(function_type); + ir_node *irn = new_d_Builtin(dbgi, get_store(), ir_bk_trap, 0, NULL, tp); + set_store(new_Proj(irn, mode_M, pn_Builtin_M)); + return NULL; + } + case bk_ms__debugbreak: { + ir_type *tp = get_ir_type(function_type); + ir_node *irn = new_d_Builtin(dbgi, get_store(), ir_bk_debugbreak, 0, NULL, tp); + set_store(new_Proj(irn, mode_M, pn_Builtin_M)); + return NULL; + } + case bk_ms_ReturnAddress: { + ir_node *in[2]; + + in[0] = new_Const_long(mode_int, 0); + in[1] = get_irg_frame(current_ir_graph); + ir_type *tp = get_ir_type(function_type); + ir_node *irn = new_d_Builtin(dbgi, get_irg_no_mem(current_ir_graph), ir_bk_return_address, 2, in, tp); + return new_Proj(irn, mode_P_data, pn_Builtin_1_result); + } + case bk_ms_rotl: + case bk_ms_rotl64: { + ir_node *val = expression_to_firm(call->arguments->expression); + ir_node *shf = expression_to_firm(call->arguments->next->expression); + ir_mode *mode = get_irn_mode(val); + return new_d_Rotl(dbgi, val, create_conv(dbgi, shf, mode_uint), mode); + } + case bk_ms_rotr: + case bk_ms_rotr64: { + ir_node *val = expression_to_firm(call->arguments->expression); + ir_node *shf = expression_to_firm(call->arguments->next->expression); + ir_mode *mode = get_irn_mode(val); + ir_node *c = new_Const_long(mode_uint, get_mode_size_bits(mode)); + ir_node *sub = new_d_Sub(dbgi, c, create_conv(dbgi, shf, mode_uint), mode_uint); + return new_d_Rotl(dbgi, val, sub, mode); + } + case bk_ms_byteswap_ushort: + case bk_ms_byteswap_ulong: + case bk_ms_byteswap_uint64: + return gen_unary_builtin(ir_bk_bswap, call->arguments->expression, function_type, dbgi); + case bk_ms__inbyte: + case bk_ms__inword: + case bk_ms__indword: + return gen_unary_builtin_pinned(ir_bk_inport, call->arguments->expression, function_type, dbgi); + case bk_ms__outbyte: + case bk_ms__outword: + case bk_ms__outdword: + return gen_binary_builtin_mem(ir_bk_outport, call->arguments->expression, + call->arguments->next->expression, function_type, dbgi); default: panic("unsupported builtin found"); } @@ -1699,13 +1818,15 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call) assert(get_cur_block() != NULL); expression_t *function = call->function; - if (function->kind == EXPR_BUILTIN_SYMBOL) { - return process_builtin_call(call); - } if (function->kind == EXPR_REFERENCE) { const reference_expression_t *ref = &function->reference; entity_t *entity = ref->entity; + if (ref->entity->kind == ENTITY_FUNCTION && + ref->entity->function.btk != bk_none) { + return process_builtin_call(call); + } + if (entity->kind == ENTITY_FUNCTION && entity->function.entity == rts_entities[rts_alloca]) { /* handle alloca() call */ @@ -3109,7 +3230,12 @@ static ir_node *va_start_expression_to_firm( new_d_simpleSel(dbgi, no_mem, arg_base, parm_ent); ir_node *const cnst = get_type_size(expr->parameter->base.type); - ir_node *const add = new_d_Add(dbgi, arg_sel, cnst, mode_P_data); + ir_mode *const mode = get_irn_mode(cnst); + ir_node *const c1 = new_Const_long(mode, stack_param_align - 1); + ir_node *const c2 = new_d_Add(dbgi, cnst, c1, mode); + ir_node *const c3 = new_Const_long(mode, -(long)stack_param_align); + ir_node *const c4 = new_d_And(dbgi, c2, c3, mode); + ir_node *const add = new_d_Add(dbgi, arg_sel, c2, mode_P_data); set_value_for_expression(expr->ap, add); return NULL; @@ -3125,7 +3251,12 @@ static ir_node *va_arg_expression_to_firm(const va_arg_expression_t *const expr) ir_node *const res = deref_address(dbgi, type, ap); ir_node *const cnst = get_type_size(expr->base.type); - ir_node *const add = new_d_Add(dbgi, ap, cnst, mode_P_data); + ir_mode *const mode = get_irn_mode(cnst); + ir_node *const c1 = new_Const_long(mode, stack_param_align - 1); + ir_node *const c2 = new_d_Add(dbgi, cnst, c1, mode); + ir_node *const c3 = new_Const_long(mode, -(long)stack_param_align); + ir_node *const c4 = new_d_And(dbgi, c2, c3, mode); + ir_node *const add = new_d_Add(dbgi, ap, c4, mode_P_data); set_value_for_expression_addr(ap_expr, add, ap_addr); @@ -3225,23 +3356,6 @@ static ir_node *label_address_to_firm( return new_SymConst(mode_P_code, value, symconst_label); } -static ir_node *builtin_symbol_to_firm( - const builtin_symbol_expression_t *expression) -{ - /* for gcc compatibility we have to produce (dummy) addresses for some - * builtins */ - if (warning.other) { - warningf(&expression->base.source_position, - "taking address of builtin '%Y'", expression->symbol); - } - - /* simply create a NULL pointer */ - ir_mode *mode = get_ir_mode_arithmetic(type_void_ptr); - ir_node *res = new_Const_long(mode, 0); - - return res; -} - /** * creates firm nodes for an expression. The difference between this function * and expression_to_firm is, that this version might produce mode_b nodes @@ -3297,8 +3411,6 @@ static ir_node *_expression_to_firm(const expression_t *expression) return va_start_expression_to_firm(&expression->va_starte); case EXPR_VA_ARG: return va_arg_expression_to_firm(&expression->va_arge); - case EXPR_BUILTIN_SYMBOL: - return builtin_symbol_to_firm(&expression->builtin_symbol); case EXPR_BUILTIN_CONSTANT_P: return builtin_constant_to_firm(&expression->builtin_constant); case EXPR_BUILTIN_TYPES_COMPATIBLE_P: @@ -3317,15 +3429,20 @@ static ir_node *_expression_to_firm(const expression_t *expression) panic("invalid expression found"); } +/** + * Check if a given expression is a GNU __builtin_expect() call. + */ static bool is_builtin_expect(const expression_t *expression) { if (expression->kind != EXPR_CALL) return false; expression_t *function = expression->call.function; - if (function->kind != EXPR_BUILTIN_SYMBOL) + if (function->kind != EXPR_REFERENCE) return false; - if (function->builtin_symbol.symbol->ID != T___builtin_expect) + reference_expression_t *ref = &function->reference; + if (ref->entity->kind != ENTITY_FUNCTION || + ref->entity->function.btk != bk_gnu_builtin_expect) return false; return true; @@ -5627,6 +5744,10 @@ static void scope_to_firm(scope_t *scope) continue; if (entity->kind == ENTITY_FUNCTION) { + if (entity->function.btk != bk_none) { + /* builtins have no representation */ + continue; + } get_function_entity(entity); } else if (entity->kind == ENTITY_VARIABLE) { create_global_variable(entity); @@ -5640,6 +5761,10 @@ static void scope_to_firm(scope_t *scope) continue; if (entity->kind == ENTITY_FUNCTION) { + if (entity->function.btk != bk_none) { + /* builtins have no representation */ + continue; + } create_function(entity); } else if (entity->kind == ENTITY_VARIABLE) { assert(entity->declaration.kind @@ -5692,6 +5817,8 @@ static void init_ir_types(void) const backend_params *be_params = be_get_backend_param(); mode_float_arithmetic = be_params->mode_float_arithmetic; + + stack_param_align = be_params->stack_param_align; } void exit_ast2firm(void)