Esempio n. 1
0
static void fix_address_pic_elf(ir_node *const node, void *const data)
{
	(void)data;
	foreach_irn_in(node, i, pred) {
		if (!is_Address(pred))
			continue;
		ir_entity *const entity = get_Address_entity(pred);
		if (is_tls_entity(entity))
			continue;

		ir_graph *const irg         = get_irn_irg(node);
		bool      const ext_visible = is_externally_visible(entity);
		ir_node  *      res;
		if (i == n_Call_ptr && is_Call(node)) {
			/* We can compilation-unit local functions directly, everything else
			 * goes through the PLT */
			x86_immediate_kind_t const reloc
				= ext_visible ? X86_IMM_PLT : X86_IMM_PCREL;
			res = be_new_Relocation(irg, reloc, entity, mode_P);
		} else if (!ext_visible) {
			res = be_new_Relocation(irg, X86_IMM_PCREL, entity, mode_P);
		} else {
			res = create_gotpcrel_load(irg, entity);
		}
		set_irn_n(node, i, res);
	}
}
Esempio n. 2
0
static void fix_address_pic_mach_o(ir_node *const node, void *const data)
{
	(void)data;
	foreach_irn_in(node, i, pred) {
		if (!is_Address(pred))
			continue;
		ir_entity *const entity = get_Address_entity(pred);
		if (is_tls_entity(entity))
			continue;

		ir_graph *const irg = get_irn_irg(node);
		ir_node  *      res;
		if (i == n_Call_ptr && is_Call(node)) {
			// Somehow we can always call PC relative. Are there trampolines
			// involved?
			res = be_new_Relocation(irg, X86_IMM_PCREL, entity, mode_P);
		} else if (entity_has_definition(entity)
		        && !(get_entity_linkage(entity) & IR_LINKAGE_MERGE)) {
			res = be_new_Relocation(irg, X86_IMM_PCREL, entity, mode_P);
		} else {
			res = create_gotpcrel_load(irg, entity);
		}
		set_irn_n(node, i, res);
	}
}
Esempio n. 3
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);
	}
}
Esempio n. 4
0
static bool eat_imm(x86_address_t *const addr, ir_node const *const node,
                    bool basereg_usable)
{
	switch (get_irn_opcode(node)) {
	case iro_Add:
		/* Add is supported as long as both operands are immediates. */
		return
			!x86_is_non_address_mode_node(node) &&
			eat_imm(addr, get_Add_left(node), basereg_usable) &&
			eat_imm(addr, get_Add_right(node), basereg_usable);

	case iro_Address:
		/* The first Address of a DAG can be folded into an immediate. */
		if (addr->imm.entity)
			return false;
		addr->imm.entity = get_Address_entity(node);
		addr->imm.kind = X86_IMM_ADDR;
		if (is_tls_entity(addr->imm.entity))
			addr->tls_segment = true;
		return true;

	case iro_Const: {
		/* Add the value to the offset. */
		ir_tarval *const tv = get_Const_tarval(node);
		if (!tarval_possible(tv))
			return false;
		addr->imm.offset += get_tarval_long(tv);
		return true;
	}

	case iro_Unknown:
		/* Use '0' for Unknowns. */
		return true;

	default:
		if (be_is_Relocation(node)) {
			if (addr->imm.entity)
				return false;
			addr->imm.entity = be_get_Relocation_entity(node);
			x86_immediate_kind_t const kind
				= (x86_immediate_kind_t)be_get_Relocation_kind(node);
			addr->imm.kind = kind;
			if (kind == X86_IMM_GOTPCREL || kind == X86_IMM_PCREL) {
				if (!basereg_usable)
					return false;
				addr->ip_base = true;
			}
			return true;
		}
		/* All other nodes are no immediates. */
		return false;
	}
}
Esempio n. 5
0
ir_entity *detect_call(ir_node* call) {
	assert(is_Call(call));

	ir_node *callee = get_irn_n(call, 1);
	if (is_Address(callee)) {
		ir_entity *entity = get_Address_entity(callee);
		if (entity == gcj_init_entity) {
			assert(get_irn_arity(call) == 3);
			ir_node *arg = get_irn_n(call, 2);
			assert(is_Address(arg));
			ir_entity *rtti = get_Address_entity(arg);
			ir_type *klass = cpmap_find(&rtti2class, rtti);
			assert(klass);
			ir_entity *init_method = cpmap_find(&class2init, klass);
			//assert(init_method); // _Jv_InitClass calls can be there although class has no clinit
			return init_method;
		} // else if (entity == ...)

	} else
		assert(false);

	return NULL;
}