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 }