| ... | @@ -117,6 +117,7 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { | ... | @@ -117,6 +117,7 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { |
| 117 | | 117 | |
| 118 | var top_scope: Scope.Top = .{}; | 118 | var top_scope: Scope.Top = .{}; |
| 119 | | 119 | |
| | 120 | var gz_instructions: std.ArrayListUnmanaged(Zir.Inst.Index) = .{}; |
| 120 | var gen_scope: GenZir = .{ | 121 | var gen_scope: GenZir = .{ |
| 121 | .force_comptime = true, | 122 | .force_comptime = true, |
| 122 | .in_defer = false, | 123 | .in_defer = false, |
| ... | @@ -125,8 +126,10 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { | ... | @@ -125,8 +126,10 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { |
| 125 | .decl_node_index = 0, | 126 | .decl_node_index = 0, |
| 126 | .decl_line = 0, | 127 | .decl_line = 0, |
| 127 | .astgen = &astgen, | 128 | .astgen = &astgen, |
| | 129 | .instructions = &gz_instructions, |
| | 130 | .instructions_top = 0, |
| 128 | }; | 131 | }; |
| 129 | defer gen_scope.instructions.deinit(gpa); | 132 | defer gz_instructions.deinit(gpa); |
| 130 | | 133 | |
| 131 | const container_decl: Ast.full.ContainerDecl = .{ | 134 | const container_decl: Ast.full.ContainerDecl = .{ |
| 132 | .layout_token = null, | 135 | .layout_token = null, |
| ... | @@ -1041,12 +1044,12 @@ fn suspendExpr( | ... | @@ -1041,12 +1044,12 @@ fn suspendExpr( |
| 1041 | } | 1044 | } |
| 1042 | assert(body_node != 0); | 1045 | assert(body_node != 0); |
| 1043 | | 1046 | |
| 1044 | const suspend_inst = try gz.addBlock(.suspend_block, node); | 1047 | const suspend_inst = try gz.makeBlockInst(.suspend_block, node); |
| 1045 | try gz.instructions.append(gpa, suspend_inst); | 1048 | try gz.instructions.append(gpa, suspend_inst); |
| 1046 | | 1049 | |
| 1047 | var suspend_scope = gz.makeSubBlock(scope); | 1050 | var suspend_scope = gz.makeSubBlock(scope); |
| 1048 | suspend_scope.suspend_node = node; | 1051 | suspend_scope.suspend_node = node; |
| 1049 | defer suspend_scope.instructions.deinit(gpa); | 1052 | defer suspend_scope.unstack(); |
| 1050 | | 1053 | |
| 1051 | const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node); | 1054 | const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node); |
| 1052 | if (!gz.refIsNoReturn(body_result)) { | 1055 | if (!gz.refIsNoReturn(body_result)) { |
| ... | @@ -1101,7 +1104,6 @@ fn fnProtoExpr( | ... | @@ -1101,7 +1104,6 @@ fn fnProtoExpr( |
| 1101 | fn_proto: Ast.full.FnProto, | 1104 | fn_proto: Ast.full.FnProto, |
| 1102 | ) InnerError!Zir.Inst.Ref { | 1105 | ) InnerError!Zir.Inst.Ref { |
| 1103 | const astgen = gz.astgen; | 1106 | const astgen = gz.astgen; |
| 1104 | const gpa = astgen.gpa; | | |
| 1105 | const tree = astgen.tree; | 1107 | const tree = astgen.tree; |
| 1106 | const token_tags = tree.tokens.items(.tag); | 1108 | const token_tags = tree.tokens.items(.tag); |
| 1107 | | 1109 | |
| ... | @@ -1147,14 +1149,14 @@ fn fnProtoExpr( | ... | @@ -1147,14 +1149,14 @@ fn fnProtoExpr( |
| 1147 | const param_type_node = param.type_expr; | 1149 | const param_type_node = param.type_expr; |
| 1148 | assert(param_type_node != 0); | 1150 | assert(param_type_node != 0); |
| 1149 | var param_gz = gz.makeSubBlock(scope); | 1151 | var param_gz = gz.makeSubBlock(scope); |
| 1150 | defer param_gz.instructions.deinit(gpa); | 1152 | defer param_gz.unstack(); |
| 1151 | const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node); | 1153 | const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node); |
| 1152 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); | 1154 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); |
| 1153 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); | 1155 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); |
| 1154 | const main_tokens = tree.nodes.items(.main_token); | 1156 | const main_tokens = tree.nodes.items(.main_token); |
| 1155 | const name_token = param.name_token orelse main_tokens[param_type_node]; | 1157 | const name_token = param.name_token orelse main_tokens[param_type_node]; |
| 1156 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; | 1158 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 1157 | const param_inst = try gz.addParam(tag, name_token, param_name, param_gz.instructions.items); | 1159 | const param_inst = try gz.addParam(&param_gz, tag, name_token, param_name); |
| 1158 | assert(param_inst_expected == param_inst); | 1160 | assert(param_inst_expected == param_inst); |
| 1159 | } | 1161 | } |
| 1160 | } | 1162 | } |
| ... | @@ -1189,16 +1191,16 @@ fn fnProtoExpr( | ... | @@ -1189,16 +1191,16 @@ fn fnProtoExpr( |
| 1189 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); | 1191 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); |
| 1190 | } | 1192 | } |
| 1191 | var ret_gz = gz.makeSubBlock(scope); | 1193 | var ret_gz = gz.makeSubBlock(scope); |
| 1192 | defer ret_gz.instructions.deinit(gpa); | 1194 | defer ret_gz.unstack(); |
| 1193 | const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type); | 1195 | const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type); |
| 1194 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); | 1196 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); |
| 1195 | | 1197 | |
| 1196 | const result = try gz.addFunc(.{ | 1198 | const result = try gz.addFunc(.{ |
| 1197 | .src_node = fn_proto.ast.proto_node, | 1199 | .src_node = fn_proto.ast.proto_node, |
| 1198 | .param_block = 0, | 1200 | .param_block = 0, |
| 1199 | .ret_ty = ret_gz.instructions.items, | 1201 | .ret_gz = &ret_gz, |
| 1200 | .ret_br = ret_br, | 1202 | .ret_br = ret_br, |
| 1201 | .body = &[0]Zir.Inst.Index{}, | 1203 | .body_gz = null, |
| 1202 | .cc = cc, | 1204 | .cc = cc, |
| 1203 | .align_inst = align_inst, | 1205 | .align_inst = align_inst, |
| 1204 | .lib_name = 0, | 1206 | .lib_name = 0, |
| ... | @@ -1376,7 +1378,7 @@ fn arrayInitExprRlPtr( | ... | @@ -1376,7 +1378,7 @@ fn arrayInitExprRlPtr( |
| 1376 | } | 1378 | } |
| 1377 | | 1379 | |
| 1378 | var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr); | 1380 | var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr); |
| 1379 | defer as_scope.instructions.deinit(gz.astgen.gpa); | 1381 | defer as_scope.unstack(); |
| 1380 | | 1382 | |
| 1381 | const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements); | 1383 | const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements); |
| 1382 | return as_scope.finishCoercion(gz, rl, node, result, array_ty); | 1384 | return as_scope.finishCoercion(gz, rl, node, result, array_ty); |
| ... | @@ -1554,7 +1556,7 @@ fn structInitExprRlPtr( | ... | @@ -1554,7 +1556,7 @@ fn structInitExprRlPtr( |
| 1554 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | 1556 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1555 | | 1557 | |
| 1556 | var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr); | 1558 | var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr); |
| 1557 | defer as_scope.instructions.deinit(gz.astgen.gpa); | 1559 | defer as_scope.unstack(); |
| 1558 | | 1560 | |
| 1559 | const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr); | 1561 | const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr); |
| 1560 | return as_scope.finishCoercion(gz, rl, node, result, ty_inst); | 1562 | return as_scope.finishCoercion(gz, rl, node, result, ty_inst); |
| ... | @@ -1875,7 +1877,7 @@ fn labeledBlockExpr( | ... | @@ -1875,7 +1877,7 @@ fn labeledBlockExpr( |
| 1875 | | 1877 | |
| 1876 | // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct | 1878 | // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct |
| 1877 | // so that break statements can reference it. | 1879 | // so that break statements can reference it. |
| 1878 | const block_inst = try gz.addBlock(zir_tag, block_node); | 1880 | const block_inst = try gz.makeBlockInst(zir_tag, block_node); |
| 1879 | try gz.instructions.append(astgen.gpa, block_inst); | 1881 | try gz.instructions.append(astgen.gpa, block_inst); |
| 1880 | | 1882 | |
| 1881 | var block_scope = gz.makeSubBlock(parent_scope); | 1883 | var block_scope = gz.makeSubBlock(parent_scope); |
| ... | @@ -1884,7 +1886,7 @@ fn labeledBlockExpr( | ... | @@ -1884,7 +1886,7 @@ fn labeledBlockExpr( |
| 1884 | .block_inst = block_inst, | 1886 | .block_inst = block_inst, |
| 1885 | }; | 1887 | }; |
| 1886 | block_scope.setBreakResultLoc(rl); | 1888 | block_scope.setBreakResultLoc(rl); |
| 1887 | defer block_scope.instructions.deinit(astgen.gpa); | 1889 | defer block_scope.unstack(); |
| 1888 | defer block_scope.labeled_breaks.deinit(astgen.gpa); | 1890 | defer block_scope.labeled_breaks.deinit(astgen.gpa); |
| 1889 | defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); | 1891 | defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 1890 | | 1892 | |
| ... | @@ -2489,7 +2491,6 @@ fn varDecl( | ... | @@ -2489,7 +2491,6 @@ fn varDecl( |
| 2489 | ) InnerError!*Scope { | 2491 | ) InnerError!*Scope { |
| 2490 | try emitDbgNode(gz, node); | 2492 | try emitDbgNode(gz, node); |
| 2491 | const astgen = gz.astgen; | 2493 | const astgen = gz.astgen; |
| 2492 | const gpa = astgen.gpa; | | |
| 2493 | const tree = astgen.tree; | 2494 | const tree = astgen.tree; |
| 2494 | const token_tags = tree.tokens.items(.tag); | 2495 | const token_tags = tree.tokens.items(.tag); |
| 2495 | const main_tokens = tree.nodes.items(.main_token); | 2496 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -2550,7 +2551,9 @@ fn varDecl( | ... | @@ -2550,7 +2551,9 @@ fn varDecl( |
| 2550 | // Detect whether the initialization expression actually uses the | 2551 | // Detect whether the initialization expression actually uses the |
| 2551 | // result location pointer. | 2552 | // result location pointer. |
| 2552 | var init_scope = gz.makeSubBlock(scope); | 2553 | var init_scope = gz.makeSubBlock(scope); |
| 2553 | defer init_scope.instructions.deinit(gpa); | 2554 | // we may add more instructions to gz before stacking init_scope |
| | 2555 | init_scope.instructions_top = GenZir.unstacked_top; |
| | 2556 | defer init_scope.unstack(); |
| 2554 | | 2557 | |
| 2555 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; | 2558 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; |
| 2556 | var opt_type_inst: Zir.Inst.Ref = .none; | 2559 | var opt_type_inst: Zir.Inst.Ref = .none; |
| ... | @@ -2558,6 +2561,7 @@ fn varDecl( | ... | @@ -2558,6 +2561,7 @@ fn varDecl( |
| 2558 | const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node); | 2561 | const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node); |
| 2559 | opt_type_inst = type_inst; | 2562 | opt_type_inst = type_inst; |
| 2560 | if (align_inst == .none) { | 2563 | if (align_inst == .none) { |
| | 2564 | init_scope.instructions_top = gz.instructions.items.len; |
| 2561 | init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node); | 2565 | init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node); |
| 2562 | } else { | 2566 | } else { |
| 2563 | init_scope.rl_ptr = try gz.addAllocExtended(.{ | 2567 | init_scope.rl_ptr = try gz.addAllocExtended(.{ |
| ... | @@ -2567,19 +2571,24 @@ fn varDecl( | ... | @@ -2567,19 +2571,24 @@ fn varDecl( |
| 2567 | .is_const = true, | 2571 | .is_const = true, |
| 2568 | .is_comptime = false, | 2572 | .is_comptime = false, |
| 2569 | }); | 2573 | }); |
| | 2574 | init_scope.instructions_top = gz.instructions.items.len; |
| 2570 | } | 2575 | } |
| 2571 | init_scope.rl_ty_inst = type_inst; | 2576 | init_scope.rl_ty_inst = type_inst; |
| 2572 | } else { | 2577 | } else { |
| 2573 | const alloc = if (align_inst == .none) | 2578 | const alloc = if (align_inst == .none) alloc: { |
| 2574 | try init_scope.addNode(.alloc_inferred, node) | 2579 | init_scope.instructions_top = gz.instructions.items.len; |
| 2575 | else | 2580 | break :alloc try init_scope.addNode(.alloc_inferred, node); |
| 2576 | try gz.addAllocExtended(.{ | 2581 | } else alloc: { |
| | 2582 | const ref = try gz.addAllocExtended(.{ |
| 2577 | .node = node, | 2583 | .node = node, |
| 2578 | .type_inst = .none, | 2584 | .type_inst = .none, |
| 2579 | .align_inst = align_inst, | 2585 | .align_inst = align_inst, |
| 2580 | .is_const = true, | 2586 | .is_const = true, |
| 2581 | .is_comptime = false, | 2587 | .is_comptime = false, |
| 2582 | }); | 2588 | }); |
| | 2589 | init_scope.instructions_top = gz.instructions.items.len; |
| | 2590 | break :alloc ref; |
| | 2591 | }; |
| 2583 | resolve_inferred_alloc = alloc; | 2592 | resolve_inferred_alloc = alloc; |
| 2584 | init_scope.rl_ptr = alloc; | 2593 | init_scope.rl_ptr = alloc; |
| 2585 | } | 2594 | } |
| ... | @@ -2589,20 +2598,24 @@ fn varDecl( | ... | @@ -2589,20 +2598,24 @@ fn varDecl( |
| 2589 | const zir_tags = astgen.instructions.items(.tag); | 2598 | const zir_tags = astgen.instructions.items(.tag); |
| 2590 | const zir_datas = astgen.instructions.items(.data); | 2599 | const zir_datas = astgen.instructions.items(.data); |
| 2591 | | 2600 | |
| 2592 | const parent_zir = &gz.instructions; | | |
| 2593 | if (align_inst == .none and init_scope.rvalue_rl_count == 1) { | 2601 | if (align_inst == .none and init_scope.rvalue_rl_count == 1) { |
| 2594 | // Result location pointer not used. We don't need an alloc for this | 2602 | // Result location pointer not used. We don't need an alloc for this |
| 2595 | // const local, and type inference becomes trivial. | 2603 | // const local, and type inference becomes trivial. |
| 2596 | // Move the init_scope instructions into the parent scope, eliding | 2604 | // Implicitly move the init_scope instructions into the parent scope, |
| 2597 | // the alloc instruction and the store_to_block_ptr instruction. | 2605 | // then elide the alloc instruction and the store_to_block_ptr instruction. |
| 2598 | try parent_zir.ensureUnusedCapacity(gpa, init_scope.instructions.items.len); | 2606 | var src = init_scope.instructions_top; |
| 2599 | for (init_scope.instructions.items) |src_inst| { | 2607 | var dst = src; |
| | 2608 | init_scope.instructions_top = GenZir.unstacked_top; |
| | 2609 | while (src < gz.instructions.items.len) : (src += 1) { |
| | 2610 | const src_inst = gz.instructions.items[src]; |
| 2600 | if (indexToRef(src_inst) == init_scope.rl_ptr) continue; | 2611 | if (indexToRef(src_inst) == init_scope.rl_ptr) continue; |
| 2601 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 2612 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 2602 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue; | 2613 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue; |
| 2603 | } | 2614 | } |
| 2604 | parent_zir.appendAssumeCapacity(src_inst); | 2615 | gz.instructions.items[dst] = src_inst; |
| | 2616 | dst += 1; |
| 2605 | } | 2617 | } |
| | 2618 | gz.instructions.items.len = dst; |
| 2606 | | 2619 | |
| 2607 | const sub_scope = try block_arena.create(Scope.LocalVal); | 2620 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| 2608 | sub_scope.* = .{ | 2621 | sub_scope.* = .{ |
| ... | @@ -2617,11 +2630,13 @@ fn varDecl( | ... | @@ -2617,11 +2630,13 @@ fn varDecl( |
| 2617 | } | 2630 | } |
| 2618 | // The initialization expression took advantage of the result location | 2631 | // The initialization expression took advantage of the result location |
| 2619 | // of the const local. In this case we will create an alloc and a LocalPtr for it. | 2632 | // of the const local. In this case we will create an alloc and a LocalPtr for it. |
| 2620 | // Move the init_scope instructions into the parent scope, swapping | 2633 | // Implicitly move the init_scope instructions into the parent scope, then swap |
| 2621 | // store_to_block_ptr for store_to_inferred_ptr. | 2634 | // store_to_block_ptr for store_to_inferred_ptr. |
| 2622 | const expected_len = parent_zir.items.len + init_scope.instructions.items.len; | 2635 | |
| 2623 | try parent_zir.ensureTotalCapacity(gpa, expected_len); | 2636 | var src = init_scope.instructions_top; |
| 2624 | for (init_scope.instructions.items) |src_inst| { | 2637 | init_scope.instructions_top = GenZir.unstacked_top; |
| | 2638 | while (src < gz.instructions.items.len) : (src += 1) { |
| | 2639 | const src_inst = gz.instructions.items[src]; |
| 2625 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 2640 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 2626 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) { | 2641 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) { |
| 2627 | if (var_decl.ast.type_node != 0) { | 2642 | if (var_decl.ast.type_node != 0) { |
| ... | @@ -2631,9 +2646,7 @@ fn varDecl( | ... | @@ -2631,9 +2646,7 @@ fn varDecl( |
| 2631 | } | 2646 | } |
| 2632 | } | 2647 | } |
| 2633 | } | 2648 | } |
| 2634 | parent_zir.appendAssumeCapacity(src_inst); | | |
| 2635 | } | 2649 | } |
| 2636 | assert(parent_zir.items.len == expected_len); | | |
| 2637 | if (resolve_inferred_alloc != .none) { | 2650 | if (resolve_inferred_alloc != .none) { |
| 2638 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); | 2651 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 2639 | } | 2652 | } |
| ... | @@ -3120,7 +3133,6 @@ fn fnDecl( | ... | @@ -3120,7 +3133,6 @@ fn fnDecl( |
| 3120 | body_node: Ast.Node.Index, | 3133 | body_node: Ast.Node.Index, |
| 3121 | fn_proto: Ast.full.FnProto, | 3134 | fn_proto: Ast.full.FnProto, |
| 3122 | ) InnerError!void { | 3135 | ) InnerError!void { |
| 3123 | const gpa = astgen.gpa; | | |
| 3124 | const tree = astgen.tree; | 3136 | const tree = astgen.tree; |
| 3125 | const token_tags = tree.tokens.items(.tag); | 3137 | const token_tags = tree.tokens.items(.tag); |
| 3126 | | 3138 | |
| ... | @@ -3130,7 +3142,7 @@ fn fnDecl( | ... | @@ -3130,7 +3142,7 @@ fn fnDecl( |
| 3130 | | 3142 | |
| 3131 | // We insert this at the beginning so that its instruction index marks the | 3143 | // We insert this at the beginning so that its instruction index marks the |
| 3132 | // start of the top level declaration. | 3144 | // start of the top level declaration. |
| 3133 | const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node); | 3145 | const block_inst = try gz.makeBlockInst(.block_inline, fn_proto.ast.proto_node); |
| 3134 | | 3146 | |
| 3135 | var decl_gz: GenZir = .{ | 3147 | var decl_gz: GenZir = .{ |
| 3136 | .force_comptime = true, | 3148 | .force_comptime = true, |
| ... | @@ -3139,8 +3151,10 @@ fn fnDecl( | ... | @@ -3139,8 +3151,10 @@ fn fnDecl( |
| 3139 | .decl_line = gz.calcLine(decl_node), | 3151 | .decl_line = gz.calcLine(decl_node), |
| 3140 | .parent = scope, | 3152 | .parent = scope, |
| 3141 | .astgen = astgen, | 3153 | .astgen = astgen, |
| | 3154 | .instructions = gz.instructions, |
| | 3155 | .instructions_top = gz.instructions.items.len, |
| 3142 | }; | 3156 | }; |
| 3143 | defer decl_gz.instructions.deinit(gpa); | 3157 | defer decl_gz.unstack(); |
| 3144 | | 3158 | |
| 3145 | var fn_gz: GenZir = .{ | 3159 | var fn_gz: GenZir = .{ |
| 3146 | .force_comptime = false, | 3160 | .force_comptime = false, |
| ... | @@ -3149,8 +3163,10 @@ fn fnDecl( | ... | @@ -3149,8 +3163,10 @@ fn fnDecl( |
| 3149 | .decl_line = decl_gz.decl_line, | 3163 | .decl_line = decl_gz.decl_line, |
| 3150 | .parent = &decl_gz.base, | 3164 | .parent = &decl_gz.base, |
| 3151 | .astgen = astgen, | 3165 | .astgen = astgen, |
| | 3166 | .instructions = gz.instructions, |
| | 3167 | .instructions_top = GenZir.unstacked_top, |
| 3152 | }; | 3168 | }; |
| 3153 | defer fn_gz.instructions.deinit(gpa); | 3169 | defer fn_gz.unstack(); |
| 3154 | | 3170 | |
| 3155 | // TODO: support noinline | 3171 | // TODO: support noinline |
| 3156 | const is_pub = fn_proto.visib_token != null; | 3172 | const is_pub = fn_proto.visib_token != null; |
| ... | @@ -3216,7 +3232,7 @@ fn fnDecl( | ... | @@ -3216,7 +3232,7 @@ fn fnDecl( |
| 3216 | const param_type_node = param.type_expr; | 3232 | const param_type_node = param.type_expr; |
| 3217 | assert(param_type_node != 0); | 3233 | assert(param_type_node != 0); |
| 3218 | var param_gz = decl_gz.makeSubBlock(scope); | 3234 | var param_gz = decl_gz.makeSubBlock(scope); |
| 3219 | defer param_gz.instructions.deinit(gpa); | 3235 | defer param_gz.unstack(); |
| 3220 | const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node); | 3236 | const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node); |
| 3221 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); | 3237 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); |
| 3222 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); | 3238 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); |
| ... | @@ -3224,7 +3240,7 @@ fn fnDecl( | ... | @@ -3224,7 +3240,7 @@ fn fnDecl( |
| 3224 | const main_tokens = tree.nodes.items(.main_token); | 3240 | const main_tokens = tree.nodes.items(.main_token); |
| 3225 | const name_token = param.name_token orelse main_tokens[param_type_node]; | 3241 | const name_token = param.name_token orelse main_tokens[param_type_node]; |
| 3226 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; | 3242 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 3227 | const param_inst = try decl_gz.addParam(tag, name_token, param_name, param_gz.instructions.items); | 3243 | const param_inst = try decl_gz.addParam(&param_gz, tag, name_token, param_name); |
| 3228 | assert(param_inst_expected == param_inst); | 3244 | assert(param_inst_expected == param_inst); |
| 3229 | break :param indexToRef(param_inst); | 3245 | break :param indexToRef(param_inst); |
| 3230 | }; | 3246 | }; |
| ... | @@ -3289,7 +3305,7 @@ fn fnDecl( | ... | @@ -3289,7 +3305,7 @@ fn fnDecl( |
| 3289 | }; | 3305 | }; |
| 3290 | | 3306 | |
| 3291 | var ret_gz = decl_gz.makeSubBlock(params_scope); | 3307 | var ret_gz = decl_gz.makeSubBlock(params_scope); |
| 3292 | defer ret_gz.instructions.deinit(gpa); | 3308 | defer ret_gz.unstack(); |
| 3293 | const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); | 3309 | const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); |
| 3294 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); | 3310 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); |
| 3295 | | 3311 | |
| ... | @@ -3302,10 +3318,10 @@ fn fnDecl( | ... | @@ -3302,10 +3318,10 @@ fn fnDecl( |
| 3302 | } | 3318 | } |
| 3303 | break :func try decl_gz.addFunc(.{ | 3319 | break :func try decl_gz.addFunc(.{ |
| 3304 | .src_node = decl_node, | 3320 | .src_node = decl_node, |
| 3305 | .ret_ty = ret_gz.instructions.items, | 3321 | .ret_gz = &ret_gz, |
| 3306 | .ret_br = ret_br, | 3322 | .ret_br = ret_br, |
| 3307 | .param_block = block_inst, | 3323 | .param_block = block_inst, |
| 3308 | .body = &[0]Zir.Inst.Index{}, | 3324 | .body_gz = null, |
| 3309 | .cc = cc, | 3325 | .cc = cc, |
| 3310 | .align_inst = .none, // passed in the per-decl data | 3326 | .align_inst = .none, // passed in the per-decl data |
| 3311 | .lib_name = lib_name, | 3327 | .lib_name = lib_name, |
| ... | @@ -3319,6 +3335,9 @@ fn fnDecl( | ... | @@ -3319,6 +3335,9 @@ fn fnDecl( |
| 3319 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{}); | 3335 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{}); |
| 3320 | } | 3336 | } |
| 3321 | | 3337 | |
| | 3338 | // as a scope, fn_gz encloses ret_gz, but for instruction list, fn_gz stacks on ret_gz |
| | 3339 | fn_gz.instructions_top = ret_gz.instructions.items.len; |
| | 3340 | |
| 3322 | const prev_fn_block = astgen.fn_block; | 3341 | const prev_fn_block = astgen.fn_block; |
| 3323 | astgen.fn_block = &fn_gz; | 3342 | astgen.fn_block = &fn_gz; |
| 3324 | defer astgen.fn_block = prev_fn_block; | 3343 | defer astgen.fn_block = prev_fn_block; |
| ... | @@ -3332,14 +3351,7 @@ fn fnDecl( | ... | @@ -3332,14 +3351,7 @@ fn fnDecl( |
| 3332 | _ = try expr(&fn_gz, params_scope, .none, body_node); | 3351 | _ = try expr(&fn_gz, params_scope, .none, body_node); |
| 3333 | try checkUsed(gz, &fn_gz.base, params_scope); | 3352 | try checkUsed(gz, &fn_gz.base, params_scope); |
| 3334 | | 3353 | |
| 3335 | const need_implicit_ret = blk: { | 3354 | if (!fn_gz.endsWithNoReturn()) { |
| 3336 | if (fn_gz.instructions.items.len == 0) | | |
| 3337 | break :blk true; | | |
| 3338 | const last = fn_gz.instructions.items[fn_gz.instructions.items.len - 1]; | | |
| 3339 | const zir_tags = astgen.instructions.items(.tag); | | |
| 3340 | break :blk !zir_tags[last].isNoReturn(); | | |
| 3341 | }; | | |
| 3342 | if (need_implicit_ret) { | | |
| 3343 | // Since we are adding the return instruction here, we must handle the coercion. | 3355 | // Since we are adding the return instruction here, we must handle the coercion. |
| 3344 | // We do this by using the `ret_coerce` instruction. | 3356 | // We do this by using the `ret_coerce` instruction. |
| 3345 | _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); | 3357 | _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); |
| ... | @@ -3350,9 +3362,9 @@ fn fnDecl( | ... | @@ -3350,9 +3362,9 @@ fn fnDecl( |
| 3350 | .lbrace_line = lbrace_line, | 3362 | .lbrace_line = lbrace_line, |
| 3351 | .lbrace_column = lbrace_column, | 3363 | .lbrace_column = lbrace_column, |
| 3352 | .param_block = block_inst, | 3364 | .param_block = block_inst, |
| 3353 | .ret_ty = ret_gz.instructions.items, | 3365 | .ret_gz = &ret_gz, |
| 3354 | .ret_br = ret_br, | 3366 | .ret_br = ret_br, |
| 3355 | .body = fn_gz.instructions.items, | 3367 | .body_gz = &fn_gz, |
| 3356 | .cc = cc, | 3368 | .cc = cc, |
| 3357 | .align_inst = .none, // passed in the per-decl data | 3369 | .align_inst = .none, // passed in the per-decl data |
| 3358 | .lib_name = lib_name, | 3370 | .lib_name = lib_name, |
| ... | @@ -3364,7 +3376,7 @@ fn fnDecl( | ... | @@ -3364,7 +3376,7 @@ fn fnDecl( |
| 3364 | }; | 3376 | }; |
| 3365 | | 3377 | |
| 3366 | // We add this at the end so that its instruction index marks the end range | 3378 | // We add this at the end so that its instruction index marks the end range |
| 3367 | // of the top level declaration. | 3379 | // of the top level declaration. addFunc already unstacked fn_gz and ret_gz. |
| 3368 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); | 3380 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); |
| 3369 | try decl_gz.setBlockBody(block_inst); | 3381 | try decl_gz.setBlockBody(block_inst); |
| 3370 | | 3382 | |
| ... | @@ -3396,14 +3408,13 @@ fn globalVarDecl( | ... | @@ -3396,14 +3408,13 @@ fn globalVarDecl( |
| 3396 | node: Ast.Node.Index, | 3408 | node: Ast.Node.Index, |
| 3397 | var_decl: Ast.full.VarDecl, | 3409 | var_decl: Ast.full.VarDecl, |
| 3398 | ) InnerError!void { | 3410 | ) InnerError!void { |
| 3399 | const gpa = astgen.gpa; | | |
| 3400 | const tree = astgen.tree; | 3411 | const tree = astgen.tree; |
| 3401 | const token_tags = tree.tokens.items(.tag); | 3412 | const token_tags = tree.tokens.items(.tag); |
| 3402 | | 3413 | |
| 3403 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; | 3414 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; |
| 3404 | // We do this at the beginning so that the instruction index marks the range start | 3415 | // We do this at the beginning so that the instruction index marks the range start |
| 3405 | // of the top level declaration. | 3416 | // of the top level declaration. |
| 3406 | const block_inst = try gz.addBlock(.block_inline, node); | 3417 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3407 | | 3418 | |
| 3408 | const name_token = var_decl.ast.mut_token + 1; | 3419 | const name_token = var_decl.ast.mut_token + 1; |
| 3409 | const name_str_index = try astgen.identAsString(name_token); | 3420 | const name_str_index = try astgen.identAsString(name_token); |
| ... | @@ -3416,8 +3427,10 @@ fn globalVarDecl( | ... | @@ -3416,8 +3427,10 @@ fn globalVarDecl( |
| 3416 | .force_comptime = true, | 3427 | .force_comptime = true, |
| 3417 | .in_defer = false, | 3428 | .in_defer = false, |
| 3418 | .anon_name_strategy = .parent, | 3429 | .anon_name_strategy = .parent, |
| | 3430 | .instructions = gz.instructions, |
| | 3431 | .instructions_top = gz.instructions.items.len, |
| 3419 | }; | 3432 | }; |
| 3420 | defer block_scope.instructions.deinit(gpa); | 3433 | defer block_scope.unstack(); |
| 3421 | | 3434 | |
| 3422 | const is_pub = var_decl.visib_token != null; | 3435 | const is_pub = var_decl.visib_token != null; |
| 3423 | const is_export = blk: { | 3436 | const is_export = blk: { |
| ... | @@ -3543,14 +3556,13 @@ fn comptimeDecl( | ... | @@ -3543,14 +3556,13 @@ fn comptimeDecl( |
| 3543 | wip_members: *WipMembers, | 3556 | wip_members: *WipMembers, |
| 3544 | node: Ast.Node.Index, | 3557 | node: Ast.Node.Index, |
| 3545 | ) InnerError!void { | 3558 | ) InnerError!void { |
| 3546 | const gpa = astgen.gpa; | | |
| 3547 | const tree = astgen.tree; | 3559 | const tree = astgen.tree; |
| 3548 | const node_datas = tree.nodes.items(.data); | 3560 | const node_datas = tree.nodes.items(.data); |
| 3549 | const body_node = node_datas[node].lhs; | 3561 | const body_node = node_datas[node].lhs; |
| 3550 | | 3562 | |
| 3551 | // Up top so the ZIR instruction index marks the start range of this | 3563 | // Up top so the ZIR instruction index marks the start range of this |
| 3552 | // top-level declaration. | 3564 | // top-level declaration. |
| 3553 | const block_inst = try gz.addBlock(.block_inline, node); | 3565 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3554 | wip_members.nextDecl(false, false, false, false); | 3566 | wip_members.nextDecl(false, false, false, false); |
| 3555 | | 3567 | |
| 3556 | var decl_block: GenZir = .{ | 3568 | var decl_block: GenZir = .{ |
| ... | @@ -3560,11 +3572,13 @@ fn comptimeDecl( | ... | @@ -3560,11 +3572,13 @@ fn comptimeDecl( |
| 3560 | .decl_line = gz.calcLine(node), | 3572 | .decl_line = gz.calcLine(node), |
| 3561 | .parent = scope, | 3573 | .parent = scope, |
| 3562 | .astgen = astgen, | 3574 | .astgen = astgen, |
| | 3575 | .instructions = gz.instructions, |
| | 3576 | .instructions_top = gz.instructions.items.len, |
| 3563 | }; | 3577 | }; |
| 3564 | defer decl_block.instructions.deinit(gpa); | 3578 | defer decl_block.unstack(); |
| 3565 | | 3579 | |
| 3566 | const block_result = try expr(&decl_block, &decl_block.base, .none, body_node); | 3580 | const block_result = try expr(&decl_block, &decl_block.base, .none, body_node); |
| 3567 | if (decl_block.instructions.items.len == 0 or !decl_block.refIsNoReturn(block_result)) { | 3581 | if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) { |
| 3568 | _ = try decl_block.addBreak(.break_inline, block_inst, .void_value); | 3582 | _ = try decl_block.addBreak(.break_inline, block_inst, .void_value); |
| 3569 | } | 3583 | } |
| 3570 | try decl_block.setBlockBody(block_inst); | 3584 | try decl_block.setBlockBody(block_inst); |
| ... | @@ -3589,7 +3603,6 @@ fn usingnamespaceDecl( | ... | @@ -3589,7 +3603,6 @@ fn usingnamespaceDecl( |
| 3589 | wip_members: *WipMembers, | 3603 | wip_members: *WipMembers, |
| 3590 | node: Ast.Node.Index, | 3604 | node: Ast.Node.Index, |
| 3591 | ) InnerError!void { | 3605 | ) InnerError!void { |
| 3592 | const gpa = astgen.gpa; | | |
| 3593 | const tree = astgen.tree; | 3606 | const tree = astgen.tree; |
| 3594 | const node_datas = tree.nodes.items(.data); | 3607 | const node_datas = tree.nodes.items(.data); |
| 3595 | | 3608 | |
| ... | @@ -3602,7 +3615,7 @@ fn usingnamespaceDecl( | ... | @@ -3602,7 +3615,7 @@ fn usingnamespaceDecl( |
| 3602 | }; | 3615 | }; |
| 3603 | // Up top so the ZIR instruction index marks the start range of this | 3616 | // Up top so the ZIR instruction index marks the start range of this |
| 3604 | // top-level declaration. | 3617 | // top-level declaration. |
| 3605 | const block_inst = try gz.addBlock(.block_inline, node); | 3618 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3606 | wip_members.nextDecl(is_pub, true, false, false); | 3619 | wip_members.nextDecl(is_pub, true, false, false); |
| 3607 | | 3620 | |
| 3608 | var decl_block: GenZir = .{ | 3621 | var decl_block: GenZir = .{ |
| ... | @@ -3612,8 +3625,10 @@ fn usingnamespaceDecl( | ... | @@ -3612,8 +3625,10 @@ fn usingnamespaceDecl( |
| 3612 | .decl_line = gz.calcLine(node), | 3625 | .decl_line = gz.calcLine(node), |
| 3613 | .parent = scope, | 3626 | .parent = scope, |
| 3614 | .astgen = astgen, | 3627 | .astgen = astgen, |
| | 3628 | .instructions = gz.instructions, |
| | 3629 | .instructions_top = gz.instructions.items.len, |
| 3615 | }; | 3630 | }; |
| 3616 | defer decl_block.instructions.deinit(gpa); | 3631 | defer decl_block.unstack(); |
| 3617 | | 3632 | |
| 3618 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); | 3633 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); |
| 3619 | _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst); | 3634 | _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst); |
| ... | @@ -3639,14 +3654,13 @@ fn testDecl( | ... | @@ -3639,14 +3654,13 @@ fn testDecl( |
| 3639 | wip_members: *WipMembers, | 3654 | wip_members: *WipMembers, |
| 3640 | node: Ast.Node.Index, | 3655 | node: Ast.Node.Index, |
| 3641 | ) InnerError!void { | 3656 | ) InnerError!void { |
| 3642 | const gpa = astgen.gpa; | | |
| 3643 | const tree = astgen.tree; | 3657 | const tree = astgen.tree; |
| 3644 | const node_datas = tree.nodes.items(.data); | 3658 | const node_datas = tree.nodes.items(.data); |
| 3645 | const body_node = node_datas[node].rhs; | 3659 | const body_node = node_datas[node].rhs; |
| 3646 | | 3660 | |
| 3647 | // Up top so the ZIR instruction index marks the start range of this | 3661 | // Up top so the ZIR instruction index marks the start range of this |
| 3648 | // top-level declaration. | 3662 | // top-level declaration. |
| 3649 | const block_inst = try gz.addBlock(.block_inline, node); | 3663 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3650 | | 3664 | |
| 3651 | wip_members.nextDecl(false, false, false, false); | 3665 | wip_members.nextDecl(false, false, false, false); |
| 3652 | | 3666 | |
| ... | @@ -3657,8 +3671,10 @@ fn testDecl( | ... | @@ -3657,8 +3671,10 @@ fn testDecl( |
| 3657 | .decl_line = gz.calcLine(node), | 3671 | .decl_line = gz.calcLine(node), |
| 3658 | .parent = scope, | 3672 | .parent = scope, |
| 3659 | .astgen = astgen, | 3673 | .astgen = astgen, |
| | 3674 | .instructions = gz.instructions, |
| | 3675 | .instructions_top = gz.instructions.items.len, |
| 3660 | }; | 3676 | }; |
| 3661 | defer decl_block.instructions.deinit(gpa); | 3677 | defer decl_block.unstack(); |
| 3662 | | 3678 | |
| 3663 | const test_name: u32 = blk: { | 3679 | const test_name: u32 = blk: { |
| 3664 | const main_tokens = tree.nodes.items(.main_token); | 3680 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -3679,8 +3695,10 @@ fn testDecl( | ... | @@ -3679,8 +3695,10 @@ fn testDecl( |
| 3679 | .decl_line = decl_block.decl_line, | 3695 | .decl_line = decl_block.decl_line, |
| 3680 | .parent = &decl_block.base, | 3696 | .parent = &decl_block.base, |
| 3681 | .astgen = astgen, | 3697 | .astgen = astgen, |
| | 3698 | .instructions = decl_block.instructions, |
| | 3699 | .instructions_top = decl_block.instructions.items.len, |
| 3682 | }; | 3700 | }; |
| 3683 | defer fn_block.instructions.deinit(gpa); | 3701 | defer fn_block.unstack(); |
| 3684 | | 3702 | |
| 3685 | const prev_fn_block = astgen.fn_block; | 3703 | const prev_fn_block = astgen.fn_block; |
| 3686 | astgen.fn_block = &fn_block; | 3704 | astgen.fn_block = &fn_block; |
| ... | @@ -3693,7 +3711,7 @@ fn testDecl( | ... | @@ -3693,7 +3711,7 @@ fn testDecl( |
| 3693 | const lbrace_column = @intCast(u32, astgen.source_column); | 3711 | const lbrace_column = @intCast(u32, astgen.source_column); |
| 3694 | | 3712 | |
| 3695 | const block_result = try expr(&fn_block, &fn_block.base, .none, body_node); | 3713 | const block_result = try expr(&fn_block, &fn_block.base, .none, body_node); |
| 3696 | if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) { | 3714 | if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) { |
| 3697 | // Since we are adding the return instruction here, we must handle the coercion. | 3715 | // Since we are adding the return instruction here, we must handle the coercion. |
| 3698 | // We do this by using the `ret_coerce` instruction. | 3716 | // We do this by using the `ret_coerce` instruction. |
| 3699 | _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); | 3717 | _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); |
| ... | @@ -3704,9 +3722,9 @@ fn testDecl( | ... | @@ -3704,9 +3722,9 @@ fn testDecl( |
| 3704 | .lbrace_line = lbrace_line, | 3722 | .lbrace_line = lbrace_line, |
| 3705 | .lbrace_column = lbrace_column, | 3723 | .lbrace_column = lbrace_column, |
| 3706 | .param_block = block_inst, | 3724 | .param_block = block_inst, |
| 3707 | .ret_ty = &.{}, | 3725 | .ret_gz = null, |
| 3708 | .ret_br = 0, | 3726 | .ret_br = 0, |
| 3709 | .body = fn_block.instructions.items, | 3727 | .body_gz = &fn_block, |
| 3710 | .cc = .none, | 3728 | .cc = .none, |
| 3711 | .align_inst = .none, | 3729 | .align_inst = .none, |
| 3712 | .lib_name = 0, | 3730 | .lib_name = 0, |
| ... | @@ -3776,8 +3794,10 @@ fn structDeclInner( | ... | @@ -3776,8 +3794,10 @@ fn structDeclInner( |
| 3776 | .astgen = astgen, | 3794 | .astgen = astgen, |
| 3777 | .force_comptime = true, | 3795 | .force_comptime = true, |
| 3778 | .in_defer = false, | 3796 | .in_defer = false, |
| | 3797 | .instructions = gz.instructions, |
| | 3798 | .instructions_top = gz.instructions.items.len, |
| 3779 | }; | 3799 | }; |
| 3780 | defer block_scope.instructions.deinit(gpa); | 3800 | defer block_scope.unstack(); |
| 3781 | | 3801 | |
| 3782 | const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members); | 3802 | const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 3783 | const field_count = @intCast(u32, container_decl.ast.members.len - decl_count); | 3803 | const field_count = @intCast(u32, container_decl.ast.members.len - decl_count); |
| ... | @@ -3829,14 +3849,16 @@ fn structDeclInner( | ... | @@ -3829,14 +3849,16 @@ fn structDeclInner( |
| 3829 | } | 3849 | } |
| 3830 | } | 3850 | } |
| 3831 | | 3851 | |
| 3832 | if (block_scope.instructions.items.len != 0) { | 3852 | if (!block_scope.isEmpty()) { |
| 3833 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 3853 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 3834 | } | 3854 | } |
| 3835 | | 3855 | |
| | 3856 | const body = block_scope.instructionsSlice(); |
| | 3857 | |
| 3836 | try gz.setStruct(decl_inst, .{ | 3858 | try gz.setStruct(decl_inst, .{ |
| 3837 | .src_node = node, | 3859 | .src_node = node, |
| 3838 | .layout = layout, | 3860 | .layout = layout, |
| 3839 | .body_len = @intCast(u32, block_scope.instructions.items.len), | 3861 | .body_len = @intCast(u32, body.len), |
| 3840 | .fields_len = field_count, | 3862 | .fields_len = field_count, |
| 3841 | .decls_len = decl_count, | 3863 | .decls_len = decl_count, |
| 3842 | .known_has_bits = known_has_bits, | 3864 | .known_has_bits = known_has_bits, |
| ... | @@ -3845,11 +3867,12 @@ fn structDeclInner( | ... | @@ -3845,11 +3867,12 @@ fn structDeclInner( |
| 3845 | wip_members.finishBits(bits_per_field); | 3867 | wip_members.finishBits(bits_per_field); |
| 3846 | const decls_slice = wip_members.declsSlice(); | 3868 | const decls_slice = wip_members.declsSlice(); |
| 3847 | const fields_slice = wip_members.fieldsSlice(); | 3869 | const fields_slice = wip_members.fieldsSlice(); |
| 3848 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + block_scope.instructions.items.len + fields_slice.len); | 3870 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 3849 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 3871 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 3850 | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); | 3872 | astgen.extra.appendSliceAssumeCapacity(body); |
| 3851 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 3873 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 3852 | | 3874 | |
| | 3875 | block_scope.unstack(); |
| 3853 | try gz.addNamespaceCaptures(&namespace); | 3876 | try gz.addNamespaceCaptures(&namespace); |
| 3854 | return indexToRef(decl_inst); | 3877 | return indexToRef(decl_inst); |
| 3855 | } | 3878 | } |
| ... | @@ -3888,8 +3911,10 @@ fn unionDeclInner( | ... | @@ -3888,8 +3911,10 @@ fn unionDeclInner( |
| 3888 | .astgen = astgen, | 3911 | .astgen = astgen, |
| 3889 | .force_comptime = true, | 3912 | .force_comptime = true, |
| 3890 | .in_defer = false, | 3913 | .in_defer = false, |
| | 3914 | .instructions = gz.instructions, |
| | 3915 | .instructions_top = gz.instructions.items.len, |
| 3891 | }; | 3916 | }; |
| 3892 | defer block_scope.instructions.deinit(gpa); | 3917 | defer block_scope.unstack(); |
| 3893 | | 3918 | |
| 3894 | const decl_count = try astgen.scanDecls(&namespace, members); | 3919 | const decl_count = try astgen.scanDecls(&namespace, members); |
| 3895 | const field_count = @intCast(u32, members.len - decl_count); | 3920 | const field_count = @intCast(u32, members.len - decl_count); |
| ... | @@ -3972,15 +3997,17 @@ fn unionDeclInner( | ... | @@ -3972,15 +3997,17 @@ fn unionDeclInner( |
| 3972 | return astgen.failNode(node, "union declarations must have at least one tag", .{}); | 3997 | return astgen.failNode(node, "union declarations must have at least one tag", .{}); |
| 3973 | } | 3998 | } |
| 3974 | | 3999 | |
| 3975 | if (block_scope.instructions.items.len != 0) { | 4000 | if (!block_scope.isEmpty()) { |
| 3976 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 4001 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 3977 | } | 4002 | } |
| 3978 | | 4003 | |
| | 4004 | const body = block_scope.instructionsSlice(); |
| | 4005 | |
| 3979 | try gz.setUnion(decl_inst, .{ | 4006 | try gz.setUnion(decl_inst, .{ |
| 3980 | .src_node = node, | 4007 | .src_node = node, |
| 3981 | .layout = layout, | 4008 | .layout = layout, |
| 3982 | .tag_type = arg_inst, | 4009 | .tag_type = arg_inst, |
| 3983 | .body_len = @intCast(u32, block_scope.instructions.items.len), | 4010 | .body_len = @intCast(u32, body.len), |
| 3984 | .fields_len = field_count, | 4011 | .fields_len = field_count, |
| 3985 | .decls_len = decl_count, | 4012 | .decls_len = decl_count, |
| 3986 | .auto_enum_tag = have_auto_enum, | 4013 | .auto_enum_tag = have_auto_enum, |
| ... | @@ -3989,11 +4016,12 @@ fn unionDeclInner( | ... | @@ -3989,11 +4016,12 @@ fn unionDeclInner( |
| 3989 | wip_members.finishBits(bits_per_field); | 4016 | wip_members.finishBits(bits_per_field); |
| 3990 | const decls_slice = wip_members.declsSlice(); | 4017 | const decls_slice = wip_members.declsSlice(); |
| 3991 | const fields_slice = wip_members.fieldsSlice(); | 4018 | const fields_slice = wip_members.fieldsSlice(); |
| 3992 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + block_scope.instructions.items.len + fields_slice.len); | 4019 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 3993 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 4020 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 3994 | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); | 4021 | astgen.extra.appendSliceAssumeCapacity(body); |
| 3995 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 4022 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 3996 | | 4023 | |
| | 4024 | block_scope.unstack(); |
| 3997 | try gz.addNamespaceCaptures(&namespace); | 4025 | try gz.addNamespaceCaptures(&namespace); |
| 3998 | return indexToRef(decl_inst); | 4026 | return indexToRef(decl_inst); |
| 3999 | } | 4027 | } |
| ... | @@ -4163,8 +4191,10 @@ fn containerDecl( | ... | @@ -4163,8 +4191,10 @@ fn containerDecl( |
| 4163 | .astgen = astgen, | 4191 | .astgen = astgen, |
| 4164 | .force_comptime = true, | 4192 | .force_comptime = true, |
| 4165 | .in_defer = false, | 4193 | .in_defer = false, |
| | 4194 | .instructions = gz.instructions, |
| | 4195 | .instructions_top = gz.instructions.items.len, |
| 4166 | }; | 4196 | }; |
| 4167 | defer block_scope.instructions.deinit(gpa); | 4197 | defer block_scope.unstack(); |
| 4168 | | 4198 | |
| 4169 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); | 4199 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4170 | | 4200 | |
| ... | @@ -4215,15 +4245,17 @@ fn containerDecl( | ... | @@ -4215,15 +4245,17 @@ fn containerDecl( |
| 4215 | } | 4245 | } |
| 4216 | } | 4246 | } |
| 4217 | | 4247 | |
| 4218 | if (block_scope.instructions.items.len != 0) { | 4248 | if (!block_scope.isEmpty()) { |
| 4219 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 4249 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 4220 | } | 4250 | } |
| 4221 | | 4251 | |
| | 4252 | const body = block_scope.instructionsSlice(); |
| | 4253 | |
| 4222 | try gz.setEnum(decl_inst, .{ | 4254 | try gz.setEnum(decl_inst, .{ |
| 4223 | .src_node = node, | 4255 | .src_node = node, |
| 4224 | .nonexhaustive = nonexhaustive, | 4256 | .nonexhaustive = nonexhaustive, |
| 4225 | .tag_type = arg_inst, | 4257 | .tag_type = arg_inst, |
| 4226 | .body_len = @intCast(u32, block_scope.instructions.items.len), | 4258 | .body_len = @intCast(u32, body.len), |
| 4227 | .fields_len = @intCast(u32, counts.total_fields), | 4259 | .fields_len = @intCast(u32, counts.total_fields), |
| 4228 | .decls_len = @intCast(u32, counts.decls), | 4260 | .decls_len = @intCast(u32, counts.decls), |
| 4229 | }); | 4261 | }); |
| ... | @@ -4231,11 +4263,12 @@ fn containerDecl( | ... | @@ -4231,11 +4263,12 @@ fn containerDecl( |
| 4231 | wip_members.finishBits(bits_per_field); | 4263 | wip_members.finishBits(bits_per_field); |
| 4232 | const decls_slice = wip_members.declsSlice(); | 4264 | const decls_slice = wip_members.declsSlice(); |
| 4233 | const fields_slice = wip_members.fieldsSlice(); | 4265 | const fields_slice = wip_members.fieldsSlice(); |
| 4234 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + block_scope.instructions.items.len + fields_slice.len); | 4266 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 4235 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 4267 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4236 | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); | 4268 | astgen.extra.appendSliceAssumeCapacity(body); |
| 4237 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 4269 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4238 | | 4270 | |
| | 4271 | block_scope.unstack(); |
| 4239 | try gz.addNamespaceCaptures(&namespace); | 4272 | try gz.addNamespaceCaptures(&namespace); |
| 4240 | return rvalue(gz, rl, indexToRef(decl_inst), node); | 4273 | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 4241 | }, | 4274 | }, |
| ... | @@ -4453,7 +4486,7 @@ fn tryExpr( | ... | @@ -4453,7 +4486,7 @@ fn tryExpr( |
| 4453 | | 4486 | |
| 4454 | var block_scope = parent_gz.makeSubBlock(scope); | 4487 | var block_scope = parent_gz.makeSubBlock(scope); |
| 4455 | block_scope.setBreakResultLoc(rl); | 4488 | block_scope.setBreakResultLoc(rl); |
| 4456 | defer block_scope.instructions.deinit(astgen.gpa); | 4489 | defer block_scope.unstack(); |
| 4457 | | 4490 | |
| 4458 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { | 4491 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 4459 | .ref => .ref, | 4492 | .ref => .ref, |
| ... | @@ -4473,12 +4506,13 @@ fn tryExpr( | ... | @@ -4473,12 +4506,13 @@ fn tryExpr( |
| 4473 | const cond = try block_scope.addUnNode(err_ops[0], operand, node); | 4506 | const cond = try block_scope.addUnNode(err_ops[0], operand, node); |
| 4474 | const condbr = try block_scope.addCondBr(.condbr, node); | 4507 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 4475 | | 4508 | |
| 4476 | const block = try parent_gz.addBlock(.block, node); | 4509 | const block = try parent_gz.makeBlockInst(.block, node); |
| 4477 | try parent_gz.instructions.append(astgen.gpa, block); | | |
| 4478 | try block_scope.setBlockBody(block); | 4510 | try block_scope.setBlockBody(block); |
| | 4511 | // block_scope unstacked now, can add new instructions to parent_gz |
| | 4512 | try parent_gz.instructions.append(astgen.gpa, block); |
| 4479 | | 4513 | |
| 4480 | var then_scope = parent_gz.makeSubBlock(scope); | 4514 | var then_scope = parent_gz.makeSubBlock(scope); |
| 4481 | defer then_scope.instructions.deinit(astgen.gpa); | 4515 | defer then_scope.unstack(); |
| 4482 | | 4516 | |
| 4483 | block_scope.break_count += 1; | 4517 | block_scope.break_count += 1; |
| 4484 | // This could be a pointer or value depending on `err_ops[2]`. | 4518 | // This could be a pointer or value depending on `err_ops[2]`. |
| ... | @@ -4488,8 +4522,9 @@ fn tryExpr( | ... | @@ -4488,8 +4522,9 @@ fn tryExpr( |
| 4488 | else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node), | 4522 | else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node), |
| 4489 | }; | 4523 | }; |
| 4490 | | 4524 | |
| | 4525 | // else_scope will be stacked on then_scope as both are stacked on parent_gz |
| 4491 | var else_scope = parent_gz.makeSubBlock(scope); | 4526 | var else_scope = parent_gz.makeSubBlock(scope); |
| 4492 | defer else_scope.instructions.deinit(astgen.gpa); | 4527 | defer else_scope.unstack(); |
| 4493 | | 4528 | |
| 4494 | const err_code = try else_scope.addUnNode(err_ops[1], operand, node); | 4529 | const err_code = try else_scope.addUnNode(err_ops[1], operand, node); |
| 4495 | try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code }); | 4530 | try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code }); |
| ... | @@ -4529,7 +4564,7 @@ fn orelseCatchExpr( | ... | @@ -4529,7 +4564,7 @@ fn orelseCatchExpr( |
| 4529 | | 4564 | |
| 4530 | var block_scope = parent_gz.makeSubBlock(scope); | 4565 | var block_scope = parent_gz.makeSubBlock(scope); |
| 4531 | block_scope.setBreakResultLoc(rl); | 4566 | block_scope.setBreakResultLoc(rl); |
| 4532 | defer block_scope.instructions.deinit(astgen.gpa); | 4567 | defer block_scope.unstack(); |
| 4533 | | 4568 | |
| 4534 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { | 4569 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 4535 | .ref => .ref, | 4570 | .ref => .ref, |
| ... | @@ -4544,12 +4579,13 @@ fn orelseCatchExpr( | ... | @@ -4544,12 +4579,13 @@ fn orelseCatchExpr( |
| 4544 | const cond = try block_scope.addUnNode(cond_op, operand, node); | 4579 | const cond = try block_scope.addUnNode(cond_op, operand, node); |
| 4545 | const condbr = try block_scope.addCondBr(.condbr, node); | 4580 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 4546 | | 4581 | |
| 4547 | const block = try parent_gz.addBlock(.block, node); | 4582 | const block = try parent_gz.makeBlockInst(.block, node); |
| 4548 | try parent_gz.instructions.append(astgen.gpa, block); | | |
| 4549 | try block_scope.setBlockBody(block); | 4583 | try block_scope.setBlockBody(block); |
| | 4584 | // block_scope unstacked now, can add new instructions to parent_gz |
| | 4585 | try parent_gz.instructions.append(astgen.gpa, block); |
| 4550 | | 4586 | |
| 4551 | var then_scope = parent_gz.makeSubBlock(scope); | 4587 | var then_scope = parent_gz.makeSubBlock(scope); |
| 4552 | defer then_scope.instructions.deinit(astgen.gpa); | 4588 | defer then_scope.unstack(); |
| 4553 | | 4589 | |
| 4554 | // This could be a pointer or value depending on `unwrap_op`. | 4590 | // This could be a pointer or value depending on `unwrap_op`. |
| 4555 | const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); | 4591 | const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); |
| ... | @@ -4559,7 +4595,7 @@ fn orelseCatchExpr( | ... | @@ -4559,7 +4595,7 @@ fn orelseCatchExpr( |
| 4559 | }; | 4595 | }; |
| 4560 | | 4596 | |
| 4561 | var else_scope = parent_gz.makeSubBlock(scope); | 4597 | var else_scope = parent_gz.makeSubBlock(scope); |
| 4562 | defer else_scope.instructions.deinit(astgen.gpa); | 4598 | defer else_scope.unstack(); |
| 4563 | | 4599 | |
| 4564 | var err_val_scope: Scope.LocalVal = undefined; | 4600 | var err_val_scope: Scope.LocalVal = undefined; |
| 4565 | const else_sub_scope = blk: { | 4601 | const else_sub_scope = blk: { |
| ... | @@ -4606,6 +4642,7 @@ fn orelseCatchExpr( | ... | @@ -4606,6 +4642,7 @@ fn orelseCatchExpr( |
| 4606 | ); | 4642 | ); |
| 4607 | } | 4643 | } |
| 4608 | | 4644 | |
| | 4645 | /// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`. |
| 4609 | fn finishThenElseBlock( | 4646 | fn finishThenElseBlock( |
| 4610 | parent_gz: *GenZir, | 4647 | parent_gz: *GenZir, |
| 4611 | rl: ResultLoc, | 4648 | rl: ResultLoc, |
| ... | @@ -4624,33 +4661,33 @@ fn finishThenElseBlock( | ... | @@ -4624,33 +4661,33 @@ fn finishThenElseBlock( |
| 4624 | // We now have enough information to decide whether the result instruction should | 4661 | // We now have enough information to decide whether the result instruction should |
| 4625 | // be communicated via result location pointer or break instructions. | 4662 | // be communicated via result location pointer or break instructions. |
| 4626 | const strat = rl.strategy(block_scope); | 4663 | const strat = rl.strategy(block_scope); |
| | 4664 | // else_scope may be stacked on then_scope, so check for no-return on then_scope manually |
| | 4665 | const tags = parent_gz.astgen.instructions.items(.tag); |
| | 4666 | const then_slice = then_scope.instructionsSliceUpto(else_scope); |
| | 4667 | const then_no_return = then_slice.len > 0 and tags[then_slice[then_slice.len - 1]].isNoReturn(); |
| | 4668 | const else_no_return = else_scope.endsWithNoReturn(); |
| | 4669 | |
| 4627 | switch (strat.tag) { | 4670 | switch (strat.tag) { |
| 4628 | .break_void => { | 4671 | .break_void => { |
| 4629 | if (!then_scope.endsWithNoReturn()) { | 4672 | const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, .void_value) else 0; |
| 4630 | _ = try then_scope.addBreak(break_tag, then_break_block, .void_value); | 4673 | const else_break = if (!else_no_return) try else_scope.makeBreak(break_tag, main_block, .void_value) else 0; |
| 4631 | } | | |
| 4632 | if (!else_scope.endsWithNoReturn()) { | | |
| 4633 | _ = try else_scope.addBreak(break_tag, main_block, .void_value); | | |
| 4634 | } | | |
| 4635 | assert(!strat.elide_store_to_block_ptr_instructions); | 4674 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 4636 | try setCondBrPayload(condbr, cond, then_scope, else_scope); | 4675 | try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break); |
| 4637 | return indexToRef(main_block); | 4676 | return indexToRef(main_block); |
| 4638 | }, | 4677 | }, |
| 4639 | .break_operand => { | 4678 | .break_operand => { |
| 4640 | if (!then_scope.endsWithNoReturn()) { | 4679 | const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, then_result) else 0; |
| 4641 | _ = try then_scope.addBreak(break_tag, then_break_block, then_result); | 4680 | const else_break = if (else_result == .none) |
| 4642 | } | 4681 | try else_scope.makeBreak(break_tag, main_block, .void_value) |
| 4643 | if (else_result != .none) { | 4682 | else if (!else_no_return) |
| 4644 | if (!else_scope.endsWithNoReturn()) { | 4683 | try else_scope.makeBreak(break_tag, main_block, else_result) |
| 4645 | _ = try else_scope.addBreak(break_tag, main_block, else_result); | 4684 | else |
| 4646 | } | 4685 | 0; |
| 4647 | } else { | 4686 | |
| 4648 | _ = try else_scope.addBreak(break_tag, main_block, .void_value); | | |
| 4649 | } | | |
| 4650 | if (strat.elide_store_to_block_ptr_instructions) { | 4687 | if (strat.elide_store_to_block_ptr_instructions) { |
| 4651 | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope, block_scope.rl_ptr); | 4688 | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, then_break, else_scope, else_break, block_scope.rl_ptr); |
| 4652 | } else { | 4689 | } else { |
| 4653 | try setCondBrPayload(condbr, cond, then_scope, else_scope); | 4690 | try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break); |
| 4654 | } | 4691 | } |
| 4655 | const block_ref = indexToRef(main_block); | 4692 | const block_ref = indexToRef(main_block); |
| 4656 | switch (rl) { | 4693 | switch (rl) { |
| ... | @@ -4778,7 +4815,7 @@ fn boolBinOp( | ... | @@ -4778,7 +4815,7 @@ fn boolBinOp( |
| 4778 | const bool_br = try gz.addBoolBr(zir_tag, lhs); | 4815 | const bool_br = try gz.addBoolBr(zir_tag, lhs); |
| 4779 | | 4816 | |
| 4780 | var rhs_scope = gz.makeSubBlock(scope); | 4817 | var rhs_scope = gz.makeSubBlock(scope); |
| 4781 | defer rhs_scope.instructions.deinit(gz.astgen.gpa); | 4818 | defer rhs_scope.unstack(); |
| 4782 | const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); | 4819 | const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); |
| 4783 | if (!gz.refIsNoReturn(rhs)) { | 4820 | if (!gz.refIsNoReturn(rhs)) { |
| 4784 | _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); | 4821 | _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); |
| ... | @@ -4802,7 +4839,7 @@ fn ifExpr( | ... | @@ -4802,7 +4839,7 @@ fn ifExpr( |
| 4802 | | 4839 | |
| 4803 | var block_scope = parent_gz.makeSubBlock(scope); | 4840 | var block_scope = parent_gz.makeSubBlock(scope); |
| 4804 | block_scope.setBreakResultLoc(rl); | 4841 | block_scope.setBreakResultLoc(rl); |
| 4805 | defer block_scope.instructions.deinit(astgen.gpa); | 4842 | defer block_scope.unstack(); |
| 4806 | | 4843 | |
| 4807 | const payload_is_ref = if (if_full.payload_token) |payload_token| | 4844 | const payload_is_ref = if (if_full.payload_token) |payload_token| |
| 4808 | token_tags[payload_token] == .asterisk | 4845 | token_tags[payload_token] == .asterisk |
| ... | @@ -4840,12 +4877,13 @@ fn ifExpr( | ... | @@ -4840,12 +4877,13 @@ fn ifExpr( |
| 4840 | | 4877 | |
| 4841 | const condbr = try block_scope.addCondBr(.condbr, node); | 4878 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 4842 | | 4879 | |
| 4843 | const block = try parent_gz.addBlock(.block, node); | 4880 | const block = try parent_gz.makeBlockInst(.block, node); |
| 4844 | try parent_gz.instructions.append(astgen.gpa, block); | | |
| 4845 | try block_scope.setBlockBody(block); | 4881 | try block_scope.setBlockBody(block); |
| | 4882 | // block_scope unstacked now, can add new instructions to parent_gz |
| | 4883 | try parent_gz.instructions.append(astgen.gpa, block); |
| 4846 | | 4884 | |
| 4847 | var then_scope = parent_gz.makeSubBlock(scope); | 4885 | var then_scope = parent_gz.makeSubBlock(scope); |
| 4848 | defer then_scope.instructions.deinit(astgen.gpa); | 4886 | defer then_scope.unstack(); |
| 4849 | | 4887 | |
| 4850 | var payload_val_scope: Scope.LocalVal = undefined; | 4888 | var payload_val_scope: Scope.LocalVal = undefined; |
| 4851 | | 4889 | |
| ... | @@ -4911,7 +4949,7 @@ fn ifExpr( | ... | @@ -4911,7 +4949,7 @@ fn ifExpr( |
| 4911 | // instructions or not. | 4949 | // instructions or not. |
| 4912 | | 4950 | |
| 4913 | var else_scope = parent_gz.makeSubBlock(scope); | 4951 | var else_scope = parent_gz.makeSubBlock(scope); |
| 4914 | defer else_scope.instructions.deinit(astgen.gpa); | 4952 | defer else_scope.unstack(); |
| 4915 | | 4953 | |
| 4916 | const else_node = if_full.ast.else_expr; | 4954 | const else_node = if_full.ast.else_expr; |
| 4917 | const else_info: struct { | 4955 | const else_info: struct { |
| ... | @@ -4974,52 +5012,70 @@ fn ifExpr( | ... | @@ -4974,52 +5012,70 @@ fn ifExpr( |
| 4974 | ); | 5012 | ); |
| 4975 | } | 5013 | } |
| 4976 | | 5014 | |
| | 5015 | /// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`. |
| 4977 | fn setCondBrPayload( | 5016 | fn setCondBrPayload( |
| 4978 | condbr: Zir.Inst.Index, | 5017 | condbr: Zir.Inst.Index, |
| 4979 | cond: Zir.Inst.Ref, | 5018 | cond: Zir.Inst.Ref, |
| 4980 | then_scope: *GenZir, | 5019 | then_scope: *GenZir, |
| | 5020 | then_break: Zir.Inst.Index, |
| 4981 | else_scope: *GenZir, | 5021 | else_scope: *GenZir, |
| | 5022 | else_break: Zir.Inst.Index, |
| 4982 | ) !void { | 5023 | ) !void { |
| | 5024 | defer then_scope.unstack(); |
| | 5025 | defer else_scope.unstack(); |
| 4983 | const astgen = then_scope.astgen; | 5026 | const astgen = then_scope.astgen; |
| 4984 | | 5027 | const then_body = then_scope.instructionsSliceUpto(else_scope); |
| | 5028 | const else_body = else_scope.instructionsSlice(); |
| | 5029 | const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0)); |
| | 5030 | const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0)); |
| 4985 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + | 5031 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 4986 | then_scope.instructions.items.len + else_scope.instructions.items.len); | 5032 | then_body_len + else_body_len); |
| 4987 | | 5033 | |
| 4988 | const zir_datas = astgen.instructions.items(.data); | 5034 | const zir_datas = astgen.instructions.items(.data); |
| 4989 | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ | 5035 | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| 4990 | .condition = cond, | 5036 | .condition = cond, |
| 4991 | .then_body_len = @intCast(u32, then_scope.instructions.items.len), | 5037 | .then_body_len = then_body_len, |
| 4992 | .else_body_len = @intCast(u32, else_scope.instructions.items.len), | 5038 | .else_body_len = else_body_len, |
| 4993 | }); | 5039 | }); |
| 4994 | astgen.extra.appendSliceAssumeCapacity(then_scope.instructions.items); | 5040 | astgen.extra.appendSliceAssumeCapacity(then_body); |
| 4995 | astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items); | 5041 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); |
| | 5042 | astgen.extra.appendSliceAssumeCapacity(else_body); |
| | 5043 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); |
| 4996 | } | 5044 | } |
| 4997 | | 5045 | |
| | 5046 | /// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`. |
| 4998 | fn setCondBrPayloadElideBlockStorePtr( | 5047 | fn setCondBrPayloadElideBlockStorePtr( |
| 4999 | condbr: Zir.Inst.Index, | 5048 | condbr: Zir.Inst.Index, |
| 5000 | cond: Zir.Inst.Ref, | 5049 | cond: Zir.Inst.Ref, |
| 5001 | then_scope: *GenZir, | 5050 | then_scope: *GenZir, |
| | 5051 | then_break: Zir.Inst.Index, |
| 5002 | else_scope: *GenZir, | 5052 | else_scope: *GenZir, |
| | 5053 | else_break: Zir.Inst.Index, |
| 5003 | block_ptr: Zir.Inst.Ref, | 5054 | block_ptr: Zir.Inst.Ref, |
| 5004 | ) !void { | 5055 | ) !void { |
| | 5056 | defer then_scope.unstack(); |
| | 5057 | defer else_scope.unstack(); |
| 5005 | const astgen = then_scope.astgen; | 5058 | const astgen = then_scope.astgen; |
| 5006 | | 5059 | const then_body = then_scope.instructionsSliceUpto(else_scope); |
| | 5060 | const else_body = else_scope.instructionsSlice(); |
| | 5061 | const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0)); |
| | 5062 | const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0)); |
| 5007 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + | 5063 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 5008 | then_scope.instructions.items.len + else_scope.instructions.items.len); | 5064 | then_body_len + else_body_len); |
| 5009 | | 5065 | |
| 5010 | const zir_tags = astgen.instructions.items(.tag); | 5066 | const zir_tags = astgen.instructions.items(.tag); |
| 5011 | const zir_datas = astgen.instructions.items(.data); | 5067 | const zir_datas = astgen.instructions.items(.data); |
| 5012 | | 5068 | |
| 5013 | const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ | 5069 | const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| 5014 | .condition = cond, | 5070 | .condition = cond, |
| 5015 | .then_body_len = @intCast(u32, then_scope.instructions.items.len), | 5071 | .then_body_len = then_body_len, |
| 5016 | .else_body_len = @intCast(u32, else_scope.instructions.items.len), | 5072 | .else_body_len = else_body_len, |
| 5017 | }); | 5073 | }); |
| 5018 | zir_datas[condbr].pl_node.payload_index = condbr_pl; | 5074 | zir_datas[condbr].pl_node.payload_index = condbr_pl; |
| 5019 | const then_body_len_index = condbr_pl + 1; | 5075 | const then_body_len_index = condbr_pl + 1; |
| 5020 | const else_body_len_index = condbr_pl + 2; | 5076 | const else_body_len_index = condbr_pl + 2; |
| 5021 | | 5077 | |
| 5022 | for (then_scope.instructions.items) |src_inst| { | 5078 | for (then_body) |src_inst| { |
| 5023 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 5079 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 5024 | if (zir_datas[src_inst].bin.lhs == block_ptr) { | 5080 | if (zir_datas[src_inst].bin.lhs == block_ptr) { |
| 5025 | astgen.extra.items[then_body_len_index] -= 1; | 5081 | astgen.extra.items[then_body_len_index] -= 1; |
| ... | @@ -5028,7 +5084,8 @@ fn setCondBrPayloadElideBlockStorePtr( | ... | @@ -5028,7 +5084,8 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5028 | } | 5084 | } |
| 5029 | astgen.extra.appendAssumeCapacity(src_inst); | 5085 | astgen.extra.appendAssumeCapacity(src_inst); |
| 5030 | } | 5086 | } |
| 5031 | for (else_scope.instructions.items) |src_inst| { | 5087 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); |
| | 5088 | for (else_body) |src_inst| { |
| 5032 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 5089 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 5033 | if (zir_datas[src_inst].bin.lhs == block_ptr) { | 5090 | if (zir_datas[src_inst].bin.lhs == block_ptr) { |
| 5034 | astgen.extra.items[else_body_len_index] -= 1; | 5091 | astgen.extra.items[else_body_len_index] -= 1; |
| ... | @@ -5037,6 +5094,7 @@ fn setCondBrPayloadElideBlockStorePtr( | ... | @@ -5037,6 +5094,7 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5037 | } | 5094 | } |
| 5038 | astgen.extra.appendAssumeCapacity(src_inst); | 5095 | astgen.extra.appendAssumeCapacity(src_inst); |
| 5039 | } | 5096 | } |
| | 5097 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); |
| 5040 | } | 5098 | } |
| 5041 | | 5099 | |
| 5042 | fn whileExpr( | 5100 | fn whileExpr( |
| ... | @@ -5056,17 +5114,17 @@ fn whileExpr( | ... | @@ -5056,17 +5114,17 @@ fn whileExpr( |
| 5056 | | 5114 | |
| 5057 | const is_inline = parent_gz.force_comptime or while_full.inline_token != null; | 5115 | const is_inline = parent_gz.force_comptime or while_full.inline_token != null; |
| 5058 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; | 5116 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; |
| 5059 | const loop_block = try parent_gz.addBlock(loop_tag, node); | 5117 | const loop_block = try parent_gz.makeBlockInst(loop_tag, node); |
| 5060 | try parent_gz.instructions.append(astgen.gpa, loop_block); | 5118 | try parent_gz.instructions.append(astgen.gpa, loop_block); |
| 5061 | | 5119 | |
| 5062 | var loop_scope = parent_gz.makeSubBlock(scope); | 5120 | var loop_scope = parent_gz.makeSubBlock(scope); |
| 5063 | loop_scope.setBreakResultLoc(rl); | 5121 | loop_scope.setBreakResultLoc(rl); |
| 5064 | defer loop_scope.instructions.deinit(astgen.gpa); | 5122 | defer loop_scope.unstack(); |
| 5065 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); | 5123 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 5066 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); | 5124 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 5067 | | 5125 | |
| 5068 | var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); | 5126 | var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); |
| 5069 | defer continue_scope.instructions.deinit(astgen.gpa); | 5127 | defer continue_scope.unstack(); |
| 5070 | | 5128 | |
| 5071 | const payload_is_ref = if (while_full.payload_token) |payload_token| | 5129 | const payload_is_ref = if (while_full.payload_token) |payload_token| |
| 5072 | token_tags[payload_token] == .asterisk | 5130 | token_tags[payload_token] == .asterisk |
| ... | @@ -5105,15 +5163,19 @@ fn whileExpr( | ... | @@ -5105,15 +5163,19 @@ fn whileExpr( |
| 5105 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; | 5163 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; |
| 5106 | const condbr = try continue_scope.addCondBr(condbr_tag, node); | 5164 | const condbr = try continue_scope.addCondBr(condbr_tag, node); |
| 5107 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; | 5165 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; |
| 5108 | const cond_block = try loop_scope.addBlock(block_tag, node); | 5166 | const cond_block = try loop_scope.makeBlockInst(block_tag, node); |
| 5109 | try loop_scope.instructions.append(astgen.gpa, cond_block); | | |
| 5110 | try continue_scope.setBlockBody(cond_block); | 5167 | try continue_scope.setBlockBody(cond_block); |
| | 5168 | // continue_scope unstacked now, can add new instructions to loop_scope |
| | 5169 | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5111 | | 5170 | |
| | 5171 | // make scope now but don't stack on parent_gz until loop_scope |
| | 5172 | // gets unstacked after cont_expr is emitted and added below |
| 5112 | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); | 5173 | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5113 | defer then_scope.instructions.deinit(astgen.gpa); | 5174 | then_scope.instructions_top = GenZir.unstacked_top; |
| | 5175 | defer then_scope.unstack(); |
| 5114 | | 5176 | |
| | 5177 | var payload_inst: Zir.Inst.Index = 0; |
| 5115 | var payload_val_scope: Scope.LocalVal = undefined; | 5178 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5116 | | | |
| 5117 | const then_sub_scope = s: { | 5179 | const then_sub_scope = s: { |
| 5118 | if (while_full.error_token != null) { | 5180 | if (while_full.error_token != null) { |
| 5119 | if (while_full.payload_token) |payload_token| { | 5181 | if (while_full.payload_token) |payload_token| { |
| ... | @@ -5121,7 +5183,8 @@ fn whileExpr( | ... | @@ -5121,7 +5183,8 @@ fn whileExpr( |
| 5121 | .err_union_payload_unsafe_ptr | 5183 | .err_union_payload_unsafe_ptr |
| 5122 | else | 5184 | else |
| 5123 | .err_union_payload_unsafe; | 5185 | .err_union_payload_unsafe; |
| 5124 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); | 5186 | // will add this instruction to then_scope.instructions below |
| | 5187 | payload_inst = try then_scope.makeUnNode(tag, cond.inst, node); |
| 5125 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; | 5188 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; |
| 5126 | const ident_bytes = tree.tokenSlice(ident_token); | 5189 | const ident_bytes = tree.tokenSlice(ident_token); |
| 5127 | if (mem.eql(u8, "_", ident_bytes)) | 5190 | if (mem.eql(u8, "_", ident_bytes)) |
| ... | @@ -5133,7 +5196,7 @@ fn whileExpr( | ... | @@ -5133,7 +5196,7 @@ fn whileExpr( |
| 5133 | .parent = &then_scope.base, | 5196 | .parent = &then_scope.base, |
| 5134 | .gen_zir = &then_scope, | 5197 | .gen_zir = &then_scope, |
| 5135 | .name = ident_name, | 5198 | .name = ident_name, |
| 5136 | .inst = payload_inst, | 5199 | .inst = indexToRef(payload_inst), |
| 5137 | .token_src = payload_token, | 5200 | .token_src = payload_token, |
| 5138 | .id_cat = .@"capture", | 5201 | .id_cat = .@"capture", |
| 5139 | }; | 5202 | }; |
| ... | @@ -5147,7 +5210,8 @@ fn whileExpr( | ... | @@ -5147,7 +5210,8 @@ fn whileExpr( |
| 5147 | .optional_payload_unsafe_ptr | 5210 | .optional_payload_unsafe_ptr |
| 5148 | else | 5211 | else |
| 5149 | .optional_payload_unsafe; | 5212 | .optional_payload_unsafe; |
| 5150 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); | 5213 | // will add this instruction to then_scope.instructions below |
| | 5214 | payload_inst = try then_scope.makeUnNode(tag, cond.inst, node); |
| 5151 | const ident_name = try astgen.identAsString(ident_token); | 5215 | const ident_name = try astgen.identAsString(ident_token); |
| 5152 | const ident_bytes = tree.tokenSlice(ident_token); | 5216 | const ident_bytes = tree.tokenSlice(ident_token); |
| 5153 | if (mem.eql(u8, "_", ident_bytes)) | 5217 | if (mem.eql(u8, "_", ident_bytes)) |
| ... | @@ -5157,7 +5221,7 @@ fn whileExpr( | ... | @@ -5157,7 +5221,7 @@ fn whileExpr( |
| 5157 | .parent = &then_scope.base, | 5221 | .parent = &then_scope.base, |
| 5158 | .gen_zir = &then_scope, | 5222 | .gen_zir = &then_scope, |
| 5159 | .name = ident_name, | 5223 | .name = ident_name, |
| 5160 | .inst = payload_inst, | 5224 | .inst = indexToRef(payload_inst), |
| 5161 | .token_src = ident_token, | 5225 | .token_src = ident_token, |
| 5162 | .id_cat = .@"capture", | 5226 | .id_cat = .@"capture", |
| 5163 | }; | 5227 | }; |
| ... | @@ -5187,6 +5251,9 @@ fn whileExpr( | ... | @@ -5187,6 +5251,9 @@ fn whileExpr( |
| 5187 | }); | 5251 | }); |
| 5188 | } | 5252 | } |
| 5189 | | 5253 | |
| | 5254 | // done adding instructions to loop_scope, can now stack then_scope |
| | 5255 | then_scope.instructions_top = then_scope.instructions.items.len; |
| | 5256 | if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst); |
| 5190 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); | 5257 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); |
| 5191 | if (!then_scope.endsWithNoReturn()) { | 5258 | if (!then_scope.endsWithNoReturn()) { |
| 5192 | loop_scope.break_count += 1; | 5259 | loop_scope.break_count += 1; |
| ... | @@ -5194,7 +5261,7 @@ fn whileExpr( | ... | @@ -5194,7 +5261,7 @@ fn whileExpr( |
| 5194 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); | 5261 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 5195 | | 5262 | |
| 5196 | var else_scope = parent_gz.makeSubBlock(&continue_scope.base); | 5263 | var else_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5197 | defer else_scope.instructions.deinit(astgen.gpa); | 5264 | defer else_scope.unstack(); |
| 5198 | | 5265 | |
| 5199 | const else_node = while_full.ast.else_expr; | 5266 | const else_node = while_full.ast.else_expr; |
| 5200 | const else_info: struct { | 5267 | const else_info: struct { |
| ... | @@ -5207,7 +5274,7 @@ fn whileExpr( | ... | @@ -5207,7 +5274,7 @@ fn whileExpr( |
| 5207 | .err_union_code_ptr | 5274 | .err_union_code_ptr |
| 5208 | else | 5275 | else |
| 5209 | .err_union_code; | 5276 | .err_union_code; |
| 5210 | const payload_inst = try else_scope.addUnNode(tag, cond.inst, node); | 5277 | const else_payload_inst = try else_scope.addUnNode(tag, cond.inst, node); |
| 5211 | const ident_name = try astgen.identAsString(error_token); | 5278 | const ident_name = try astgen.identAsString(error_token); |
| 5212 | const ident_bytes = tree.tokenSlice(error_token); | 5279 | const ident_bytes = tree.tokenSlice(error_token); |
| 5213 | if (mem.eql(u8, ident_bytes, "_")) | 5280 | if (mem.eql(u8, ident_bytes, "_")) |
| ... | @@ -5217,7 +5284,7 @@ fn whileExpr( | ... | @@ -5217,7 +5284,7 @@ fn whileExpr( |
| 5217 | .parent = &else_scope.base, | 5284 | .parent = &else_scope.base, |
| 5218 | .gen_zir = &else_scope, | 5285 | .gen_zir = &else_scope, |
| 5219 | .name = ident_name, | 5286 | .name = ident_name, |
| 5220 | .inst = payload_inst, | 5287 | .inst = else_payload_inst, |
| 5221 | .token_src = error_token, | 5288 | .token_src = error_token, |
| 5222 | .id_cat = .@"capture", | 5289 | .id_cat = .@"capture", |
| 5223 | }; | 5290 | }; |
| ... | @@ -5299,17 +5366,17 @@ fn forExpr( | ... | @@ -5299,17 +5366,17 @@ fn forExpr( |
| 5299 | }; | 5366 | }; |
| 5300 | | 5367 | |
| 5301 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; | 5368 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; |
| 5302 | const loop_block = try parent_gz.addBlock(loop_tag, node); | 5369 | const loop_block = try parent_gz.makeBlockInst(loop_tag, node); |
| 5303 | try parent_gz.instructions.append(astgen.gpa, loop_block); | 5370 | try parent_gz.instructions.append(astgen.gpa, loop_block); |
| 5304 | | 5371 | |
| 5305 | var loop_scope = parent_gz.makeSubBlock(scope); | 5372 | var loop_scope = parent_gz.makeSubBlock(scope); |
| 5306 | loop_scope.setBreakResultLoc(rl); | 5373 | loop_scope.setBreakResultLoc(rl); |
| 5307 | defer loop_scope.instructions.deinit(astgen.gpa); | 5374 | defer loop_scope.unstack(); |
| 5308 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); | 5375 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 5309 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); | 5376 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 5310 | | 5377 | |
| 5311 | var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); | 5378 | var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); |
| 5312 | defer cond_scope.instructions.deinit(astgen.gpa); | 5379 | defer cond_scope.unstack(); |
| 5313 | | 5380 | |
| 5314 | // check condition i < array_expr.len | 5381 | // check condition i < array_expr.len |
| 5315 | const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); | 5382 | const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); |
| ... | @@ -5321,9 +5388,10 @@ fn forExpr( | ... | @@ -5321,9 +5388,10 @@ fn forExpr( |
| 5321 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; | 5388 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; |
| 5322 | const condbr = try cond_scope.addCondBr(condbr_tag, node); | 5389 | const condbr = try cond_scope.addCondBr(condbr_tag, node); |
| 5323 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; | 5390 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; |
| 5324 | const cond_block = try loop_scope.addBlock(block_tag, node); | 5391 | const cond_block = try loop_scope.makeBlockInst(block_tag, node); |
| 5325 | try loop_scope.instructions.append(astgen.gpa, cond_block); | | |
| 5326 | try cond_scope.setBlockBody(cond_block); | 5392 | try cond_scope.setBlockBody(cond_block); |
| | 5393 | // cond_block unstacked now, can add new instructions to loop_scope |
| | 5394 | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5327 | | 5395 | |
| 5328 | // Increment the index variable. | 5396 | // Increment the index variable. |
| 5329 | const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); | 5397 | const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); |
| ... | @@ -5346,7 +5414,7 @@ fn forExpr( | ... | @@ -5346,7 +5414,7 @@ fn forExpr( |
| 5346 | } | 5414 | } |
| 5347 | | 5415 | |
| 5348 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); | 5416 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 5349 | defer then_scope.instructions.deinit(astgen.gpa); | 5417 | defer then_scope.unstack(); |
| 5350 | | 5418 | |
| 5351 | var payload_val_scope: Scope.LocalVal = undefined; | 5419 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5352 | var index_scope: Scope.LocalPtr = undefined; | 5420 | var index_scope: Scope.LocalPtr = undefined; |
| ... | @@ -5408,7 +5476,7 @@ fn forExpr( | ... | @@ -5408,7 +5476,7 @@ fn forExpr( |
| 5408 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); | 5476 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 5409 | | 5477 | |
| 5410 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); | 5478 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 5411 | defer else_scope.instructions.deinit(astgen.gpa); | 5479 | defer else_scope.unstack(); |
| 5412 | | 5480 | |
| 5413 | const else_node = for_full.ast.else_expr; | 5481 | const else_node = for_full.ast.else_expr; |
| 5414 | const else_info: struct { | 5482 | const else_info: struct { |
| ... | @@ -5600,15 +5668,16 @@ fn switchExpr( | ... | @@ -5600,15 +5668,16 @@ fn switchExpr( |
| 5600 | defer astgen.scratch.items.len = scratch_top; | 5668 | defer astgen.scratch.items.len = scratch_top; |
| 5601 | | 5669 | |
| 5602 | var block_scope = parent_gz.makeSubBlock(scope); | 5670 | var block_scope = parent_gz.makeSubBlock(scope); |
| | 5671 | // block_scope not used for collecting instructions |
| | 5672 | block_scope.instructions_top = GenZir.unstacked_top; |
| 5603 | block_scope.setBreakResultLoc(rl); | 5673 | block_scope.setBreakResultLoc(rl); |
| 5604 | defer block_scope.instructions.deinit(gpa); | | |
| 5605 | | 5674 | |
| 5606 | // This gets added to the parent block later, after the item expressions. | 5675 | // This gets added to the parent block later, after the item expressions. |
| 5607 | const switch_block = try parent_gz.addBlock(.switch_block, switch_node); | 5676 | const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node); |
| 5608 | | 5677 | |
| 5609 | // We re-use this same scope for all cases, including the special prong, if any. | 5678 | // We re-use this same scope for all cases, including the special prong, if any. |
| 5610 | var case_scope = parent_gz.makeSubBlock(&block_scope.base); | 5679 | var case_scope = parent_gz.makeSubBlock(&block_scope.base); |
| 5611 | defer case_scope.instructions.deinit(gpa); | 5680 | case_scope.instructions_top = GenZir.unstacked_top; |
| 5612 | | 5681 | |
| 5613 | // In this pass we generate all the item and prong expressions. | 5682 | // In this pass we generate all the item and prong expressions. |
| 5614 | var multi_case_index: u32 = 0; | 5683 | var multi_case_index: u32 = 0; |
| ... | @@ -5620,12 +5689,10 @@ fn switchExpr( | ... | @@ -5620,12 +5689,10 @@ fn switchExpr( |
| 5620 | else => unreachable, | 5689 | else => unreachable, |
| 5621 | }; | 5690 | }; |
| 5622 | | 5691 | |
| 5623 | // Reset the scope. | | |
| 5624 | case_scope.instructions.shrinkRetainingCapacity(0); | | |
| 5625 | | | |
| 5626 | const is_multi_case = case.ast.values.len > 1 or | 5692 | const is_multi_case = case.ast.values.len > 1 or |
| 5627 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); | 5693 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); |
| 5628 | | 5694 | |
| | 5695 | var capture_inst: Zir.Inst.Index = 0; |
| 5629 | var capture_val_scope: Scope.LocalVal = undefined; | 5696 | var capture_val_scope: Scope.LocalVal = undefined; |
| 5630 | const sub_scope = blk: { | 5697 | const sub_scope = blk: { |
| 5631 | const payload_token = case.payload_token orelse break :blk &case_scope.base; | 5698 | const payload_token = case.payload_token orelse break :blk &case_scope.base; |
| ... | @@ -5640,19 +5707,20 @@ fn switchExpr( | ... | @@ -5640,19 +5707,20 @@ fn switchExpr( |
| 5640 | } | 5707 | } |
| 5641 | break :blk &case_scope.base; | 5708 | break :blk &case_scope.base; |
| 5642 | } | 5709 | } |
| 5643 | const capture = if (case_node == special_node) capture: { | 5710 | if (case_node == special_node) { |
| 5644 | const capture_tag: Zir.Inst.Tag = if (is_ptr) | 5711 | const capture_tag: Zir.Inst.Tag = if (is_ptr) |
| 5645 | .switch_capture_else_ref | 5712 | .switch_capture_else_ref |
| 5646 | else | 5713 | else |
| 5647 | .switch_capture_else; | 5714 | .switch_capture_else; |
| 5648 | break :capture try case_scope.add(.{ | 5715 | capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| | 5716 | try astgen.instructions.append(gpa, .{ |
| 5649 | .tag = capture_tag, | 5717 | .tag = capture_tag, |
| 5650 | .data = .{ .switch_capture = .{ | 5718 | .data = .{ .switch_capture = .{ |
| 5651 | .switch_inst = switch_block, | 5719 | .switch_inst = switch_block, |
| 5652 | .prong_index = undefined, | 5720 | .prong_index = undefined, |
| 5653 | } }, | 5721 | } }, |
| 5654 | }); | 5722 | }); |
| 5655 | } else capture: { | 5723 | } else { |
| 5656 | const is_multi_case_bits: u2 = @boolToInt(is_multi_case); | 5724 | const is_multi_case_bits: u2 = @boolToInt(is_multi_case); |
| 5657 | const is_ptr_bits: u2 = @boolToInt(is_ptr); | 5725 | const is_ptr_bits: u2 = @boolToInt(is_ptr); |
| 5658 | const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) { | 5726 | const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) { |
| ... | @@ -5662,20 +5730,21 @@ fn switchExpr( | ... | @@ -5662,20 +5730,21 @@ fn switchExpr( |
| 5662 | 0b11 => .switch_capture_multi_ref, | 5730 | 0b11 => .switch_capture_multi_ref, |
| 5663 | }; | 5731 | }; |
| 5664 | const capture_index = if (is_multi_case) multi_case_index else scalar_case_index; | 5732 | const capture_index = if (is_multi_case) multi_case_index else scalar_case_index; |
| 5665 | break :capture try case_scope.add(.{ | 5733 | capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| | 5734 | try astgen.instructions.append(gpa, .{ |
| 5666 | .tag = capture_tag, | 5735 | .tag = capture_tag, |
| 5667 | .data = .{ .switch_capture = .{ | 5736 | .data = .{ .switch_capture = .{ |
| 5668 | .switch_inst = switch_block, | 5737 | .switch_inst = switch_block, |
| 5669 | .prong_index = capture_index, | 5738 | .prong_index = capture_index, |
| 5670 | } }, | 5739 | } }, |
| 5671 | }); | 5740 | }); |
| 5672 | }; | 5741 | } |
| 5673 | const capture_name = try astgen.identAsString(ident); | 5742 | const capture_name = try astgen.identAsString(ident); |
| 5674 | capture_val_scope = .{ | 5743 | capture_val_scope = .{ |
| 5675 | .parent = &case_scope.base, | 5744 | .parent = &case_scope.base, |
| 5676 | .gen_zir = &case_scope, | 5745 | .gen_zir = &case_scope, |
| 5677 | .name = capture_name, | 5746 | .name = capture_name, |
| 5678 | .inst = capture, | 5747 | .inst = indexToRef(capture_inst), |
| 5679 | .token_src = payload_token, | 5748 | .token_src = payload_token, |
| 5680 | .id_cat = .@"capture", | 5749 | .id_cat = .@"capture", |
| 5681 | }; | 5750 | }; |
| ... | @@ -5728,14 +5797,23 @@ fn switchExpr( | ... | @@ -5728,14 +5797,23 @@ fn switchExpr( |
| 5728 | break :blk header_index + 1; | 5797 | break :blk header_index + 1; |
| 5729 | }; | 5798 | }; |
| 5730 | | 5799 | |
| 5731 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); | 5800 | { |
| 5732 | try checkUsed(parent_gz, &case_scope.base, sub_scope); | 5801 | // temporarily stack case_scope on parent_gz |
| 5733 | if (!parent_gz.refIsNoReturn(case_result)) { | 5802 | case_scope.instructions_top = parent_gz.instructions.items.len; |
| 5734 | block_scope.break_count += 1; | 5803 | defer case_scope.unstack(); |
| 5735 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); | 5804 | |
| | 5805 | if (capture_inst != 0) try case_scope.instructions.append(gpa, capture_inst); |
| | 5806 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| | 5807 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| | 5808 | if (!parent_gz.refIsNoReturn(case_result)) { |
| | 5809 | block_scope.break_count += 1; |
| | 5810 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| | 5811 | } |
| | 5812 | |
| | 5813 | const case_slice = case_scope.instructionsSlice(); |
| | 5814 | payloads.items[body_len_index] = @intCast(u32, case_slice.len); |
| | 5815 | try payloads.appendSlice(gpa, case_slice); |
| 5736 | } | 5816 | } |
| 5737 | payloads.items[body_len_index] = @intCast(u32, case_scope.instructions.items.len); | | |
| 5738 | try payloads.appendSlice(gpa, case_scope.instructions.items); | | |
| 5739 | } | 5817 | } |
| 5740 | // Now that the item expressions are generated we can add this. | 5818 | // Now that the item expressions are generated we can add this. |
| 5741 | try parent_gz.instructions.append(gpa, switch_block); | 5819 | try parent_gz.instructions.append(gpa, switch_block); |
| ... | @@ -5917,13 +5995,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref | ... | @@ -5917,13 +5995,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 5917 | const condbr = try gz.addCondBr(.condbr, node); | 5995 | const condbr = try gz.addCondBr(.condbr, node); |
| 5918 | | 5996 | |
| 5919 | var then_scope = gz.makeSubBlock(scope); | 5997 | var then_scope = gz.makeSubBlock(scope); |
| 5920 | defer then_scope.instructions.deinit(astgen.gpa); | 5998 | defer then_scope.unstack(); |
| 5921 | | 5999 | |
| 5922 | try genDefers(&then_scope, defer_outer, scope, .normal_only); | 6000 | try genDefers(&then_scope, defer_outer, scope, .normal_only); |
| 5923 | try then_scope.addRet(rl, operand, node); | 6001 | try then_scope.addRet(rl, operand, node); |
| 5924 | | 6002 | |
| 5925 | var else_scope = gz.makeSubBlock(scope); | 6003 | var else_scope = gz.makeSubBlock(scope); |
| 5926 | defer else_scope.instructions.deinit(astgen.gpa); | 6004 | defer else_scope.unstack(); |
| 5927 | | 6005 | |
| 5928 | const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{ | 6006 | const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{ |
| 5929 | .both = try else_scope.addUnNode(.err_union_code, result, node), | 6007 | .both = try else_scope.addUnNode(.err_union_code, result, node), |
| ... | @@ -5931,7 +6009,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref | ... | @@ -5931,7 +6009,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 5931 | try genDefers(&else_scope, defer_outer, scope, which_ones); | 6009 | try genDefers(&else_scope, defer_outer, scope, which_ones); |
| 5932 | try else_scope.addRet(rl, operand, node); | 6010 | try else_scope.addRet(rl, operand, node); |
| 5933 | | 6011 | |
| 5934 | try setCondBrPayload(condbr, is_non_err, &then_scope, &else_scope); | 6012 | try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0); |
| 5935 | | 6013 | |
| 5936 | return Zir.Inst.Ref.unreachable_value; | 6014 | return Zir.Inst.Ref.unreachable_value; |
| 5937 | }, | 6015 | }, |
| ... | @@ -6561,10 +6639,8 @@ fn asRlPtr( | ... | @@ -6561,10 +6639,8 @@ fn asRlPtr( |
| 6561 | operand_node: Ast.Node.Index, | 6639 | operand_node: Ast.Node.Index, |
| 6562 | dest_type: Zir.Inst.Ref, | 6640 | dest_type: Zir.Inst.Ref, |
| 6563 | ) InnerError!Zir.Inst.Ref { | 6641 | ) InnerError!Zir.Inst.Ref { |
| 6564 | const astgen = parent_gz.astgen; | | |
| 6565 | | | |
| 6566 | var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr); | 6642 | var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr); |
| 6567 | defer as_scope.instructions.deinit(astgen.gpa); | 6643 | defer as_scope.unstack(); |
| 6568 | | 6644 | |
| 6569 | const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node); | 6645 | const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node); |
| 6570 | return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type); | 6646 | return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type); |
| ... | @@ -7336,14 +7412,15 @@ fn cImport( | ... | @@ -7336,14 +7412,15 @@ fn cImport( |
| 7336 | var block_scope = gz.makeSubBlock(scope); | 7412 | var block_scope = gz.makeSubBlock(scope); |
| 7337 | block_scope.force_comptime = true; | 7413 | block_scope.force_comptime = true; |
| 7338 | block_scope.c_import = true; | 7414 | block_scope.c_import = true; |
| 7339 | defer block_scope.instructions.deinit(gpa); | 7415 | defer block_scope.unstack(); |
| 7340 | | 7416 | |
| 7341 | const block_inst = try gz.addBlock(.c_import, node); | 7417 | const block_inst = try gz.makeBlockInst(.c_import, node); |
| 7342 | const block_result = try expr(&block_scope, &block_scope.base, .none, body_node); | 7418 | const block_result = try expr(&block_scope, &block_scope.base, .none, body_node); |
| 7343 | if (!gz.refIsNoReturn(block_result)) { | 7419 | if (!gz.refIsNoReturn(block_result)) { |
| 7344 | _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); | 7420 | _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); |
| 7345 | } | 7421 | } |
| 7346 | try block_scope.setBlockBody(block_inst); | 7422 | try block_scope.setBlockBody(block_inst); |
| | 7423 | // block_scope unstacked now, can add new instructions to gz |
| 7347 | try gz.instructions.append(gpa, block_inst); | 7424 | try gz.instructions.append(gpa, block_inst); |
| 7348 | | 7425 | |
| 7349 | return indexToRef(block_inst); | 7426 | return indexToRef(block_inst); |
| ... | @@ -8167,6 +8244,7 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { | ... | @@ -8167,6 +8244,7 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 8167 | /// result locations must call this function on their result. | 8244 | /// result locations must call this function on their result. |
| 8168 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. | 8245 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. |
| 8169 | /// If the `ResultLoc` is `ty`, it will coerce the result to the type. | 8246 | /// If the `ResultLoc` is `ty`, it will coerce the result to the type. |
| | 8247 | /// Assumes nothing stacked on `gz`. |
| 8170 | fn rvalue( | 8248 | fn rvalue( |
| 8171 | gz: *GenZir, | 8249 | gz: *GenZir, |
| 8172 | rl: ResultLoc, | 8250 | rl: ResultLoc, |
| ... | @@ -8779,9 +8857,12 @@ const GenZir = struct { | ... | @@ -8779,9 +8857,12 @@ const GenZir = struct { |
| 8779 | parent: *Scope, | 8857 | parent: *Scope, |
| 8780 | /// All `GenZir` scopes for the same ZIR share this. | 8858 | /// All `GenZir` scopes for the same ZIR share this. |
| 8781 | astgen: *AstGen, | 8859 | astgen: *AstGen, |
| 8782 | /// Keeps track of the list of instructions in this scope only. Indexes | 8860 | /// Keeps track of the list of instructions in this scope. Possibly shared. |
| 8783 | /// to instructions in `astgen`. | 8861 | /// Indexes to instructions in `astgen`. |
| 8784 | instructions: ArrayListUnmanaged(Zir.Inst.Index) = .{}, | 8862 | instructions: *ArrayListUnmanaged(Zir.Inst.Index), |
| | 8863 | /// A sub-block may share its instructions ArrayList with containing GenZir, |
| | 8864 | /// if use is strictly nested. This saves prior size of list for unstacking. |
| | 8865 | instructions_top: usize, |
| 8785 | label: ?Label = null, | 8866 | label: ?Label = null, |
| 8786 | break_block: Zir.Inst.Index = 0, | 8867 | break_block: Zir.Inst.Index = 0, |
| 8787 | continue_block: Zir.Inst.Index = 0, | 8868 | continue_block: Zir.Inst.Index = 0, |
| ... | @@ -8817,6 +8898,36 @@ const GenZir = struct { | ... | @@ -8817,6 +8898,36 @@ const GenZir = struct { |
| 8817 | /// Keys are the raw instruction index, values are the closure_capture instruction. | 8898 | /// Keys are the raw instruction index, values are the closure_capture instruction. |
| 8818 | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, | 8899 | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, |
| 8819 | | 8900 | |
| | 8901 | const unstacked_top = std.math.maxInt(usize); |
| | 8902 | /// Call unstack before adding any new instructions to containing GenZir. |
| | 8903 | fn unstack(self: *GenZir) void { |
| | 8904 | if (self.instructions_top != unstacked_top) { |
| | 8905 | self.instructions.items.len = self.instructions_top; |
| | 8906 | self.instructions_top = unstacked_top; |
| | 8907 | } |
| | 8908 | } |
| | 8909 | |
| | 8910 | fn isEmpty(self: *const GenZir) bool { |
| | 8911 | return (self.instructions_top == unstacked_top) or |
| | 8912 | (self.instructions.items.len == self.instructions_top); |
| | 8913 | } |
| | 8914 | |
| | 8915 | fn instructionsSlice(self: *const GenZir) []Zir.Inst.Index { |
| | 8916 | return if (self.instructions_top == unstacked_top) |
| | 8917 | &[0]Zir.Inst.Index{} |
| | 8918 | else |
| | 8919 | self.instructions.items[self.instructions_top..]; |
| | 8920 | } |
| | 8921 | |
| | 8922 | fn instructionsSliceUpto(self: *const GenZir, stacked_gz: *GenZir) []Zir.Inst.Index { |
| | 8923 | return if (self.instructions_top == unstacked_top) |
| | 8924 | &[0]Zir.Inst.Index{} |
| | 8925 | else if (self.instructions == stacked_gz.instructions and stacked_gz.instructions_top != unstacked_top) |
| | 8926 | self.instructions.items[self.instructions_top..stacked_gz.instructions_top] |
| | 8927 | else |
| | 8928 | self.instructions.items[self.instructions_top..]; |
| | 8929 | } |
| | 8930 | |
| 8820 | fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { | 8931 | fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { |
| 8821 | return .{ | 8932 | return .{ |
| 8822 | .force_comptime = gz.force_comptime, | 8933 | .force_comptime = gz.force_comptime, |
| ... | @@ -8828,6 +8939,8 @@ const GenZir = struct { | ... | @@ -8828,6 +8939,8 @@ const GenZir = struct { |
| 8828 | .astgen = gz.astgen, | 8939 | .astgen = gz.astgen, |
| 8829 | .suspend_node = gz.suspend_node, | 8940 | .suspend_node = gz.suspend_node, |
| 8830 | .nosuspend_node = gz.nosuspend_node, | 8941 | .nosuspend_node = gz.nosuspend_node, |
| | 8942 | .instructions = gz.instructions, |
| | 8943 | .instructions_top = gz.instructions.items.len, |
| 8831 | }; | 8944 | }; |
| 8832 | } | 8945 | } |
| 8833 | | 8946 | |
| ... | @@ -8841,12 +8954,13 @@ const GenZir = struct { | ... | @@ -8841,12 +8954,13 @@ const GenZir = struct { |
| 8841 | // result location. If it does, elide the coerce_result_ptr instruction | 8954 | // result location. If it does, elide the coerce_result_ptr instruction |
| 8842 | // as well as the store instruction, instead passing the result as an rvalue. | 8955 | // as well as the store instruction, instead passing the result as an rvalue. |
| 8843 | var as_scope = parent_gz.makeSubBlock(scope); | 8956 | var as_scope = parent_gz.makeSubBlock(scope); |
| 8844 | errdefer as_scope.instructions.deinit(parent_gz.astgen.gpa); | 8957 | errdefer as_scope.unstack(); |
| 8845 | as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); | 8958 | as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); |
| 8846 | | 8959 | |
| 8847 | return as_scope; | 8960 | return as_scope; |
| 8848 | } | 8961 | } |
| 8849 | | 8962 | |
| | 8963 | /// Assumes `as_scope` is stacked immediately on top of `parent_gz`. Unstacks `as_scope`. |
| 8850 | fn finishCoercion( | 8964 | fn finishCoercion( |
| 8851 | as_scope: *GenZir, | 8965 | as_scope: *GenZir, |
| 8852 | parent_gz: *GenZir, | 8966 | parent_gz: *GenZir, |
| ... | @@ -8854,25 +8968,32 @@ const GenZir = struct { | ... | @@ -8854,25 +8968,32 @@ const GenZir = struct { |
| 8854 | src_node: Ast.Node.Index, | 8968 | src_node: Ast.Node.Index, |
| 8855 | result: Zir.Inst.Ref, | 8969 | result: Zir.Inst.Ref, |
| 8856 | dest_type: Zir.Inst.Ref, | 8970 | dest_type: Zir.Inst.Ref, |
| 8857 | ) !Zir.Inst.Ref { | 8971 | ) InnerError!Zir.Inst.Ref { |
| | 8972 | assert(as_scope.instructions == parent_gz.instructions); |
| 8858 | const astgen = as_scope.astgen; | 8973 | const astgen = as_scope.astgen; |
| 8859 | const parent_zir = &parent_gz.instructions; | | |
| 8860 | if (as_scope.rvalue_rl_count == 1) { | 8974 | if (as_scope.rvalue_rl_count == 1) { |
| 8861 | // Busted! This expression didn't actually need a pointer. | 8975 | // Busted! This expression didn't actually need a pointer. |
| 8862 | const zir_tags = astgen.instructions.items(.tag); | 8976 | const zir_tags = astgen.instructions.items(.tag); |
| 8863 | const zir_datas = astgen.instructions.items(.data); | 8977 | const zir_datas = astgen.instructions.items(.data); |
| 8864 | try parent_zir.ensureUnusedCapacity(astgen.gpa, as_scope.instructions.items.len); | 8978 | var src: usize = as_scope.instructions_top; |
| 8865 | for (as_scope.instructions.items) |src_inst| { | 8979 | var dst: usize = src; |
| | 8980 | while (src < as_scope.instructions.items.len) : (src += 1) { |
| | 8981 | const src_inst = as_scope.instructions.items[src]; |
| 8866 | if (indexToRef(src_inst) == as_scope.rl_ptr) continue; | 8982 | if (indexToRef(src_inst) == as_scope.rl_ptr) continue; |
| 8867 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 8983 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 8868 | if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue; | 8984 | if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue; |
| 8869 | } | 8985 | } |
| 8870 | parent_zir.appendAssumeCapacity(src_inst); | 8986 | as_scope.instructions.items[dst] = src_inst; |
| | 8987 | dst += 1; |
| 8871 | } | 8988 | } |
| | 8989 | parent_gz.instructions.items.len -= src - dst; |
| | 8990 | as_scope.instructions_top = GenZir.unstacked_top; |
| | 8991 | // as_scope now unstacked, can add new instructions to parent_gz |
| 8872 | const casted_result = try parent_gz.addBin(.as, dest_type, result); | 8992 | const casted_result = try parent_gz.addBin(.as, dest_type, result); |
| 8873 | return rvalue(parent_gz, rl, casted_result, src_node); | 8993 | return rvalue(parent_gz, rl, casted_result, src_node); |
| 8874 | } else { | 8994 | } else { |
| 8875 | try parent_zir.appendSlice(astgen.gpa, as_scope.instructions.items); | 8995 | // implicitly move all as_scope instructions to parent_gz |
| | 8996 | as_scope.instructions_top = GenZir.unstacked_top; |
| 8876 | return result; | 8997 | return result; |
| 8877 | } | 8998 | } |
| 8878 | } | 8999 | } |
| ... | @@ -8883,9 +9004,10 @@ const GenZir = struct { | ... | @@ -8883,9 +9004,10 @@ const GenZir = struct { |
| 8883 | used: bool = false, | 9004 | used: bool = false, |
| 8884 | }; | 9005 | }; |
| 8885 | | 9006 | |
| | 9007 | /// Assumes nothing stacked on `gz`. |
| 8886 | fn endsWithNoReturn(gz: GenZir) bool { | 9008 | fn endsWithNoReturn(gz: GenZir) bool { |
| | 9009 | if (gz.isEmpty()) return false; |
| 8887 | const tags = gz.astgen.instructions.items(.tag); | 9010 | const tags = gz.astgen.instructions.items(.tag); |
| 8888 | if (gz.instructions.items.len == 0) return false; | | |
| 8889 | const last_inst = gz.instructions.items[gz.instructions.items.len - 1]; | 9011 | const last_inst = gz.instructions.items[gz.instructions.items.len - 1]; |
| 8890 | return tags[last_inst].isNoReturn(); | 9012 | return tags[last_inst].isNoReturn(); |
| 8891 | } | 9013 | } |
| ... | @@ -8955,41 +9077,46 @@ const GenZir = struct { | ... | @@ -8955,41 +9077,46 @@ const GenZir = struct { |
| 8955 | } | 9077 | } |
| 8956 | } | 9078 | } |
| 8957 | | 9079 | |
| 8958 | fn setBoolBrBody(gz: GenZir, inst: Zir.Inst.Index) !void { | 9080 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| | 9081 | fn setBoolBrBody(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 8959 | const gpa = gz.astgen.gpa; | 9082 | const gpa = gz.astgen.gpa; |
| 8960 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + | 9083 | const body = gz.instructionsSlice(); |
| 8961 | gz.instructions.items.len); | 9084 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 8962 | const zir_datas = gz.astgen.instructions.items(.data); | 9085 | const zir_datas = gz.astgen.instructions.items(.data); |
| 8963 | zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity( | 9086 | zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 8964 | Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) }, | 9087 | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, |
| 8965 | ); | 9088 | ); |
| 8966 | gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items); | 9089 | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| | 9090 | gz.unstack(); |
| 8967 | } | 9091 | } |
| 8968 | | 9092 | |
| 8969 | fn setBlockBody(gz: GenZir, inst: Zir.Inst.Index) !void { | 9093 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| | 9094 | fn setBlockBody(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 8970 | const gpa = gz.astgen.gpa; | 9095 | const gpa = gz.astgen.gpa; |
| 8971 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + | 9096 | const body = gz.instructionsSlice(); |
| 8972 | gz.instructions.items.len); | 9097 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 8973 | const zir_datas = gz.astgen.instructions.items(.data); | 9098 | const zir_datas = gz.astgen.instructions.items(.data); |
| 8974 | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( | 9099 | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 8975 | Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) }, | 9100 | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, |
| 8976 | ); | 9101 | ); |
| 8977 | gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items); | 9102 | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| | 9103 | gz.unstack(); |
| 8978 | } | 9104 | } |
| 8979 | | 9105 | |
| 8980 | /// Same as `setBlockBody` except we don't copy instructions which are | 9106 | /// Same as `setBlockBody` except we don't copy instructions which are |
| 8981 | /// `store_to_block_ptr` instructions with lhs set to .none. | 9107 | /// `store_to_block_ptr` instructions with lhs set to .none. |
| 8982 | fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void { | 9108 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| | 9109 | fn setBlockBodyEliding(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 8983 | const gpa = gz.astgen.gpa; | 9110 | const gpa = gz.astgen.gpa; |
| 8984 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + | 9111 | const body = gz.instructionsSlice(); |
| 8985 | gz.instructions.items.len); | 9112 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 8986 | const zir_datas = gz.astgen.instructions.items(.data); | 9113 | const zir_datas = gz.astgen.instructions.items(.data); |
| 8987 | const zir_tags = gz.astgen.instructions.items(.tag); | 9114 | const zir_tags = gz.astgen.instructions.items(.tag); |
| 8988 | const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{ | 9115 | const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{ |
| 8989 | .body_len = @intCast(u32, gz.instructions.items.len), | 9116 | .body_len = @intCast(u32, body.len), |
| 8990 | }); | 9117 | }); |
| 8991 | zir_datas[inst].pl_node.payload_index = block_pl_index; | 9118 | zir_datas[inst].pl_node.payload_index = block_pl_index; |
| 8992 | for (gz.instructions.items) |sub_inst| { | 9119 | for (body) |sub_inst| { |
| 8993 | if (zir_tags[sub_inst] == .store_to_block_ptr and | 9120 | if (zir_tags[sub_inst] == .store_to_block_ptr and |
| 8994 | zir_datas[sub_inst].bin.lhs == .none) | 9121 | zir_datas[sub_inst].bin.lhs == .none) |
| 8995 | { | 9122 | { |
| ... | @@ -8999,15 +9126,17 @@ const GenZir = struct { | ... | @@ -8999,15 +9126,17 @@ const GenZir = struct { |
| 8999 | } | 9126 | } |
| 9000 | gz.astgen.extra.appendAssumeCapacity(sub_inst); | 9127 | gz.astgen.extra.appendAssumeCapacity(sub_inst); |
| 9001 | } | 9128 | } |
| | 9129 | gz.unstack(); |
| 9002 | } | 9130 | } |
| 9003 | | 9131 | |
| | 9132 | /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`. |
| 9004 | fn addFunc(gz: *GenZir, args: struct { | 9133 | fn addFunc(gz: *GenZir, args: struct { |
| 9005 | src_node: Ast.Node.Index, | 9134 | src_node: Ast.Node.Index, |
| 9006 | lbrace_line: u32 = 0, | 9135 | lbrace_line: u32 = 0, |
| 9007 | lbrace_column: u32 = 0, | 9136 | lbrace_column: u32 = 0, |
| 9008 | body: []const Zir.Inst.Index, | 9137 | body_gz: ?*GenZir, |
| 9009 | param_block: Zir.Inst.Index, | 9138 | param_block: Zir.Inst.Index, |
| 9010 | ret_ty: []const Zir.Inst.Index, | 9139 | ret_gz: ?*GenZir, |
| 9011 | ret_br: Zir.Inst.Index, | 9140 | ret_br: Zir.Inst.Index, |
| 9012 | cc: Zir.Inst.Ref, | 9141 | cc: Zir.Inst.Ref, |
| 9013 | align_inst: Zir.Inst.Ref, | 9142 | align_inst: Zir.Inst.Ref, |
| ... | @@ -9021,12 +9150,13 @@ const GenZir = struct { | ... | @@ -9021,12 +9150,13 @@ const GenZir = struct { |
| 9021 | const astgen = gz.astgen; | 9150 | const astgen = gz.astgen; |
| 9022 | const gpa = astgen.gpa; | 9151 | const gpa = astgen.gpa; |
| 9023 | | 9152 | |
| 9024 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | | |
| 9025 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); | 9153 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9026 | | 9154 | |
| | 9155 | var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; |
| | 9156 | var ret_ty: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; |
| 9027 | var src_locs_buffer: [3]u32 = undefined; | 9157 | var src_locs_buffer: [3]u32 = undefined; |
| 9028 | var src_locs: []u32 = src_locs_buffer[0..0]; | 9158 | var src_locs: []u32 = src_locs_buffer[0..0]; |
| 9029 | if (args.body.len != 0) { | 9159 | if (args.body_gz) |body_gz| { |
| 9030 | const tree = astgen.tree; | 9160 | const tree = astgen.tree; |
| 9031 | const node_tags = tree.nodes.items(.tag); | 9161 | const node_tags = tree.nodes.items(.tag); |
| 9032 | const node_datas = tree.nodes.items(.data); | 9162 | const node_datas = tree.nodes.items(.data); |
| ... | @@ -9044,6 +9174,13 @@ const GenZir = struct { | ... | @@ -9044,6 +9174,13 @@ const GenZir = struct { |
| 9044 | src_locs_buffer[1] = rbrace_line; | 9174 | src_locs_buffer[1] = rbrace_line; |
| 9045 | src_locs_buffer[2] = columns; | 9175 | src_locs_buffer[2] = columns; |
| 9046 | src_locs = &src_locs_buffer; | 9176 | src_locs = &src_locs_buffer; |
| | 9177 | |
| | 9178 | body = body_gz.instructionsSlice(); |
| | 9179 | if (args.ret_gz) |ret_gz| |
| | 9180 | ret_ty = ret_gz.instructionsSliceUpto(body_gz); |
| | 9181 | } else { |
| | 9182 | if (args.ret_gz) |ret_gz| |
| | 9183 | ret_ty = ret_gz.instructionsSlice(); |
| 9047 | } | 9184 | } |
| 9048 | | 9185 | |
| 9049 | if (args.cc != .none or args.lib_name != 0 or | 9186 | if (args.cc != .none or args.lib_name != 0 or |
| ... | @@ -9053,7 +9190,7 @@ const GenZir = struct { | ... | @@ -9053,7 +9190,7 @@ const GenZir = struct { |
| 9053 | try astgen.extra.ensureUnusedCapacity( | 9190 | try astgen.extra.ensureUnusedCapacity( |
| 9054 | gpa, | 9191 | gpa, |
| 9055 | @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len + | 9192 | @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len + |
| 9056 | args.ret_ty.len + args.body.len + src_locs.len + | 9193 | ret_ty.len + body.len + src_locs.len + |
| 9057 | @boolToInt(args.lib_name != 0) + | 9194 | @boolToInt(args.lib_name != 0) + |
| 9058 | @boolToInt(args.align_inst != .none) + | 9195 | @boolToInt(args.align_inst != .none) + |
| 9059 | @boolToInt(args.cc != .none), | 9196 | @boolToInt(args.cc != .none), |
| ... | @@ -9061,8 +9198,8 @@ const GenZir = struct { | ... | @@ -9061,8 +9198,8 @@ const GenZir = struct { |
| 9061 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{ | 9198 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{ |
| 9062 | .src_node = gz.nodeIndexToRelative(args.src_node), | 9199 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 9063 | .param_block = args.param_block, | 9200 | .param_block = args.param_block, |
| 9064 | .ret_body_len = @intCast(u32, args.ret_ty.len), | 9201 | .ret_body_len = @intCast(u32, ret_ty.len), |
| 9065 | .body_len = @intCast(u32, args.body.len), | 9202 | .body_len = @intCast(u32, body.len), |
| 9066 | }); | 9203 | }); |
| 9067 | if (args.lib_name != 0) { | 9204 | if (args.lib_name != 0) { |
| 9068 | astgen.extra.appendAssumeCapacity(args.lib_name); | 9205 | astgen.extra.appendAssumeCapacity(args.lib_name); |
| ... | @@ -9073,9 +9210,13 @@ const GenZir = struct { | ... | @@ -9073,9 +9210,13 @@ const GenZir = struct { |
| 9073 | if (args.align_inst != .none) { | 9210 | if (args.align_inst != .none) { |
| 9074 | astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst)); | 9211 | astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst)); |
| 9075 | } | 9212 | } |
| 9076 | astgen.extra.appendSliceAssumeCapacity(args.ret_ty); | 9213 | astgen.extra.appendSliceAssumeCapacity(ret_ty); |
| 9077 | astgen.extra.appendSliceAssumeCapacity(args.body); | 9214 | astgen.extra.appendSliceAssumeCapacity(body); |
| 9078 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 9215 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| | 9216 | // order is important when unstacking |
| | 9217 | if (args.body_gz) |body_gz| body_gz.unstack(); |
| | 9218 | if (args.ret_gz) |ret_gz| ret_gz.unstack(); |
| | 9219 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9079 | | 9220 | |
| 9080 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | 9221 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 9081 | if (args.ret_br != 0) { | 9222 | if (args.ret_br != 0) { |
| ... | @@ -9103,17 +9244,21 @@ const GenZir = struct { | ... | @@ -9103,17 +9244,21 @@ const GenZir = struct { |
| 9103 | try astgen.extra.ensureUnusedCapacity( | 9244 | try astgen.extra.ensureUnusedCapacity( |
| 9104 | gpa, | 9245 | gpa, |
| 9105 | @typeInfo(Zir.Inst.Func).Struct.fields.len + | 9246 | @typeInfo(Zir.Inst.Func).Struct.fields.len + |
| 9106 | args.ret_ty.len + args.body.len + src_locs.len, | 9247 | ret_ty.len + body.len + src_locs.len, |
| 9107 | ); | 9248 | ); |
| 9108 | | 9249 | |
| 9109 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{ | 9250 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{ |
| 9110 | .param_block = args.param_block, | 9251 | .param_block = args.param_block, |
| 9111 | .ret_body_len = @intCast(u32, args.ret_ty.len), | 9252 | .ret_body_len = @intCast(u32, ret_ty.len), |
| 9112 | .body_len = @intCast(u32, args.body.len), | 9253 | .body_len = @intCast(u32, body.len), |
| 9113 | }); | 9254 | }); |
| 9114 | astgen.extra.appendSliceAssumeCapacity(args.ret_ty); | 9255 | astgen.extra.appendSliceAssumeCapacity(ret_ty); |
| 9115 | astgen.extra.appendSliceAssumeCapacity(args.body); | 9256 | astgen.extra.appendSliceAssumeCapacity(body); |
| 9116 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 9257 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| | 9258 | // order is important when unstacking |
| | 9259 | if (args.body_gz) |body_gz| body_gz.unstack(); |
| | 9260 | if (args.ret_gz) |ret_gz| ret_gz.unstack(); |
| | 9261 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9117 | | 9262 | |
| 9118 | const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func; | 9263 | const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func; |
| 9119 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | 9264 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| ... | @@ -9260,6 +9405,25 @@ const GenZir = struct { | ... | @@ -9260,6 +9405,25 @@ const GenZir = struct { |
| 9260 | }); | 9405 | }); |
| 9261 | } | 9406 | } |
| 9262 | | 9407 | |
| | 9408 | fn makeUnNode( |
| | 9409 | gz: *GenZir, |
| | 9410 | tag: Zir.Inst.Tag, |
| | 9411 | operand: Zir.Inst.Ref, |
| | 9412 | /// Absolute node index. This function does the conversion to offset from Decl. |
| | 9413 | src_node: Ast.Node.Index, |
| | 9414 | ) !Zir.Inst.Index { |
| | 9415 | assert(operand != .none); |
| | 9416 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| | 9417 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ |
| | 9418 | .tag = tag, |
| | 9419 | .data = .{ .un_node = .{ |
| | 9420 | .operand = operand, |
| | 9421 | .src_node = gz.nodeIndexToRelative(src_node), |
| | 9422 | } }, |
| | 9423 | }); |
| | 9424 | return new_index; |
| | 9425 | } |
| | 9426 | |
| 9263 | fn addPlNode( | 9427 | fn addPlNode( |
| 9264 | gz: *GenZir, | 9428 | gz: *GenZir, |
| 9265 | tag: Zir.Inst.Tag, | 9429 | tag: Zir.Inst.Tag, |
| ... | @@ -9300,25 +9464,27 @@ const GenZir = struct { | ... | @@ -9300,25 +9464,27 @@ const GenZir = struct { |
| 9300 | }); | 9464 | }); |
| 9301 | } | 9465 | } |
| 9302 | | 9466 | |
| | 9467 | /// Supports `param_gz` stacked on `gz`. Assumes nothing stacked on `param_gz`. Unstacks `param_gz`. |
| 9303 | fn addParam( | 9468 | fn addParam( |
| 9304 | gz: *GenZir, | 9469 | gz: *GenZir, |
| | 9470 | param_gz: *GenZir, |
| 9305 | tag: Zir.Inst.Tag, | 9471 | tag: Zir.Inst.Tag, |
| 9306 | /// Absolute token index. This function does the conversion to Decl offset. | 9472 | /// Absolute token index. This function does the conversion to Decl offset. |
| 9307 | abs_tok_index: Ast.TokenIndex, | 9473 | abs_tok_index: Ast.TokenIndex, |
| 9308 | name: u32, | 9474 | name: u32, |
| 9309 | body: []const u32, | | |
| 9310 | ) !Zir.Inst.Index { | 9475 | ) !Zir.Inst.Index { |
| 9311 | const gpa = gz.astgen.gpa; | 9476 | const gpa = gz.astgen.gpa; |
| 9312 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | 9477 | const param_body = param_gz.instructionsSlice(); |
| 9313 | try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); | 9478 | try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9314 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len + | 9479 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len + |
| 9315 | body.len); | 9480 | param_body.len); |
| 9316 | | 9481 | |
| 9317 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{ | 9482 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{ |
| 9318 | .name = name, | 9483 | .name = name, |
| 9319 | .body_len = @intCast(u32, body.len), | 9484 | .body_len = @intCast(u32, param_body.len), |
| 9320 | }); | 9485 | }); |
| 9321 | gz.astgen.extra.appendSliceAssumeCapacity(body); | 9486 | gz.astgen.extra.appendSliceAssumeCapacity(param_body); |
| | 9487 | param_gz.unstack(); |
| 9322 | | 9488 | |
| 9323 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | 9489 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 9324 | gz.astgen.instructions.appendAssumeCapacity(.{ | 9490 | gz.astgen.instructions.appendAssumeCapacity(.{ |
| ... | @@ -9461,6 +9627,23 @@ const GenZir = struct { | ... | @@ -9461,6 +9627,23 @@ const GenZir = struct { |
| 9461 | }); | 9627 | }); |
| 9462 | } | 9628 | } |
| 9463 | | 9629 | |
| | 9630 | fn makeBreak( |
| | 9631 | gz: *GenZir, |
| | 9632 | tag: Zir.Inst.Tag, |
| | 9633 | break_block: Zir.Inst.Index, |
| | 9634 | operand: Zir.Inst.Ref, |
| | 9635 | ) !Zir.Inst.Index { |
| | 9636 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| | 9637 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ |
| | 9638 | .tag = tag, |
| | 9639 | .data = .{ .@"break" = .{ |
| | 9640 | .block_inst = break_block, |
| | 9641 | .operand = operand, |
| | 9642 | } }, |
| | 9643 | }); |
| | 9644 | return new_index; |
| | 9645 | } |
| | 9646 | |
| 9464 | fn addBin( | 9647 | fn addBin( |
| 9465 | gz: *GenZir, | 9648 | gz: *GenZir, |
| 9466 | tag: Zir.Inst.Tag, | 9649 | tag: Zir.Inst.Tag, |
| ... | @@ -9649,7 +9832,7 @@ const GenZir = struct { | ... | @@ -9649,7 +9832,7 @@ const GenZir = struct { |
| 9649 | /// Note that this returns a `Zir.Inst.Index` not a ref. | 9832 | /// Note that this returns a `Zir.Inst.Index` not a ref. |
| 9650 | /// Does *not* append the block instruction to the scope. | 9833 | /// Does *not* append the block instruction to the scope. |
| 9651 | /// Leaves the `payload_index` field undefined. | 9834 | /// Leaves the `payload_index` field undefined. |
| 9652 | fn addBlock(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index { | 9835 | fn makeBlockInst(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index { |
| 9653 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | 9836 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 9654 | const gpa = gz.astgen.gpa; | 9837 | const gpa = gz.astgen.gpa; |
| 9655 | try gz.astgen.instructions.append(gpa, .{ | 9838 | try gz.astgen.instructions.append(gpa, .{ |