| ... | @@ -93,6 +93,10 @@ static Buf *exec_c_import_buf(IrExecutable *exec) { | ... | @@ -93,6 +93,10 @@ static Buf *exec_c_import_buf(IrExecutable *exec) { |
| 93 | return exec->c_import_buf; | 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 | static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) { | 100 | static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) { |
| 97 | new_instruction->other = old_instruction; | 101 | new_instruction->other = old_instruction; |
| 98 | old_instruction->other = new_instruction; | 102 | old_instruction->other = new_instruction; |
| ... | @@ -411,6 +415,34 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) { | ... | @@ -411,6 +415,34 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) { |
| 411 | return IrInstructionIdOverflowOp; | 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 | template<typename T> | 446 | template<typename T> |
| 415 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { | 447 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { |
| 416 | T *special_instruction = allocate<T>(1); | 448 | T *special_instruction = allocate<T>(1); |
| ... | @@ -1037,8 +1069,11 @@ static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -1037,8 +1069,11 @@ static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode |
| 1037 | return &instruction->base; | 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) { | 1072 | static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1041 | IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>(irb, scope, source_node); | 1073 | IrInstruction *value) |
| | 1074 | { |
| | 1075 | IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>( |
| | 1076 | irb, scope, source_node); |
| 1042 | instruction->value = value; | 1077 | instruction->value = value; |
| 1043 | | 1078 | |
| 1044 | ir_ref_instruction(value); | 1079 | ir_ref_instruction(value); |
| ... | @@ -1198,6 +1233,33 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction * | ... | @@ -1198,6 +1233,33 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction * |
| 1198 | return new_instruction; | 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 | static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { | 1263 | static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1202 | IrInstructionClz *instruction = ir_build_instruction<IrInstructionClz>(irb, scope, source_node); | 1264 | IrInstructionClz *instruction = ir_build_instruction<IrInstructionClz>(irb, scope, source_node); |
| 1203 | instruction->value = value; | 1265 | instruction->value = value; |
| ... | @@ -1709,6 +1771,76 @@ static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *so | ... | @@ -1709,6 +1771,76 @@ static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *so |
| 1709 | return &instruction->base; | 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 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 1844 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 1713 | results[ReturnKindUnconditional] = 0; | 1845 | results[ReturnKindUnconditional] = 0; |
| 1714 | results[ReturnKindError] = 0; | 1846 | results[ReturnKindError] = 0; |
| ... | @@ -1799,7 +1931,29 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -1799,7 +1931,29 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 1799 | return ir_build_return(irb, scope, node, return_value); | 1931 | return ir_build_return(irb, scope, node, return_value); |
| 1800 | } | 1932 | } |
| 1801 | case ReturnKindError: | 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 | case ReturnKindMaybe: | 1957 | case ReturnKindMaybe: |
| 1804 | { | 1958 | { |
| 1805 | assert(expr_node); | 1959 | assert(expr_node); |
| ... | @@ -2798,13 +2952,33 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -2798,13 +2952,33 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode |
| 2798 | return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone); | 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) { | 2955 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 2802 | AstNode *expr = node->data.prefix_op_expr.primary_expr; | 2956 | assert(node->type == NodeTypePrefixOpExpr); |
| 2803 | IrInstruction *value = ir_gen_node_extra(irb, expr, scope, LValPurposeAddressOf); | 2957 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 2804 | if (value == irb->codegen->invalid_instruction) | 2958 | |
| 2805 | return value; | 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 | if (lval == LValPurposeNone) | 2982 | if (lval == LValPurposeNone) |
| 2809 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); | 2983 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| 2810 | else | 2984 | else |
| ... | @@ -2860,9 +3034,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod | ... | @@ -2860,9 +3034,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 2860 | case PrefixOpError: | 3034 | case PrefixOpError: |
| 2861 | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpError); | 3035 | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpError); |
| 2862 | case PrefixOpUnwrapError: | 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 | case PrefixOpUnwrapMaybe: | 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 | zig_unreachable(); | 3041 | zig_unreachable(); |
| 2868 | } | 3042 | } |
| ... | @@ -3626,6 +3800,66 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) | ... | @@ -3626,6 +3800,66 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) |
| 3626 | return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, slice_expr->is_const); | 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 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, | 3863 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| 3630 | LValPurpose lval) | 3864 | LValPurpose lval) |
| 3631 | { | 3865 | { |
| ... | @@ -3703,6 +3937,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -3703,6 +3937,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 3703 | case NodeTypeSliceExpr: | 3937 | case NodeTypeSliceExpr: |
| 3704 | return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); | 3938 | return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); |
| 3705 | case NodeTypeUnwrapErrorExpr: | 3939 | case NodeTypeUnwrapErrorExpr: |
| | 3940 | return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval); |
| 3706 | case NodeTypeZeroesLiteral: | 3941 | case NodeTypeZeroesLiteral: |
| 3707 | case NodeTypeVarLiteral: | 3942 | case NodeTypeVarLiteral: |
| 3708 | case NodeTypeFnProto: | 3943 | case NodeTypeFnProto: |
| ... | @@ -4279,11 +4514,20 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins | ... | @@ -4279,11 +4514,20 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins |
| 4279 | } | 4514 | } |
| 4280 | | 4515 | |
| 4281 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { | 4516 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { |
| 4282 | if (value->static_value.special != ConstValSpecialStatic) { | 4517 | switch (value->static_value.special) { |
| 4283 | ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); | 4518 | case ConstValSpecialStatic: |
| 4284 | return nullptr; | 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 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | 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,6 +4619,95 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 4375 | return const_val->data.x_fn; | 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 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 4711 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 4379 | TypeTableEntry *wanted_type, IrInstruction *value) | 4712 | TypeTableEntry *wanted_type, IrInstruction *value) |
| 4380 | { | 4713 | { |
| ... | @@ -4503,18 +4836,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -4503,18 +4836,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 4503 | // explicit cast from child type of maybe type to maybe type | 4836 | // explicit cast from child type of maybe type to maybe type |
| 4504 | if (wanted_type->id == TypeTableEntryIdMaybe) { | 4837 | if (wanted_type->id == TypeTableEntryIdMaybe) { |
| 4505 | if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) { | 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, | 4839 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); |
| 4507 | CastOpMaybeWrap, true); | | |
| 4508 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; | | |
| 4509 | return cast_instruction; | | |
| 4510 | } else if (actual_type->id == TypeTableEntryIdNumLitInt || | 4840 | } else if (actual_type->id == TypeTableEntryIdNumLitInt || |
| 4511 | actual_type->id == TypeTableEntryIdNumLitFloat) | 4841 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 4512 | { | 4842 | { |
| 4513 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) { | 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, | 4844 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); |
| 4515 | CastOpMaybeWrap, true); | | |
| 4516 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; | | |
| 4517 | return cast_instruction; | | |
| 4518 | } else { | 4845 | } else { |
| 4519 | return ira->codegen->invalid_instruction; | 4846 | return ira->codegen->invalid_instruction; |
| 4520 | } | 4847 | } |
| ... | @@ -4525,27 +4852,18 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -4525,27 +4852,18 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 4525 | if (wanted_type->id == TypeTableEntryIdMaybe && | 4852 | if (wanted_type->id == TypeTableEntryIdMaybe && |
| 4526 | actual_type->id == TypeTableEntryIdNullLit) | 4853 | actual_type->id == TypeTableEntryIdNullLit) |
| 4527 | { | 4854 | { |
| 4528 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, | 4855 | return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type); |
| 4529 | CastOpNullToMaybe, true); | | |
| 4530 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNull; | | |
| 4531 | return cast_instruction; | | |
| 4532 | } | 4856 | } |
| 4533 | | 4857 | |
| 4534 | // explicit cast from child type of error type to error type | 4858 | // explicit cast from child type of error type to error type |
| 4535 | if (wanted_type->id == TypeTableEntryIdErrorUnion) { | 4859 | if (wanted_type->id == TypeTableEntryIdErrorUnion) { |
| 4536 | if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) { | 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, | 4861 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); |
| 4538 | CastOpErrorWrap, true); | | |
| 4539 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; | | |
| 4540 | return cast_instruction; | | |
| 4541 | } else if (actual_type->id == TypeTableEntryIdNumLitInt || | 4862 | } else if (actual_type->id == TypeTableEntryIdNumLitInt || |
| 4542 | actual_type->id == TypeTableEntryIdNumLitFloat) | 4863 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 4543 | { | 4864 | { |
| 4544 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) { | 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, | 4866 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); |
| 4546 | CastOpErrorWrap, true); | | |
| 4547 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; | | |
| 4548 | return cast_instruction; | | |
| 4549 | } else { | 4867 | } else { |
| 4550 | return ira->codegen->invalid_instruction; | 4868 | return ira->codegen->invalid_instruction; |
| 4551 | } | 4869 | } |
| ... | @@ -4556,10 +4874,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -4556,10 +4874,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 4556 | if (wanted_type->id == TypeTableEntryIdErrorUnion && | 4874 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 4557 | actual_type->id == TypeTableEntryIdPureError) | 4875 | actual_type->id == TypeTableEntryIdPureError) |
| 4558 | { | 4876 | { |
| 4559 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, | 4877 | return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); |
| 4560 | CastOpPureErrorWrap, false); | | |
| 4561 | cast_instruction->return_knowledge = ReturnKnowledgeKnownError; | | |
| 4562 | return cast_instruction; | | |
| 4563 | } | 4878 | } |
| 4564 | | 4879 | |
| 4565 | // explicit cast from number literal to another type | 4880 | // explicit cast from number literal to another type |
| ... | @@ -5997,33 +6312,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op | ... | @@ -5997,33 +6312,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op |
| 5997 | zig_unreachable(); | 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 | static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | 6315 | static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 6028 | IrInstruction *value = un_op_instruction->value->other; | 6316 | IrInstruction *value = un_op_instruction->value->other; |
| 6029 | TypeTableEntry *expr_type = value->type_entry; | 6317 | TypeTableEntry *expr_type = value->type_entry; |
| ... | @@ -6099,27 +6387,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio | ... | @@ -6099,27 +6387,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 6099 | return ir_analyze_maybe(ira, un_op_instruction); | 6387 | return ir_analyze_maybe(ira, un_op_instruction); |
| 6100 | case IrUnOpError: | 6388 | case IrUnOpError: |
| 6101 | return ir_analyze_unary_prefix_op_err(ira, un_op_instruction); | 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 | zig_unreachable(); | 6391 | zig_unreachable(); |
| 6125 | } | 6392 | } |
| ... | @@ -6835,6 +7102,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, | ... | @@ -6835,6 +7102,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 6835 | if (type_entry->id == TypeTableEntryIdInvalid) | 7102 | if (type_entry->id == TypeTableEntryIdInvalid) |
| 6836 | return type_entry; | 7103 | return type_entry; |
| 6837 | | 7104 | |
| | 7105 | // TODO handle typedefs |
| 6838 | if (type_entry->id != TypeTableEntryIdPointer) { | 7106 | if (type_entry->id != TypeTableEntryIdPointer) { |
| 6839 | add_node_error(ira->codegen, ptr_type_child_instruction->base.source_node, | 7107 | add_node_error(ira->codegen, ptr_type_child_instruction->base.source_node, |
| 6840 | buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name))); | 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,6 +7511,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 7243 | assert(ptr_type->id == TypeTableEntryIdPointer); | 7511 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 7244 | | 7512 | |
| 7245 | TypeTableEntry *type_entry = ptr_type->data.pointer.child_type; | 7513 | TypeTableEntry *type_entry = ptr_type->data.pointer.child_type; |
| | 7514 | // TODO handle typedef |
| 7246 | if (type_entry->id == TypeTableEntryIdInvalid) { | 7515 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 7247 | return ira->codegen->builtin_types.entry_invalid; | 7516 | return ira->codegen->builtin_types.entry_invalid; |
| 7248 | } else if (type_entry->id != TypeTableEntryIdMaybe) { | 7517 | } else if (type_entry->id != TypeTableEntryIdMaybe) { |
| ... | @@ -7253,9 +7522,12 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | ... | @@ -7253,9 +7522,12 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 7253 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | 7522 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 7254 | TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false); | 7523 | TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false); |
| 7255 | | 7524 | |
| 7256 | if (value->static_value.special != ConstValSpecialRuntime) { | 7525 | if (instr_is_comptime(value)) { |
| 7257 | ConstExprValue *maybe_val = value->static_value.data.x_ptr.base_ptr; | 7526 | ConstExprValue *val = ir_resolve_const(ira, value); |
| 7258 | assert(value->static_value.data.x_ptr.index == SIZE_MAX); | 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 | if (maybe_val->special != ConstValSpecialRuntime) { | 7532 | if (maybe_val->special != ConstValSpecialRuntime) { |
| 7261 | if (!maybe_val->data.x_maybe) { | 7533 | if (!maybe_val->data.x_maybe) { |
| ... | @@ -8837,6 +9109,161 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst | ... | @@ -8837,6 +9109,161 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst |
| 8837 | return ira->codegen->builtin_types.entry_bool; | 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 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 9267 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 8841 | switch (instruction->id) { | 9268 | switch (instruction->id) { |
| 8842 | case IrInstructionIdInvalid: | 9269 | case IrInstructionIdInvalid: |
| ... | @@ -8971,6 +9398,17 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -8971,6 +9398,17 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 8971 | return ir_analyze_instruction_alignof(ira, (IrInstructionAlignOf *)instruction); | 9398 | return ir_analyze_instruction_alignof(ira, (IrInstructionAlignOf *)instruction); |
| 8972 | case IrInstructionIdOverflowOp: | 9399 | case IrInstructionIdOverflowOp: |
| 8973 | return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction); | 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 | case IrInstructionIdCast: | 9412 | case IrInstructionIdCast: |
| 8975 | case IrInstructionIdStructFieldPtr: | 9413 | case IrInstructionIdStructFieldPtr: |
| 8976 | case IrInstructionIdEnumFieldPtr: | 9414 | case IrInstructionIdEnumFieldPtr: |
| ... | @@ -9122,6 +9560,13 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -9122,6 +9560,13 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 9122 | case IrInstructionIdAlignOf: | 9560 | case IrInstructionIdAlignOf: |
| 9123 | case IrInstructionIdReturnAddress: | 9561 | case IrInstructionIdReturnAddress: |
| 9124 | case IrInstructionIdFrameAddress: | 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 | return false; | 9570 | return false; |
| 9126 | case IrInstructionIdAsm: | 9571 | case IrInstructionIdAsm: |
| 9127 | { | 9572 | { |
| ... | @@ -9131,268 +9576,3 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -9131,268 +9576,3 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 9131 | } | 9576 | } |
| 9132 | zig_unreachable(); | 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 | //} | | |