| ... | ... | @@ -110,21 +110,22 @@ static void ir_ref_var(VariableTableEntry *var) { |
| 110 | 110 | var->ref_count += 1; |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | | static IrBasicBlock *ir_build_basic_block_raw(IrBuilder *irb, const char *name_hint) { |
| 113 | static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) { |
| 114 | 114 | IrBasicBlock *result = allocate<IrBasicBlock>(1); |
| 115 | result->scope = scope; |
| 115 | 116 | result->name_hint = name_hint; |
| 116 | 117 | result->debug_id = exec_next_debug_id(irb->exec); |
| 117 | 118 | return result; |
| 118 | 119 | } |
| 119 | 120 | |
| 120 | | static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint) { |
| 121 | | IrBasicBlock *result = ir_build_basic_block_raw(irb, name_hint); |
| 121 | static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) { |
| 122 | IrBasicBlock *result = ir_create_basic_block(irb, scope, name_hint); |
| 122 | 123 | irb->exec->basic_block_list.append(result); |
| 123 | 124 | return result; |
| 124 | 125 | } |
| 125 | 126 | |
| 126 | 127 | static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) { |
| 127 | | IrBasicBlock *new_bb = ir_build_basic_block_raw(irb, other_bb->name_hint); |
| 128 | IrBasicBlock *new_bb = ir_create_basic_block(irb, other_bb->scope, other_bb->name_hint); |
| 128 | 129 | ir_link_new_bb(new_bb, other_bb); |
| 129 | 130 | return new_bb; |
| 130 | 131 | } |
| ... | ... | @@ -1240,19 +1241,21 @@ static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instr |
| 1240 | 1241 | return new_instruction; |
| 1241 | 1242 | } |
| 1242 | 1243 | |
| 1243 | | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *parent_scope, Scope *inner_scope, Scope *outer_scope, |
| 1244 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, |
| 1244 | 1245 | bool gen_error_defers, bool gen_maybe_defers) |
| 1245 | 1246 | { |
| 1246 | 1247 | while (inner_scope != outer_scope) { |
| 1248 | assert(inner_scope); |
| 1247 | 1249 | if (inner_scope->id == ScopeIdDefer) { |
| 1248 | | assert(inner_scope->source_node->type == NodeTypeDefer); |
| 1249 | | ReturnKind defer_kind = inner_scope->source_node->data.defer.kind; |
| 1250 | AstNode *defer_node = inner_scope->source_node; |
| 1251 | assert(defer_node->type == NodeTypeDefer); |
| 1252 | ReturnKind defer_kind = defer_node->data.defer.kind; |
| 1250 | 1253 | if (defer_kind == ReturnKindUnconditional || |
| 1251 | 1254 | (gen_error_defers && defer_kind == ReturnKindError) || |
| 1252 | 1255 | (gen_maybe_defers && defer_kind == ReturnKindMaybe)) |
| 1253 | 1256 | { |
| 1254 | | AstNode *defer_expr_node = inner_scope->source_node->data.defer.expr; |
| 1255 | | ir_gen_node(irb, defer_expr_node, parent_scope); |
| 1257 | AstNode *defer_expr_node = defer_node->data.defer.expr; |
| 1258 | ir_gen_node(irb, defer_expr_node, defer_node->data.defer.parent_scope); |
| 1256 | 1259 | } |
| 1257 | 1260 | |
| 1258 | 1261 | } |
| ... | ... | @@ -1263,7 +1266,8 @@ static void ir_gen_defers_for_block(IrBuilder *irb, Scope *parent_scope, Scope * |
| 1263 | 1266 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 1264 | 1267 | assert(node->type == NodeTypeReturnExpr); |
| 1265 | 1268 | |
| 1266 | | if (!exec_fn_entry(irb->exec)) { |
| 1269 | FnTableEntry *fn_entry = exec_fn_entry(irb->exec); |
| 1270 | if (!fn_entry) { |
| 1267 | 1271 | add_node_error(irb->codegen, node, buf_sprintf("return expression outside function definition")); |
| 1268 | 1272 | return irb->codegen->invalid_instruction; |
| 1269 | 1273 | } |
| ... | ... | @@ -1279,6 +1283,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node) |
| 1279 | 1283 | return_value = ir_build_const_void(irb, scope, node); |
| 1280 | 1284 | } |
| 1281 | 1285 | |
| 1286 | Scope *outer_scope = fn_entry->child_scope; |
| 1287 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); |
| 1282 | 1288 | return ir_build_return(irb, scope, node, return_value); |
| 1283 | 1289 | } |
| 1284 | 1290 | case ReturnKindError: |
| ... | ... | @@ -1385,7 +1391,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 1385 | 1391 | if (!return_value) |
| 1386 | 1392 | return_value = ir_build_const_void(irb, child_scope, block_node); |
| 1387 | 1393 | |
| 1388 | | ir_gen_defers_for_block(irb, parent_scope, child_scope, outer_block_scope, false, false); |
| 1394 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false, false); |
| 1389 | 1395 | |
| 1390 | 1396 | return return_value; |
| 1391 | 1397 | } |
| ... | ... | @@ -1433,9 +1439,9 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node |
| 1433 | 1439 | IrBasicBlock *post_val1_block = irb->current_basic_block; |
| 1434 | 1440 | |
| 1435 | 1441 | // block for when val1 == false |
| 1436 | | IrBasicBlock *false_block = ir_build_basic_block(irb, "BoolOrFalse"); |
| 1442 | IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolOrFalse"); |
| 1437 | 1443 | // block for when val1 == true (don't even evaluate the second part) |
| 1438 | | IrBasicBlock *true_block = ir_build_basic_block(irb, "BoolOrTrue"); |
| 1444 | IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolOrTrue"); |
| 1439 | 1445 | |
| 1440 | 1446 | ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_inline); |
| 1441 | 1447 | |
| ... | ... | @@ -1470,9 +1476,9 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod |
| 1470 | 1476 | IrBasicBlock *post_val1_block = irb->current_basic_block; |
| 1471 | 1477 | |
| 1472 | 1478 | // block for when val1 == true |
| 1473 | | IrBasicBlock *true_block = ir_build_basic_block(irb, "BoolAndTrue"); |
| 1479 | IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolAndTrue"); |
| 1474 | 1480 | // block for when val1 == false (don't even evaluate the second part) |
| 1475 | | IrBasicBlock *false_block = ir_build_basic_block(irb, "BoolAndFalse"); |
| 1481 | IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolAndFalse"); |
| 1476 | 1482 | |
| 1477 | 1483 | ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_inline); |
| 1478 | 1484 | |
| ... | ... | @@ -1935,9 +1941,9 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 1935 | 1941 | AstNode *then_node = node->data.if_bool_expr.then_block; |
| 1936 | 1942 | AstNode *else_node = node->data.if_bool_expr.else_node; |
| 1937 | 1943 | |
| 1938 | | IrBasicBlock *then_block = ir_build_basic_block(irb, "Then"); |
| 1939 | | IrBasicBlock *else_block = ir_build_basic_block(irb, "Else"); |
| 1940 | | IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf"); |
| 1944 | IrBasicBlock *then_block = ir_build_basic_block(irb, scope, "Then"); |
| 1945 | IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "Else"); |
| 1946 | IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "EndIf"); |
| 1941 | 1947 | |
| 1942 | 1948 | bool is_inline = ir_should_inline(irb) || node->data.if_bool_expr.is_inline; |
| 1943 | 1949 | ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_inline); |
| ... | ... | @@ -2124,11 +2130,11 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 2124 | 2130 | |
| 2125 | 2131 | AstNode *continue_expr_node = node->data.while_expr.continue_expr; |
| 2126 | 2132 | |
| 2127 | | IrBasicBlock *cond_block = ir_build_basic_block(irb, "WhileCond"); |
| 2128 | | IrBasicBlock *body_block = ir_build_basic_block(irb, "WhileBody"); |
| 2133 | IrBasicBlock *cond_block = ir_build_basic_block(irb, scope, "WhileCond"); |
| 2134 | IrBasicBlock *body_block = ir_build_basic_block(irb, scope, "WhileBody"); |
| 2129 | 2135 | IrBasicBlock *continue_block = continue_expr_node ? |
| 2130 | | ir_build_basic_block(irb, "WhileContinue") : cond_block; |
| 2131 | | IrBasicBlock *end_block = ir_build_basic_block(irb, "WhileEnd"); |
| 2136 | ir_build_basic_block(irb, scope, "WhileContinue") : cond_block; |
| 2137 | IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "WhileEnd"); |
| 2132 | 2138 | |
| 2133 | 2139 | bool is_inline = ir_should_inline(irb) || node->data.while_expr.is_inline; |
| 2134 | 2140 | ir_build_br(irb, scope, node, cond_block, is_inline); |
| ... | ... | @@ -2219,10 +2225,10 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 2219 | 2225 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var); |
| 2220 | 2226 | |
| 2221 | 2227 | |
| 2222 | | IrBasicBlock *cond_block = ir_build_basic_block(irb, "ForCond"); |
| 2223 | | IrBasicBlock *body_block = ir_build_basic_block(irb, "ForBody"); |
| 2224 | | IrBasicBlock *end_block = ir_build_basic_block(irb, "ForEnd"); |
| 2225 | | IrBasicBlock *continue_block = ir_build_basic_block(irb, "ForContinue"); |
| 2228 | IrBasicBlock *cond_block = ir_build_basic_block(irb, child_scope, "ForCond"); |
| 2229 | IrBasicBlock *body_block = ir_build_basic_block(irb, child_scope, "ForBody"); |
| 2230 | IrBasicBlock *end_block = ir_build_basic_block(irb, child_scope, "ForEnd"); |
| 2231 | IrBasicBlock *continue_block = ir_build_basic_block(irb, child_scope, "ForContinue"); |
| 2226 | 2232 | |
| 2227 | 2233 | IrInstruction *len_val = ir_build_array_len(irb, child_scope, node, array_val); |
| 2228 | 2234 | ir_build_br(irb, child_scope, node, cond_block, is_inline); |
| ... | ... | @@ -2404,9 +2410,9 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 2404 | 2410 | |
| 2405 | 2411 | IrInstruction *is_nonnull_value = ir_build_test_null(irb, scope, node, expr_value); |
| 2406 | 2412 | |
| 2407 | | IrBasicBlock *then_block = ir_build_basic_block(irb, "MaybeThen"); |
| 2408 | | IrBasicBlock *else_block = ir_build_basic_block(irb, "MaybeElse"); |
| 2409 | | IrBasicBlock *endif_block = ir_build_basic_block(irb, "MaybeEndIf"); |
| 2413 | IrBasicBlock *then_block = ir_build_basic_block(irb, scope, "MaybeThen"); |
| 2414 | IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "MaybeElse"); |
| 2415 | IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf"); |
| 2410 | 2416 | |
| 2411 | 2417 | bool is_inline = ir_should_inline(irb) || node->data.if_var_expr.is_inline; |
| 2412 | 2418 | ir_build_cond_br(irb, scope, node, is_nonnull_value, then_block, else_block, is_inline); |
| ... | ... | @@ -2506,8 +2512,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 2506 | 2512 | return target_value_ptr; |
| 2507 | 2513 | IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); |
| 2508 | 2514 | |
| 2509 | | IrBasicBlock *else_block = ir_build_basic_block(irb, "SwitchElse"); |
| 2510 | | IrBasicBlock *end_block = ir_build_basic_block(irb, "SwitchEnd"); |
| 2515 | IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "SwitchElse"); |
| 2516 | IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "SwitchEnd"); |
| 2511 | 2517 | |
| 2512 | 2518 | size_t prong_count = node->data.switch_expr.prongs.length; |
| 2513 | 2519 | ZigList<IrInstructionSwitchBrCase> cases = {0}; |
| ... | ... | @@ -2586,8 +2592,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 2586 | 2592 | } |
| 2587 | 2593 | } |
| 2588 | 2594 | |
| 2589 | | IrBasicBlock *range_block_yes = ir_build_basic_block(irb, "SwitchRangeYes"); |
| 2590 | | IrBasicBlock *range_block_no = ir_build_basic_block(irb, "SwitchRangeNo"); |
| 2595 | IrBasicBlock *range_block_yes = ir_build_basic_block(irb, scope, "SwitchRangeYes"); |
| 2596 | IrBasicBlock *range_block_no = ir_build_basic_block(irb, scope, "SwitchRangeNo"); |
| 2591 | 2597 | |
| 2592 | 2598 | assert(ok_bit); |
| 2593 | 2599 | assert(last_item_node); |
| ... | ... | @@ -2602,7 +2608,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 2602 | 2608 | |
| 2603 | 2609 | ir_set_cursor_at_end(irb, range_block_no); |
| 2604 | 2610 | } else { |
| 2605 | | IrBasicBlock *prong_block = ir_build_basic_block(irb, "SwitchProng"); |
| 2611 | IrBasicBlock *prong_block = ir_build_basic_block(irb, scope, "SwitchProng"); |
| 2606 | 2612 | IrInstruction *last_item_value = nullptr; |
| 2607 | 2613 | |
| 2608 | 2614 | for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { |
| ... | ... | @@ -2678,7 +2684,7 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, Scope *scope, AstNode *node) |
| 2678 | 2684 | assert(node->type == NodeTypeLabel); |
| 2679 | 2685 | |
| 2680 | 2686 | Buf *label_name = node->data.label.name; |
| 2681 | | IrBasicBlock *label_block = ir_build_basic_block(irb, buf_ptr(label_name)); |
| 2687 | IrBasicBlock *label_block = ir_build_basic_block(irb, scope, buf_ptr(label_name)); |
| 2682 | 2688 | LabelTableEntry *label = allocate<LabelTableEntry>(1); |
| 2683 | 2689 | label->decl_node = node; |
| 2684 | 2690 | label->bb = label_block; |
| ... | ... | @@ -2712,6 +2718,8 @@ static IrInstruction *ir_gen_goto(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 2712 | 2718 | goto_item->source_node = node; |
| 2713 | 2719 | goto_item->scope = scope; |
| 2714 | 2720 | |
| 2721 | // we don't know if we need to generate defer expressions yet |
| 2722 | // we do that later when we find out which label we're jumping to. |
| 2715 | 2723 | return ir_build_unreachable(irb, scope, node); |
| 2716 | 2724 | } |
| 2717 | 2725 | |
| ... | ... | @@ -2727,6 +2735,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node) |
| 2727 | 2735 | bool is_inline = ir_should_inline(irb) || node->data.break_expr.is_inline; |
| 2728 | 2736 | LoopStackItem *loop_stack_item = &irb->loop_stack.last(); |
| 2729 | 2737 | IrBasicBlock *dest_block = loop_stack_item->break_block; |
| 2738 | ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false); |
| 2730 | 2739 | return ir_build_br(irb, scope, node, dest_block, is_inline); |
| 2731 | 2740 | } |
| 2732 | 2741 | |
| ... | ... | @@ -2742,6 +2751,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod |
| 2742 | 2751 | bool is_inline = ir_should_inline(irb) || node->data.continue_expr.is_inline; |
| 2743 | 2752 | LoopStackItem *loop_stack_item = &irb->loop_stack.last(); |
| 2744 | 2753 | IrBasicBlock *dest_block = loop_stack_item->continue_block; |
| 2754 | ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false); |
| 2745 | 2755 | return ir_build_br(irb, scope, node, dest_block, is_inline); |
| 2746 | 2756 | } |
| 2747 | 2757 | |
| ... | ... | @@ -2761,6 +2771,16 @@ static IrInstruction *ir_gen_type_literal(IrBuilder *irb, Scope *scope, AstNode |
| 2761 | 2771 | return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_type); |
| 2762 | 2772 | } |
| 2763 | 2773 | |
| 2774 | static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
| 2775 | assert(node->type == NodeTypeDefer); |
| 2776 | |
| 2777 | ScopeDefer *defer_scope = create_defer_scope(node, parent_scope); |
| 2778 | node->data.defer.child_scope = &defer_scope->base; |
| 2779 | node->data.defer.parent_scope = parent_scope; |
| 2780 | |
| 2781 | return ir_build_const_void(irb, parent_scope, node); |
| 2782 | } |
| 2783 | |
| 2764 | 2784 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| 2765 | 2785 | LValPurpose lval) |
| 2766 | 2786 | { |
| ... | ... | @@ -2824,8 +2844,9 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 2824 | 2844 | return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval); |
| 2825 | 2845 | case NodeTypeContinue: |
| 2826 | 2846 | return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval); |
| 2827 | | case NodeTypeUnwrapErrorExpr: |
| 2828 | 2847 | case NodeTypeDefer: |
| 2848 | return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval); |
| 2849 | case NodeTypeUnwrapErrorExpr: |
| 2829 | 2850 | case NodeTypeSliceExpr: |
| 2830 | 2851 | case NodeTypeCharLiteral: |
| 2831 | 2852 | case NodeTypeZeroesLiteral: |
| ... | ... | @@ -2864,9 +2885,11 @@ static bool ir_goto_pass2(IrBuilder *irb) { |
| 2864 | 2885 | for (size_t i = 0; i < irb->exec->goto_list.length; i += 1) { |
| 2865 | 2886 | IrGotoItem *goto_item = &irb->exec->goto_list.at(i); |
| 2866 | 2887 | AstNode *source_node = goto_item->source_node; |
| 2867 | | size_t instruction_index = goto_item->instruction_index; |
| 2868 | | IrInstruction **slot = &goto_item->bb->instruction_list.at(instruction_index); |
| 2869 | | IrInstruction *old_instruction = *slot; |
| 2888 | |
| 2889 | // Since a goto will always end a basic block, we move the "current instruction" |
| 2890 | // index back to over the placeholder unreachable instruction and begin overwriting |
| 2891 | irb->current_basic_block = goto_item->bb; |
| 2892 | irb->current_basic_block->instruction_list.resize(goto_item->instruction_index); |
| 2870 | 2893 | |
| 2871 | 2894 | Buf *label_name = source_node->data.goto_expr.name; |
| 2872 | 2895 | LabelTableEntry *label = find_label(irb->exec, goto_item->scope, label_name); |
| ... | ... | @@ -2878,9 +2901,8 @@ static bool ir_goto_pass2(IrBuilder *irb) { |
| 2878 | 2901 | label->used = true; |
| 2879 | 2902 | |
| 2880 | 2903 | bool is_inline = ir_should_inline(irb) || source_node->data.goto_expr.is_inline; |
| 2881 | | IrInstruction *new_instruction = ir_create_br(irb, goto_item->scope, source_node, label->bb, is_inline); |
| 2882 | | new_instruction->ref_count = old_instruction->ref_count; |
| 2883 | | *slot = new_instruction; |
| 2904 | ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false, false); |
| 2905 | ir_build_br(irb, goto_item->scope, source_node, label->bb, is_inline); |
| 2884 | 2906 | } |
| 2885 | 2907 | |
| 2886 | 2908 | for (size_t i = 0; i < irb->exec->all_labels.length; i += 1) { |
| ... | ... | @@ -2905,7 +2927,7 @@ IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutabl |
| 2905 | 2927 | irb->codegen = codegen; |
| 2906 | 2928 | irb->exec = ir_executable; |
| 2907 | 2929 | |
| 2908 | | irb->current_basic_block = ir_build_basic_block(irb, "Entry"); |
| 2930 | irb->current_basic_block = ir_build_basic_block(irb, scope, "Entry"); |
| 2909 | 2931 | // Entry block gets a reference because we enter it to begin. |
| 2910 | 2932 | ir_ref_bb(irb->current_basic_block); |
| 2911 | 2933 | |
| ... | ... | @@ -7803,29 +7825,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 7803 | 7825 | // } |
| 7804 | 7826 | //} |
| 7805 | 7827 | // |
| 7806 | | //static TypeTableEntry *analyze_defer(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context, |
| 7807 | | // TypeTableEntry *expected_type, AstNode *node) |
| 7808 | | //{ |
| 7809 | | // if (!parent_context->fn_entry) { |
| 7810 | | // add_node_error(g, node, buf_sprintf("defer expression outside function definition")); |
| 7811 | | // return g->builtin_types.entry_invalid; |
| 7812 | | // } |
| 7813 | | // |
| 7814 | | // if (!node->data.defer.expr) { |
| 7815 | | // add_node_error(g, node, buf_sprintf("defer expects an expression")); |
| 7816 | | // return g->builtin_types.entry_void; |
| 7817 | | // } |
| 7818 | | // |
| 7819 | | // node->data.defer.child_block = new_block_context(node, parent_context); |
| 7820 | | // |
| 7821 | | // TypeTableEntry *resolved_type = analyze_expression(g, import, parent_context, nullptr, |
| 7822 | | // node->data.defer.expr); |
| 7823 | | // validate_voided_expr(g, node->data.defer.expr, resolved_type); |
| 7824 | | // |
| 7825 | | // return g->builtin_types.entry_void; |
| 7826 | | //} |
| 7827 | | // |
| 7828 | | // |
| 7829 | 7828 | //static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import, |
| 7830 | 7829 | // BlockContext *context, AstNode *node, Buf *err_name) |
| 7831 | 7830 | //{ |
| ... | ... | @@ -7849,38 +7848,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 7849 | 7848 | // } |
| 7850 | 7849 | //} |
| 7851 | 7850 | // |
| 7852 | | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { |
| 7853 | | // size_t result = 0; |
| 7854 | | // while (inner_block != outer_block) { |
| 7855 | | // if (inner_block->node->type == NodeTypeDefer && |
| 7856 | | // (inner_block->node->data.defer.kind == ReturnKindError || |
| 7857 | | // inner_block->node->data.defer.kind == ReturnKindMaybe)) |
| 7858 | | // { |
| 7859 | | // result += 1; |
| 7860 | | // } |
| 7861 | | // inner_block = inner_block->parent; |
| 7862 | | // } |
| 7863 | | // return result; |
| 7864 | | //} |
| 7865 | 7851 | |
| 7866 | 7852 | |
| 7867 | | //static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) { |
| 7868 | | // BlockContext *defer_inner_block = source_node->block_context; |
| 7869 | | // BlockContext *defer_outer_block = irb->node->block_context; |
| 7870 | | // if (rk == ReturnKnowledgeUnknown) { |
| 7871 | | // if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) { |
| 7872 | | // // generate branching code that checks the return value and generates defers |
| 7873 | | // // if the return value is error |
| 7874 | | // zig_panic("TODO"); |
| 7875 | | // } |
| 7876 | | // } else if (rk != ReturnKnowledgeSkipDefers) { |
| 7877 | | // ir_gen_defers_for_block(irb, defer_inner_block, defer_outer_block, |
| 7878 | | // rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull); |
| 7879 | | // } |
| 7880 | | // |
| 7881 | | // return ir_build_return(irb, source_node, value); |
| 7882 | | //} |
| 7883 | | // |
| 7884 | 7853 | //static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) { |
| 7885 | 7854 | // assert(node->type == NodeTypeFnCallExpr); |
| 7886 | 7855 | // assert(g->generate_error_name_table); |
| ... | ... | @@ -8400,21 +8369,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8400 | 8369 | // return phi; |
| 8401 | 8370 | //} |
| 8402 | 8371 | // |
| 8403 | | //static void gen_defers_for_block(CodeGen *g, BlockContext *inner_block, BlockContext *outer_block, |
| 8404 | | // bool gen_error_defers, bool gen_maybe_defers) |
| 8405 | | //{ |
| 8406 | | // while (inner_block != outer_block) { |
| 8407 | | // if (inner_block->node->type == NodeTypeDefer && |
| 8408 | | // ((inner_block->node->data.defer.kind == ReturnKindUnconditional) || |
| 8409 | | // (gen_error_defers && inner_block->node->data.defer.kind == ReturnKindError) || |
| 8410 | | // (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe))) |
| 8411 | | // { |
| 8412 | | // gen_expr(g, inner_block->node->data.defer.expr); |
| 8413 | | // } |
| 8414 | | // inner_block = inner_block->parent; |
| 8415 | | // } |
| 8416 | | //} |
| 8417 | | // |
| 8418 | 8372 | //static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 8419 | 8373 | // assert(node->type == NodeTypeReturnExpr); |
| 8420 | 8374 | // AstNode *param_node = node->data.return_expr.expr; |
| ... | ... | @@ -8529,30 +8483,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8529 | 8483 | // zig_unreachable(); |
| 8530 | 8484 | //} |
| 8531 | 8485 | // |
| 8532 | | //static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) { |
| 8533 | | // assert(block_node->type == NodeTypeBlock); |
| 8534 | | // |
| 8535 | | // LLVMValueRef return_value = nullptr; |
| 8536 | | // for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { |
| 8537 | | // AstNode *statement_node = block_node->data.block.statements.at(i); |
| 8538 | | // return_value = gen_expr(g, statement_node); |
| 8539 | | // } |
| 8540 | | // |
| 8541 | | // bool end_unreachable = implicit_return_type && implicit_return_type->id == TypeTableEntryIdUnreachable; |
| 8542 | | // if (end_unreachable) { |
| 8543 | | // return nullptr; |
| 8544 | | // } |
| 8545 | | // |
| 8546 | | // gen_defers_for_block(g, block_node->data.block.nested_block, block_node->data.block.child_block, |
| 8547 | | // false, false); |
| 8548 | | // |
| 8549 | | // if (implicit_return_type) { |
| 8550 | | // return gen_return(g, block_node, return_value, ReturnKnowledgeSkipDefers); |
| 8551 | | // } else { |
| 8552 | | // return return_value; |
| 8553 | | // } |
| 8554 | | //} |
| 8555 | | // |
| 8556 | 8486 | //static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl, |
| 8557 | 8487 | // bool unwrap_maybe, LLVMValueRef *init_value, TypeTableEntry **expr_type, bool var_is_ptr) |
| 8558 | 8488 | //{ |
| ... | ... | @@ -8691,37 +8621,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8691 | 8621 | // } |
| 8692 | 8622 | //} |
| 8693 | 8623 | // |
| 8694 | | //static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value, ReturnKnowledge rk) { |
| 8695 | | // BlockContext *defer_inner_block = source_node->block_context; |
| 8696 | | // BlockContext *defer_outer_block = source_node->block_context->fn_entry->fn_def_node->block_context; |
| 8697 | | // if (rk == ReturnKnowledgeUnknown) { |
| 8698 | | // if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) { |
| 8699 | | // // generate branching code that checks the return value and generates defers |
| 8700 | | // // if the return value is error |
| 8701 | | // zig_panic("TODO"); |
| 8702 | | // } |
| 8703 | | // } else if (rk != ReturnKnowledgeSkipDefers) { |
| 8704 | | // gen_defers_for_block(g, defer_inner_block, defer_outer_block, |
| 8705 | | // rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull); |
| 8706 | | // } |
| 8707 | | // |
| 8708 | | // TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; |
| 8709 | | // bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern; |
| 8710 | | // if (handle_is_ptr(return_type)) { |
| 8711 | | // if (is_extern) { |
| 8712 | | // LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, ""); |
| 8713 | | // LLVMBuildRet(g->builder, by_val_value); |
| 8714 | | // } else { |
| 8715 | | // assert(g->cur_ret_ptr); |
| 8716 | | // gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type); |
| 8717 | | // LLVMBuildRetVoid(g->builder); |
| 8718 | | // } |
| 8719 | | // } else { |
| 8720 | | // LLVMBuildRet(g->builder, value); |
| 8721 | | // } |
| 8722 | | // return nullptr; |
| 8723 | | //} |
| 8724 | | // |
| 8725 | 8624 | //static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { |
| 8726 | 8625 | // AstNode *init_expr = node->data.variable_declaration.expr; |
| 8727 | 8626 | // if (node->data.variable_declaration.is_const && init_expr) { |
| ... | ... | @@ -8763,17 +8662,3 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8763 | 8662 | // } |
| 8764 | 8663 | // zig_unreachable(); |
| 8765 | 8664 | //} |
| 8766 | | // |
| 8767 | | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { |
| 8768 | | // size_t result = 0; |
| 8769 | | // while (inner_block != outer_block) { |
| 8770 | | // if (inner_block->node->type == NodeTypeDefer && |
| 8771 | | // (inner_block->node->data.defer.kind == ReturnKindError || |
| 8772 | | // inner_block->node->data.defer.kind == ReturnKindMaybe)) |
| 8773 | | // { |
| 8774 | | // result += 1; |
| 8775 | | // } |
| 8776 | | // inner_block = inner_block->parent; |
| 8777 | | // } |
| 8778 | | // return result; |
| 8779 | | //} |