kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

ir_eval.c (3864B)


      1 /* The single definition of the width-aware integer constant-fold semantics.
      2  * See cg/ir_eval.h for the contract and rationale. Plain (op, width, i64)
      3  * arithmetic only — no Compiler, no IR types — so cg/ and opt/ share it. */
      4 
      5 #include "cg/ir_eval.h"
      6 
      7 u64 kit_ir_width_mask(u32 width) {
      8   if (width >= 64u) return UINT64_MAX;
      9   return (1ull << width) - 1ull;
     10 }
     11 
     12 u64 kit_ir_mask_width(u64 v, u32 width) { return v & kit_ir_width_mask(width); }
     13 
     14 i64 kit_ir_sign_extend_width(u64 v, u32 width) {
     15   v = kit_ir_mask_width(v, width);
     16   if (!width || width >= 64u) return (i64)v;
     17   u64 sign = 1ull << (width - 1u);
     18   return (i64)((v ^ sign) - sign);
     19 }
     20 
     21 int kit_ir_eval_binop(BinOp op, u32 width, i64 a, i64 b, i64* out) {
     22   u64 ua = kit_ir_mask_width((u64)a, width);
     23   u64 ub = kit_ir_mask_width((u64)b, width);
     24   u64 r = 0;
     25   if (!out) return 0;
     26   switch (op) {
     27     case BO_IADD:
     28       r = ua + ub;
     29       break;
     30     case BO_ISUB:
     31       r = ua - ub;
     32       break;
     33     case BO_IMUL:
     34       r = ua * ub;
     35       break;
     36     case BO_AND:
     37       r = ua & ub;
     38       break;
     39     case BO_OR:
     40       r = ua | ub;
     41       break;
     42     case BO_XOR:
     43       r = ua ^ ub;
     44       break;
     45     case BO_SHL: {
     46       u32 sh = (u32)(ub & (u64)(width - 1u));
     47       r = ua << sh;
     48       break;
     49     }
     50     case BO_SHR_U: {
     51       u32 sh = (u32)(ub & (u64)(width - 1u));
     52       r = ua >> sh;
     53       break;
     54     }
     55     case BO_SHR_S: {
     56       u32 sh = (u32)(ub & (u64)(width - 1u));
     57       if (!sh) {
     58         r = ua;
     59       } else {
     60         u64 sign = 1ull << (width - 1u);
     61         r = ua >> sh;
     62         if (ua & sign) r |= kit_ir_width_mask(width) << (width - sh);
     63       }
     64       break;
     65     }
     66     default:
     67       return 0;
     68   }
     69   *out = (i64)kit_ir_mask_width(r, width);
     70   return 1;
     71 }
     72 
     73 int kit_ir_eval_unop(UnOp op, u32 width, i64 a, i64* out) {
     74   u64 ua = kit_ir_mask_width((u64)a, width);
     75   u64 r;
     76   if (!out) return 0;
     77   switch (op) {
     78     case UO_NEG:
     79       r = 0u - ua;
     80       break;
     81     case UO_NOT:
     82       r = ua == 0;
     83       break;
     84     case UO_BNOT:
     85       r = ~ua;
     86       break;
     87     default:
     88       return 0;
     89   }
     90   *out = (i64)kit_ir_mask_width(r, width);
     91   return 1;
     92 }
     93 
     94 int kit_ir_eval_cmp(CmpOp op, u32 width, i64 a, i64 b, i64* out) {
     95   u64 ua = kit_ir_mask_width((u64)a, width);
     96   u64 ub = kit_ir_mask_width((u64)b, width);
     97   i64 sa = kit_ir_sign_extend_width(ua, width);
     98   i64 sb = kit_ir_sign_extend_width(ub, width);
     99   int r;
    100   if (!out) return 0;
    101   switch (op) {
    102     case CMP_EQ:
    103       r = ua == ub;
    104       break;
    105     case CMP_NE:
    106       r = ua != ub;
    107       break;
    108     case CMP_LT_S:
    109       r = sa < sb;
    110       break;
    111     case CMP_LE_S:
    112       r = sa <= sb;
    113       break;
    114     case CMP_GT_S:
    115       r = sa > sb;
    116       break;
    117     case CMP_GE_S:
    118       r = sa >= sb;
    119       break;
    120     case CMP_LT_U:
    121       r = ua < ub;
    122       break;
    123     case CMP_LE_U:
    124       r = ua <= ub;
    125       break;
    126     case CMP_GT_U:
    127       r = ua > ub;
    128       break;
    129     case CMP_GE_U:
    130       r = ua >= ub;
    131       break;
    132     default:
    133       return 0;
    134   }
    135   *out = r ? 1 : 0;
    136   return 1;
    137 }
    138 
    139 int kit_ir_eval_convert(ConvKind k, u32 src_width, u32 dst_width, i64 src,
    140                         i64* out) {
    141   u64 v;
    142   if (!out) return 0;
    143   switch (k) {
    144     case CV_TRUNC:
    145     case CV_ZEXT:
    146       v = kit_ir_mask_width((u64)src, src_width);
    147       break;
    148     case CV_SEXT:
    149       v = (u64)kit_ir_sign_extend_width((u64)src, src_width);
    150       break;
    151     case CV_BITCAST:
    152       if (src_width != dst_width) return 0;
    153       v = kit_ir_mask_width((u64)src, src_width);
    154       break;
    155     default:
    156       return 0;
    157   }
    158   *out = (i64)kit_ir_mask_width(v, dst_width);
    159   return 1;
    160 }
    161 
    162 int kit_ir_binop_is_commutative_int(BinOp op) {
    163   switch (op) {
    164     case BO_IADD:
    165     case BO_IMUL:
    166     case BO_AND:
    167     case BO_OR:
    168     case BO_XOR:
    169       return 1;
    170     default:
    171       return 0;
    172   }
    173 }
    174 
    175 int kit_ir_cmp_is_commutative_int(CmpOp op) {
    176   return op == CMP_EQ || op == CMP_NE;
    177 }