| author | |
| committer | |
| log | aa89fd3b3e4522fe9199049a4fcc6bdc69f4bfde |
| tree | d93fec6d41037ce8c355f41a7798a2e87c984fd7 |
| parent | fa605485ea94ae9a59c8c1c0d66ee263e0bfa722 |
7 files changed, 337 insertions(+), 114 deletions(-)
src/all_types.hpp+1-1| ... | ... | @@ -65,7 +65,6 @@ struct ConstExprValue { |
| 65 | 65 | bool ok; // true if constant expression evalution worked |
| 66 | 66 | bool depends_on_compile_var; |
| 67 | 67 | bool undef; |
| 68 | bool deep_const; | |
| 69 | 68 | |
| 70 | 69 | union { |
| 71 | 70 | BigNum x_bignum; |
| ... | ... | @@ -961,6 +960,7 @@ struct TypeTableEntry { |
| 961 | 960 | LLVMZigDIType *di_type; |
| 962 | 961 | |
| 963 | 962 | bool zero_bits; |
| 963 | bool deep_const; | |
| 964 | 964 | |
| 965 | 965 | union { |
| 966 | 966 | TypeTableEntryPointer pointer; |
src/analyze.cpp+39-96| ... | ... | @@ -207,6 +207,7 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { |
| 207 | 207 | static TypeTableEntry *get_generic_fn_type(CodeGen *g, AstNode *decl_node) { |
| 208 | 208 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdGenericFn); |
| 209 | 209 | buf_init_from_str(&entry->name, "(generic function)"); |
| 210 | entry->deep_const = true; | |
| 210 | 211 | entry->zero_bits = true; |
| 211 | 212 | entry->data.generic_fn.decl_node = decl_node; |
| 212 | 213 | return entry; |
| ... | ... | @@ -220,6 +221,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 220 | 221 | } else { |
| 221 | 222 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer); |
| 222 | 223 | |
| 224 | entry->deep_const = is_const && child_type->deep_const; | |
| 225 | ||
| 223 | 226 | const char *const_str = is_const ? "const " : ""; |
| 224 | 227 | buf_resize(&entry->name, 0); |
| 225 | 228 | buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name)); |
| ... | ... | @@ -261,6 +264,8 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { |
| 261 | 264 | assert(child_type->type_ref); |
| 262 | 265 | assert(child_type->di_type); |
| 263 | 266 | |
| 267 | entry->deep_const = child_type->deep_const; | |
| 268 | ||
| 264 | 269 | buf_resize(&entry->name, 0); |
| 265 | 270 | buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); |
| 266 | 271 | |
| ... | ... | @@ -344,6 +349,8 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { |
| 344 | 349 | |
| 345 | 350 | entry->data.error.child_type = child_type; |
| 346 | 351 | |
| 352 | entry->deep_const = child_type->deep_const; | |
| 353 | ||
| 347 | 354 | if (!type_has_bits(child_type)) { |
| 348 | 355 | entry->type_ref = g->err_tag_type->type_ref; |
| 349 | 356 | entry->di_type = g->err_tag_type->di_type; |
| ... | ... | @@ -415,6 +422,7 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t |
| 415 | 422 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray); |
| 416 | 423 | entry->type_ref = LLVMArrayType(child_type->type_ref, array_size); |
| 417 | 424 | entry->zero_bits = (array_size == 0) || child_type->zero_bits; |
| 425 | entry->deep_const = child_type->deep_const; | |
| 418 | 426 | |
| 419 | 427 | buf_resize(&entry->name, 0); |
| 420 | 428 | buf_appendf(&entry->name, "[%" PRIu64 "]%s", array_size, buf_ptr(&child_type->name)); |
| ... | ... | @@ -465,6 +473,8 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c |
| 465 | 473 | TypeTableEntry *var_peer = get_slice_type(g, child_type, false); |
| 466 | 474 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); |
| 467 | 475 | |
| 476 | entry->deep_const = child_type->deep_const; | |
| 477 | ||
| 468 | 478 | buf_resize(&entry->name, 0); |
| 469 | 479 | buf_appendf(&entry->name, "[]const %s", buf_ptr(&child_type->name)); |
| 470 | 480 | |
| ... | ... | @@ -550,6 +560,7 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry * |
| 550 | 560 | |
| 551 | 561 | buf_init_from_str(&entry->name, name); |
| 552 | 562 | |
| 563 | entry->deep_const = child_type->deep_const; | |
| 553 | 564 | entry->type_ref = child_type->type_ref; |
| 554 | 565 | entry->di_type = child_type->di_type; |
| 555 | 566 | entry->zero_bits = child_type->zero_bits; |
| ... | ... | @@ -573,6 +584,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 573 | 584 | } |
| 574 | 585 | |
| 575 | 586 | TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn); |
| 587 | fn_type->deep_const = true; | |
| 576 | 588 | fn_type->data.fn.fn_type_id = *fn_type_id; |
| 577 | 589 | if (fn_type_id->param_info == &fn_type_id->prealloc_param_info[0]) { |
| 578 | 590 | fn_type->data.fn.fn_type_id.param_info = &fn_type->data.fn.fn_type_id.prealloc_param_info[0]; |
| ... | ... | @@ -1038,6 +1050,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 1038 | 1050 | |
| 1039 | 1051 | assert(enum_type->di_type); |
| 1040 | 1052 | |
| 1053 | enum_type->deep_const = true; | |
| 1054 | ||
| 1041 | 1055 | uint32_t field_count = decl_node->data.struct_decl.fields.length; |
| 1042 | 1056 | |
| 1043 | 1057 | enum_type->data.enumeration.field_count = field_count; |
| ... | ... | @@ -1065,6 +1079,10 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 1065 | 1079 | type_enum_field->type_entry = field_type; |
| 1066 | 1080 | type_enum_field->value = i; |
| 1067 | 1081 | |
| 1082 | if (!field_type->deep_const) { | |
| 1083 | enum_type->deep_const = false; | |
| 1084 | } | |
| 1085 | ||
| 1068 | 1086 | |
| 1069 | 1087 | di_enumerators[i] = LLVMZigCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i); |
| 1070 | 1088 | |
| ... | ... | @@ -1225,6 +1243,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 1225 | 1243 | |
| 1226 | 1244 | assert(struct_type->di_type); |
| 1227 | 1245 | |
| 1246 | struct_type->deep_const = true; | |
| 1247 | ||
| 1228 | 1248 | int field_count = decl_node->data.struct_decl.fields.length; |
| 1229 | 1249 | |
| 1230 | 1250 | struct_type->data.structure.src_field_count = field_count; |
| ... | ... | @@ -1248,6 +1268,10 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 1248 | 1268 | type_struct_field->src_index = i; |
| 1249 | 1269 | type_struct_field->gen_index = -1; |
| 1250 | 1270 | |
| 1271 | if (!field_type->deep_const) { | |
| 1272 | struct_type->deep_const = false; | |
| 1273 | } | |
| 1274 | ||
| 1251 | 1275 | if (field_type->id == TypeTableEntryIdStruct) { |
| 1252 | 1276 | resolve_struct_type(g, import, field_type); |
| 1253 | 1277 | } else if (field_type->id == TypeTableEntryIdEnum) { |
| ... | ... | @@ -2486,7 +2510,6 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i |
| 2486 | 2510 | static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node) { |
| 2487 | 2511 | Expr *expr = get_resolved_expr(node); |
| 2488 | 2512 | expr->const_val.ok = true; |
| 2489 | expr->const_val.deep_const = true; | |
| 2490 | 2513 | return g->builtin_types.entry_void; |
| 2491 | 2514 | } |
| 2492 | 2515 | |
| ... | ... | @@ -2494,7 +2517,6 @@ static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, |
| 2494 | 2517 | Expr *expr = get_resolved_expr(node); |
| 2495 | 2518 | expr->const_val.ok = true; |
| 2496 | 2519 | expr->const_val.data.x_type = type; |
| 2497 | expr->const_val.deep_const = true; | |
| 2498 | 2520 | return g->builtin_types.entry_type; |
| 2499 | 2521 | } |
| 2500 | 2522 | |
| ... | ... | @@ -2509,7 +2531,6 @@ static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, F |
| 2509 | 2531 | Expr *expr = get_resolved_expr(node); |
| 2510 | 2532 | expr->const_val.ok = true; |
| 2511 | 2533 | expr->const_val.data.x_fn = fn; |
| 2512 | expr->const_val.deep_const = true; | |
| 2513 | 2534 | return fn->type_entry; |
| 2514 | 2535 | } |
| 2515 | 2536 | |
| ... | ... | @@ -2519,7 +2540,6 @@ static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode |
| 2519 | 2540 | Expr *expr = get_resolved_expr(node); |
| 2520 | 2541 | expr->const_val.ok = true; |
| 2521 | 2542 | expr->const_val.data.x_type = type_entry; |
| 2522 | expr->const_val.deep_const = true; | |
| 2523 | 2543 | return type_entry; |
| 2524 | 2544 | } |
| 2525 | 2545 | |
| ... | ... | @@ -2527,7 +2547,6 @@ static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node, |
| 2527 | 2547 | Expr *expr = get_resolved_expr(node); |
| 2528 | 2548 | expr->const_val.ok = true; |
| 2529 | 2549 | expr->const_val.data.x_err.err = err; |
| 2530 | expr->const_val.deep_const = true; | |
| 2531 | 2550 | return g->builtin_types.entry_pure_error; |
| 2532 | 2551 | } |
| 2533 | 2552 | |
| ... | ... | @@ -2538,7 +2557,6 @@ static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, |
| 2538 | 2557 | expr->const_val.ok = true; |
| 2539 | 2558 | expr->const_val.depends_on_compile_var = depends_on_compile_var; |
| 2540 | 2559 | expr->const_val.data.x_bool = value; |
| 2541 | expr->const_val.deep_const = true; | |
| 2542 | 2560 | return g->builtin_types.entry_bool; |
| 2543 | 2561 | } |
| 2544 | 2562 | |
| ... | ... | @@ -2546,7 +2564,6 @@ static TypeTableEntry *resolve_expr_const_val_as_null(CodeGen *g, AstNode *node, |
| 2546 | 2564 | Expr *expr = get_resolved_expr(node); |
| 2547 | 2565 | expr->const_val.ok = true; |
| 2548 | 2566 | expr->const_val.data.x_maybe = nullptr; |
| 2549 | expr->const_val.deep_const = true; | |
| 2550 | 2567 | return type; |
| 2551 | 2568 | } |
| 2552 | 2569 | |
| ... | ... | @@ -2557,14 +2574,12 @@ static TypeTableEntry *resolve_expr_const_val_as_non_null(CodeGen *g, AstNode *n |
| 2557 | 2574 | Expr *expr = get_resolved_expr(node); |
| 2558 | 2575 | expr->const_val.ok = true; |
| 2559 | 2576 | expr->const_val.data.x_maybe = other_val; |
| 2560 | expr->const_val.deep_const = other_val->deep_const; | |
| 2561 | 2577 | return type; |
| 2562 | 2578 | } |
| 2563 | 2579 | |
| 2564 | 2580 | static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNode *node, Buf *str) { |
| 2565 | 2581 | Expr *expr = get_resolved_expr(node); |
| 2566 | 2582 | expr->const_val.ok = true; |
| 2567 | expr->const_val.deep_const = true; | |
| 2568 | 2583 | |
| 2569 | 2584 | int len_with_null = buf_len(str) + 1; |
| 2570 | 2585 | expr->const_val.data.x_ptr.ptr = allocate<ConstExprValue*>(len_with_null); |
| ... | ... | @@ -2574,14 +2589,12 @@ static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNod |
| 2574 | 2589 | for (int i = 0; i < buf_len(str); i += 1) { |
| 2575 | 2590 | ConstExprValue *this_char = &all_chars[i]; |
| 2576 | 2591 | this_char->ok = true; |
| 2577 | this_char->deep_const = true; | |
| 2578 | 2592 | bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]); |
| 2579 | 2593 | expr->const_val.data.x_ptr.ptr[i] = this_char; |
| 2580 | 2594 | } |
| 2581 | 2595 | |
| 2582 | 2596 | ConstExprValue *null_char = &all_chars[len_with_null - 1]; |
| 2583 | 2597 | null_char->ok = true; |
| 2584 | null_char->deep_const = true; | |
| 2585 | 2598 | bignum_init_unsigned(&null_char->data.x_bignum, 0); |
| 2586 | 2599 | expr->const_val.data.x_ptr.ptr[len_with_null - 1] = null_char; |
| 2587 | 2600 | |
| ... | ... | @@ -2591,14 +2604,12 @@ static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNod |
| 2591 | 2604 | static TypeTableEntry *resolve_expr_const_val_as_string_lit(CodeGen *g, AstNode *node, Buf *str) { |
| 2592 | 2605 | Expr *expr = get_resolved_expr(node); |
| 2593 | 2606 | expr->const_val.ok = true; |
| 2594 | expr->const_val.deep_const = true; | |
| 2595 | 2607 | expr->const_val.data.x_array.fields = allocate<ConstExprValue*>(buf_len(str)); |
| 2596 | 2608 | |
| 2597 | 2609 | ConstExprValue *all_chars = allocate<ConstExprValue>(buf_len(str)); |
| 2598 | 2610 | for (int i = 0; i < buf_len(str); i += 1) { |
| 2599 | 2611 | ConstExprValue *this_char = &all_chars[i]; |
| 2600 | 2612 | this_char->ok = true; |
| 2601 | this_char->deep_const = true; | |
| 2602 | 2613 | bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]); |
| 2603 | 2614 | expr->const_val.data.x_array.fields[i] = this_char; |
| 2604 | 2615 | } |
| ... | ... | @@ -2611,7 +2622,6 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As |
| 2611 | 2622 | { |
| 2612 | 2623 | Expr *expr = get_resolved_expr(node); |
| 2613 | 2624 | expr->const_val.ok = true; |
| 2614 | expr->const_val.deep_const = true; | |
| 2615 | 2625 | |
| 2616 | 2626 | bignum_init_unsigned(&expr->const_val.data.x_bignum, x); |
| 2617 | 2627 | |
| ... | ... | @@ -2623,7 +2633,6 @@ static TypeTableEntry *resolve_expr_const_val_as_float_num_lit(CodeGen *g, AstNo |
| 2623 | 2633 | { |
| 2624 | 2634 | Expr *expr = get_resolved_expr(node); |
| 2625 | 2635 | expr->const_val.ok = true; |
| 2626 | expr->const_val.deep_const = true; | |
| 2627 | 2636 | |
| 2628 | 2637 | bignum_init_float(&expr->const_val.data.x_bignum, x); |
| 2629 | 2638 | |
| ... | ... | @@ -2639,7 +2648,6 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode * |
| 2639 | 2648 | ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val; |
| 2640 | 2649 | |
| 2641 | 2650 | const_val->ok = true; |
| 2642 | const_val->deep_const = true; | |
| 2643 | 2651 | |
| 2644 | 2652 | if (bignum_fn(&const_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum)) { |
| 2645 | 2653 | add_node_error(g, node, |
| ... | ... | @@ -2713,12 +2721,7 @@ static bool var_is_pure(VariableTableEntry *var, TypeTableEntry *var_type, Block |
| 2713 | 2721 | // variable was declared in the current function, so it's OK. |
| 2714 | 2722 | return true; |
| 2715 | 2723 | } |
| 2716 | if (!var->is_const) { | |
| 2717 | return false; | |
| 2718 | } | |
| 2719 | ||
| 2720 | ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val; | |
| 2721 | return const_val->deep_const; | |
| 2724 | return var->is_const && var->type->deep_const; | |
| 2722 | 2725 | } |
| 2723 | 2726 | |
| 2724 | 2727 | static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| ... | ... | @@ -3714,17 +3717,6 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, |
| 3714 | 3717 | node, then_node, else_node, cond_is_const, cond_bool_val); |
| 3715 | 3718 | } |
| 3716 | 3719 | |
| 3717 | static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type) { | |
| 3718 | assert(int_type->id == TypeTableEntryIdInt); | |
| 3719 | ||
| 3720 | for (int i = 0; i < CIntTypeCount; i += 1) { | |
| 3721 | if (int_type == g->builtin_types.entry_c_int[i]) { | |
| 3722 | return true; | |
| 3723 | } | |
| 3724 | } | |
| 3725 | return false; | |
| 3726 | } | |
| 3727 | ||
| 3728 | 3720 | static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 3729 | 3721 | AstNode *node, const char *err_format, bool is_max) |
| 3730 | 3722 | { |
| ... | ... | @@ -3733,67 +3725,15 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor |
| 3733 | 3725 | |
| 3734 | 3726 | AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| 3735 | 3727 | TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); |
| 3728 | ||
| 3736 | 3729 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 3737 | 3730 | return g->builtin_types.entry_invalid; |
| 3738 | } else if (type_entry->id == TypeTableEntryIdInt) { | |
| 3739 | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | |
| 3740 | const_val->ok = true; | |
| 3741 | const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry); | |
| 3742 | if (is_max) { | |
| 3743 | if (type_entry->data.integral.is_signed) { | |
| 3744 | int64_t val; | |
| 3745 | if (type_entry->data.integral.bit_count == 64) { | |
| 3746 | val = INT64_MAX; | |
| 3747 | } else if (type_entry->data.integral.bit_count == 32) { | |
| 3748 | val = INT32_MAX; | |
| 3749 | } else if (type_entry->data.integral.bit_count == 16) { | |
| 3750 | val = INT16_MAX; | |
| 3751 | } else if (type_entry->data.integral.bit_count == 8) { | |
| 3752 | val = INT8_MAX; | |
| 3753 | } else { | |
| 3754 | zig_unreachable(); | |
| 3755 | } | |
| 3756 | bignum_init_signed(&const_val->data.x_bignum, val); | |
| 3757 | } else { | |
| 3758 | uint64_t val; | |
| 3759 | if (type_entry->data.integral.bit_count == 64) { | |
| 3760 | val = UINT64_MAX; | |
| 3761 | } else if (type_entry->data.integral.bit_count == 32) { | |
| 3762 | val = UINT32_MAX; | |
| 3763 | } else if (type_entry->data.integral.bit_count == 16) { | |
| 3764 | val = UINT16_MAX; | |
| 3765 | } else if (type_entry->data.integral.bit_count == 8) { | |
| 3766 | val = UINT8_MAX; | |
| 3767 | } else { | |
| 3768 | zig_unreachable(); | |
| 3769 | } | |
| 3770 | bignum_init_unsigned(&const_val->data.x_bignum, val); | |
| 3771 | } | |
| 3772 | } else { | |
| 3773 | if (type_entry->data.integral.is_signed) { | |
| 3774 | int64_t val; | |
| 3775 | if (type_entry->data.integral.bit_count == 64) { | |
| 3776 | val = INT64_MIN; | |
| 3777 | } else if (type_entry->data.integral.bit_count == 32) { | |
| 3778 | val = INT32_MIN; | |
| 3779 | } else if (type_entry->data.integral.bit_count == 16) { | |
| 3780 | val = INT16_MIN; | |
| 3781 | } else if (type_entry->data.integral.bit_count == 8) { | |
| 3782 | val = INT8_MIN; | |
| 3783 | } else { | |
| 3784 | zig_unreachable(); | |
| 3785 | } | |
| 3786 | bignum_init_signed(&const_val->data.x_bignum, val); | |
| 3787 | } else { | |
| 3788 | bignum_init_unsigned(&const_val->data.x_bignum, 0); | |
| 3789 | } | |
| 3790 | } | |
| 3791 | return type_entry; | |
| 3792 | } else if (type_entry->id == TypeTableEntryIdFloat) { | |
| 3793 | zig_panic("TODO analyze_min_max_value float"); | |
| 3731 | } else if (type_entry->id == TypeTableEntryIdInt || | |
| 3732 | type_entry->id == TypeTableEntryIdFloat || | |
| 3733 | type_entry->id == TypeTableEntryIdBool) | |
| 3734 | { | |
| 3735 | eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); | |
| 3794 | 3736 | return type_entry; |
| 3795 | } else if (type_entry->id == TypeTableEntryIdBool) { | |
| 3796 | return resolve_expr_const_val_as_bool(g, node, is_max, false); | |
| 3797 | 3737 | } else { |
| 3798 | 3738 | add_node_error(g, node, |
| 3799 | 3739 | buf_sprintf(err_format, buf_ptr(&type_entry->name))); |
| ... | ... | @@ -3810,7 +3750,8 @@ static TypeTableEntry *resolve_cast(CodeGen *g, BlockContext *context, AstNode * |
| 3810 | 3750 | TypeTableEntry *other_type = get_resolved_expr(expr_node)->type_entry; |
| 3811 | 3751 | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| 3812 | 3752 | if (other_val->ok) { |
| 3813 | eval_const_expr_implicit_cast(node->data.fn_call_expr.cast_op, other_val, other_type, const_val); | |
| 3753 | eval_const_expr_implicit_cast(node->data.fn_call_expr.cast_op, other_val, other_type, | |
| 3754 | const_val, wanted_type); | |
| 3814 | 3755 | } |
| 3815 | 3756 | |
| 3816 | 3757 | if (need_alloca) { |
| ... | ... | @@ -4238,8 +4179,6 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 4238 | 4179 | } |
| 4239 | 4180 | case BuiltinFnIdMemcpy: |
| 4240 | 4181 | { |
| 4241 | mark_impure_fn(context); | |
| 4242 | ||
| 4243 | 4182 | AstNode *dest_node = node->data.fn_call_expr.params.at(0); |
| 4244 | 4183 | AstNode *src_node = node->data.fn_call_expr.params.at(1); |
| 4245 | 4184 | AstNode *len_node = node->data.fn_call_expr.params.at(2); |
| ... | ... | @@ -4278,8 +4217,6 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 4278 | 4217 | } |
| 4279 | 4218 | case BuiltinFnIdMemset: |
| 4280 | 4219 | { |
| 4281 | mark_impure_fn(context); | |
| 4282 | ||
| 4283 | 4220 | AstNode *dest_node = node->data.fn_call_expr.params.at(0); |
| 4284 | 4221 | AstNode *char_node = node->data.fn_call_expr.params.at(1); |
| 4285 | 4222 | AstNode *len_node = node->data.fn_call_expr.params.at(2); |
| ... | ... | @@ -4601,6 +4538,8 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, |
| 4601 | 4538 | // calling an impure fn is impure |
| 4602 | 4539 | mark_impure_fn(context); |
| 4603 | 4540 | } |
| 4541 | } else { | |
| 4542 | mark_impure_fn(context); | |
| 4604 | 4543 | } |
| 4605 | 4544 | |
| 4606 | 4545 | if (handle_is_ptr(return_type)) { |
| ... | ... | @@ -5602,6 +5541,10 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 5602 | 5541 | param_decl_node->data.param_decl.variable = var; |
| 5603 | 5542 | |
| 5604 | 5543 | var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index; |
| 5544 | ||
| 5545 | if (!type->deep_const) { | |
| 5546 | fn_table_entry->is_pure = false; | |
| 5547 | } | |
| 5605 | 5548 | } |
| 5606 | 5549 | |
| 5607 | 5550 | TypeTableEntry *expected_type = fn_type->data.fn.fn_type_id.return_type; |
src/bignum.cpp+5| ... | ... | @@ -71,6 +71,11 @@ bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) { |
| 71 | 71 | } |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | void bignum_truncate(BigNum *bn, int bit_count) { | |
| 75 | assert(bn->kind == BigNumKindInt); | |
| 76 | bn->data.x_uint &= (1LL << bit_count) - 1; | |
| 77 | } | |
| 78 | ||
| 74 | 79 | uint64_t bignum_to_twos_complement(BigNum *bn) { |
| 75 | 80 | assert(bn->kind == BigNumKindInt); |
| 76 | 81 |
src/bignum.hpp+2| ... | ... | @@ -47,6 +47,8 @@ void bignum_negate(BigNum *dest, BigNum *op); |
| 47 | 47 | void bignum_cast_to_float(BigNum *dest, BigNum *op); |
| 48 | 48 | void bignum_cast_to_int(BigNum *dest, BigNum *op); |
| 49 | 49 | |
| 50 | void bignum_truncate(BigNum *dest, int bit_count); | |
| 51 | ||
| 50 | 52 | // returns the result of the comparison |
| 51 | 53 | bool bignum_cmp_eq(BigNum *op1, BigNum *op2); |
| 52 | 54 | bool bignum_cmp_neq(BigNum *op1, BigNum *op2); |
src/codegen.cpp+19| ... | ... | @@ -3463,23 +3463,27 @@ static void define_builtin_types(CodeGen *g) { |
| 3463 | 3463 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNamespace); |
| 3464 | 3464 | buf_init_from_str(&entry->name, "(namespace)"); |
| 3465 | 3465 | entry->zero_bits = true; |
| 3466 | entry->deep_const = true; | |
| 3466 | 3467 | g->builtin_types.entry_namespace = entry; |
| 3467 | 3468 | } |
| 3468 | 3469 | { |
| 3469 | 3470 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat); |
| 3470 | 3471 | buf_init_from_str(&entry->name, "(float literal)"); |
| 3471 | 3472 | entry->zero_bits = true; |
| 3473 | entry->deep_const = true; | |
| 3472 | 3474 | g->builtin_types.entry_num_lit_float = entry; |
| 3473 | 3475 | } |
| 3474 | 3476 | { |
| 3475 | 3477 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitInt); |
| 3476 | 3478 | buf_init_from_str(&entry->name, "(integer literal)"); |
| 3477 | 3479 | entry->zero_bits = true; |
| 3480 | entry->deep_const = true; | |
| 3478 | 3481 | g->builtin_types.entry_num_lit_int = entry; |
| 3479 | 3482 | } |
| 3480 | 3483 | { |
| 3481 | 3484 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefLit); |
| 3482 | 3485 | buf_init_from_str(&entry->name, "(undefined)"); |
| 3486 | entry->deep_const = true; | |
| 3483 | 3487 | g->builtin_types.entry_undef = entry; |
| 3484 | 3488 | } |
| 3485 | 3489 | |
| ... | ... | @@ -3489,6 +3493,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3489 | 3493 | for (;;) { |
| 3490 | 3494 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 3491 | 3495 | entry->type_ref = LLVMIntType(size_in_bits); |
| 3496 | entry->deep_const = true; | |
| 3492 | 3497 | |
| 3493 | 3498 | const char u_or_i = is_signed ? 'i' : 'u'; |
| 3494 | 3499 | buf_resize(&entry->name, 0); |
| ... | ... | @@ -3534,6 +3539,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3534 | 3539 | |
| 3535 | 3540 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 3536 | 3541 | entry->type_ref = LLVMIntType(size_in_bits); |
| 3542 | entry->deep_const = true; | |
| 3537 | 3543 | |
| 3538 | 3544 | buf_init_from_str(&entry->name, info->name); |
| 3539 | 3545 | |
| ... | ... | @@ -3553,6 +3559,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3553 | 3559 | { |
| 3554 | 3560 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool); |
| 3555 | 3561 | entry->type_ref = LLVMInt1Type(); |
| 3562 | entry->deep_const = true; | |
| 3556 | 3563 | buf_init_from_str(&entry->name, "bool"); |
| 3557 | 3564 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); |
| 3558 | 3565 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref); |
| ... | ... | @@ -3565,6 +3572,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3565 | 3572 | } |
| 3566 | 3573 | { |
| 3567 | 3574 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 3575 | entry->deep_const = true; | |
| 3568 | 3576 | entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8); |
| 3569 | 3577 | buf_init_from_str(&entry->name, "isize"); |
| 3570 | 3578 | entry->data.integral.is_signed = true; |
| ... | ... | @@ -3581,6 +3589,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3581 | 3589 | } |
| 3582 | 3590 | { |
| 3583 | 3591 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 3592 | entry->deep_const = true; | |
| 3584 | 3593 | entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8); |
| 3585 | 3594 | buf_init_from_str(&entry->name, "usize"); |
| 3586 | 3595 | entry->data.integral.is_signed = false; |
| ... | ... | @@ -3597,6 +3606,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3597 | 3606 | } |
| 3598 | 3607 | { |
| 3599 | 3608 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); |
| 3609 | entry->deep_const = true; | |
| 3600 | 3610 | entry->type_ref = LLVMFloatType(); |
| 3601 | 3611 | buf_init_from_str(&entry->name, "f32"); |
| 3602 | 3612 | entry->data.floating.bit_count = 32; |
| ... | ... | @@ -3612,6 +3622,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3612 | 3622 | } |
| 3613 | 3623 | { |
| 3614 | 3624 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); |
| 3625 | entry->deep_const = true; | |
| 3615 | 3626 | entry->type_ref = LLVMDoubleType(); |
| 3616 | 3627 | buf_init_from_str(&entry->name, "f64"); |
| 3617 | 3628 | entry->data.floating.bit_count = 64; |
| ... | ... | @@ -3627,6 +3638,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3627 | 3638 | } |
| 3628 | 3639 | { |
| 3629 | 3640 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); |
| 3641 | entry->deep_const = true; | |
| 3630 | 3642 | entry->type_ref = LLVMX86FP80Type(); |
| 3631 | 3643 | buf_init_from_str(&entry->name, "c_long_double"); |
| 3632 | 3644 | entry->data.floating.bit_count = 80; |
| ... | ... | @@ -3642,6 +3654,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3642 | 3654 | } |
| 3643 | 3655 | { |
| 3644 | 3656 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid); |
| 3657 | entry->deep_const = true; | |
| 3645 | 3658 | entry->type_ref = LLVMVoidType(); |
| 3646 | 3659 | entry->zero_bits = true; |
| 3647 | 3660 | buf_init_from_str(&entry->name, "void"); |
| ... | ... | @@ -3654,6 +3667,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3654 | 3667 | } |
| 3655 | 3668 | { |
| 3656 | 3669 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUnreachable); |
| 3670 | entry->deep_const = true; | |
| 3657 | 3671 | entry->type_ref = LLVMVoidType(); |
| 3658 | 3672 | entry->zero_bits = true; |
| 3659 | 3673 | buf_init_from_str(&entry->name, "unreachable"); |
| ... | ... | @@ -3663,6 +3677,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3663 | 3677 | } |
| 3664 | 3678 | { |
| 3665 | 3679 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType); |
| 3680 | entry->deep_const = true; | |
| 3666 | 3681 | buf_init_from_str(&entry->name, "type"); |
| 3667 | 3682 | entry->zero_bits = true; |
| 3668 | 3683 | g->builtin_types.entry_type = entry; |
| ... | ... | @@ -3685,6 +3700,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3685 | 3700 | |
| 3686 | 3701 | { |
| 3687 | 3702 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError); |
| 3703 | entry->deep_const = true; | |
| 3688 | 3704 | buf_init_from_str(&entry->name, "error"); |
| 3689 | 3705 | |
| 3690 | 3706 | // TODO allow overriding this type and keep track of max value and emit an |
| ... | ... | @@ -3700,6 +3716,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3700 | 3716 | |
| 3701 | 3717 | { |
| 3702 | 3718 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); |
| 3719 | entry->deep_const = true; | |
| 3703 | 3720 | entry->zero_bits = true; // only allowed at compile time |
| 3704 | 3721 | buf_init_from_str(&entry->name, "@OS"); |
| 3705 | 3722 | uint32_t field_count = target_os_count(); |
| ... | ... | @@ -3725,6 +3742,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3725 | 3742 | |
| 3726 | 3743 | { |
| 3727 | 3744 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); |
| 3745 | entry->deep_const = true; | |
| 3728 | 3746 | entry->zero_bits = true; // only allowed at compile time |
| 3729 | 3747 | buf_init_from_str(&entry->name, "@Arch"); |
| 3730 | 3748 | uint32_t field_count = target_arch_count(); |
| ... | ... | @@ -3756,6 +3774,7 @@ static void define_builtin_types(CodeGen *g) { |
| 3756 | 3774 | |
| 3757 | 3775 | { |
| 3758 | 3776 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); |
| 3777 | entry->deep_const = true; | |
| 3759 | 3778 | entry->zero_bits = true; // only allowed at compile time |
| 3760 | 3779 | buf_init_from_str(&entry->name, "@Environ"); |
| 3761 | 3780 | uint32_t field_count = target_environ_count(); |
src/eval.cpp+268-16| ... | ... | @@ -360,7 +360,7 @@ static bool eval_if_bool_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val |
| 360 | 360 | |
| 361 | 361 | void eval_const_expr_implicit_cast(CastOp cast_op, |
| 362 | 362 | ConstExprValue *other_val, TypeTableEntry *other_type, |
| 363 | ConstExprValue *const_val) | |
| 363 | ConstExprValue *const_val, TypeTableEntry *new_type) | |
| 364 | 364 | { |
| 365 | 365 | const_val->depends_on_compile_var = other_val->depends_on_compile_var; |
| 366 | 366 | const_val->undef = other_val->undef; |
| ... | ... | @@ -371,9 +371,30 @@ void eval_const_expr_implicit_cast(CastOp cast_op, |
| 371 | 371 | zig_unreachable(); |
| 372 | 372 | case CastOpNoop: |
| 373 | 373 | case CastOpWidenOrShorten: |
| 374 | case CastOpPointerReinterpret: | |
| 375 | 374 | *const_val = *other_val; |
| 376 | 375 | break; |
| 376 | case CastOpPointerReinterpret: | |
| 377 | { | |
| 378 | TypeTableEntry *other_child_type = other_type->data.pointer.child_type; | |
| 379 | TypeTableEntry *new_child_type = new_type->data.pointer.child_type; | |
| 380 | ||
| 381 | if ((other_child_type->id == TypeTableEntryIdInt || | |
| 382 | other_child_type->id == TypeTableEntryIdFloat) && | |
| 383 | (new_child_type->id == TypeTableEntryIdInt || | |
| 384 | new_child_type->id == TypeTableEntryIdFloat)) | |
| 385 | { | |
| 386 | ConstExprValue **ptr_val = allocate<ConstExprValue*>(1); | |
| 387 | *ptr_val = other_val->data.x_ptr.ptr[0]; | |
| 388 | const_val->data.x_ptr.ptr = ptr_val; | |
| 389 | const_val->data.x_ptr.len = 1; | |
| 390 | const_val->ok = true; | |
| 391 | const_val->undef = other_val->undef; | |
| 392 | const_val->depends_on_compile_var = other_val->depends_on_compile_var; | |
| 393 | } else { | |
| 394 | zig_panic("TODO"); | |
| 395 | } | |
| 396 | break; | |
| 397 | } | |
| 377 | 398 | case CastOpPtrToInt: |
| 378 | 399 | case CastOpIntToPtr: |
| 379 | 400 | // can't do it |
| ... | ... | @@ -435,20 +456,184 @@ void eval_const_expr_implicit_cast(CastOp cast_op, |
| 435 | 456 | } |
| 436 | 457 | } |
| 437 | 458 | |
| 459 | static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type) { | |
| 460 | assert(int_type->id == TypeTableEntryIdInt); | |
| 461 | ||
| 462 | for (int i = 0; i < CIntTypeCount; i += 1) { | |
| 463 | if (int_type == g->builtin_types.entry_c_int[i]) { | |
| 464 | return true; | |
| 465 | } | |
| 466 | } | |
| 467 | return false; | |
| 468 | } | |
| 469 | ||
| 470 | void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) { | |
| 471 | if (type_entry->id == TypeTableEntryIdInt) { | |
| 472 | const_val->ok = true; | |
| 473 | const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry); | |
| 474 | if (is_max) { | |
| 475 | if (type_entry->data.integral.is_signed) { | |
| 476 | int64_t val; | |
| 477 | if (type_entry->data.integral.bit_count == 64) { | |
| 478 | val = INT64_MAX; | |
| 479 | } else if (type_entry->data.integral.bit_count == 32) { | |
| 480 | val = INT32_MAX; | |
| 481 | } else if (type_entry->data.integral.bit_count == 16) { | |
| 482 | val = INT16_MAX; | |
| 483 | } else if (type_entry->data.integral.bit_count == 8) { | |
| 484 | val = INT8_MAX; | |
| 485 | } else { | |
| 486 | zig_unreachable(); | |
| 487 | } | |
| 488 | bignum_init_signed(&const_val->data.x_bignum, val); | |
| 489 | } else { | |
| 490 | uint64_t val; | |
| 491 | if (type_entry->data.integral.bit_count == 64) { | |
| 492 | val = UINT64_MAX; | |
| 493 | } else if (type_entry->data.integral.bit_count == 32) { | |
| 494 | val = UINT32_MAX; | |
| 495 | } else if (type_entry->data.integral.bit_count == 16) { | |
| 496 | val = UINT16_MAX; | |
| 497 | } else if (type_entry->data.integral.bit_count == 8) { | |
| 498 | val = UINT8_MAX; | |
| 499 | } else { | |
| 500 | zig_unreachable(); | |
| 501 | } | |
| 502 | bignum_init_unsigned(&const_val->data.x_bignum, val); | |
| 503 | } | |
| 504 | } else { | |
| 505 | if (type_entry->data.integral.is_signed) { | |
| 506 | int64_t val; | |
| 507 | if (type_entry->data.integral.bit_count == 64) { | |
| 508 | val = INT64_MIN; | |
| 509 | } else if (type_entry->data.integral.bit_count == 32) { | |
| 510 | val = INT32_MIN; | |
| 511 | } else if (type_entry->data.integral.bit_count == 16) { | |
| 512 | val = INT16_MIN; | |
| 513 | } else if (type_entry->data.integral.bit_count == 8) { | |
| 514 | val = INT8_MIN; | |
| 515 | } else { | |
| 516 | zig_unreachable(); | |
| 517 | } | |
| 518 | bignum_init_signed(&const_val->data.x_bignum, val); | |
| 519 | } else { | |
| 520 | bignum_init_unsigned(&const_val->data.x_bignum, 0); | |
| 521 | } | |
| 522 | } | |
| 523 | } else if (type_entry->id == TypeTableEntryIdFloat) { | |
| 524 | zig_panic("TODO analyze_min_max_value float"); | |
| 525 | } else if (type_entry->id == TypeTableEntryIdBool) { | |
| 526 | const_val->ok = true; | |
| 527 | const_val->data.x_bool = is_max; | |
| 528 | } else { | |
| 529 | zig_unreachable(); | |
| 530 | } | |
| 531 | } | |
| 532 | ||
| 533 | static bool eval_min_max(EvalFn *ef, AstNode *node, ConstExprValue *out_val, bool is_max) { | |
| 534 | assert(node->type == NodeTypeFnCallExpr); | |
| 535 | AstNode *type_node = node->data.fn_call_expr.params.at(0); | |
| 536 | TypeTableEntry *type_entry = resolve_expr_type(type_node); | |
| 537 | eval_min_max_value(ef->root->codegen, type_entry, out_val, is_max); | |
| 538 | return false; | |
| 539 | } | |
| 540 | ||
| 541 | static bool eval_fn_with_overflow(EvalFn *ef, AstNode *node, ConstExprValue *out_val, | |
| 542 | bool (*bignum_fn)(BigNum *dest, BigNum *op1, BigNum *op2)) | |
| 543 | { | |
| 544 | assert(node->type == NodeTypeFnCallExpr); | |
| 545 | ||
| 546 | AstNode *type_node = node->data.fn_call_expr.params.at(0); | |
| 547 | TypeTableEntry *int_type = resolve_expr_type(type_node); | |
| 548 | assert(int_type->id == TypeTableEntryIdInt); | |
| 549 | ||
| 550 | AstNode *op1_node = node->data.fn_call_expr.params.at(1); | |
| 551 | AstNode *op2_node = node->data.fn_call_expr.params.at(2); | |
| 552 | AstNode *result_node = node->data.fn_call_expr.params.at(3); | |
| 553 | ||
| 554 | ConstExprValue op1_val = {0}; | |
| 555 | if (eval_expr(ef, op1_node, &op1_val)) return true; | |
| 556 | ||
| 557 | ConstExprValue op2_val = {0}; | |
| 558 | if (eval_expr(ef, op2_node, &op2_val)) return true; | |
| 559 | ||
| 560 | ConstExprValue result_ptr_val = {0}; | |
| 561 | if (eval_expr(ef, result_node, &result_ptr_val)) return true; | |
| 562 | ||
| 563 | ConstExprValue *result_val = result_ptr_val.data.x_ptr.ptr[0]; | |
| 564 | ||
| 565 | out_val->ok = true; | |
| 566 | bool overflow = bignum_fn(&result_val->data.x_bignum, &op1_val.data.x_bignum, &op2_val.data.x_bignum); | |
| 567 | ||
| 568 | overflow = overflow || !bignum_fits_in_bits(&result_val->data.x_bignum, | |
| 569 | int_type->data.integral.bit_count, int_type->data.integral.is_signed); | |
| 570 | ||
| 571 | out_val->data.x_bool = overflow; | |
| 572 | ||
| 573 | if (overflow) { | |
| 574 | bignum_truncate(&result_val->data.x_bignum, int_type->data.integral.bit_count); | |
| 575 | } | |
| 576 | ||
| 577 | return false; | |
| 578 | } | |
| 579 | ||
| 580 | static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_val) { | |
| 581 | assert(node->type == NodeTypeFnCallExpr); | |
| 582 | ||
| 583 | BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn; | |
| 584 | switch (builtin_fn->id) { | |
| 585 | case BuiltinFnIdMaxValue: | |
| 586 | return eval_min_max(ef, node, out_val, true); | |
| 587 | case BuiltinFnIdMinValue: | |
| 588 | return eval_min_max(ef, node, out_val, false); | |
| 589 | case BuiltinFnIdMulWithOverflow: | |
| 590 | return eval_fn_with_overflow(ef, node, out_val, bignum_mul); | |
| 591 | case BuiltinFnIdAddWithOverflow: | |
| 592 | return eval_fn_with_overflow(ef, node, out_val, bignum_add); | |
| 593 | case BuiltinFnIdSubWithOverflow: | |
| 594 | return eval_fn_with_overflow(ef, node, out_val, bignum_sub); | |
| 595 | case BuiltinFnIdMemcpy: | |
| 596 | case BuiltinFnIdMemset: | |
| 597 | case BuiltinFnIdSizeof: | |
| 598 | case BuiltinFnIdAlignof: | |
| 599 | case BuiltinFnIdMemberCount: | |
| 600 | case BuiltinFnIdTypeof: | |
| 601 | case BuiltinFnIdCInclude: | |
| 602 | case BuiltinFnIdCDefine: | |
| 603 | case BuiltinFnIdCUndef: | |
| 604 | case BuiltinFnIdCompileVar: | |
| 605 | case BuiltinFnIdConstEval: | |
| 606 | case BuiltinFnIdCtz: | |
| 607 | case BuiltinFnIdClz: | |
| 608 | case BuiltinFnIdImport: | |
| 609 | case BuiltinFnIdCImport: | |
| 610 | case BuiltinFnIdErrName: | |
| 611 | zig_panic("TODO"); | |
| 612 | case BuiltinFnIdBreakpoint: | |
| 613 | case BuiltinFnIdInvalid: | |
| 614 | zig_unreachable(); | |
| 615 | } | |
| 616 | ||
| 617 | return false; | |
| 618 | } | |
| 619 | ||
| 438 | 620 | static bool eval_fn_call_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) { |
| 439 | 621 | assert(node->type == NodeTypeFnCallExpr); |
| 440 | 622 | |
| 623 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | |
| 441 | 624 | CastOp cast_op = node->data.fn_call_expr.cast_op; |
| 442 | 625 | if (node->data.fn_call_expr.is_builtin) { |
| 443 | zig_panic("TODO"); | |
| 626 | return eval_fn_call_builtin(ef, node, out_val); | |
| 444 | 627 | } else if (cast_op != CastOpNoCast) { |
| 445 | AstNode *expr_node = node->data.fn_call_expr.params.at(0); | |
| 446 | Expr *expr = get_resolved_expr(expr_node); | |
| 447 | eval_const_expr_implicit_cast(cast_op, &expr->const_val, expr->type_entry, out_val); | |
| 628 | TypeTableEntry *new_type = resolve_expr_type(fn_ref_expr); | |
| 629 | AstNode *param_node = node->data.fn_call_expr.params.at(0); | |
| 630 | TypeTableEntry *old_type = get_resolved_expr(param_node)->type_entry; | |
| 631 | ConstExprValue param_val = {0}; | |
| 632 | if (eval_expr(ef, param_node, &param_val)) return true; | |
| 633 | eval_const_expr_implicit_cast(cast_op, &param_val, old_type, out_val, new_type); | |
| 448 | 634 | return false; |
| 449 | 635 | } |
| 450 | 636 | |
| 451 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | |
| 452 | 637 | if (node->data.fn_call_expr.enum_type) { |
| 453 | 638 | zig_panic("TODO"); |
| 454 | 639 | } |
| ... | ... | @@ -503,7 +688,12 @@ static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou |
| 503 | 688 | zig_panic("TODO"); |
| 504 | 689 | } |
| 505 | 690 | } else if (struct_type->id == TypeTableEntryIdMetaType) { |
| 506 | zig_panic("TODO"); | |
| 691 | TypeTableEntry *child_type = resolve_expr_type(struct_expr); | |
| 692 | if (child_type->id == TypeTableEntryIdPureError) { | |
| 693 | *out_val = get_resolved_expr(node)->const_val; | |
| 694 | } else { | |
| 695 | zig_panic("TODO"); | |
| 696 | } | |
| 507 | 697 | } else if (struct_type->id == TypeTableEntryIdNamespace) { |
| 508 | 698 | zig_panic("TODO"); |
| 509 | 699 | } else { |
| ... | ... | @@ -630,7 +820,6 @@ static bool eval_bool_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou |
| 630 | 820 | assert(node->type == NodeTypeBoolLiteral); |
| 631 | 821 | |
| 632 | 822 | out_val->ok = true; |
| 633 | out_val->deep_const = true; | |
| 634 | 823 | out_val->data.x_bool = node->data.bool_literal.value; |
| 635 | 824 | |
| 636 | 825 | return false; |
| ... | ... | @@ -640,20 +829,38 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v |
| 640 | 829 | assert(node->type == NodeTypePrefixOpExpr); |
| 641 | 830 | |
| 642 | 831 | PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; |
| 832 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | |
| 643 | 833 | |
| 644 | 834 | ConstExprValue expr_val = {0}; |
| 645 | if (eval_expr(ef, node->data.prefix_op_expr.primary_expr, &expr_val)) return true; | |
| 835 | if (eval_expr(ef, expr_node, &expr_val)) return true; | |
| 836 | ||
| 837 | TypeTableEntry *expr_type = get_resolved_expr(expr_node)->type_entry; | |
| 646 | 838 | |
| 647 | 839 | switch (prefix_op) { |
| 648 | 840 | case PrefixOpBoolNot: |
| 649 | 841 | *out_val = expr_val; |
| 650 | 842 | out_val->data.x_bool = !out_val->data.x_bool; |
| 651 | 843 | break; |
| 652 | case PrefixOpBinNot: | |
| 653 | case PrefixOpNegation: | |
| 844 | case PrefixOpDereference: | |
| 845 | assert(expr_type->id == TypeTableEntryIdPointer); | |
| 846 | *out_val = *expr_val.data.x_ptr.ptr[0]; | |
| 847 | break; | |
| 654 | 848 | case PrefixOpAddressOf: |
| 655 | 849 | case PrefixOpConstAddressOf: |
| 656 | case PrefixOpDereference: | |
| 850 | { | |
| 851 | ConstExprValue *child_val = allocate<ConstExprValue>(1); | |
| 852 | *child_val = expr_val; | |
| 853 | ||
| 854 | ConstExprValue **ptr_val = allocate<ConstExprValue*>(1); | |
| 855 | *ptr_val = child_val; | |
| 856 | ||
| 857 | out_val->data.x_ptr.ptr = ptr_val; | |
| 858 | out_val->data.x_ptr.len = 1; | |
| 859 | out_val->ok = true; | |
| 860 | break; | |
| 861 | } | |
| 862 | case PrefixOpBinNot: | |
| 863 | case PrefixOpNegation: | |
| 657 | 864 | case PrefixOpMaybe: |
| 658 | 865 | case PrefixOpError: |
| 659 | 866 | case PrefixOpUnwrapError: |
| ... | ... | @@ -666,6 +873,48 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v |
| 666 | 873 | return false; |
| 667 | 874 | } |
| 668 | 875 | |
| 876 | static bool eval_var_decl_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) { | |
| 877 | assert(node->type == NodeTypeVariableDeclaration); | |
| 878 | ||
| 879 | assert(node->data.variable_declaration.expr); | |
| 880 | ||
| 881 | EvalScope *my_scope = ef->scope_stack.at(ef->scope_stack.length - 1); | |
| 882 | ||
| 883 | my_scope->vars.add_one(); | |
| 884 | EvalVar *var = &my_scope->vars.last(); | |
| 885 | var->name = &node->data.variable_declaration.symbol; | |
| 886 | ||
| 887 | if (eval_expr(ef, node->data.variable_declaration.expr, &var->value)) return true; | |
| 888 | ||
| 889 | out_val->ok = true; | |
| 890 | ||
| 891 | return false; | |
| 892 | } | |
| 893 | ||
| 894 | static bool eval_number_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) { | |
| 895 | assert(node->type == NodeTypeNumberLiteral); | |
| 896 | assert(!node->data.number_literal.overflow); | |
| 897 | ||
| 898 | out_val->ok = true; | |
| 899 | if (node->data.number_literal.kind == NumLitUInt) { | |
| 900 | bignum_init_unsigned(&out_val->data.x_bignum, node->data.number_literal.data.x_uint); | |
| 901 | } else if (node->data.number_literal.kind == NumLitFloat) { | |
| 902 | bignum_init_float(&out_val->data.x_bignum, node->data.number_literal.data.x_float); | |
| 903 | } else { | |
| 904 | zig_unreachable(); | |
| 905 | } | |
| 906 | ||
| 907 | return false; | |
| 908 | } | |
| 909 | ||
| 910 | static bool eval_char_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) { | |
| 911 | assert(node->type == NodeTypeCharLiteral); | |
| 912 | ||
| 913 | out_val->ok = true; | |
| 914 | bignum_init_unsigned(&out_val->data.x_bignum, node->data.char_literal.value); | |
| 915 | ||
| 916 | return false; | |
| 917 | } | |
| 669 | 918 | |
| 670 | 919 | static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) { |
| 671 | 920 | if (ef->root->branches_used > ef->root->branch_quota) { |
| ... | ... | @@ -697,6 +946,12 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) { |
| 697 | 946 | return eval_bool_literal_expr(ef, node, out); |
| 698 | 947 | case NodeTypePrefixOpExpr: |
| 699 | 948 | return eval_prefix_op_expr(ef, node, out); |
| 949 | case NodeTypeVariableDeclaration: | |
| 950 | return eval_var_decl_expr(ef, node, out); | |
| 951 | case NodeTypeNumberLiteral: | |
| 952 | return eval_number_literal_expr(ef, node, out); | |
| 953 | case NodeTypeCharLiteral: | |
| 954 | return eval_char_literal_expr(ef, node, out); | |
| 700 | 955 | case NodeTypeRoot: |
| 701 | 956 | case NodeTypeFnProto: |
| 702 | 957 | case NodeTypeFnDef: |
| ... | ... | @@ -704,13 +959,10 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) { |
| 704 | 959 | case NodeTypeParamDecl: |
| 705 | 960 | case NodeTypeDirective: |
| 706 | 961 | case NodeTypeDefer: |
| 707 | case NodeTypeVariableDeclaration: | |
| 708 | 962 | case NodeTypeTypeDecl: |
| 709 | 963 | case NodeTypeErrorValueDecl: |
| 710 | 964 | case NodeTypeUnwrapErrorExpr: |
| 711 | case NodeTypeNumberLiteral: | |
| 712 | 965 | case NodeTypeStringLiteral: |
| 713 | case NodeTypeCharLiteral: | |
| 714 | 966 | case NodeTypeSliceExpr: |
| 715 | 967 | case NodeTypeUse: |
| 716 | 968 | case NodeTypeNullLiteral: |
src/eval.hpp+3-1| ... | ... | @@ -19,6 +19,8 @@ void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, |
| 19 | 19 | |
| 20 | 20 | void eval_const_expr_implicit_cast(CastOp cast_op, |
| 21 | 21 | ConstExprValue *other_val, TypeTableEntry *other_type, |
| 22 | ConstExprValue *const_val); | |
| 22 | ConstExprValue *const_val, TypeTableEntry *new_type); | |
| 23 | ||
| 24 | void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max); | |
| 23 | 25 | |
| 24 | 26 | #endif |