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"
21 #include "firm_common_t.h"
24 #include "../bearch.h"
26 #include "ia32_nodes_attr.h"
27 #include "ia32_new_nodes.h"
28 #include "gen_ia32_regalloc_if.h"
32 /***********************************************************************************
35 * __| |_ _ _ __ ___ _ __ ___ _ __ _ _ __ | |_ ___ _ __| |_ __ _ ___ ___
36 * / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__| _/ _` |/ __/ _ \
37 * | (_| | |_| | | | | | | |_) | __/ | | | | | | || __/ | | || (_| | (_| __/
38 * \__,_|\__,_|_| |_| |_| .__/ \___|_| |_|_| |_|\__\___|_| |_| \__,_|\___\___|
41 ***********************************************************************************/
44 * Prints a tarval to file F.
45 * @param F output file
47 * @param brackets 1 == print square brackets around tarval
49 static void fprintf_tv(FILE *F, tarval *tv, int brackets) {
51 tarval_snprintf(buf, sizeof(buf), tv);
54 fprintf(F, "[%s]", buf);
56 fprintf(F, "%s", buf);
60 * Returns the name of a SymConst.
61 * @param symc the SymConst
62 * @return name of the SymConst
64 const char *get_sc_name(ir_node *symc) {
65 if (get_irn_opcode(symc) != iro_SymConst)
68 switch (get_SymConst_kind(symc)) {
69 case symconst_addr_name:
70 return get_id_str(get_SymConst_name(symc));
72 case symconst_addr_ent:
73 return get_entity_ld_name(get_SymConst_entity(symc));
76 assert(0 && "Unsupported SymConst");
83 * Dumper interface for dumping ia32 nodes in vcg.
84 * @param n the node to dump
85 * @param F the output file
86 * @param reason indicates which kind of information should be dumped
87 * @return 0 on success or != 0 on failure
89 static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
95 const arch_register_req_t **reqs;
96 const arch_register_t **slots;
99 case dump_node_opcode_txt:
100 name = get_irn_opname(n);
101 fprintf(F, "%s", name);
104 case dump_node_mode_txt:
105 mode = get_irn_mode(n);
107 if (mode == mode_BB || mode == mode_ANY || mode == mode_BAD || mode == mode_T) {
110 else if (is_ia32_Load(n)) {
111 mode = get_irn_mode(get_irn_n(n, 1));
113 else if (is_ia32_Store(n)) {
114 mode = get_irn_mode(get_irn_n(n, 2));
118 fprintf(F, "[%s]", get_mode_name(mode));
121 case dump_node_nodeattr_txt:
122 name = get_irn_opname(n);
123 p = name + strlen(name) - 2;
124 if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n) || is_ia32_fConst(n)) {
125 tarval *tv = get_ia32_Immop_tarval(n);
127 fprintf_tv(F, tv, 1);
129 fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
132 else if (is_ia32_Call(n)) {
133 ir_node *sc = get_ia32_old_ir(n);
135 fprintf(F, "&%s ", get_sc_name(sc));
139 case dump_node_info_txt:
140 attr = get_ia32_attr(n);
142 /* dump IN requirements */
143 if (get_irn_arity(n) > 0) {
144 reqs = get_ia32_in_req(n);
147 for (i = 0; i < get_irn_arity(n); i++) {
148 if (reqs[i]->type != arch_register_req_type_none)
149 fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->cls->name);
151 fprintf(F, "inreq[%d]=[none]\n", i);
156 fprintf(F, "NO IN REQS\n");
159 /* dump OUT requirements */
160 if (attr->n_res > 0) {
161 reqs = get_ia32_out_req(n);
164 for (i = 0; i < attr->n_res; i++) {
165 if (reqs[i]->type != arch_register_req_type_none)
166 fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->cls->name);
168 fprintf(F, "outreq[%d]=[none]\n", i);
172 fprintf(F, "NO OUT REQS\n");
175 /* dump assigned registers */
176 slots = get_ia32_slots(n);
177 if (slots && attr->n_res > 0) {
178 for (i = 0; i < attr->n_res; i++) {
180 fprintf(F, "REG[%d]=[%s]\n", i, slots[i]->name);
183 fprintf(F, "REG[%d]=[none]\n", i);
187 /* special for LEA */
188 if (is_ia32_Lea(n)) {
189 tarval *o = get_ia32_offs(n);
190 tarval *tv = get_ia32_Immop_tarval(n);
195 fprintf(F, "(%s, %s", get_irn_opname(get_irn_n(n, 0)), get_irn_opname(get_irn_n(n, 1)));
198 fprintf_tv(F, tv, 0);
210 /***************************************************************************************************
212 * | | | | | | / / | | | | | | | |
213 * __ _| |_| |_ _ __ ___ ___| |_ / /_ _ ___| |_ _ __ ___ ___| |_| |__ ___ __| |___
214 * / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
215 * | (_| | |_| |_| | \__ \ __/ |_ / / (_| | __/ |_ | | | | | | __/ |_| | | | (_) | (_| \__ \
216 * \__,_|\__|\__|_| |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
219 ***************************************************************************************************/
222 * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
223 * Firm was made by people hating const :-(
225 asmop_attr *get_ia32_attr(const ir_node *node) {
226 return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
230 * Return the tarval of an immediate operation or NULL in case of SymConst
232 tarval *get_ia32_Immop_tarval(const ir_node *node) {
233 asmop_attr *attr = get_ia32_attr(node);
234 if (attr->tp == asmop_Const)
241 * Return the old_ir attribute.
243 ir_node *get_ia32_old_ir(const ir_node *node) {
244 asmop_attr *attr = get_ia32_attr(node);
249 * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
251 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
252 asmop_attr *na = get_ia32_attr(node);
253 asmop_attr *ca = get_ia32_attr(cnst);
255 assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr");
261 na->old_ir = calloc(1, sizeof(*(ca->old_ir)));
262 memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir)));
269 * Copy the attributes from a Const to an ia32_Const
271 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
272 asmop_attr *attr = get_ia32_attr(ia32_cnst);
274 assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr");
276 switch (get_irn_opcode(cnst)) {
278 attr->tp = asmop_Const;
279 attr->tv = get_Const_tarval(cnst);
282 attr->tp = asmop_SymConst;
283 attr->old_ir = calloc(1, sizeof(*cnst));
284 memcpy(attr->old_ir, cnst, sizeof(*cnst));
287 assert(0 && "Unknown Const NYI");
290 assert(0 && "Cannot create ia32_Const for this opcode");
295 * Sets the type of an ia32_Const.
297 void set_ia32_Const_type(ir_node *node, int type) {
298 asmop_attr *attr = get_ia32_attr(node);
300 assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type");
301 assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
307 * Sets the attributes of an immediate operation to the specified tarval
309 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
310 asmop_attr *attr = get_ia32_attr(node);
312 attr->tp = asmop_Const;
317 * Sets the offset for a Lea.
319 void set_ia32_offs(ir_node *node, tarval *offs) {
320 asmop_attr *attr = get_ia32_attr(node);
325 * Gets the offset for a Lea.
327 tarval *get_ia32_offs(const ir_node *node) {
328 asmop_attr *attr = get_ia32_attr(node);
333 * Returns the argument register requirements of an ia32 node.
335 const arch_register_req_t **get_ia32_in_req(const ir_node *node) {
336 asmop_attr *attr = get_ia32_attr(node);
341 * Returns the result register requirements of an ia32 node.
343 const arch_register_req_t **get_ia32_out_req(const ir_node *node) {
344 asmop_attr *attr = get_ia32_attr(node);
345 return attr->out_req;
349 * Sets the OUT register requirements at position pos.
351 void set_ia32_regreq_out(ir_node *node, const arch_register_req_t *req, int pos) {
352 asmop_attr *attr = get_ia32_attr(node);
353 attr->out_req[pos] = req;
357 * Sets the IN register requirements at position pos.
359 void set_ia32_regreq_in(ir_node *node, const arch_register_req_t *req, int pos) {
360 asmop_attr *attr = get_ia32_attr(node);
361 attr->in_req[pos] = req;
365 * Returns the register flag of an ia32 node.
367 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
368 asmop_attr *attr = get_ia32_attr(node);
373 * Returns the result register slots of an ia32 node.
375 const arch_register_t **get_ia32_slots(const ir_node *node) {
376 asmop_attr *attr = get_ia32_attr(node);
381 * Returns the name of the OUT register at position pos.
383 const char *get_ia32_out_reg_name(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.");
388 assert(attr->slots[pos] && "No register assigned");
390 return attr->slots[pos]->name;
394 * Returns the index of the OUT register at position pos within its register class.
396 int get_ia32_out_regnr(const ir_node *node, int pos) {
397 asmop_attr *attr = get_ia32_attr(node);
399 assert(is_ia32_irn(node) && "Not an ia32 node.");
400 assert(pos < attr->n_res && "Invalid OUT position.");
401 assert(attr->slots[pos] && "No register assigned");
403 return attr->slots[pos]->index;
407 * Sets the number of results.
409 void set_ia32_n_res(ir_node *node, int n_res) {
410 asmop_attr *attr = get_ia32_attr(node);
415 * Returns the number of results.
417 int get_ia32_n_res(const ir_node *node) {
418 asmop_attr *attr = get_ia32_attr(node);
423 * Sets the flavour of an ia32 DivMod node to flavour_Div/Mod/DivMod.
425 void set_ia32_DivMod_flavour(ir_node *node, divmod_flavour_t dm_flav) {
426 asmop_attr *attr = get_ia32_attr(node);
427 attr->dm_flav = dm_flav;
431 * Returns the projnum code.
433 long get_ia32_pncode(const ir_node *node) {
434 asmop_attr *attr = get_ia32_attr(node);
435 return attr->pn_code;
439 * Sets the projnum code
441 void set_ia32_pncode(ir_node *node, long code) {
442 asmop_attr *attr = get_ia32_attr(node);
443 attr->pn_code = code;
446 /* Include the generated functions */
447 #include "gen_ia32_new_nodes.c.inl"