introduce more generic resource reservation debug helpers instead of old set_using_xx...
[libfirm] / ir / be / ia32 / ia32_common_transform.c
index 0c81ef4..d596b08 100644 (file)
  * @file
  * @brief       This file implements the common parts of IR transformation from
  *              firm into ia32-Firm.
- * @author      Sebastian Buchwald
+ * @author      Matthias Braun, Sebastian Buchwald
  * @version     $Id: ia32_common_transform.c 21012 2008-08-06 13:35:17Z beck $
  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 #include "error.h"
 #include "irargs_t.h"
@@ -32,6 +35,7 @@
 #include "typerep.h"
 
 #include "../betranshlp.h"
+#include "../beirg_t.h"
 
 #include "ia32_architecture.h"
 #include "ia32_common_transform.h"
@@ -41,7 +45,9 @@
 #include "gen_ia32_regalloc_if.h"
 
 /** hold the current code generator during transformation */
-ia32_code_gen_t *env_cg       = NULL;
+ia32_code_gen_t *env_cg = NULL;
+
+heights_t *heights = NULL;
 
 static const arch_register_req_t no_register_req = {
        arch_register_req_type_none,
@@ -54,28 +60,19 @@ static const arch_register_req_t no_register_req = {
 static int check_immediate_constraint(long val, char immediate_constraint_type)
 {
        switch (immediate_constraint_type) {
-       case 0:
-       case 'i':
-               return 1;
-       case 'I':
-               return val >= 0 && val <= 32;
-       case 'J':
-               return val >= 0 && val <= 63;
-       case 'K':
-               return val >= -128 && val <= 127;
-       case 'L':
-               return val == 0xff || val == 0xffff;
-       case 'M':
-               return val >= 0 && val <= 3;
-       case 'N':
-               return val >= 0 && val <= 255;
-       case 'O':
-               return val >= 0 && val <= 127;
-       default:
-               break;
+               case 0:
+               case 'i': return 1;
+
+               case 'I': return    0 <= val && val <=  31;
+               case 'J': return    0 <= val && val <=  63;
+               case 'K': return -128 <= val && val <= 127;
+               case 'L': return val == 0xff || val == 0xffff;
+               case 'M': return    0 <= val && val <=   3;
+               case 'N': return    0 <= val && val <= 255;
+               case 'O': return    0 <= val && val <= 127;
+
+               default: panic("Invalid immediate constraint found");
        }
-       panic("Invalid immediate constraint found");
-       return 0;
 }
 
 /**
@@ -463,8 +460,12 @@ static void parse_asm_constraints(constraint_t *constraint, const char *c,
 ir_node *gen_ASM(ir_node *node)
 {
        ir_graph                   *irg       = current_ir_graph;
+#ifdef FIRM_GRGEN_BE
+       ir_node                    *new_block = get_nodes_block(node);
+#else
        ir_node                    *block     = get_nodes_block(node);
        ir_node                    *new_block = be_transform_node(block);
+#endif
        dbg_info                   *dbgi      = get_irn_dbg_info(node);
        int                         i, arity;
        int                         out_idx;
@@ -482,6 +483,9 @@ ir_node *gen_ASM(ir_node *node)
        const ir_asm_constraint    *out_constraints;
        ident                     **clobbers;
        int                         clobbers_flags = 0;
+       unsigned                    clobber_bits[N_CLASSES];
+
+       memset(&clobber_bits, 0, sizeof(clobber_bits));
 
        /* workaround for lots of buggy code out there as most people think volatile
         * asm is enough for everything and forget the flags (linux kernel, etc.)
@@ -497,13 +501,19 @@ ir_node *gen_ASM(ir_node *node)
        clobbers   = get_ASM_clobbers(node);
        n_clobbers = 0;
        for(i = 0; i < get_ASM_n_clobbers(node); ++i) {
-               const char *c = get_id_str(clobbers[i]);
+               const arch_register_req_t *req;
+               const char                *c = get_id_str(clobbers[i]);
+
                if (strcmp(c, "memory") == 0)
                        continue;
                if (strcmp(c, "cc") == 0) {
                        clobbers_flags = 1;
                        continue;
                }
+
+               req = parse_clobber(c);
+               clobber_bits[req->cls->index] |= *req->limited;
+
                n_clobbers++;
        }
        n_out_constraints = get_ASM_n_output_constraints(node);
@@ -561,10 +571,24 @@ ir_node *gen_ASM(ir_node *node)
                unsigned                   pos          = constraint->pos;
                int                        is_memory_op = 0;
                ir_node                   *input        = NULL;
+               unsigned                   r_clobber_bits;
                constraint_t               parsed_constraint;
                const arch_register_req_t *req;
 
                parse_asm_constraints(&parsed_constraint, c, 0);
+               if (parsed_constraint.cls != NULL) {
+                       r_clobber_bits = clobber_bits[parsed_constraint.cls->index];
+                       if (r_clobber_bits != 0) {
+                               if (parsed_constraint.all_registers_allowed) {
+                                       parsed_constraint.all_registers_allowed = 0;
+                                       be_abi_set_non_ignore_regs(env_cg->birg->abi,
+                                                       parsed_constraint.cls,
+                                                       &parsed_constraint.allowed_registers);
+                               }
+                               parsed_constraint.allowed_registers &= ~r_clobber_bits;
+                       }
+               }
+
                req = make_register_req(&parsed_constraint, n_out_constraints,
                                        out_reg_reqs, i);
                in_reg_reqs[i] = req;
@@ -575,8 +599,12 @@ ir_node *gen_ASM(ir_node *node)
                }
 
                if (input == NULL) {
+#ifdef FIRM_GRGEN_BE
+                       input         = get_irn_n(node, i);
+#else
                        ir_node *pred = get_irn_n(node, i);
                        input         = be_transform_node(pred);
+#endif
 
                        if (parsed_constraint.cls == NULL
                                        && parsed_constraint.same_as < 0) {