Assert that ia32_perform_memory_operand() only tries to fold a reload into a node...
[libfirm] / ir / be / ia32 / bearch_ia32.c
index fbb4f7a..6b25e85 100644 (file)
@@ -70,6 +70,7 @@
 #include "../begnuas.h"
 #include "../bestate.h"
 #include "../beflags.h"
+#include "../betranshlp.h"
 
 #include "bearch_ia32_t.h"
 
@@ -180,7 +181,8 @@ ir_node *ia32_new_Fpu_truncate(ia32_code_gen_t *cg) {
 /**
  * Returns the admissible noreg register node for input register pos of node irn.
  */
-ir_node *ia32_get_admissible_noreg(ia32_code_gen_t *cg, ir_node *irn, int pos) {
+static ir_node *ia32_get_admissible_noreg(ia32_code_gen_t *cg, ir_node *irn, int pos)
+{
        const arch_register_req_t *req;
 
        req = arch_get_register_req(cg->arch_env, irn, pos);
@@ -391,6 +393,9 @@ static void ia32_set_frame_offset(ir_node *irn, int bias)
 
 static int ia32_get_sp_bias(const ir_node *node)
 {
+       if (is_ia32_Call(node))
+               return -(int)get_ia32_call_attr_const(node)->pop;
+
        if (is_ia32_Push(node))
                return 4;
 
@@ -544,8 +549,8 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
  */
 static void *ia32_abi_init(const be_abi_call_t *call, const arch_env_t *aenv, ir_graph *irg)
 {
-       ia32_abi_env_t *env    = xmalloc(sizeof(env[0]));
-       be_abi_call_flags_t fl = be_abi_call_get_flags(call);
+       ia32_abi_env_t      *env = XMALLOC(ia32_abi_env_t);
+       be_abi_call_flags_t  fl  = be_abi_call_get_flags(call);
        env->flags = fl.bits;
        env->irg   = irg;
        env->aenv  = aenv;
@@ -818,12 +823,14 @@ static int ia32_possible_memory_operand(const ir_node *irn, unsigned int i)
 
        if (!is_ia32_irn(irn)                              ||  /* must be an ia32 irn */
            get_ia32_op_type(irn) != ia32_Normal           ||  /* must not already be a addressmode irn */
-           !(get_ia32_am_support(irn) & ia32_am_Source)   ||  /* must be capable of source addressmode */
            !ia32_is_spillmode_compatible(mode, spillmode) ||
            is_ia32_use_frame(irn))                            /* must not already use frame */
                return 0;
 
-       switch (get_ia32_am_arity(irn)) {
+       switch (get_ia32_am_support(irn)) {
+               case ia32_am_none:
+                       return 0;
+
                case ia32_am_unary:
                        return i == n_ia32_unary_op;
 
@@ -852,7 +859,7 @@ static int ia32_possible_memory_operand(const ir_node *irn, unsigned int i)
                        }
 
                default:
-                       panic("Unknown arity");
+                       panic("Unknown AM type");
        }
 }
 
@@ -874,14 +881,16 @@ static void ia32_perform_memory_operand(ir_node *irn, ir_node *spill,
        set_ia32_use_frame(irn);
        set_ia32_need_stackent(irn);
 
-       if (i == n_ia32_binary_left                  &&
-           get_ia32_am_arity(irn) == ia32_am_binary &&
+       if (i == n_ia32_binary_left                    &&
+           get_ia32_am_support(irn) == ia32_am_binary &&
            /* immediates are only allowed on the right side */
            !is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_right))) {
                ia32_swap_left_right(irn);
                i = n_ia32_binary_right;
        }
 
+       assert(is_NoMem(get_irn_n(irn, n_ia32_mem)));
+
        set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn)));
        set_irn_n(irn, n_ia32_mem,  spill);
        set_irn_n(irn, i,           ia32_get_admissible_noreg(ia32_current_cg, irn, i));
@@ -1019,7 +1028,7 @@ static void ia32_before_sched(void *self) {
        (void) self;
 }
 
-static void turn_back_am(ir_node *node)
+ir_node *turn_back_am(ir_node *node)
 {
        ir_graph *irg   = current_ir_graph;
        dbg_info *dbgi  = get_irn_dbg_info(node);
@@ -1037,15 +1046,13 @@ static void turn_back_am(ir_node *node)
                set_ia32_is_reload(load);
        set_irn_n(node, n_ia32_mem, new_NoMem());
 
-       switch (get_ia32_am_arity(node)) {
+       switch (get_ia32_am_support(node)) {
                case ia32_am_unary:
                        set_irn_n(node, n_ia32_unary_op, load_res);
                        break;
 
                case ia32_am_binary:
                        if (is_ia32_Immediate(get_irn_n(node, n_ia32_binary_right))) {
-                               assert(is_ia32_Cmp(node)  || is_ia32_Cmp8Bit(node) ||
-                                      is_ia32_Test(node) || is_ia32_Test8Bit(node));
                                set_irn_n(node, n_ia32_binary_left, load_res);
                        } else {
                                set_irn_n(node, n_ia32_binary_right, load_res);
@@ -1053,7 +1060,7 @@ static void turn_back_am(ir_node *node)
                        break;
 
                default:
-                       panic("Unknown arity");
+                       panic("Unknown AM type");
        }
        noreg = ia32_new_NoReg_gp(ia32_current_cg);
        set_irn_n(node, n_ia32_base,  noreg);
@@ -1079,6 +1086,8 @@ static void turn_back_am(ir_node *node)
        set_ia32_op_type(node, ia32_Normal);
        if (sched_is_scheduled(node))
                sched_add_before(node, load);
+
+       return load_res;
 }
 
 static ir_node *flags_remat(ir_node *node, ir_node *after)
@@ -1266,6 +1275,7 @@ static ir_node *create_push(ia32_code_gen_t *cg, ir_node *node, ir_node *schedpo
        set_ia32_use_frame(push);
        set_ia32_op_type(push, ia32_AddrModeS);
        set_ia32_ls_mode(push, mode_Is);
+       set_ia32_is_spill(push);
 
        sched_add_before(schedpoint, push);
        return push;
@@ -1284,6 +1294,7 @@ static ir_node *create_pop(ia32_code_gen_t *cg, ir_node *node, ir_node *schedpoi
        set_ia32_use_frame(pop);
        set_ia32_op_type(pop, ia32_AddrModeD);
        set_ia32_ls_mode(pop, mode_Is);
+       set_ia32_is_reload(pop);
 
        sched_add_before(schedpoint, pop);
 
@@ -1552,8 +1563,7 @@ static ir_node *ia32_get_pic_base(void *self) {
        get_eip     = new_rd_ia32_GetEIP(NULL, cg->irg, block);
        cg->get_eip = get_eip;
 
-       add_irn_dep(get_eip, get_irg_frame(cg->irg));
-
+       be_dep_on_frame(get_eip);
        return get_eip;
 }
 
@@ -1577,7 +1587,7 @@ static const arch_code_generator_if_t ia32_code_gen_if = {
  */
 static void *ia32_cg_init(be_irg_t *birg) {
        ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env;
-       ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));
+       ia32_code_gen_t *cg  = XMALLOCZ(ia32_code_gen_t);
 
        cg->impl      = &ia32_code_gen_if;
        cg->irg       = birg->irg;
@@ -1739,7 +1749,7 @@ static arch_env_t *ia32_init(FILE *file_handle) {
 
        set_tarval_output_modes();
 
-       isa = xmalloc(sizeof(*isa));
+       isa = XMALLOC(ia32_isa_t);
        memcpy(isa, &ia32_isa_template, sizeof(*isa));
 
        if(mode_fpcw == NULL) {
@@ -1762,7 +1772,7 @@ static arch_env_t *ia32_init(FILE *file_handle) {
        ia32_build_8bit_reg_map_high(isa->regs_8bit_high);
 
 #ifndef NDEBUG
-       isa->name_obst = xmalloc(sizeof(*isa->name_obst));
+       isa->name_obst = XMALLOC(struct obstack);
        obstack_init(isa->name_obst);
 #endif /* NDEBUG */
 
@@ -1884,7 +1894,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
        call_flags.bits.store_args_sequential = 0;
        /* call_flags.bits.try_omit_fp                 not changed: can handle both settings */
        call_flags.bits.fp_free               = 0;  /* the frame pointer is fixed in IA32 */
-       call_flags.bits.call_has_imm          = 1;  /* No call immediates, we handle this by ourselves */
+       call_flags.bits.call_has_imm          = 0;  /* No call immediates, we handle this by ourselves */
 
        /* set parameter passing style */
        be_abi_call_set_flags(abi, call_flags, &ia32_abi_callbacks);
@@ -2083,16 +2093,13 @@ static const be_execution_unit_t ***ia32_get_allowed_execution_units(
 
        if (is_ia32_irn(irn)) {
                ret = get_ia32_exec_units(irn);
-       }
-       else if (is_be_node(irn)) {
-               if (be_is_Call(irn) || be_is_Return(irn)) {
+       } else if (is_be_node(irn)) {
+               if (be_is_Return(irn)) {
                        ret = _units_callret;
-               }
-               else if (be_is_Barrier(irn)) {
+               } else if (be_is_Barrier(irn)) {
                        ret = _units_dummy;
-               }
-               else {
-                        ret = _units_other;
+               } else {
+                       ret = _units_other;
                }
        }
        else {