Пример #1
0
ir_graph *create_irg_copy(ir_graph *irg)
{
	ir_graph *res = alloc_graph();

	res->irg_pinned_state = irg->irg_pinned_state;

	/* clone the frame type here for safety */
	irp_reserve_resources(irp, IRP_RESOURCE_ENTITY_LINK);
	res->frame_type  = clone_frame_type(irg->frame_type);

	ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);

	/* copy all nodes from the graph irg to the new graph res */
	irg_walk_anchors(irg, copy_all_nodes, rewire, res);

	/* copy the Anchor node */
	res->anchor = get_new_node(irg->anchor);

	/* -- The end block -- */
	set_irg_end_block (res, get_new_node(get_irg_end_block(irg)));
	set_irg_end       (res, get_new_node(get_irg_end(irg)));

	/* -- The start block -- */
	set_irg_start_block(res, get_new_node(get_irg_start_block(irg)));
	set_irg_no_mem     (res, get_new_node(get_irg_no_mem(irg)));
	set_irg_start      (res, get_new_node(get_irg_start(irg)));

	/* Proj results of start node */
	set_irg_initial_mem(res, get_new_node(get_irg_initial_mem(irg)));

	ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
	irp_free_resources(irp, IRP_RESOURCE_ENTITY_LINK);

	return res;
}
Пример #2
0
/**
 * Copies a node to a new irg. The Ins of the new node point to
 * the predecessors on the old irg.  n->link points to the new node.
 *
 * @param n    The node to be copied
 * @param irg  the new irg
 *
 * Does NOT copy standard nodes like Start, End etc that are fixed
 * in an irg. Instead, the corresponding nodes of the new irg are returned.
 * Note further, that the new nodes have no block.
 */
static void copy_irn_to_irg(ir_node *n, ir_graph *irg)
{
    /* do not copy standard nodes */
    ir_node *nn = NULL;
    switch (get_irn_opcode(n)) {
    case iro_NoMem:
        nn = get_irg_no_mem(irg);
        break;

    case iro_Block: {
        ir_graph *old_irg = get_irn_irg(n);
        if (n == get_irg_start_block(old_irg))
            nn = get_irg_start_block(irg);
        else if (n == get_irg_end_block(old_irg))
            nn = get_irg_end_block(irg);
        break;
    }

    case iro_Start:
        nn = get_irg_start(irg);
        break;

    case iro_End:
        nn = get_irg_end(irg);
        break;

    case iro_Proj: {
        ir_graph *old_irg = get_irn_irg(n);
        if (n == get_irg_frame(old_irg))
            nn = get_irg_frame(irg);
        else if (n == get_irg_initial_mem(old_irg))
            nn = get_irg_initial_mem(irg);
        else if (n == get_irg_args(old_irg))
            nn = get_irg_args(irg);
        break;
    }
    }

    if (nn) {
        set_irn_link(n, nn);
        return;
    }

    nn = new_ir_node(get_irn_dbg_info(n),
                     irg,
                     NULL,            /* no block yet, will be set later */
                     get_irn_op(n),
                     get_irn_mode(n),
                     get_irn_arity(n),
                     get_irn_in(n));


    /* Copy the attributes.  These might point to additional data.  If this
       was allocated on the old obstack the pointers now are dangling.  This
       frees e.g. the memory of the graph_arr allocated in new_immBlock. */
    copy_node_attr(irg, n, nn);
    set_irn_link(n, nn);
}
Пример #3
0
static ir_node *create_fpu_mode_reload(void *const env, ir_node *const state, ir_node *const spill, ir_node *const before, ir_node *const last_state)
{
	(void)env;
	(void)state;

	ir_node        *reload;
	ir_node  *const block = get_nodes_block(before);
	ir_graph *const irg   = get_irn_irg(block);
	ir_node  *const noreg = ia32_new_NoReg_gp(irg);
	ir_node  *const nomem = get_irg_no_mem(irg);
	if (ia32_cg_config.use_unsafe_floatconv) {
		reload = new_bd_ia32_FldCW(NULL, block, noreg, noreg, nomem);
		ir_entity *const rounding_mode = spill ?
			create_ent(&fpcw_round,    0xC7F, "_fpcw_round") :
			create_ent(&fpcw_truncate, 0x37F, "_fpcw_truncate");
		set_ia32_am_ent(reload, rounding_mode);
	} else {
		ir_node       *mem;
		ir_node *const frame = get_irg_frame(irg);
		if (spill) {
			mem = spill;
		} else {
			assert(last_state);
			ir_node *const cwstore = create_fnstcw(block, frame, noreg, nomem, last_state);
			sched_add_before(before, cwstore);

			ir_node *const load = new_bd_ia32_Load(NULL, block, frame, noreg, cwstore);
			set_ia32_op_type(load, ia32_AddrModeS);
			set_ia32_ls_mode(load, mode_Hu);
			set_ia32_frame_use(load, IA32_FRAME_USE_32BIT);
			sched_add_before(before, load);

			ir_node *const load_res = new_r_Proj(load, ia32_mode_gp, pn_ia32_Load_res);

			/* TODO: Make the actual mode configurable in ChangeCW. */
			ir_node *const or_const = ia32_create_Immediate(irg, 0xC00);
			ir_node *const orn      = new_bd_ia32_Or(NULL, block, noreg, noreg, nomem, load_res, or_const);
			sched_add_before(before, orn);

			ir_node *const store = new_bd_ia32_Store(NULL, block, frame, noreg, nomem, orn);
			set_ia32_op_type(store, ia32_AddrModeD);
			/* Use ia32_mode_gp, as movl has a shorter opcode than movw. */
			set_ia32_ls_mode(store, ia32_mode_gp);
			set_ia32_frame_use(store, IA32_FRAME_USE_32BIT);
			sched_add_before(before, store);
			mem = new_r_Proj(store, mode_M, pn_ia32_Store_M);
		}

		reload = new_bd_ia32_FldCW(NULL, block, frame, noreg, mem);
	}

	set_ia32_op_type(reload, ia32_AddrModeS);
	set_ia32_ls_mode(reload, ia32_mode_fpcw);
	set_ia32_frame_use(reload, IA32_FRAME_USE_32BIT);
	arch_set_irn_register(reload, &ia32_registers[REG_FPCW]);
	sched_add_before(before, reload);
	return reload;
}
Пример #4
0
/** patches Addresses to work in position independent code */
static void fix_pic_addresses(ir_node *const node, void *const data)
{
	(void)data;

	ir_graph      *const irg = get_irn_irg(node);
	be_main_env_t *const be  = be_get_irg_main_env(irg);
	foreach_irn_in(node, i, pred) {
		if (!is_Address(pred))
			continue;

		ir_node         *res;
		ir_entity *const entity = get_Address_entity(pred);
		dbg_info  *const dbgi   = get_irn_dbg_info(pred);
		if (i == n_Call_ptr && is_Call(node)) {
			/* Calls can jump to relative addresses, so we can directly jump to
			 * the (relatively) known call address or the trampoline */
			if (can_address_relative(entity))
				continue;

			ir_entity *const trampoline = get_trampoline(be, entity);
			res = new_rd_Address(dbgi, irg, trampoline);
		} else if (get_entity_type(entity) == get_code_type()) {
			/* Block labels can always be addressed directly. */
			continue;
		} else {
			/* Everything else is accessed relative to EIP. */
			ir_node *const block    = get_nodes_block(pred);
			ir_mode *const mode     = get_irn_mode(pred);
			ir_node *const pic_base = ia32_get_pic_base(irg);

			if (can_address_relative(entity)) {
				/* All ok now for locally constructed stuff. */
				res = new_rd_Add(dbgi, block, pic_base, pred, mode);
				/* Make sure the walker doesn't visit this add again. */
				mark_irn_visited(res);
			} else {
				/* Get entry from pic symbol segment. */
				ir_entity *const pic_symbol  = get_pic_symbol(be, entity);
				ir_node   *const pic_address = new_rd_Address(dbgi, irg, pic_symbol);
				ir_node   *const add         = new_rd_Add(dbgi, block, pic_base, pic_address, mode);
				mark_irn_visited(add);

				/* We need an extra indirection for global data outside our current
				 * module. The loads are always safe and can therefore float and
				 * need no memory input */
				ir_type *const type  = get_entity_type(entity);
				ir_node *const nomem = get_irg_no_mem(irg);
				ir_node *const load  = new_rd_Load(dbgi, block, nomem, add, mode, type, cons_floats);
				res = new_r_Proj(load, mode, pn_Load_res);
			}
		}
		set_irn_n(node, i, res);
	}
}
Пример #5
0
static ir_node *create_gotpcrel_load(ir_graph  *irg, ir_entity *const entity)
{
	ir_node *const addr
		= be_new_Relocation(irg, X86_IMM_GOTPCREL, entity, mode_P);
	ir_type *const type  = get_entity_type(entity);
	ir_node *const nomem = get_irg_no_mem(irg);
	ir_node *const block = get_irg_start_block(irg);
	ir_node *const load  = new_rd_Load(NULL, block, nomem, addr, mode_P,
									   type, cons_floats);
	return new_r_Proj(load, mode_P, pn_Load_res);
}
Пример #6
0
static ir_node *arm_new_spill(ir_node *value, ir_node *after)
{
	ir_node  *block  = get_block(after);
	ir_graph *irg    = get_irn_irg(after);
	ir_node  *frame  = get_irg_frame(irg);
	ir_node  *mem    = get_irg_no_mem(irg);
	ir_mode  *mode   = get_irn_mode(value);
	ir_node  *store  = new_bd_arm_Str(NULL, block, frame, value, mem, mode,
	                                  NULL, false, 0, true);
	arch_add_irn_flags(store, arch_irn_flag_spill);
	sched_add_after(after, store);
	return store;
}
Пример #7
0
static ir_node *make_softfloat_call(ir_node *const n, char const *const name,
                                    size_t const arity,
                                    ir_node *const *const in)
{
	dbg_info *const dbgi     = get_irn_dbg_info(n);
	ir_node  *const block    = get_nodes_block(n);
	ir_graph *const irg      = get_irn_irg(n);
	ir_node  *const nomem    = get_irg_no_mem(irg);
	ir_node  *const callee   = create_softfloat_address(n, name);
	ir_type  *const type     = get_softfloat_type(n);
	ir_mode  *const res_mode = get_type_mode(get_method_res_type(type, 0));
	ir_node  *const call     = new_rd_Call(dbgi, block, nomem, callee, arity,
	                                       in, type);
	ir_node  *const results  = new_r_Proj(call, mode_T, pn_Call_T_result);
	ir_node  *const result   = new_r_Proj(results, res_mode, 0);
	return result;
}
Пример #8
0
static ir_node *create_fpu_mode_spill(void *const env, ir_node *const state, bool const force, ir_node *const after)
{
	(void)env;

	if (!force && is_ia32_ChangeCW(state))
		return NULL;

	ir_node       *spill;
	ir_node *const block = get_nodes_block(state);
	/* Don't spill the fpcw in unsafe mode. */
	if (ia32_cg_config.use_unsafe_floatconv) {
		spill = new_bd_ia32_FnstCWNOP(NULL, block, state);
	} else {
		ir_graph *const irg   = get_irn_irg(state);
		ir_node  *const noreg = ia32_new_NoReg_gp(irg);
		ir_node  *const nomem = get_irg_no_mem(irg);
		ir_node  *const frame = get_irg_frame(irg);
		spill = create_fnstcw(block, frame, noreg, nomem, state);
	}
	sched_add_after(skip_Proj(after), spill);
	return spill;
}
Пример #9
0
ir_graph *new_const_code_irg(void)
{
	ir_graph *const res = new_r_ir_graph(NULL, 0);
	mature_immBlock(get_irg_end_block(res));

	/* There is no Start node in the const_code_irg */
	set_irg_start(res, new_r_Bad(res, mode_T));
	set_irg_frame(res, new_r_Bad(res, mode_BAD));
	set_irg_args(res, new_r_Bad(res, mode_T));
	set_irg_initial_mem(res, new_r_Bad(res, mode_M));
	set_r_store(res, get_irg_no_mem(res));

	/* Set the visited flag high enough that the blocks will never be
	 * visited. */
	ir_node *const body_block = get_r_cur_block(res);
	set_irn_visited(body_block, -1);
	set_Block_block_visited(body_block, -1);
	ir_node *const start_block = get_irg_start_block(res);
	set_Block_block_visited(start_block, -1);
	set_irn_visited(start_block, -1);

	return res;
}