Initializers for entities must be allocated on the const code irg
[libfirm] / ir / be / ia32 / ia32_optimize.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "irnode.h"
6 #include "irprog_t.h"
7 #include "ircons.h"
8 #include "firm_types.h"
9
10 #include "ia32_new_nodes.h"
11 #include "bearch_ia32_t.h"
12
13 /**
14  * creates a unique ident by adding a number to a tag
15  *
16  * @param tag   the tag string, must contain a %d if a number
17  *              should be added
18  */
19 static ident *unique_id(const char *tag)
20 {
21   static unsigned id = 0;
22   char str[256];
23
24   snprintf(str, sizeof(str), tag, ++id);
25   return new_id_from_str(str);
26 }
27
28
29
30 /**
31  * Transforms a SymConst.
32  *
33  * @param mod     the debug module
34  * @param block   the block the new node should belong to
35  * @param node    the ir SymConst node
36  * @param mode    mode of the SymConst
37  * @return the created ia32 Const node
38  */
39 static ir_node *gen_SymConst(ia32_transform_env_t *env) {
40         ir_node  *cnst;
41         dbg_info *dbg   = env->dbg;
42         ir_mode  *mode  = env->mode;
43         ir_graph *irg   = env->irg;
44         ir_node  *block = env->block;
45
46         if (mode_is_float(mode)) {
47                 cnst = new_rd_ia32_fConst(dbg, irg, block, mode);
48
49         }
50         else {
51                 cnst = new_rd_ia32_Const(dbg, irg, block, mode);
52         }
53
54         set_ia32_Const_attr(cnst, env->irn);
55         return cnst;
56 }
57
58 /**
59  * Transforms a Const.
60  *
61  * @param mod     the debug module
62  * @param block   the block the new node should belong to
63  * @param node    the ir Const node
64  * @param mode    mode of the Const
65  * @return the created ia32 Const node
66  */
67 static ir_node *gen_Const(ia32_transform_env_t *env) {
68         ir_node *cnst;
69         entity  *ent;
70         ir_type *tp;
71         symconst_symbol sym;
72         dbg_info *dbg   = env->dbg;
73         ir_mode  *mode  = env->mode;
74         ir_graph *irg   = env->irg;
75         ir_node  *block = env->block;
76         ir_node  *node  = env->irn;
77         ir_graph *rem;
78
79         if (mode_is_float(mode)) {
80                 tp  = get_Const_type(node);
81                 if (tp == firm_unknown_type) {
82                         tp = new_type_primitive(unique_id("tp_ia32_float_%u"), mode);
83                 }
84
85                 ent = new_entity(get_glob_type(), unique_id("ia32FloatCnst_%u"), tp);
86
87                 set_entity_ld_ident(ent, get_entity_ident(ent));
88                 set_entity_visibility(ent, visibility_local);
89                 set_entity_variability(ent, variability_constant);
90                 set_entity_allocation(ent, allocation_static);
91
92                  /* we create a new entity here: It's initialization must resist on the
93                     const code irg */
94                 rem = current_ir_graph;
95                 current_ir_graph = get_const_code_irg();
96                 set_atomic_ent_value(ent, copy_const_value(NULL, node));
97                 current_ir_graph = rem;
98
99                 sym.entity_p = ent;
100
101                 cnst = new_rd_SymConst(dbg, irg, block, sym, symconst_addr_ent);
102                 env->irn = cnst;
103                 cnst = gen_SymConst(env);
104         }
105         else {
106                 cnst = new_rd_ia32_Const(dbg, irg, block, mode);
107                 set_ia32_Const_attr(cnst, node);
108         }
109
110         return cnst;
111 }
112
113
114
115 /**
116  * Transforms (all) Const's into ia32_Const and places them in the
117  * block where they are used (or in the cfg-pred Block in case of Phi's)
118  */
119 void ia32_place_consts(ir_node *irn, void *env) {
120         ia32_code_gen_t      *cg = env;
121         ia32_transform_env_t  tenv;
122         ir_mode              *mode;
123         ir_node              *pred, *cnst;
124         int                   i;
125         opcode                opc;
126
127         if (is_Block(irn))
128                 return;
129
130         mode = get_irn_mode(irn);
131
132         tenv.arch_env = cg->arch_env;
133         tenv.block    = get_nodes_block(irn);
134         tenv.cg       = cg;
135         tenv.irg      = cg->irg;
136         tenv.mod      = firm_dbg_register("ir.be.ia32.optimize");
137
138         /* Loop over all predecessors and check for Sym/Const nodes */
139         for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
140                 pred      = get_irn_n(irn, i);
141                 cnst      = NULL;
142                 opc       = get_irn_opcode(pred);
143                 tenv.irn  = pred;
144                 tenv.mode = get_irn_mode(pred);
145                 tenv.dbg  = get_irn_dbg_info(pred);
146
147                 /* If it's a Phi, then we need to create the */
148                 /* new Const in it's predecessor block       */
149                 if (is_Phi(irn)) {
150                         tenv.block = get_Block_cfgpred_block(get_nodes_block(irn), i);
151                 }
152
153                 switch (opc) {
154                         case iro_Const:
155                                 cnst = gen_Const(&tenv);
156                                 break;
157                         case iro_SymConst:
158                                 cnst = gen_SymConst(&tenv);
159                                 break;
160                         default:
161                                 break;
162                 }
163
164                 /* if we found a const, then set it */
165                 if (cnst) {
166                         set_irn_n(irn, i, cnst);
167                 }
168         }
169 }