X(X_initial_exec),
X(P_frame_base),
X(P_globals),
+ X(P_tls),
X(T_args),
X(P_value_arg_base)
#undef X
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;
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;
/* --
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);
* 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;
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;
}
_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);
* *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.
*
* 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.)
/** 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. */
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
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];
#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)
/* 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));
/* 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();
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) {
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)
* 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)
#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. */
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;
/** 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();
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);
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);
}
/* 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();
}
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);
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 */
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);
#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_ */