kit

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

cg_const_test.c (6825B)


      1 #include <kit/cg.h>
      2 #include <kit/core.h>
      3 #include <kit/object.h>
      4 #include <stdint.h>
      5 #include <string.h>
      6 
      7 #include "lib/kit_unit.h"
      8 
      9 static int make_cg(KitUnit* u, KitCompiler* c, KitCg** cg_out,
     10                    KitObjBuilder** ob_out) {
     11   KitCodeOptions opts;
     12   KitObjBuilder* ob = NULL;
     13   KitCg* cg = NULL;
     14   memset(&opts, 0, sizeof opts);
     15   CU_CHECK_RET(u, kit_obj_builder_new(c, &ob) == KIT_OK && ob,
     16                "obj builder allocation failed");
     17   CU_CHECK_RET(u, kit_cg_new(c, &cg) == KIT_OK && cg, "cg new failed");
     18   CU_CHECK_RET(u, kit_cg_begin(cg, ob, &opts) == KIT_OK, "cg begin failed");
     19   *cg_out = cg;
     20   *ob_out = ob;
     21   return 1;
     22 }
     23 
     24 static void destroy_cg(KitCg* cg, KitObjBuilder* ob) {
     25   kit_cg_free(cg);
     26   kit_obj_builder_free(ob);
     27 }
     28 
     29 static void expect_const(KitUnit* u, KitCg* cg, uint16_t width, uint64_t lo,
     30                          uint64_t hi, const char* what) {
     31   KitCgConstInt v;
     32   memset(&v, 0, sizeof v);
     33   CU_EXPECT(u, kit_cg_top_const_int_ex(cg, &v), "%s should be known", what);
     34   CU_EXPECT(u, v.known && v.width == width && v.lo == lo && v.hi == hi,
     35             "%s got known=%u width=%u hi=%llu lo=%llu", what, (unsigned)v.known,
     36             (unsigned)v.width, (unsigned long long)v.hi,
     37             (unsigned long long)v.lo);
     38 }
     39 
     40 static void test_file_scope_unevaluated(KitUnit* u, KitCompiler* c) {
     41   KitCgTypeId i32 = kit_cg_type_builtin(c, KIT_CG_BUILTIN_I32);
     42   KitCgTypeId i64 = kit_cg_type_builtin(c, KIT_CG_BUILTIN_I64);
     43   KitCg* cg = NULL;
     44   KitObjBuilder* ob = NULL;
     45   int64_t i64v = 0;
     46   if (!make_cg(u, c, &cg, &ob)) return;
     47 
     48   kit_cg_unevaluated_push(cg);
     49   kit_cg_push_int(cg, 40, i64);
     50   kit_cg_push_int(cg, 2, i64);
     51   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
     52   expect_const(u, cg, 64, 42, 0, "file-scope add");
     53   CU_EXPECT(u, kit_cg_top_const_i64(cg, &i64v) && i64v == 42,
     54             "i64 convenience query should see 42");
     55 
     56   kit_cg_unevaluated_push(cg);
     57   kit_cg_push_int(cg, 7, i32);
     58   kit_cg_push_int(cg, 3, i32);
     59   kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
     60   expect_const(u, cg, 32, 21, 0, "nested multiply");
     61   kit_cg_drop(cg);
     62   kit_cg_unevaluated_pop(cg);
     63 
     64   expect_const(u, cg, 64, 42, 0, "outer value after nested pop");
     65   kit_cg_drop(cg);
     66   kit_cg_unevaluated_pop(cg);
     67   CU_EXPECT(u, kit_cg_stack_depth(cg) == 0, "unevaluated stack should empty");
     68 
     69   destroy_cg(cg, ob);
     70 }
     71 
     72 static void test_divrem_and_unknown(KitUnit* u, KitCompiler* c) {
     73   KitCgTypeId i64 = kit_cg_type_builtin(c, KIT_CG_BUILTIN_I64);
     74   KitCg* cg = NULL;
     75   KitObjBuilder* ob = NULL;
     76   KitCgConstInt v;
     77   if (!make_cg(u, c, &cg, &ob)) return;
     78   kit_cg_unevaluated_push(cg);
     79 
     80   kit_cg_push_int(cg, 10, i64);
     81   kit_cg_push_int(cg, 3, i64);
     82   kit_cg_int_binop(cg, KIT_CG_INT_UDIV, 0);
     83   expect_const(u, cg, 64, 3, 0, "u64 div");
     84   kit_cg_drop(cg);
     85 
     86   kit_cg_push_int(cg, 10, i64);
     87   kit_cg_push_int(cg, 3, i64);
     88   kit_cg_int_binop(cg, KIT_CG_INT_UREM, 0);
     89   expect_const(u, cg, 64, 1, 0, "u64 rem");
     90   kit_cg_drop(cg);
     91 
     92   kit_cg_push_int(cg, 10, i64);
     93   kit_cg_push_int(cg, 0, i64);
     94   kit_cg_int_binop(cg, KIT_CG_INT_UDIV, 0);
     95   memset(&v, 0, sizeof v);
     96   CU_EXPECT(u, !kit_cg_top_const_int_ex(cg, &v),
     97             "divide by zero should produce unknown constant");
     98   kit_cg_drop(cg);
     99 
    100   kit_cg_unevaluated_pop(cg);
    101   destroy_cg(cg, ob);
    102 }
    103 
    104 static KitCgConstInt u128(uint64_t hi, uint64_t lo) {
    105   KitCgConstInt v;
    106   memset(&v, 0, sizeof v);
    107   v.lo = lo;
    108   v.hi = hi;
    109   v.width = 128;
    110   v.known = 1;
    111   return v;
    112 }
    113 
    114 static void test_i128_bit_folds(KitUnit* u, KitCompiler* c) {
    115   KitCgTypeId i128 = kit_cg_type_builtin(c, KIT_CG_BUILTIN_I128);
    116   KitCg* cg = NULL;
    117   KitObjBuilder* ob = NULL;
    118   KitCgConstInt v;
    119   if (!make_cg(u, c, &cg, &ob)) return;
    120   kit_cg_unevaluated_push(cg);
    121 
    122   v = u128(0, UINT64_MAX);
    123   kit_cg_push_const_int(cg, i128, &v);
    124   kit_cg_push_int(cg, 1, i128);
    125   kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    126   expect_const(u, cg, 128, 0, 1, "i128 add carry");
    127   kit_cg_drop(cg);
    128 
    129   v = u128(1, 0);
    130   kit_cg_push_const_int(cg, i128, &v);
    131   kit_cg_push_int(cg, 2, i128);
    132   kit_cg_int_binop(cg, KIT_CG_INT_MUL, 0);
    133   expect_const(u, cg, 128, 0, 2, "i128 mul low 128");
    134   kit_cg_drop(cg);
    135 
    136   kit_cg_push_int(cg, 1, i128);
    137   kit_cg_push_int(cg, 65, i128);
    138   kit_cg_int_binop(cg, KIT_CG_INT_SHL, 0);
    139   expect_const(u, cg, 128, 0, 2, "i128 shl");
    140   kit_cg_drop(cg);
    141 
    142   v = u128(1, 0);
    143   kit_cg_push_const_int(cg, i128, &v);
    144   v = u128(2, 0);
    145   kit_cg_push_const_int(cg, i128, &v);
    146   kit_cg_int_cmp(cg, KIT_CG_INT_LT_U);
    147   expect_const(u, cg, 32, 1, 0, "i128 cmp");
    148   kit_cg_drop(cg);
    149 
    150   v = u128(4, 0);
    151   kit_cg_push_const_int(cg, i128, &v);
    152   kit_cg_push_int(cg, 2, i128);
    153   kit_cg_int_binop(cg, KIT_CG_INT_UDIV, 0);
    154   CU_EXPECT(u, !kit_cg_top_const_int_ex(cg, NULL),
    155             "i128 div is intentionally unknown");
    156   kit_cg_drop(cg);
    157 
    158   kit_cg_unevaluated_pop(cg);
    159   destroy_cg(cg, ob);
    160 }
    161 
    162 static void test_dummy_handle_stack_effects(KitUnit* u, KitCompiler* c) {
    163   KitCgTypeId i32 = kit_cg_type_builtin(c, KIT_CG_BUILTIN_I32);
    164   KitCgTypeId fn;
    165   KitCgFuncResult result;
    166   KitCgFuncSig sig;
    167   KitCgDecl decl;
    168   KitCgSym sym;
    169   KitCg* cg = NULL;
    170   KitObjBuilder* ob = NULL;
    171   if (!make_cg(u, c, &cg, &ob)) return;
    172 
    173   memset(&result, 0, sizeof result);
    174   result.type = i32;
    175   memset(&sig, 0, sizeof sig);
    176   sig.result = result;
    177   sig.call_conv = KIT_CG_CC_TARGET_C;
    178   fn = kit_cg_type_func(c, sig);
    179   memset(&decl, 0, sizeof decl);
    180   decl.kind = KIT_CG_DECL_FUNC;
    181   decl.linkage_name = kit_sym_intern(c, KIT_SLICE_LIT("callee"));
    182   decl.display_name = decl.linkage_name;
    183   decl.type = fn;
    184   decl.sym.bind = KIT_SB_GLOBAL;
    185   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    186   sym = kit_cg_decl(cg, decl);
    187 
    188   kit_cg_unevaluated_push(cg);
    189   kit_cg_push_label_addr(cg, kit_cg_label_new(cg), kit_cg_type_ptr(c, i32, 0));
    190   CU_EXPECT(u, kit_cg_stack_depth(cg) == 1, "label addr should push one");
    191   CU_EXPECT(u, !kit_cg_top_const_int_ex(cg, NULL),
    192             "label address should not be an integer constant");
    193   kit_cg_drop(cg);
    194 
    195   kit_cg_push_symbol_addr(cg, sym, 0);
    196   kit_cg_call(cg, 0, fn, (KitCgCallAttrs){0});
    197   CU_EXPECT(u, kit_cg_stack_depth(cg) == 1, "call should push result");
    198   CU_EXPECT(u, !kit_cg_top_const_int_ex(cg, NULL),
    199             "call result should be unknown");
    200   kit_cg_drop(cg);
    201   kit_cg_unevaluated_pop(cg);
    202 
    203   destroy_cg(cg, ob);
    204 }
    205 
    206 int main(void) {
    207   KitUnit u;
    208   KitCompiler* c = NULL;
    209   KitTargetSpec t;
    210   kit_unit_init(&u);
    211   t = kit_unit_target(KIT_ARCH_X86_64, KIT_OS_LINUX, KIT_OBJ_ELF);
    212   CU_EXPECT(&u, kit_unit_compiler_new(&u, t, &c) == KIT_OK && c,
    213             "compiler allocation failed");
    214   if (c) {
    215     test_file_scope_unevaluated(&u, c);
    216     test_divrem_and_unknown(&u, c);
    217     test_i128_bit_folds(&u, c);
    218     test_dummy_handle_stack_effects(&u, c);
    219     kit_compiler_free(c);
    220   }
    221   kit_unit_summary(&u, "cg_const_test");
    222   return kit_unit_status(&u);
    223 }