From: Michael Beck Date: Sat, 3 Jun 2006 02:11:07 +0000 (+0000) Subject: added support for Thread local storage X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=cdd903d8e390c19bf09b67bb991b45dde115050e;p=libfirm added support for Thread local storage [r7863] --- diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c index 4c0af7b5b..bf0c81aa3 100644 --- a/ir/ir/irdump.c +++ b/ir/ir/irdump.c @@ -818,6 +818,7 @@ static const pns_lookup_t start_lut[] = { X(X_initial_exec), X(P_frame_base), X(P_globals), + X(P_tls), X(T_args), X(P_value_arg_base) #undef X diff --git a/ir/ir/irgopt.c b/ir/ir/irgopt.c index e2d633289..884d7e69f 100644 --- a/ir/ir/irgopt.c +++ b/ir/ir/irgopt.c @@ -900,7 +900,7 @@ static int can_inline(ir_node *call, ir_graph *called_graph) int inline_method(ir_node *call, ir_graph *called_graph) { ir_node *pre_call; ir_node *post_call, *post_bl; - ir_node *in[5]; + ir_node *in[pn_Start_max]; ir_node *end, *end_bl; ir_node **res_pred; ir_node **cf_pred; @@ -983,14 +983,15 @@ int inline_method(ir_node *call, ir_graph *called_graph) { graph. Both will end up being a tuple. -- */ post_bl = get_nodes_block(call); set_irg_current_block(current_ir_graph, post_bl); - /* XxMxPxP of Start + parameter of Call */ + /* XxMxPxPxPxT of Start + parameter of Call */ in[pn_Start_X_initial_exec] = new_Jmp(); in[pn_Start_M] = get_Call_mem(call); in[pn_Start_P_frame_base] = get_irg_frame(current_ir_graph); in[pn_Start_P_globals] = get_irg_globals(current_ir_graph); + in[pn_Start_P_tls] = get_irg_tls(current_ir_graph); in[pn_Start_T_args] = new_Tuple(get_Call_n_params(call), get_Call_param_arr(call)); /* in[pn_Start_P_value_arg_base] = ??? */ - pre_call = new_Tuple(5, in); + pre_call = new_Tuple(pn_Start_max, in); post_call = call; /* -- diff --git a/ir/ir/irgraph.c b/ir/ir/irgraph.c index 810007bcb..c91e41ae7 100644 --- a/ir/ir/irgraph.c +++ b/ir/ir/irgraph.c @@ -227,6 +227,7 @@ new_r_ir_graph (entity *ent, int n_loc) projX = new_Proj(start, mode_X, pn_Start_X_initial_exec); set_irg_frame (res, new_Proj(start, mode_P_data, pn_Start_P_frame_base)); set_irg_globals (res, new_Proj(start, mode_P_data, pn_Start_P_globals)); + set_irg_tls (res, new_Proj(start, mode_P_data, pn_Start_P_tls)); set_irg_args (res, new_Proj(start, mode_T, pn_Start_T_args)); initial_mem = new_Proj(start, mode_M, pn_Start_M); set_irg_initial_mem(res, initial_mem); @@ -244,11 +245,11 @@ new_r_ir_graph (entity *ent, int n_loc) * Use of this edge is matter of discussion, unresolved. Also possible: * add_immBlock_pred(res->start_block, res->start_block), but invalid typed. */ - mature_immBlock (res->current_block); + mature_immBlock(res->current_block); /*-- Make a block to start with --*/ first_block = new_immBlock(); - add_immBlock_pred (first_block, projX); + add_immBlock_pred(first_block, projX); res->method_execution_frequency = -1; res->estimated_node_count = 0; @@ -258,9 +259,9 @@ new_r_ir_graph (entity *ent, int n_loc) ir_graph * -new_ir_graph (entity *ent, int n_loc) +new_ir_graph(entity *ent, int n_loc) { - ir_graph *res = new_r_ir_graph (ent, n_loc); + ir_graph *res = new_r_ir_graph(ent, n_loc); add_irp_irg(res); /* remember this graph global. */ return res; } @@ -478,6 +479,16 @@ void _set_irg_globals(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); diff --git a/ir/ir/irgraph.h b/ir/ir/irgraph.h index 1500e8f9a..115dc9ff9 100644 --- a/ir/ir/irgraph.h +++ b/ir/ir/irgraph.h @@ -56,22 +56,26 @@ * *frame The ir_node producing the pointer to the stack frame of * the procedure as output. This is the Proj node on the * third output of the start node. This output of the start - * node is tagged as pns_frame_base. In FIRM most local + * node is tagged as pns_frame_base. In FIRM most local * variables are modeled as data flow edges. Static * allocated arrays can not be represented as data flow * edges. Therefore FIRM has to represent them in the stack * frame. * * *globals This models a pointer to a space in the memory where - * _all_ global things are held. Select from this pointer - * with a Sel node the pointer to a global variable / - * procedure / compiler known function... . + * _all_ global things are held. Select from this pointer + * with a Sel node the pointer to a global variable / + * procedure / compiler known function... . * - * *args The ir_node that produces the arguments of the method as - * it's result. This is a Proj node on the fourth output of - * the start node. This output is tagged as pn_Start_T_args. + * *tls This models a pointer to a space in the memory where + * thread local things are held. Select from this pointer + * with a Sel node the pointer to a thread local variable. * - * *proj_args The proj nodes of the args node. + * *args The ir_node that produces the arguments of the method as + * it's result. This is a Proj node on the fourth output of + * the start node. This output is tagged as pn_Start_T_args. + * + * *proj_args The proj nodes of the args node. * * *bad The Bad node is an auxiliary node. It is needed only once, * so there is this globally reachable node. @@ -89,14 +93,14 @@ * Only needed for ir construction. * * params/n_loc An int giving the number of local variables in this - * procedure. This is needed for ir construction. Name will - * be changed. + * procedure. This is needed for ir construction. Name will + * be changed. * * *value_table This hash table (pset) is used for global value numbering - * for optimizing use in iropt.c. + * for optimizing use in iropt.c. * * *Phi_in_stack; a stack needed for automatic Phi construction, needed only - * during ir construction. + * during ir construction. * * visited A int used as flag to traverse the ir_graph. * @@ -137,7 +141,7 @@ void set_interprocedural_view(int state); * procedure: * * - The start block containing a start node and Proj nodes for it's - * five results (X, M, P, P, T). + * seven results (X, M, P, P, P, T, P). * - The end block containing an end node. This block is not matured * after executing new_ir_graph() as predecessors need to be added to it. * (Maturing a block means fixing it's number of predecessors.) @@ -220,6 +224,11 @@ ir_node *get_irg_globals (const ir_graph *irg); /** Sets the node that represents the global pointer. */ void set_irg_globals (ir_graph *irg, ir_node *node); +/** Returns the node that represents the tls pointer. */ +ir_node *get_irg_tls (const ir_graph *irg); +/** Sets the node that represents the tls pointer. */ +void set_irg_tls (ir_graph *irg, ir_node *node); + /** Returns the node that represents the initial memory. */ ir_node *get_irg_initial_mem (const ir_graph *irg); /** Sets the node that represents the initial memory. */ diff --git a/ir/ir/irgraph_t.h b/ir/ir/irgraph_t.h index 034d1afe6..04fd7345b 100644 --- a/ir/ir/irgraph_t.h +++ b/ir/ir/irgraph_t.h @@ -64,6 +64,8 @@ enum irg_anchors { anchor_frame, /**< method's frame */ anchor_globals, /**< pointer to the data segment containing all globals as well as global procedures. */ + 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 @@ -271,6 +273,16 @@ _set_irg_globals(ir_graph *irg, ir_node *node) { irg->anchors[anchor_globals] = node; } +static INLINE ir_node * +_get_irg_tls(const ir_graph *irg) { + return irg->anchors[anchor_tls]; +} + +static INLINE void +_set_irg_tls(ir_graph *irg, ir_node *node) { + irg->anchors[anchor_tls] = node; +} + static INLINE ir_node * _get_irg_initial_mem(const ir_graph *irg) { return irg->anchors[anchor_initial_mem]; @@ -583,6 +595,8 @@ get_idx_irn(ir_graph *irg, unsigned idx) { #define set_irg_frame(irg, node) _set_irg_frame(irg, node) #define get_irg_globals(irg) _get_irg_globals(irg) #define set_irg_globals(irg, node) _set_irg_globals(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) diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c index e16438177..b4f025e28 100644 --- a/ir/ir/irnode.c +++ b/ir/ir/irnode.c @@ -592,8 +592,7 @@ set_nodes_block (ir_node *node, ir_node *block) { /* Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base) * from Start. If so returns frame type, else Null. */ ir_type *is_frame_pointer(ir_node *n) { - if ((get_irn_op(n) == op_Proj) && - (get_Proj_proj(n) == pn_Start_P_frame_base)) { + if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) { ir_node *start = get_Proj_pred(n); if (get_irn_op(start) == op_Start) { return get_irg_frame_type(get_irn_irg(start)); @@ -605,8 +604,7 @@ ir_type *is_frame_pointer(ir_node *n) { /* Test whether arbitrary node is globals pointer, i.e. Proj(pn_Start_P_globals) * from Start. If so returns global type, else Null. */ ir_type *is_globals_pointer(ir_node *n) { - if ((get_irn_op(n) == op_Proj) && - (get_Proj_proj(n) == pn_Start_P_globals)) { + if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) { ir_node *start = get_Proj_pred(n); if (get_irn_op(start) == op_Start) { return get_glob_type(); @@ -615,6 +613,18 @@ ir_type *is_globals_pointer(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(ir_node *n) { + if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) { + ir_node *start = get_Proj_pred(n); + if (get_irn_op(start) == op_Start) { + return get_tls_type(); + } + } + return NULL; +} + /* Test whether arbitrary node is value arg base, i.e. Proj(pn_Start_P_value_arg_base) * from Start. If so returns 1, else 0. */ int is_value_arg_pointer(ir_node *n) { diff --git a/ir/ir/irnode.h b/ir/ir/irnode.h index 2b6934fba..fd1b3d675 100644 --- a/ir/ir/irnode.h +++ b/ir/ir/irnode.h @@ -245,14 +245,16 @@ typedef enum { pn_Start_M, /**< Projection on the initial memory. */ pn_Start_P_frame_base, /**< Projection on the frame base pointer. */ pn_Start_P_globals, /**< Projection on the pointer to the data segment - containing _all_ global entities. */ + containing _all_ global entities. Use for + position independent data/code access. */ + pn_Start_P_tls, /**< Projection on the pointer to the thread local store + segment containing _all_thread local variables. */ pn_Start_T_args, /**< Projection on all arguments. */ pn_Start_P_value_arg_base, /**< Pointer to region of compound value arguments as defined by type of this method. */ pn_Start_max /**< number of projections from a Start */ } pn_Start; /* Projection numbers for Start. */ - /** Test whether arbitrary node is frame pointer. * * Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base) @@ -265,6 +267,12 @@ ir_type *is_frame_pointer(ir_node *n); * from Start. If so returns global type, else Null. */ ir_type *is_globals_pointer(ir_node *n); +/** Test whether arbitrary node is 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. */ +ir_type *is_tls_pointer(ir_node *n); + /** Test whether arbitrary node is value arg base. * * Test whether arbitrary node is value arg base, i.e. Proj(pn_Start_P_value_arg_base) diff --git a/ir/ir/irprog.c b/ir/ir/irprog.c index 7c588b599..cc01bcd11 100644 --- a/ir/ir/irprog.c +++ b/ir/ir/irprog.c @@ -26,7 +26,11 @@ #include "typegmod.h" #include "irop_t.h" +/** The name of the Global Type. */ #define GLOBAL_TYPE_NAME "GlobalType" +/** The name of the Thread Local STorage Type. */ +#define TLS_TYPE_NAME "TLS" +/** The initial name of the irp program. */ #define INITAL_PROG_NAME "no_name_set" /* A variable from where everything in the ir can be accessed. */ @@ -39,7 +43,7 @@ ir_prog *get_irp(void) { return irp; } static ir_prog *new_incomplete_ir_prog (void) { ir_prog *res; - res = xmalloc (sizeof(*res)); + res = xmalloc(sizeof(*res)); memset(res, 0, sizeof(*res)); irp = res; @@ -59,13 +63,15 @@ static ir_prog *new_incomplete_ir_prog (void) { /** Completes an incomplete irprog. */ static ir_prog *complete_ir_prog(ir_prog *irp) { +#define X(s) s, sizeof(s)-1 + irp->name = new_id_from_chars(X(INITAL_PROG_NAME)); - irp->name = new_id_from_str(INITAL_PROG_NAME); - - irp->glob_type = new_type_class(new_id_from_str (GLOBAL_TYPE_NAME)); - /* Remove type from type list. Must be treated differently than + irp->glob_type = new_type_class(new_id_from_chars(X(GLOBAL_TYPE_NAME))); + irp->tls_type = new_type_struct(new_id_from_chars(X(TLS_TYPE_NAME))); + /* Remove these types from type list. Must be treated differently than other types. */ remove_irp_type(irp->glob_type); + remove_irp_type(irp->tls_type); irp->const_code_irg = new_const_code_irg(); @@ -99,6 +105,8 @@ ir_prog *new_ir_prog (void) { void free_ir_prog(void) { if (irp->glob_type) free_type(irp->glob_type); + if (irp->tls_type) + free_type(irp->tls_type); /* @@@ * free_ir_graph(irp->const_code_irg); * ?? End has no in?? */ DEL_ARR_F(irp->graphs); @@ -130,6 +138,10 @@ ir_type *(get_glob_type)(void) { return _get_glob_type(); } +ir_type *(get_tls_type)(void) { + return _get_tls_type(); +} + /* Adds irg to the list of ir graphs in irp. */ void add_irp_irg(ir_graph *irg) { assert (irg != NULL); @@ -186,7 +198,7 @@ void set_irp_irg(int pos, ir_graph *irg) { } /* Gets the number of graphs _and_ pseudo graphs. */ -int get_irp_n_allirgs(void) { +int get_irp_n_allirgs(void) { /* We can not call get_irp_n_irgs, as we end up in a recursion ... */ return ARR_LEN(irp->graphs) + get_irp_n_pseudo_irgs(); } diff --git a/ir/ir/irprog.h b/ir/ir/irprog.h index 68a95573d..5c6598553 100644 --- a/ir/ir/irprog.h +++ b/ir/ir/irprog.h @@ -131,10 +131,18 @@ int get_irp_n_allirgs(void); pseudo graphs). Visits first graphs, then pseudo graphs. */ ir_graph *get_irp_allirg(int pos); - -/** Returns the "global" type of the irp. */ +/** + * Returns the "global" type of the irp. + * Upon creation this is an empty class type. + */ ir_type *get_glob_type(void); +/** + * Returns the "thread local storage" type of the irp. + * Upon creation this is an empty struct type. + */ +ir_type *get_tls_type(void); + /** Adds type to the list of types in irp. */ void add_irp_type(ir_type *typ); diff --git a/ir/ir/irprog_t.h b/ir/ir/irprog_t.h index b3e3f91af..51781d0a2 100644 --- a/ir/ir/irprog_t.h +++ b/ir/ir/irprog_t.h @@ -48,8 +48,10 @@ struct ir_prog { to allocate nodes the represent values of constant entities. It is not meant as a procedure. */ - ir_type *glob_type; /**< global type. Must be a class as it can + ir_type *glob_type; /**< The global type. Must be a class as it can have fields and procedures. */ + ir_type *tls_type; /**< The thread local storage type. Must be a struct as it can + only have fields. */ ir_type **types; /**< all types in the ir */ ir_mode **modes; /**< all modes in the ir */ ir_op **opcodes; /**< all opcodes in the ir */ @@ -96,6 +98,12 @@ _get_glob_type(void) { return irp->glob_type = skip_tid(irp->glob_type); } +static INLINE ir_type * +_get_tls_type(void) { + assert(irp); + return irp->tls_type = skip_tid(irp->tls_type); +} + static INLINE int _get_irp_n_irgs(void) { assert (irp && irp->graphs); @@ -181,5 +189,6 @@ void init_irprog_2(void); #define get_irp_opcode(pos) _get_irp_opcode(pos) #define get_const_code_irg() _get_const_code_irg() #define get_glob_type() _get_glob_type() +#define get_tls_type() _get_tls_type() #endif /* ifndef _FIRM_IR_IRPROG_T_H_ */