/** * Adjust the size of a node representing a stack alloc to a certain * stack_alignment. * * @param size the node containing the non-aligned size * @param block the block where new nodes are allocated on * @return a node representing the aligned size */ static ir_node *adjust_alloc_size(dbg_info *dbgi, ir_node *size, ir_node *block) { /* Example: po2_alignment 4 (align to 16 bytes): * size = (size+15) & 0xfff...f8 */ ir_mode *mode = get_irn_mode(size); ir_graph *irg = get_irn_irg(block); ir_tarval *allone = get_mode_all_one(mode); ir_tarval *shr = tarval_shr_unsigned(allone, po2_stack_alignment); ir_tarval *mask = tarval_shl_unsigned(shr, po2_stack_alignment); ir_tarval *invmask = tarval_not(mask); ir_node *addv = new_r_Const(irg, invmask); ir_node *add = new_rd_Add(dbgi, block, size, addv); ir_node *maskc = new_r_Const(irg, mask); ir_node *and = new_rd_And(dbgi, block, add, maskc); return and; }
ir_tarval *fold_expression(expression_t const *const expr) { switch (expr->kind) { case EXPR_CONDITIONAL: { conditional_expression_t const *const cond = &expr->conditional; if (cond->true_expression != NULL) { /* note that we need this if in case of a complex expression as * condition */ bool condval = fold_expression_to_bool(cond->condition); expression_t *res = condval ? cond->true_expression : cond->false_expression; return fold_expression(res); } ir_tarval *const val = fold_expression(cond->condition); return tarval_is_null(val) ? fold_expression(cond->false_expression) : cond->true_expression ? fold_expression(cond->true_expression) : val; } case EXPR_SIZEOF: { type_t *const type = skip_typeref(expr->typeprop.type); ir_mode *const mode = get_ir_mode_arithmetic(skip_typeref(expr->base.type)); return get_type_size_tarval(type, mode); } case EXPR_ALIGNOF: return alignof_to_tarval( &expr->typeprop); case EXPR_BUILTIN_CONSTANT_P: return builtin_constant_to_tarval( &expr->builtin_constant); case EXPR_BUILTIN_TYPES_COMPATIBLE_P: return builtin_types_compatible_to_tarval(&expr->builtin_types_compatible); case EXPR_CLASSIFY_TYPE: return classify_type_to_tarval( &expr->classify_type); case EXPR_ENUM_CONSTANT: return enum_constant_to_tarval( &expr->reference); case EXPR_LITERAL_CASES: return literal_to_tarval( &expr->literal); case EXPR_LITERAL_CHARACTER: return char_literal_to_tarval( &expr->string_literal); case EXPR_OFFSETOF: return offsetof_to_tarval( &expr->offsetofe); case EXPR_UNARY_TAKE_ADDRESS: return fold_expression_to_address( expr->unary.value); case EXPR_UNARY_NEGATE: return tarval_neg(fold_expression(expr->unary.value)); case EXPR_UNARY_PLUS: return fold_expression(expr->unary.value); case EXPR_UNARY_COMPLEMENT: return tarval_not(fold_expression(expr->unary.value)); case EXPR_UNARY_NOT: { type_t *const type = skip_typeref(expr->base.type); ir_mode *const mode = get_ir_mode_arithmetic(type); ir_tarval *const val = fold_expression(expr->unary.value); return create_tarval_from_bool(mode, tarval_is_null(val)); } case EXPR_UNARY_CAST: { type_t *const type = skip_typeref(expr->base.type); ir_mode *const mode = get_ir_mode_arithmetic(type); ir_tarval *const val = fold_expression(expr->unary.value); if (is_type_atomic(type, ATOMIC_TYPE_BOOL)) { return create_tarval_from_bool(mode, !tarval_is_null(val)); } else { return tarval_convert_to(val, mode); } } case EXPR_BINARY_EQUAL: case EXPR_BINARY_NOTEQUAL: case EXPR_BINARY_LESS: case EXPR_BINARY_LESSEQUAL: case EXPR_BINARY_GREATER: case EXPR_BINARY_GREATEREQUAL: case EXPR_BINARY_ISGREATER: case EXPR_BINARY_ISGREATEREQUAL: case EXPR_BINARY_ISLESS: case EXPR_BINARY_ISLESSEQUAL: case EXPR_BINARY_ISLESSGREATER: case EXPR_BINARY_ISUNORDERED: return fold_binary_comparison(&expr->binary); case EXPR_BINARY_ADD: return fold_binary_add(&expr->binary); case EXPR_BINARY_SUB: return fold_binary_sub(&expr->binary); case EXPR_BINARY_MUL: return fold_binary_expression_arithmetic(&expr->binary, tarval_mul); case EXPR_BINARY_DIV: return fold_binary_expression_arithmetic(&expr->binary, tarval_div); case EXPR_BINARY_MOD: return fold_binary_expression_arithmetic(&expr->binary, tarval_mod); case EXPR_BINARY_BITWISE_OR: return fold_binary_expression_arithmetic(&expr->binary, tarval_or); case EXPR_BINARY_BITWISE_AND: return fold_binary_expression_arithmetic(&expr->binary, tarval_and); case EXPR_BINARY_BITWISE_XOR: return fold_binary_expression_arithmetic(&expr->binary, tarval_eor); case EXPR_BINARY_SHIFTLEFT: return fold_binary_expression_arithmetic(&expr->binary, tarval_shl); case EXPR_BINARY_SHIFTRIGHT: { fold_binary_func fold = is_type_signed(skip_typeref(expr->base.type)) ? tarval_shrs : tarval_shr; return fold_binary_expression_arithmetic(&expr->binary, fold); } case EXPR_BINARY_LOGICAL_AND: { bool const c = !tarval_is_null(fold_expression(expr->binary.left)) && !tarval_is_null(fold_expression(expr->binary.right)); type_t *const type = skip_typeref(expr->base.type); ir_mode *const mode = get_ir_mode_arithmetic(type); return create_tarval_from_bool(mode, c); } case EXPR_BINARY_LOGICAL_OR: { bool const c = !tarval_is_null(fold_expression(expr->binary.left)) || !tarval_is_null(fold_expression(expr->binary.right)); type_t *const type = skip_typeref(expr->base.type); ir_mode *const mode = get_ir_mode_arithmetic(type); return create_tarval_from_bool(mode, c); } case EXPR_UNARY_REAL: { complex_constant cnst = fold_complex(expr->unary.value); return cnst.real; } case EXPR_UNARY_IMAG: { complex_constant cnst = fold_complex(expr->unary.value); return cnst.imag; } case EXPR_CALL: return fold_call_builtin(&expr->call); case EXPR_ARRAY_ACCESS: case EXPR_BINARY_ADD_ASSIGN: case EXPR_BINARY_ASSIGN: case EXPR_BINARY_BITWISE_AND_ASSIGN: case EXPR_BINARY_BITWISE_OR_ASSIGN: case EXPR_BINARY_BITWISE_XOR_ASSIGN: case EXPR_BINARY_COMMA: case EXPR_BINARY_DIV_ASSIGN: case EXPR_BINARY_MOD_ASSIGN: case EXPR_BINARY_MUL_ASSIGN: case EXPR_BINARY_SHIFTLEFT_ASSIGN: case EXPR_BINARY_SHIFTRIGHT_ASSIGN: case EXPR_BINARY_SUB_ASSIGN: case EXPR_COMPOUND_LITERAL: case EXPR_ERROR: case EXPR_FUNCNAME: case EXPR_LABEL_ADDRESS: case EXPR_REFERENCE: case EXPR_SELECT: case EXPR_STATEMENT: case EXPR_STRING_LITERAL: case EXPR_UNARY_ASSUME: case EXPR_UNARY_DELETE: case EXPR_UNARY_DELETE_ARRAY: case EXPR_UNARY_DEREFERENCE: case EXPR_UNARY_POSTFIX_DECREMENT: case EXPR_UNARY_POSTFIX_INCREMENT: case EXPR_UNARY_PREFIX_DECREMENT: case EXPR_UNARY_PREFIX_INCREMENT: case EXPR_UNARY_THROW: case EXPR_VA_ARG: case EXPR_VA_COPY: case EXPR_VA_START: panic("invalid expression kind for constant folding"); } panic("unexpected expression kind for constant folding"); }