Commit a9950b7e authored by Matthias Braun's avatar Matthias Braun
Browse files

remove get_irg_tls() concept, simply use SymConst and let the backend figure it out

parent b7a0d752
......@@ -227,11 +227,6 @@ FIRM_API ir_node *get_irg_frame(const ir_graph *irg);
/** Sets the node that represents the frame pointer of the given IR graph. */
FIRM_API void set_irg_frame(ir_graph *irg, ir_node *node);
/** Returns the node that represents the tls pointer of the given IR graph. */
FIRM_API ir_node *get_irg_tls(const ir_graph *irg);
/** Sets the node that represents the tls pointer of the given IR graph. */
FIRM_API void set_irg_tls(ir_graph *irg, ir_node *node);
/** Returns the node that represents the initial memory of the given IR graph. */
FIRM_API ir_node *get_irg_initial_mem(const ir_graph *irg);
/** Sets the node that represents the initial memory of the given IR graph. */
......
......@@ -255,12 +255,6 @@ FIRM_API void set_nodes_block (ir_node *node, ir_node *block);
* from Start. If so returns frame type, else Null. */
FIRM_API ir_type *is_frame_pointer(const ir_node *n);
/** Test whether arbitrary node is the thread local storage (tls) pointer.
*
* Test whether arbitrary node is tls pointer, i.e. Proj(pn_Start_P_tls)
* from Start. If so returns tls type, else Null. */
FIRM_API ir_type *is_tls_pointer(const ir_node *n);
/** Return the number of control flow predecessors of a block. */
FIRM_API int get_Block_n_cfgpreds(const ir_node *block);
/** Return the control flow predecessor of a block at a given position. */
......
......@@ -437,17 +437,14 @@ ir_storage_class_class_t classify_pointer(const ir_node *irn,
ir_storage_class_class_t res = ir_sc_pointer;
if (is_Global(irn)) {
ir_entity *entity = get_Global_entity(irn);
res = ir_sc_globalvar;
ir_type *owner = get_entity_owner(entity);
res = owner == get_tls_type() ? ir_sc_tls : ir_sc_globalvar;
if (! (get_entity_usage(entity) & ir_usage_address_taken))
res |= ir_sc_modifier_nottaken;
} else if (irn == get_irg_frame(irg)) {
res = ir_sc_localvar;
if (ent != NULL && !(get_entity_usage(ent) & ir_usage_address_taken))
res |= ir_sc_modifier_nottaken;
} else if (irn == get_irg_tls(irg)) {
res = ir_sc_tls;
if (ent != NULL && !(get_entity_usage(ent) & ir_usage_address_taken))
res |= ir_sc_modifier_nottaken;
} else if (is_Proj(irn) && is_malloc_Result(irn)) {
return ir_sc_malloced;
} else if (is_Const(irn)) {
......@@ -1189,18 +1186,15 @@ static void print_entity_usage_flags(const ir_type *tp)
/**
* Post-walker: check for global entity address
*/
static void check_global_address(ir_node *irn, void *env)
static void check_global_address(ir_node *irn, void *data)
{
ir_node *tls = (ir_node*) env;
ir_entity *ent;
unsigned flags;
(void) data;
if (is_Global(irn)) {
/* A global. */
ent = get_Global_entity(irn);
} else if (is_Sel(irn) && get_Sel_ptr(irn) == tls) {
/* A TLS variable. */
ent = get_Sel_entity(irn);
} else
return;
......@@ -1231,7 +1225,7 @@ static void analyse_irp_globals_entity_usage(void)
ir_graph *irg = get_irp_irg(i);
assure_irg_outs(irg);
irg_walk_graph(irg, NULL, check_global_address, get_irg_tls(irg));
irg_walk_graph(irg, NULL, check_global_address, NULL);
}
#ifdef DEBUG_libfirm
......
......@@ -1434,9 +1434,6 @@ static ir_node *gen_Proj_Start(ir_node *node)
case pn_Start_P_frame_base:
return be_prolog_get_reg_value(abihelper, sp_reg);
case pn_Start_P_tls:
return new_r_Bad(get_irn_irg(node));
case pn_Start_max:
break;
}
......
......@@ -318,15 +318,6 @@ static void pre_transform_anchor(ir_graph *irg, int anchor)
set_irg_anchor(irg, anchor, transformed);
}
static void kill_unused_anchor(int anchor)
{
ir_node *old_anchor_node = get_irn_n(env.old_anchor, anchor);
ir_node *old_bad = get_irn_n(env.old_anchor, anchor_bad);
if (old_anchor_node != NULL && get_irn_n_edges(old_anchor_node) <= 1) {
set_irn_n(env.old_anchor, anchor, old_bad);
}
}
/**
* Transforms all nodes. Deletes the old obstack and creates a new one.
*/
......@@ -366,7 +357,6 @@ static void transform_nodes(ir_graph *irg, arch_pretrans_nodes *pre_transform)
pre_transform_anchor(irg, anchor_start_block);
pre_transform_anchor(irg, anchor_start);
pre_transform_anchor(irg, anchor_frame);
kill_unused_anchor(anchor_tls);
if (pre_transform)
pre_transform();
......
......@@ -55,7 +55,7 @@ static bitset_t *non_address_mode_nodes;
*
* @return non-zero if the DAG represents an immediate, 0 else
*/
static int do_is_immediate(const ir_node *node, int *symconsts, int negate)
static bool do_is_immediate(const ir_node *node, int *symconsts, bool negate)
{
ir_node *left;
ir_node *right;
......@@ -69,44 +69,43 @@ static int do_is_immediate(const ir_node *node, int *symconsts, int negate)
"Optimisation warning tarval of %+F(%+F) is not a long.\n",
node, current_ir_graph);
#endif
return 0;
return false;
}
return 1;
return true;
case iro_SymConst:
/* the first SymConst of a DAG can be fold into an immediate */
#ifndef SUPPORT_NEGATIVE_SYMCONSTS
/* unfortunately the assembler/linker doesn't support -symconst */
if (negate)
return 0;
return false;
#endif
if (get_SymConst_kind(node) != symconst_addr_ent)
return 0;
return false;
if (++*symconsts > 1)
return 0;
return false;
return 1;
return true;
case iro_Unknown:
/* we can use '0' for Unknowns */
return 1;
return true;
case iro_Add:
case iro_Sub:
/* Add's and Sub's are typically supported as long as both operands are
* immediates */
if (ia32_is_non_address_mode_node(node))
return 0;
return false;
left = get_binop_left(node);
if (!do_is_immediate(left, symconsts, negate))
return 0;
return false;
right = get_binop_right(node);
if (!do_is_immediate(right, symconsts, is_Sub(node) ? !negate : negate))
return 0;
return false;
return 1;
return true;
default:
/* all other nodes are NO immediates */
return 0;
return false;
}
}
......@@ -118,7 +117,7 @@ static int do_is_immediate(const ir_node *node, int *symconsts, int negate)
* @param node the node
* @param negate if set, the immediate must be negated
*/
static int is_immediate(ia32_address_t *addr, const ir_node *node, int negate)
static int is_immediate(ia32_address_t *addr, const ir_node *node, bool negate)
{
int symconsts = (addr->symconst_ent != NULL);
return do_is_immediate(node, &symconsts, negate);
......@@ -131,7 +130,7 @@ static int is_immediate(ia32_address_t *addr, const ir_node *node, int negate)
* @param node the node
* @param negate if set, the immediate must be negated
*/
static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
static void eat_immediate(ia32_address_t *addr, ir_node *node, bool negate)
{
ir_tarval *tv;
ir_node *left;
......@@ -155,6 +154,8 @@ static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
panic("Internal error: more than 1 symconst in address calculation");
}
addr->symconst_ent = get_SymConst_entity(node);
if (get_entity_owner(addr->symconst_ent) == get_tls_type())
addr->tls_segment = true;
#ifndef SUPPORT_NEGATIVE_SYMCONSTS
assert(!negate);
#endif
......
......@@ -27,6 +27,7 @@
#ifndef IA32_ADDRESS_MODE_H
#define IA32_ADDRESS_MODE_H
#include <stdbool.h>
#include "irtypes.h"
#include "../beirg.h"
......@@ -41,9 +42,10 @@ struct ia32_address_t {
int offset; /**< An integer offset. */
int scale; /**< An integer scale. {0,1,2,3} */
ir_entity *symconst_ent; /**< A SynConst entity if any. */
int use_frame; /**< Set, if the frame is accessed */
bool use_frame; /**< Set, if the frame is accessed */
bool tls_segment; /**< Set if AM is relative to TLS */
ir_entity *frame_entity; /**< The accessed frame entity if any. */
int symconst_sign; /**< The "sign" of the symconst. */
bool symconst_sign; /**< The "sign" of the symconst. */
};
/**
......
......@@ -781,10 +781,7 @@ ir_node *ia32_gen_CopyB(ir_node *node)
ir_node *ia32_gen_Proj_tls(ir_node *node)
{
ir_node *block = get_new_node(get_nodes_block(node));
ir_node *res = NULL;
res = new_bd_ia32_LdTls(NULL, block, mode_Iu);
ir_node *res = new_bd_ia32_LdTls(NULL, block);
return res;
}
......@@ -946,16 +943,17 @@ ir_node *ia32_try_create_Immediate(ir_node *node, char immediate_constraint_type
if (is_Const(node)) {
cnst = node;
symconst = NULL;
} else if (is_Global(node)) {
} else if (is_SymConst_addr_ent(node)
&& get_entity_owner(get_SymConst_entity(node)) != get_tls_type()) {
cnst = NULL;
symconst = node;
} else if (is_Add(node)) {
ir_node *left = get_Add_left(node);
ir_node *right = get_Add_right(node);
if (is_Const(left) && is_Global(right)) {
if (is_Const(left) && is_SymConst_addr_ent(right)) {
cnst = left;
symconst = right;
} else if (is_Global(left) && is_Const(right)) {
} else if (is_SymConst_addr_ent(left) && is_Const(right)) {
cnst = right;
symconst = left;
}
......
......@@ -563,6 +563,9 @@ void ia32_emit_am(const ir_node *node)
/* just to be sure... */
assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
if (get_ia32_am_tls_segment(node))
be_emit_cstring("%gs:");
/* emit offset */
if (ent != NULL) {
const ia32_attr_t *attr = get_ia32_attr_const(node);
......@@ -1606,14 +1609,6 @@ static void emit_ia32_Const(const ir_node *node)
ia32_emitf(node, "\tmovl %I, %D0\n");
}
/**
* Emits code to load the TLS base
*/
static void emit_ia32_LdTls(const ir_node *node)
{
ia32_emitf(node, "\tmovl %%gs:0, %D0\n");
}
/* helper function for emit_ia32_Minus64Bit */
static void emit_mov(const ir_node* node, const arch_register_t *src, const arch_register_t *dst)
{
......@@ -1779,7 +1774,6 @@ static void ia32_register_emitters(void)
IA32_EMIT(IMul);
IA32_EMIT(Jcc);
IA32_EMIT(Setcc);
IA32_EMIT(LdTls);
IA32_EMIT(Minus64Bit);
IA32_EMIT(SwitchJmp);
IA32_EMIT(ClimbFrame);
......
......@@ -470,6 +470,18 @@ int is_ia32_am_sc_sign(const ir_node *node)
return attr->data.am_sc_sign;
}
void set_ia32_am_tls_segment(ir_node *node, bool value)
{
ia32_attr_t *attr = get_ia32_attr(node);
attr->data.am_tls_segment = value;
}
bool get_ia32_am_tls_segment(const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
return attr->data.am_tls_segment;
}
/**
* Gets the addr mode const.
*/
......
......@@ -155,6 +155,10 @@ void clear_ia32_am_sc_sign(ir_node *node);
*/
int is_ia32_am_sc_sign(const ir_node *node);
void set_ia32_am_tls_segment(ir_node *node, bool value);
bool get_ia32_am_tls_segment(const ir_node *node);
/**
* Gets the addr mode const.
*/
......
......@@ -177,6 +177,7 @@ struct ia32_attr_t {
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 am_tls_segment:1; /**< addresses are relative to TLS */
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. */
......
......@@ -1384,6 +1384,8 @@ LdTls => {
irn_flags => [ "rematerializable" ],
reg_req => { out => [ "gp" ] },
units => [ "GP" ],
emit => ". movl %%gs:0, %D0",
mode => $mode_gp,
latency => 1,
},
......
......@@ -370,8 +370,15 @@ static ir_node *gen_SymConst(ir_node *node)
panic("backend only support symconst_addr_ent (at %+F)", node);
}
entity = get_SymConst_entity(node);
if (get_entity_owner(entity) == get_tls_type()) {
ir_node *tls_base = new_bd_ia32_LdTls(NULL, block);
ir_node *lea = new_bd_ia32_Lea(dbgi, block, tls_base, noreg_GP);
set_ia32_am_sc(lea, entity);
cnst = lea;
} else {
cnst = new_bd_ia32_Const(dbgi, block, entity, 0, 0, 0);
}
}
SET_IA32_ORIG_NODE(cnst, node);
......@@ -636,6 +643,7 @@ static void build_address(ia32_address_mode_t *am, ir_node *node,
addr->index = noreg_GP;
addr->mem = nomem;
addr->symconst_ent = entity;
addr->tls_segment = false;
addr->use_frame = 1;
am->ls_mode = get_type_mode(get_entity_type(entity));
am->pinned = op_pin_state_floats;
......@@ -664,6 +672,7 @@ static void set_address(ir_node *node, const ia32_address_t *addr)
set_ia32_am_scale(node, addr->scale);
set_ia32_am_sc(node, addr->symconst_ent);
set_ia32_am_offs_int(node, addr->offset);
set_ia32_am_tls_segment(node, addr->tls_segment);
if (addr->symconst_sign)
set_ia32_am_sc_sign(node);
if (addr->use_frame)
......@@ -1200,6 +1209,18 @@ static ir_node *create_lea_from_address(dbg_info *dbgi, ir_node *block,
index = be_transform_node(index);
}
/* segment overrides are ineffective for Leas :-( so we have to patch
* around... */
if (addr->tls_segment) {
assert(addr->symconst_ent != NULL);
ir_node *tls_base = new_bd_ia32_LdTls(NULL, block);
if (base == noreg_GP)
base = tls_base;
else
base = new_bd_ia32_Lea(dbgi, block, tls_base, base);
addr->tls_segment = false;
}
res = new_bd_ia32_Lea(dbgi, block, base, index);
set_address(res, addr);
......@@ -4338,6 +4359,7 @@ static ir_node *gen_ia32_l_LLtoFloat(ir_node *node)
am.addr.offset = 0;
am.addr.scale = 2;
am.addr.symconst_ent = ia32_gen_fp_known_const(ia32_ULLBIAS);
am.addr.tls_segment = false;
am.addr.use_frame = 0;
am.addr.frame_entity = NULL;
am.addr.symconst_sign = 0;
......@@ -5585,9 +5607,6 @@ static ir_node *gen_Proj(ir_node *node)
return jump;
}
case pn_Start_P_tls:
return ia32_gen_Proj_tls(node);
}
break;
......
......@@ -1887,8 +1887,6 @@ static ir_node *gen_Proj_Start(ir_node *node)
return new_r_Bad(get_irn_irg(block));
case pn_Start_P_frame_base:
return get_frame_base();
case pn_Start_P_tls:
return new_r_Bad(current_ir_graph);
case pn_Start_max:
break;
}
......
......@@ -808,7 +808,6 @@ static const pns_lookup_t start_lut[] = {
#define X(a) { pn_Start_##a, #a }
X(X_initial_exec),
X(P_frame_base),
X(P_tls),
X(T_args),
#undef X
};
......
......@@ -227,7 +227,6 @@ ir_graph *new_r_ir_graph(ir_entity *ent, int n_loc)
projX = new_r_Proj(start, mode_X, pn_Start_X_initial_exec);
set_irg_initial_exec (res, projX);
set_irg_frame (res, new_r_Proj(start, mode_P_data, pn_Start_P_frame_base));
set_irg_tls (res, new_r_Proj(start, mode_P_data, pn_Start_P_tls));
set_irg_args (res, new_r_Proj(start, mode_T, pn_Start_T_args));
initial_mem = new_r_Proj(start, mode_M, pn_Start_M);
set_irg_initial_mem(res, initial_mem);
......@@ -565,16 +564,6 @@ void (set_irg_frame)(ir_graph *irg, ir_node *node)
_set_irg_frame(irg, node);
}
ir_node *(get_irg_tls)(const ir_graph *irg)
{
return _get_irg_tls(irg);
}
void (set_irg_tls)(ir_graph *irg, ir_node *node)
{
_set_irg_tls(irg, node);
}
ir_node *(get_irg_initial_mem)(const ir_graph *irg)
{
return _get_irg_initial_mem(irg);
......
......@@ -166,16 +166,6 @@ static inline void _set_irg_frame(ir_graph *irg, ir_node *node)
set_irn_n(irg->anchor, anchor_frame, node);
}
static inline ir_node *_get_irg_tls(const ir_graph *irg)
{
return get_irn_n(irg->anchor, anchor_tls);
}
static inline void _set_irg_tls(ir_graph *irg, ir_node *node)
{
set_irn_n(irg->anchor, anchor_tls, node);
}
static inline ir_node *_get_irg_initial_mem(const ir_graph *irg)
{
return get_irn_n(irg->anchor, anchor_initial_mem);
......@@ -536,8 +526,6 @@ static inline ir_phase *irg_get_phase(const ir_graph *irg, ir_phase_id id)
#define set_irg_initial_exec(irg, node) _set_irg_initial_exec(irg, node)
#define get_irg_frame(irg) _get_irg_frame(irg)
#define set_irg_frame(irg, node) _set_irg_frame(irg, node)
#define get_irg_tls(irg) _get_irg_tls(irg)
#define set_irg_tls(irg, node) _set_irg_tls(irg, node)
#define get_irg_initial_mem(irg) _get_irg_initial_mem(irg)
#define set_irg_initial_mem(irg, node) _set_irg_initial_mem(irg, node)
#define get_irg_args(irg) _get_irg_args(irg)
......
......@@ -516,19 +516,6 @@ ir_type *is_frame_pointer(const ir_node *n)
return NULL;
}
/* Test whether arbitrary node is tls pointer, i.e. Proj(pn_Start_P_tls)
* from Start. If so returns tls type, else Null. */
ir_type *is_tls_pointer(const ir_node *n)
{
if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_tls)) {
ir_node *start = get_Proj_pred(n);
if (is_Start(start)) {
return get_tls_type();
}
}
return NULL;
}
ir_node **get_Block_cfgpred_arr(ir_node *node)
{
assert(is_Block(node));
......
......@@ -431,8 +431,6 @@ enum irg_anchors {
anchor_start, /**< start node of this ir_graph */
anchor_initial_exec, /**< methods initial control flow */
anchor_frame, /**< methods frame */
anchor_tls, /**< pointer to the thread local storage containing all
thread local data. */
anchor_initial_mem, /**< initial memory of this graph */
anchor_args, /**< methods arguments */
anchor_bad, /**< bad node of this ir_graph, the one and
......
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