2 * This file implements the creation of the achitecture specific firm opcodes
3 * and the coresponding node constructors for the $arch assembler irg.
4 * @author Christian Wuerdig
15 #include "irgraph_t.h"
20 #include "firm_common_t.h"
23 #include "../bearch.h"
25 #include "ia32_nodes_attr.h"
26 #include "ia32_new_nodes.h"
30 /***********************************************************************************
33 * __| |_ _ _ __ ___ _ __ ___ _ __ _ _ __ | |_ ___ _ __| |_ __ _ ___ ___
34 * / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__| _/ _` |/ __/ _ \
35 * | (_| | |_| | | | | | | |_) | __/ | | | | | | || __/ | | || (_| | (_| __/
36 * \__,_|\__,_|_| |_| |_| .__/ \___|_| |_|_| |_|\__\___|_| |_| \__,_|\___\___|
39 ***********************************************************************************/
42 * Prints a tarval to file F.
43 * @param F output file
45 * @param brackets 1 == print square brackets around tarval
47 static void fprintf_tv(FILE *F, tarval *tv, int brackets) {
49 tarval_snprintf(buf, sizeof(buf), tv);
52 fprintf(F, "[%s]", buf);
54 fprintf(F, "%s", buf);
58 * Returns the name of a SymConst.
59 * @param symc the SymConst
60 * @return name of the SymConst
62 const char *get_sc_name(ir_node *symc) {
63 if (get_irn_opcode(symc) != iro_SymConst)
66 switch (get_SymConst_kind(symc)) {
67 case symconst_addr_name:
68 return get_id_str(get_SymConst_name(symc));
70 case symconst_addr_ent:
71 return get_entity_ld_name(get_SymConst_entity(symc));
74 assert(0 && "Unsupported SymConst");
79 * Dumper interface for dumping ia32 nodes in vcg.
80 * @param n the node to dump
81 * @param F the output file
82 * @param reason indicates which kind of information should be dumped
83 * @return 0 on success or != 0 on failure
85 static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
91 const arch_register_req_t **reqs;
92 const arch_register_t **slots;
95 case dump_node_opcode_txt:
96 name = get_irn_opname(n);
97 fprintf(F, "%s", name);
100 case dump_node_mode_txt:
101 mode = get_irn_mode(n);
103 if (mode == mode_BB || mode == mode_ANY || mode == mode_BAD || mode == mode_T) {
106 else if (is_ia32_Load(n)) {
107 mode = get_irn_mode(get_irn_n(n, 1));
109 else if (is_ia32_Store(n)) {
110 mode = get_irn_mode(get_irn_n(n, 2));
114 fprintf(F, "[%s]", get_mode_name(mode));
117 case dump_node_nodeattr_txt:
118 name = get_irn_opname(n);
119 p = name + strlen(name) - 2;
120 if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n)) {
121 tarval *tv = get_ia32_Immop_tarval(n);
123 fprintf_tv(F, tv, 1);
125 fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
128 else if (is_ia32_Call(n)) {
129 ir_node *sc = get_ia32_old_ir(get_ia32_old_ir(n));
131 fprintf(F, "&%s ", get_sc_name(sc));
135 case dump_node_info_txt:
136 attr = get_ia32_attr(n);
138 /* dump IN requirements */
139 if (get_irn_arity(n) > 0) {
140 reqs = get_ia32_in_req(n);
143 for (i = 0; i < get_irn_arity(n); i++) {
144 if (reqs[i]->type != arch_register_req_type_none)
145 fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->cls->name);
147 fprintf(F, "inreq[%d]=[none]\n", i);
152 fprintf(F, "NO IN REQS\n");
155 /* dump OUT requirements */
156 if (attr->n_res > 0) {
157 reqs = get_ia32_out_req(n);
160 for (i = 0; i < attr->n_res; i++) {
161 if (reqs[i]->type != arch_register_req_type_none)
162 fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->cls->name);
164 fprintf(F, "outreq[%d]=[none]\n", i);
168 fprintf(F, "NO OUT REQS\n");
171 /* dump assigned registers */
172 slots = get_ia32_slots(n);
173 if (slots && attr->n_res > 0) {
174 for (i = 0; i < attr->n_res; i++) {
176 fprintf(F, "REG[%d]=[%s]\n", i, slots[i]->name);
179 fprintf(F, "REG[%d]=[none]\n", i);
183 /* special for LEA */
184 if (is_ia32_Lea(n)) {
185 tarval *o = get_ia32_offs(n);
186 tarval *tv = get_ia32_Immop_tarval(n);
191 fprintf(F, "(%s, %s", get_irn_opname(get_irn_n(n, 0)), get_irn_opname(get_irn_n(n, 1)));
194 fprintf_tv(F, tv, 0);
206 /***************************************************************************************************
208 * | | | | | | / / | | | | | | | |
209 * __ _| |_| |_ _ __ ___ ___| |_ / /_ _ ___| |_ _ __ ___ ___| |_| |__ ___ __| |___
210 * / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
211 * | (_| | |_| |_| | \__ \ __/ |_ / / (_| | __/ |_ | | | | | | __/ |_| | | | (_) | (_| \__ \
212 * \__,_|\__|\__|_| |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
215 ***************************************************************************************************/
218 * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
219 * Firm was made by people hating const :-(
221 asmop_attr *get_ia32_attr(const ir_node *node) {
222 return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
226 * Return the tarval of an immediate operation or NULL in case of SymConst
228 tarval *get_ia32_Immop_tarval(const ir_node *node) {
229 asmop_attr *attr = get_ia32_attr(node);
230 if (attr->tp == asmop_Const)
237 * Return the old_ir attribute.
239 ir_node *get_ia32_old_ir(const ir_node *node) {
240 asmop_attr *attr = get_ia32_attr(node);
245 * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
247 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
248 asmop_attr *na = get_ia32_attr(node);
249 asmop_attr *ca = get_ia32_attr(cnst);
251 assert(is_ia32_Const(cnst) && "Need ia32_Const to set Immop attr");
255 na->old_ir = ca->old_ir;
259 * Copy the attributes from a Const to an ia32_Const
261 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
262 asmop_attr *attr = get_ia32_attr(ia32_cnst);
264 assert(is_ia32_Const(ia32_cnst) && "Need ia32_Const to set Const attr");
266 switch (get_irn_opcode(cnst)) {
268 attr->tp = asmop_Const;
269 attr->tv = get_Const_tarval(cnst);
272 attr->tp = asmop_SymConst;
273 attr->old_ir = calloc(1, sizeof(*cnst));
274 memcpy(attr->old_ir, cnst, sizeof(*cnst));
277 assert(0 && "Unknown Const NYI");
280 assert(0 && "Cannot create ia32_Const for this opcode");
285 * Sets the type of an ia32_Const.
287 void set_ia32_Const_type(ir_node *node, int type) {
288 asmop_attr *attr = get_ia32_attr(node);
290 assert(is_ia32_Const(node) && "Need ia32_Const to set type");
291 assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
297 * Sets the attributes of an immediate operation to the specified tarval
299 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
300 asmop_attr *attr = get_ia32_attr(node);
302 attr->tp = asmop_Const;
307 * Sets the offset for a Lea.
309 void set_ia32_offs(ir_node *node, tarval *offs) {
310 asmop_attr *attr = get_ia32_attr(node);
315 * Gets the offset for a Lea.
317 tarval *get_ia32_offs(const ir_node *node) {
318 asmop_attr *attr = get_ia32_attr(node);
323 * Returns the argument register requirements of an ia32 node.
325 const arch_register_req_t **get_ia32_in_req(const ir_node *node) {
326 asmop_attr *attr = get_ia32_attr(node);
331 * Returns the result register requirements of an ia32 node.
333 const arch_register_req_t **get_ia32_out_req(const ir_node *node) {
334 asmop_attr *attr = get_ia32_attr(node);
335 return attr->out_req;
339 * Returns the register flag of an ia32 node.
341 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
342 asmop_attr *attr = get_ia32_attr(node);
347 * Returns the result register slots of an ia32 node.
349 const arch_register_t **get_ia32_slots(const ir_node *node) {
350 asmop_attr *attr = get_ia32_attr(node);
355 * Returns the name of the IN register at position pos.
357 const char *get_ia32_in_reg_name(const ir_node *node, int pos) {
358 assert(0 && "in reg name not yet implemented");
362 * Returns the name of the OUT register at position pos.
364 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
365 asmop_attr *attr = get_ia32_attr(node);
367 assert(is_ia32_irn(node) && "Not an ia32 node.");
368 assert(pos < attr->n_res && "Invalid OUT position.");
370 return attr->slots[pos]->name;
374 * Returns the index of the IN register at position pos within its register class.
376 int get_ia32_in_regnr(const ir_node *node, int pos) {
377 assert(0 && "in reg nr not yet implemented");
381 * Returns the index of the OUT register at position pos within its register class.
383 int get_ia32_out_regnr(const ir_node *node, int pos) {
384 asmop_attr *attr = get_ia32_attr(node);
386 assert(is_ia32_irn(node) && "Not an ia32 node.");
387 assert(pos < attr->n_res && "Invalid OUT position.");
389 return attr->slots[pos]->index;
393 * Sets the number of results.
395 void set_ia32_n_res(ir_node *node, int n_res) {
396 asmop_attr *attr = get_ia32_attr(node);
401 * Returns the number of results.
403 int get_ia32_n_res(const ir_node *node) {
404 asmop_attr *attr = get_ia32_attr(node);
409 * Sets the flavour of an ia32 DivMod node to flavour_Div/Mod/DivMod.
411 void set_ia32_DivMod_flavour(ir_node *node, divmod_flavour_t dm_flav) {
412 asmop_attr *attr = get_ia32_attr(node);
413 attr->dm_flav = dm_flav;
416 /* include generated register allocator interface */
417 #include "gen_ia32_regalloc_if.c.inl"
419 /* Include the generated functions */
420 #include "gen_ia32_new_nodes.c.inl"