implemented new beabi interface
[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         cnst = new_rd_ia32_Const(dbg, irg, block, mode);
47         set_ia32_Const_attr(cnst, env->irn);
48         return cnst;
49 }
50
51 /**
52  * Get a primitive type for a mode.
53  */
54 static ir_type *get_prim_type(pmap *types, ir_mode *mode)
55 {
56         pmap_entry *e = pmap_find(types, mode);
57         ir_type *res;
58
59         if (! e) {
60                 char buf[64];
61                 snprintf(buf, sizeof(buf), "prim_type_%s", get_mode_name(mode));
62                 res = new_type_primitive(new_id_from_str(buf), mode);
63                 pmap_insert(types, mode, res);
64         }
65         else
66                 res = e->value;
67         return res;
68 }
69
70 /**
71  * Get an entity that is initialized with a tarval
72  */
73 static entity *get_entity_for_tv(ia32_code_gen_t *cg, ir_node *cnst)
74 {
75         tarval *tv    = get_Const_tarval(cnst);
76         pmap_entry *e = pmap_find(cg->tv_ent, tv);
77         entity *res;
78         ir_graph *rem;
79
80         if (! e) {
81                 ir_mode *mode = get_irn_mode(cnst);
82                 ir_type *tp = get_Const_type(cnst);
83                 if (tp == firm_unknown_type)
84                         tp = get_prim_type(cg->types, mode);
85
86                 res = new_entity(get_glob_type(), unique_id("ia32FloatCnst_%u"), tp);
87
88                 set_entity_ld_ident(res, get_entity_ident(res));
89                 set_entity_visibility(res, visibility_local);
90                 set_entity_variability(res, variability_constant);
91                 set_entity_allocation(res, allocation_static);
92
93                  /* we create a new entity here: It's initialization must resist on the
94                     const code irg */
95                 rem = current_ir_graph;
96                 current_ir_graph = get_const_code_irg();
97                 set_atomic_ent_value(res, new_Const_type(tv, tp));
98                 current_ir_graph = rem;
99         }
100         else
101                 res = e->value;
102         return res;
103 }
104
105 /**
106  * Transforms a Const.
107  *
108  * @param mod     the debug module
109  * @param block   the block the new node should belong to
110  * @param node    the ir Const node
111  * @param mode    mode of the Const
112  * @return the created ia32 Const node
113  */
114 static ir_node *gen_Const(ia32_transform_env_t *env) {
115         ir_node *cnst;
116         symconst_symbol sym;
117         ir_graph *irg   = env->irg;
118         ir_node  *block = env->block;
119         ir_node  *node  = env->irn;
120         dbg_info *dbg   = env->dbg;
121         ir_mode  *mode  = env->mode;
122
123         if (mode_is_float(mode)) {
124                 sym.entity_p = get_entity_for_tv(env->cg, node);
125
126                 cnst = new_rd_SymConst(dbg, irg, block, sym, symconst_addr_ent);
127                 env->irn = cnst;
128                 cnst = gen_SymConst(env);
129         }
130         else {
131                 cnst = new_rd_ia32_Const(dbg, irg, block, get_irn_mode(node));
132                 set_ia32_Const_attr(cnst, node);
133         }
134         return cnst;
135 }
136
137
138
139 /**
140  * Transforms (all) Const's into ia32_Const and places them in the
141  * block where they are used (or in the cfg-pred Block in case of Phi's)
142  */
143 void ia32_place_consts(ir_node *irn, void *env) {
144         ia32_code_gen_t      *cg = env;
145         ia32_transform_env_t  tenv;
146         ir_mode              *mode;
147         ir_node              *pred, *cnst;
148         int                   i;
149         opcode                opc;
150
151         if (is_Block(irn))
152                 return;
153
154         mode = get_irn_mode(irn);
155
156         tenv.arch_env = cg->arch_env;
157         tenv.block    = get_nodes_block(irn);
158         tenv.cg       = cg;
159         tenv.irg      = cg->irg;
160         tenv.mod      = firm_dbg_register("firm.be.ia32.optimize");
161
162         /* Loop over all predecessors and check for Sym/Const nodes */
163         for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
164                 pred      = get_irn_n(irn, i);
165                 cnst      = NULL;
166                 opc       = get_irn_opcode(pred);
167                 tenv.irn  = pred;
168                 tenv.mode = get_irn_mode(pred);
169                 tenv.dbg  = get_irn_dbg_info(pred);
170
171                 /* If it's a Phi, then we need to create the */
172                 /* new Const in it's predecessor block       */
173                 if (is_Phi(irn)) {
174                         tenv.block = get_Block_cfgpred_block(get_nodes_block(irn), i);
175                 }
176
177                 switch (opc) {
178                         case iro_Const:
179                                 cnst = gen_Const(&tenv);
180                                 break;
181                         case iro_SymConst:
182                                 cnst = gen_SymConst(&tenv);
183                                 break;
184                         default:
185                                 break;
186                 }
187
188                 /* if we found a const, then set it */
189                 if (cnst) {
190                         set_irn_n(irn, i, cnst);
191                 }
192         }
193 }