Commit 8713f359 authored by Matthias Braun's avatar Matthias Braun
Browse files

fix some cases of PIC emitting

[r25583]
parent f45d3536
......@@ -125,7 +125,7 @@ static ia32_intrinsic_env_t intrinsic_env = {
typedef ir_node *(*create_const_node_func) (dbg_info *dbg, ir_node *block);
/**
* Used to create a Pseudo-Register or Unknown node.
* Used to create per-graph unique pseudo nodes.
*/
static inline ir_node *create_const(ia32_code_gen_t *cg, ir_node **place,
create_const_node_func func,
......
......@@ -167,7 +167,7 @@ ir_node *ia32_create_Immediate(ir_entity *symconst, int symconst_sign, long val)
ir_graph *irg = current_ir_graph;
ir_node *start_block = get_irg_start_block(irg);
ir_node *immediate = new_bd_ia32_Immediate(NULL, start_block, symconst,
symconst_sign, val);
symconst_sign, no_pic_adjust, val);
arch_set_irn_register(immediate, &ia32_gp_regs[REG_GP_NOREG]);
return immediate;
......@@ -692,7 +692,7 @@ ir_node *gen_CopyB(ir_node *node) {
rem = size & 0x3; /* size % 4 */
size >>= 2;
res = new_bd_ia32_Const(dbgi, block, NULL, 0, size);
res = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, size);
be_dep_on_frame(res);
res = new_bd_ia32_CopyB(dbgi, block, new_dst, new_src, res, new_mem, rem);
......
......@@ -45,6 +45,7 @@ struct constraint_t {
extern ia32_code_gen_t *env_cg;
extern heights_t *heights;
extern int no_pic_adjust;
/**
* Get an atomic entity that is initialized with a tarval forming
......
......@@ -68,10 +68,10 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static const ia32_isa_t *isa;
static ia32_code_gen_t *cg;
static int do_pic;
static char pic_base_label[128];
static ir_label_t exc_label_id;
static int mark_spill_reload = 0;
static int do_pic;
/** Return the next block in Block schedule */
static ir_node *get_prev_block_sched(const ir_node *block)
......@@ -291,8 +291,7 @@ static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
}
}
if (!no_pic_adjust && do_pic) {
/* TODO: only do this when necessary */
if (do_pic && !no_pic_adjust) {
be_emit_char('-');
be_emit_string(pic_base_label);
}
......@@ -305,7 +304,7 @@ static void emit_ia32_Immediate_no_prefix(const ir_node *node)
if (attr->symconst != NULL) {
if (attr->sc_sign)
be_emit_char('-');
ia32_emit_entity(attr->symconst, 0);
ia32_emit_entity(attr->symconst, attr->no_pic_adjust);
}
if (attr->symconst == NULL || attr->offset != 0) {
if (attr->symconst != NULL) {
......@@ -570,6 +569,63 @@ typedef enum ia32_emit_mod_t {
EMIT_LONG = 1U << 2
} ia32_emit_mod_t;
/**
* Emits address mode.
*/
void ia32_emit_am(const ir_node *node)
{
ir_entity *ent = get_ia32_am_sc(node);
int offs = get_ia32_am_offs_int(node);
ir_node *base = get_irn_n(node, n_ia32_base);
int has_base = !is_ia32_NoReg_GP(base);
ir_node *index = get_irn_n(node, n_ia32_index);
int has_index = !is_ia32_NoReg_GP(index);
/* just to be sure... */
assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
/* emit offset */
if (ent != NULL) {
const ia32_attr_t *attr = get_ia32_attr_const(node);
if (is_ia32_am_sc_sign(node))
be_emit_char('-');
ia32_emit_entity(ent, attr->data.am_sc_no_pic_adjust);
}
/* also handle special case if nothing is set */
if (offs != 0 || (ent == NULL && !has_base && !has_index)) {
if (ent != NULL) {
be_emit_irprintf("%+d", offs);
} else {
be_emit_irprintf("%d", offs);
}
}
if (has_base || has_index) {
be_emit_char('(');
/* emit base */
if (has_base) {
const arch_register_t *reg = get_in_reg(node, n_ia32_base);
emit_register(reg, NULL);
}
/* emit index + scale */
if (has_index) {
const arch_register_t *reg = get_in_reg(node, n_ia32_index);
int scale;
be_emit_char(',');
emit_register(reg, NULL);
scale = get_ia32_am_scale(node);
if (scale > 0) {
be_emit_irprintf(",%d", 1 << scale);
}
}
be_emit_char(')');
}
}
/**
* fmt parameter output
* ---- ---------------------- ---------------------------------------------
......@@ -645,6 +701,7 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
case 'M':
if (mod & EMIT_ALTERNATE_AM)
be_emit_char('*');
ia32_emit_am(node);
break;
......@@ -833,62 +890,6 @@ void ia32_emit_unop(const ir_node *node, int pos)
ia32_emitf(node, fmt);
}
/**
* Emits address mode.
*/
void ia32_emit_am(const ir_node *node)
{
ir_entity *ent = get_ia32_am_sc(node);
int offs = get_ia32_am_offs_int(node);
ir_node *base = get_irn_n(node, n_ia32_base);
int has_base = !is_ia32_NoReg_GP(base);
ir_node *index = get_irn_n(node, n_ia32_index);
int has_index = !is_ia32_NoReg_GP(index);
/* just to be sure... */
assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
/* emit offset */
if (ent != NULL) {
if (is_ia32_am_sc_sign(node))
be_emit_char('-');
ia32_emit_entity(ent, 0);
}
/* also handle special case if nothing is set */
if (offs != 0 || (ent == NULL && !has_base && !has_index)) {
if (ent != NULL) {
be_emit_irprintf("%+d", offs);
} else {
be_emit_irprintf("%d", offs);
}
}
if (has_base || has_index) {
be_emit_char('(');
/* emit base */
if (has_base) {
const arch_register_t *reg = get_in_reg(node, n_ia32_base);
emit_register(reg, NULL);
}
/* emit index + scale */
if (has_index) {
const arch_register_t *reg = get_in_reg(node, n_ia32_index);
int scale;
be_emit_char(',');
emit_register(reg, NULL);
scale = get_ia32_am_scale(node);
if (scale > 0) {
be_emit_irprintf(",%d", 1 << scale);
}
}
be_emit_char(')');
}
}
static void emit_ia32_IMul(const ir_node *node)
{
ir_node *left = get_irn_n(node, n_ia32_IMul_left);
......
......@@ -194,7 +194,7 @@ static ir_node *create_fpu_mode_reload(void *env, ir_node *state,
/* TODO: make the actual mode configurable in ChangeCW... */
or_const = new_bd_ia32_Immediate(NULL, get_irg_start_block(irg),
NULL, 0, 3072);
NULL, 0, 0, 3072);
arch_set_irn_register(or_const, &ia32_gp_regs[REG_GP_NOREG]);
or = new_bd_ia32_Or(NULL, block, noreg, noreg, nomem, load_res,
or_const);
......
......@@ -163,6 +163,9 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
fputc('+', F);
}
fprintf(F, "%ld", attr->offset);
if (attr->no_pic_adjust) {
fputs("(no_pic_adjust)", F);
}
}
}
else {
......@@ -176,6 +179,9 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
fputc('-', F);
}
fputs(get_entity_name(attr->am_sc), F);
if(attr->data.am_sc_no_pic_adjust) {
fputs("(no_pic_adjust)", F);
}
}
if(attr->am_offs != 0) {
if(attr->am_offs > 0 && attr->am_sc != NULL) {
......@@ -996,16 +1002,18 @@ init_ia32_asm_attributes(ir_node *res)
void
init_ia32_immediate_attributes(ir_node *res, ir_entity *symconst,
int symconst_sign, long offset)
int symconst_sign, int no_pic_adjust,
long offset)
{
ia32_immediate_attr_t *attr = get_irn_generic_attr(res);
#ifndef NDEBUG
attr->attr.attr_type |= IA32_ATTR_ia32_immediate_attr_t;
#endif
attr->symconst = symconst;
attr->sc_sign = symconst_sign;
attr->offset = offset;
attr->symconst = symconst;
attr->sc_sign = symconst_sign;
attr->no_pic_adjust = no_pic_adjust;
attr->offset = offset;
}
void init_ia32_call_attributes(ir_node* res, unsigned pop, ir_type* call_tp)
......@@ -1069,6 +1077,7 @@ int ia32_compare_attr(const ia32_attr_t *a, const ia32_attr_t *b)
|| a->data.am_sc_sign != b->data.am_sc_sign
|| a->am_offs != b->am_offs
|| a->am_sc != b->am_sc
|| a->data.am_sc_no_pic_adjust != b->data.am_sc_no_pic_adjust
|| a->ls_mode != b->ls_mode)
return 1;
......@@ -1198,10 +1207,12 @@ int ia32_compare_immediate_attr(ir_node *a, ir_node *b)
const ia32_immediate_attr_t *attr_a = get_ia32_immediate_attr_const(a);
const ia32_immediate_attr_t *attr_b = get_ia32_immediate_attr_const(b);
if (attr_a->symconst != attr_b->symconst ||
attr_a->sc_sign != attr_b->sc_sign ||
attr_a->offset != attr_b->offset)
if (attr_a->symconst != attr_b->symconst
|| attr_a->sc_sign != attr_b->sc_sign
|| attr_a->no_pic_adjust != attr_b->no_pic_adjust
|| attr_a->offset != attr_b->offset) {
return 1;
}
return 0;
}
......
......@@ -401,7 +401,8 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
void init_ia32_x87_attributes(ir_node *node);
void init_ia32_asm_attributes(ir_node *node);
void init_ia32_immediate_attributes(ir_node *node, ir_entity *symconst,
int symconst_sign, long offset);
int symconst_sign, int no_pic_adjust,
long offset);
void init_ia32_call_attributes(ir_node *res, unsigned pop, ir_type *call_tp);
void init_ia32_copyb_attributes(ir_node *res, unsigned size);
void init_ia32_condcode_attributes(ir_node *res, long pnc);
......
......@@ -96,6 +96,7 @@ struct ia32_attr_t {
unsigned am_scale:2; /**< The address mode scale for index register. */
unsigned am_sc_sign:1; /**< The sign bit of the address mode symconst. */
unsigned am_sc_no_pic_adjust : 1;/**< AM symconst can be relative to EIP */
unsigned use_frame:1; /**< Indicates whether the operation uses the frame pointer or not. */
unsigned has_except_label:1; /**< Set if this node needs a label because of possible exception. */
......@@ -170,7 +171,8 @@ struct ia32_immediate_attr_t {
ia32_attr_t attr; /**< generic attribute */
ir_entity *symconst; /**< An entity if any. */
long offset; /**< An offset if any. */
unsigned sc_sign:1; /**< The sign bit of the symconst. */
unsigned sc_sign : 1; /**< The sign bit of the symconst. */
unsigned no_pic_adjust : 1; /**< constant can be relative to EIP */
};
/**
......
......@@ -982,8 +982,8 @@ static ir_node *create_immediate_from_int(int val)
{
ir_graph *irg = current_ir_graph;
ir_node *start_block = get_irg_start_block(irg);
ir_node *immediate = new_bd_ia32_Immediate(NULL, start_block, NULL, 0,
val);
ir_node *immediate
= new_bd_ia32_Immediate(NULL, start_block, NULL, 0, 0, val);
arch_set_irn_register(immediate, &ia32_gp_regs[REG_GP_NOREG]);
return immediate;
......@@ -994,10 +994,13 @@ static ir_node *create_immediate_from_am(const ir_node *node)
ir_node *block = get_nodes_block(node);
int offset = get_ia32_am_offs_int(node);
int sc_sign = is_ia32_am_sc_sign(node);
const ia32_attr_t *attr = get_ia32_attr_const(node);
int sc_no_pic_adjust = attr->data.am_sc_no_pic_adjust;
ir_entity *entity = get_ia32_am_sc(node);
ir_node *res;
res = new_bd_ia32_Immediate(NULL, block, entity, sc_sign, offset);
res = new_bd_ia32_Immediate(NULL, block, entity, sc_sign, sc_no_pic_adjust,
offset);
arch_set_irn_register(res, &ia32_gp_regs[REG_GP_NOREG]);
return res;
}
......
......@@ -289,7 +289,7 @@ $custom_init_attr_func = \&ia32_custom_init_attr;
"\tinit_ia32_copyb_attributes(res, size);",
ia32_immediate_attr_t =>
"\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
"\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);",
"\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, no_pic_adjust, offset);",
ia32_x87_attr_t =>
"\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
"\tinit_ia32_x87_attributes(res);",
......@@ -327,7 +327,7 @@ Immediate => {
state => "pinned",
op_flags => "c",
reg_req => { out => [ "gp_NOREG:I" ] },
attr => "ir_entity *symconst, int symconst_sign, long offset",
attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
attr_type => "ia32_immediate_attr_t",
hash_func => "ia32_hash_Immediate",
latency => 0,
......@@ -1198,7 +1198,7 @@ Const => {
irn_flags => "R",
reg_req => { out => [ "gp" ] },
units => [ "GP" ],
attr => "ir_entity *symconst, int symconst_sign, long offset",
attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
attr_type => "ia32_immediate_attr_t",
latency => 1,
mode => $mode_gp,
......
......@@ -93,6 +93,7 @@
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static ir_node *initial_fpcw = NULL;
int no_pic_adjust;
typedef ir_node *construct_binop_func(dbg_info *db, ir_node *block,
ir_node *base, ir_node *index, ir_node *mem, ir_node *op1,
......@@ -238,7 +239,7 @@ static ir_node *gen_Const(ir_node *node)
(get_tarval_sub_bits(tv, 1) << 8) |
(get_tarval_sub_bits(tv, 2) << 16) |
(get_tarval_sub_bits(tv, 3) << 24);
ir_node *cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, val);
ir_node *cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
load = new_bd_ia32_xMovd(dbgi, block, cnst);
set_ia32_ls_mode(load, mode);
res = load;
......@@ -258,7 +259,7 @@ static ir_node *gen_Const(ir_node *node)
(get_tarval_sub_bits(tv, 5) << 8) |
(get_tarval_sub_bits(tv, 6) << 16) |
(get_tarval_sub_bits(tv, 7) << 24);
cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, val);
cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
load = new_bd_ia32_xMovd(dbgi, block, cnst);
set_ia32_ls_mode(load, mode);
psllq = new_bd_ia32_xPsllq(dbgi, block, load, imm32);
......@@ -321,7 +322,7 @@ end:
}
val = get_tarval_long(tv);
cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, val);
cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
SET_IA32_ORIG_NODE(cnst, node);
be_dep_on_frame(cnst);
......@@ -354,7 +355,7 @@ static ir_node *gen_SymConst(ir_node *node)
panic("backend only support symconst_addr_ent (at %+F)", node);
}
entity = get_SymConst_entity(node);
cnst = new_bd_ia32_Const(dbgi, block, entity, 0, 0);
cnst = new_bd_ia32_Const(dbgi, block, entity, 0, 0, 0);
}
SET_IA32_ORIG_NODE(cnst, node);
......@@ -1199,7 +1200,7 @@ static ir_node *gen_Add(ir_node *node)
/* a constant? */
if (addr.base == NULL && addr.index == NULL) {
new_node = new_bd_ia32_Const(dbgi, new_block, addr.symconst_ent,
addr.symconst_sign, addr.offset);
addr.symconst_sign, 0, addr.offset);
be_dep_on_frame(new_node);
SET_IA32_ORIG_NODE(new_node, node);
return new_node;
......@@ -1528,7 +1529,7 @@ static ir_node *create_Div(ir_node *node)
new_node = new_bd_ia32_IDiv(dbgi, new_block, addr->base,
addr->index, new_mem, am.new_op2, am.new_op1, sign_extension);
} else {
sign_extension = new_bd_ia32_Const(dbgi, new_block, NULL, 0, 0);
sign_extension = new_bd_ia32_Const(dbgi, new_block, NULL, 0, 0, 0);
be_dep_on_frame(sign_extension);
new_node = new_bd_ia32_Div(dbgi, new_block, addr->base,
......@@ -4471,6 +4472,7 @@ static ir_node *gen_be_Call(ir_node *node)
ir_node * edx = noreg_GP;
unsigned const pop = be_Call_get_pop(node);
ir_type *const call_tp = be_Call_get_type(node);
int old_no_pic_adjust;
/* Run the x87 simulator if the call returns a float value */
if (get_method_n_ress(call_tp) > 0) {
......@@ -4485,9 +4487,15 @@ static ir_node *gen_be_Call(ir_node *node)
/* We do not want be_Call direct calls */
assert(be_Call_get_entity(node) == NULL);
/* special case for PIC trampoline calls */
old_no_pic_adjust = no_pic_adjust;
no_pic_adjust = env_cg->birg->main_env->options->pic;
match_arguments(&am, src_block, NULL, src_ptr, src_mem,
match_am | match_immediate);
no_pic_adjust = old_no_pic_adjust;
i = get_irn_arity(node) - 1;
fpcw = be_transform_node(get_irn_n(node, i--));
for (; i >= be_pos_Call_first_arg; --i) {
......@@ -5096,7 +5104,7 @@ static ir_node *gen_inner_trampoline(ir_node *node) {
/* the callee is typically an immediate */
if (is_SymConst(callee)) {
rel = new_bd_ia32_Const(dbgi, new_block, get_SymConst_entity(callee), 0, -10);
rel = new_bd_ia32_Const(dbgi, new_block, get_SymConst_entity(callee), 0, 0, -10);
} else {
rel = new_bd_ia32_Lea(dbgi, new_block, be_transform_node(callee), ia32_create_Immediate(NULL, 0, -10));
}
......@@ -5713,8 +5721,9 @@ void ia32_transform_graph(ia32_code_gen_t *cg)
int cse_last;
register_transformers();
env_cg = cg;
initial_fpcw = NULL;
env_cg = cg;
initial_fpcw = NULL;
no_pic_adjust = 0;
BE_TIMER_PUSH(t_heights);
heights = heights_new(cg->irg);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment