authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-26 00:25:48-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-26 00:25:48-05:00
logbbf785bc1d5740488521b0cb90eeae31090e67ae
tree5933254eac0a0d958b5f42b504037a3ae8f7c991
parent0c22358cc1cccacb9a30929fbbc990ba9d82b6b3

IR: switch expression works with numbers


6 files changed, 372 insertions(+), 165 deletions(-)

src/all_types.hpp+7
...@@ -1455,6 +1455,7 @@ enum IrInstructionId {...@@ -1455,6 +1455,7 @@ enum IrInstructionId {
1455 IrInstructionIdSizeOf,1455 IrInstructionIdSizeOf,
1456 IrInstructionIdTestNull,1456 IrInstructionIdTestNull,
1457 IrInstructionIdUnwrapMaybe,1457 IrInstructionIdUnwrapMaybe,
1458 IrInstructionIdEnumTag,
1458 IrInstructionIdClz,1459 IrInstructionIdClz,
1459 IrInstructionIdCtz,1460 IrInstructionIdCtz,
1460};1461};
...@@ -1801,6 +1802,12 @@ struct IrInstructionClz {...@@ -1801,6 +1802,12 @@ struct IrInstructionClz {
1801 IrInstruction *value;1802 IrInstruction *value;
1802};1803};
18031804
1805struct IrInstructionEnumTag {
1806 IrInstruction base;
1807
1808 IrInstruction *value;
1809};
1810
1804enum LValPurpose {1811enum LValPurpose {
1805 LValPurposeNone,1812 LValPurposeNone,
1806 LValPurposeAssign,1813 LValPurposeAssign,
src/analyze.cpp-126
...@@ -2108,44 +2108,6 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {...@@ -2108,44 +2108,6 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
2108 zig_unreachable();2108 zig_unreachable();
2109}2109}
21102110
2111static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTableEntry *other_type) {
2112 TypeTableEntry *other_type_underlying = get_underlying_type(other_type);
2113
2114 if (other_type_underlying->id == TypeTableEntryIdInvalid) {
2115 return false;
2116 }
2117
2118 Expr *expr = get_resolved_expr(literal_node);
2119 ConstExprValue *const_val = &expr->instruction->static_value;
2120 assert(const_val->special != ConstValSpecialRuntime);
2121 if (other_type_underlying->id == TypeTableEntryIdFloat) {
2122 return true;
2123 } else if (other_type_underlying->id == TypeTableEntryIdInt &&
2124 const_val->data.x_bignum.kind == BigNumKindInt)
2125 {
2126 if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type_underlying->data.integral.bit_count,
2127 other_type_underlying->data.integral.is_signed))
2128 {
2129 return true;
2130 }
2131 } else if ((other_type_underlying->id == TypeTableEntryIdNumLitFloat &&
2132 const_val->data.x_bignum.kind == BigNumKindFloat) ||
2133 (other_type_underlying->id == TypeTableEntryIdNumLitInt &&
2134 const_val->data.x_bignum.kind == BigNumKindInt))
2135 {
2136 return true;
2137 }
2138
2139 const char *num_lit_str = (const_val->data.x_bignum.kind == BigNumKindFloat) ? "float" : "integer";
2140
2141 add_node_error(g, literal_node,
2142 buf_sprintf("%s value %s cannot be implicitly casted to type '%s'",
2143 num_lit_str,
2144 buf_ptr(bignum_to_buf(&const_val->data.x_bignum)),
2145 buf_ptr(&other_type->name)));
2146 return false;
2147}
2148
2149bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type) {2111bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
2150 if (expected_type == actual_type)2112 if (expected_type == actual_type)
2151 return true;2113 return true;
...@@ -2233,94 +2195,6 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *...@@ -2233,94 +2195,6 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
2233 return false;2195 return false;
2234}2196}
22352197
2236static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_type,
2237 TypeTableEntry *actual_type, AstNode *literal_node, bool *reported_err)
2238{
2239 if (types_match_const_cast_only(expected_type, actual_type)) {
2240 return true;
2241 }
2242
2243 // implicit conversion from non maybe type to maybe type
2244 if (expected_type->id == TypeTableEntryIdMaybe &&
2245 types_match_with_implicit_cast(g, expected_type->data.maybe.child_type, actual_type,
2246 literal_node, reported_err))
2247 {
2248 return true;
2249 }
2250
2251 // implicit conversion from null literal to maybe type
2252 if (expected_type->id == TypeTableEntryIdMaybe &&
2253 actual_type->id == TypeTableEntryIdNullLit)
2254 {
2255 return true;
2256 }
2257
2258 // implicit conversion from error child type to error type
2259 if (expected_type->id == TypeTableEntryIdErrorUnion &&
2260 types_match_with_implicit_cast(g, expected_type->data.error.child_type, actual_type,
2261 literal_node, reported_err))
2262 {
2263 return true;
2264 }
2265
2266 // implicit conversion from pure error to error union type
2267 if (expected_type->id == TypeTableEntryIdErrorUnion &&
2268 actual_type->id == TypeTableEntryIdPureError)
2269 {
2270 return true;
2271 }
2272
2273 // implicit widening conversion
2274 if (expected_type->id == TypeTableEntryIdInt &&
2275 actual_type->id == TypeTableEntryIdInt &&
2276 expected_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
2277 expected_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
2278 {
2279 return true;
2280 }
2281
2282 // small enough unsigned ints can get casted to large enough signed ints
2283 if (expected_type->id == TypeTableEntryIdInt && expected_type->data.integral.is_signed &&
2284 actual_type->id == TypeTableEntryIdInt && !actual_type->data.integral.is_signed &&
2285 expected_type->data.integral.bit_count > actual_type->data.integral.bit_count)
2286 {
2287 return true;
2288 }
2289
2290 // implicit float widening conversion
2291 if (expected_type->id == TypeTableEntryIdFloat &&
2292 actual_type->id == TypeTableEntryIdFloat &&
2293 expected_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
2294 {
2295 return true;
2296 }
2297
2298 // implicit array to slice conversion
2299 if (expected_type->id == TypeTableEntryIdStruct &&
2300 expected_type->data.structure.is_slice &&
2301 actual_type->id == TypeTableEntryIdArray &&
2302 types_match_const_cast_only(
2303 expected_type->data.structure.fields[0].type_entry->data.pointer.child_type,
2304 actual_type->data.array.child_type))
2305 {
2306 return true;
2307 }
2308
2309 // implicit number literal to typed number
2310 if ((actual_type->id == TypeTableEntryIdNumLitFloat ||
2311 actual_type->id == TypeTableEntryIdNumLitInt))
2312 {
2313 if (num_lit_fits_in_other_type(g, literal_node, expected_type)) {
2314 return true;
2315 } else {
2316 *reported_err = true;
2317 }
2318 }
2319
2320
2321 return false;
2322}
2323
2324BlockContext *new_block_context(AstNode *node, BlockContext *parent) {2198BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
2325 BlockContext *context = allocate<BlockContext>(1);2199 BlockContext *context = allocate<BlockContext>(1);
2326 context->node = node;2200 context->node = node;
src/ast_render.cpp+44-2
...@@ -354,6 +354,9 @@ static void render_node_ungrouped(AstRender *ar, AstNode *node) {...@@ -354,6 +354,9 @@ static void render_node_ungrouped(AstRender *ar, AstNode *node) {
354354
355static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {355static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
356 switch (node->type) {356 switch (node->type) {
357 case NodeTypeSwitchProng:
358 case NodeTypeSwitchRange:
359 zig_unreachable();
357 case NodeTypeRoot:360 case NodeTypeRoot:
358 for (size_t i = 0; i < node->data.root.top_level_decls.length; i += 1) {361 for (size_t i = 0; i < node->data.root.top_level_decls.length; i += 1) {
359 AstNode *child = node->data.root.top_level_decls.at(i);362 AstNode *child = node->data.root.top_level_decls.at(i);
...@@ -728,6 +731,47 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -728,6 +731,47 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
728 break;731 break;
729 }732 }
730 case NodeTypeSwitchExpr:733 case NodeTypeSwitchExpr:
734 {
735 AstNodeSwitchExpr *switch_expr = &node->data.switch_expr;
736 fprintf(ar->f, "switch (");
737 render_node_grouped(ar, switch_expr->expr);
738 fprintf(ar->f, ") {\n");
739 ar->indent += ar->indent_size;
740
741 for (size_t prong_i = 0; prong_i < switch_expr->prongs.length; prong_i += 1) {
742 AstNode *prong_node = switch_expr->prongs.at(prong_i);
743 AstNodeSwitchProng *switch_prong = &prong_node->data.switch_prong;
744 print_indent(ar);
745 for (size_t item_i = 0; item_i < switch_prong->items.length; item_i += 1) {
746 AstNode *item_node = switch_prong->items.at(item_i);
747 if (item_i != 0)
748 fprintf(ar->f, ", ");
749 if (item_node->type == NodeTypeSwitchRange) {
750 AstNode *start_node = item_node->data.switch_range.start;
751 AstNode *end_node = item_node->data.switch_range.end;
752 render_node_grouped(ar, start_node);
753 fprintf(ar->f, "...");
754 render_node_grouped(ar, end_node);
755 } else {
756 render_node_grouped(ar, item_node);
757 }
758 }
759 const char *else_str = (switch_prong->items.length == 0) ? "else" : "";
760 fprintf(ar->f, "%s => ", else_str);
761 if (switch_prong->var_symbol) {
762 const char *star_str = switch_prong->var_is_ptr ? "*" : "";
763 Buf *var_name = switch_prong->var_symbol->data.symbol_expr.symbol;
764 fprintf(ar->f, "|%s%s| ", star_str, buf_ptr(var_name));
765 }
766 render_node_grouped(ar, switch_prong->expr);
767 fprintf(ar->f, ",\n");
768 }
769
770 ar->indent -= ar->indent_size;
771 print_indent(ar);
772 fprintf(ar->f, "}");
773 break;
774 }
731 case NodeTypeFnDecl:775 case NodeTypeFnDecl:
732 case NodeTypeParamDecl:776 case NodeTypeParamDecl:
733 case NodeTypeErrorValueDecl:777 case NodeTypeErrorValueDecl:
...@@ -738,8 +782,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -738,8 +782,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
738 case NodeTypeUse:782 case NodeTypeUse:
739 case NodeTypeZeroesLiteral:783 case NodeTypeZeroesLiteral:
740 case NodeTypeForExpr:784 case NodeTypeForExpr:
741 case NodeTypeSwitchProng:
742 case NodeTypeSwitchRange:
743 case NodeTypeLabel:785 case NodeTypeLabel:
744 case NodeTypeGoto:786 case NodeTypeGoto:
745 case NodeTypeBreak:787 case NodeTypeBreak:
src/codegen.cpp+30-2
...@@ -1638,6 +1638,31 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru...@@ -1638,6 +1638,31 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru
1638 return LLVMBuildCall(g->builder, fn_val, params, 2, "");1638 return LLVMBuildCall(g->builder, fn_val, params, 2, "");
1639}1639}
16401640
1641static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, IrInstructionSwitchBr *instruction) {
1642 assert(!instruction->is_inline);
1643
1644 LLVMValueRef target_value = ir_llvm_value(g, instruction->target_value);
1645 LLVMBasicBlockRef else_block = instruction->else_block->llvm_block;
1646 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block, instruction->case_count);
1647 for (size_t i = 0; i < instruction->case_count; i += 1) {
1648 IrInstructionSwitchBrCase *this_case = &instruction->cases[i];
1649 LLVMAddCase(switch_instr, ir_llvm_value(g, this_case->value), this_case->block->llvm_block);
1650 }
1651 return nullptr;
1652}
1653
1654static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstructionPhi *instruction) {
1655 LLVMValueRef phi = LLVMBuildPhi(g->builder, instruction->base.type_entry->type_ref, "");
1656 LLVMValueRef *incoming_values = allocate<LLVMValueRef>(instruction->incoming_count);
1657 LLVMBasicBlockRef *incoming_blocks = allocate<LLVMBasicBlockRef>(instruction->incoming_count);
1658 for (size_t i = 0; i < instruction->incoming_count; i += 1) {
1659 incoming_values[i] = ir_llvm_value(g, instruction->incoming_values[i]);
1660 incoming_blocks[i] = instruction->incoming_blocks[i]->llvm_block;
1661 }
1662 LLVMAddIncoming(phi, incoming_values, incoming_blocks, instruction->incoming_count);
1663 return phi;
1664}
1665
1641static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {1666static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
1642 set_debug_source_node(g, instruction->source_node);1667 set_debug_source_node(g, instruction->source_node);
16431668
...@@ -1655,6 +1680,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1655,6 +1680,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1655 case IrInstructionIdSliceType:1680 case IrInstructionIdSliceType:
1656 case IrInstructionIdCompileVar:1681 case IrInstructionIdCompileVar:
1657 case IrInstructionIdSizeOf:1682 case IrInstructionIdSizeOf:
1683 case IrInstructionIdSwitchTarget:
1658 zig_unreachable();1684 zig_unreachable();
1659 case IrInstructionIdReturn:1685 case IrInstructionIdReturn:
1660 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);1686 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -1695,12 +1721,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1695,12 +1721,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1695 case IrInstructionIdCtz:1721 case IrInstructionIdCtz:
1696 return ir_render_ctz(g, executable, (IrInstructionCtz *)instruction);1722 return ir_render_ctz(g, executable, (IrInstructionCtz *)instruction);
1697 case IrInstructionIdSwitchBr:1723 case IrInstructionIdSwitchBr:
1698 case IrInstructionIdSwitchTarget:1724 return ir_render_switch_br(g, executable, (IrInstructionSwitchBr *)instruction);
1699 case IrInstructionIdSwitchVar:
1700 case IrInstructionIdPhi:1725 case IrInstructionIdPhi:
1726 return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);
1727 case IrInstructionIdSwitchVar:
1701 case IrInstructionIdContainerInitList:1728 case IrInstructionIdContainerInitList:
1702 case IrInstructionIdContainerInitFields:1729 case IrInstructionIdContainerInitFields:
1703 case IrInstructionIdReadField:1730 case IrInstructionIdReadField:
1731 case IrInstructionIdEnumTag:
1704 zig_panic("TODO render more IR instructions to LLVM");1732 zig_panic("TODO render more IR instructions to LLVM");
1705 }1733 }
1706 zig_unreachable();1734 zig_unreachable();
src/ir.cpp+247-34
...@@ -88,16 +88,21 @@ static void ir_ref_var(VariableTableEntry *var) {...@@ -88,16 +88,21 @@ static void ir_ref_var(VariableTableEntry *var) {
88 var->ref_count += 1;88 var->ref_count += 1;
89}89}
9090
91static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint) {91static IrBasicBlock *ir_build_basic_block_raw(IrBuilder *irb, const char *name_hint) {
92 IrBasicBlock *result = allocate<IrBasicBlock>(1);92 IrBasicBlock *result = allocate<IrBasicBlock>(1);
93 result->name_hint = name_hint;93 result->name_hint = name_hint;
94 result->debug_id = exec_next_debug_id(irb->exec);94 result->debug_id = exec_next_debug_id(irb->exec);
95 return result;
96}
97
98static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint) {
99 IrBasicBlock *result = ir_build_basic_block_raw(irb, name_hint);
95 irb->exec->basic_block_list.append(result);100 irb->exec->basic_block_list.append(result);
96 return result;101 return result;
97}102}
98103
99static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {104static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
100 IrBasicBlock *new_bb = ir_build_basic_block(irb, other_bb->name_hint);105 IrBasicBlock *new_bb = ir_build_basic_block_raw(irb, other_bb->name_hint);
101 ir_link_new_bb(new_bb, other_bb);106 ir_link_new_bb(new_bb, other_bb);
102 return new_bb;107 return new_bb;
103}108}
...@@ -254,6 +259,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) {...@@ -254,6 +259,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) {
254 return IrInstructionIdCtz;259 return IrInstructionIdCtz;
255}260}
256261
262static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) {
263 return IrInstructionIdEnumTag;
264}
265
257template<typename T>266template<typename T>
258static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {267static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
259 T *special_instruction = allocate<T>(1);268 T *special_instruction = allocate<T>(1);
...@@ -612,6 +621,9 @@ static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_inst...@@ -612,6 +621,9 @@ static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_inst
612static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,621static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,
613 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)622 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
614{623{
624 assert(incoming_count != 0);
625 assert(incoming_count != SIZE_MAX);
626
615 IrInstructionPhi *phi_instruction = ir_build_instruction<IrInstructionPhi>(irb, source_node);627 IrInstructionPhi *phi_instruction = ir_build_instruction<IrInstructionPhi>(irb, source_node);
616 phi_instruction->incoming_count = incoming_count;628 phi_instruction->incoming_count = incoming_count;
617 phi_instruction->incoming_blocks = incoming_blocks;629 phi_instruction->incoming_blocks = incoming_blocks;
...@@ -993,6 +1005,8 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, AstNode *source_node, I...@@ -993,6 +1005,8 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, AstNode *source_node, I
993 IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, bool is_inline)1005 IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, bool is_inline)
994{1006{
995 IrInstructionSwitchBr *instruction = ir_build_instruction<IrInstructionSwitchBr>(irb, source_node);1007 IrInstructionSwitchBr *instruction = ir_build_instruction<IrInstructionSwitchBr>(irb, source_node);
1008 instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
1009 instruction->base.static_value.special = ConstValSpecialStatic;
996 instruction->target_value = target_value;1010 instruction->target_value = target_value;
997 instruction->else_block = else_block;1011 instruction->else_block = else_block;
998 instruction->case_count = case_count;1012 instruction->case_count = case_count;
...@@ -1010,6 +1024,16 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, AstNode *source_node, I...@@ -1010,6 +1024,16 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, AstNode *source_node, I
1010 return &instruction->base;1024 return &instruction->base;
1011}1025}
10121026
1027static IrInstruction *ir_build_switch_br_from(IrBuilder *irb, IrInstruction *old_instruction,
1028 IrInstruction *target_value, IrBasicBlock *else_block, size_t case_count,
1029 IrInstructionSwitchBrCase *cases, bool is_inline)
1030{
1031 IrInstruction *new_instruction = ir_build_switch_br(irb, old_instruction->source_node,
1032 target_value, else_block, case_count, cases, is_inline);
1033 ir_link_new_instruction(new_instruction, old_instruction);
1034 return new_instruction;
1035}
1036
1013static IrInstruction *ir_build_switch_target(IrBuilder *irb, AstNode *source_node,1037static IrInstruction *ir_build_switch_target(IrBuilder *irb, AstNode *source_node,
1014 IrInstruction *target_value_ptr)1038 IrInstruction *target_value_ptr)
1015{1039{
...@@ -1034,6 +1058,21 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, AstNode *source_node,...@@ -1034,6 +1058,21 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, AstNode *source_node,
1034 return &instruction->base;1058 return &instruction->base;
1035}1059}
10361060
1061static IrInstruction *ir_build_enum_tag(IrBuilder *irb, AstNode *source_node, IrInstruction *value) {
1062 IrInstructionEnumTag *instruction = ir_build_instruction<IrInstructionEnumTag>(irb, source_node);
1063 instruction->value = value;
1064
1065 ir_ref_instruction(value);
1066
1067 return &instruction->base;
1068}
1069
1070static IrInstruction *ir_build_enum_tag_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
1071 IrInstruction *new_instruction = ir_build_enum_tag(irb, old_instruction->source_node, value);
1072 ir_link_new_instruction(new_instruction, old_instruction);
1073 return new_instruction;
1074}
1075
1037static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,1076static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
1038 bool gen_error_defers, bool gen_maybe_defers)1077 bool gen_error_defers, bool gen_maybe_defers)
1039{1078{
...@@ -2149,7 +2188,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, AstNode *node) {...@@ -2149,7 +2188,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, AstNode *node) {
21492188
2150static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNode *prong_node,2189static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNode *prong_node,
2151 IrBasicBlock *end_block, bool is_inline, IrInstruction *target_value_ptr, IrInstruction *prong_value,2190 IrBasicBlock *end_block, bool is_inline, IrInstruction *target_value_ptr, IrInstruction *prong_value,
2152 ZigList<IrBasicBlock *> incoming_blocks, ZigList<IrInstruction *> incoming_values)2191 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
2153{2192{
2154 assert(switch_node->type == NodeTypeSwitchExpr);2193 assert(switch_node->type == NodeTypeSwitchExpr);
2155 assert(prong_node->type == NodeTypeSwitchProng);2194 assert(prong_node->type == NodeTypeSwitchProng);
...@@ -2184,8 +2223,8 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNo...@@ -2184,8 +2223,8 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNo
2184 if (expr_result == irb->codegen->invalid_instruction)2223 if (expr_result == irb->codegen->invalid_instruction)
2185 return false;2224 return false;
2186 ir_build_br(irb, switch_node, end_block, is_inline);2225 ir_build_br(irb, switch_node, end_block, is_inline);
2187 incoming_blocks.append(irb->current_basic_block);2226 incoming_blocks->append(irb->current_basic_block);
2188 incoming_values.append(expr_result);2227 incoming_values->append(expr_result);
2189 return true;2228 return true;
2190}2229}
21912230
...@@ -2222,11 +2261,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {...@@ -2222,11 +2261,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
2222 }2261 }
2223 else_prong = prong_node;2262 else_prong = prong_node;
22242263
2264 IrBasicBlock *prev_block = irb->current_basic_block;
2265 ir_set_cursor_at_end(irb, else_block);
2225 if (!ir_gen_switch_prong_expr(irb, node, prong_node, end_block,2266 if (!ir_gen_switch_prong_expr(irb, node, prong_node, end_block,
2226 is_inline, target_value_ptr, nullptr, incoming_blocks, incoming_values))2267 is_inline, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
2227 {2268 {
2228 return irb->codegen->invalid_instruction;2269 return irb->codegen->invalid_instruction;
2229 }2270 }
2271 ir_set_cursor_at_end(irb, prev_block);
2230 } else {2272 } else {
2231 if (prong_node->data.switch_prong.any_items_are_range) {2273 if (prong_node->data.switch_prong.any_items_are_range) {
2232 IrInstruction *ok_bit = nullptr;2274 IrInstruction *ok_bit = nullptr;
...@@ -2235,6 +2277,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {...@@ -2235,6 +2277,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
2235 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);2277 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
2236 last_item_node = item_node;2278 last_item_node = item_node;
2237 if (item_node->type == NodeTypeSwitchRange) {2279 if (item_node->type == NodeTypeSwitchRange) {
2280 item_node->block_context = node->block_context;
2238 AstNode *start_node = item_node->data.switch_range.start;2281 AstNode *start_node = item_node->data.switch_range.start;
2239 AstNode *end_node = item_node->data.switch_range.end;2282 AstNode *end_node = item_node->data.switch_range.end;
22402283
...@@ -2252,7 +2295,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {...@@ -2252,7 +2295,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
2252 IrInstruction *both_ok = ir_build_bin_op(irb, item_node, IrBinOpBoolAnd,2295 IrInstruction *both_ok = ir_build_bin_op(irb, item_node, IrBinOpBoolAnd,
2253 lower_range_ok, upper_range_ok);2296 lower_range_ok, upper_range_ok);
2254 if (ok_bit) {2297 if (ok_bit) {
2255 ok_bit = ir_build_bin_op(irb, item_node, IrBinOpBoolAnd, both_ok, ok_bit);2298 ok_bit = ir_build_bin_op(irb, item_node, IrBinOpBoolOr, both_ok, ok_bit);
2256 } else {2299 } else {
2257 ok_bit = both_ok;2300 ok_bit = both_ok;
2258 }2301 }
...@@ -2264,7 +2307,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {...@@ -2264,7 +2307,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
2264 IrInstruction *cmp_ok = ir_build_bin_op(irb, item_node, IrBinOpCmpEq,2307 IrInstruction *cmp_ok = ir_build_bin_op(irb, item_node, IrBinOpCmpEq,
2265 item_value, target_value);2308 item_value, target_value);
2266 if (ok_bit) {2309 if (ok_bit) {
2267 ok_bit = ir_build_bin_op(irb, item_node, IrBinOpBoolAnd, cmp_ok, ok_bit);2310 ok_bit = ir_build_bin_op(irb, item_node, IrBinOpBoolOr, cmp_ok, ok_bit);
2268 } else {2311 } else {
2269 ok_bit = cmp_ok;2312 ok_bit = cmp_ok;
2270 }2313 }
...@@ -2280,13 +2323,16 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {...@@ -2280,13 +2323,16 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
22802323
2281 ir_set_cursor_at_end(irb, range_block_yes);2324 ir_set_cursor_at_end(irb, range_block_yes);
2282 if (!ir_gen_switch_prong_expr(irb, node, prong_node, end_block,2325 if (!ir_gen_switch_prong_expr(irb, node, prong_node, end_block,
2283 is_inline, target_value_ptr, nullptr, incoming_blocks, incoming_values))2326 is_inline, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
2284 {2327 {
2285 return irb->codegen->invalid_instruction;2328 return irb->codegen->invalid_instruction;
2286 }2329 }
22872330
2288 ir_set_cursor_at_end(irb, range_block_no);2331 ir_set_cursor_at_end(irb, range_block_no);
2289 } else {2332 } else {
2333 IrBasicBlock *prong_block = ir_build_basic_block(irb, "SwitchProng");
2334 IrInstruction *last_item_value = nullptr;
2335
2290 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {2336 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
2291 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);2337 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
2292 assert(item_node->type != NodeTypeSwitchRange);2338 assert(item_node->type != NodeTypeSwitchRange);
...@@ -2295,22 +2341,24 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {...@@ -2295,22 +2341,24 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
2295 if (item_value == irb->codegen->invalid_instruction)2341 if (item_value == irb->codegen->invalid_instruction)
2296 return irb->codegen->invalid_instruction;2342 return irb->codegen->invalid_instruction;
22972343
2298 IrBasicBlock *prong_block = ir_build_basic_block(irb, "SwitchProng");
2299 IrBasicBlock *prev_block = irb->current_basic_block;
2300 ir_set_cursor_at_end(irb, prong_block);
2301
2302 if (!ir_gen_switch_prong_expr(irb, node, prong_node, end_block,
2303 is_inline, target_value_ptr, item_value, incoming_blocks, incoming_values))
2304 {
2305 return irb->codegen->invalid_instruction;
2306 }
2307
2308 IrInstructionSwitchBrCase *this_case = cases.add_one();2344 IrInstructionSwitchBrCase *this_case = cases.add_one();
2309 this_case->value = item_value;2345 this_case->value = item_value;
2310 this_case->block = prong_block;2346 this_case->block = prong_block;
23112347
2312 ir_set_cursor_at_end(irb, prev_block);2348 last_item_value = item_value;
2313 }2349 }
2350 IrInstruction *only_item_value = (prong_item_count == 1) ? last_item_value : nullptr;
2351
2352 IrBasicBlock *prev_block = irb->current_basic_block;
2353 ir_set_cursor_at_end(irb, prong_block);
2354 if (!ir_gen_switch_prong_expr(irb, node, prong_node, end_block,
2355 is_inline, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values))
2356 {
2357 return irb->codegen->invalid_instruction;
2358 }
2359
2360 ir_set_cursor_at_end(irb, prev_block);
2361
2314 }2362 }
2315 }2363 }
2316 }2364 }
...@@ -2712,26 +2760,47 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {...@@ -2712,26 +2760,47 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
2712 if (old_bb->other)2760 if (old_bb->other)
2713 return old_bb->other;2761 return old_bb->other;
2714 IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb);2762 IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb);
2763
2764 // We are about to enqueue old_bb for analysis. Before we do so, check old_bb
2765 // for phi instructions. Any incoming blocks in the phi instructions need to be
2766 // queued first.
2767 for (size_t instr_i = 0; instr_i < old_bb->instruction_list.length; instr_i += 1) {
2768 IrInstruction *instruction = old_bb->instruction_list.at(instr_i);
2769 if (instruction->id != IrInstructionIdPhi)
2770 break;
2771 IrInstructionPhi *phi_instruction = (IrInstructionPhi *)instruction;
2772 for (size_t incoming_i = 0; incoming_i < phi_instruction->incoming_count; incoming_i += 1) {
2773 IrBasicBlock *predecessor = phi_instruction->incoming_blocks[incoming_i];
2774 ir_get_new_bb(ira, predecessor);
2775 }
2776 }
2715 ira->old_bb_queue.append(old_bb);2777 ira->old_bb_queue.append(old_bb);
2778
2716 return new_bb;2779 return new_bb;
2717}2780}
27182781
2782static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *const_predecessor_bb) {
2783 ira->instruction_index = 0;
2784 ira->old_irb.current_basic_block = old_bb;
2785 ira->const_predecessor_bb = const_predecessor_bb;
2786
2787 assert(old_bb->other);
2788 ira->new_irb.exec->basic_block_list.append(old_bb->other);
2789}
2790
2719static void ir_finish_bb(IrAnalyze *ira) {2791static void ir_finish_bb(IrAnalyze *ira) {
2720 ira->block_queue_index += 1;2792 ira->block_queue_index += 1;
27212793
2722 if (ira->block_queue_index < ira->old_bb_queue.length) {2794 if (ira->block_queue_index < ira->old_bb_queue.length) {
2723 IrBasicBlock *old_bb = ira->old_bb_queue.at(ira->block_queue_index);2795 IrBasicBlock *old_bb = ira->old_bb_queue.at(ira->block_queue_index);
2724 ira->instruction_index = 0;
2725 ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb);2796 ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb);
2726 ira->old_irb.current_basic_block = old_bb;2797
2727 ira->const_predecessor_bb = nullptr;2798 ir_start_bb(ira, old_bb, nullptr);
2728 }2799 }
2729}2800}
27302801
2731static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {2802static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
2732 ira->instruction_index = 0;2803 ir_start_bb(ira, old_bb, ira->old_irb.current_basic_block);
2733 ira->const_predecessor_bb = ira->old_irb.current_basic_block;
2734 ira->old_irb.current_basic_block = old_bb;
2735}2804}
27362805
2737static TypeTableEntry *ir_finish_anal(IrAnalyze *ira, TypeTableEntry *result_type) {2806static TypeTableEntry *ir_finish_anal(IrAnalyze *ira, TypeTableEntry *result_type) {
...@@ -3603,6 +3672,8 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc...@@ -3603,6 +3672,8 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
3603 return explicit_type;3672 return explicit_type;
3604 }3673 }
36053674
3675 AstNode *source_node = decl_var_instruction->base.source_node;
3676
3606 IrInstruction *casted_init_value = ir_get_casted_value(ira, init_value, explicit_type);3677 IrInstruction *casted_init_value = ir_get_casted_value(ira, init_value, explicit_type);
3607 TypeTableEntry *result_type = get_underlying_type(casted_init_value->type_entry);3678 TypeTableEntry *result_type = get_underlying_type(casted_init_value->type_entry);
3608 switch (result_type->id) {3679 switch (result_type->id) {
...@@ -3614,7 +3685,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc...@@ -3614,7 +3685,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
3614 case TypeTableEntryIdNumLitFloat:3685 case TypeTableEntryIdNumLitFloat:
3615 case TypeTableEntryIdNumLitInt:3686 case TypeTableEntryIdNumLitInt:
3616 if (is_export || is_extern || casted_init_value->static_value.special == ConstValSpecialRuntime) {3687 if (is_export || is_extern || casted_init_value->static_value.special == ConstValSpecialRuntime) {
3617 add_node_error(ira->codegen, var_type->source_node, buf_sprintf("unable to infer variable type"));3688 add_node_error(ira->codegen, source_node, buf_sprintf("unable to infer variable type"));
3618 result_type = ira->codegen->builtin_types.entry_invalid;3689 result_type = ira->codegen->builtin_types.entry_invalid;
3619 }3690 }
3620 break;3691 break;
...@@ -3622,14 +3693,14 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc...@@ -3622,14 +3693,14 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
3622 case TypeTableEntryIdVar:3693 case TypeTableEntryIdVar:
3623 case TypeTableEntryIdBlock:3694 case TypeTableEntryIdBlock:
3624 case TypeTableEntryIdNullLit:3695 case TypeTableEntryIdNullLit:
3625 add_node_error(ira->codegen, var_type->source_node,3696 add_node_error(ira->codegen, source_node,
3626 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));3697 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
3627 result_type = ira->codegen->builtin_types.entry_invalid;3698 result_type = ira->codegen->builtin_types.entry_invalid;
3628 break;3699 break;
3629 case TypeTableEntryIdMetaType:3700 case TypeTableEntryIdMetaType:
3630 case TypeTableEntryIdNamespace:3701 case TypeTableEntryIdNamespace:
3631 if (casted_init_value->static_value.special == ConstValSpecialRuntime) {3702 if (casted_init_value->static_value.special == ConstValSpecialRuntime) {
3632 add_node_error(ira->codegen, var_type->source_node,3703 add_node_error(ira->codegen, source_node,
3633 buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));3704 buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));
3634 result_type = ira->codegen->builtin_types.entry_invalid;3705 result_type = ira->codegen->builtin_types.entry_invalid;
3635 }3706 }
...@@ -4072,6 +4143,8 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr...@@ -4072,6 +4143,8 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr
40724143
4073static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {4144static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
4074 IrInstruction *condition = cond_br_instruction->condition->other;4145 IrInstruction *condition = cond_br_instruction->condition->other;
4146 if (condition->type_entry->id == TypeTableEntryIdInvalid)
4147 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
40754148
4076 // TODO detect backward jumps4149 // TODO detect backward jumps
40774150
...@@ -4116,6 +4189,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -4116,6 +4189,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
4116 continue;4189 continue;
4117 IrInstruction *value = phi_instruction->incoming_values[i]->other;4190 IrInstruction *value = phi_instruction->incoming_values[i]->other;
4118 assert(value->type_entry);4191 assert(value->type_entry);
4192 if (value->type_entry->id == TypeTableEntryIdInvalid)
4193 return ira->codegen->builtin_types.entry_invalid;
4194
4119 if (value->static_value.special != ConstValSpecialRuntime) {4195 if (value->static_value.special != ConstValSpecialRuntime) {
4120 ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base,4196 ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base,
4121 value->static_value.depends_on_compile_var);4197 value->static_value.depends_on_compile_var);
...@@ -4141,7 +4217,10 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -4141,7 +4217,10 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
41414217
4142 IrInstruction *old_value = phi_instruction->incoming_values[i];4218 IrInstruction *old_value = phi_instruction->incoming_values[i];
4143 assert(old_value);4219 assert(old_value);
4144 new_incoming_values.append(old_value->other);4220 IrInstruction *new_value = old_value->other;
4221 if (new_value->type_entry->id == TypeTableEntryIdInvalid)
4222 return ira->codegen->builtin_types.entry_invalid;
4223 new_incoming_values.append(new_value);
4145 }4224 }
4146 assert(new_incoming_blocks.length != 0);4225 assert(new_incoming_blocks.length != 0);
41474226
...@@ -4156,6 +4235,21 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -4156,6 +4235,21 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
4156 if (resolved_type->id == TypeTableEntryIdInvalid)4235 if (resolved_type->id == TypeTableEntryIdInvalid)
4157 return resolved_type;4236 return resolved_type;
41584237
4238 if (resolved_type->id == TypeTableEntryIdNumLitFloat ||
4239 resolved_type->id == TypeTableEntryIdNumLitInt)
4240 {
4241 add_node_error(ira->codegen, phi_instruction->base.source_node,
4242 buf_sprintf("unable to infer expression type"));
4243 return ira->codegen->builtin_types.entry_invalid;
4244 }
4245
4246 // cast all literal values to the resolved type
4247 for (size_t i = 0; i < new_incoming_values.length; i += 1) {
4248 IrInstruction *new_value = new_incoming_values.at(i);
4249 IrInstruction *casted_value = ir_get_casted_value(ira, new_value, resolved_type);
4250 new_incoming_values.items[i] = casted_value;
4251 }
4252
4159 ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length,4253 ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length,
4160 new_incoming_blocks.items, new_incoming_values.items);4254 new_incoming_blocks.items, new_incoming_values.items);
4161 return resolved_type;4255 return resolved_type;
...@@ -5114,13 +5208,123 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC...@@ -5114,13 +5208,123 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC
5114static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,5208static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
5115 IrInstructionSwitchBr *switch_br_instruction)5209 IrInstructionSwitchBr *switch_br_instruction)
5116{5210{
5117 zig_panic("TODO switch br analyze");5211 IrInstruction *target_value = switch_br_instruction->target_value->other;
5212 if (target_value->type_entry->id == TypeTableEntryIdInvalid)
5213 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
5214
5215 // TODO detect backward jumps
5216
5217 size_t case_count = switch_br_instruction->case_count;
5218 bool is_inline = switch_br_instruction->is_inline;
5219
5220 if (is_inline || target_value->static_value.special != ConstValSpecialRuntime) {
5221 zig_panic("TODO compile time switch br");
5222 }
5223
5224 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(case_count);
5225 for (size_t i = 0; i < case_count; i += 1) {
5226 IrInstructionSwitchBrCase *old_case = &switch_br_instruction->cases[i];
5227 IrInstructionSwitchBrCase *new_case = &cases[i];
5228 new_case->block = ir_get_new_bb(ira, old_case->block);
5229 new_case->value = ira->codegen->invalid_instruction;
5230
5231 IrInstruction *old_value = old_case->value;
5232 IrInstruction *new_value = old_value->other;
5233 if (new_value->type_entry->id == TypeTableEntryIdInvalid)
5234 continue;
5235
5236 IrInstruction *casted_new_value = ir_get_casted_value(ira, new_value, target_value->type_entry);
5237 if (casted_new_value->type_entry->id == TypeTableEntryIdInvalid)
5238 continue;
5239
5240 if (casted_new_value->static_value.special != ConstValSpecialStatic) {
5241 add_node_error(ira->codegen, casted_new_value->source_node,
5242 buf_sprintf("unable to evaluate constant expression"));
5243 continue;
5244 }
5245
5246 new_case->value = casted_new_value;
5247 }
5248
5249 IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block);
5250 ir_build_switch_br_from(&ira->new_irb, &switch_br_instruction->base,
5251 target_value, new_else_block, case_count, cases, is_inline);
5252 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
5118}5253}
51195254
5120static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,5255static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
5121 IrInstructionSwitchTarget *switch_target_instruction)5256 IrInstructionSwitchTarget *switch_target_instruction)
5122{5257{
5123 zig_panic("TODO switch target analyze");5258 IrInstruction *target_value_ptr = switch_target_instruction->target_value_ptr->other;
5259 if (target_value_ptr->type_entry->id == TypeTableEntryIdInvalid)
5260 return ira->codegen->builtin_types.entry_invalid;
5261
5262 assert(target_value_ptr->type_entry->id == TypeTableEntryIdPointer);
5263 TypeTableEntry *target_type = target_value_ptr->type_entry->data.pointer.child_type;
5264 bool depends_on_compile_var = target_value_ptr->static_value.depends_on_compile_var;
5265 ConstExprValue *pointee_val = nullptr;
5266 if (target_value_ptr->static_value.special != ConstValSpecialRuntime) {
5267 pointee_val = const_ptr_pointee(&target_value_ptr->static_value);
5268 if (pointee_val->special == ConstValSpecialRuntime)
5269 pointee_val = nullptr;
5270 }
5271 TypeTableEntry *canon_target_type = get_underlying_type(target_type);
5272 switch (canon_target_type->id) {
5273 case TypeTableEntryIdInvalid:
5274 case TypeTableEntryIdVar:
5275 case TypeTableEntryIdTypeDecl:
5276 zig_unreachable();
5277 case TypeTableEntryIdMetaType:
5278 case TypeTableEntryIdVoid:
5279 case TypeTableEntryIdBool:
5280 case TypeTableEntryIdInt:
5281 case TypeTableEntryIdFloat:
5282 case TypeTableEntryIdNumLitFloat:
5283 case TypeTableEntryIdNumLitInt:
5284 case TypeTableEntryIdPointer:
5285 case TypeTableEntryIdFn:
5286 case TypeTableEntryIdNamespace:
5287 case TypeTableEntryIdPureError:
5288 if (pointee_val) {
5289 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base,
5290 depends_on_compile_var);
5291 *out_val = *pointee_val;
5292 return target_type;
5293 }
5294
5295 ir_build_load_ptr_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr);
5296 return target_type;
5297 case TypeTableEntryIdEnum:
5298 {
5299 TypeTableEntry *tag_type = target_type->data.enumeration.tag_type;
5300 if (pointee_val) {
5301 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base,
5302 depends_on_compile_var);
5303 bignum_init_unsigned(&out_val->data.x_bignum, pointee_val->data.x_enum.tag);
5304 return tag_type;
5305 }
5306
5307 ir_build_enum_tag_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr);
5308 return tag_type;
5309 }
5310 case TypeTableEntryIdErrorUnion:
5311 // see https://github.com/andrewrk/zig/issues/83
5312 zig_panic("TODO switch on error union");
5313 case TypeTableEntryIdUnreachable:
5314 case TypeTableEntryIdArray:
5315 case TypeTableEntryIdStruct:
5316 case TypeTableEntryIdUndefLit:
5317 case TypeTableEntryIdNullLit:
5318 case TypeTableEntryIdMaybe:
5319 case TypeTableEntryIdUnion:
5320 case TypeTableEntryIdBlock:
5321 case TypeTableEntryIdGenericFn:
5322 add_node_error(ira->codegen, switch_target_instruction->base.source_node,
5323 buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
5324 // TODO if this is a typedecl, add error note showing the declaration of the type decl
5325 return ira->codegen->builtin_types.entry_invalid;
5326 }
5327 zig_unreachable();
5124}5328}
51255329
5126static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira,5330static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira,
...@@ -5129,6 +5333,12 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira,...@@ -5129,6 +5333,12 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira,
5129 zig_panic("TODO switch var analyze");5333 zig_panic("TODO switch var analyze");
5130}5334}
51315335
5336static TypeTableEntry *ir_analyze_instruction_enum_tag(IrAnalyze *ira,
5337 IrInstructionEnumTag *enum_tag_instruction)
5338{
5339 zig_panic("TODO ir_analyze_instruction_enum_tag");
5340}
5341
5132static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {5342static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
5133 switch (instruction->id) {5343 switch (instruction->id) {
5134 case IrInstructionIdInvalid:5344 case IrInstructionIdInvalid:
...@@ -5201,6 +5411,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -5201,6 +5411,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
5201 return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction);5411 return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction);
5202 case IrInstructionIdSwitchVar:5412 case IrInstructionIdSwitchVar:
5203 return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction);5413 return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction);
5414 case IrInstructionIdEnumTag:
5415 return ir_analyze_instruction_enum_tag(ira, (IrInstructionEnumTag *)instruction);
5204 case IrInstructionIdCast:5416 case IrInstructionIdCast:
5205 case IrInstructionIdContainerInitList:5417 case IrInstructionIdContainerInitList:
5206 case IrInstructionIdContainerInitFields:5418 case IrInstructionIdContainerInitFields:
...@@ -5247,10 +5459,10 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -5247,10 +5459,10 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
5247 IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0);5459 IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0);
5248 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb);5460 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb);
5249 ir_ref_bb(new_entry_bb);5461 ir_ref_bb(new_entry_bb);
5250 ira->old_irb.current_basic_block = old_entry_bb;
5251 ira->new_irb.current_basic_block = new_entry_bb;5462 ira->new_irb.current_basic_block = new_entry_bb;
5252 ira->block_queue_index = 0;5463 ira->block_queue_index = 0;
5253 ira->instruction_index = 0;5464
5465 ir_start_bb(ira, old_entry_bb, nullptr);
52545466
5255 while (ira->block_queue_index < ira->old_bb_queue.length) {5467 while (ira->block_queue_index < ira->old_bb_queue.length) {
5256 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);5468 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
...@@ -5319,6 +5531,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -5319,6 +5531,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
5319 case IrInstructionIdCtz:5531 case IrInstructionIdCtz:
5320 case IrInstructionIdSwitchVar:5532 case IrInstructionIdSwitchVar:
5321 case IrInstructionIdSwitchTarget:5533 case IrInstructionIdSwitchTarget:
5534 case IrInstructionIdEnumTag:
5322 return false;5535 return false;
5323 case IrInstructionIdAsm:5536 case IrInstructionIdAsm:
5324 {5537 {
src/ir_print.cpp+44-1
...@@ -313,6 +313,8 @@ static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {...@@ -313,6 +313,8 @@ static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
313}313}
314314
315static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {315static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
316 assert(phi_instruction->incoming_count != 0);
317 assert(phi_instruction->incoming_count != SIZE_MAX);
316 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {318 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
317 IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];319 IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];
318 IrInstruction *incoming_value = phi_instruction->incoming_values[i];320 IrInstruction *incoming_value = phi_instruction->incoming_values[i];
...@@ -534,6 +536,39 @@ static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {...@@ -534,6 +536,39 @@ static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {
534 fprintf(irp->f, ")");536 fprintf(irp->f, ")");
535}537}
536538
539static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction) {
540 const char *inline_kw = instruction->is_inline ? "inline " : "";
541 fprintf(irp->f, "%sswitch (", inline_kw);
542 ir_print_other_instruction(irp, instruction->target_value);
543 fprintf(irp->f, ") ");
544 for (size_t i = 0; i < instruction->case_count; i += 1) {
545 IrInstructionSwitchBrCase *this_case = &instruction->cases[i];
546 ir_print_other_instruction(irp, this_case->value);
547 fprintf(irp->f, " => ");
548 ir_print_other_block(irp, this_case->block);
549 fprintf(irp->f, ", ");
550 }
551 fprintf(irp->f, "else => ");
552 ir_print_other_block(irp, instruction->else_block);
553}
554
555static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instruction) {
556 fprintf(irp->f, "switchvar ");
557 ir_print_other_instruction(irp, instruction->target_value_ptr);
558 fprintf(irp->f, ", ");
559 ir_print_other_instruction(irp, instruction->prong_value);
560}
561
562static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *instruction) {
563 fprintf(irp->f, "switchtarget ");
564 ir_print_other_instruction(irp, instruction->target_value_ptr);
565}
566
567static void ir_print_enum_tag(IrPrint *irp, IrInstructionEnumTag *instruction) {
568 fprintf(irp->f, "enumtag ");
569 ir_print_other_instruction(irp, instruction->value);
570}
571
537static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {572static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
538 ir_print_prefix(irp, instruction);573 ir_print_prefix(irp, instruction);
539 switch (instruction->id) {574 switch (instruction->id) {
...@@ -645,9 +680,17 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -645,9 +680,17 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
645 ir_print_clz(irp, (IrInstructionClz *)instruction);680 ir_print_clz(irp, (IrInstructionClz *)instruction);
646 break;681 break;
647 case IrInstructionIdSwitchBr:682 case IrInstructionIdSwitchBr:
683 ir_print_switch_br(irp, (IrInstructionSwitchBr *)instruction);
684 break;
648 case IrInstructionIdSwitchVar:685 case IrInstructionIdSwitchVar:
686 ir_print_switch_var(irp, (IrInstructionSwitchVar *)instruction);
687 break;
649 case IrInstructionIdSwitchTarget:688 case IrInstructionIdSwitchTarget:
650 zig_panic("TODO print more IR instructions");689 ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction);
690 break;
691 case IrInstructionIdEnumTag:
692 ir_print_enum_tag(irp, (IrInstructionEnumTag *)instruction);
693 break;
651 }694 }
652 fprintf(irp->f, "\n");695 fprintf(irp->f, "\n");
653}696}