const.c (14829B)
1 #include "cg/internal.h" 2 3 static u64 const_mask(u32 width) { 4 if (width >= 64u) return UINT64_MAX; 5 return (1ull << width) - 1ull; 6 } 7 8 static int const_type_width(KitCg* g, KitCgTypeId type, u32* width_out) { 9 u32 width; 10 if (!g || !width_out) return 0; 11 width = api_int_like_width(g->c, type); 12 if (!width || width > 128u) return 0; 13 *width_out = width; 14 return 1; 15 } 16 17 static KitCgConstInt const_normalize(KitCgConstInt v, u32 width) { 18 v.width = (uint16_t)width; 19 if (!v.known || width == 0 || width > 128u) { 20 memset(&v, 0, sizeof v); 21 v.width = (uint16_t)width; 22 return v; 23 } 24 if (width < 64u) { 25 v.lo &= const_mask(width); 26 v.hi = 0; 27 } else if (width == 64u) { 28 v.hi = 0; 29 } else if (width < 128u) { 30 v.hi &= const_mask(width - 64u); 31 } 32 v.known = 1; 33 return v; 34 } 35 36 static int const_is_zero(KitCgConstInt v) { 37 return v.known && v.lo == 0 && v.hi == 0; 38 } 39 40 static int const_sign_bit(KitCgConstInt v) { 41 u32 width = v.width; 42 if (!width) return 0; 43 if (width <= 64u) return ((v.lo >> (width - 1u)) & 1u) != 0; 44 return ((v.hi >> (width - 65u)) & 1u) != 0; 45 } 46 47 static int const_cmp_unsigned(KitCgConstInt a, KitCgConstInt b) { 48 if (a.hi != b.hi) return a.hi < b.hi ? -1 : 1; 49 if (a.lo != b.lo) return a.lo < b.lo ? -1 : 1; 50 return 0; 51 } 52 53 static int const_cmp_signed(KitCgConstInt a, KitCgConstInt b) { 54 int as = const_sign_bit(a); 55 int bs = const_sign_bit(b); 56 if (as != bs) return as ? -1 : 1; 57 return const_cmp_unsigned(a, b); 58 } 59 60 static u64 const_low_masked(KitCgConstInt v) { 61 if (v.width >= 64u) return v.lo; 62 return v.lo & const_mask(v.width); 63 } 64 65 static u64 const_abs_signed64_bits(u64 bits, u32 width, int* neg_out) { 66 u64 mask = const_mask(width); 67 int neg = width && ((bits >> (width - 1u)) & 1u) != 0; 68 bits &= mask; 69 if (neg) bits = ((~bits) + 1u) & mask; 70 if (neg_out) *neg_out = neg; 71 return bits; 72 } 73 74 static int const_divrem64(BinOp op, u32 width, u64 a, u64 b, u64* out) { 75 u64 mask = const_mask(width); 76 if (!out || b == 0) return 0; 77 a &= mask; 78 b &= mask; 79 switch (op) { 80 case BO_UDIV: 81 *out = (a / b) & mask; 82 return 1; 83 case BO_UREM: 84 *out = (a % b) & mask; 85 return 1; 86 case BO_SDIV: 87 case BO_SREM: { 88 int an, bn; 89 u64 aa = const_abs_signed64_bits(a, width, &an); 90 u64 bb = const_abs_signed64_bits(b, width, &bn); 91 u64 r; 92 if (bb == 0) return 0; 93 if (op == BO_SDIV) { 94 r = aa / bb; 95 if (an != bn) r = ((~r) + 1u) & mask; 96 } else { 97 r = aa % bb; 98 if (an) r = ((~r) + 1u) & mask; 99 } 100 *out = r & mask; 101 return 1; 102 } 103 default: 104 return 0; 105 } 106 } 107 108 static KitCgConstInt const_add(KitCgConstInt a, KitCgConstInt b) { 109 KitCgConstInt r = a; 110 u64 lo = a.lo + b.lo; 111 u64 carry = lo < a.lo; 112 r.lo = lo; 113 r.hi = a.hi + b.hi + carry; 114 return const_normalize(r, r.width); 115 } 116 117 static KitCgConstInt const_sub(KitCgConstInt a, KitCgConstInt b) { 118 KitCgConstInt r = a; 119 u64 borrow = a.lo < b.lo; 120 r.lo = a.lo - b.lo; 121 r.hi = a.hi - b.hi - borrow; 122 return const_normalize(r, r.width); 123 } 124 125 static KitCgConstInt const_mul(KitCgConstInt a, KitCgConstInt b) { 126 KitCgConstInt r = a; 127 u16 al[8]; 128 u16 bl[8]; 129 u16 rl[8]; 130 u32 i; 131 u32 k; 132 for (i = 0; i < 4u; ++i) { 133 al[i] = (u16)(a.lo >> (i * 16u)); 134 bl[i] = (u16)(b.lo >> (i * 16u)); 135 al[i + 4u] = (u16)(a.hi >> (i * 16u)); 136 bl[i + 4u] = (u16)(b.hi >> (i * 16u)); 137 rl[i] = 0; 138 rl[i + 4u] = 0; 139 } 140 { 141 u64 carry = 0; 142 for (k = 0; k < 8u; ++k) { 143 u64 sum = carry; 144 for (i = 0; i <= k; ++i) sum += (u32)al[i] * (u32)bl[k - i]; 145 rl[k] = (u16)sum; 146 carry = sum >> 16; 147 } 148 } 149 r.lo = 0; 150 r.hi = 0; 151 for (i = 0; i < 4u; ++i) { 152 r.lo |= (u64)rl[i] << (i * 16u); 153 r.hi |= (u64)rl[i + 4u] << (i * 16u); 154 } 155 return const_normalize(r, r.width); 156 } 157 158 static KitCgConstInt const_shl(KitCgConstInt a, u32 sh) { 159 KitCgConstInt r = a; 160 sh &= (u32)(a.width - 1u); 161 if (sh == 0) return const_normalize(r, r.width); 162 if (sh >= 64u) { 163 r.hi = a.lo << (sh - 64u); 164 r.lo = 0; 165 } else { 166 r.hi = (a.hi << sh) | (a.lo >> (64u - sh)); 167 r.lo = a.lo << sh; 168 } 169 return const_normalize(r, r.width); 170 } 171 172 static KitCgConstInt const_lshr(KitCgConstInt a, u32 sh) { 173 KitCgConstInt r = a; 174 sh &= (u32)(a.width - 1u); 175 if (sh == 0) return const_normalize(r, r.width); 176 if (sh >= 64u) { 177 r.lo = a.hi >> (sh - 64u); 178 r.hi = 0; 179 } else { 180 r.lo = (a.lo >> sh) | (a.hi << (64u - sh)); 181 r.hi = a.hi >> sh; 182 } 183 return const_normalize(r, r.width); 184 } 185 186 static KitCgConstInt const_ashr(KitCgConstInt a, u32 sh) { 187 KitCgConstInt r = const_lshr(a, sh); 188 u32 width = a.width; 189 if (!const_sign_bit(a)) return r; 190 sh &= (u32)(width - 1u); 191 if (sh == 0) return r; 192 if (width <= 64u) { 193 u64 fill = ~const_mask(width - sh); 194 r.lo |= fill & const_mask(width); 195 r.hi = 0; 196 } else { 197 u32 top_bits = sh; 198 while (top_bits) { 199 u32 bit = width - top_bits; 200 if (bit < 64u) 201 r.lo |= 1ull << bit; 202 else 203 r.hi |= 1ull << (bit - 64u); 204 --top_bits; 205 } 206 } 207 return const_normalize(r, width); 208 } 209 210 static KitCgConstInt const_sext(KitCgConstInt v, u32 src_width, u32 dst_width) { 211 int neg; 212 v = const_normalize(v, src_width); 213 neg = const_sign_bit(v); 214 v.width = (uint16_t)dst_width; 215 if (neg && dst_width > src_width) { 216 u32 bit; 217 for (bit = src_width; bit < dst_width; ++bit) { 218 if (bit < 64u) 219 v.lo |= 1ull << bit; 220 else 221 v.hi |= 1ull << (bit - 64u); 222 } 223 } 224 return const_normalize(v, dst_width); 225 } 226 227 int api_unevaluated(KitCg* g) { return g && g->unevaluated_depth != 0; } 228 229 ApiSValue api_uneval_value(KitCg* g, KitCgTypeId type) { 230 KitCgTypeId ty = type ? resolve_type(g->c, type) : KIT_CG_TYPE_NONE; 231 return api_make_sv(api_op_imm(0, ty), ty); 232 } 233 234 ApiSValue api_uneval_place(KitCg* g, KitCgTypeId type) { 235 KitCgTypeId ty = type ? resolve_type(g->c, type) : KIT_CG_TYPE_NONE; 236 return api_make_lv(api_op_indirect(CG_LOCAL_NONE, 0, ty), ty); 237 } 238 239 ApiConstValue api_const_unknown(KitCgTypeId type) { 240 ApiConstValue cv; 241 memset(&cv, 0, sizeof cv); 242 cv.type = type; 243 return cv; 244 } 245 246 ApiConstValue api_const_int_result(KitCg* g, KitCgTypeId type, u64 lo, u64 hi, 247 int is_signed) { 248 ApiConstValue cv = api_const_unknown(type); 249 u32 width; 250 if (!const_type_width(g, type, &width)) return cv; 251 cv.value.lo = lo; 252 cv.value.hi = hi; 253 cv.value.width = (uint16_t)width; 254 cv.value.is_signed = is_signed ? 1u : 0u; 255 cv.value.known = 1u; 256 cv.value = const_normalize(cv.value, width); 257 return cv; 258 } 259 260 ApiConstValue api_const_for_push(KitCg* g, KitCgTypeId type, 261 const KitCgConstInt* value) { 262 ApiConstValue cv = api_const_unknown(type); 263 u32 width; 264 if (!value || !value->known || !const_type_width(g, type, &width)) return cv; 265 cv.type = type; 266 cv.value = const_normalize(*value, width); 267 cv.value.known = 1u; 268 return cv; 269 } 270 271 ApiConstValue api_const_from_sv(KitCg* g, const ApiSValue* sv) { 272 KitCgTypeId type; 273 if (!g || !sv) return api_const_unknown(KIT_CG_TYPE_NONE); 274 type = api_sv_type(sv); 275 if (api_sv_kind(sv) == SV_OPERAND && sv->op.kind == OPK_IMM) { 276 return api_const_int_result(g, type, (u64)sv->op.v.imm, 0, 0); 277 } 278 return api_const_unknown(type); 279 } 280 281 ApiConstValue api_const_at(KitCg* g, u32 depth) { 282 if (!g || depth >= g->sp || !g->const_stack) 283 return api_const_unknown(KIT_CG_TYPE_NONE); 284 return g->const_stack[g->sp - 1u - depth]; 285 } 286 287 void api_const_set_top(KitCg* g, ApiConstValue value) { 288 if (!g || !g->sp || !g->const_stack) return; 289 g->const_stack[g->sp - 1u] = value; 290 } 291 292 void api_const_set_at(KitCg* g, u32 depth, ApiConstValue value) { 293 if (!g || depth >= g->sp || !g->const_stack) return; 294 g->const_stack[g->sp - 1u - depth] = value; 295 } 296 297 void api_const_copy_top_from(KitCg* g, ApiConstValue value) { 298 api_const_set_top(g, value); 299 } 300 301 int api_const_fold_binop(KitCg* g, BinOp op, KitCgTypeId type, ApiConstValue a, 302 ApiConstValue b, u32 flags, ApiConstValue* out) { 303 ApiConstValue r; 304 u32 width; 305 if (!out) return 0; 306 r = api_const_unknown(type); 307 if (!g || flags || !a.value.known || !b.value.known || 308 !const_type_width(g, type, &width)) { 309 *out = r; 310 return 0; 311 } 312 a.value = const_normalize(a.value, width); 313 b.value = const_normalize(b.value, width); 314 r = api_const_int_result(g, type, 0, 0, a.value.is_signed); 315 switch (op) { 316 case BO_IADD: 317 r.value = const_add(a.value, b.value); 318 break; 319 case BO_ISUB: 320 r.value = const_sub(a.value, b.value); 321 break; 322 case BO_IMUL: 323 r.value = const_mul(a.value, b.value); 324 break; 325 case BO_AND: 326 r.value.lo = a.value.lo & b.value.lo; 327 r.value.hi = a.value.hi & b.value.hi; 328 r.value = const_normalize(r.value, width); 329 break; 330 case BO_OR: 331 r.value.lo = a.value.lo | b.value.lo; 332 r.value.hi = a.value.hi | b.value.hi; 333 r.value = const_normalize(r.value, width); 334 break; 335 case BO_XOR: 336 r.value.lo = a.value.lo ^ b.value.lo; 337 r.value.hi = a.value.hi ^ b.value.hi; 338 r.value = const_normalize(r.value, width); 339 break; 340 case BO_SHL: 341 r.value = const_shl(a.value, (u32)b.value.lo); 342 break; 343 case BO_SHR_U: 344 r.value = const_lshr(a.value, (u32)b.value.lo); 345 break; 346 case BO_SHR_S: 347 r.value = const_ashr(a.value, (u32)b.value.lo); 348 break; 349 case BO_SDIV: 350 case BO_UDIV: 351 case BO_SREM: 352 case BO_UREM: { 353 u64 folded; 354 if (width > 64u || !const_divrem64(op, width, const_low_masked(a.value), 355 const_low_masked(b.value), &folded)) { 356 *out = api_const_unknown(type); 357 return 0; 358 } 359 r.value = 360 api_const_int_result(g, type, folded, 0, a.value.is_signed).value; 361 break; 362 } 363 default: 364 *out = api_const_unknown(type); 365 return 0; 366 } 367 r.type = type; 368 r.value.known = 1u; 369 *out = r; 370 return 1; 371 } 372 373 int api_const_fold_unop(KitCg* g, UnOp op, KitCgTypeId type, ApiConstValue a, 374 u32 flags, ApiConstValue* out) { 375 ApiConstValue r; 376 u32 width; 377 if (!out) return 0; 378 r = api_const_unknown(type); 379 if (!g || flags || !a.value.known || !const_type_width(g, type, &width)) { 380 *out = r; 381 return 0; 382 } 383 a.value = const_normalize(a.value, width); 384 r = api_const_int_result(g, type, 0, 0, a.value.is_signed); 385 switch (op) { 386 case UO_NEG: 387 r.value.lo = ~a.value.lo; 388 r.value.hi = ~a.value.hi; 389 r.value = const_add(const_normalize(r.value, width), 390 api_const_int_result(g, type, 1, 0, 0).value); 391 break; 392 case UO_NOT: 393 r.value.lo = const_is_zero(a.value) ? 1u : 0u; 394 r.value.hi = 0; 395 r.value = const_normalize(r.value, width); 396 break; 397 case UO_BNOT: 398 r.value.lo = ~a.value.lo; 399 r.value.hi = ~a.value.hi; 400 r.value = const_normalize(r.value, width); 401 break; 402 default: 403 *out = api_const_unknown(type); 404 return 0; 405 } 406 r.type = type; 407 r.value.known = 1u; 408 *out = r; 409 return 1; 410 } 411 412 int api_const_fold_cmp(KitCg* g, CmpOp op, ApiConstValue a, ApiConstValue b, 413 ApiConstValue* out) { 414 KitCgTypeId bool_ty = builtin_id(KIT_CG_BUILTIN_I32); 415 ApiConstValue r; 416 u32 width = a.value.width ? a.value.width : b.value.width; 417 int cmp; 418 int ok; 419 if (!out) return 0; 420 r = api_const_unknown(bool_ty); 421 if (!g || !a.value.known || !b.value.known || !width || width > 128u) { 422 *out = r; 423 return 0; 424 } 425 a.value = const_normalize(a.value, width); 426 b.value = const_normalize(b.value, width); 427 switch (op) { 428 case CMP_EQ: 429 ok = a.value.lo == b.value.lo && a.value.hi == b.value.hi; 430 break; 431 case CMP_NE: 432 ok = a.value.lo != b.value.lo || a.value.hi != b.value.hi; 433 break; 434 case CMP_LT_U: 435 ok = const_cmp_unsigned(a.value, b.value) < 0; 436 break; 437 case CMP_LE_U: 438 ok = const_cmp_unsigned(a.value, b.value) <= 0; 439 break; 440 case CMP_GT_U: 441 ok = const_cmp_unsigned(a.value, b.value) > 0; 442 break; 443 case CMP_GE_U: 444 ok = const_cmp_unsigned(a.value, b.value) >= 0; 445 break; 446 case CMP_LT_S: 447 cmp = const_cmp_signed(a.value, b.value); 448 ok = cmp < 0; 449 break; 450 case CMP_LE_S: 451 cmp = const_cmp_signed(a.value, b.value); 452 ok = cmp <= 0; 453 break; 454 case CMP_GT_S: 455 cmp = const_cmp_signed(a.value, b.value); 456 ok = cmp > 0; 457 break; 458 case CMP_GE_S: 459 cmp = const_cmp_signed(a.value, b.value); 460 ok = cmp >= 0; 461 break; 462 default: 463 *out = r; 464 return 0; 465 } 466 r = api_const_int_result(g, bool_ty, ok ? 1u : 0u, 0, 0); 467 *out = r; 468 return 1; 469 } 470 471 int api_const_fold_convert(KitCg* g, ConvKind ck, KitCgTypeId src_type, 472 KitCgTypeId dst_type, ApiConstValue in, 473 ApiConstValue* out) { 474 ApiConstValue r; 475 u32 sw; 476 u32 dw; 477 if (!out) return 0; 478 r = api_const_unknown(dst_type); 479 if (!g || !in.value.known || !const_type_width(g, src_type, &sw) || 480 !const_type_width(g, dst_type, &dw)) { 481 *out = r; 482 return 0; 483 } 484 switch (ck) { 485 case CV_TRUNC: 486 case CV_ZEXT: 487 r = api_const_int_result(g, dst_type, in.value.lo, in.value.hi, 488 in.value.is_signed); 489 break; 490 case CV_SEXT: 491 r = api_const_int_result(g, dst_type, 0, 0, 1); 492 r.value = const_sext(in.value, sw, dw); 493 r.value.known = 1u; 494 r.value.is_signed = 1u; 495 break; 496 case CV_BITCAST: 497 if (sw != dw) { 498 *out = r; 499 return 0; 500 } 501 r = api_const_int_result(g, dst_type, in.value.lo, in.value.hi, 502 in.value.is_signed); 503 break; 504 default: 505 *out = r; 506 return 0; 507 } 508 r.type = dst_type; 509 *out = r; 510 return r.value.known != 0; 511 } 512 513 void kit_cg_unevaluated_push(KitCg* g) { 514 if (!g) return; 515 ++g->unevaluated_depth; 516 CG_REQUIRE(g, g->unevaluated_depth != 0, "KitCg: unevaluated depth overflow"); 517 } 518 519 void kit_cg_unevaluated_pop(KitCg* g) { 520 if (!g) return; 521 CG_REQUIRE(g, g->unevaluated_depth, "KitCg: unevaluated pop underflow"); 522 --g->unevaluated_depth; 523 } 524 525 int kit_cg_top_const_int_ex(KitCg* g, KitCgConstInt* out_value) { 526 ApiConstValue cv; 527 if (!g || !g->sp) return 0; 528 cv = api_const_at(g, 0); 529 if (!cv.value.known) return 0; 530 if (out_value) *out_value = cv.value; 531 return 1; 532 } 533 534 int kit_cg_top_const_i64(KitCg* g, int64_t* out_value) { 535 KitCgConstInt v; 536 if (!out_value || !kit_cg_top_const_int_ex(g, &v) || v.width > 64u) return 0; 537 if (v.is_signed) 538 *out_value = api_sign_extend_width(v.lo, v.width); 539 else 540 *out_value = (int64_t)const_low_masked(v); 541 return 1; 542 } 543 544 int kit_cg_top_const_int(KitCg* g, int64_t* out_value) { 545 return kit_cg_top_const_i64(g, out_value); 546 }