added support for Thread local storage
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Sat, 3 Jun 2006 02:11:07 +0000 (02:11 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Sat, 3 Jun 2006 02:11:07 +0000 (02:11 +0000)
[r7863]

ir/ir/irdump.c
ir/ir/irgopt.c
ir/ir/irgraph.c
ir/ir/irgraph.h
ir/ir/irgraph_t.h
ir/ir/irnode.c
ir/ir/irnode.h
ir/ir/irprog.c
ir/ir/irprog.h
ir/ir/irprog_t.h

index 4c0af7b..bf0c81a 100644 (file)
@@ -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
index e2d6332..884d7e6 100644 (file)
@@ -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;
 
   /* --
index 810007b..c91e41a 100644 (file)
@@ -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);
index 1500e8f..115dc9f 100644 (file)
  *      *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.
  *                       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. */
index 034d1af..04fd734 100644 (file)
@@ -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)
index e164381..b4f025e 100644 (file)
@@ -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) {
index 2b6934f..fd1b3d6 100644 (file)
@@ -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)
index 7c588b5..cc01bcd 100644 (file)
 #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();
 }
index 68a9557..5c65985 100644 (file)
@@ -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);
 
index b3e3f91..51781d0 100644 (file)
@@ -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_ */