| ... | ... | @@ -576,13 +576,10 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In |
| 576 | 576 | |
| 577 | 577 | fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst { |
| 578 | 578 | const b = try mod.requireFunctionBlock(scope, inst.base.src); |
| 579 | | switch (b.label) { |
| 580 | | .none, .breaking => {}, |
| 581 | | .inlining => |*inlining| { |
| 582 | | const param_index = inlining.param_index; |
| 583 | | inlining.param_index += 1; |
| 584 | | return inlining.casted_args[param_index]; |
| 585 | | }, |
| 579 | if (b.inlining) |*inlining| { |
| 580 | const param_index = inlining.param_index; |
| 581 | inlining.param_index += 1; |
| 582 | return inlining.casted_args[param_index]; |
| 586 | 583 | } |
| 587 | 584 | const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty; |
| 588 | 585 | const param_index = b.instructions.items.len; |
| ... | ... | @@ -620,6 +617,7 @@ fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError |
| 620 | 617 | .decl = parent_block.decl, |
| 621 | 618 | .instructions = .{}, |
| 622 | 619 | .arena = parent_block.arena, |
| 620 | .inlining = parent_block.inlining, |
| 623 | 621 | .is_comptime = parent_block.is_comptime, |
| 624 | 622 | }; |
| 625 | 623 | defer child_block.instructions.deinit(mod.gpa); |
| ... | ... | @@ -642,7 +640,8 @@ fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_c |
| 642 | 640 | .decl = parent_block.decl, |
| 643 | 641 | .instructions = .{}, |
| 644 | 642 | .arena = parent_block.arena, |
| 645 | | .label = .none, |
| 643 | .label = null, |
| 644 | .inlining = parent_block.inlining, |
| 646 | 645 | .is_comptime = parent_block.is_comptime or is_comptime, |
| 647 | 646 | }; |
| 648 | 647 | defer child_block.instructions.deinit(mod.gpa); |
| ... | ... | @@ -680,18 +679,18 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_compt |
| 680 | 679 | .decl = parent_block.decl, |
| 681 | 680 | .instructions = .{}, |
| 682 | 681 | .arena = parent_block.arena, |
| 683 | | .label = Scope.Block.Label{ |
| 684 | | .breaking = .{ |
| 685 | | .zir_block = inst, |
| 686 | | .merges = .{ |
| 687 | | .results = .{}, |
| 688 | | .block_inst = block_inst, |
| 689 | | }, |
| 682 | // TODO @as here is working around a stage1 miscompilation bug :( |
| 683 | .label = @as(?Scope.Block.Label, Scope.Block.Label{ |
| 684 | .zir_block = inst, |
| 685 | .merges = .{ |
| 686 | .results = .{}, |
| 687 | .block_inst = block_inst, |
| 690 | 688 | }, |
| 691 | | }, |
| 689 | }), |
| 690 | .inlining = parent_block.inlining, |
| 692 | 691 | .is_comptime = is_comptime or parent_block.is_comptime, |
| 693 | 692 | }; |
| 694 | | const merges = &child_block.label.breaking.merges; |
| 693 | const merges = &child_block.label.?.merges; |
| 695 | 694 | |
| 696 | 695 | defer child_block.instructions.deinit(mod.gpa); |
| 697 | 696 | defer merges.results.deinit(mod.gpa); |
| ... | ... | @@ -705,7 +704,7 @@ fn analyzeBlockBody( |
| 705 | 704 | mod: *Module, |
| 706 | 705 | scope: *Scope, |
| 707 | 706 | child_block: *Scope.Block, |
| 708 | | merges: *Scope.Block.Label.Merges, |
| 707 | merges: *Scope.Block.Merges, |
| 709 | 708 | ) InnerError!*Inst { |
| 710 | 709 | const parent_block = scope.cast(Scope.Block).?; |
| 711 | 710 | |
| ... | ... | @@ -895,19 +894,20 @@ fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError |
| 895 | 894 | .decl = scope.decl().?, |
| 896 | 895 | .instructions = .{}, |
| 897 | 896 | .arena = scope.arena(), |
| 898 | | .label = Scope.Block.Label{ |
| 899 | | .inlining = .{ |
| 900 | | .param_index = 0, |
| 901 | | .casted_args = casted_args, |
| 902 | | .merges = .{ |
| 903 | | .results = .{}, |
| 904 | | .block_inst = block_inst, |
| 905 | | }, |
| 897 | .label = null, |
| 898 | // TODO @as here is working around a stage1 miscompilation bug :( |
| 899 | .inlining = @as(?Scope.Block.Inlining, Scope.Block.Inlining{ |
| 900 | .caller = b.func, |
| 901 | .param_index = 0, |
| 902 | .casted_args = casted_args, |
| 903 | .merges = .{ |
| 904 | .results = .{}, |
| 905 | .block_inst = block_inst, |
| 906 | 906 | }, |
| 907 | | }, |
| 907 | }), |
| 908 | 908 | .is_comptime = is_comptime_call, |
| 909 | 909 | }; |
| 910 | | const merges = &child_block.label.inlining.merges; |
| 910 | const merges = &child_block.inlining.?.merges; |
| 911 | 911 | |
| 912 | 912 | defer child_block.instructions.deinit(mod.gpa); |
| 913 | 913 | defer merges.results.deinit(mod.gpa); |
| ... | ... | @@ -1416,6 +1416,7 @@ fn analyzeInstSwitchBr(mod: *Module, scope: *Scope, inst: *zir.Inst.SwitchBr) In |
| 1416 | 1416 | .decl = parent_block.decl, |
| 1417 | 1417 | .instructions = .{}, |
| 1418 | 1418 | .arena = parent_block.arena, |
| 1419 | .inlining = parent_block.inlining, |
| 1419 | 1420 | .is_comptime = parent_block.is_comptime, |
| 1420 | 1421 | }; |
| 1421 | 1422 | defer case_block.instructions.deinit(mod.gpa); |
| ... | ... | @@ -1955,6 +1956,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE |
| 1955 | 1956 | .decl = parent_block.decl, |
| 1956 | 1957 | .instructions = .{}, |
| 1957 | 1958 | .arena = parent_block.arena, |
| 1959 | .inlining = parent_block.inlining, |
| 1958 | 1960 | .is_comptime = parent_block.is_comptime, |
| 1959 | 1961 | }; |
| 1960 | 1962 | defer true_block.instructions.deinit(mod.gpa); |
| ... | ... | @@ -1966,6 +1968,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE |
| 1966 | 1968 | .decl = parent_block.decl, |
| 1967 | 1969 | .instructions = .{}, |
| 1968 | 1970 | .arena = parent_block.arena, |
| 1971 | .inlining = parent_block.inlining, |
| 1969 | 1972 | .is_comptime = parent_block.is_comptime, |
| 1970 | 1973 | }; |
| 1971 | 1974 | defer false_block.instructions.deinit(mod.gpa); |
| ... | ... | @@ -1995,40 +1998,34 @@ fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError! |
| 1995 | 1998 | const operand = try resolveInst(mod, scope, inst.positionals.operand); |
| 1996 | 1999 | const b = try mod.requireFunctionBlock(scope, inst.base.src); |
| 1997 | 2000 | |
| 1998 | | switch (b.label) { |
| 1999 | | .inlining => |*inlining| { |
| 2000 | | // We are inlining a function call; rewrite the `ret` as a `break`. |
| 2001 | | try inlining.merges.results.append(mod.gpa, operand); |
| 2002 | | return mod.addBr(b, inst.base.src, inlining.merges.block_inst, operand); |
| 2003 | | }, |
| 2004 | | .none, .breaking => { |
| 2005 | | return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, operand); |
| 2006 | | }, |
| 2001 | if (b.inlining) |*inlining| { |
| 2002 | // We are inlining a function call; rewrite the `ret` as a `break`. |
| 2003 | try inlining.merges.results.append(mod.gpa, operand); |
| 2004 | return mod.addBr(b, inst.base.src, inlining.merges.block_inst, operand); |
| 2007 | 2005 | } |
| 2006 | |
| 2007 | return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, operand); |
| 2008 | 2008 | } |
| 2009 | 2009 | |
| 2010 | 2010 | fn analyzeInstRetVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { |
| 2011 | 2011 | const b = try mod.requireFunctionBlock(scope, inst.base.src); |
| 2012 | | switch (b.label) { |
| 2013 | | .inlining => |*inlining| { |
| 2014 | | // We are inlining a function call; rewrite the `retvoid` as a `breakvoid`. |
| 2015 | | const void_inst = try mod.constVoid(scope, inst.base.src); |
| 2016 | | try inlining.merges.results.append(mod.gpa, void_inst); |
| 2017 | | return mod.addBr(b, inst.base.src, inlining.merges.block_inst, void_inst); |
| 2018 | | }, |
| 2019 | | .none, .breaking => { |
| 2020 | | if (b.func) |func| { |
| 2021 | | // Need to emit a compile error if returning void is not allowed. |
| 2022 | | const void_inst = try mod.constVoid(scope, inst.base.src); |
| 2023 | | const fn_ty = func.owner_decl.typed_value.most_recent.typed_value.ty; |
| 2024 | | const casted_void = try mod.coerce(scope, fn_ty.fnReturnType(), void_inst); |
| 2025 | | if (casted_void.ty.zigTypeTag() != .Void) { |
| 2026 | | return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, casted_void); |
| 2027 | | } |
| 2028 | | } |
| 2029 | | return mod.addNoOp(b, inst.base.src, Type.initTag(.noreturn), .retvoid); |
| 2030 | | }, |
| 2012 | if (b.inlining) |*inlining| { |
| 2013 | // We are inlining a function call; rewrite the `retvoid` as a `breakvoid`. |
| 2014 | const void_inst = try mod.constVoid(scope, inst.base.src); |
| 2015 | try inlining.merges.results.append(mod.gpa, void_inst); |
| 2016 | return mod.addBr(b, inst.base.src, inlining.merges.block_inst, void_inst); |
| 2017 | } |
| 2018 | |
| 2019 | if (b.func) |func| { |
| 2020 | // Need to emit a compile error if returning void is not allowed. |
| 2021 | const void_inst = try mod.constVoid(scope, inst.base.src); |
| 2022 | const fn_ty = func.owner_decl.typed_value.most_recent.typed_value.ty; |
| 2023 | const casted_void = try mod.coerce(scope, fn_ty.fnReturnType(), void_inst); |
| 2024 | if (casted_void.ty.zigTypeTag() != .Void) { |
| 2025 | return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, casted_void); |
| 2026 | } |
| 2031 | 2027 | } |
| 2028 | return mod.addNoOp(b, inst.base.src, Type.initTag(.noreturn), .retvoid); |
| 2032 | 2029 | } |
| 2033 | 2030 | |
| 2034 | 2031 | fn floatOpAllowed(tag: zir.Inst.Tag) bool { |
| ... | ... | @@ -2048,16 +2045,12 @@ fn analyzeBreak( |
| 2048 | 2045 | ) InnerError!*Inst { |
| 2049 | 2046 | var opt_block = scope.cast(Scope.Block); |
| 2050 | 2047 | while (opt_block) |block| { |
| 2051 | | switch (block.label) { |
| 2052 | | .none => {}, |
| 2053 | | .breaking => |*label| { |
| 2054 | | if (label.zir_block == zir_block) { |
| 2055 | | try label.merges.results.append(mod.gpa, operand); |
| 2056 | | const b = try mod.requireFunctionBlock(scope, src); |
| 2057 | | return mod.addBr(b, src, label.merges.block_inst, operand); |
| 2058 | | } |
| 2059 | | }, |
| 2060 | | .inlining => unreachable, // Invalid `break` ZIR inside inline function call. |
| 2048 | if (block.label) |*label| { |
| 2049 | if (label.zir_block == zir_block) { |
| 2050 | try label.merges.results.append(mod.gpa, operand); |
| 2051 | const b = try mod.requireFunctionBlock(scope, src); |
| 2052 | return mod.addBr(b, src, label.merges.block_inst, operand); |
| 2053 | } |
| 2061 | 2054 | } |
| 2062 | 2055 | opt_block = block.parent; |
| 2063 | 2056 | } else unreachable; |