| ... | @@ -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 | } |
| 90 | | 90 | |
| 91 | static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint) { | 91 | static 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 | |
| | 98 | static 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 | } |
| 98 | | 103 | |
| 99 | static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) { | 104 | static 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 | } |
| 256 | | 261 | |
| | 262 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) { |
| | 263 | return IrInstructionIdEnumTag; |
| | 264 | } |
| | 265 | |
| 257 | template<typename T> | 266 | template<typename T> |
| 258 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { | 267 | static 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 |
| 612 | static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node, | 621 | static 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 | } |
| 1012 | | 1026 | |
| | 1027 | static 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 | |
| 1013 | static IrInstruction *ir_build_switch_target(IrBuilder *irb, AstNode *source_node, | 1037 | static 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 | } |
| 1036 | | 1060 | |
| | 1061 | static 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 | |
| | 1070 | static 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 | |
| 1037 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, | 1076 | static 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) { |
| 2149 | | 2188 | |
| 2150 | static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNode *prong_node, | 2189 | static 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 | } |
| 2191 | | 2230 | |
| ... | @@ -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; |
| 2224 | | 2263 | |
| | 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; |
| 2240 | | 2283 | |
| ... | @@ -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) { |
| 2280 | | 2323 | |
| 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 | } |
| 2287 | | 2330 | |
| 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; |
| 2297 | | 2343 | |
| 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; |
| 2311 | | 2347 | |
| 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 | } |
| 2718 | | 2781 | |
| | 2782 | static 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 | |
| 2719 | static void ir_finish_bb(IrAnalyze *ira) { | 2791 | static void ir_finish_bb(IrAnalyze *ira) { |
| 2720 | ira->block_queue_index += 1; | 2792 | ira->block_queue_index += 1; |
| 2721 | | 2793 | |
| 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 | } |
| 2730 | | 2801 | |
| 2731 | static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { | 2802 | static 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 | } |
| 2736 | | 2805 | |
| 2737 | static TypeTableEntry *ir_finish_anal(IrAnalyze *ira, TypeTableEntry *result_type) { | 2806 | static 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 | } |
| 3605 | | 3674 | |
| | 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 |
| 4072 | | 4143 | |
| 4073 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { | 4144 | static 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); |
| 4075 | | 4148 | |
| 4076 | // TODO detect backward jumps | 4149 | // TODO detect backward jumps |
| 4077 | | 4150 | |
| ... | @@ -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 |
| 4141 | | 4217 | |
| 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); |
| 4147 | | 4226 | |
| ... | @@ -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; |
| 4158 | | 4237 | |
| | 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 |
| 5114 | static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, | 5208 | static 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 | } |
| 5119 | | 5254 | |
| 5120 | static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, | 5255 | static 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 | } |
| 5125 | | 5329 | |
| 5126 | static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, | 5330 | static 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 | } |
| 5131 | | 5335 | |
| | 5336 | static 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 | |
| 5132 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 5342 | static 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); |
| 5254 | | 5466 | |
| 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 | { |