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