| author | |
| committer | |
| log | 0224ad19b82bb307a2c246f2e30826af599aa895 |
| tree | e620d0d10e6d406ec5da5cb8e6f63ad520bdfe6e |
| parent | 33826a6a2e035d2a2be65314ed80a6b7abaf7f12 |
This introduces two ZIR instructions:
* `try`
* `try_inline`
This is part of an effort to implement #11772.4 files changed, 150 insertions(+), 67 deletions(-)
src/AstGen.zig+33-53| ... | @@ -2425,6 +2425,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner | ... | @@ -2425,6 +2425,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2425 | .param_type, | 2425 | .param_type, |
| 2426 | .ret_ptr, | 2426 | .ret_ptr, |
| 2427 | .ret_type, | 2427 | .ret_type, |
| 2428 | .@"try", | ||
| 2429 | .try_inline, | ||
| 2428 | => break :b false, | 2430 | => break :b false, |
| 2429 | 2431 | ||
| 2430 | .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) { | 2432 | .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) { |
| ... | @@ -4871,68 +4873,30 @@ fn tryExpr( | ... | @@ -4871,68 +4873,30 @@ fn tryExpr( |
| 4871 | 4873 | ||
| 4872 | if (parent_gz.in_defer) return astgen.failNode(node, "'try' not allowed inside defer expression", .{}); | 4874 | if (parent_gz.in_defer) return astgen.failNode(node, "'try' not allowed inside defer expression", .{}); |
| 4873 | 4875 | ||
| 4874 | var block_scope = parent_gz.makeSubBlock(scope); | 4876 | const operand_rl: ResultLoc = switch (rl) { |
| 4875 | block_scope.setBreakResultLoc(rl); | ||
| 4876 | defer block_scope.unstack(); | ||
| 4877 | |||
| 4878 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { | ||
| 4879 | .ref => .ref, | 4877 | .ref => .ref, |
| 4880 | else => .none, | 4878 | else => .none, |
| 4881 | }; | 4879 | }; |
| 4882 | const err_ops = switch (operand_rl) { | 4880 | // This could be a pointer or value depending on the `rl` parameter. |
| 4883 | // zig fmt: off | 4881 | const operand = try expr(parent_gz, scope, operand_rl, operand_node); |
| 4884 | .ref => [3]Zir.Inst.Tag{ .is_non_err_ptr, .err_union_code_ptr, .err_union_payload_unsafe_ptr }, | 4882 | const is_inline = parent_gz.force_comptime; |
| 4885 | else => [3]Zir.Inst.Tag{ .is_non_err, .err_union_code, .err_union_payload_unsafe }, | 4883 | const block_tag: Zir.Inst.Tag = if (is_inline) .try_inline else .@"try"; |
| 4886 | // zig fmt: on | 4884 | const try_inst = try parent_gz.makeBlockInst(block_tag, node); |
| 4887 | }; | 4885 | try parent_gz.instructions.append(astgen.gpa, try_inst); |
| 4888 | // This could be a pointer or value depending on the `operand_rl` parameter. | ||
| 4889 | // We cannot use `block_scope.break_result_loc` because that has the bare | ||
| 4890 | // type, whereas this expression has the optional type. Later we make | ||
| 4891 | // up for this fact by calling rvalue on the else branch. | ||
| 4892 | const operand = try expr(&block_scope, &block_scope.base, operand_rl, operand_node); | ||
| 4893 | const cond = try block_scope.addUnNode(err_ops[0], operand, node); | ||
| 4894 | const condbr = try block_scope.addCondBr(.condbr, node); | ||
| 4895 | 4886 | ||
| 4896 | const block = try parent_gz.makeBlockInst(.block, node); | ||
| 4897 | try block_scope.setBlockBody(block); | ||
| 4898 | // block_scope unstacked now, can add new instructions to parent_gz | ||
| 4899 | try parent_gz.instructions.append(astgen.gpa, block); | ||
| 4900 | |||
| 4901 | var then_scope = parent_gz.makeSubBlock(scope); | ||
| 4902 | defer then_scope.unstack(); | ||
| 4903 | |||
| 4904 | block_scope.break_count += 1; | ||
| 4905 | // This could be a pointer or value depending on `err_ops[2]`. | ||
| 4906 | const unwrapped_payload = try then_scope.addUnNode(err_ops[2], operand, node); | ||
| 4907 | const then_result = switch (rl) { | ||
| 4908 | .ref => unwrapped_payload, | ||
| 4909 | else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node), | ||
| 4910 | }; | ||
| 4911 | |||
| 4912 | // else_scope will be stacked on then_scope as both are stacked on parent_gz | ||
| 4913 | var else_scope = parent_gz.makeSubBlock(scope); | 4887 | var else_scope = parent_gz.makeSubBlock(scope); |
| 4914 | defer else_scope.unstack(); | 4888 | defer else_scope.unstack(); |
| 4915 | 4889 | ||
| 4916 | const err_code = try else_scope.addUnNode(err_ops[1], operand, node); | 4890 | const err_tag = switch (rl) { |
| 4891 | .ref => Zir.Inst.Tag.err_union_code_ptr, | ||
| 4892 | else => Zir.Inst.Tag.err_union_code, | ||
| 4893 | }; | ||
| 4894 | const err_code = try else_scope.addUnNode(err_tag, operand, node); | ||
| 4917 | try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code }); | 4895 | try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code }); |
| 4918 | const else_result = try else_scope.addUnNode(.ret_node, err_code, node); | 4896 | _ = try else_scope.addUnNode(.ret_node, err_code, node); |
| 4919 | 4897 | ||
| 4920 | const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break"; | 4898 | try else_scope.setTryBody(try_inst, operand); |
| 4921 | return finishThenElseBlock( | 4899 | return indexToRef(try_inst); |
| 4922 | parent_gz, | ||
| 4923 | rl, | ||
| 4924 | node, | ||
| 4925 | &block_scope, | ||
| 4926 | &then_scope, | ||
| 4927 | &else_scope, | ||
| 4928 | condbr, | ||
| 4929 | cond, | ||
| 4930 | then_result, | ||
| 4931 | else_result, | ||
| 4932 | block, | ||
| 4933 | block, | ||
| 4934 | break_tag, | ||
| 4935 | ); | ||
| 4936 | } | 4900 | } |
| 4937 | 4901 | ||
| 4938 | fn orelseCatchExpr( | 4902 | fn orelseCatchExpr( |
| ... | @@ -10011,6 +9975,22 @@ const GenZir = struct { | ... | @@ -10011,6 +9975,22 @@ const GenZir = struct { |
| 10011 | gz.unstack(); | 9975 | gz.unstack(); |
| 10012 | } | 9976 | } |
| 10013 | 9977 | ||
| 9978 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. | ||
| 9979 | fn setTryBody(gz: *GenZir, inst: Zir.Inst.Index, operand: Zir.Inst.Ref) !void { | ||
| 9980 | const gpa = gz.astgen.gpa; | ||
| 9981 | const body = gz.instructionsSlice(); | ||
| 9982 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Try).Struct.fields.len + body.len); | ||
| 9983 | const zir_datas = gz.astgen.instructions.items(.data); | ||
| 9984 | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( | ||
| 9985 | Zir.Inst.Try{ | ||
| 9986 | .operand = operand, | ||
| 9987 | .body_len = @intCast(u32, body.len), | ||
| 9988 | }, | ||
| 9989 | ); | ||
| 9990 | gz.astgen.extra.appendSliceAssumeCapacity(body); | ||
| 9991 | gz.unstack(); | ||
| 9992 | } | ||
| 9993 | |||
| 10014 | /// Must be called with the following stack set up: | 9994 | /// Must be called with the following stack set up: |
| 10015 | /// * gz (bottom) | 9995 | /// * gz (bottom) |
| 10016 | /// * align_gz | 9996 | /// * align_gz |
src/Sema.zig+63-8| ... | @@ -1322,6 +1322,13 @@ fn analyzeBodyInner( | ... | @@ -1322,6 +1322,13 @@ fn analyzeBodyInner( |
| 1322 | break break_data.inst; | 1322 | break break_data.inst; |
| 1323 | } | 1323 | } |
| 1324 | }, | 1324 | }, |
| 1325 | .@"try" => blk: { | ||
| 1326 | if (!block.is_comptime) break :blk try sema.zirTry(block, inst); | ||
| 1327 | @panic("TODO"); | ||
| 1328 | }, | ||
| 1329 | .try_inline => { | ||
| 1330 | @panic("TODO"); | ||
| 1331 | }, | ||
| 1325 | }; | 1332 | }; |
| 1326 | if (sema.typeOf(air_inst).isNoReturn()) | 1333 | if (sema.typeOf(air_inst).isNoReturn()) |
| 1327 | break always_noreturn; | 1334 | break always_noreturn; |
| ... | @@ -6415,32 +6422,43 @@ fn zirErrUnionPayload( | ... | @@ -6415,32 +6422,43 @@ fn zirErrUnionPayload( |
| 6415 | const src = inst_data.src(); | 6422 | const src = inst_data.src(); |
| 6416 | const operand = try sema.resolveInst(inst_data.operand); | 6423 | const operand = try sema.resolveInst(inst_data.operand); |
| 6417 | const operand_src = src; | 6424 | const operand_src = src; |
| 6418 | const operand_ty = sema.typeOf(operand); | 6425 | const err_union_ty = sema.typeOf(operand); |
| 6419 | if (operand_ty.zigTypeTag() != .ErrorUnion) { | 6426 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { |
| 6420 | return sema.fail(block, operand_src, "expected error union type, found '{}'", .{ | 6427 | return sema.fail(block, operand_src, "expected error union type, found '{}'", .{ |
| 6421 | operand_ty.fmt(sema.mod), | 6428 | err_union_ty.fmt(sema.mod), |
| 6422 | }); | 6429 | }); |
| 6423 | } | 6430 | } |
| 6431 | return sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, safety_check); | ||
| 6432 | } | ||
| 6424 | 6433 | ||
| 6425 | const result_ty = operand_ty.errorUnionPayload(); | 6434 | fn analyzeErrUnionPayload( |
| 6426 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { | 6435 | sema: *Sema, |
| 6436 | block: *Block, | ||
| 6437 | src: LazySrcLoc, | ||
| 6438 | err_union_ty: Type, | ||
| 6439 | operand: Zir.Inst.Ref, | ||
| 6440 | operand_src: LazySrcLoc, | ||
| 6441 | safety_check: bool, | ||
| 6442 | ) CompileError!Air.Inst.Ref { | ||
| 6443 | const payload_ty = err_union_ty.errorUnionPayload(); | ||
| 6444 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { | ||
| 6427 | if (val.getError()) |name| { | 6445 | if (val.getError()) |name| { |
| 6428 | return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); | 6446 | return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); |
| 6429 | } | 6447 | } |
| 6430 | const data = val.castTag(.eu_payload).?.data; | 6448 | const data = val.castTag(.eu_payload).?.data; |
| 6431 | return sema.addConstant(result_ty, data); | 6449 | return sema.addConstant(payload_ty, data); |
| 6432 | } | 6450 | } |
| 6433 | 6451 | ||
| 6434 | try sema.requireRuntimeBlock(block, src); | 6452 | try sema.requireRuntimeBlock(block, src); |
| 6435 | 6453 | ||
| 6436 | // If the error set has no fields then no safety check is needed. | 6454 | // If the error set has no fields then no safety check is needed. |
| 6437 | if (safety_check and block.wantSafety() and | 6455 | if (safety_check and block.wantSafety() and |
| 6438 | operand_ty.errorUnionSet().errorSetCardinality() != .zero) | 6456 | err_union_ty.errorUnionSet().errorSetCardinality() != .zero) |
| 6439 | { | 6457 | { |
| 6440 | try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err); | 6458 | try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err); |
| 6441 | } | 6459 | } |
| 6442 | 6460 | ||
| 6443 | return block.addTyOp(.unwrap_errunion_payload, result_ty, operand); | 6461 | return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand); |
| 6444 | } | 6462 | } |
| 6445 | 6463 | ||
| 6446 | /// Pointer in, pointer out. | 6464 | /// Pointer in, pointer out. |
| ... | @@ -12958,6 +12976,43 @@ fn zirCondbr( | ... | @@ -12958,6 +12976,43 @@ fn zirCondbr( |
| 12958 | return always_noreturn; | 12976 | return always_noreturn; |
| 12959 | } | 12977 | } |
| 12960 | 12978 | ||
| 12979 | fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref { | ||
| 12980 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | ||
| 12981 | const src = inst_data.src(); | ||
| 12982 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | ||
| 12983 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); | ||
| 12984 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; | ||
| 12985 | const operand = try sema.resolveInst(extra.data.operand); | ||
| 12986 | const is_ptr = sema.typeOf(operand).zigTypeTag() == .Pointer; | ||
| 12987 | const err_union = if (is_ptr) | ||
| 12988 | try sema.analyzeLoad(parent_block, src, operand, operand_src) | ||
| 12989 | else | ||
| 12990 | operand; | ||
| 12991 | const err_union_ty = sema.typeOf(err_union); | ||
| 12992 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { | ||
| 12993 | return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ | ||
| 12994 | err_union_ty.fmt(sema.mod), | ||
| 12995 | }); | ||
| 12996 | } | ||
| 12997 | const is_non_err = try sema.analyzeIsNonErr(parent_block, operand_src, err_union); | ||
| 12998 | |||
| 12999 | if (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)) |is_non_err_val| { | ||
| 13000 | if (is_non_err_val.toBool()) { | ||
| 13001 | if (is_ptr) { | ||
| 13002 | return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false); | ||
| 13003 | } else { | ||
| 13004 | return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, operand, operand_src, false); | ||
| 13005 | } | ||
| 13006 | } | ||
| 13007 | // We can analyze the body directly in the parent block because we know there are | ||
| 13008 | // no breaks from the body possible, and that the body is noreturn. | ||
| 13009 | return sema.resolveBody(parent_block, body, inst); | ||
| 13010 | } | ||
| 13011 | _ = body; | ||
| 13012 | _ = is_non_err; | ||
| 13013 | @panic("TODO"); | ||
| 13014 | } | ||
| 13015 | |||
| 12961 | // A `break` statement is inside a runtime condition, but trying to | 13016 | // A `break` statement is inside a runtime condition, but trying to |
| 12962 | // break from an inline loop. In such case we must convert it to | 13017 | // break from an inline loop. In such case we must convert it to |
| 12963 | // a runtime break. | 13018 | // a runtime break. |
src/Zir.zig+33| ... | @@ -319,6 +319,19 @@ pub const Inst = struct { | ... | @@ -319,6 +319,19 @@ pub const Inst = struct { |
| 319 | /// only the taken branch is analyzed. The then block and else block must | 319 | /// only the taken branch is analyzed. The then block and else block must |
| 320 | /// terminate with an "inline" variant of a noreturn instruction. | 320 | /// terminate with an "inline" variant of a noreturn instruction. |
| 321 | condbr_inline, | 321 | condbr_inline, |
| 322 | /// Given an operand which is an error union, splits control flow. In | ||
| 323 | /// case of error, control flow goes into the block that is part of this | ||
| 324 | /// instruction, which is guaranteed to end with a return instruction | ||
| 325 | /// and never breaks out of the block. | ||
| 326 | /// In the case of non-error, control flow proceeds to the next instruction | ||
| 327 | /// after the `try`, with the result of this instruction being the unwrapped | ||
| 328 | /// payload value, as if `err_union_payload_unsafe` was executed on the operand. | ||
| 329 | /// Uses the `pl_node` union field. Payload is `Try`. | ||
| 330 | @"try", | ||
| 331 | /// Same as `try` except the operand is coerced to a comptime value, and | ||
| 332 | /// only the taken branch is analyzed. The block must terminate with an "inline" | ||
| 333 | /// variant of a noreturn instruction. | ||
| 334 | try_inline, | ||
| 322 | /// An error set type definition. Contains a list of field names. | 335 | /// An error set type definition. Contains a list of field names. |
| 323 | /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`. | 336 | /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`. |
| 324 | error_set_decl, | 337 | error_set_decl, |
| ... | @@ -1231,6 +1244,8 @@ pub const Inst = struct { | ... | @@ -1231,6 +1244,8 @@ pub const Inst = struct { |
| 1231 | .closure_capture, | 1244 | .closure_capture, |
| 1232 | .ret_ptr, | 1245 | .ret_ptr, |
| 1233 | .ret_type, | 1246 | .ret_type, |
| 1247 | .@"try", | ||
| 1248 | .try_inline, | ||
| 1234 | => false, | 1249 | => false, |
| 1235 | 1250 | ||
| 1236 | .@"break", | 1251 | .@"break", |
| ... | @@ -1509,6 +1524,8 @@ pub const Inst = struct { | ... | @@ -1509,6 +1524,8 @@ pub const Inst = struct { |
| 1509 | .repeat, | 1524 | .repeat, |
| 1510 | .repeat_inline, | 1525 | .repeat_inline, |
| 1511 | .panic, | 1526 | .panic, |
| 1527 | .@"try", | ||
| 1528 | .try_inline, | ||
| 1512 | => false, | 1529 | => false, |
| 1513 | 1530 | ||
| 1514 | .extended => switch (data.extended.opcode) { | 1531 | .extended => switch (data.extended.opcode) { |
| ... | @@ -1569,6 +1586,8 @@ pub const Inst = struct { | ... | @@ -1569,6 +1586,8 @@ pub const Inst = struct { |
| 1569 | .coerce_result_ptr = .bin, | 1586 | .coerce_result_ptr = .bin, |
| 1570 | .condbr = .pl_node, | 1587 | .condbr = .pl_node, |
| 1571 | .condbr_inline = .pl_node, | 1588 | .condbr_inline = .pl_node, |
| 1589 | .@"try" = .pl_node, | ||
| 1590 | .try_inline = .pl_node, | ||
| 1572 | .error_set_decl = .pl_node, | 1591 | .error_set_decl = .pl_node, |
| 1573 | .error_set_decl_anon = .pl_node, | 1592 | .error_set_decl_anon = .pl_node, |
| 1574 | .error_set_decl_func = .pl_node, | 1593 | .error_set_decl_func = .pl_node, |
| ... | @@ -2803,6 +2822,14 @@ pub const Inst = struct { | ... | @@ -2803,6 +2822,14 @@ pub const Inst = struct { |
| 2803 | else_body_len: u32, | 2822 | else_body_len: u32, |
| 2804 | }; | 2823 | }; |
| 2805 | 2824 | ||
| 2825 | /// This data is stored inside extra, trailed by: | ||
| 2826 | /// * 0. body: Index // for each `body_len`. | ||
| 2827 | pub const Try = struct { | ||
| 2828 | /// The error union to unwrap. | ||
| 2829 | operand: Ref, | ||
| 2830 | body_len: u32, | ||
| 2831 | }; | ||
| 2832 | |||
| 2806 | /// Stored in extra. Depending on the flags in Data, there will be up to 5 | 2833 | /// Stored in extra. Depending on the flags in Data, there will be up to 5 |
| 2807 | /// trailing Ref fields: | 2834 | /// trailing Ref fields: |
| 2808 | /// 0. sentinel: Ref // if `has_sentinel` flag is set | 2835 | /// 0. sentinel: Ref // if `has_sentinel` flag is set |
| ... | @@ -3739,6 +3766,12 @@ fn findDeclsInner( | ... | @@ -3739,6 +3766,12 @@ fn findDeclsInner( |
| 3739 | try zir.findDeclsBody(list, then_body); | 3766 | try zir.findDeclsBody(list, then_body); |
| 3740 | try zir.findDeclsBody(list, else_body); | 3767 | try zir.findDeclsBody(list, else_body); |
| 3741 | }, | 3768 | }, |
| 3769 | .@"try", .try_inline => { | ||
| 3770 | const inst_data = datas[inst].pl_node; | ||
| 3771 | const extra = zir.extraData(Inst.Try, inst_data.payload_index); | ||
| 3772 | const body = zir.extra[extra.end..][0..extra.data.body_len]; | ||
| 3773 | try zir.findDeclsBody(list, body); | ||
| 3774 | }, | ||
| 3742 | .switch_block => return findDeclsSwitch(zir, list, inst), | 3775 | .switch_block => return findDeclsSwitch(zir, list, inst), |
| 3743 | 3776 | ||
| 3744 | .suspend_block => @panic("TODO iterate suspend block"), | 3777 | .suspend_block => @panic("TODO iterate suspend block"), |
src/print_zir.zig+21-6| ... | @@ -374,17 +374,21 @@ const Writer = struct { | ... | @@ -374,17 +374,21 @@ const Writer = struct { |
| 374 | .validate_array_init_comptime, | 374 | .validate_array_init_comptime, |
| 375 | .c_import, | 375 | .c_import, |
| 376 | .typeof_builtin, | 376 | .typeof_builtin, |
| 377 | => try self.writePlNodeBlock(stream, inst), | 377 | => try self.writeBlock(stream, inst), |
| 378 | 378 | ||
| 379 | .condbr, | 379 | .condbr, |
| 380 | .condbr_inline, | 380 | .condbr_inline, |
| 381 | => try self.writePlNodeCondBr(stream, inst), | 381 | => try self.writeCondBr(stream, inst), |
| 382 | |||
| 383 | .@"try", | ||
| 384 | .try_inline, | ||
| 385 | => try self.writeTry(stream, inst), | ||
| 382 | 386 | ||
| 383 | .error_set_decl => try self.writeErrorSetDecl(stream, inst, .parent), | 387 | .error_set_decl => try self.writeErrorSetDecl(stream, inst, .parent), |
| 384 | .error_set_decl_anon => try self.writeErrorSetDecl(stream, inst, .anon), | 388 | .error_set_decl_anon => try self.writeErrorSetDecl(stream, inst, .anon), |
| 385 | .error_set_decl_func => try self.writeErrorSetDecl(stream, inst, .func), | 389 | .error_set_decl_func => try self.writeErrorSetDecl(stream, inst, .func), |
| 386 | 390 | ||
| 387 | .switch_block => try self.writePlNodeSwitchBlock(stream, inst), | 391 | .switch_block => try self.writeSwitchBlock(stream, inst), |
| 388 | 392 | ||
| 389 | .field_ptr, | 393 | .field_ptr, |
| 390 | .field_val, | 394 | .field_val, |
| ... | @@ -1171,7 +1175,7 @@ const Writer = struct { | ... | @@ -1171,7 +1175,7 @@ const Writer = struct { |
| 1171 | try self.writeSrc(stream, inst_data.src()); | 1175 | try self.writeSrc(stream, inst_data.src()); |
| 1172 | } | 1176 | } |
| 1173 | 1177 | ||
| 1174 | fn writePlNodeBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | 1178 | fn writeBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
| 1175 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 1179 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 1176 | try self.writePlNodeBlockWithoutSrc(stream, inst); | 1180 | try self.writePlNodeBlockWithoutSrc(stream, inst); |
| 1177 | try self.writeSrc(stream, inst_data.src()); | 1181 | try self.writeSrc(stream, inst_data.src()); |
| ... | @@ -1185,7 +1189,7 @@ const Writer = struct { | ... | @@ -1185,7 +1189,7 @@ const Writer = struct { |
| 1185 | try stream.writeAll(") "); | 1189 | try stream.writeAll(") "); |
| 1186 | } | 1190 | } |
| 1187 | 1191 | ||
| 1188 | fn writePlNodeCondBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | 1192 | fn writeCondBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
| 1189 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 1193 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 1190 | const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); | 1194 | const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); |
| 1191 | const then_body = self.code.extra[extra.end..][0..extra.data.then_body_len]; | 1195 | const then_body = self.code.extra[extra.end..][0..extra.data.then_body_len]; |
| ... | @@ -1199,6 +1203,17 @@ const Writer = struct { | ... | @@ -1199,6 +1203,17 @@ const Writer = struct { |
| 1199 | try self.writeSrc(stream, inst_data.src()); | 1203 | try self.writeSrc(stream, inst_data.src()); |
| 1200 | } | 1204 | } |
| 1201 | 1205 | ||
| 1206 | fn writeTry(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | ||
| 1207 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | ||
| 1208 | const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index); | ||
| 1209 | const body = self.code.extra[extra.end..][0..extra.data.body_len]; | ||
| 1210 | try self.writeInstRef(stream, extra.data.operand); | ||
| 1211 | try stream.writeAll(", "); | ||
| 1212 | try self.writeBracedBody(stream, body); | ||
| 1213 | try stream.writeAll(") "); | ||
| 1214 | try self.writeSrc(stream, inst_data.src()); | ||
| 1215 | } | ||
| 1216 | |||
| 1202 | fn writeStructDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | 1217 | fn writeStructDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1203 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); | 1218 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| 1204 | 1219 | ||
| ... | @@ -1746,7 +1761,7 @@ const Writer = struct { | ... | @@ -1746,7 +1761,7 @@ const Writer = struct { |
| 1746 | try self.writeSrc(stream, inst_data.src()); | 1761 | try self.writeSrc(stream, inst_data.src()); |
| 1747 | } | 1762 | } |
| 1748 | 1763 | ||
| 1749 | fn writePlNodeSwitchBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | 1764 | fn writeSwitchBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
| 1750 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 1765 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 1751 | const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); | 1766 | const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); |
| 1752 | 1767 |