authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-07 18:58:01-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-07 18:58:01-05:00
log05de70017d8bf15a37f1d1be4e23f5d3f3f9b146
tree434ef9d14ed874f72231ccd734d8d618ca91affb
parenta2e32939305e470ce3d32c9d2667d3083158ddb3

IR: support slice types


6 files changed, 341 insertions(+), 151 deletions(-)

src/all_types.hpp+16
......@@ -1447,6 +1447,8 @@ enum IrInstructionId {
14471447 IrInstructionIdToPtrType,
14481448 IrInstructionIdPtrTypeChild,
14491449 IrInstructionIdSetFnTest,
1450 IrInstructionIdArrayType,
1451 IrInstructionIdSliceType,
14501452};
14511453
14521454struct IrInstruction {
......@@ -1696,6 +1698,20 @@ struct IrInstructionSetFnTest {
16961698 IrInstruction *is_test;
16971699};
16981700
1701struct IrInstructionArrayType {
1702 IrInstruction base;
1703
1704 IrInstruction *size;
1705 IrInstruction *child_type;
1706};
1707
1708struct IrInstructionSliceType {
1709 IrInstruction base;
1710
1711 bool is_const;
1712 IrInstruction *child_type;
1713};
1714
16991715enum LValPurpose {
17001716 LValPurposeNone,
17011717 LValPurposeAssign,
src/analyze.cpp+2-2
......@@ -369,7 +369,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
369369 }
370370}
371371
372static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
372TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
373373 if (child_type->error_parent) {
374374 return child_type->error_parent;
375375 } else {
......@@ -2582,7 +2582,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
25822582 &fn_table_entry->analyzed_executable, expected_type, fn_proto->return_type);
25832583 node->data.fn_def.implicit_return_type = block_return_type;
25842584
2585 if (g->verbose) {
2585 if (block_return_type->id != TypeTableEntryIdInvalid && g->verbose) {
25862586 fprintf(stderr, "fn %s { // (analyzed)\n", buf_ptr(&fn_table_entry->symbol_name));
25872587 ir_print(stderr, &fn_table_entry->analyzed_executable, 4);
25882588 fprintf(stderr, "}\n");
src/analyze.hpp+1
......@@ -31,6 +31,7 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
3131TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3232 ContainerKind kind, AstNode *decl_node, const char *name);
3333TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
34TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
3435bool handle_is_ptr(TypeTableEntry *type_entry);
3536void find_libc_include_path(CodeGen *g);
3637void find_libc_lib_path(CodeGen *g);
src/codegen.cpp+2
......@@ -2966,6 +2966,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
29662966 case IrInstructionIdPtrTypeChild:
29672967 case IrInstructionIdFieldPtr:
29682968 case IrInstructionIdSetFnTest:
2969 case IrInstructionIdArrayType:
2970 case IrInstructionIdSliceType:
29692971 zig_unreachable();
29702972 case IrInstructionIdReturn:
29712973 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+301-149
......@@ -189,6 +189,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {
189189 return IrInstructionIdSetFnTest;
190190}
191191
192static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
193 return IrInstructionIdArrayType;
194}
195
196static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) {
197 return IrInstructionIdSliceType;
198}
199
192200template<typename T>
193201static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
194202 T *special_instruction = allocate<T>(1);
......@@ -716,19 +724,30 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node,
716724 return &instruction->base;
717725}
718726
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//}
727static 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
740static 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}
732751
733752static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
734753 bool gen_error_defers, bool gen_maybe_defers)
......@@ -777,23 +796,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) {
777796 zig_unreachable();
778797}
779798
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
797799static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
798800 assert(basic_block);
799801
......@@ -1588,6 +1590,38 @@ static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, AstNode *node) {
15881590 return ir_build_const_bool(irb, node, node->data.bool_literal.value);
15891591}
15901592
1593static 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
15911625static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
15921626 LValPurpose lval)
15931627{
......@@ -1627,6 +1661,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
16271661 return ir_gen_this_literal(irb, node);
16281662 case NodeTypeBoolLiteral:
16291663 return ir_gen_bool_literal(irb, node);
1664 case NodeTypeArrayType:
1665 return ir_gen_array_type(irb, node);
16301666 case NodeTypeUnwrapErrorExpr:
16311667 case NodeTypeDefer:
16321668 case NodeTypeSliceExpr:
......@@ -1644,7 +1680,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
16441680 case NodeTypeZeroesLiteral:
16451681 case NodeTypeErrorType:
16461682 case NodeTypeTypeLiteral:
1647 case NodeTypeArrayType:
16481683 case NodeTypeVarLiteral:
16491684 case NodeTypeRoot:
16501685 case NodeTypeFnProto:
......@@ -1703,51 +1738,6 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
17031738 return ir_gen(codegn, body_node, scope, ir_executable);
17041739}
17051740
1706/*
1707static 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
17511741static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
17521742 TypeTableEntry *other_type_underlying = get_underlying_type(other_type);
17531743
......@@ -2970,6 +2960,59 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn
29702960 return bool_type;
29712961}
29722962
2963static 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
29733016static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
29743017 IrUnOp op_id = un_op_instruction->op_id;
29753018 switch (op_id) {
......@@ -2977,7 +3020,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
29773020 zig_unreachable();
29783021 case IrUnOpBoolNot:
29793022 return ir_analyze_unary_bool_not(ira, un_op_instruction);
2980 zig_panic("TODO analyze PrefixOpBoolNot");
29813023 case IrUnOpBinNot:
29823024 zig_panic("TODO analyze PrefixOpBinNot");
29833025 //{
......@@ -3106,31 +3148,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
31063148 // }
31073149 //}
31083150 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);
31343152 case IrUnOpUnwrapError:
31353153 zig_panic("TODO analyze PrefixOpUnwrapError");
31363154 //{
......@@ -3691,6 +3709,59 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,
36913709 return ira->codegen->builtin_types.entry_void;
36923710}
36933711
3712static 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
36943765static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
36953766 switch (instruction->id) {
36963767 case IrInstructionIdInvalid:
......@@ -3735,11 +3806,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
37353806 return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
37363807 case IrInstructionIdSetFnTest:
37373808 return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
3809 case IrInstructionIdSliceType:
3810 return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);
37383811 case IrInstructionIdSwitchBr:
37393812 case IrInstructionIdCast:
37403813 case IrInstructionIdContainerInitList:
37413814 case IrInstructionIdContainerInitFields:
37423815 case IrInstructionIdStructFieldPtr:
3816 case IrInstructionIdArrayType:
37433817 zig_panic("TODO analyze more instructions");
37443818 }
37453819 zig_unreachable();
......@@ -3836,6 +3910,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
38363910 case IrInstructionIdPtrTypeChild:
38373911 case IrInstructionIdReadField:
38383912 case IrInstructionIdStructFieldPtr:
3913 case IrInstructionIdArrayType:
3914 case IrInstructionIdSliceType:
38393915 return false;
38403916 }
38413917 zig_unreachable();
......@@ -6782,53 +6858,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
67826858// false, nullptr, false);
67836859//}
67846860//
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//}
68326861//
68336862//static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
68346863// TypeTableEntry *expected_type, AstNode *node)
......@@ -7218,3 +7247,126 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
72187247// }
72197248//}
72207249//
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/*
7329static 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
src/ir_print.cpp+19
......@@ -394,6 +394,19 @@ static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instructi
394394 fprintf(irp->f, ")");
395395}
396396
397static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) {
398 fprintf(irp->f, "[");
399 ir_print_other_instruction(irp, instruction->size);
400 fprintf(irp->f, "]");
401 ir_print_other_instruction(irp, instruction->child_type);
402}
403
404static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) {
405 const char *const_kw = instruction->is_const ? "const " : "";
406 fprintf(irp->f, "[]%s", const_kw);
407 ir_print_other_instruction(irp, instruction->child_type);
408}
409
397410static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
398411 ir_print_prefix(irp, instruction);
399412 switch (instruction->id) {
......@@ -471,6 +484,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
471484 case IrInstructionIdSetFnTest:
472485 ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
473486 break;
487 case IrInstructionIdArrayType:
488 ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
489 break;
490 case IrInstructionIdSliceType:
491 ir_print_slice_type(irp, (IrInstructionSliceType *)instruction);
492 break;
474493 case IrInstructionIdSwitchBr:
475494 zig_panic("TODO print more IR instructions");
476495 }