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); } }
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); } }
/** 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); } }
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; } }
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; }