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 {
14551455 IrInstructionIdSizeOf,
14561456 IrInstructionIdTestNull,
14571457 IrInstructionIdUnwrapMaybe,
1458 IrInstructionIdEnumTag,
14581459 IrInstructionIdClz,
14591460 IrInstructionIdCtz,
14601461};
......@@ -1801,6 +1802,12 @@ struct IrInstructionClz {
18011802 IrInstruction *value;
18021803};
18031804
1805struct IrInstructionEnumTag {
1806 IrInstruction base;
1807
1808 IrInstruction *value;
1809};
1810
18041811enum LValPurpose {
18051812 LValPurposeNone,
18061813 LValPurposeAssign,
src/analyze.cpp-126
......@@ -2108,44 +2108,6 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
21082108 zig_unreachable();
21092109}
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
21492111bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
21502112 if (expected_type == actual_type)
21512113 return true;
......@@ -2233,94 +2195,6 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
22332195 return false;
22342196}
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
23242198BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
23252199 BlockContext *context = allocate<BlockContext>(1);
23262200 context->node = node;
src/ast_render.cpp+44-2
......@@ -354,6 +354,9 @@ static void render_node_ungrouped(AstRender *ar, AstNode *node) {
354354
355355static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
356356 switch (node->type) {
357 case NodeTypeSwitchProng:
358 case NodeTypeSwitchRange:
359 zig_unreachable();
357360 case NodeTypeRoot:
358361 for (size_t i = 0; i < node->data.root.top_level_decls.length; i += 1) {
359362 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) {
728731 break;
729732 }
730733 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 }
731775 case NodeTypeFnDecl:
732776 case NodeTypeParamDecl:
733777 case NodeTypeErrorValueDecl:
......@@ -738,8 +782,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
738782 case NodeTypeUse:
739783 case NodeTypeZeroesLiteral:
740784 case NodeTypeForExpr:
741 case NodeTypeSwitchProng:
742 case NodeTypeSwitchRange:
743785 case NodeTypeLabel:
744786 case NodeTypeGoto:
745787 case NodeTypeBreak:
src/codegen.cpp+30-2
......@@ -1638,6 +1638,31 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru
16381638 return LLVMBuildCall(g->builder, fn_val, params, 2, "");
16391639}
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
16411666static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
16421667 set_debug_source_node(g, instruction->source_node);
16431668
......@@ -1655,6 +1680,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
16551680 case IrInstructionIdSliceType:
16561681 case IrInstructionIdCompileVar:
16571682 case IrInstructionIdSizeOf:
1683 case IrInstructionIdSwitchTarget:
16581684 zig_unreachable();
16591685 case IrInstructionIdReturn:
16601686 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
......@@ -1695,12 +1721,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
16951721 case IrInstructionIdCtz:
16961722 return ir_render_ctz(g, executable, (IrInstructionCtz *)instruction);
16971723 case IrInstructionIdSwitchBr:
1698 case IrInstructionIdSwitchTarget:
1699 case IrInstructionIdSwitchVar:
1724 return ir_render_switch_br(g, executable, (IrInstructionSwitchBr *)instruction);
17001725 case IrInstructionIdPhi:
1726 return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);
1727 case IrInstructionIdSwitchVar:
17011728 case IrInstructionIdContainerInitList:
17021729 case IrInstructionIdContainerInitFields:
17031730 case IrInstructionIdReadField:
1731 case IrInstructionIdEnumTag:
17041732 zig_panic("TODO render more IR instructions to LLVM");
17051733 }
17061734 zig_unreachable();
src/ir.cpp+247-34
......@@ -88,16 +88,21 @@ static void ir_ref_var(VariableTableEntry *var) {
8888 var->ref_count += 1;
8989}
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) {
9292 IrBasicBlock *result = allocate<IrBasicBlock>(1);
9393 result->name_hint = name_hint;
9494 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);
95100 irb->exec->basic_block_list.append(result);
96101 return result;
97102}
98103
99104static 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);
101106 ir_link_new_bb(new_bb, other_bb);
102107 return new_bb;
103108}
......@@ -254,6 +259,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) {
254259 return IrInstructionIdCtz;
255260}
256261
262static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) {
263 return IrInstructionIdEnumTag;
264}
265
257266template<typename T>
258267static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
259268 T *special_instruction = allocate<T>(1);
......@@ -612,6 +621,9 @@ static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_inst
612621static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,
613622 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
614623{
624 assert(incoming_count != 0);
625 assert(incoming_count != SIZE_MAX);
626
615627 IrInstructionPhi *phi_instruction = ir_build_instruction<IrInstructionPhi>(irb, source_node);
616628 phi_instruction->incoming_count = incoming_count;
617629 phi_instruction->incoming_blocks = incoming_blocks;
......@@ -993,6 +1005,8 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, AstNode *source_node, I
9931005 IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, bool is_inline)
9941006{
9951007 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;
9961010 instruction->target_value = target_value;
9971011 instruction->else_block = else_block;
9981012 instruction->case_count = case_count;
......@@ -1010,6 +1024,16 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, AstNode *source_node, I
10101024 return &instruction->base;
10111025}
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
10131037static IrInstruction *ir_build_switch_target(IrBuilder *irb, AstNode *source_node,
10141038 IrInstruction *target_value_ptr)
10151039{
......@@ -1034,6 +1058,21 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, AstNode *source_node,
10341058 return &instruction->base;
10351059}
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
10371076static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
10381077 bool gen_error_defers, bool gen_maybe_defers)
10391078{
......@@ -2149,7 +2188,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, AstNode *node) {
21492188
21502189static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNode *prong_node,
21512190 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)
21532192{
21542193 assert(switch_node->type == NodeTypeSwitchExpr);
21552194 assert(prong_node->type == NodeTypeSwitchProng);
......@@ -2184,8 +2223,8 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNo
21842223 if (expr_result == irb->codegen->invalid_instruction)
21852224 return false;
21862225 ir_build_br(irb, switch_node, end_block, is_inline);
2187 incoming_blocks.append(irb->current_basic_block);
2188 incoming_values.append(expr_result);
2226 incoming_blocks->append(irb->current_basic_block);
2227 incoming_values->append(expr_result);
21892228 return true;
21902229}
21912230
......@@ -2222,11 +2261,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
22222261 }
22232262 else_prong = prong_node;
22242263
2264 IrBasicBlock *prev_block = irb->current_basic_block;
2265 ir_set_cursor_at_end(irb, else_block);
22252266 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))
22272268 {
22282269 return irb->codegen->invalid_instruction;
22292270 }
2271 ir_set_cursor_at_end(irb, prev_block);
22302272 } else {
22312273 if (prong_node->data.switch_prong.any_items_are_range) {
22322274 IrInstruction *ok_bit = nullptr;
......@@ -2235,6 +2277,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
22352277 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
22362278 last_item_node = item_node;
22372279 if (item_node->type == NodeTypeSwitchRange) {
2280 item_node->block_context = node->block_context;
22382281 AstNode *start_node = item_node->data.switch_range.start;
22392282 AstNode *end_node = item_node->data.switch_range.end;
22402283
......@@ -2252,7 +2295,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
22522295 IrInstruction *both_ok = ir_build_bin_op(irb, item_node, IrBinOpBoolAnd,
22532296 lower_range_ok, upper_range_ok);
22542297 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);
22562299 } else {
22572300 ok_bit = both_ok;
22582301 }
......@@ -2264,7 +2307,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
22642307 IrInstruction *cmp_ok = ir_build_bin_op(irb, item_node, IrBinOpCmpEq,
22652308 item_value, target_value);
22662309 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);
22682311 } else {
22692312 ok_bit = cmp_ok;
22702313 }
......@@ -2280,13 +2323,16 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
22802323
22812324 ir_set_cursor_at_end(irb, range_block_yes);
22822325 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))
22842327 {
22852328 return irb->codegen->invalid_instruction;
22862329 }
22872330
22882331 ir_set_cursor_at_end(irb, range_block_no);
22892332 } else {
2333 IrBasicBlock *prong_block = ir_build_basic_block(irb, "SwitchProng");
2334 IrInstruction *last_item_value = nullptr;
2335
22902336 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
22912337 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
22922338 assert(item_node->type != NodeTypeSwitchRange);
......@@ -2295,22 +2341,24 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) {
22952341 if (item_value == irb->codegen->invalid_instruction)
22962342 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
23082344 IrInstructionSwitchBrCase *this_case = cases.add_one();
23092345 this_case->value = item_value;
23102346 this_case->block = prong_block;
23112347
2312 ir_set_cursor_at_end(irb, prev_block);
2348 last_item_value = item_value;
23132349 }
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
23142362 }
23152363 }
23162364 }
......@@ -2712,26 +2760,47 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
27122760 if (old_bb->other)
27132761 return old_bb->other;
27142762 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 }
27152777 ira->old_bb_queue.append(old_bb);
2778
27162779 return new_bb;
27172780}
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
27192791static void ir_finish_bb(IrAnalyze *ira) {
27202792 ira->block_queue_index += 1;
27212793
27222794 if (ira->block_queue_index < ira->old_bb_queue.length) {
27232795 IrBasicBlock *old_bb = ira->old_bb_queue.at(ira->block_queue_index);
2724 ira->instruction_index = 0;
27252796 ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb);
2726 ira->old_irb.current_basic_block = old_bb;
2727 ira->const_predecessor_bb = nullptr;
2797
2798 ir_start_bb(ira, old_bb, nullptr);
27282799 }
27292800}
27302801
27312802static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
2732 ira->instruction_index = 0;
2733 ira->const_predecessor_bb = ira->old_irb.current_basic_block;
2734 ira->old_irb.current_basic_block = old_bb;
2803 ir_start_bb(ira, old_bb, ira->old_irb.current_basic_block);
27352804}
27362805
27372806static TypeTableEntry *ir_finish_anal(IrAnalyze *ira, TypeTableEntry *result_type) {
......@@ -3603,6 +3672,8 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
36033672 return explicit_type;
36043673 }
36053674
3675 AstNode *source_node = decl_var_instruction->base.source_node;
3676
36063677 IrInstruction *casted_init_value = ir_get_casted_value(ira, init_value, explicit_type);
36073678 TypeTableEntry *result_type = get_underlying_type(casted_init_value->type_entry);
36083679 switch (result_type->id) {
......@@ -3614,7 +3685,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
36143685 case TypeTableEntryIdNumLitFloat:
36153686 case TypeTableEntryIdNumLitInt:
36163687 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"));
36183689 result_type = ira->codegen->builtin_types.entry_invalid;
36193690 }
36203691 break;
......@@ -3622,14 +3693,14 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
36223693 case TypeTableEntryIdVar:
36233694 case TypeTableEntryIdBlock:
36243695 case TypeTableEntryIdNullLit:
3625 add_node_error(ira->codegen, var_type->source_node,
3696 add_node_error(ira->codegen, source_node,
36263697 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
36273698 result_type = ira->codegen->builtin_types.entry_invalid;
36283699 break;
36293700 case TypeTableEntryIdMetaType:
36303701 case TypeTableEntryIdNamespace:
36313702 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,
36333704 buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));
36343705 result_type = ira->codegen->builtin_types.entry_invalid;
36353706 }
......@@ -4072,6 +4143,8 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr
40724143
40734144static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
40744145 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
40764149 // TODO detect backward jumps
40774150
......@@ -4116,6 +4189,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
41164189 continue;
41174190 IrInstruction *value = phi_instruction->incoming_values[i]->other;
41184191 assert(value->type_entry);
4192 if (value->type_entry->id == TypeTableEntryIdInvalid)
4193 return ira->codegen->builtin_types.entry_invalid;
4194
41194195 if (value->static_value.special != ConstValSpecialRuntime) {
41204196 ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base,
41214197 value->static_value.depends_on_compile_var);
......@@ -4141,7 +4217,10 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
41414217
41424218 IrInstruction *old_value = phi_instruction->incoming_values[i];
41434219 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);
41454224 }
41464225 assert(new_incoming_blocks.length != 0);
41474226
......@@ -4156,6 +4235,21 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
41564235 if (resolved_type->id == TypeTableEntryIdInvalid)
41574236 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
41594253 ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length,
41604254 new_incoming_blocks.items, new_incoming_values.items);
41614255 return resolved_type;
......@@ -5114,13 +5208,123 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC
51145208static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
51155209 IrInstructionSwitchBr *switch_br_instruction)
51165210{
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);
51185253}
51195254
51205255static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
51215256 IrInstructionSwitchTarget *switch_target_instruction)
51225257{
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();
51245328}
51255329
51265330static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira,
......@@ -5129,6 +5333,12 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira,
51295333 zig_panic("TODO switch var analyze");
51305334}
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
51325342static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
51335343 switch (instruction->id) {
51345344 case IrInstructionIdInvalid:
......@@ -5201,6 +5411,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
52015411 return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction);
52025412 case IrInstructionIdSwitchVar:
52035413 return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction);
5414 case IrInstructionIdEnumTag:
5415 return ir_analyze_instruction_enum_tag(ira, (IrInstructionEnumTag *)instruction);
52045416 case IrInstructionIdCast:
52055417 case IrInstructionIdContainerInitList:
52065418 case IrInstructionIdContainerInitFields:
......@@ -5247,10 +5459,10 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
52475459 IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0);
52485460 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb);
52495461 ir_ref_bb(new_entry_bb);
5250 ira->old_irb.current_basic_block = old_entry_bb;
52515462 ira->new_irb.current_basic_block = new_entry_bb;
52525463 ira->block_queue_index = 0;
5253 ira->instruction_index = 0;
5464
5465 ir_start_bb(ira, old_entry_bb, nullptr);
52545466
52555467 while (ira->block_queue_index < ira->old_bb_queue.length) {
52565468 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) {
53195531 case IrInstructionIdCtz:
53205532 case IrInstructionIdSwitchVar:
53215533 case IrInstructionIdSwitchTarget:
5534 case IrInstructionIdEnumTag:
53225535 return false;
53235536 case IrInstructionIdAsm:
53245537 {
src/ir_print.cpp+44-1
......@@ -313,6 +313,8 @@ static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
313313}
314314
315315static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
316 assert(phi_instruction->incoming_count != 0);
317 assert(phi_instruction->incoming_count != SIZE_MAX);
316318 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
317319 IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];
318320 IrInstruction *incoming_value = phi_instruction->incoming_values[i];
......@@ -534,6 +536,39 @@ static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {
534536 fprintf(irp->f, ")");
535537}
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
537572static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
538573 ir_print_prefix(irp, instruction);
539574 switch (instruction->id) {
......@@ -645,9 +680,17 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
645680 ir_print_clz(irp, (IrInstructionClz *)instruction);
646681 break;
647682 case IrInstructionIdSwitchBr:
683 ir_print_switch_br(irp, (IrInstructionSwitchBr *)instruction);
684 break;
648685 case IrInstructionIdSwitchVar:
686 ir_print_switch_var(irp, (IrInstructionSwitchVar *)instruction);
687 break;
649688 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;
651694 }
652695 fprintf(irp->f, "\n");
653696}