void lower_CopyB(ir_graph *irg, unsigned max_small_sz, unsigned min_large_sz, int allow_misaligns) { const backend_params *bparams = be_get_backend_param(); assert(max_small_sz < min_large_sz && "CopyB size ranges must not overlap"); max_small_size = max_small_sz; min_large_size = min_large_sz; native_mode_bytes = bparams->machine_size / 8; allow_misalignments = allow_misaligns; walk_env_t env = { .copybs = NEW_ARR_F(ir_node*, 0) }; irg_walk_graph(irg, NULL, find_copyb_nodes, &env); bool changed = false; for (size_t i = 0, n = ARR_LEN(env.copybs); i != n; ++i) { lower_copyb_node(env.copybs[i]); changed = true; } confirm_irg_properties(irg, changed ? IR_GRAPH_PROPERTIES_CONTROL_FLOW : IR_GRAPH_PROPERTIES_ALL); DEL_ARR_F(env.copybs); }
void init_constfold(void) { tarval_set_wrap_on_overflow(true); const backend_params *be_params = be_get_backend_param(); /* initialize modes for arithmetic types */ memset(atomic_modes, 0, sizeof(atomic_modes)); const ir_type *const type_ld = be_params->type_long_double; if (type_ld != NULL) atomic_modes[ATOMIC_TYPE_LONG_DOUBLE] = get_type_mode(type_ld); mode_float_arithmetic = be_params->mode_float_arithmetic; for (int i = 0; i <= ATOMIC_TYPE_LAST; ++i) { if (atomic_modes[i] != NULL) continue; atomic_modes[i] = init_atomic_ir_mode((atomic_type_kind_t) i); } }
/** * Transforms a Cmp into the appropriate soft float function. */ static bool lower_Cmp(ir_node *const n) { ir_node *const left = get_Cmp_left(n); ir_mode *const op_mode = get_irn_mode(left); if (!mode_is_float(op_mode)) return false; dbg_info *const dbgi = get_irn_dbg_info(n); ir_graph *const irg = get_irn_irg(n); ir_node *const zero = new_rd_Const_null(dbgi, irg, mode_Is); char const *name = NULL; char const *name2 = NULL; ir_node *result = NULL; ir_relation relation = get_Cmp_relation(n); switch (relation) { case ir_relation_false: result = zero; break; case ir_relation_equal: name = "eq"; break; case ir_relation_less: name = "lt"; break; case ir_relation_greater: name = "gt"; break; case ir_relation_unordered: name = "unord"; relation = ir_relation_less_greater; break; case ir_relation_less_equal: name = "le"; break; case ir_relation_greater_equal: name = "ge"; break; case ir_relation_less_greater: name = "unord"; name2 = "ne"; break; case ir_relation_less_equal_greater: name = "unord"; relation = ir_relation_equal; break; case ir_relation_unordered_equal: name = "unord"; relation = ir_relation_less_greater; name2 = "ne"; break; case ir_relation_unordered_less: name = "ge"; relation = ir_relation_less; break; case ir_relation_unordered_less_equal: name = "gt"; relation = ir_relation_less_equal; break; case ir_relation_unordered_greater: name = "le"; relation = ir_relation_greater; break; case ir_relation_unordered_greater_equal: name = "lt"; relation = ir_relation_greater_equal; break; case ir_relation_unordered_less_greater: name = "eq"; relation = ir_relation_less_greater; break; case ir_relation_true: result = zero; break; } ir_node *const block = get_nodes_block(n); ir_node *const right = get_Cmp_right(n); if (result == NULL) { ir_node *const in[] = { left, right }; result = make_softfloat_call(n, name, ARRAY_SIZE(in), in); } ir_node *cmp = new_r_Cmp(block, result, zero, relation); /* We need two calls into the softfloat library */ if (name2 != NULL) { ir_node *const in[] = { left, right }; result = make_softfloat_call(n, name2, ARRAY_SIZE(in), in); relation = get_Cmp_relation(n); ir_node *const mux = new_rd_Mux(dbgi, block, cmp, result, zero); arch_allow_ifconv_func const allow_ifconv = be_get_backend_param()->allow_ifconv; if (!allow_ifconv(cmp, result, zero)) ir_nodeset_insert(&created_mux_nodes, mux); cmp = new_r_Cmp(block, mux, zero, relation); } exchange(n, cmp); return true; }
static bool pass_options_to_firm_be(void) { switch (target.object_format) { case OBJECT_FORMAT_ELF: set_be_option("objectformat=elf"); break; case OBJECT_FORMAT_MACH_O: set_be_option("objectformat=mach-o"); break; case OBJECT_FORMAT_PE_COFF: set_be_option("objectformat=coff"); break; } if (profile_generate) { driver_add_flag(&ldflags_obst, "-lfirmprof"); set_be_option("profilegenerate"); } if (profile_use) { set_be_option("profileuse"); } bool res = true; const char *pic_option; if (target.pic_mode > 0) { /* Select correct PIC mode */ if (target.object_format == OBJECT_FORMAT_MACH_O) { pic_option = "pic=mach-o"; } else { pic_option = target.pic_no_plt ? "pic=elf-noplt" : "pic=elf"; } } else { pic_option = "pic=none"; } set_be_option(pic_option); /* pass options to firm backend (this happens delayed because we first * had to decide which backend is actually used) */ for (codegen_option_t *option = codegen_options; option != NULL; option = option->next) { char buf[256]; const char *opt = option->option; /* pass option along to firm backend (except the -m32, -m64 stuff) */ snprintf(buf, sizeof(buf), "%s-%s", target.firm_isa, opt); if (be_parse_arg(buf) == 0) { errorf(NULL, "Unknown codegen option '-m%s'", opt); res = false; continue; } /* hack to emulate the behaviour of some gcc spec files which filter * flags to pass to cpp/ld/as */ static char const *const pass_to_cpp_and_ld[] = { "soft-float" }; for (size_t i = 0; i < ARRAY_SIZE(pass_to_cpp_and_ld); ++i) { if (streq(pass_to_cpp_and_ld[i], option->option)) { snprintf(buf, sizeof(buf), "-m%s", option->option); driver_add_flag(&cppflags_obst, buf); driver_add_flag(&asflags_obst, buf); driver_add_flag(&ldflags_obst, buf); break; } } } /* We can initialize the backend at this point and call be_get_backend_param() */ if (target.pic_mode > 0 && !be_get_backend_param()->pic_supported) { errorf(NULL, "Selected backend '%s' does not support position independent code (PIC)", target.firm_isa); res = false; } return res; }
void target_adjust_types_and_dialect(void) { init_types(dialect.int_size, dialect.long_size, dialect.pointer_size); atomic_type_properties_t *props = atomic_type_properties; /* Adjustments for some systems */ props[ATOMIC_TYPE_LONGLONG].size = dialect.long_long_size; props[ATOMIC_TYPE_LONGLONG].alignment = dialect.long_long_size; props[ATOMIC_TYPE_LONGLONG].struct_alignment = dialect.long_long_size; props[ATOMIC_TYPE_ULONGLONG].size = dialect.long_long_size; props[ATOMIC_TYPE_ULONGLONG].alignment = dialect.long_long_size; props[ATOMIC_TYPE_ULONGLONG].struct_alignment = dialect.long_long_size; unsigned const ll_d_struct_align = dialect.long_long_and_double_struct_align; if (ll_d_struct_align > 0) { props[ATOMIC_TYPE_LONGLONG].struct_alignment = ll_d_struct_align; props[ATOMIC_TYPE_ULONGLONG].struct_alignment = ll_d_struct_align; props[ATOMIC_TYPE_DOUBLE].struct_alignment = ll_d_struct_align; } unsigned const size = dialect.long_double_size; unsigned const alignment = size == 12 && dialect.long_double_x87_80bit_float ? 4 : size; props[ATOMIC_TYPE_LONG_DOUBLE].size = size; props[ATOMIC_TYPE_LONG_DOUBLE].alignment = alignment; props[ATOMIC_TYPE_LONG_DOUBLE].struct_alignment = alignment; /* stuff decided after processing operating system specifics and * commandline flags */ if (dialect.char_is_signed) { props[ATOMIC_TYPE_CHAR].flags |= ATOMIC_TYPE_FLAG_SIGNED; } else { props[ATOMIC_TYPE_CHAR].flags &= ~ATOMIC_TYPE_FLAG_SIGNED; } /* copy over wchar_t properties (including rank) */ props[ATOMIC_TYPE_WCHAR_T] = props[dialect.wchar_atomic_kind]; static bool had_cpp_warning; if (dialect.cpp && !had_cpp_warning) { warningf(WARN_EXPERIMENTAL, NULL, "C++ support is highly experimental and unfinished"); had_cpp_warning = true; } if (target.firm_isa_specified) { backend_params const *const p = be_get_backend_param(); target.float_int_overflow = p->float_int_overflow; target.byte_order_big_endian = p->byte_order_big_endian; dialect.pointer_size = p->machine_size / BITS_PER_BYTE; } else { /* The frontend should do all decisions and should not be influenced by * outside influences like the firm backend. So we just check here that * our decisions match the firm backend. */ assert(be_get_backend_param()->machine_size % BITS_PER_BYTE == 0); assert(dialect.pointer_size == be_get_backend_param()->machine_size / BITS_PER_BYTE); assert(target.byte_order_big_endian == be_get_backend_param()->byte_order_big_endian); assert(target.float_int_overflow == be_get_backend_param()->float_int_overflow); } }
void init_predefined_types(void) { static const type_base_t error = { TYPE_ERROR, TYPE_QUALIFIER_NONE, NULL }; type_error_type = (type_t*)&error; type_bool = make_atomic_type(ATOMIC_TYPE_BOOL, TYPE_QUALIFIER_NONE); type_signed_char = make_atomic_type(ATOMIC_TYPE_SCHAR, TYPE_QUALIFIER_NONE); type_unsigned_char = make_atomic_type(ATOMIC_TYPE_UCHAR, TYPE_QUALIFIER_NONE); type_short = make_atomic_type(ATOMIC_TYPE_SHORT, TYPE_QUALIFIER_NONE); type_unsigned_short = make_atomic_type(ATOMIC_TYPE_USHORT, TYPE_QUALIFIER_NONE); type_int = make_atomic_type(ATOMIC_TYPE_INT, TYPE_QUALIFIER_NONE); type_unsigned_int = make_atomic_type(ATOMIC_TYPE_UINT, TYPE_QUALIFIER_NONE); type_long = make_atomic_type(ATOMIC_TYPE_LONG, TYPE_QUALIFIER_NONE); type_unsigned_long = make_atomic_type(ATOMIC_TYPE_ULONG, TYPE_QUALIFIER_NONE); type_long_long = make_atomic_type(ATOMIC_TYPE_LONGLONG, TYPE_QUALIFIER_NONE); type_unsigned_long_long = make_atomic_type(ATOMIC_TYPE_ULONGLONG, TYPE_QUALIFIER_NONE); type_long_double = make_atomic_type(ATOMIC_TYPE_LONG_DOUBLE, TYPE_QUALIFIER_NONE); type_double = make_atomic_type(ATOMIC_TYPE_DOUBLE, TYPE_QUALIFIER_NONE); type_float = make_atomic_type(ATOMIC_TYPE_FLOAT, TYPE_QUALIFIER_NONE); type_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_NONE); type_void = make_void_type(TYPE_QUALIFIER_NONE); type_const_void = make_void_type(TYPE_QUALIFIER_CONST); type_builtin_template = allocate_type_zero(TYPE_BUILTIN_TEMPLATE); type_builtin_template = identify_new_type(type_builtin_template); int8_type_kind = find_signed_int_atomic_type_kind_for_size(1); int16_type_kind = find_signed_int_atomic_type_kind_for_size(2); int32_type_kind = find_signed_int_atomic_type_kind_for_size(4); int64_type_kind = find_signed_int_atomic_type_kind_for_size(8); type_int32_t = make_atomic_type(int32_type_kind, TYPE_QUALIFIER_NONE); type_int64_t = make_atomic_type(int64_type_kind, TYPE_QUALIFIER_NONE); /* pointer types */ type_void_ptr = make_pointer_type(type_void, TYPE_QUALIFIER_NONE); type_const_void_ptr = make_pointer_type(type_const_void, TYPE_QUALIFIER_NONE); type_void_ptr_restrict = make_pointer_type(type_void, TYPE_QUALIFIER_RESTRICT); type_const_void_ptr_restrict = make_pointer_type(type_const_void, TYPE_QUALIFIER_RESTRICT); type_char_ptr = make_pointer_type(type_char, TYPE_QUALIFIER_NONE); type_char_ptr_restrict = make_pointer_type(type_char, TYPE_QUALIFIER_RESTRICT); type_signed_char_ptr = make_pointer_type(type_signed_char, TYPE_QUALIFIER_NONE); type_short_ptr = make_pointer_type(type_short, TYPE_QUALIFIER_NONE); type_int_ptr = make_pointer_type(type_int, TYPE_QUALIFIER_NONE); type_long_ptr = make_pointer_type(type_long, TYPE_QUALIFIER_NONE); type_unsigned_char_ptr = make_pointer_type(type_unsigned_char, TYPE_QUALIFIER_NONE); type_unsigned_short_ptr = make_pointer_type(type_unsigned_short, TYPE_QUALIFIER_NONE); type_unsigned_int_ptr = make_pointer_type(type_unsigned_int, TYPE_QUALIFIER_NONE); type_unsigned_long_ptr = make_pointer_type(type_unsigned_long, TYPE_QUALIFIER_NONE); type_unsigned_long_long_ptr = make_pointer_type(type_unsigned_long, TYPE_QUALIFIER_NONE); type_long_long_ptr = make_pointer_type(type_long_long, TYPE_QUALIFIER_NONE); type_long_double_ptr = make_pointer_type(type_long_double, TYPE_QUALIFIER_NONE); type_double_ptr = make_pointer_type(type_double, TYPE_QUALIFIER_NONE); type_float_ptr = make_pointer_type(type_float, TYPE_QUALIFIER_NONE); type_char_ptr_ptr = make_pointer_type(type_char_ptr, TYPE_QUALIFIER_NONE); type_builtin_template_ptr = make_pointer_type(type_builtin_template, TYPE_QUALIFIER_NONE); backend_params const *const be_params = be_get_backend_param(); ir_type *be_va_list_type = be_params->vararg.va_list_type; if (!be_va_list_type) { /* Backend has no vararg support. Just hope the the program will not be * using any. If it does, the parse_va_* functions will complain. */ type_valist = type_error_type; type_valist_arg = type_error_type; } else if (is_Pointer_type(be_va_list_type)) { type_valist = type_void_ptr; type_valist_arg = type_void_ptr; } else if (is_Struct_type(be_va_list_type)) { entity_t *ent = allocate_entity_zero(ENTITY_STRUCT, NAMESPACE_NORMAL, sym_anonymous, &builtin_position); ent->compound.alignment = get_type_alignment_bytes(be_va_list_type); ent->compound.size = get_type_size_bytes(be_va_list_type); ent->compound.complete = true; ent->compound.members = (scope_t){ .first_entity = NULL, .last_entity = NULL, .depth = 0 }; type_t *type_valist_struct = allocate_type_zero(TYPE_COMPOUND_STRUCT); type_valist_struct->base.firm_type = be_va_list_type; type_valist_struct->compound.compound = &ent->compound; type_valist = make_array_type(type_valist_struct, 1, TYPE_QUALIFIER_NONE); type_valist_arg = automatic_type_conversion(type_valist); } /* const character types */ type_const_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST); type_const_char_ptr = make_pointer_type(type_const_char, TYPE_QUALIFIER_NONE); type_const_char_ptr_restrict = make_pointer_type(type_const_char, TYPE_QUALIFIER_RESTRICT); atomic_type_kind_t pointer_sized_int = dialect.pointer_sized_int; atomic_type_kind_t pointer_sized_uint = dialect.pointer_sized_uint; type_size_t = make_atomic_type(pointer_sized_uint, TYPE_QUALIFIER_NONE); type_ssize_t = make_atomic_type(pointer_sized_int, TYPE_QUALIFIER_NONE); type_uptrdiff_t = type_size_t; type_ptrdiff_t = type_ssize_t; type_intmax_t = type_long_long; type_uintmax_t = type_unsigned_long_long; type_wint_t = type_unsigned_int; type_intmax_t_ptr = make_pointer_type(type_intmax_t, TYPE_QUALIFIER_NONE); type_uintmax_t_ptr = make_pointer_type(type_uintmax_t, TYPE_QUALIFIER_NONE); type_ptrdiff_t_ptr = make_pointer_type(type_ptrdiff_t, TYPE_QUALIFIER_NONE); type_uptrdiff_t_ptr = make_pointer_type(type_uptrdiff_t, TYPE_QUALIFIER_NONE); type_ssize_t_ptr = make_pointer_type(type_ssize_t, TYPE_QUALIFIER_NONE); type_size_t_ptr = make_pointer_type(type_size_t, TYPE_QUALIFIER_NONE); atomic_type_kind_t akind = dialect.cpp ? ATOMIC_TYPE_WCHAR_T : dialect.wchar_atomic_kind; type_wchar_t = make_atomic_type(akind, TYPE_QUALIFIER_NONE); type_const_wchar_t = make_atomic_type(akind, TYPE_QUALIFIER_CONST); type_wchar_t_ptr = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE); type_const_wchar_t_ptr = make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE); atomic_type_kind_t const u2 = find_unsigned_int_atomic_type_kind_for_size(2); type_char16_t = make_atomic_type(u2, TYPE_QUALIFIER_NONE); type_char16_t_const = make_atomic_type(u2, TYPE_QUALIFIER_CONST); type_char16_t_ptr = make_pointer_type(type_char16_t, TYPE_QUALIFIER_NONE); type_char16_t_const_ptr = make_pointer_type(type_char16_t_const, TYPE_QUALIFIER_NONE); atomic_type_kind_t const u4 = find_unsigned_int_atomic_type_kind_for_size(4); type_char32_t = make_atomic_type(u4, TYPE_QUALIFIER_NONE); type_char32_t_const = make_atomic_type(u4, TYPE_QUALIFIER_CONST); type_char32_t_ptr = make_pointer_type(type_char32_t, TYPE_QUALIFIER_NONE); type_char32_t_const_ptr = make_pointer_type(type_char32_t_const, TYPE_QUALIFIER_NONE); if (dialect.ms) init_ms_types(); }