| ... | ... | @@ -189,6 +189,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) { |
| 189 | 189 | return IrInstructionIdSetFnTest; |
| 190 | 190 | } |
| 191 | 191 | |
| 192 | static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) { |
| 193 | return IrInstructionIdArrayType; |
| 194 | } |
| 195 | |
| 196 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) { |
| 197 | return IrInstructionIdSliceType; |
| 198 | } |
| 199 | |
| 192 | 200 | template<typename T> |
| 193 | 201 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 194 | 202 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -716,19 +724,30 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node, |
| 716 | 724 | return &instruction->base; |
| 717 | 725 | } |
| 718 | 726 | |
| 719 | | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { |
| 720 | | // size_t result = 0; |
| 721 | | // while (inner_block != outer_block) { |
| 722 | | // if (inner_block->node->type == NodeTypeDefer && |
| 723 | | // (inner_block->node->data.defer.kind == ReturnKindError || |
| 724 | | // inner_block->node->data.defer.kind == ReturnKindMaybe)) |
| 725 | | // { |
| 726 | | // result += 1; |
| 727 | | // } |
| 728 | | // inner_block = inner_block->parent; |
| 729 | | // } |
| 730 | | // return result; |
| 731 | | //} |
| 727 | static IrInstruction *ir_build_array_type(IrBuilder *irb, AstNode *source_node, IrInstruction *size, |
| 728 | IrInstruction *child_type) |
| 729 | { |
| 730 | IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, source_node); |
| 731 | instruction->size = size; |
| 732 | instruction->child_type = child_type; |
| 733 | |
| 734 | ir_ref_instruction(size); |
| 735 | ir_ref_instruction(child_type); |
| 736 | |
| 737 | return &instruction->base; |
| 738 | } |
| 739 | |
| 740 | static IrInstruction *ir_build_slice_type(IrBuilder *irb, AstNode *source_node, bool is_const, |
| 741 | IrInstruction *child_type) |
| 742 | { |
| 743 | IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, source_node); |
| 744 | instruction->is_const = is_const; |
| 745 | instruction->child_type = child_type; |
| 746 | |
| 747 | ir_ref_instruction(child_type); |
| 748 | |
| 749 | return &instruction->base; |
| 750 | } |
| 732 | 751 | |
| 733 | 752 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, |
| 734 | 753 | bool gen_error_defers, bool gen_maybe_defers) |
| ... | ... | @@ -777,23 +796,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) { |
| 777 | 796 | zig_unreachable(); |
| 778 | 797 | } |
| 779 | 798 | |
| 780 | | //static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) { |
| 781 | | // BlockContext *defer_inner_block = source_node->block_context; |
| 782 | | // BlockContext *defer_outer_block = irb->node->block_context; |
| 783 | | // if (rk == ReturnKnowledgeUnknown) { |
| 784 | | // if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) { |
| 785 | | // // generate branching code that checks the return value and generates defers |
| 786 | | // // if the return value is error |
| 787 | | // zig_panic("TODO"); |
| 788 | | // } |
| 789 | | // } else if (rk != ReturnKnowledgeSkipDefers) { |
| 790 | | // ir_gen_defers_for_block(irb, defer_inner_block, defer_outer_block, |
| 791 | | // rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull); |
| 792 | | // } |
| 793 | | // |
| 794 | | // return ir_build_return(irb, source_node, value); |
| 795 | | //} |
| 796 | | |
| 797 | 799 | static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) { |
| 798 | 800 | assert(basic_block); |
| 799 | 801 | |
| ... | ... | @@ -1588,6 +1590,38 @@ static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, AstNode *node) { |
| 1588 | 1590 | return ir_build_const_bool(irb, node, node->data.bool_literal.value); |
| 1589 | 1591 | } |
| 1590 | 1592 | |
| 1593 | static IrInstruction *ir_gen_array_type(IrBuilder *irb, AstNode *node) { |
| 1594 | assert(node->type == NodeTypeArrayType); |
| 1595 | |
| 1596 | AstNode *size_node = node->data.array_type.size; |
| 1597 | AstNode *child_type_node = node->data.array_type.child_type; |
| 1598 | bool is_const = node->data.array_type.is_const; |
| 1599 | |
| 1600 | if (size_node) { |
| 1601 | if (is_const) { |
| 1602 | add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); |
| 1603 | return irb->codegen->invalid_instruction; |
| 1604 | } |
| 1605 | |
| 1606 | IrInstruction *size_value = ir_gen_node(irb, size_node, node->block_context); |
| 1607 | if (size_value == irb->codegen->invalid_instruction) |
| 1608 | return size_value; |
| 1609 | |
| 1610 | IrInstruction *child_type = ir_gen_node(irb, child_type_node, node->block_context); |
| 1611 | if (child_type == irb->codegen->invalid_instruction) |
| 1612 | return child_type; |
| 1613 | |
| 1614 | return ir_build_array_type(irb, node, size_value, child_type); |
| 1615 | } else { |
| 1616 | IrInstruction *child_type = ir_gen_node_extra(irb, child_type_node, |
| 1617 | node->block_context, LValPurposeAddressOf); |
| 1618 | if (child_type == irb->codegen->invalid_instruction) |
| 1619 | return child_type; |
| 1620 | |
| 1621 | return ir_build_slice_type(irb, node, is_const, child_type); |
| 1622 | } |
| 1623 | } |
| 1624 | |
| 1591 | 1625 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, |
| 1592 | 1626 | LValPurpose lval) |
| 1593 | 1627 | { |
| ... | ... | @@ -1627,6 +1661,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 1627 | 1661 | return ir_gen_this_literal(irb, node); |
| 1628 | 1662 | case NodeTypeBoolLiteral: |
| 1629 | 1663 | return ir_gen_bool_literal(irb, node); |
| 1664 | case NodeTypeArrayType: |
| 1665 | return ir_gen_array_type(irb, node); |
| 1630 | 1666 | case NodeTypeUnwrapErrorExpr: |
| 1631 | 1667 | case NodeTypeDefer: |
| 1632 | 1668 | case NodeTypeSliceExpr: |
| ... | ... | @@ -1644,7 +1680,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 1644 | 1680 | case NodeTypeZeroesLiteral: |
| 1645 | 1681 | case NodeTypeErrorType: |
| 1646 | 1682 | case NodeTypeTypeLiteral: |
| 1647 | | case NodeTypeArrayType: |
| 1648 | 1683 | case NodeTypeVarLiteral: |
| 1649 | 1684 | case NodeTypeRoot: |
| 1650 | 1685 | case NodeTypeFnProto: |
| ... | ... | @@ -1703,51 +1738,6 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 1703 | 1738 | return ir_gen(codegn, body_node, scope, ir_executable); |
| 1704 | 1739 | } |
| 1705 | 1740 | |
| 1706 | | /* |
| 1707 | | static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 1708 | | assert(node->type == NodeTypeGoto); |
| 1709 | | Buf *label_name = node->data.goto_expr.name; |
| 1710 | | BlockContext *context = node->block_context; |
| 1711 | | assert(context); |
| 1712 | | LabelTableEntry *label = find_label(g, context, label_name); |
| 1713 | | |
| 1714 | | if (!label) { |
| 1715 | | add_node_error(g, node, buf_sprintf("no label in scope named '%s'", buf_ptr(label_name))); |
| 1716 | | return; |
| 1717 | | } |
| 1718 | | |
| 1719 | | label->used = true; |
| 1720 | | node->data.goto_expr.label_entry = label; |
| 1721 | | } |
| 1722 | | |
| 1723 | | for (size_t i = 0; i < fn_table_entry->goto_list.length; i += 1) { |
| 1724 | | AstNode *goto_node = fn_table_entry->goto_list.at(i); |
| 1725 | | assert(goto_node->type == NodeTypeGoto); |
| 1726 | | analyze_goto_pass2(g, import, goto_node); |
| 1727 | | } |
| 1728 | | |
| 1729 | | for (size_t i = 0; i < fn_table_entry->all_labels.length; i += 1) { |
| 1730 | | LabelTableEntry *label = fn_table_entry->all_labels.at(i); |
| 1731 | | if (!label->used) { |
| 1732 | | add_node_error(g, label->decl_node, |
| 1733 | | buf_sprintf("label '%s' defined but not used", |
| 1734 | | buf_ptr(label->decl_node->data.label.name))); |
| 1735 | | } |
| 1736 | | } |
| 1737 | | */ |
| 1738 | | |
| 1739 | | //static LabelTableEntry *find_label(CodeGen *g, BlockContext *orig_context, Buf *name) { |
| 1740 | | // BlockContext *context = orig_context; |
| 1741 | | // while (context && context->fn_entry) { |
| 1742 | | // auto entry = context->label_table.maybe_get(name); |
| 1743 | | // if (entry) { |
| 1744 | | // return entry->value; |
| 1745 | | // } |
| 1746 | | // context = context->parent; |
| 1747 | | // } |
| 1748 | | // return nullptr; |
| 1749 | | //} |
| 1750 | | |
| 1751 | 1741 | static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) { |
| 1752 | 1742 | TypeTableEntry *other_type_underlying = get_underlying_type(other_type); |
| 1753 | 1743 | |
| ... | ... | @@ -2970,6 +2960,59 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn |
| 2970 | 2960 | return bool_type; |
| 2971 | 2961 | } |
| 2972 | 2962 | |
| 2963 | static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 2964 | assert(un_op_instruction->op_id == IrUnOpError); |
| 2965 | IrInstruction *value = un_op_instruction->value->other; |
| 2966 | |
| 2967 | TypeTableEntry *type_entry = value->type_entry; |
| 2968 | if (type_entry->id == TypeTableEntryIdInvalid) |
| 2969 | return ira->codegen->builtin_types.entry_invalid; |
| 2970 | |
| 2971 | TypeTableEntry *meta_type = ir_resolve_type(ira, value); |
| 2972 | TypeTableEntry *underlying_meta_type = get_underlying_type(meta_type); |
| 2973 | switch (underlying_meta_type->id) { |
| 2974 | case TypeTableEntryIdTypeDecl: |
| 2975 | zig_unreachable(); |
| 2976 | case TypeTableEntryIdInvalid: |
| 2977 | return ira->codegen->builtin_types.entry_invalid; |
| 2978 | case TypeTableEntryIdVoid: |
| 2979 | case TypeTableEntryIdBool: |
| 2980 | case TypeTableEntryIdInt: |
| 2981 | case TypeTableEntryIdFloat: |
| 2982 | case TypeTableEntryIdPointer: |
| 2983 | case TypeTableEntryIdArray: |
| 2984 | case TypeTableEntryIdStruct: |
| 2985 | case TypeTableEntryIdMaybe: |
| 2986 | case TypeTableEntryIdErrorUnion: |
| 2987 | case TypeTableEntryIdPureError: |
| 2988 | case TypeTableEntryIdEnum: |
| 2989 | case TypeTableEntryIdUnion: |
| 2990 | case TypeTableEntryIdFn: |
| 2991 | case TypeTableEntryIdGenericFn: |
| 2992 | { |
| 2993 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, |
| 2994 | value->static_value.depends_on_compile_var); |
| 2995 | TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type); |
| 2996 | out_val->data.x_type = result_type; |
| 2997 | return ira->codegen->builtin_types.entry_type; |
| 2998 | } |
| 2999 | case TypeTableEntryIdMetaType: |
| 3000 | case TypeTableEntryIdNumLitFloat: |
| 3001 | case TypeTableEntryIdNumLitInt: |
| 3002 | case TypeTableEntryIdUndefLit: |
| 3003 | case TypeTableEntryIdNullLit: |
| 3004 | case TypeTableEntryIdNamespace: |
| 3005 | case TypeTableEntryIdBlock: |
| 3006 | case TypeTableEntryIdUnreachable: |
| 3007 | case TypeTableEntryIdVar: |
| 3008 | add_node_error(ira->codegen, un_op_instruction->base.source_node, |
| 3009 | buf_sprintf("unable to wrap type '%s' in error type", buf_ptr(&meta_type->name))); |
| 3010 | // TODO if meta_type is type decl, add note pointing to type decl declaration |
| 3011 | return ira->codegen->builtin_types.entry_invalid; |
| 3012 | } |
| 3013 | zig_unreachable(); |
| 3014 | } |
| 3015 | |
| 2973 | 3016 | static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 2974 | 3017 | IrUnOp op_id = un_op_instruction->op_id; |
| 2975 | 3018 | switch (op_id) { |
| ... | ... | @@ -2977,7 +3020,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 2977 | 3020 | zig_unreachable(); |
| 2978 | 3021 | case IrUnOpBoolNot: |
| 2979 | 3022 | return ir_analyze_unary_bool_not(ira, un_op_instruction); |
| 2980 | | zig_panic("TODO analyze PrefixOpBoolNot"); |
| 2981 | 3023 | case IrUnOpBinNot: |
| 2982 | 3024 | zig_panic("TODO analyze PrefixOpBinNot"); |
| 2983 | 3025 | //{ |
| ... | ... | @@ -3106,31 +3148,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 3106 | 3148 | // } |
| 3107 | 3149 | //} |
| 3108 | 3150 | case IrUnOpError: |
| 3109 | | zig_panic("TODO analyze PrefixOpError"); |
| 3110 | | //{ |
| 3111 | | // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node); |
| 3112 | | |
| 3113 | | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| 3114 | | // return type_entry; |
| 3115 | | // } else if (type_entry->id == TypeTableEntryIdMetaType) { |
| 3116 | | // TypeTableEntry *meta_type = resolve_type(g, *expr_node); |
| 3117 | | // if (meta_type->id == TypeTableEntryIdInvalid) { |
| 3118 | | // return meta_type; |
| 3119 | | // } else if (meta_type->id == TypeTableEntryIdUnreachable) { |
| 3120 | | // add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in error type")); |
| 3121 | | // return g->builtin_types.entry_invalid; |
| 3122 | | // } else { |
| 3123 | | // return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type), false); |
| 3124 | | // } |
| 3125 | | // } else if (type_entry->id == TypeTableEntryIdUnreachable) { |
| 3126 | | // add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in error type")); |
| 3127 | | // return g->builtin_types.entry_invalid; |
| 3128 | | // } else { |
| 3129 | | // // TODO eval const expr |
| 3130 | | // return get_error_type(g, type_entry); |
| 3131 | | // } |
| 3132 | | |
| 3133 | | //} |
| 3151 | return ir_analyze_unary_prefix_op_err(ira, un_op_instruction); |
| 3134 | 3152 | case IrUnOpUnwrapError: |
| 3135 | 3153 | zig_panic("TODO analyze PrefixOpUnwrapError"); |
| 3136 | 3154 | //{ |
| ... | ... | @@ -3691,6 +3709,59 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira, |
| 3691 | 3709 | return ira->codegen->builtin_types.entry_void; |
| 3692 | 3710 | } |
| 3693 | 3711 | |
| 3712 | static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 3713 | IrInstructionSliceType *slice_type_instruction) |
| 3714 | { |
| 3715 | IrInstruction *child_type = slice_type_instruction->child_type->other; |
| 3716 | if (child_type->type_entry->id == TypeTableEntryIdInvalid) |
| 3717 | return ira->codegen->builtin_types.entry_invalid; |
| 3718 | bool is_const = slice_type_instruction->is_const; |
| 3719 | |
| 3720 | TypeTableEntry *resolved_child_type = ir_resolve_type(ira, child_type); |
| 3721 | TypeTableEntry *canon_child_type = get_underlying_type(resolved_child_type); |
| 3722 | switch (canon_child_type->id) { |
| 3723 | case TypeTableEntryIdTypeDecl: |
| 3724 | zig_unreachable(); |
| 3725 | case TypeTableEntryIdInvalid: |
| 3726 | return ira->codegen->builtin_types.entry_invalid; |
| 3727 | case TypeTableEntryIdVar: |
| 3728 | case TypeTableEntryIdUnreachable: |
| 3729 | case TypeTableEntryIdUndefLit: |
| 3730 | case TypeTableEntryIdNullLit: |
| 3731 | case TypeTableEntryIdBlock: |
| 3732 | add_node_error(ira->codegen, slice_type_instruction->base.source_node, |
| 3733 | buf_sprintf("slice of type '%s' not allowed", buf_ptr(&resolved_child_type->name))); |
| 3734 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| 3735 | return ira->codegen->builtin_types.entry_invalid; |
| 3736 | case TypeTableEntryIdMetaType: |
| 3737 | case TypeTableEntryIdVoid: |
| 3738 | case TypeTableEntryIdBool: |
| 3739 | case TypeTableEntryIdInt: |
| 3740 | case TypeTableEntryIdFloat: |
| 3741 | case TypeTableEntryIdPointer: |
| 3742 | case TypeTableEntryIdArray: |
| 3743 | case TypeTableEntryIdStruct: |
| 3744 | case TypeTableEntryIdNumLitFloat: |
| 3745 | case TypeTableEntryIdNumLitInt: |
| 3746 | case TypeTableEntryIdMaybe: |
| 3747 | case TypeTableEntryIdErrorUnion: |
| 3748 | case TypeTableEntryIdPureError: |
| 3749 | case TypeTableEntryIdEnum: |
| 3750 | case TypeTableEntryIdUnion: |
| 3751 | case TypeTableEntryIdFn: |
| 3752 | case TypeTableEntryIdNamespace: |
| 3753 | case TypeTableEntryIdGenericFn: |
| 3754 | { |
| 3755 | TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const); |
| 3756 | ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base, |
| 3757 | child_type->static_value.depends_on_compile_var); |
| 3758 | out_val->data.x_type = result_type; |
| 3759 | return ira->codegen->builtin_types.entry_type; |
| 3760 | } |
| 3761 | } |
| 3762 | zig_unreachable(); |
| 3763 | } |
| 3764 | |
| 3694 | 3765 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 3695 | 3766 | switch (instruction->id) { |
| 3696 | 3767 | case IrInstructionIdInvalid: |
| ... | ... | @@ -3735,11 +3806,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 3735 | 3806 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); |
| 3736 | 3807 | case IrInstructionIdSetFnTest: |
| 3737 | 3808 | return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction); |
| 3809 | case IrInstructionIdSliceType: |
| 3810 | return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); |
| 3738 | 3811 | case IrInstructionIdSwitchBr: |
| 3739 | 3812 | case IrInstructionIdCast: |
| 3740 | 3813 | case IrInstructionIdContainerInitList: |
| 3741 | 3814 | case IrInstructionIdContainerInitFields: |
| 3742 | 3815 | case IrInstructionIdStructFieldPtr: |
| 3816 | case IrInstructionIdArrayType: |
| 3743 | 3817 | zig_panic("TODO analyze more instructions"); |
| 3744 | 3818 | } |
| 3745 | 3819 | zig_unreachable(); |
| ... | ... | @@ -3836,6 +3910,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 3836 | 3910 | case IrInstructionIdPtrTypeChild: |
| 3837 | 3911 | case IrInstructionIdReadField: |
| 3838 | 3912 | case IrInstructionIdStructFieldPtr: |
| 3913 | case IrInstructionIdArrayType: |
| 3914 | case IrInstructionIdSliceType: |
| 3839 | 3915 | return false; |
| 3840 | 3916 | } |
| 3841 | 3917 | zig_unreachable(); |
| ... | ... | @@ -6782,53 +6858,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 6782 | 6858 | // false, nullptr, false); |
| 6783 | 6859 | //} |
| 6784 | 6860 | // |
| 6785 | | //static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 6786 | | // TypeTableEntry *expected_type, AstNode *node) |
| 6787 | | //{ |
| 6788 | | // AstNode *size_node = node->data.array_type.size; |
| 6789 | | // |
| 6790 | | // TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context, |
| 6791 | | // node->data.array_type.child_type, true); |
| 6792 | | // |
| 6793 | | // if (child_type->id == TypeTableEntryIdUnreachable) { |
| 6794 | | // add_node_error(g, node, buf_create_from_str("array of unreachable not allowed")); |
| 6795 | | // return g->builtin_types.entry_invalid; |
| 6796 | | // } else if (child_type->id == TypeTableEntryIdInvalid) { |
| 6797 | | // return g->builtin_types.entry_invalid; |
| 6798 | | // } |
| 6799 | | // |
| 6800 | | // if (size_node) { |
| 6801 | | // child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type); |
| 6802 | | // TypeTableEntry *size_type = analyze_expression(g, import, context, |
| 6803 | | // g->builtin_types.entry_usize, size_node); |
| 6804 | | // if (size_type->id == TypeTableEntryIdInvalid) { |
| 6805 | | // return g->builtin_types.entry_invalid; |
| 6806 | | // } |
| 6807 | | // |
| 6808 | | // ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; |
| 6809 | | // if (const_val->ok) { |
| 6810 | | // if (const_val->data.x_bignum.is_negative) { |
| 6811 | | // add_node_error(g, size_node, |
| 6812 | | // buf_sprintf("array size %s is negative", |
| 6813 | | // buf_ptr(bignum_to_buf(&const_val->data.x_bignum)))); |
| 6814 | | // return g->builtin_types.entry_invalid; |
| 6815 | | // } else { |
| 6816 | | // return resolve_expr_const_val_as_type(g, node, |
| 6817 | | // get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false); |
| 6818 | | // } |
| 6819 | | // } else if (context->fn_entry) { |
| 6820 | | // return resolve_expr_const_val_as_type(g, node, |
| 6821 | | // get_slice_type(g, child_type, node->data.array_type.is_const), false); |
| 6822 | | // } else { |
| 6823 | | // add_node_error(g, first_executing_node(size_node), |
| 6824 | | // buf_sprintf("unable to evaluate constant expression")); |
| 6825 | | // return g->builtin_types.entry_invalid; |
| 6826 | | // } |
| 6827 | | // } else { |
| 6828 | | // TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const); |
| 6829 | | // return resolve_expr_const_val_as_type(g, node, slice_type, false); |
| 6830 | | // } |
| 6831 | | //} |
| 6832 | 6861 | // |
| 6833 | 6862 | //static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 6834 | 6863 | // TypeTableEntry *expected_type, AstNode *node) |
| ... | ... | @@ -7218,3 +7247,126 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 7218 | 7247 | // } |
| 7219 | 7248 | //} |
| 7220 | 7249 | // |
| 7250 | //static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 7251 | // TypeTableEntry *expected_type, AstNode *node) |
| 7252 | //{ |
| 7253 | // AstNode *size_node = node->data.array_type.size; |
| 7254 | // |
| 7255 | // TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context, |
| 7256 | // node->data.array_type.child_type, true); |
| 7257 | // |
| 7258 | // if (child_type->id == TypeTableEntryIdUnreachable) { |
| 7259 | // add_node_error(g, node, buf_create_from_str("array of unreachable not allowed")); |
| 7260 | // return g->builtin_types.entry_invalid; |
| 7261 | // } else if (child_type->id == TypeTableEntryIdInvalid) { |
| 7262 | // return g->builtin_types.entry_invalid; |
| 7263 | // } |
| 7264 | // |
| 7265 | // if (size_node) { |
| 7266 | // child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type); |
| 7267 | // TypeTableEntry *size_type = analyze_expression(g, import, context, |
| 7268 | // g->builtin_types.entry_usize, size_node); |
| 7269 | // if (size_type->id == TypeTableEntryIdInvalid) { |
| 7270 | // return g->builtin_types.entry_invalid; |
| 7271 | // } |
| 7272 | // |
| 7273 | // ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; |
| 7274 | // if (const_val->ok) { |
| 7275 | // if (const_val->data.x_bignum.is_negative) { |
| 7276 | // add_node_error(g, size_node, |
| 7277 | // buf_sprintf("array size %s is negative", |
| 7278 | // buf_ptr(bignum_to_buf(&const_val->data.x_bignum)))); |
| 7279 | // return g->builtin_types.entry_invalid; |
| 7280 | // } else { |
| 7281 | // return resolve_expr_const_val_as_type(g, node, |
| 7282 | // get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false); |
| 7283 | // } |
| 7284 | // } else if (context->fn_entry) { |
| 7285 | // return resolve_expr_const_val_as_type(g, node, |
| 7286 | // get_slice_type(g, child_type, node->data.array_type.is_const), false); |
| 7287 | // } else { |
| 7288 | // add_node_error(g, first_executing_node(size_node), |
| 7289 | // buf_sprintf("unable to evaluate constant expression")); |
| 7290 | // return g->builtin_types.entry_invalid; |
| 7291 | // } |
| 7292 | // } else { |
| 7293 | // TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const); |
| 7294 | // return resolve_expr_const_val_as_type(g, node, slice_type, false); |
| 7295 | // } |
| 7296 | //} |
| 7297 | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { |
| 7298 | // size_t result = 0; |
| 7299 | // while (inner_block != outer_block) { |
| 7300 | // if (inner_block->node->type == NodeTypeDefer && |
| 7301 | // (inner_block->node->data.defer.kind == ReturnKindError || |
| 7302 | // inner_block->node->data.defer.kind == ReturnKindMaybe)) |
| 7303 | // { |
| 7304 | // result += 1; |
| 7305 | // } |
| 7306 | // inner_block = inner_block->parent; |
| 7307 | // } |
| 7308 | // return result; |
| 7309 | //} |
| 7310 | |
| 7311 | |
| 7312 | //static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) { |
| 7313 | // BlockContext *defer_inner_block = source_node->block_context; |
| 7314 | // BlockContext *defer_outer_block = irb->node->block_context; |
| 7315 | // if (rk == ReturnKnowledgeUnknown) { |
| 7316 | // if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) { |
| 7317 | // // generate branching code that checks the return value and generates defers |
| 7318 | // // if the return value is error |
| 7319 | // zig_panic("TODO"); |
| 7320 | // } |
| 7321 | // } else if (rk != ReturnKnowledgeSkipDefers) { |
| 7322 | // ir_gen_defers_for_block(irb, defer_inner_block, defer_outer_block, |
| 7323 | // rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull); |
| 7324 | // } |
| 7325 | // |
| 7326 | // return ir_build_return(irb, source_node, value); |
| 7327 | //} |
| 7328 | /* |
| 7329 | static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 7330 | assert(node->type == NodeTypeGoto); |
| 7331 | Buf *label_name = node->data.goto_expr.name; |
| 7332 | BlockContext *context = node->block_context; |
| 7333 | assert(context); |
| 7334 | LabelTableEntry *label = find_label(g, context, label_name); |
| 7335 | |
| 7336 | if (!label) { |
| 7337 | add_node_error(g, node, buf_sprintf("no label in scope named '%s'", buf_ptr(label_name))); |
| 7338 | return; |
| 7339 | } |
| 7340 | |
| 7341 | label->used = true; |
| 7342 | node->data.goto_expr.label_entry = label; |
| 7343 | } |
| 7344 | |
| 7345 | for (size_t i = 0; i < fn_table_entry->goto_list.length; i += 1) { |
| 7346 | AstNode *goto_node = fn_table_entry->goto_list.at(i); |
| 7347 | assert(goto_node->type == NodeTypeGoto); |
| 7348 | analyze_goto_pass2(g, import, goto_node); |
| 7349 | } |
| 7350 | |
| 7351 | for (size_t i = 0; i < fn_table_entry->all_labels.length; i += 1) { |
| 7352 | LabelTableEntry *label = fn_table_entry->all_labels.at(i); |
| 7353 | if (!label->used) { |
| 7354 | add_node_error(g, label->decl_node, |
| 7355 | buf_sprintf("label '%s' defined but not used", |
| 7356 | buf_ptr(label->decl_node->data.label.name))); |
| 7357 | } |
| 7358 | } |
| 7359 | */ |
| 7360 | |
| 7361 | //static LabelTableEntry *find_label(CodeGen *g, BlockContext *orig_context, Buf *name) { |
| 7362 | // BlockContext *context = orig_context; |
| 7363 | // while (context && context->fn_entry) { |
| 7364 | // auto entry = context->label_table.maybe_get(name); |
| 7365 | // if (entry) { |
| 7366 | // return entry->value; |
| 7367 | // } |
| 7368 | // context = context->parent; |
| 7369 | // } |
| 7370 | // return nullptr; |
| 7371 | //} |
| 7372 | |