extend switch lowerer to produce the out-of-bounds check in firm-IR if necessary
[libfirm] / ir / be / arm / arm_transform.c
index deef63c..053d90d 100644 (file)
@@ -30,7 +30,6 @@
 #include "irmode_t.h"
 #include "irgmod.h"
 #include "iredges.h"
-#include "irvrfy.h"
 #include "ircons.h"
 #include "irprintf.h"
 #include "dbginfo.h"
@@ -439,6 +438,11 @@ static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
                                        attr->shift_modifier);
                        }
                        break;
+               case ARM_SHF_REG:
+               case ARM_SHF_RRX:
+                       break;
+               case ARM_SHF_INVALID:
+                       panic("invalid shift");
                }
        }
        if ((flags & (MATCH_COMMUTATIVE|MATCH_REVERSE)) && is_arm_Mov(new_op1)) {
@@ -446,7 +450,7 @@ static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
                int idx = flags & MATCH_REVERSE ? 1 : 0;
 
                switch (attr->shift_modifier) {
-                       ir_node *mov_op, *mov_sft;
+               ir_node *mov_op, *mov_sft;
 
                case ARM_SHF_IMM:
                case ARM_SHF_ASR_IMM:
@@ -471,6 +475,12 @@ static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
                                        attr->shift_modifier);
                        }
                        break;
+
+               case ARM_SHF_REG:
+               case ARM_SHF_RRX:
+                       break;
+               case ARM_SHF_INVALID:
+                       panic("invalid shift");
                }
        }
        return factory->new_binop_reg(dbgi, block, new_op1, new_op2);
@@ -840,7 +850,7 @@ static ir_node *gen_Not(ir_node *node)
                const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(new_op);
 
                switch (attr->shift_modifier) {
-                       ir_node *mov_op, *mov_sft;
+               ir_node *mov_op, *mov_sft;
 
                case ARM_SHF_IMM:
                case ARM_SHF_ASR_IMM:
@@ -859,6 +869,12 @@ static ir_node *gen_Not(ir_node *node)
                        mov_sft = get_irn_n(new_op, 1);
                        return new_bd_arm_Mvn_reg_shift_reg(dbgi, block, mov_op, mov_sft,
                                attr->shift_modifier);
+
+               case ARM_SHF_REG:
+               case ARM_SHF_RRX:
+                       break;
+               case ARM_SHF_INVALID:
+                       panic("invalid shift");
                }
        }
 
@@ -1025,39 +1041,11 @@ static ir_node *gen_Cmp(ir_node *node)
                new_op2 = be_transform_node(op2);
 
                return new_bd_arm_Cmfe(dbgi, block, new_op1, new_op2, false);
-
-               panic("FloatCmp NIY");
-#if 0
-               ir_node *new_op2  = be_transform_node(op2);
-               /* floating point compare */
-               pn_Cmp pnc = get_Proj_proj(selector);
-
-               if (pnc & pn_Cmp_Uo) {
-                       /* check for unordered, need cmf */
-                       return new_bd_arm_CmfBra(dbgi, block, new_op1, new_op2, pnc);
-               }
-               /* Hmm: use need cmfe */
-               return new_bd_arm_CmfeBra(dbgi, block, new_op1, new_op2, pnc);
-#endif
        }
 
        assert(get_irn_mode(op2) == cmp_mode);
        is_unsigned = !mode_is_signed(cmp_mode);
 
-       /* compare with 0 can be done with Tst */
-       if (is_Const(op2) && is_Const_null(op2)) {
-               new_op1 = be_transform_node(op1);
-               new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
-               return new_bd_arm_Tst_reg(dbgi, block, new_op1, new_op1, /*ins_permuted=*/false,
-                                         is_unsigned);
-       }
-       if (is_Const(op1) && is_Const_null(op1)) {
-               new_op2 = be_transform_node(op2);
-               new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
-               return new_bd_arm_Tst_reg(dbgi, block, new_op2, new_op2, /*ins_permuted=*/true,
-                                         is_unsigned);
-       }
-
        /* integer compare, TODO: use shifter_op in all its combinations */
        new_op1 = be_transform_node(op1);
        new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
@@ -1258,6 +1246,82 @@ static ir_node *gen_CopyB(ir_node *node)
                        new_mem, size);
 }
 
+/**
+ * Transform builtin clz.
+ */
+static ir_node *gen_clz(ir_node *node)
+{
+       ir_node  *block  = be_transform_node(get_nodes_block(node));
+       dbg_info *dbg    = get_irn_dbg_info(node);
+       ir_node  *op     = get_irn_n(node, 1);
+       ir_node  *new_op = be_transform_node(op);
+
+       /* TODO armv5 instruction, otherwise create a call */
+       return new_bd_arm_Clz(dbg, block, new_op);
+}
+
+/**
+ * Transform Builtin node.
+ */
+static ir_node *gen_Builtin(ir_node *node)
+{
+       ir_builtin_kind kind = get_Builtin_kind(node);
+
+       switch (kind) {
+       case ir_bk_trap:
+       case ir_bk_debugbreak:
+       case ir_bk_return_address:
+       case ir_bk_frame_address:
+       case ir_bk_prefetch:
+       case ir_bk_ffs:
+               break;
+       case ir_bk_clz:
+               return gen_clz(node);
+       case ir_bk_ctz:
+       case ir_bk_parity:
+       case ir_bk_popcount:
+       case ir_bk_bswap:
+       case ir_bk_outport:
+       case ir_bk_inport:
+       case ir_bk_inner_trampoline:
+               break;
+       }
+       panic("Builtin %s not implemented in ARM", get_builtin_kind_name(kind));
+}
+
+/**
+ * Transform Proj(Builtin) node.
+ */
+static ir_node *gen_Proj_Builtin(ir_node *proj)
+{
+       ir_node         *node     = get_Proj_pred(proj);
+       ir_node         *new_node = be_transform_node(node);
+       ir_builtin_kind kind      = get_Builtin_kind(node);
+
+       switch (kind) {
+       case ir_bk_return_address:
+       case ir_bk_frame_address:
+       case ir_bk_ffs:
+       case ir_bk_clz:
+       case ir_bk_ctz:
+       case ir_bk_parity:
+       case ir_bk_popcount:
+       case ir_bk_bswap:
+               assert(get_Proj_proj(proj) == pn_Builtin_1_result);
+               return new_node;
+       case ir_bk_trap:
+       case ir_bk_debugbreak:
+       case ir_bk_prefetch:
+       case ir_bk_outport:
+               assert(get_Proj_proj(proj) == pn_Builtin_M);
+               return new_node;
+       case ir_bk_inport:
+       case ir_bk_inner_trampoline:
+               break;
+       }
+       panic("Builtin %s not implemented in ARM", get_builtin_kind_name(kind));
+}
+
 static ir_node *gen_Proj_Load(ir_node *node)
 {
        ir_node  *load     = get_Proj_pred(node);
@@ -1539,6 +1603,8 @@ static ir_node *gen_Proj(ir_node *node)
                }
                /* FALLTHROUGH */
        }
+       case iro_Builtin:
+               return gen_Proj_Builtin(node);
        default:
                panic("code selection didn't expect Proj after %+F\n", pred);
        }
@@ -1934,7 +2000,7 @@ static ir_node *gen_Call(ir_node *node)
                pmap_insert(node_to_stack, node, incsp);
        }
 
-       set_arm_in_req_all(res, in_req);
+       arch_set_in_register_reqs(res, in_req);
 
        /* create output register reqs */
        arch_set_out_register_req(res, 0, arch_no_register_req);
@@ -2043,6 +2109,7 @@ static void arm_register_transformers(void)
        be_set_transform_function(op_Sub,      gen_Sub);
        be_set_transform_function(op_SymConst, gen_SymConst);
        be_set_transform_function(op_Unknown,  gen_Unknown);
+       be_set_transform_function(op_Builtin,  gen_Builtin);
 }
 
 /**