Exemple #1
0
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);
	}
}
Exemple #3
0
/**
 * 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;
}
Exemple #4
0
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;
}
Exemple #5
0
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);
	}
}
Exemple #6
0
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();
}