Added sparse matrix impl. Used by copyopt_ilp
[libfirm] / ir / be / bearch.c
1 /**
2  * Processor architecture specification.
3  * @author Sebastian Hack
4  * @date 11.2.2005
5  *
6  * $Id$
7  */
8
9 #include <string.h>
10
11 #include "bearch_t.h"
12
13 #include "firm_config.h"
14 #include "pset.h"
15
16 #include "entity.h"
17 #include "ircons_t.h"
18
19 #if 1 /* HAVE_ALLOCA_H */
20 #include <alloca.h>
21 #endif /* HAVE_ALLOCA_H */
22
23 /* Needed for obstack copy */
24 #define bcopy(src,dst,n) memcpy(dst,src,n)
25
26 #define INIT_HEADER(tgt, kind_suffix, a_isa, str) \
27         do { \
28                 arch_header_t *h = (arch_header_t *) (tgt); \
29                 memset(tgt, 0, sizeof(*(tgt))); \
30                 h->kind = arch_kind_ ## kind_suffix; \
31                 h->name = new_id_from_str(str); \
32                 h->isa = a_isa; \
33         } while(0)
34
35 static INLINE int hash_header(const arch_header_t *header)
36 {
37         int res = HASH_PTR(header->isa);
38         res = 37 * res + HASH_STR(header->name, strlen(header->name));
39         res = 37 * res + header->kind;
40         return res;
41 }
42
43 static int cmp_header(const void *a, const void *b)
44 {
45         const arch_header_t *h1 = a;
46         const arch_header_t *h2 = b;
47
48         return !(h1->kind == h2->kind && h1->isa == h2->isa && strcmp(h1->name, h2->name) == 0);
49 }
50
51 /**
52  * The obstack and pset where the arch data is stored.
53  */
54 typedef struct _arch_data_t {
55         struct obstack obst;                    /**< Here is the data allocated. */
56         pset *header_set;                                       /**< Here reside copies of the headers. */
57 } arch_data_t;
58
59 /**
60  * Get the storage (obstack and pset) for the arch objects.
61  * @return A struct containing both, the obst and pset where
62  * the objects are allocated and their pointer are recorded.
63  */
64 static INLINE arch_data_t *get_arch_data(void)
65 {
66         static arch_data_t arch_data;
67         static int inited = 0;
68
69         if(!inited) {
70                 obstack_init(&arch_data.obst);
71                 arch_data.header_set = new_pset(cmp_header, 512);
72                 inited = 1;
73         }
74
75         return &arch_data;
76 }
77
78 /**
79  * Dump all arch objects in the arch_data collection.
80  */
81 static void dump_arch_data(void)
82 {
83         void *p;
84         arch_data_t *d = get_arch_data();
85         static const char *kind_names[] = {
86 #define ARCH_OBJ(name,in_list)  #name,
87 #include "bearch_obj.def"
88 #undef ARCH_OBJ
89                 ""
90         };
91
92         printf("arch set:\n");
93         for(p = pset_first(d->header_set); p; p = pset_next(d->header_set)) {
94                 arch_header_t *header = p;
95                 printf("%20s %10s %10s\n", kind_names[header->kind], header->name,
96                                 header->isa ? header->isa->header.name : "");
97         }
98 }
99
100 typedef struct _obj_info_t {
101         const char *name;
102         int listed_in_isa;
103         size_t size;
104 } obj_info_t;
105
106 static const obj_info_t obj_info[] = {
107 #define ARCH_OBJ(name,listed_in_isa)            { #name, listed_in_isa, sizeof(arch_ ## name ## _t) },
108 #include "bearch_obj.def"
109 #undef ARCH_OBJ
110         { 0 }
111 };
112
113 /**
114  * Insert an arch object to the global arch obj storage.
115  *
116  * If the object has already been created there, nothing is done and
117  * the old object is created.
118  *
119  * @param kind The kind of the arch object.
120  * @param isa The isa the object belongs to or NULL if it is the isa
121  * itself.
122  * @param name The name of the object.
123  * @return A pointer to the object.
124  */
125 static INLINE void *_arch_data_insert(arch_kind_t kind, arch_isa_t *isa,
126                 const char *name, size_t size)
127 {
128         arch_data_t *ad = get_arch_data();
129         const obj_info_t *info = &obj_info[kind];
130         arch_header_t *header = obstack_alloc(&ad->obst, size);
131         arch_header_t *res = NULL;
132
133         memset(header, 0, size);
134         header->name = name;
135         header->kind = kind;
136         header->isa = isa;
137         header->is_new = 1;
138
139         res = pset_insert(ad->header_set, header, hash_header(header));
140
141         /*
142          * If the object is newly created and thus not yet present
143          * in the set, add it to the isa
144          * The inserted object was no isa, list it in the isa if this is
145          * desired.
146          */
147         if(res->is_new && isa && info->listed_in_isa) {
148                 list_add(&res->list, &isa->heads[kind]);
149         }
150
151         /* if it was in the set, remove it from the obstack */
152         if(!res->is_new)
153                 obstack_free(&ad->obst, header);
154
155         /* Mark the object as NOT new. */
156         res->is_new = 0;
157
158         return res;
159 }
160
161 #define arch_data_insert(type_suffix, isa, name) \
162         _arch_data_insert(arch_kind_ ## type_suffix, isa, name, sizeof(arch_ ## type_suffix ## _t))
163
164 static INLINE void *_arch_data_find(arch_kind_t kind, const arch_isa_t *isa, const char *name)
165 {
166         arch_header_t header;
167
168         header.kind = kind;
169         header.isa = (arch_isa_t *) isa;
170         header.name = name;
171
172         return pset_find(get_arch_data()->header_set, &header, hash_header(&header));
173 }
174
175 #define arch_data_find(type_suffix, isa, name) \
176         _arch_data_find(arch_kind_ ## type_suffix, isa, name)
177
178 arch_isa_t *arch_add_isa(const char *name)
179 {
180         arch_isa_t *isa;
181         int i;
182
183         isa = arch_data_insert(isa, NULL, name);
184         for(i = 0; i < arch_kind_last; ++i)
185                 INIT_LIST_HEAD(&isa->heads[i]);
186
187         return isa;
188 }
189
190 arch_register_set_t *arch_add_register_set(arch_isa_t *isa,
191                 const arch_register_class_t *cls, const char *name)
192 {
193         arch_register_set_t *set =
194                 _arch_data_insert(arch_kind_register_set, isa, name,
195                                 sizeof(arch_register_set_t) + cls->n_regs * sizeof(set->regs[0]));
196
197         set->reg_class = cls;
198         memset(set->regs, 0, sizeof(set->regs[0]) * cls->n_regs);
199
200         return set;
201 }
202
203 arch_register_class_t *arch_add_register_class(arch_isa_t *isa, const char *name, int n_regs)
204 {
205         char buf[64];
206         char *set_name;
207         int i, n;
208
209         arch_register_class_t *cls =
210                 _arch_data_insert(arch_kind_register_class, isa, name,
211                                 sizeof(arch_register_class_t) + n_regs * sizeof(arch_register_t *));
212
213         /* Make a name for the set contianing all regs in this class. */
214         n = snprintf(buf, sizeof(buf), "%s$set", name);
215         set_name = obstack_copy(&get_arch_data()->obst, buf, n);
216
217         cls->n_regs = n_regs;
218
219         /* make the set of all registers in this class */
220         cls->set = arch_add_register_set(isa, cls, name);
221
222         /* Add each register in this class to the set */
223         for(i = 0; i < n_regs; ++i)
224                 cls->set->regs[i] = 1;
225
226         return cls;
227 }
228
229 void arch_register_set_add_register(arch_register_set_t *set, int index)
230 {
231         assert(index >= 0 && index < set->reg_class->n_regs);
232         set->regs[index] = 1;
233 }
234
235 arch_register_t *arch_add_register(arch_register_class_t *cls, int index, const char *name)
236 {
237         arch_register_t *reg = NULL;
238
239         assert(index >= 0 && index < cls->n_regs);
240         reg = _arch_data_insert(arch_kind_register, arch_obj_get_isa(cls), name,
241                         sizeof(arch_register_t));
242         cls->regs[index] = reg;
243
244         reg->index = index;
245         reg->reg_class = cls;
246         reg->flags = arch_register_flag_none;
247
248         return reg;
249 }
250
251 arch_immediate_t *arch_add_immediate(arch_isa_t *isa, const char *name, ir_mode *mode)
252 {
253         arch_immediate_t *imm = arch_data_insert(immediate, isa, name);
254         imm->mode = mode;
255         return imm;
256 }
257
258 /*
259  * Size of each operand type which should be allocated in an irn.
260  * Keep this list up to date with the arch_operand_type_t enum.
261  */
262 static const size_t operand_sizes[] = {
263 #define ARCH_OPERAND_TYPE(name,size_in_irn) size_in_irn,
264 #include "bearch_operand_types.def"
265 #undef ARCH_OPERAND_TYPE
266         0
267 };
268
269 /**
270  * Determine the amount of bytes which has to be extra allocated when a
271  * new ir node is made from a insn format.
272  * This size depends on the operands specified in the insn format.
273  * @param fmt The instruction format.
274  * @return The number of bytes which the operands of an instruction
275  * will need in an ir node.
276  */
277 static INLINE int arch_get_operands_size(const arch_insn_format_t *fmt)
278 {
279         int i, res = 0;
280
281         for(i = 0; i < fmt->n_in + fmt->n_out; ++i) {
282                 arch_operand_type_t type = fmt->operands[i].type;
283
284                 assert(type > arch_operand_type_invalid && type < arch_operand_type_last);
285                 res += operand_sizes[type];
286         }
287
288         return res;
289 }
290
291 arch_insn_format_t *arch_add_insn_format(arch_isa_t *isa, const char *name, int n_in, int n_out)
292 {
293         int i;
294
295         arch_insn_format_t *fmt =
296                 _arch_data_insert(arch_kind_insn_format, isa, name,
297                                 sizeof(arch_insn_format_t) + (n_in + n_out) * sizeof(arch_operand_t));
298
299         fmt->n_in = n_in;
300         fmt->n_out = n_out;
301
302         /* initialize each operand with invalid. */
303         for(i = 0; i < n_in + n_out; ++i)
304                 fmt->operands[i].type = arch_operand_type_invalid;
305
306         return fmt;
307 }
308
309 arch_insn_t *arch_add_insn(arch_insn_format_t *fmt, const char *name)
310 {
311         /* Get the size the operands will need in the irn. */
312         int operands_size = arch_get_operands_size(fmt);
313
314         /* Insert the insn into the isa. */
315         arch_insn_t *insn = arch_data_insert(insn, arch_obj_get_isa(fmt), name);
316
317         insn->format = fmt;
318         insn->op = new_ir_op(get_next_ir_opcode(), name, op_pin_state_pinned, 0,
319                         oparity_dynamic, 0, sizeof(arch_irn_data_t) + operands_size);
320
321         return insn;
322 }
323
324 arch_insn_format_t *arch_find_insn_format(const arch_isa_t *isa, const char *name)
325 {
326         return arch_data_find(insn_format, isa, name);
327 }
328
329 arch_isa_t *arch_find_isa(const char *name)
330 {
331         return arch_data_find(isa, NULL, name);
332 }
333
334 arch_insn_t *arch_find_insn(const arch_isa_t *isa, const char *name)
335 {
336         return arch_data_find(insn, isa, name);
337 }
338
339 arch_immediate_t *arch_find_immediate(const arch_isa_t *isa, const char *name)
340 {
341         return arch_data_find(immediate, isa, name);
342 }
343
344 arch_register_class_t *arch_find_register_class(const arch_isa_t *isa, const char *name)
345 {
346         return arch_data_find(register_class, isa, name);
347 }
348
349 arch_register_set_t *arch_find_register_set(const arch_isa_t *isa, const char *name)
350 {
351         return arch_data_find(register_set, isa, name);
352 }
353
354 arch_register_set_t *arch_get_register_set_for_class(arch_register_class_t *cls)
355 {
356         return _arch_get_register_set_for_class(cls);
357 }
358
359 static INLINE arch_operand_t *_arch_set_operand(arch_insn_format_t *fmt, int pos,
360                 arch_operand_type_t type)
361 {
362         arch_operand_t *operand;
363         int ofs = arch_inout_to_index(fmt, pos);
364
365         assert(ofs < fmt->n_in + fmt->n_out);
366
367         operand = &fmt->operands[ofs];
368         operand->type = type;
369         return operand;
370 }
371
372 arch_operand_t *arch_set_operand_register_set(arch_insn_format_t *fmt,
373                 int pos, const arch_register_set_t *set)
374 {
375         arch_operand_t *op = _arch_set_operand(fmt, pos, arch_operand_type_register_set);
376         op->data.set = set;
377         return op;
378 }
379
380 arch_operand_t *arch_set_operand_callback(arch_insn_format_t *fmt,
381                 int pos, arch_register_callback_t *cb)
382 {
383         arch_operand_t *op = _arch_set_operand(fmt, pos, arch_operand_type_callback);
384         op->data.callback = cb;
385         return op;
386 }
387
388 arch_operand_t *arch_set_operand_immediate(arch_insn_format_t *fmt,
389                 int pos, const arch_immediate_t *imm)
390 {
391         arch_operand_t *op = _arch_set_operand(fmt, pos, arch_operand_type_immediate);
392         op->data.imm = imm;
393         return op;
394 }
395
396 arch_operand_t *arch_set_operand_memory(arch_insn_format_t *fmt, int pos)
397 {
398         arch_operand_t *op = _arch_set_operand(fmt, pos, arch_operand_type_memory);
399         return op;
400 }
401
402 arch_operand_t *arch_set_operand_equals(arch_insn_format_t *fmt, int pos, int same_as_pos)
403 {
404         arch_operand_t *op = _arch_set_operand(fmt, pos, arch_operand_type_equals);
405         op->data.same_as_pos = same_as_pos;
406         return op;
407 }
408
409 ir_node *arch_new_node(const arch_insn_t *insn, ir_graph *irg, ir_node *block,
410                 ir_mode *mode, int arity, ir_node **in)
411 {
412         ir_node *irn = new_ir_node(NULL, irg, block, insn->op, mode, arity, in);
413         arch_irn_data_t *data = (void *) &irn->attr;
414
415         data->magic = ARCH_IRN_FOURCC;
416         data->insn = insn;
417
418         return irn;
419 }
420
421 ir_node *arch_new_node_bare(const arch_insn_t *insn, ir_graph *irg, int arity)
422 {
423         int i;
424         ir_node **in = alloca(sizeof(in[0]) * arity);
425
426         for(i = 0; i < arity; ++i)
427                 in[i] = new_Unknown(mode_Is);
428
429         return arch_new_node(insn, irg, new_Unknown(mode_BB), mode_Is, arity, in);
430 }
431
432 ir_mode *arch_get_unknown_mode(void)
433 {
434         return mode_Is;
435 }