| ... | ... | @@ -93,6 +93,10 @@ static Buf *exec_c_import_buf(IrExecutable *exec) { |
| 93 | 93 | return exec->c_import_buf; |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | static bool instr_is_comptime(IrInstruction *instruction) { |
| 97 | return instruction->static_value.special != ConstValSpecialRuntime; |
| 98 | } |
| 99 | |
| 96 | 100 | static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) { |
| 97 | 101 | new_instruction->other = old_instruction; |
| 98 | 102 | old_instruction->other = new_instruction; |
| ... | ... | @@ -411,6 +415,34 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) { |
| 411 | 415 | return IrInstructionIdOverflowOp; |
| 412 | 416 | } |
| 413 | 417 | |
| 418 | static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErr *) { |
| 419 | return IrInstructionIdTestErr; |
| 420 | } |
| 421 | |
| 422 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrCode *) { |
| 423 | return IrInstructionIdUnwrapErrCode; |
| 424 | } |
| 425 | |
| 426 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrPayload *) { |
| 427 | return IrInstructionIdUnwrapErrPayload; |
| 428 | } |
| 429 | |
| 430 | static constexpr IrInstructionId ir_instruction_id(IrInstructionErrUnionTypeChild *) { |
| 431 | return IrInstructionIdErrUnionTypeChild; |
| 432 | } |
| 433 | |
| 434 | static constexpr IrInstructionId ir_instruction_id(IrInstructionMaybeWrap *) { |
| 435 | return IrInstructionIdMaybeWrap; |
| 436 | } |
| 437 | |
| 438 | static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapPayload *) { |
| 439 | return IrInstructionIdErrWrapPayload; |
| 440 | } |
| 441 | |
| 442 | static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapCode *) { |
| 443 | return IrInstructionIdErrWrapCode; |
| 444 | } |
| 445 | |
| 414 | 446 | template<typename T> |
| 415 | 447 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { |
| 416 | 448 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -1037,8 +1069,11 @@ static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode |
| 1037 | 1069 | return &instruction->base; |
| 1038 | 1070 | } |
| 1039 | 1071 | |
| 1040 | | static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1041 | | IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>(irb, scope, source_node); |
| 1072 | static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1073 | IrInstruction *value) |
| 1074 | { |
| 1075 | IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>( |
| 1076 | irb, scope, source_node); |
| 1042 | 1077 | instruction->value = value; |
| 1043 | 1078 | |
| 1044 | 1079 | ir_ref_instruction(value); |
| ... | ... | @@ -1198,6 +1233,33 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction * |
| 1198 | 1233 | return new_instruction; |
| 1199 | 1234 | } |
| 1200 | 1235 | |
| 1236 | static IrInstruction *ir_build_maybe_wrap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1237 | IrInstructionMaybeWrap *instruction = ir_build_instruction<IrInstructionMaybeWrap>(irb, scope, source_node); |
| 1238 | instruction->value = value; |
| 1239 | |
| 1240 | ir_ref_instruction(value); |
| 1241 | |
| 1242 | return &instruction->base; |
| 1243 | } |
| 1244 | |
| 1245 | static IrInstruction *ir_build_err_wrap_payload(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1246 | IrInstructionErrWrapPayload *instruction = ir_build_instruction<IrInstructionErrWrapPayload>(irb, scope, source_node); |
| 1247 | instruction->value = value; |
| 1248 | |
| 1249 | ir_ref_instruction(value); |
| 1250 | |
| 1251 | return &instruction->base; |
| 1252 | } |
| 1253 | |
| 1254 | static IrInstruction *ir_build_err_wrap_code(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1255 | IrInstructionErrWrapCode *instruction = ir_build_instruction<IrInstructionErrWrapCode>(irb, scope, source_node); |
| 1256 | instruction->value = value; |
| 1257 | |
| 1258 | ir_ref_instruction(value); |
| 1259 | |
| 1260 | return &instruction->base; |
| 1261 | } |
| 1262 | |
| 1201 | 1263 | static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1202 | 1264 | IrInstructionClz *instruction = ir_build_instruction<IrInstructionClz>(irb, scope, source_node); |
| 1203 | 1265 | instruction->value = value; |
| ... | ... | @@ -1709,6 +1771,76 @@ static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *so |
| 1709 | 1771 | return &instruction->base; |
| 1710 | 1772 | } |
| 1711 | 1773 | |
| 1774 | static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1775 | IrInstruction *value) |
| 1776 | { |
| 1777 | IrInstructionTestErr *instruction = ir_build_instruction<IrInstructionTestErr>(irb, scope, source_node); |
| 1778 | instruction->value = value; |
| 1779 | |
| 1780 | ir_ref_instruction(value); |
| 1781 | |
| 1782 | return &instruction->base; |
| 1783 | } |
| 1784 | |
| 1785 | static IrInstruction *ir_build_test_err_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) { |
| 1786 | IrInstruction *new_instruction = ir_build_test_err(irb, old_instruction->scope, old_instruction->source_node, |
| 1787 | value); |
| 1788 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1789 | return new_instruction; |
| 1790 | } |
| 1791 | |
| 1792 | static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1793 | IrInstruction *value) |
| 1794 | { |
| 1795 | IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node); |
| 1796 | instruction->value = value; |
| 1797 | |
| 1798 | ir_ref_instruction(value); |
| 1799 | |
| 1800 | return &instruction->base; |
| 1801 | } |
| 1802 | |
| 1803 | static IrInstruction *ir_build_unwrap_err_code_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 1804 | IrInstruction *value) |
| 1805 | { |
| 1806 | IrInstruction *new_instruction = ir_build_unwrap_err_code(irb, old_instruction->scope, |
| 1807 | old_instruction->source_node, value); |
| 1808 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1809 | return new_instruction; |
| 1810 | } |
| 1811 | |
| 1812 | static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1813 | IrInstruction *value, bool safety_check_on) |
| 1814 | { |
| 1815 | IrInstructionUnwrapErrPayload *instruction = ir_build_instruction<IrInstructionUnwrapErrPayload>(irb, scope, source_node); |
| 1816 | instruction->value = value; |
| 1817 | instruction->safety_check_on = safety_check_on; |
| 1818 | |
| 1819 | ir_ref_instruction(value); |
| 1820 | |
| 1821 | return &instruction->base; |
| 1822 | } |
| 1823 | |
| 1824 | static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 1825 | IrInstruction *value, bool safety_check_on) |
| 1826 | { |
| 1827 | IrInstruction *new_instruction = ir_build_unwrap_err_payload(irb, old_instruction->scope, |
| 1828 | old_instruction->source_node, value, safety_check_on); |
| 1829 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1830 | return new_instruction; |
| 1831 | } |
| 1832 | |
| 1833 | static IrInstruction *ir_build_err_union_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1834 | IrInstruction *type_value) |
| 1835 | { |
| 1836 | IrInstructionErrUnionTypeChild *instruction = ir_build_instruction<IrInstructionErrUnionTypeChild>(irb, scope, source_node); |
| 1837 | instruction->type_value = type_value; |
| 1838 | |
| 1839 | ir_ref_instruction(type_value); |
| 1840 | |
| 1841 | return &instruction->base; |
| 1842 | } |
| 1843 | |
| 1712 | 1844 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 1713 | 1845 | results[ReturnKindUnconditional] = 0; |
| 1714 | 1846 | results[ReturnKindError] = 0; |
| ... | ... | @@ -1799,7 +1931,29 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 1799 | 1931 | return ir_build_return(irb, scope, node, return_value); |
| 1800 | 1932 | } |
| 1801 | 1933 | case ReturnKindError: |
| 1802 | | zig_panic("TODO gen IR for %%return"); |
| 1934 | { |
| 1935 | assert(expr_node); |
| 1936 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 1937 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 1938 | return irb->codegen->invalid_instruction; |
| 1939 | IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_ptr); |
| 1940 | |
| 1941 | IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn"); |
| 1942 | IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue"); |
| 1943 | ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_inline); |
| 1944 | |
| 1945 | ir_set_cursor_at_end(irb, return_block); |
| 1946 | ir_gen_defers_for_block(irb, scope, outer_scope, true, false); |
| 1947 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); |
| 1948 | ir_build_return(irb, scope, node, err_val); |
| 1949 | |
| 1950 | ir_set_cursor_at_end(irb, continue_block); |
| 1951 | IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false); |
| 1952 | if (lval != LValPurposeNone) |
| 1953 | return unwrapped_ptr; |
| 1954 | else |
| 1955 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| 1956 | } |
| 1803 | 1957 | case ReturnKindMaybe: |
| 1804 | 1958 | { |
| 1805 | 1959 | assert(expr_node); |
| ... | ... | @@ -2798,13 +2952,33 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode |
| 2798 | 2952 | return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone); |
| 2799 | 2953 | } |
| 2800 | 2954 | |
| 2801 | | static IrInstruction *ir_gen_prefix_op_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 2802 | | AstNode *expr = node->data.prefix_op_expr.primary_expr; |
| 2803 | | IrInstruction *value = ir_gen_node_extra(irb, expr, scope, LValPurposeAddressOf); |
| 2804 | | if (value == irb->codegen->invalid_instruction) |
| 2805 | | return value; |
| 2955 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 2956 | assert(node->type == NodeTypePrefixOpExpr); |
| 2957 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 2958 | |
| 2959 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 2960 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 2961 | return irb->codegen->invalid_instruction; |
| 2962 | |
| 2963 | IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, true); |
| 2964 | if (payload_ptr == irb->codegen->invalid_instruction) |
| 2965 | return irb->codegen->invalid_instruction; |
| 2806 | 2966 | |
| 2807 | | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, value, true); |
| 2967 | if (lval == LValPurposeNone) |
| 2968 | return ir_build_load_ptr(irb, scope, node, payload_ptr); |
| 2969 | else |
| 2970 | return payload_ptr; |
| 2971 | } |
| 2972 | |
| 2973 | static IrInstruction *ir_gen_maybe_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 2974 | assert(node->type == NodeTypePrefixOpExpr); |
| 2975 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 2976 | |
| 2977 | IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 2978 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| 2979 | return irb->codegen->invalid_instruction; |
| 2980 | |
| 2981 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true); |
| 2808 | 2982 | if (lval == LValPurposeNone) |
| 2809 | 2983 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| 2810 | 2984 | else |
| ... | ... | @@ -2860,9 +3034,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 2860 | 3034 | case PrefixOpError: |
| 2861 | 3035 | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpError); |
| 2862 | 3036 | case PrefixOpUnwrapError: |
| 2863 | | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpUnwrapError); |
| 3037 | return ir_gen_err_assert_ok(irb, scope, node, lval); |
| 2864 | 3038 | case PrefixOpUnwrapMaybe: |
| 2865 | | return ir_gen_prefix_op_unwrap_maybe(irb, scope, node, lval); |
| 3039 | return ir_gen_maybe_assert_ok(irb, scope, node, lval); |
| 2866 | 3040 | } |
| 2867 | 3041 | zig_unreachable(); |
| 2868 | 3042 | } |
| ... | ... | @@ -3626,6 +3800,66 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) |
| 3626 | 3800 | return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, slice_expr->is_const); |
| 3627 | 3801 | } |
| 3628 | 3802 | |
| 3803 | static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
| 3804 | assert(node->type == NodeTypeUnwrapErrorExpr); |
| 3805 | |
| 3806 | AstNode *op1_node = node->data.unwrap_err_expr.op1; |
| 3807 | AstNode *op2_node = node->data.unwrap_err_expr.op2; |
| 3808 | AstNode *var_node = node->data.unwrap_err_expr.symbol; |
| 3809 | |
| 3810 | bool is_inline = ir_should_inline(irb); |
| 3811 | |
| 3812 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf); |
| 3813 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 3814 | return irb->codegen->invalid_instruction; |
| 3815 | |
| 3816 | IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_ptr); |
| 3817 | |
| 3818 | IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrOk"); |
| 3819 | IrBasicBlock *err_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrError"); |
| 3820 | IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrEnd"); |
| 3821 | ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_inline); |
| 3822 | |
| 3823 | ir_set_cursor_at_end(irb, err_block); |
| 3824 | Scope *err_scope; |
| 3825 | if (var_node) { |
| 3826 | assert(var_node->type == NodeTypeSymbol); |
| 3827 | IrInstruction *err_union_ptr_type = ir_build_typeof(irb, parent_scope, var_node, err_union_ptr); |
| 3828 | IrInstruction *err_union_type = ir_build_ptr_type_child(irb, parent_scope, var_node, err_union_ptr_type); |
| 3829 | IrInstruction *var_type = ir_build_err_union_type_child(irb, parent_scope, var_node, err_union_type); |
| 3830 | Buf *var_name = var_node->data.symbol_expr.symbol; |
| 3831 | bool is_const = true; |
| 3832 | bool is_shadowable = false; |
| 3833 | VariableTableEntry *var = ir_create_var(irb, node, parent_scope, var_name, |
| 3834 | is_const, is_const, is_shadowable, is_inline); |
| 3835 | err_scope = var->child_scope; |
| 3836 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); |
| 3837 | ir_build_var_decl(irb, err_scope, var_node, var, var_type, err_val); |
| 3838 | } else { |
| 3839 | err_scope = parent_scope; |
| 3840 | } |
| 3841 | IrInstruction *err_result = ir_gen_node(irb, op2_node, err_scope); |
| 3842 | if (err_result == irb->codegen->invalid_instruction) |
| 3843 | return irb->codegen->invalid_instruction; |
| 3844 | IrBasicBlock *after_err_block = irb->current_basic_block; |
| 3845 | ir_build_br(irb, err_scope, node, end_block, is_inline); |
| 3846 | |
| 3847 | ir_set_cursor_at_end(irb, ok_block); |
| 3848 | IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false); |
| 3849 | IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); |
| 3850 | IrBasicBlock *after_ok_block = irb->current_basic_block; |
| 3851 | ir_build_br(irb, parent_scope, node, end_block, is_inline); |
| 3852 | |
| 3853 | ir_set_cursor_at_end(irb, end_block); |
| 3854 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| 3855 | incoming_values[0] = err_result; |
| 3856 | incoming_values[1] = unwrapped_payload; |
| 3857 | IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); |
| 3858 | incoming_blocks[0] = after_err_block; |
| 3859 | incoming_blocks[1] = after_ok_block; |
| 3860 | return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values); |
| 3861 | } |
| 3862 | |
| 3629 | 3863 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| 3630 | 3864 | LValPurpose lval) |
| 3631 | 3865 | { |
| ... | ... | @@ -3703,6 +3937,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 3703 | 3937 | case NodeTypeSliceExpr: |
| 3704 | 3938 | return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); |
| 3705 | 3939 | case NodeTypeUnwrapErrorExpr: |
| 3940 | return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval); |
| 3706 | 3941 | case NodeTypeZeroesLiteral: |
| 3707 | 3942 | case NodeTypeVarLiteral: |
| 3708 | 3943 | case NodeTypeFnProto: |
| ... | ... | @@ -4279,11 +4514,20 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins |
| 4279 | 4514 | } |
| 4280 | 4515 | |
| 4281 | 4516 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { |
| 4282 | | if (value->static_value.special != ConstValSpecialStatic) { |
| 4283 | | ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); |
| 4284 | | return nullptr; |
| 4517 | switch (value->static_value.special) { |
| 4518 | case ConstValSpecialStatic: |
| 4519 | return &value->static_value; |
| 4520 | case ConstValSpecialRuntime: |
| 4521 | ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); |
| 4522 | return nullptr; |
| 4523 | case ConstValSpecialUndef: |
| 4524 | ir_add_error(ira, value, buf_sprintf("use of undefined value")); |
| 4525 | return nullptr; |
| 4526 | case ConstValSpecialZeroes: |
| 4527 | ir_add_error(ira, value, buf_sprintf("zeroes is deprecated")); |
| 4528 | return nullptr; |
| 4285 | 4529 | } |
| 4286 | | return &value->static_value; |
| 4530 | zig_unreachable(); |
| 4287 | 4531 | } |
| 4288 | 4532 | |
| 4289 | 4533 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| ... | ... | @@ -4375,6 +4619,95 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 4375 | 4619 | return const_val->data.x_fn; |
| 4376 | 4620 | } |
| 4377 | 4621 | |
| 4622 | static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) { |
| 4623 | assert(wanted_type->id == TypeTableEntryIdMaybe); |
| 4624 | |
| 4625 | if (instr_is_comptime(value)) { |
| 4626 | ConstExprValue *val = ir_resolve_const(ira, value); |
| 4627 | if (!val) |
| 4628 | return ira->codegen->invalid_instruction; |
| 4629 | |
| 4630 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec, |
| 4631 | source_instr->scope, source_instr->source_node); |
| 4632 | const_instruction->base.type_entry = wanted_type; |
| 4633 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 4634 | const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var; |
| 4635 | const_instruction->base.static_value.data.x_maybe = &value->static_value; |
| 4636 | return &const_instruction->base; |
| 4637 | } |
| 4638 | |
| 4639 | IrInstruction *result = ir_build_maybe_wrap(&ira->new_irb, source_instr->scope, source_instr->source_node, value); |
| 4640 | result->type_entry = wanted_type; |
| 4641 | result->static_value.data.rh_maybe = RuntimeHintMaybeNonNull; |
| 4642 | ir_add_alloca(ira, result, wanted_type); |
| 4643 | return result; |
| 4644 | } |
| 4645 | |
| 4646 | static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) { |
| 4647 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 4648 | |
| 4649 | if (instr_is_comptime(value)) { |
| 4650 | ConstExprValue *val = ir_resolve_const(ira, value); |
| 4651 | if (!val) |
| 4652 | return ira->codegen->invalid_instruction; |
| 4653 | |
| 4654 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec, |
| 4655 | source_instr->scope, source_instr->source_node); |
| 4656 | const_instruction->base.type_entry = wanted_type; |
| 4657 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 4658 | const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var; |
| 4659 | const_instruction->base.static_value.data.x_err_union.err = nullptr; |
| 4660 | const_instruction->base.static_value.data.x_err_union.payload = val; |
| 4661 | return &const_instruction->base; |
| 4662 | } |
| 4663 | |
| 4664 | IrInstruction *result = ir_build_err_wrap_payload(&ira->new_irb, source_instr->scope, source_instr->source_node, value); |
| 4665 | result->type_entry = wanted_type; |
| 4666 | result->static_value.data.rh_error_union = RuntimeHintErrorUnionNonError; |
| 4667 | ir_add_alloca(ira, result, wanted_type); |
| 4668 | return result; |
| 4669 | } |
| 4670 | |
| 4671 | static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) { |
| 4672 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 4673 | |
| 4674 | if (instr_is_comptime(value)) { |
| 4675 | ConstExprValue *val = ir_resolve_const(ira, value); |
| 4676 | if (!val) |
| 4677 | return ira->codegen->invalid_instruction; |
| 4678 | |
| 4679 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec, |
| 4680 | source_instr->scope, source_instr->source_node); |
| 4681 | const_instruction->base.type_entry = wanted_type; |
| 4682 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 4683 | const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var; |
| 4684 | const_instruction->base.static_value.data.x_err_union.err = val->data.x_pure_err; |
| 4685 | const_instruction->base.static_value.data.x_err_union.payload = nullptr; |
| 4686 | return &const_instruction->base; |
| 4687 | } |
| 4688 | |
| 4689 | IrInstruction *result = ir_build_err_wrap_code(&ira->new_irb, source_instr->scope, source_instr->source_node, value); |
| 4690 | result->type_entry = wanted_type; |
| 4691 | result->static_value.data.rh_error_union = RuntimeHintErrorUnionError; |
| 4692 | ir_add_alloca(ira, result, wanted_type); |
| 4693 | return result; |
| 4694 | } |
| 4695 | |
| 4696 | static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) { |
| 4697 | assert(wanted_type->id == TypeTableEntryIdMaybe); |
| 4698 | assert(instr_is_comptime(value)); |
| 4699 | |
| 4700 | ConstExprValue *val = ir_resolve_const(ira, value); |
| 4701 | assert(val); |
| 4702 | |
| 4703 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec, source_instr->scope, source_instr->source_node); |
| 4704 | const_instruction->base.type_entry = wanted_type; |
| 4705 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 4706 | const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var; |
| 4707 | const_instruction->base.static_value.data.x_maybe = nullptr; |
| 4708 | return &const_instruction->base; |
| 4709 | } |
| 4710 | |
| 4378 | 4711 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 4379 | 4712 | TypeTableEntry *wanted_type, IrInstruction *value) |
| 4380 | 4713 | { |
| ... | ... | @@ -4503,18 +4836,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 4503 | 4836 | // explicit cast from child type of maybe type to maybe type |
| 4504 | 4837 | if (wanted_type->id == TypeTableEntryIdMaybe) { |
| 4505 | 4838 | if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) { |
| 4506 | | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 4507 | | CastOpMaybeWrap, true); |
| 4508 | | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; |
| 4509 | | return cast_instruction; |
| 4839 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); |
| 4510 | 4840 | } else if (actual_type->id == TypeTableEntryIdNumLitInt || |
| 4511 | 4841 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 4512 | 4842 | { |
| 4513 | 4843 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) { |
| 4514 | | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 4515 | | CastOpMaybeWrap, true); |
| 4516 | | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; |
| 4517 | | return cast_instruction; |
| 4844 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); |
| 4518 | 4845 | } else { |
| 4519 | 4846 | return ira->codegen->invalid_instruction; |
| 4520 | 4847 | } |
| ... | ... | @@ -4525,27 +4852,18 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 4525 | 4852 | if (wanted_type->id == TypeTableEntryIdMaybe && |
| 4526 | 4853 | actual_type->id == TypeTableEntryIdNullLit) |
| 4527 | 4854 | { |
| 4528 | | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 4529 | | CastOpNullToMaybe, true); |
| 4530 | | cast_instruction->return_knowledge = ReturnKnowledgeKnownNull; |
| 4531 | | return cast_instruction; |
| 4855 | return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type); |
| 4532 | 4856 | } |
| 4533 | 4857 | |
| 4534 | 4858 | // explicit cast from child type of error type to error type |
| 4535 | 4859 | if (wanted_type->id == TypeTableEntryIdErrorUnion) { |
| 4536 | 4860 | if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) { |
| 4537 | | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 4538 | | CastOpErrorWrap, true); |
| 4539 | | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; |
| 4540 | | return cast_instruction; |
| 4861 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); |
| 4541 | 4862 | } else if (actual_type->id == TypeTableEntryIdNumLitInt || |
| 4542 | 4863 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 4543 | 4864 | { |
| 4544 | 4865 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) { |
| 4545 | | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 4546 | | CastOpErrorWrap, true); |
| 4547 | | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; |
| 4548 | | return cast_instruction; |
| 4866 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); |
| 4549 | 4867 | } else { |
| 4550 | 4868 | return ira->codegen->invalid_instruction; |
| 4551 | 4869 | } |
| ... | ... | @@ -4556,10 +4874,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 4556 | 4874 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 4557 | 4875 | actual_type->id == TypeTableEntryIdPureError) |
| 4558 | 4876 | { |
| 4559 | | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 4560 | | CastOpPureErrorWrap, false); |
| 4561 | | cast_instruction->return_knowledge = ReturnKnowledgeKnownError; |
| 4562 | | return cast_instruction; |
| 4877 | return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); |
| 4563 | 4878 | } |
| 4564 | 4879 | |
| 4565 | 4880 | // explicit cast from number literal to another type |
| ... | ... | @@ -5997,33 +6312,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op |
| 5997 | 6312 | zig_unreachable(); |
| 5998 | 6313 | } |
| 5999 | 6314 | |
| 6000 | | static TypeTableEntry *ir_analyze_unwrap_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 6001 | | IrInstruction *value = un_op_instruction->value->other; |
| 6002 | | TypeTableEntry *type_entry = value->type_entry; |
| 6003 | | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 6004 | | return type_entry; |
| 6005 | | } else if (type_entry->id == TypeTableEntryIdMaybe) { |
| 6006 | | if (value->static_value.special != ConstValSpecialRuntime) { |
| 6007 | | bool depends_on_compile_var = value->static_value.depends_on_compile_var; |
| 6008 | | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, depends_on_compile_var); |
| 6009 | | ConstExprValue *child_val = value->static_value.data.x_maybe; |
| 6010 | | if (!child_val) { |
| 6011 | | ir_add_error(ira, &un_op_instruction->base, |
| 6012 | | buf_sprintf("unable to unwrap null")); |
| 6013 | | return ira->codegen->builtin_types.entry_invalid; |
| 6014 | | } |
| 6015 | | *out_val = *child_val; |
| 6016 | | return type_entry->data.maybe.child_type; |
| 6017 | | } |
| 6018 | | ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, IrUnOpUnwrapMaybe, value); |
| 6019 | | return type_entry->data.maybe.child_type; |
| 6020 | | } else { |
| 6021 | | add_node_error(ira->codegen, un_op_instruction->base.source_node, |
| 6022 | | buf_sprintf("expected maybe type, found '%s'", buf_ptr(&type_entry->name))); |
| 6023 | | return ira->codegen->builtin_types.entry_invalid; |
| 6024 | | } |
| 6025 | | } |
| 6026 | | |
| 6027 | 6315 | static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 6028 | 6316 | IrInstruction *value = un_op_instruction->value->other; |
| 6029 | 6317 | TypeTableEntry *expr_type = value->type_entry; |
| ... | ... | @@ -6099,27 +6387,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 6099 | 6387 | return ir_analyze_maybe(ira, un_op_instruction); |
| 6100 | 6388 | case IrUnOpError: |
| 6101 | 6389 | return ir_analyze_unary_prefix_op_err(ira, un_op_instruction); |
| 6102 | | case IrUnOpUnwrapError: |
| 6103 | | zig_panic("TODO analyze PrefixOpUnwrapError"); |
| 6104 | | //{ |
| 6105 | | // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node); |
| 6106 | | |
| 6107 | | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| 6108 | | // return type_entry; |
| 6109 | | // } else if (type_entry->id == TypeTableEntryIdErrorUnion) { |
| 6110 | | // return type_entry->data.error.child_type; |
| 6111 | | // } else { |
| 6112 | | // add_node_error(g, *expr_node, |
| 6113 | | // buf_sprintf("expected error type, found '%s'", buf_ptr(&type_entry->name))); |
| 6114 | | // return g->builtin_types.entry_invalid; |
| 6115 | | // } |
| 6116 | | //} |
| 6117 | | case IrUnOpUnwrapMaybe: |
| 6118 | | return ir_analyze_unwrap_maybe(ira, un_op_instruction); |
| 6119 | | case IrUnOpErrorReturn: |
| 6120 | | zig_panic("TODO analyze IrUnOpErrorReturn"); |
| 6121 | | case IrUnOpMaybeReturn: |
| 6122 | | zig_panic("TODO analyze IrUnOpMaybeReturn"); |
| 6123 | 6390 | } |
| 6124 | 6391 | zig_unreachable(); |
| 6125 | 6392 | } |
| ... | ... | @@ -6835,6 +7102,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 6835 | 7102 | if (type_entry->id == TypeTableEntryIdInvalid) |
| 6836 | 7103 | return type_entry; |
| 6837 | 7104 | |
| 7105 | // TODO handle typedefs |
| 6838 | 7106 | if (type_entry->id != TypeTableEntryIdPointer) { |
| 6839 | 7107 | add_node_error(ira->codegen, ptr_type_child_instruction->base.source_node, |
| 6840 | 7108 | buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name))); |
| ... | ... | @@ -7243,6 +7511,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 7243 | 7511 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 7244 | 7512 | |
| 7245 | 7513 | TypeTableEntry *type_entry = ptr_type->data.pointer.child_type; |
| 7514 | // TODO handle typedef |
| 7246 | 7515 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 7247 | 7516 | return ira->codegen->builtin_types.entry_invalid; |
| 7248 | 7517 | } else if (type_entry->id != TypeTableEntryIdMaybe) { |
| ... | ... | @@ -7253,9 +7522,12 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 7253 | 7522 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 7254 | 7523 | TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false); |
| 7255 | 7524 | |
| 7256 | | if (value->static_value.special != ConstValSpecialRuntime) { |
| 7257 | | ConstExprValue *maybe_val = value->static_value.data.x_ptr.base_ptr; |
| 7258 | | assert(value->static_value.data.x_ptr.index == SIZE_MAX); |
| 7525 | if (instr_is_comptime(value)) { |
| 7526 | ConstExprValue *val = ir_resolve_const(ira, value); |
| 7527 | if (!val) |
| 7528 | return ira->codegen->builtin_types.entry_invalid; |
| 7529 | ConstExprValue *maybe_val = val->data.x_ptr.base_ptr; |
| 7530 | assert(val->data.x_ptr.index == SIZE_MAX); |
| 7259 | 7531 | |
| 7260 | 7532 | if (maybe_val->special != ConstValSpecialRuntime) { |
| 7261 | 7533 | if (!maybe_val->data.x_maybe) { |
| ... | ... | @@ -8837,6 +9109,161 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst |
| 8837 | 9109 | return ira->codegen->builtin_types.entry_bool; |
| 8838 | 9110 | } |
| 8839 | 9111 | |
| 9112 | static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) { |
| 9113 | IrInstruction *value = instruction->value->other; |
| 9114 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 9115 | return ira->codegen->builtin_types.entry_invalid; |
| 9116 | |
| 9117 | TypeTableEntry *ptr_type = value->type_entry; |
| 9118 | |
| 9119 | // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing. |
| 9120 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 9121 | |
| 9122 | TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type; |
| 9123 | TypeTableEntry *canon_type = get_underlying_type(non_canon_type); |
| 9124 | if (canon_type->id == TypeTableEntryIdInvalid) { |
| 9125 | return ira->codegen->builtin_types.entry_invalid; |
| 9126 | } else if (canon_type->id == TypeTableEntryIdErrorUnion) { |
| 9127 | if (instr_is_comptime(value)) { |
| 9128 | ConstExprValue *ptr_val = ir_resolve_const(ira, value); |
| 9129 | if (!ptr_val) |
| 9130 | return ira->codegen->builtin_types.entry_invalid; |
| 9131 | ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr; |
| 9132 | assert(ptr_val->data.x_ptr.index == SIZE_MAX); |
| 9133 | |
| 9134 | if (err_union_val->special != ConstValSpecialRuntime) { |
| 9135 | bool depends_on_compile_var = ptr_val->depends_on_compile_var || err_union_val->depends_on_compile_var; |
| 9136 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); |
| 9137 | out_val->data.x_bool = (err_union_val->data.x_err_union.err != nullptr); |
| 9138 | return ira->codegen->builtin_types.entry_bool; |
| 9139 | } |
| 9140 | } |
| 9141 | |
| 9142 | ir_build_test_err_from(&ira->new_irb, &instruction->base, value); |
| 9143 | return ira->codegen->builtin_types.entry_bool; |
| 9144 | } else { |
| 9145 | ir_add_error(ira, value, |
| 9146 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name))); |
| 9147 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| 9148 | return ira->codegen->builtin_types.entry_invalid; |
| 9149 | } |
| 9150 | } |
| 9151 | |
| 9152 | static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, |
| 9153 | IrInstructionUnwrapErrCode *instruction) |
| 9154 | { |
| 9155 | IrInstruction *value = instruction->value->other; |
| 9156 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 9157 | return ira->codegen->builtin_types.entry_invalid; |
| 9158 | TypeTableEntry *ptr_type = value->type_entry; |
| 9159 | |
| 9160 | // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing. |
| 9161 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 9162 | |
| 9163 | TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type; |
| 9164 | TypeTableEntry *canon_type = get_underlying_type(non_canon_type); |
| 9165 | if (canon_type->id == TypeTableEntryIdInvalid) { |
| 9166 | return ira->codegen->builtin_types.entry_invalid; |
| 9167 | } else if (canon_type->id == TypeTableEntryIdErrorUnion) { |
| 9168 | if (instr_is_comptime(value)) { |
| 9169 | ConstExprValue *ptr_val = ir_resolve_const(ira, value); |
| 9170 | if (!ptr_val) |
| 9171 | return ira->codegen->builtin_types.entry_invalid; |
| 9172 | ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr; |
| 9173 | assert(ptr_val->data.x_ptr.index == SIZE_MAX); |
| 9174 | if (err_union_val->special != ConstValSpecialRuntime) { |
| 9175 | ErrorTableEntry *err = err_union_val->data.x_err_union.err; |
| 9176 | assert(err); |
| 9177 | |
| 9178 | bool depends_on_compile_var = ptr_val->depends_on_compile_var || err_union_val->depends_on_compile_var; |
| 9179 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); |
| 9180 | out_val->data.x_pure_err = err; |
| 9181 | return ira->codegen->builtin_types.entry_pure_error; |
| 9182 | } |
| 9183 | } |
| 9184 | |
| 9185 | ir_build_unwrap_err_code_from(&ira->new_irb, &instruction->base, value); |
| 9186 | return ira->codegen->builtin_types.entry_pure_error; |
| 9187 | } else { |
| 9188 | ir_add_error(ira, value, |
| 9189 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name))); |
| 9190 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| 9191 | return ira->codegen->builtin_types.entry_invalid; |
| 9192 | } |
| 9193 | } |
| 9194 | |
| 9195 | static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 9196 | IrInstructionUnwrapErrPayload *instruction) |
| 9197 | { |
| 9198 | IrInstruction *value = instruction->value->other; |
| 9199 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 9200 | return ira->codegen->builtin_types.entry_invalid; |
| 9201 | TypeTableEntry *ptr_type = value->type_entry; |
| 9202 | |
| 9203 | // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing. |
| 9204 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 9205 | |
| 9206 | TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type; |
| 9207 | TypeTableEntry *canon_type = get_underlying_type(non_canon_type); |
| 9208 | if (canon_type->id == TypeTableEntryIdInvalid) { |
| 9209 | return ira->codegen->builtin_types.entry_invalid; |
| 9210 | } else if (canon_type->id == TypeTableEntryIdErrorUnion) { |
| 9211 | TypeTableEntry *child_type = canon_type->data.error.child_type; |
| 9212 | TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false); |
| 9213 | if (instr_is_comptime(value)) { |
| 9214 | ConstExprValue *ptr_val = ir_resolve_const(ira, value); |
| 9215 | if (!ptr_val) |
| 9216 | return ira->codegen->builtin_types.entry_invalid; |
| 9217 | ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr; |
| 9218 | assert(ptr_val->data.x_ptr.index == SIZE_MAX); |
| 9219 | if (err_union_val->special != ConstValSpecialRuntime) { |
| 9220 | ErrorTableEntry *err = err_union_val->data.x_err_union.err; |
| 9221 | if (err != nullptr) { |
| 9222 | ir_add_error(ira, &instruction->base, |
| 9223 | buf_sprintf("unable to unwrap error '%s'", buf_ptr(&err->name))); |
| 9224 | return ira->codegen->builtin_types.entry_invalid; |
| 9225 | } |
| 9226 | |
| 9227 | bool depends_on_compile_var = ptr_val->depends_on_compile_var || err_union_val->depends_on_compile_var; |
| 9228 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); |
| 9229 | out_val->data.x_ptr.base_ptr = err_union_val->data.x_err_union.payload; |
| 9230 | out_val->data.x_ptr.index = SIZE_MAX; |
| 9231 | return result_type; |
| 9232 | } |
| 9233 | } |
| 9234 | |
| 9235 | ir_build_unwrap_err_payload_from(&ira->new_irb, &instruction->base, value, instruction->safety_check_on); |
| 9236 | return result_type; |
| 9237 | } else { |
| 9238 | ir_add_error(ira, value, |
| 9239 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name))); |
| 9240 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| 9241 | return ira->codegen->builtin_types.entry_invalid; |
| 9242 | } |
| 9243 | |
| 9244 | } |
| 9245 | |
| 9246 | static TypeTableEntry *ir_analyze_instruction_err_union_type_child(IrAnalyze *ira, |
| 9247 | IrInstructionErrUnionTypeChild *instruction) |
| 9248 | { |
| 9249 | IrInstruction *type_value = instruction->type_value->other; |
| 9250 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| 9251 | if (type_entry->id == TypeTableEntryIdInvalid) |
| 9252 | return type_entry; |
| 9253 | |
| 9254 | // TODO handle typedefs |
| 9255 | if (type_entry->id != TypeTableEntryIdErrorUnion) { |
| 9256 | add_node_error(ira->codegen, instruction->base.source_node, |
| 9257 | buf_sprintf("expected error type, found '%s'", buf_ptr(&type_entry->name))); |
| 9258 | return ira->codegen->builtin_types.entry_invalid; |
| 9259 | } |
| 9260 | |
| 9261 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, |
| 9262 | type_value->static_value.depends_on_compile_var); |
| 9263 | out_val->data.x_type = type_entry->data.error.child_type; |
| 9264 | return ira->codegen->builtin_types.entry_type; |
| 9265 | } |
| 9266 | |
| 8840 | 9267 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 8841 | 9268 | switch (instruction->id) { |
| 8842 | 9269 | case IrInstructionIdInvalid: |
| ... | ... | @@ -8971,6 +9398,17 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 8971 | 9398 | return ir_analyze_instruction_alignof(ira, (IrInstructionAlignOf *)instruction); |
| 8972 | 9399 | case IrInstructionIdOverflowOp: |
| 8973 | 9400 | return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction); |
| 9401 | case IrInstructionIdTestErr: |
| 9402 | return ir_analyze_instruction_test_err(ira, (IrInstructionTestErr *)instruction); |
| 9403 | case IrInstructionIdUnwrapErrCode: |
| 9404 | return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction); |
| 9405 | case IrInstructionIdUnwrapErrPayload: |
| 9406 | return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction); |
| 9407 | case IrInstructionIdErrUnionTypeChild: |
| 9408 | return ir_analyze_instruction_err_union_type_child(ira, (IrInstructionErrUnionTypeChild *)instruction); |
| 9409 | case IrInstructionIdMaybeWrap: |
| 9410 | case IrInstructionIdErrWrapCode: |
| 9411 | case IrInstructionIdErrWrapPayload: |
| 8974 | 9412 | case IrInstructionIdCast: |
| 8975 | 9413 | case IrInstructionIdStructFieldPtr: |
| 8976 | 9414 | case IrInstructionIdEnumFieldPtr: |
| ... | ... | @@ -9122,6 +9560,13 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 9122 | 9560 | case IrInstructionIdAlignOf: |
| 9123 | 9561 | case IrInstructionIdReturnAddress: |
| 9124 | 9562 | case IrInstructionIdFrameAddress: |
| 9563 | case IrInstructionIdTestErr: |
| 9564 | case IrInstructionIdUnwrapErrCode: |
| 9565 | case IrInstructionIdUnwrapErrPayload: |
| 9566 | case IrInstructionIdErrUnionTypeChild: |
| 9567 | case IrInstructionIdMaybeWrap: |
| 9568 | case IrInstructionIdErrWrapCode: |
| 9569 | case IrInstructionIdErrWrapPayload: |
| 9125 | 9570 | return false; |
| 9126 | 9571 | case IrInstructionIdAsm: |
| 9127 | 9572 | { |
| ... | ... | @@ -9131,268 +9576,3 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 9131 | 9576 | } |
| 9132 | 9577 | zig_unreachable(); |
| 9133 | 9578 | } |
| 9134 | | |
| 9135 | | // TODO port over all this commented out code into new IR way of doing things |
| 9136 | | |
| 9137 | | //static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 9138 | | // TypeTableEntry *expected_type, AstNode *node) |
| 9139 | | //{ |
| 9140 | | // TypeTableEntry *expected_return_type = get_return_type(context); |
| 9141 | | // |
| 9142 | | // switch (node->data.return_expr.kind) { |
| 9143 | | // case ReturnKindError: |
| 9144 | | // { |
| 9145 | | // TypeTableEntry *expected_err_type; |
| 9146 | | // if (expected_type) { |
| 9147 | | // expected_err_type = get_error_type(g, expected_type); |
| 9148 | | // } else { |
| 9149 | | // expected_err_type = nullptr; |
| 9150 | | // } |
| 9151 | | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_err_type, |
| 9152 | | // node->data.return_expr.expr); |
| 9153 | | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| 9154 | | // return resolved_type; |
| 9155 | | // } else if (resolved_type->id == TypeTableEntryIdErrorUnion) { |
| 9156 | | // if (expected_return_type->id != TypeTableEntryIdErrorUnion && |
| 9157 | | // expected_return_type->id != TypeTableEntryIdPureError) |
| 9158 | | // { |
| 9159 | | // ErrorMsg *msg = add_node_error(g, node, |
| 9160 | | // buf_sprintf("%%return statement in function with return type '%s'", |
| 9161 | | // buf_ptr(&expected_return_type->name))); |
| 9162 | | // AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type; |
| 9163 | | // add_error_note(g, msg, return_type_node, buf_sprintf("function return type here")); |
| 9164 | | // } |
| 9165 | | // |
| 9166 | | // return resolved_type->data.error.child_type; |
| 9167 | | // } else { |
| 9168 | | // add_node_error(g, node->data.return_expr.expr, |
| 9169 | | // buf_sprintf("expected error type, found '%s'", buf_ptr(&resolved_type->name))); |
| 9170 | | // return g->builtin_types.entry_invalid; |
| 9171 | | // } |
| 9172 | | // } |
| 9173 | | // } |
| 9174 | | // zig_unreachable(); |
| 9175 | | //} |
| 9176 | | //static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *import, |
| 9177 | | // BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *node) |
| 9178 | | //{ |
| 9179 | | // AstNode *op1 = node->data.unwrap_err_expr.op1; |
| 9180 | | // AstNode *op2 = node->data.unwrap_err_expr.op2; |
| 9181 | | // AstNode *var_node = node->data.unwrap_err_expr.symbol; |
| 9182 | | // |
| 9183 | | // TypeTableEntry *lhs_type = analyze_expression(g, import, parent_context, nullptr, op1); |
| 9184 | | // if (lhs_type->id == TypeTableEntryIdInvalid) { |
| 9185 | | // return lhs_type; |
| 9186 | | // } else if (lhs_type->id == TypeTableEntryIdErrorUnion) { |
| 9187 | | // TypeTableEntry *child_type = lhs_type->data.error.child_type; |
| 9188 | | // BlockContext *child_context; |
| 9189 | | // if (var_node) { |
| 9190 | | // child_context = new_block_context(node, parent_context); |
| 9191 | | // var_node->block_context = child_context; |
| 9192 | | // Buf *var_name = var_node->data.symbol_expr.symbol; |
| 9193 | | // node->data.unwrap_err_expr.var = add_local_var(g, var_node, import, child_context, var_name, |
| 9194 | | // g->builtin_types.entry_pure_error, true, nullptr); |
| 9195 | | // } else { |
| 9196 | | // child_context = parent_context; |
| 9197 | | // } |
| 9198 | | // |
| 9199 | | // analyze_expression(g, import, child_context, child_type, op2); |
| 9200 | | // return child_type; |
| 9201 | | // } else { |
| 9202 | | // add_node_error(g, op1, |
| 9203 | | // buf_sprintf("expected error type, found '%s'", buf_ptr(&lhs_type->name))); |
| 9204 | | // return g->builtin_types.entry_invalid; |
| 9205 | | // } |
| 9206 | | //} |
| 9207 | | // |
| 9208 | | //static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) { |
| 9209 | | // if (type_entry->id == TypeTableEntryIdMetaType) { |
| 9210 | | // add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type")); |
| 9211 | | // } else if (type_entry->id == TypeTableEntryIdErrorUnion) { |
| 9212 | | // add_node_error(g, first_executing_node(source_node), buf_sprintf("statement ignores error value")); |
| 9213 | | // } |
| 9214 | | //} |
| 9215 | | // |
| 9216 | | //static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type, |
| 9217 | | // AstNode *arg_node) |
| 9218 | | //{ |
| 9219 | | // assert(node->type == NodeTypeFieldAccessExpr); |
| 9220 | | // |
| 9221 | | // uint64_t value = node->data.field_access_expr.type_enum_field->value; |
| 9222 | | // LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref; |
| 9223 | | // LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false); |
| 9224 | | // |
| 9225 | | // if (enum_type->data.enumeration.gen_field_count == 0) { |
| 9226 | | // return tag_value; |
| 9227 | | // } else { |
| 9228 | | // TypeTableEntry *arg_node_type = nullptr; |
| 9229 | | // LLVMValueRef new_union_val = gen_expr(g, arg_node); |
| 9230 | | // if (arg_node) { |
| 9231 | | // arg_node_type = get_expr_type(arg_node); |
| 9232 | | // } else { |
| 9233 | | // arg_node_type = g->builtin_types.entry_void; |
| 9234 | | // } |
| 9235 | | // |
| 9236 | | // LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr; |
| 9237 | | // |
| 9238 | | // // populate the new tag value |
| 9239 | | // LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, ""); |
| 9240 | | // LLVMBuildStore(g->builder, tag_value, tag_field_ptr); |
| 9241 | | // |
| 9242 | | // if (arg_node_type->id != TypeTableEntryIdVoid) { |
| 9243 | | // // populate the union value |
| 9244 | | // TypeTableEntry *union_val_type = get_expr_type(arg_node); |
| 9245 | | // LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, ""); |
| 9246 | | // LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, |
| 9247 | | // LLVMPointerType(union_val_type->type_ref, 0), ""); |
| 9248 | | // |
| 9249 | | // gen_assign_raw(g, arg_node, BinOpTypeAssign, bitcasted_union_field_ptr, new_union_val, |
| 9250 | | // union_val_type, union_val_type); |
| 9251 | | // |
| 9252 | | // } |
| 9253 | | // |
| 9254 | | // return tmp_struct_ptr; |
| 9255 | | // } |
| 9256 | | //} |
| 9257 | | // |
| 9258 | | //static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) { |
| 9259 | | // assert(node->type == NodeTypeUnwrapErrorExpr); |
| 9260 | | // |
| 9261 | | // AstNode *op1 = node->data.unwrap_err_expr.op1; |
| 9262 | | // AstNode *op2 = node->data.unwrap_err_expr.op2; |
| 9263 | | // VariableTableEntry *var = node->data.unwrap_err_expr.var; |
| 9264 | | // |
| 9265 | | // LLVMValueRef expr_val = gen_expr(g, op1); |
| 9266 | | // TypeTableEntry *expr_type = get_expr_type(op1); |
| 9267 | | // TypeTableEntry *op2_type = get_expr_type(op2); |
| 9268 | | // assert(expr_type->id == TypeTableEntryIdErrorUnion); |
| 9269 | | // TypeTableEntry *child_type = expr_type->data.error.child_type; |
| 9270 | | // LLVMValueRef err_val; |
| 9271 | | // if (handle_is_ptr(expr_type)) { |
| 9272 | | // LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, ""); |
| 9273 | | // err_val = LLVMBuildLoad(g->builder, err_val_ptr, ""); |
| 9274 | | // } else { |
| 9275 | | // err_val = expr_val; |
| 9276 | | // } |
| 9277 | | // LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref); |
| 9278 | | // LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, ""); |
| 9279 | | // |
| 9280 | | // LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk"); |
| 9281 | | // LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError"); |
| 9282 | | // LLVMBasicBlockRef end_block; |
| 9283 | | // bool err_reachable = op2_type->id != TypeTableEntryIdUnreachable; |
| 9284 | | // bool have_end_block = err_reachable && type_has_bits(child_type); |
| 9285 | | // if (have_end_block) { |
| 9286 | | // end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrEnd"); |
| 9287 | | // } |
| 9288 | | // |
| 9289 | | // LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block); |
| 9290 | | // |
| 9291 | | // LLVMPositionBuilderAtEnd(g->builder, err_block); |
| 9292 | | // if (var) { |
| 9293 | | // LLVMBuildStore(g->builder, err_val, var->value_ref); |
| 9294 | | // } |
| 9295 | | // LLVMValueRef err_result = gen_expr(g, op2); |
| 9296 | | // if (have_end_block) { |
| 9297 | | // LLVMBuildBr(g->builder, end_block); |
| 9298 | | // } else if (err_reachable) { |
| 9299 | | // LLVMBuildBr(g->builder, ok_block); |
| 9300 | | // } |
| 9301 | | // |
| 9302 | | // LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 9303 | | // if (!type_has_bits(child_type)) { |
| 9304 | | // return nullptr; |
| 9305 | | // } |
| 9306 | | // LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, ""); |
| 9307 | | // LLVMValueRef child_val = get_handle_value(g, child_val_ptr, child_type); |
| 9308 | | // |
| 9309 | | // if (!have_end_block) { |
| 9310 | | // return child_val; |
| 9311 | | // } |
| 9312 | | // |
| 9313 | | // LLVMBuildBr(g->builder, end_block); |
| 9314 | | // |
| 9315 | | // LLVMPositionBuilderAtEnd(g->builder, end_block); |
| 9316 | | // LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(err_result), ""); |
| 9317 | | // LLVMValueRef incoming_values[2] = {child_val, err_result}; |
| 9318 | | // LLVMBasicBlockRef incoming_blocks[2] = {ok_block, err_block}; |
| 9319 | | // LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); |
| 9320 | | // return phi; |
| 9321 | | //} |
| 9322 | | // |
| 9323 | | //static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 9324 | | // assert(node->type == NodeTypeReturnExpr); |
| 9325 | | // AstNode *param_node = node->data.return_expr.expr; |
| 9326 | | // assert(param_node); |
| 9327 | | // LLVMValueRef value = gen_expr(g, param_node); |
| 9328 | | // TypeTableEntry *value_type = get_expr_type(param_node); |
| 9329 | | // |
| 9330 | | // switch (node->data.return_expr.kind) { |
| 9331 | | // case ReturnKindUnconditional: |
| 9332 | | // { |
| 9333 | | // Expr *expr = get_resolved_expr(param_node); |
| 9334 | | // if (expr->const_val.ok) { |
| 9335 | | // if (value_type->id == TypeTableEntryIdErrorUnion) { |
| 9336 | | // if (expr->const_val.data.x_err.err) { |
| 9337 | | // expr->return_knowledge = ReturnKnowledgeKnownError; |
| 9338 | | // } else { |
| 9339 | | // expr->return_knowledge = ReturnKnowledgeKnownNonError; |
| 9340 | | // } |
| 9341 | | // } else if (value_type->id == TypeTableEntryIdMaybe) { |
| 9342 | | // if (expr->const_val.data.x_maybe) { |
| 9343 | | // expr->return_knowledge = ReturnKnowledgeKnownNonNull; |
| 9344 | | // } else { |
| 9345 | | // expr->return_knowledge = ReturnKnowledgeKnownNull; |
| 9346 | | // } |
| 9347 | | // } |
| 9348 | | // } |
| 9349 | | // return gen_return(g, node, value, expr->return_knowledge); |
| 9350 | | // } |
| 9351 | | // case ReturnKindError: |
| 9352 | | // { |
| 9353 | | // assert(value_type->id == TypeTableEntryIdErrorUnion); |
| 9354 | | // TypeTableEntry *child_type = value_type->data.error.child_type; |
| 9355 | | // |
| 9356 | | // LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn"); |
| 9357 | | // LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue"); |
| 9358 | | // |
| 9359 | | // LLVMValueRef err_val; |
| 9360 | | // if (type_has_bits(child_type)) { |
| 9361 | | // LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, ""); |
| 9362 | | // err_val = LLVMBuildLoad(g->builder, err_val_ptr, ""); |
| 9363 | | // } else { |
| 9364 | | // err_val = value; |
| 9365 | | // } |
| 9366 | | // LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref); |
| 9367 | | // LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, ""); |
| 9368 | | // LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block); |
| 9369 | | // |
| 9370 | | // LLVMPositionBuilderAtEnd(g->builder, return_block); |
| 9371 | | // TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; |
| 9372 | | // if (return_type->id == TypeTableEntryIdPureError) { |
| 9373 | | // gen_return(g, node, err_val, ReturnKnowledgeKnownError); |
| 9374 | | // } else if (return_type->id == TypeTableEntryIdErrorUnion) { |
| 9375 | | // if (type_has_bits(return_type->data.error.child_type)) { |
| 9376 | | // assert(g->cur_ret_ptr); |
| 9377 | | // |
| 9378 | | // LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, ""); |
| 9379 | | // LLVMBuildStore(g->builder, err_val, tag_ptr); |
| 9380 | | // LLVMBuildRetVoid(g->builder); |
| 9381 | | // } else { |
| 9382 | | // gen_return(g, node, err_val, ReturnKnowledgeKnownError); |
| 9383 | | // } |
| 9384 | | // } else { |
| 9385 | | // zig_unreachable(); |
| 9386 | | // } |
| 9387 | | // |
| 9388 | | // LLVMPositionBuilderAtEnd(g->builder, continue_block); |
| 9389 | | // if (type_has_bits(child_type)) { |
| 9390 | | // LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, ""); |
| 9391 | | // return get_handle_value(g, val_ptr, child_type); |
| 9392 | | // } else { |
| 9393 | | // return nullptr; |
| 9394 | | // } |
| 9395 | | // } |
| 9396 | | // } |
| 9397 | | // zig_unreachable(); |
| 9398 | | //} |