bool types_compatible_ignore_qualifiers(const type_t *type1, const type_t *type2) { assert(!is_typeref(type1)); assert(!is_typeref(type2)); /* shortcut: the same type is always compatible */ if (type1 == type2) return true; if (type1->kind != type2->kind) { /* enum types are compatible to their base integer type */ if ((type1->kind == TYPE_ENUM && is_type_atomic(type2, type1->enumt.base.akind)) || (type2->kind == TYPE_ENUM && is_type_atomic(type1, type2->enumt.base.akind))) return true; /* error types are compatible to everything to avoid follow-up errors */ if (!is_type_valid(type1) || !is_type_valid(type2)) return true; return false; } switch (type1->kind) { case TYPE_FUNCTION: return function_types_compatible(&type1->function, &type2->function); case TYPE_ATOMIC: case TYPE_IMAGINARY: case TYPE_COMPLEX: return type1->atomic.akind == type2->atomic.akind; case TYPE_ARRAY: return array_types_compatible(&type1->array, &type2->array); case TYPE_POINTER: { const type_t *const to1 = skip_typeref(type1->pointer.points_to); const type_t *const to2 = skip_typeref(type2->pointer.points_to); return types_compatible(to1, to2); } case TYPE_REFERENCE: { const type_t *const to1 = skip_typeref(type1->reference.refers_to); const type_t *const to2 = skip_typeref(type2->reference.refers_to); return types_compatible(to1, to2); } case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: return type1->compound.compound == type2->compound.compound; case TYPE_ENUM: return type1->enumt.enume == type2->enumt.enume; case TYPE_ERROR: case TYPE_VOID: return true; case TYPE_TYPEDEF: case TYPE_TYPEOF: break; /* we already tested for is_typeref() above */ case TYPE_BUILTIN_TEMPLATE: panic("unexpected type"); } panic("invalid type kind"); }
type_t *get_default_promoted_type(type_t *orig_type) { type_t *result = orig_type; type_t *type = skip_typeref(orig_type); if (is_type_integer(type)) { result = promote_integer(type); } else if (is_type_atomic(type, ATOMIC_TYPE_FLOAT)) { result = type_double; } return result; }
static void write_pointer_type(const pointer_type_t *type) { type_t *orig_points_to = type->points_to; type_t *points_to = skip_typeref(type->points_to); if (is_type_atomic(points_to, ATOMIC_TYPE_CHAR) && orig_points_to->kind != TYPE_TYPEDEF) { fputs("String", out); return; } if (is_type_pointer(points_to)) { /* hack... */ fputs("java.nio.Buffer", out); return; } fputs("Pointer", out); }
static void write_function(const entity_t *entity) { if (entity->function.statement != NULL) { fprintf(stderr, "Warning: can't convert function bodies (at %s)\n", entity->base.symbol->string); } fprintf(out, "func extern %s(", entity->base.symbol->string); const function_type_t *function_type = (const function_type_t*) entity->declaration.type; entity_t *parameter = entity->function.parameters.entities; int first = 1; for( ; parameter != NULL; parameter = parameter->base.next) { assert(parameter->kind == ENTITY_PARAMETER); if(!first) { fprintf(out, ", "); } else { first = 0; } if(parameter->base.symbol != NULL) { fprintf(out, "%s : ", parameter->base.symbol->string); } else { fputs("_ : ", out); } write_type(parameter->declaration.type); } if(function_type->variadic) { if(!first) { fprintf(out, ", "); } else { first = 0; } fputs("...", out); } fprintf(out, ")"); const type_t *return_type = skip_typeref(function_type->return_type); if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { fprintf(out, " : "); write_type(return_type); } fputc('\n', out); }
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"); }