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