authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-31 20:15:08-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-01-31 20:15:08-08:00
logbf76501b5d46277d3706a1f0b92ba52f2a47d894
tree7a40c904b9246092009c02f5b09a2a8732b69175
parentfdc875ed0080cd2542a854a8cd6c627b25e9b7a4
parent0f5eda973e0c17b3f792cdb06674bf8d2863c8fb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7847 from ziglang/astgen-rl-rework

stage2: rework astgen result locations

7 files changed, 1280 insertions(+), 1398 deletions(-)

src/Module.zig+62-11
...@@ -375,6 +375,10 @@ pub const Scope = struct {...@@ -375,6 +375,10 @@ pub const Scope = struct {
375 }375 }
376 }376 }
377377
378 pub fn isComptime(self: *Scope) bool {
379 return self.getGenZIR().force_comptime;
380 }
381
378 pub fn ownerDecl(self: *Scope) ?*Decl {382 pub fn ownerDecl(self: *Scope) ?*Decl {
379 return switch (self.tag) {383 return switch (self.tag) {
380 .block => self.cast(Block).?.owner_decl,384 .block => self.cast(Block).?.owner_decl,
...@@ -671,14 +675,36 @@ pub const Scope = struct {...@@ -671,14 +675,36 @@ pub const Scope = struct {
671 };675 };
672676
673 pub const Merges = struct {677 pub const Merges = struct {
674 results: ArrayListUnmanaged(*Inst),
675 block_inst: *Inst.Block,678 block_inst: *Inst.Block,
679 /// Separate array list from break_inst_list so that it can be passed directly
680 /// to resolvePeerTypes.
681 results: ArrayListUnmanaged(*Inst),
682 /// Keeps track of the break instructions so that the operand can be replaced
683 /// if we need to add type coercion at the end of block analysis.
684 /// Same indexes, capacity, length as `results`.
685 br_list: ArrayListUnmanaged(*Inst.Br),
676 };686 };
677687
678 /// For debugging purposes.688 /// For debugging purposes.
679 pub fn dump(self: *Block, mod: Module) void {689 pub fn dump(self: *Block, mod: Module) void {
680 zir.dumpBlock(mod, self);690 zir.dumpBlock(mod, self);
681 }691 }
692
693 pub fn makeSubBlock(parent: *Block) Block {
694 return .{
695 .parent = parent,
696 .inst_table = parent.inst_table,
697 .func = parent.func,
698 .owner_decl = parent.owner_decl,
699 .src_decl = parent.src_decl,
700 .instructions = .{},
701 .arena = parent.arena,
702 .label = null,
703 .inlining = parent.inlining,
704 .is_comptime = parent.is_comptime,
705 .branch_quota = parent.branch_quota,
706 };
707 }
682 };708 };
683709
684 /// This is a temporary structure, references to it are valid only710 /// This is a temporary structure, references to it are valid only
...@@ -690,13 +716,32 @@ pub const Scope = struct {...@@ -690,13 +716,32 @@ pub const Scope = struct {
690 parent: *Scope,716 parent: *Scope,
691 decl: *Decl,717 decl: *Decl,
692 arena: *Allocator,718 arena: *Allocator,
719 force_comptime: bool,
693 /// The first N instructions in a function body ZIR are arg instructions.720 /// The first N instructions in a function body ZIR are arg instructions.
694 instructions: std.ArrayListUnmanaged(*zir.Inst) = .{},721 instructions: std.ArrayListUnmanaged(*zir.Inst) = .{},
695 label: ?Label = null,722 label: ?Label = null,
696 break_block: ?*zir.Inst.Block = null,723 break_block: ?*zir.Inst.Block = null,
697 continue_block: ?*zir.Inst.Block = null,724 continue_block: ?*zir.Inst.Block = null,
698 /// only valid if label != null or (continue_block and break_block) != null725 /// Only valid when setBlockResultLoc is called.
699 break_result_loc: astgen.ResultLoc = undefined,726 break_result_loc: astgen.ResultLoc = undefined,
727 /// When a block has a pointer result location, here it is.
728 rl_ptr: ?*zir.Inst = null,
729 /// Keeps track of how many branches of a block did not actually
730 /// consume the result location. astgen uses this to figure out
731 /// whether to rely on break instructions or writing to the result
732 /// pointer for the result instruction.
733 rvalue_rl_count: usize = 0,
734 /// Keeps track of how many break instructions there are. When astgen is finished
735 /// with a block, it can check this against rvalue_rl_count to find out whether
736 /// the break instructions should be downgraded to break_void.
737 break_count: usize = 0,
738 /// Tracks `break :foo bar` instructions so they can possibly be elided later if
739 /// the labeled block ends up not needing a result location pointer.
740 labeled_breaks: std.ArrayListUnmanaged(*zir.Inst.Break) = .{},
741 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions
742 /// so they can possibly be elided later if the labeled block ends up not needing
743 /// a result location pointer.
744 labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(*zir.Inst.BinOp) = .{},
700745
701 pub const Label = struct {746 pub const Label = struct {
702 token: ast.TokenIndex,747 token: ast.TokenIndex,
...@@ -968,6 +1013,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -968,6 +1013,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
968 .decl = decl,1013 .decl = decl,
969 .arena = &fn_type_scope_arena.allocator,1014 .arena = &fn_type_scope_arena.allocator,
970 .parent = &decl.container.base,1015 .parent = &decl.container.base,
1016 .force_comptime = true,
971 };1017 };
972 defer fn_type_scope.instructions.deinit(self.gpa);1018 defer fn_type_scope.instructions.deinit(self.gpa);
9731019
...@@ -1131,6 +1177,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1131,6 +1177,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1131 .decl = decl,1177 .decl = decl,
1132 .arena = &decl_arena.allocator,1178 .arena = &decl_arena.allocator,
1133 .parent = &decl.container.base,1179 .parent = &decl.container.base,
1180 .force_comptime = false,
1134 };1181 };
1135 defer gen_scope.instructions.deinit(self.gpa);1182 defer gen_scope.instructions.deinit(self.gpa);
11361183
...@@ -1171,7 +1218,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1171,7 +1218,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1171 !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())1218 !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())
1172 {1219 {
1173 const src = tree.token_locs[body_block.rbrace].start;1220 const src = tree.token_locs[body_block.rbrace].start;
1174 _ = try astgen.addZIRNoOp(self, &gen_scope.base, src, .returnvoid);1221 _ = try astgen.addZIRNoOp(self, &gen_scope.base, src, .return_void);
1175 }1222 }
11761223
1177 if (std.builtin.mode == .Debug and self.comp.verbose_ir) {1224 if (std.builtin.mode == .Debug and self.comp.verbose_ir) {
...@@ -1329,6 +1376,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1329,6 +1376,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1329 .decl = decl,1376 .decl = decl,
1330 .arena = &gen_scope_arena.allocator,1377 .arena = &gen_scope_arena.allocator,
1331 .parent = &decl.container.base,1378 .parent = &decl.container.base,
1379 .force_comptime = false,
1332 };1380 };
1333 defer gen_scope.instructions.deinit(self.gpa);1381 defer gen_scope.instructions.deinit(self.gpa);
13341382
...@@ -1388,6 +1436,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1388,6 +1436,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1388 .decl = decl,1436 .decl = decl,
1389 .arena = &type_scope_arena.allocator,1437 .arena = &type_scope_arena.allocator,
1390 .parent = &decl.container.base,1438 .parent = &decl.container.base,
1439 .force_comptime = true,
1391 };1440 };
1392 defer type_scope.instructions.deinit(self.gpa);1441 defer type_scope.instructions.deinit(self.gpa);
13931442
...@@ -1457,13 +1506,15 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1457,13 +1506,15 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
14571506
1458 decl.analysis = .in_progress;1507 decl.analysis = .in_progress;
14591508
1460 // A comptime decl does not store any value so we can just deinit this arena after analysis is done.1509 // A comptime decl does not store any value so we can just deinit
1510 // this arena after analysis is done.
1461 var analysis_arena = std.heap.ArenaAllocator.init(self.gpa);1511 var analysis_arena = std.heap.ArenaAllocator.init(self.gpa);
1462 defer analysis_arena.deinit();1512 defer analysis_arena.deinit();
1463 var gen_scope: Scope.GenZIR = .{1513 var gen_scope: Scope.GenZIR = .{
1464 .decl = decl,1514 .decl = decl,
1465 .arena = &analysis_arena.allocator,1515 .arena = &analysis_arena.allocator,
1466 .parent = &decl.container.base,1516 .parent = &decl.container.base,
1517 .force_comptime = true,
1467 };1518 };
1468 defer gen_scope.instructions.deinit(self.gpa);1519 defer gen_scope.instructions.deinit(self.gpa);
14691520
...@@ -2100,7 +2151,7 @@ pub fn addBr(...@@ -2100,7 +2151,7 @@ pub fn addBr(
2100 src: usize,2151 src: usize,
2101 target_block: *Inst.Block,2152 target_block: *Inst.Block,
2102 operand: *Inst,2153 operand: *Inst,
2103) !*Inst {2154) !*Inst.Br {
2104 const inst = try scope_block.arena.create(Inst.Br);2155 const inst = try scope_block.arena.create(Inst.Br);
2105 inst.* = .{2156 inst.* = .{
2106 .base = .{2157 .base = .{
...@@ -2112,7 +2163,7 @@ pub fn addBr(...@@ -2112,7 +2163,7 @@ pub fn addBr(
2112 .block = target_block,2163 .block = target_block,
2113 };2164 };
2114 try scope_block.instructions.append(self.gpa, &inst.base);2165 try scope_block.instructions.append(self.gpa, &inst.base);
2115 return &inst.base;2166 return inst;
2116}2167}
21172168
2118pub fn addCondBr(2169pub fn addCondBr(
...@@ -3466,18 +3517,18 @@ pub fn addSafetyCheck(mod: *Module, parent_block: *Scope.Block, ok: *Inst, panic...@@ -3466,18 +3517,18 @@ pub fn addSafetyCheck(mod: *Module, parent_block: *Scope.Block, ok: *Inst, panic
3466 };3517 };
34673518
3468 const ok_body: ir.Body = .{3519 const ok_body: ir.Body = .{
3469 .instructions = try parent_block.arena.alloc(*Inst, 1), // Only need space for the brvoid.3520 .instructions = try parent_block.arena.alloc(*Inst, 1), // Only need space for the br_void.
3470 };3521 };
3471 const brvoid = try parent_block.arena.create(Inst.BrVoid);3522 const br_void = try parent_block.arena.create(Inst.BrVoid);
3472 brvoid.* = .{3523 br_void.* = .{
3473 .base = .{3524 .base = .{
3474 .tag = .brvoid,3525 .tag = .br_void,
3475 .ty = Type.initTag(.noreturn),3526 .ty = Type.initTag(.noreturn),
3476 .src = ok.src,3527 .src = ok.src,
3477 },3528 },
3478 .block = block_inst,3529 .block = block_inst,
3479 };3530 };
3480 ok_body.instructions[0] = &brvoid.base;3531 ok_body.instructions[0] = &br_void.base;
34813532
3482 var fail_block: Scope.Block = .{3533 var fail_block: Scope.Block = .{
3483 .parent = parent_block,3534 .parent = parent_block,
src/astgen.zig+674-611
...@@ -14,25 +14,45 @@ const InnerError = Module.InnerError;...@@ -14,25 +14,45 @@ const InnerError = Module.InnerError;
1414
15pub const ResultLoc = union(enum) {15pub const ResultLoc = union(enum) {
16 /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the16 /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the
17 /// expression should be generated.17 /// expression should be generated. The result instruction from the expression must
18 /// be ignored.
18 discard,19 discard,
19 /// The expression has an inferred type, and it will be evaluated as an rvalue.20 /// The expression has an inferred type, and it will be evaluated as an rvalue.
20 none,21 none,
21 /// The expression must generate a pointer rather than a value. For example, the left hand side22 /// The expression must generate a pointer rather than a value. For example, the left hand side
22 /// of an assignment uses this kind of result location.23 /// of an assignment uses this kind of result location.
23 ref,24 ref,
24 /// The expression will be type coerced into this type, but it will be evaluated as an rvalue.25 /// The expression will be coerced into this type, but it will be evaluated as an rvalue.
25 ty: *zir.Inst,26 ty: *zir.Inst,
26 /// The expression must store its result into this typed pointer.27 /// The expression must store its result into this typed pointer. The result instruction
28 /// from the expression must be ignored.
27 ptr: *zir.Inst,29 ptr: *zir.Inst,
28 /// The expression must store its result into this allocation, which has an inferred type.30 /// The expression must store its result into this allocation, which has an inferred type.
31 /// The result instruction from the expression must be ignored.
29 inferred_ptr: *zir.Inst.Tag.alloc_inferred.Type(),32 inferred_ptr: *zir.Inst.Tag.alloc_inferred.Type(),
30 /// The expression must store its result into this pointer, which is a typed pointer that33 /// The expression must store its result into this pointer, which is a typed pointer that
31 /// has been bitcasted to whatever the expression's type is.34 /// has been bitcasted to whatever the expression's type is.
35 /// The result instruction from the expression must be ignored.
32 bitcasted_ptr: *zir.Inst.UnOp,36 bitcasted_ptr: *zir.Inst.UnOp,
33 /// There is a pointer for the expression to store its result into, however, its type37 /// There is a pointer for the expression to store its result into, however, its type
34 /// is inferred based on peer type resolution for a `zir.Inst.Block`.38 /// is inferred based on peer type resolution for a `zir.Inst.Block`.
35 block_ptr: *zir.Inst.Block,39 /// The result instruction from the expression must be ignored.
40 block_ptr: *Module.Scope.GenZIR,
41
42 pub const Strategy = struct {
43 elide_store_to_block_ptr_instructions: bool,
44 tag: Tag,
45
46 pub const Tag = enum {
47 /// Both branches will use break_void; result location is used to communicate the
48 /// result instruction.
49 break_void,
50 /// Use break statements to pass the block result value, and call rvalue() at
51 /// the end depending on rl. Also elide the store_to_block_ptr instructions
52 /// depending on rl.
53 break_operand,
54 };
55 };
36};56};
3757
38pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*zir.Inst {58pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*zir.Inst {
...@@ -179,6 +199,9 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst {...@@ -179,6 +199,9 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst {
179}199}
180200
181/// Turn Zig AST into untyped ZIR istructions.201/// Turn Zig AST into untyped ZIR istructions.
202/// When `rl` is discard, ptr, inferred_ptr, bitcasted_ptr, or inferred_ptr, the
203/// result instruction can be used to inspect whether it is isNoReturn() but that is it,
204/// it must otherwise not be used.
182pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {205pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {
183 switch (node.tag) {206 switch (node.tag) {
184 .Root => unreachable, // Top-level declaration.207 .Root => unreachable, // Top-level declaration.
...@@ -197,20 +220,20 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -197,20 +220,20 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
197 .FieldInitializer => unreachable, // Handled explicitly.220 .FieldInitializer => unreachable, // Handled explicitly.
198 .ContainerField => unreachable, // Handled explicitly.221 .ContainerField => unreachable, // Handled explicitly.
199222
200 .Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)),223 .Assign => return rvalueVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)),
201 .AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)),224 .AssignBitAnd => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bit_and)),
202 .AssignBitOr => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitOr).?, .bitor)),225 .AssignBitOr => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitOr).?, .bit_or)),
203 .AssignBitShiftLeft => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftLeft).?, .shl)),226 .AssignBitShiftLeft => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftLeft).?, .shl)),
204 .AssignBitShiftRight => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftRight).?, .shr)),227 .AssignBitShiftRight => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftRight).?, .shr)),
205 .AssignBitXor => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitXor).?, .xor)),228 .AssignBitXor => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitXor).?, .xor)),
206 .AssignDiv => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignDiv).?, .div)),229 .AssignDiv => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignDiv).?, .div)),
207 .AssignSub => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSub).?, .sub)),230 .AssignSub => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSub).?, .sub)),
208 .AssignSubWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSubWrap).?, .subwrap)),231 .AssignSubWrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSubWrap).?, .subwrap)),
209 .AssignMod => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMod).?, .mod_rem)),232 .AssignMod => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMod).?, .mod_rem)),
210 .AssignAdd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAdd).?, .add)),233 .AssignAdd => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAdd).?, .add)),
211 .AssignAddWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAddWrap).?, .addwrap)),234 .AssignAddWrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAddWrap).?, .addwrap)),
212 .AssignMul => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMul).?, .mul)),235 .AssignMul => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMul).?, .mul)),
213 .AssignMulWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMulWrap).?, .mulwrap)),236 .AssignMulWrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMulWrap).?, .mulwrap)),
214237
215 .Add => return simpleBinOp(mod, scope, rl, node.castTag(.Add).?, .add),238 .Add => return simpleBinOp(mod, scope, rl, node.castTag(.Add).?, .add),
216 .AddWrap => return simpleBinOp(mod, scope, rl, node.castTag(.AddWrap).?, .addwrap),239 .AddWrap => return simpleBinOp(mod, scope, rl, node.castTag(.AddWrap).?, .addwrap),
...@@ -220,8 +243,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -220,8 +243,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
220 .MulWrap => return simpleBinOp(mod, scope, rl, node.castTag(.MulWrap).?, .mulwrap),243 .MulWrap => return simpleBinOp(mod, scope, rl, node.castTag(.MulWrap).?, .mulwrap),
221 .Div => return simpleBinOp(mod, scope, rl, node.castTag(.Div).?, .div),244 .Div => return simpleBinOp(mod, scope, rl, node.castTag(.Div).?, .div),
222 .Mod => return simpleBinOp(mod, scope, rl, node.castTag(.Mod).?, .mod_rem),245 .Mod => return simpleBinOp(mod, scope, rl, node.castTag(.Mod).?, .mod_rem),
223 .BitAnd => return simpleBinOp(mod, scope, rl, node.castTag(.BitAnd).?, .bitand),246 .BitAnd => return simpleBinOp(mod, scope, rl, node.castTag(.BitAnd).?, .bit_and),
224 .BitOr => return simpleBinOp(mod, scope, rl, node.castTag(.BitOr).?, .bitor),247 .BitOr => return simpleBinOp(mod, scope, rl, node.castTag(.BitOr).?, .bit_or),
225 .BitShiftLeft => return simpleBinOp(mod, scope, rl, node.castTag(.BitShiftLeft).?, .shl),248 .BitShiftLeft => return simpleBinOp(mod, scope, rl, node.castTag(.BitShiftLeft).?, .shl),
226 .BitShiftRight => return simpleBinOp(mod, scope, rl, node.castTag(.BitShiftRight).?, .shr),249 .BitShiftRight => return simpleBinOp(mod, scope, rl, node.castTag(.BitShiftRight).?, .shr),
227 .BitXor => return simpleBinOp(mod, scope, rl, node.castTag(.BitXor).?, .xor),250 .BitXor => return simpleBinOp(mod, scope, rl, node.castTag(.BitXor).?, .xor),
...@@ -239,15 +262,15 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -239,15 +262,15 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
239 .BoolAnd => return boolBinOp(mod, scope, rl, node.castTag(.BoolAnd).?),262 .BoolAnd => return boolBinOp(mod, scope, rl, node.castTag(.BoolAnd).?),
240 .BoolOr => return boolBinOp(mod, scope, rl, node.castTag(.BoolOr).?),263 .BoolOr => return boolBinOp(mod, scope, rl, node.castTag(.BoolOr).?),
241264
242 .BoolNot => return rlWrap(mod, scope, rl, try boolNot(mod, scope, node.castTag(.BoolNot).?)),265 .BoolNot => return rvalue(mod, scope, rl, try boolNot(mod, scope, node.castTag(.BoolNot).?)),
243 .BitNot => return rlWrap(mod, scope, rl, try bitNot(mod, scope, node.castTag(.BitNot).?)),266 .BitNot => return rvalue(mod, scope, rl, try bitNot(mod, scope, node.castTag(.BitNot).?)),
244 .Negation => return rlWrap(mod, scope, rl, try negation(mod, scope, node.castTag(.Negation).?, .sub)),267 .Negation => return rvalue(mod, scope, rl, try negation(mod, scope, node.castTag(.Negation).?, .sub)),
245 .NegationWrap => return rlWrap(mod, scope, rl, try negation(mod, scope, node.castTag(.NegationWrap).?, .subwrap)),268 .NegationWrap => return rvalue(mod, scope, rl, try negation(mod, scope, node.castTag(.NegationWrap).?, .subwrap)),
246269
247 .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?),270 .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?),
248 .Asm => return rlWrap(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)),271 .Asm => return rvalue(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)),
249 .StringLiteral => return rlWrap(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)),272 .StringLiteral => return rvalue(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)),
250 .IntegerLiteral => return rlWrap(mod, scope, rl, try integerLiteral(mod, scope, node.castTag(.IntegerLiteral).?)),273 .IntegerLiteral => return rvalue(mod, scope, rl, try integerLiteral(mod, scope, node.castTag(.IntegerLiteral).?)),
251 .BuiltinCall => return builtinCall(mod, scope, rl, node.castTag(.BuiltinCall).?),274 .BuiltinCall => return builtinCall(mod, scope, rl, node.castTag(.BuiltinCall).?),
252 .Call => return callExpr(mod, scope, rl, node.castTag(.Call).?),275 .Call => return callExpr(mod, scope, rl, node.castTag(.Call).?),
253 .Unreachable => return unreach(mod, scope, node.castTag(.Unreachable).?),276 .Unreachable => return unreach(mod, scope, node.castTag(.Unreachable).?),
...@@ -255,38 +278,38 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -255,38 +278,38 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
255 .If => return ifExpr(mod, scope, rl, node.castTag(.If).?),278 .If => return ifExpr(mod, scope, rl, node.castTag(.If).?),
256 .While => return whileExpr(mod, scope, rl, node.castTag(.While).?),279 .While => return whileExpr(mod, scope, rl, node.castTag(.While).?),
257 .Period => return field(mod, scope, rl, node.castTag(.Period).?),280 .Period => return field(mod, scope, rl, node.castTag(.Period).?),
258 .Deref => return rlWrap(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)),281 .Deref => return rvalue(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)),
259 .AddressOf => return rlWrap(mod, scope, rl, try addressOf(mod, scope, node.castTag(.AddressOf).?)),282 .AddressOf => return rvalue(mod, scope, rl, try addressOf(mod, scope, node.castTag(.AddressOf).?)),
260 .FloatLiteral => return rlWrap(mod, scope, rl, try floatLiteral(mod, scope, node.castTag(.FloatLiteral).?)),283 .FloatLiteral => return rvalue(mod, scope, rl, try floatLiteral(mod, scope, node.castTag(.FloatLiteral).?)),
261 .UndefinedLiteral => return rlWrap(mod, scope, rl, try undefLiteral(mod, scope, node.castTag(.UndefinedLiteral).?)),284 .UndefinedLiteral => return rvalue(mod, scope, rl, try undefLiteral(mod, scope, node.castTag(.UndefinedLiteral).?)),
262 .BoolLiteral => return rlWrap(mod, scope, rl, try boolLiteral(mod, scope, node.castTag(.BoolLiteral).?)),285 .BoolLiteral => return rvalue(mod, scope, rl, try boolLiteral(mod, scope, node.castTag(.BoolLiteral).?)),
263 .NullLiteral => return rlWrap(mod, scope, rl, try nullLiteral(mod, scope, node.castTag(.NullLiteral).?)),286 .NullLiteral => return rvalue(mod, scope, rl, try nullLiteral(mod, scope, node.castTag(.NullLiteral).?)),
264 .OptionalType => return rlWrap(mod, scope, rl, try optionalType(mod, scope, node.castTag(.OptionalType).?)),287 .OptionalType => return rvalue(mod, scope, rl, try optionalType(mod, scope, node.castTag(.OptionalType).?)),
265 .UnwrapOptional => return unwrapOptional(mod, scope, rl, node.castTag(.UnwrapOptional).?),288 .UnwrapOptional => return unwrapOptional(mod, scope, rl, node.castTag(.UnwrapOptional).?),
266 .Block => return rlWrapVoid(mod, scope, rl, node, try blockExpr(mod, scope, node.castTag(.Block).?)),289 .Block => return rvalueVoid(mod, scope, rl, node, try blockExpr(mod, scope, node.castTag(.Block).?)),
267 .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?, .block),290 .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?, .block),
268 .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)),291 .Break => return rvalue(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)),
269 .Continue => return rlWrap(mod, scope, rl, try continueExpr(mod, scope, node.castTag(.Continue).?)),292 .Continue => return rvalue(mod, scope, rl, try continueExpr(mod, scope, node.castTag(.Continue).?)),
270 .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)),293 .PtrType => return rvalue(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)),
271 .GroupedExpression => return expr(mod, scope, rl, node.castTag(.GroupedExpression).?.expr),294 .GroupedExpression => return expr(mod, scope, rl, node.castTag(.GroupedExpression).?.expr),
272 .ArrayType => return rlWrap(mod, scope, rl, try arrayType(mod, scope, node.castTag(.ArrayType).?)),295 .ArrayType => return rvalue(mod, scope, rl, try arrayType(mod, scope, node.castTag(.ArrayType).?)),
273 .ArrayTypeSentinel => return rlWrap(mod, scope, rl, try arrayTypeSentinel(mod, scope, node.castTag(.ArrayTypeSentinel).?)),296 .ArrayTypeSentinel => return rvalue(mod, scope, rl, try arrayTypeSentinel(mod, scope, node.castTag(.ArrayTypeSentinel).?)),
274 .EnumLiteral => return rlWrap(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)),297 .EnumLiteral => return rvalue(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)),
275 .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)),298 .MultilineStringLiteral => return rvalue(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)),
276 .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)),299 .CharLiteral => return rvalue(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)),
277 .SliceType => return rlWrap(mod, scope, rl, try sliceType(mod, scope, node.castTag(.SliceType).?)),300 .SliceType => return rvalue(mod, scope, rl, try sliceType(mod, scope, node.castTag(.SliceType).?)),
278 .ErrorUnion => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.ErrorUnion).?, .error_union_type)),301 .ErrorUnion => return rvalue(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.ErrorUnion).?, .error_union_type)),
279 .MergeErrorSets => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.MergeErrorSets).?, .merge_error_sets)),302 .MergeErrorSets => return rvalue(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.MergeErrorSets).?, .merge_error_sets)),
280 .AnyFrameType => return rlWrap(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)),303 .AnyFrameType => return rvalue(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)),
281 .ErrorSetDecl => return rlWrap(mod, scope, rl, try errorSetDecl(mod, scope, node.castTag(.ErrorSetDecl).?)),304 .ErrorSetDecl => return rvalue(mod, scope, rl, try errorSetDecl(mod, scope, node.castTag(.ErrorSetDecl).?)),
282 .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),305 .ErrorType => return rvalue(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
283 .For => return forExpr(mod, scope, rl, node.castTag(.For).?),306 .For => return forExpr(mod, scope, rl, node.castTag(.For).?),
284 .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),307 .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),
285 .Slice => return rlWrap(mod, scope, rl, try sliceExpr(mod, scope, node.castTag(.Slice).?)),308 .Slice => return rvalue(mod, scope, rl, try sliceExpr(mod, scope, node.castTag(.Slice).?)),
286 .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?),309 .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?),
287 .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?),310 .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?),
288 .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?),311 .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?),
289 .Switch => return switchExpr(mod, scope, rl, node.castTag(.Switch).?),312 .Switch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Switch", .{}),
290 .ContainerDecl => return containerDecl(mod, scope, rl, node.castTag(.ContainerDecl).?),313 .ContainerDecl => return containerDecl(mod, scope, rl, node.castTag(.ContainerDecl).?),
291314
292 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),315 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
...@@ -311,11 +334,19 @@ fn comptimeKeyword(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.C...@@ -311,11 +334,19 @@ fn comptimeKeyword(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.C
311 return comptimeExpr(mod, scope, rl, node.expr);334 return comptimeExpr(mod, scope, rl, node.expr);
312}335}
313336
314pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {337pub fn comptimeExpr(
315 const tree = parent_scope.tree();338 mod: *Module,
316 const src = tree.token_locs[node.firstToken()].start;339 parent_scope: *Scope,
340 rl: ResultLoc,
341 node: *ast.Node,
342) InnerError!*zir.Inst {
343 // If we are already in a comptime scope, no need to make another one.
344 if (parent_scope.isComptime()) {
345 return expr(mod, parent_scope, rl, node);
346 }
317347
318 // Optimization for labeled blocks: don't need to have 2 layers of blocks, we can reuse the existing one.348 // Optimization for labeled blocks: don't need to have 2 layers of blocks,
349 // we can reuse the existing one.
319 if (node.castTag(.LabeledBlock)) |block_node| {350 if (node.castTag(.LabeledBlock)) |block_node| {
320 return labeledBlockExpr(mod, parent_scope, rl, block_node, .block_comptime);351 return labeledBlockExpr(mod, parent_scope, rl, block_node, .block_comptime);
321 }352 }
...@@ -325,6 +356,7 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as...@@ -325,6 +356,7 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as
325 .parent = parent_scope,356 .parent = parent_scope,
326 .decl = parent_scope.ownerDecl().?,357 .decl = parent_scope.ownerDecl().?,
327 .arena = parent_scope.arena(),358 .arena = parent_scope.arena(),
359 .force_comptime = true,
328 .instructions = .{},360 .instructions = .{},
329 };361 };
330 defer block_scope.instructions.deinit(mod.gpa);362 defer block_scope.instructions.deinit(mod.gpa);
...@@ -333,6 +365,9 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as...@@ -333,6 +365,9 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as
333 // instruction is the block's result value.365 // instruction is the block's result value.
334 _ = try expr(mod, &block_scope.base, rl, node);366 _ = try expr(mod, &block_scope.base, rl, node);
335367
368 const tree = parent_scope.tree();
369 const src = tree.token_locs[node.firstToken()].start;
370
336 const block = try addZIRInstBlock(mod, parent_scope, src, .block_comptime_flat, .{371 const block = try addZIRInstBlock(mod, parent_scope, src, .block_comptime_flat, .{
337 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),372 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
338 });373 });
...@@ -340,7 +375,11 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as...@@ -340,7 +375,11 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as
340 return &block.base;375 return &block.base;
341}376}
342377
343fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst {378fn breakExpr(
379 mod: *Module,
380 parent_scope: *Scope,
381 node: *ast.Node.ControlFlowExpression,
382) InnerError!*zir.Inst {
344 const tree = parent_scope.tree();383 const tree = parent_scope.tree();
345 const src = tree.token_locs[node.ltoken].start;384 const src = tree.token_locs[node.ltoken].start;
346385
...@@ -366,25 +405,31 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr...@@ -366,25 +405,31 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr
366 continue;405 continue;
367 };406 };
368407
369 if (node.getRHS()) |rhs| {408 const rhs = node.getRHS() orelse {
370 // Most result location types can be forwarded directly; however409 return addZirInstTag(mod, parent_scope, src, .break_void, .{
371 // if we need to write to a pointer which has an inferred type,
372 // proper type inference requires peer type resolution on the block's
373 // break operand expressions.
374 const branch_rl: ResultLoc = switch (gen_zir.break_result_loc) {
375 .discard, .none, .ty, .ptr, .ref => gen_zir.break_result_loc,
376 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block_inst },
377 };
378 const operand = try expr(mod, parent_scope, branch_rl, rhs);
379 return try addZIRInst(mod, parent_scope, src, zir.Inst.Break, .{
380 .block = block_inst,410 .block = block_inst,
381 .operand = operand,411 });
382 }, .{});412 };
383 } else {413 gen_zir.break_count += 1;
384 return try addZIRInst(mod, parent_scope, src, zir.Inst.BreakVoid, .{414 const prev_rvalue_rl_count = gen_zir.rvalue_rl_count;
385 .block = block_inst,415 const operand = try expr(mod, parent_scope, gen_zir.break_result_loc, rhs);
386 }, .{});416 const have_store_to_block = gen_zir.rvalue_rl_count != prev_rvalue_rl_count;
417 const br = try addZirInstTag(mod, parent_scope, src, .@"break", .{
418 .block = block_inst,
419 .operand = operand,
420 });
421 if (gen_zir.break_result_loc == .block_ptr) {
422 try gen_zir.labeled_breaks.append(mod.gpa, br.castTag(.@"break").?);
423
424 if (have_store_to_block) {
425 const inst_list = parent_scope.getGenZIR().instructions.items;
426 const last_inst = inst_list[inst_list.len - 2];
427 const store_inst = last_inst.castTag(.store_to_block_ptr).?;
428 assert(store_inst.positionals.lhs == gen_zir.rl_ptr.?);
429 try gen_zir.labeled_store_to_block_ptr_list.append(mod.gpa, store_inst);
430 }
387 }431 }
432 return br;
388 },433 },
389 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,434 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
390 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,435 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
...@@ -424,9 +469,9 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowE...@@ -424,9 +469,9 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowE
424 continue;469 continue;
425 }470 }
426471
427 return addZIRInst(mod, parent_scope, src, zir.Inst.BreakVoid, .{472 return addZirInstTag(mod, parent_scope, src, .break_void, .{
428 .block = continue_block,473 .block = continue_block,
429 }, .{});474 });
430 },475 },
431 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,476 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
432 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,477 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
...@@ -526,28 +571,65 @@ fn labeledBlockExpr(...@@ -526,28 +571,65 @@ fn labeledBlockExpr(
526 .parent = parent_scope,571 .parent = parent_scope,
527 .decl = parent_scope.ownerDecl().?,572 .decl = parent_scope.ownerDecl().?,
528 .arena = gen_zir.arena,573 .arena = gen_zir.arena,
574 .force_comptime = parent_scope.isComptime(),
529 .instructions = .{},575 .instructions = .{},
530 .break_result_loc = rl,
531 // TODO @as here is working around a stage1 miscompilation bug :(576 // TODO @as here is working around a stage1 miscompilation bug :(
532 .label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{577 .label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{
533 .token = block_node.label,578 .token = block_node.label,
534 .block_inst = block_inst,579 .block_inst = block_inst,
535 }),580 }),
536 };581 };
582 setBlockResultLoc(&block_scope, rl);
537 defer block_scope.instructions.deinit(mod.gpa);583 defer block_scope.instructions.deinit(mod.gpa);
584 defer block_scope.labeled_breaks.deinit(mod.gpa);
585 defer block_scope.labeled_store_to_block_ptr_list.deinit(mod.gpa);
538586
539 try blockExprStmts(mod, &block_scope.base, &block_node.base, block_node.statements());587 try blockExprStmts(mod, &block_scope.base, &block_node.base, block_node.statements());
588
540 if (!block_scope.label.?.used) {589 if (!block_scope.label.?.used) {
541 return mod.fail(parent_scope, tree.token_locs[block_node.label].start, "unused block label", .{});590 return mod.fail(parent_scope, tree.token_locs[block_node.label].start, "unused block label", .{});
542 }591 }
543592
544 block_inst.positionals.body.instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items);
545 try gen_zir.instructions.append(mod.gpa, &block_inst.base);593 try gen_zir.instructions.append(mod.gpa, &block_inst.base);
546594
547 return &block_inst.base;595 const strat = rlStrategy(rl, &block_scope);
596 switch (strat.tag) {
597 .break_void => {
598 // The code took advantage of the result location as a pointer.
599 // Turn the break instructions into break_void instructions.
600 for (block_scope.labeled_breaks.items) |br| {
601 br.base.tag = .break_void;
602 }
603 // TODO technically not needed since we changed the tag to break_void but
604 // would be better still to elide the ones that are in this list.
605 try copyBodyNoEliding(&block_inst.positionals.body, block_scope);
606
607 return &block_inst.base;
608 },
609 .break_operand => {
610 // All break operands are values that did not use the result location pointer.
611 if (strat.elide_store_to_block_ptr_instructions) {
612 for (block_scope.labeled_store_to_block_ptr_list.items) |inst| {
613 inst.base.tag = .void_value;
614 }
615 // TODO technically not needed since we changed the tag to void_value but
616 // would be better still to elide the ones that are in this list.
617 }
618 try copyBodyNoEliding(&block_inst.positionals.body, block_scope);
619 switch (rl) {
620 .ref => return &block_inst.base,
621 else => return rvalue(mod, parent_scope, rl, &block_inst.base),
622 }
623 },
624 }
548}625}
549626
550fn blockExprStmts(mod: *Module, parent_scope: *Scope, node: *ast.Node, statements: []*ast.Node) !void {627fn blockExprStmts(
628 mod: *Module,
629 parent_scope: *Scope,
630 node: *ast.Node,
631 statements: []*ast.Node,
632) !void {
551 const tree = parent_scope.tree();633 const tree = parent_scope.tree();
552634
553 var block_arena = std.heap.ArenaAllocator.init(mod.gpa);635 var block_arena = std.heap.ArenaAllocator.init(mod.gpa);
...@@ -563,8 +645,8 @@ fn blockExprStmts(mod: *Module, parent_scope: *Scope, node: *ast.Node, statement...@@ -563,8 +645,8 @@ fn blockExprStmts(mod: *Module, parent_scope: *Scope, node: *ast.Node, statement
563 scope = try varDecl(mod, scope, var_decl_node, &block_arena.allocator);645 scope = try varDecl(mod, scope, var_decl_node, &block_arena.allocator);
564 },646 },
565 .Assign => try assign(mod, scope, statement.castTag(.Assign).?),647 .Assign => try assign(mod, scope, statement.castTag(.Assign).?),
566 .AssignBitAnd => try assignOp(mod, scope, statement.castTag(.AssignBitAnd).?, .bitand),648 .AssignBitAnd => try assignOp(mod, scope, statement.castTag(.AssignBitAnd).?, .bit_and),
567 .AssignBitOr => try assignOp(mod, scope, statement.castTag(.AssignBitOr).?, .bitor),649 .AssignBitOr => try assignOp(mod, scope, statement.castTag(.AssignBitOr).?, .bit_or),
568 .AssignBitShiftLeft => try assignOp(mod, scope, statement.castTag(.AssignBitShiftLeft).?, .shl),650 .AssignBitShiftLeft => try assignOp(mod, scope, statement.castTag(.AssignBitShiftLeft).?, .shl),
569 .AssignBitShiftRight => try assignOp(mod, scope, statement.castTag(.AssignBitShiftRight).?, .shr),651 .AssignBitShiftRight => try assignOp(mod, scope, statement.castTag(.AssignBitShiftRight).?, .shr),
570 .AssignBitXor => try assignOp(mod, scope, statement.castTag(.AssignBitXor).?, .xor),652 .AssignBitXor => try assignOp(mod, scope, statement.castTag(.AssignBitXor).?, .xor),
...@@ -644,6 +726,7 @@ fn varDecl(...@@ -644,6 +726,7 @@ fn varDecl(
644726
645 // Namespace vars shadowing detection727 // Namespace vars shadowing detection
646 if (mod.lookupDeclName(scope, ident_name)) |_| {728 if (mod.lookupDeclName(scope, ident_name)) |_| {
729 // TODO add note for other definition
647 return mod.fail(scope, name_src, "redefinition of '{s}'", .{ident_name});730 return mod.fail(scope, name_src, "redefinition of '{s}'", .{ident_name});
648 }731 }
649 const init_node = node.getInitNode() orelse732 const init_node = node.getInitNode() orelse
...@@ -651,36 +734,103 @@ fn varDecl(...@@ -651,36 +734,103 @@ fn varDecl(
651734
652 switch (tree.token_ids[node.mut_token]) {735 switch (tree.token_ids[node.mut_token]) {
653 .Keyword_const => {736 .Keyword_const => {
654 var resolve_inferred_alloc: ?*zir.Inst = null;
655 // Depending on the type of AST the initialization expression is, we may need an lvalue737 // Depending on the type of AST the initialization expression is, we may need an lvalue
656 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as738 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
657 // the variable, no memory location needed.739 // the variable, no memory location needed.
658 const result_loc = if (nodeMayNeedMemoryLocation(init_node, scope)) r: {740 if (!nodeMayNeedMemoryLocation(init_node, scope)) {
659 if (node.getTypeNode()) |type_node| {741 const result_loc: ResultLoc = if (node.getTypeNode()) |type_node|
660 const type_inst = try typeExpr(mod, scope, type_node);742 .{ .ty = try typeExpr(mod, scope, type_node) }
661 const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst);
662 break :r ResultLoc{ .ptr = alloc };
663 } else {
664 const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred);
665 resolve_inferred_alloc = &alloc.base;
666 break :r ResultLoc{ .inferred_ptr = alloc };
667 }
668 } else r: {
669 if (node.getTypeNode()) |type_node|
670 break :r ResultLoc{ .ty = try typeExpr(mod, scope, type_node) }
671 else743 else
672 break :r .none;744 .none;
745 const init_inst = try expr(mod, scope, result_loc, init_node);
746 const sub_scope = try block_arena.create(Scope.LocalVal);
747 sub_scope.* = .{
748 .parent = scope,
749 .gen_zir = scope.getGenZIR(),
750 .name = ident_name,
751 .inst = init_inst,
752 };
753 return &sub_scope.base;
754 }
755
756 // Detect whether the initialization expression actually uses the
757 // result location pointer.
758 var init_scope: Scope.GenZIR = .{
759 .parent = scope,
760 .decl = scope.ownerDecl().?,
761 .arena = scope.arena(),
762 .force_comptime = scope.isComptime(),
763 .instructions = .{},
673 };764 };
674 const init_inst = try expr(mod, scope, result_loc, init_node);765 defer init_scope.instructions.deinit(mod.gpa);
766
767 var resolve_inferred_alloc: ?*zir.Inst = null;
768 var opt_type_inst: ?*zir.Inst = null;
769 if (node.getTypeNode()) |type_node| {
770 const type_inst = try typeExpr(mod, &init_scope.base, type_node);
771 opt_type_inst = type_inst;
772 init_scope.rl_ptr = try addZIRUnOp(mod, &init_scope.base, name_src, .alloc, type_inst);
773 } else {
774 const alloc = try addZIRNoOpT(mod, &init_scope.base, name_src, .alloc_inferred);
775 resolve_inferred_alloc = &alloc.base;
776 init_scope.rl_ptr = &alloc.base;
777 }
778 const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope };
779 const init_inst = try expr(mod, &init_scope.base, init_result_loc, init_node);
780 const parent_zir = &scope.getGenZIR().instructions;
781 if (init_scope.rvalue_rl_count == 1) {
782 // Result location pointer not used. We don't need an alloc for this
783 // const local, and type inference becomes trivial.
784 // Move the init_scope instructions into the parent scope, eliding
785 // the alloc instruction and the store_to_block_ptr instruction.
786 const expected_len = parent_zir.items.len + init_scope.instructions.items.len - 2;
787 try parent_zir.ensureCapacity(mod.gpa, expected_len);
788 for (init_scope.instructions.items) |src_inst| {
789 if (src_inst == init_scope.rl_ptr.?) continue;
790 if (src_inst.castTag(.store_to_block_ptr)) |store| {
791 if (store.positionals.lhs == init_scope.rl_ptr.?) continue;
792 }
793 parent_zir.appendAssumeCapacity(src_inst);
794 }
795 assert(parent_zir.items.len == expected_len);
796 const casted_init = if (opt_type_inst) |type_inst|
797 try addZIRBinOp(mod, scope, type_inst.src, .as, type_inst, init_inst)
798 else
799 init_inst;
800
801 const sub_scope = try block_arena.create(Scope.LocalVal);
802 sub_scope.* = .{
803 .parent = scope,
804 .gen_zir = scope.getGenZIR(),
805 .name = ident_name,
806 .inst = casted_init,
807 };
808 return &sub_scope.base;
809 }
810 // The initialization expression took advantage of the result location
811 // of the const local. In this case we will create an alloc and a LocalPtr for it.
812 // Move the init_scope instructions into the parent scope, swapping
813 // store_to_block_ptr for store_to_inferred_ptr.
814 const expected_len = parent_zir.items.len + init_scope.instructions.items.len;
815 try parent_zir.ensureCapacity(mod.gpa, expected_len);
816 for (init_scope.instructions.items) |src_inst| {
817 if (src_inst.castTag(.store_to_block_ptr)) |store| {
818 if (store.positionals.lhs == init_scope.rl_ptr.?) {
819 src_inst.tag = .store_to_inferred_ptr;
820 }
821 }
822 parent_zir.appendAssumeCapacity(src_inst);
823 }
824 assert(parent_zir.items.len == expected_len);
675 if (resolve_inferred_alloc) |inst| {825 if (resolve_inferred_alloc) |inst| {
676 _ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst);826 _ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst);
677 }827 }
678 const sub_scope = try block_arena.create(Scope.LocalVal);828 const sub_scope = try block_arena.create(Scope.LocalPtr);
679 sub_scope.* = .{829 sub_scope.* = .{
680 .parent = scope,830 .parent = scope,
681 .gen_zir = scope.getGenZIR(),831 .gen_zir = scope.getGenZIR(),
682 .name = ident_name,832 .name = ident_name,
683 .inst = init_inst,833 .ptr = init_scope.rl_ptr.?,
684 };834 };
685 return &sub_scope.base;835 return &sub_scope.base;
686 },836 },
...@@ -751,14 +901,14 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr...@@ -751,14 +901,14 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
751 .val = Value.initTag(.bool_type),901 .val = Value.initTag(.bool_type),
752 });902 });
753 const operand = try expr(mod, scope, .{ .ty = bool_type }, node.rhs);903 const operand = try expr(mod, scope, .{ .ty = bool_type }, node.rhs);
754 return addZIRUnOp(mod, scope, src, .boolnot, operand);904 return addZIRUnOp(mod, scope, src, .bool_not, operand);
755}905}
756906
757fn bitNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {907fn bitNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
758 const tree = scope.tree();908 const tree = scope.tree();
759 const src = tree.token_locs[node.op_token].start;909 const src = tree.token_locs[node.op_token].start;
760 const operand = try expr(mod, scope, .none, node.rhs);910 const operand = try expr(mod, scope, .none, node.rhs);
761 return addZIRUnOp(mod, scope, src, .bitnot, operand);911 return addZIRUnOp(mod, scope, src, .bit_not, operand);
762}912}
763913
764fn negation(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp, op_inst_tag: zir.Inst.Tag) InnerError!*zir.Inst {914fn negation(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp, op_inst_tag: zir.Inst.Tag) InnerError!*zir.Inst {
...@@ -971,6 +1121,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con...@@ -971,6 +1121,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
971 .parent = scope,1121 .parent = scope,
972 .decl = scope.ownerDecl().?,1122 .decl = scope.ownerDecl().?,
973 .arena = scope.arena(),1123 .arena = scope.arena(),
1124 .force_comptime = scope.isComptime(),
974 .instructions = .{},1125 .instructions = .{},
975 };1126 };
976 defer gen_scope.instructions.deinit(mod.gpa);1127 defer gen_scope.instructions.deinit(mod.gpa);
...@@ -1101,7 +1252,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con...@@ -1101,7 +1252,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
1101 if (rl == .ref) {1252 if (rl == .ref) {
1102 return addZIRInst(mod, scope, src, zir.Inst.DeclRef, .{ .decl = decl }, .{});1253 return addZIRInst(mod, scope, src, zir.Inst.DeclRef, .{ .decl = decl }, .{});
1103 } else {1254 } else {
1104 return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclVal, .{1255 return rvalue(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclVal, .{
1105 .decl = decl,1256 .decl = decl,
1106 }, .{}));1257 }, .{}));
1107 }1258 }
...@@ -1207,24 +1358,15 @@ fn orelseCatchExpr(...@@ -1207,24 +1358,15 @@ fn orelseCatchExpr(
1207 .parent = scope,1358 .parent = scope,
1208 .decl = scope.ownerDecl().?,1359 .decl = scope.ownerDecl().?,
1209 .arena = scope.arena(),1360 .arena = scope.arena(),
1361 .force_comptime = scope.isComptime(),
1210 .instructions = .{},1362 .instructions = .{},
1211 };1363 };
1364 setBlockResultLoc(&block_scope, rl);
1212 defer block_scope.instructions.deinit(mod.gpa);1365 defer block_scope.instructions.deinit(mod.gpa);
12131366
1214 const block = try addZIRInstBlock(mod, scope, src, .block, .{
1215 .instructions = undefined, // populated below
1216 });
1217
1218 // Most result location types can be forwarded directly; however
1219 // if we need to write to a pointer which has an inferred type,
1220 // proper type inference requires peer type resolution on the if's
1221 // branches.
1222 const branch_rl: ResultLoc = switch (rl) {
1223 .discard, .none, .ty, .ptr, .ref => rl,
1224 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
1225 };
1226 // This could be a pointer or value depending on the `rl` parameter.1367 // This could be a pointer or value depending on the `rl` parameter.
1227 const operand = try expr(mod, &block_scope.base, branch_rl, lhs);1368 block_scope.break_count += 1;
1369 const operand = try expr(mod, &block_scope.base, block_scope.break_result_loc, lhs);
1228 const cond = try addZIRUnOp(mod, &block_scope.base, src, cond_op, operand);1370 const cond = try addZIRUnOp(mod, &block_scope.base, src, cond_op, operand);
12291371
1230 const condbr = try addZIRInstSpecial(mod, &block_scope.base, src, zir.Inst.CondBr, .{1372 const condbr = try addZIRInstSpecial(mod, &block_scope.base, src, zir.Inst.CondBr, .{
...@@ -1233,18 +1375,22 @@ fn orelseCatchExpr(...@@ -1233,18 +1375,22 @@ fn orelseCatchExpr(
1233 .else_body = undefined, // populated below1375 .else_body = undefined, // populated below
1234 }, .{});1376 }, .{});
12351377
1378 const block = try addZIRInstBlock(mod, scope, src, .block, .{
1379 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
1380 });
1381
1236 var then_scope: Scope.GenZIR = .{1382 var then_scope: Scope.GenZIR = .{
1237 .parent = &block_scope.base,1383 .parent = &block_scope.base,
1238 .decl = block_scope.decl,1384 .decl = block_scope.decl,
1239 .arena = block_scope.arena,1385 .arena = block_scope.arena,
1386 .force_comptime = block_scope.force_comptime,
1240 .instructions = .{},1387 .instructions = .{},
1241 };1388 };
1242 defer then_scope.instructions.deinit(mod.gpa);1389 defer then_scope.instructions.deinit(mod.gpa);
12431390
1244 var err_val_scope: Scope.LocalVal = undefined;1391 var err_val_scope: Scope.LocalVal = undefined;
1245 const then_sub_scope = blk: {1392 const then_sub_scope = blk: {
1246 const payload = payload_node orelse1393 const payload = payload_node orelse break :blk &then_scope.base;
1247 break :blk &then_scope.base;
12481394
1249 const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken());1395 const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken());
1250 if (mem.eql(u8, err_name, "_"))1396 if (mem.eql(u8, err_name, "_"))
...@@ -1259,32 +1405,113 @@ fn orelseCatchExpr(...@@ -1259,32 +1405,113 @@ fn orelseCatchExpr(
1259 break :blk &err_val_scope.base;1405 break :blk &err_val_scope.base;
1260 };1406 };
12611407
1262 _ = try addZIRInst(mod, &then_scope.base, src, zir.Inst.Break, .{1408 block_scope.break_count += 1;
1263 .block = block,1409 const then_result = try expr(mod, then_sub_scope, block_scope.break_result_loc, rhs);
1264 .operand = try expr(mod, then_sub_scope, branch_rl, rhs),
1265 }, .{});
12661410
1267 var else_scope: Scope.GenZIR = .{1411 var else_scope: Scope.GenZIR = .{
1268 .parent = &block_scope.base,1412 .parent = &block_scope.base,
1269 .decl = block_scope.decl,1413 .decl = block_scope.decl,
1270 .arena = block_scope.arena,1414 .arena = block_scope.arena,
1415 .force_comptime = block_scope.force_comptime,
1271 .instructions = .{},1416 .instructions = .{},
1272 };1417 };
1273 defer else_scope.instructions.deinit(mod.gpa);1418 defer else_scope.instructions.deinit(mod.gpa);
12741419
1275 // This could be a pointer or value depending on `unwrap_op`.1420 // This could be a pointer or value depending on `unwrap_op`.
1276 const unwrapped_payload = try addZIRUnOp(mod, &else_scope.base, src, unwrap_op, operand);1421 const unwrapped_payload = try addZIRUnOp(mod, &else_scope.base, src, unwrap_op, operand);
1277 _ = try addZIRInst(mod, &else_scope.base, src, zir.Inst.Break, .{
1278 .block = block,
1279 .operand = unwrapped_payload,
1280 }, .{});
12811422
1282 // All branches have been generated, add the instructions to the block.1423 return finishThenElseBlock(
1283 block.positionals.body.instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items);1424 mod,
1425 scope,
1426 rl,
1427 &block_scope,
1428 &then_scope,
1429 &else_scope,
1430 &condbr.positionals.then_body,
1431 &condbr.positionals.else_body,
1432 src,
1433 src,
1434 then_result,
1435 unwrapped_payload,
1436 block,
1437 block,
1438 );
1439}
12841440
1285 condbr.positionals.then_body = .{ .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items) };1441fn finishThenElseBlock(
1286 condbr.positionals.else_body = .{ .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items) };1442 mod: *Module,
1287 return &block.base;1443 parent_scope: *Scope,
1444 rl: ResultLoc,
1445 block_scope: *Scope.GenZIR,
1446 then_scope: *Scope.GenZIR,
1447 else_scope: *Scope.GenZIR,
1448 then_body: *zir.Body,
1449 else_body: *zir.Body,
1450 then_src: usize,
1451 else_src: usize,
1452 then_result: *zir.Inst,
1453 else_result: ?*zir.Inst,
1454 main_block: *zir.Inst.Block,
1455 then_break_block: *zir.Inst.Block,
1456) InnerError!*zir.Inst {
1457 // We now have enough information to decide whether the result instruction should
1458 // be communicated via result location pointer or break instructions.
1459 const strat = rlStrategy(rl, block_scope);
1460 switch (strat.tag) {
1461 .break_void => {
1462 if (!then_result.tag.isNoReturn()) {
1463 _ = try addZirInstTag(mod, &then_scope.base, then_src, .break_void, .{
1464 .block = then_break_block,
1465 });
1466 }
1467 if (else_result) |inst| {
1468 if (!inst.tag.isNoReturn()) {
1469 _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{
1470 .block = main_block,
1471 });
1472 }
1473 } else {
1474 _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{
1475 .block = main_block,
1476 });
1477 }
1478 assert(!strat.elide_store_to_block_ptr_instructions);
1479 try copyBodyNoEliding(then_body, then_scope.*);
1480 try copyBodyNoEliding(else_body, else_scope.*);
1481 return &main_block.base;
1482 },
1483 .break_operand => {
1484 if (!then_result.tag.isNoReturn()) {
1485 _ = try addZirInstTag(mod, &then_scope.base, then_src, .@"break", .{
1486 .block = then_break_block,
1487 .operand = then_result,
1488 });
1489 }
1490 if (else_result) |inst| {
1491 if (!inst.tag.isNoReturn()) {
1492 _ = try addZirInstTag(mod, &else_scope.base, else_src, .@"break", .{
1493 .block = main_block,
1494 .operand = inst,
1495 });
1496 }
1497 } else {
1498 _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{
1499 .block = main_block,
1500 });
1501 }
1502 if (strat.elide_store_to_block_ptr_instructions) {
1503 try copyBodyWithElidedStoreBlockPtr(then_body, then_scope.*);
1504 try copyBodyWithElidedStoreBlockPtr(else_body, else_scope.*);
1505 } else {
1506 try copyBodyNoEliding(then_body, then_scope.*);
1507 try copyBodyNoEliding(else_body, else_scope.*);
1508 }
1509 switch (rl) {
1510 .ref => return &main_block.base,
1511 else => return rvalue(mod, parent_scope, rl, &main_block.base),
1512 }
1513 },
1514 }
1288}1515}
12891516
1290/// Return whether the identifier names of two tokens are equal. Resolves @""1517/// Return whether the identifier names of two tokens are equal. Resolves @""
...@@ -1308,7 +1535,7 @@ pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleI...@@ -1308,7 +1535,7 @@ pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleI
1308 .field_name = field_name,1535 .field_name = field_name,
1309 });1536 });
1310 }1537 }
1311 return rlWrap(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val, .{1538 return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val, .{
1312 .object = try expr(mod, scope, .none, node.lhs),1539 .object = try expr(mod, scope, .none, node.lhs),
1313 .field_name = field_name,1540 .field_name = field_name,
1314 }));1541 }));
...@@ -1338,7 +1565,7 @@ fn namedField(...@@ -1338,7 +1565,7 @@ fn namedField(
1338 .field_name = try comptimeExpr(mod, scope, string_rl, params[1]),1565 .field_name = try comptimeExpr(mod, scope, string_rl, params[1]),
1339 });1566 });
1340 }1567 }
1341 return rlWrap(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val_named, .{1568 return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val_named, .{
1342 .object = try expr(mod, scope, .none, params[0]),1569 .object = try expr(mod, scope, .none, params[0]),
1343 .field_name = try comptimeExpr(mod, scope, string_rl, params[1]),1570 .field_name = try comptimeExpr(mod, scope, string_rl, params[1]),
1344 }));1571 }));
...@@ -1359,7 +1586,7 @@ fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Array...@@ -1359,7 +1586,7 @@ fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Array
1359 .index = try expr(mod, scope, index_rl, node.index_expr),1586 .index = try expr(mod, scope, index_rl, node.index_expr),
1360 });1587 });
1361 }1588 }
1362 return rlWrap(mod, scope, rl, try addZirInstTag(mod, scope, src, .elem_val, .{1589 return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .elem_val, .{
1363 .array = try expr(mod, scope, .none, node.lhs),1590 .array = try expr(mod, scope, .none, node.lhs),
1364 .index = try expr(mod, scope, index_rl, node.index_expr),1591 .index = try expr(mod, scope, index_rl, node.index_expr),
1365 }));1592 }));
...@@ -1416,7 +1643,7 @@ fn simpleBinOp(...@@ -1416,7 +1643,7 @@ fn simpleBinOp(
1416 const rhs = try expr(mod, scope, .none, infix_node.rhs);1643 const rhs = try expr(mod, scope, .none, infix_node.rhs);
14171644
1418 const result = try addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs);1645 const result = try addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs);
1419 return rlWrap(mod, scope, rl, result);1646 return rvalue(mod, scope, rl, result);
1420}1647}
14211648
1422fn boolBinOp(1649fn boolBinOp(
...@@ -1436,6 +1663,7 @@ fn boolBinOp(...@@ -1436,6 +1663,7 @@ fn boolBinOp(
1436 .parent = scope,1663 .parent = scope,
1437 .decl = scope.ownerDecl().?,1664 .decl = scope.ownerDecl().?,
1438 .arena = scope.arena(),1665 .arena = scope.arena(),
1666 .force_comptime = scope.isComptime(),
1439 .instructions = .{},1667 .instructions = .{},
1440 };1668 };
1441 defer block_scope.instructions.deinit(mod.gpa);1669 defer block_scope.instructions.deinit(mod.gpa);
...@@ -1455,6 +1683,7 @@ fn boolBinOp(...@@ -1455,6 +1683,7 @@ fn boolBinOp(
1455 .parent = scope,1683 .parent = scope,
1456 .decl = block_scope.decl,1684 .decl = block_scope.decl,
1457 .arena = block_scope.arena,1685 .arena = block_scope.arena,
1686 .force_comptime = block_scope.force_comptime,
1458 .instructions = .{},1687 .instructions = .{},
1459 };1688 };
1460 defer rhs_scope.instructions.deinit(mod.gpa);1689 defer rhs_scope.instructions.deinit(mod.gpa);
...@@ -1469,6 +1698,7 @@ fn boolBinOp(...@@ -1469,6 +1698,7 @@ fn boolBinOp(
1469 .parent = scope,1698 .parent = scope,
1470 .decl = block_scope.decl,1699 .decl = block_scope.decl,
1471 .arena = block_scope.arena,1700 .arena = block_scope.arena,
1701 .force_comptime = block_scope.force_comptime,
1472 .instructions = .{},1702 .instructions = .{},
1473 };1703 };
1474 defer const_scope.instructions.deinit(mod.gpa);1704 defer const_scope.instructions.deinit(mod.gpa);
...@@ -1498,7 +1728,7 @@ fn boolBinOp(...@@ -1498,7 +1728,7 @@ fn boolBinOp(
1498 condbr.positionals.else_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) };1728 condbr.positionals.else_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) };
1499 }1729 }
15001730
1501 return rlWrap(mod, scope, rl, &block.base);1731 return rvalue(mod, scope, rl, &block.base);
1502}1732}
15031733
1504const CondKind = union(enum) {1734const CondKind = union(enum) {
...@@ -1582,8 +1812,10 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn...@@ -1582,8 +1812,10 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
1582 .parent = scope,1812 .parent = scope,
1583 .decl = scope.ownerDecl().?,1813 .decl = scope.ownerDecl().?,
1584 .arena = scope.arena(),1814 .arena = scope.arena(),
1815 .force_comptime = scope.isComptime(),
1585 .instructions = .{},1816 .instructions = .{},
1586 };1817 };
1818 setBlockResultLoc(&block_scope, rl);
1587 defer block_scope.instructions.deinit(mod.gpa);1819 defer block_scope.instructions.deinit(mod.gpa);
15881820
1589 const tree = scope.tree();1821 const tree = scope.tree();
...@@ -1605,6 +1837,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn...@@ -1605,6 +1837,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
1605 .parent = scope,1837 .parent = scope,
1606 .decl = block_scope.decl,1838 .decl = block_scope.decl,
1607 .arena = block_scope.arena,1839 .arena = block_scope.arena,
1840 .force_comptime = block_scope.force_comptime,
1608 .instructions = .{},1841 .instructions = .{},
1609 };1842 };
1610 defer then_scope.instructions.deinit(mod.gpa);1843 defer then_scope.instructions.deinit(mod.gpa);
...@@ -1612,62 +1845,81 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn...@@ -1612,62 +1845,81 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
1612 // declare payload to the then_scope1845 // declare payload to the then_scope
1613 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, if_node.payload);1846 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, if_node.payload);
16141847
1615 // Most result location types can be forwarded directly; however1848 block_scope.break_count += 1;
1616 // if we need to write to a pointer which has an inferred type,1849 const then_result = try expr(mod, then_sub_scope, block_scope.break_result_loc, if_node.body);
1617 // proper type inference requires peer type resolution on the if's1850 // We hold off on the break instructions as well as copying the then/else
1618 // branches.1851 // instructions into place until we know whether to keep store_to_block_ptr
1619 const branch_rl: ResultLoc = switch (rl) {1852 // instructions or not.
1620 .discard, .none, .ty, .ptr, .ref => rl,
1621 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
1622 };
1623
1624 const then_result = try expr(mod, then_sub_scope, branch_rl, if_node.body);
1625 if (!then_result.tag.isNoReturn()) {
1626 _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{
1627 .block = block,
1628 .operand = then_result,
1629 }, .{});
1630 }
1631 condbr.positionals.then_body = .{
1632 .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items),
1633 };
16341853
1635 var else_scope: Scope.GenZIR = .{1854 var else_scope: Scope.GenZIR = .{
1636 .parent = scope,1855 .parent = scope,
1637 .decl = block_scope.decl,1856 .decl = block_scope.decl,
1638 .arena = block_scope.arena,1857 .arena = block_scope.arena,
1858 .force_comptime = block_scope.force_comptime,
1639 .instructions = .{},1859 .instructions = .{},
1640 };1860 };
1641 defer else_scope.instructions.deinit(mod.gpa);1861 defer else_scope.instructions.deinit(mod.gpa);
16421862
1643 if (if_node.@"else") |else_node| {1863 var else_src: usize = undefined;
1644 const else_src = tree.token_locs[else_node.body.lastToken()].start;1864 var else_sub_scope: *Module.Scope = undefined;
1865 const else_result: ?*zir.Inst = if (if_node.@"else") |else_node| blk: {
1866 else_src = tree.token_locs[else_node.body.lastToken()].start;
1645 // declare payload to the then_scope1867 // declare payload to the then_scope
1646 const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload);1868 else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload);
1869
1870 block_scope.break_count += 1;
1871 break :blk try expr(mod, else_sub_scope, block_scope.break_result_loc, else_node.body);
1872 } else blk: {
1873 else_src = tree.token_locs[if_node.lastToken()].start;
1874 else_sub_scope = &else_scope.base;
1875 break :blk null;
1876 };
16471877
1648 const else_result = try expr(mod, else_sub_scope, branch_rl, else_node.body);1878 return finishThenElseBlock(
1649 if (!else_result.tag.isNoReturn()) {1879 mod,
1650 _ = try addZIRInst(mod, else_sub_scope, else_src, zir.Inst.Break, .{1880 scope,
1651 .block = block,1881 rl,
1652 .operand = else_result,1882 &block_scope,
1653 }, .{});1883 &then_scope,
1884 &else_scope,
1885 &condbr.positionals.then_body,
1886 &condbr.positionals.else_body,
1887 then_src,
1888 else_src,
1889 then_result,
1890 else_result,
1891 block,
1892 block,
1893 );
1894}
1895
1896/// Expects to find exactly 1 .store_to_block_ptr instruction.
1897fn copyBodyWithElidedStoreBlockPtr(body: *zir.Body, scope: Module.Scope.GenZIR) !void {
1898 body.* = .{
1899 .instructions = try scope.arena.alloc(*zir.Inst, scope.instructions.items.len - 1),
1900 };
1901 var dst_index: usize = 0;
1902 for (scope.instructions.items) |src_inst| {
1903 if (src_inst.tag != .store_to_block_ptr) {
1904 body.instructions[dst_index] = src_inst;
1905 dst_index += 1;
1654 }1906 }
1655 } else {
1656 // TODO Optimization opportunity: we can avoid an allocation and a memcpy here
1657 // by directly allocating the body for this one instruction.
1658 const else_src = tree.token_locs[if_node.lastToken()].start;
1659 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{
1660 .block = block,
1661 }, .{});
1662 }1907 }
1663 condbr.positionals.else_body = .{1908 assert(dst_index == body.instructions.len);
1664 .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),1909}
1665 };
16661910
1667 return &block.base;1911fn copyBodyNoEliding(body: *zir.Body, scope: Module.Scope.GenZIR) !void {
1912 body.* = .{
1913 .instructions = try scope.arena.dupe(*zir.Inst, scope.instructions.items),
1914 };
1668}1915}
16691916
1670fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.While) InnerError!*zir.Inst {1917fn whileExpr(
1918 mod: *Module,
1919 scope: *Scope,
1920 rl: ResultLoc,
1921 while_node: *ast.Node.While,
1922) InnerError!*zir.Inst {
1671 var cond_kind: CondKind = .bool;1923 var cond_kind: CondKind = .bool;
1672 if (while_node.payload) |_| cond_kind = .{ .optional = null };1924 if (while_node.payload) |_| cond_kind = .{ .optional = null };
1673 if (while_node.@"else") |else_node| {1925 if (while_node.@"else") |else_node| {
...@@ -1683,27 +1935,21 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -1683,27 +1935,21 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
1683 if (while_node.inline_token) |tok|1935 if (while_node.inline_token) |tok|
1684 return mod.failTok(scope, tok, "TODO inline while", .{});1936 return mod.failTok(scope, tok, "TODO inline while", .{});
16851937
1686 var expr_scope: Scope.GenZIR = .{1938 var loop_scope: Scope.GenZIR = .{
1687 .parent = scope,1939 .parent = scope,
1688 .decl = scope.ownerDecl().?,1940 .decl = scope.ownerDecl().?,
1689 .arena = scope.arena(),1941 .arena = scope.arena(),
1942 .force_comptime = scope.isComptime(),
1690 .instructions = .{},1943 .instructions = .{},
1691 };1944 };
1692 defer expr_scope.instructions.deinit(mod.gpa);1945 setBlockResultLoc(&loop_scope, rl);
1693
1694 var loop_scope: Scope.GenZIR = .{
1695 .parent = &expr_scope.base,
1696 .decl = expr_scope.decl,
1697 .arena = expr_scope.arena,
1698 .instructions = .{},
1699 .break_result_loc = rl,
1700 };
1701 defer loop_scope.instructions.deinit(mod.gpa);1946 defer loop_scope.instructions.deinit(mod.gpa);
17021947
1703 var continue_scope: Scope.GenZIR = .{1948 var continue_scope: Scope.GenZIR = .{
1704 .parent = &loop_scope.base,1949 .parent = &loop_scope.base,
1705 .decl = loop_scope.decl,1950 .decl = loop_scope.decl,
1706 .arena = loop_scope.arena,1951 .arena = loop_scope.arena,
1952 .force_comptime = loop_scope.force_comptime,
1707 .instructions = .{},1953 .instructions = .{},
1708 };1954 };
1709 defer continue_scope.instructions.deinit(mod.gpa);1955 defer continue_scope.instructions.deinit(mod.gpa);
...@@ -1731,11 +1977,21 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -1731,11 +1977,21 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
1731 if (while_node.continue_expr) |cont_expr| {1977 if (while_node.continue_expr) |cont_expr| {
1732 _ = try expr(mod, &loop_scope.base, .{ .ty = void_type }, cont_expr);1978 _ = try expr(mod, &loop_scope.base, .{ .ty = void_type }, cont_expr);
1733 }1979 }
1734 const loop = try addZIRInstLoop(mod, &expr_scope.base, while_src, .{1980 const loop = try scope.arena().create(zir.Inst.Loop);
1735 .instructions = try expr_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),1981 loop.* = .{
1736 });1982 .base = .{
1983 .tag = .loop,
1984 .src = while_src,
1985 },
1986 .positionals = .{
1987 .body = .{
1988 .instructions = try scope.arena().dupe(*zir.Inst, loop_scope.instructions.items),
1989 },
1990 },
1991 .kw_args = .{},
1992 };
1737 const while_block = try addZIRInstBlock(mod, scope, while_src, .block, .{1993 const while_block = try addZIRInstBlock(mod, scope, while_src, .block, .{
1738 .instructions = try expr_scope.arena.dupe(*zir.Inst, expr_scope.instructions.items),1994 .instructions = try scope.arena().dupe(*zir.Inst, &[1]*zir.Inst{&loop.base}),
1739 });1995 });
1740 loop_scope.break_block = while_block;1996 loop_scope.break_block = while_block;
1741 loop_scope.continue_block = cond_block;1997 loop_scope.continue_block = cond_block;
...@@ -1751,6 +2007,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -1751,6 +2007,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
1751 .parent = &continue_scope.base,2007 .parent = &continue_scope.base,
1752 .decl = continue_scope.decl,2008 .decl = continue_scope.decl,
1753 .arena = continue_scope.arena,2009 .arena = continue_scope.arena,
2010 .force_comptime = continue_scope.force_comptime,
1754 .instructions = .{},2011 .instructions = .{},
1755 };2012 };
1756 defer then_scope.instructions.deinit(mod.gpa);2013 defer then_scope.instructions.deinit(mod.gpa);
...@@ -1758,61 +2015,51 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -1758,61 +2015,51 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
1758 // declare payload to the then_scope2015 // declare payload to the then_scope
1759 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload);2016 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload);
17602017
1761 // Most result location types can be forwarded directly; however2018 loop_scope.break_count += 1;
1762 // if we need to write to a pointer which has an inferred type,2019 const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, while_node.body);
1763 // proper type inference requires peer type resolution on the while's
1764 // branches.
1765 const branch_rl: ResultLoc = switch (rl) {
1766 .discard, .none, .ty, .ptr, .ref => rl,
1767 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
1768 };
1769
1770 const then_result = try expr(mod, then_sub_scope, branch_rl, while_node.body);
1771 if (!then_result.tag.isNoReturn()) {
1772 _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{
1773 .block = cond_block,
1774 .operand = then_result,
1775 }, .{});
1776 }
1777 condbr.positionals.then_body = .{
1778 .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items),
1779 };
17802020
1781 var else_scope: Scope.GenZIR = .{2021 var else_scope: Scope.GenZIR = .{
1782 .parent = &continue_scope.base,2022 .parent = &continue_scope.base,
1783 .decl = continue_scope.decl,2023 .decl = continue_scope.decl,
1784 .arena = continue_scope.arena,2024 .arena = continue_scope.arena,
2025 .force_comptime = continue_scope.force_comptime,
1785 .instructions = .{},2026 .instructions = .{},
1786 };2027 };
1787 defer else_scope.instructions.deinit(mod.gpa);2028 defer else_scope.instructions.deinit(mod.gpa);
17882029
1789 if (while_node.@"else") |else_node| {2030 var else_src: usize = undefined;
1790 const else_src = tree.token_locs[else_node.body.lastToken()].start;2031 const else_result: ?*zir.Inst = if (while_node.@"else") |else_node| blk: {
2032 else_src = tree.token_locs[else_node.body.lastToken()].start;
1791 // declare payload to the then_scope2033 // declare payload to the then_scope
1792 const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload);2034 const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload);
17932035
1794 const else_result = try expr(mod, else_sub_scope, branch_rl, else_node.body);2036 loop_scope.break_count += 1;
1795 if (!else_result.tag.isNoReturn()) {2037 break :blk try expr(mod, else_sub_scope, loop_scope.break_result_loc, else_node.body);
1796 _ = try addZIRInst(mod, else_sub_scope, else_src, zir.Inst.Break, .{2038 } else blk: {
1797 .block = while_block,2039 else_src = tree.token_locs[while_node.lastToken()].start;
1798 .operand = else_result,2040 break :blk null;
1799 }, .{});
1800 }
1801 } else {
1802 const else_src = tree.token_locs[while_node.lastToken()].start;
1803 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{
1804 .block = while_block,
1805 }, .{});
1806 }
1807 condbr.positionals.else_body = .{
1808 .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
1809 };2041 };
1810 if (loop_scope.label) |some| {2042 if (loop_scope.label) |some| {
1811 if (!some.used) {2043 if (!some.used) {
1812 return mod.fail(scope, tree.token_locs[some.token].start, "unused while label", .{});2044 return mod.fail(scope, tree.token_locs[some.token].start, "unused while label", .{});
1813 }2045 }
1814 }2046 }
1815 return &while_block.base;2047 return finishThenElseBlock(
2048 mod,
2049 scope,
2050 rl,
2051 &loop_scope,
2052 &then_scope,
2053 &else_scope,
2054 &condbr.positionals.then_body,
2055 &condbr.positionals.else_body,
2056 then_src,
2057 else_src,
2058 then_result,
2059 else_result,
2060 while_block,
2061 cond_block,
2062 );
1816}2063}
18172064
1818fn forExpr(2065fn forExpr(
...@@ -1828,48 +2075,42 @@ fn forExpr(...@@ -1828,48 +2075,42 @@ fn forExpr(
1828 if (for_node.inline_token) |tok|2075 if (for_node.inline_token) |tok|
1829 return mod.failTok(scope, tok, "TODO inline for", .{});2076 return mod.failTok(scope, tok, "TODO inline for", .{});
18302077
1831 var for_scope: Scope.GenZIR = .{
1832 .parent = scope,
1833 .decl = scope.ownerDecl().?,
1834 .arena = scope.arena(),
1835 .instructions = .{},
1836 };
1837 defer for_scope.instructions.deinit(mod.gpa);
1838
1839 // setup variables and constants2078 // setup variables and constants
1840 const tree = scope.tree();2079 const tree = scope.tree();
1841 const for_src = tree.token_locs[for_node.for_token].start;2080 const for_src = tree.token_locs[for_node.for_token].start;
1842 const index_ptr = blk: {2081 const index_ptr = blk: {
1843 const usize_type = try addZIRInstConst(mod, &for_scope.base, for_src, .{2082 const usize_type = try addZIRInstConst(mod, scope, for_src, .{
1844 .ty = Type.initTag(.type),2083 .ty = Type.initTag(.type),
1845 .val = Value.initTag(.usize_type),2084 .val = Value.initTag(.usize_type),
1846 });2085 });
1847 const index_ptr = try addZIRUnOp(mod, &for_scope.base, for_src, .alloc, usize_type);2086 const index_ptr = try addZIRUnOp(mod, scope, for_src, .alloc, usize_type);
1848 // initialize to zero2087 // initialize to zero
1849 const zero = try addZIRInstConst(mod, &for_scope.base, for_src, .{2088 const zero = try addZIRInstConst(mod, scope, for_src, .{
1850 .ty = Type.initTag(.usize),2089 .ty = Type.initTag(.usize),
1851 .val = Value.initTag(.zero),2090 .val = Value.initTag(.zero),
1852 });2091 });
1853 _ = try addZIRBinOp(mod, &for_scope.base, for_src, .store, index_ptr, zero);2092 _ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero);
1854 break :blk index_ptr;2093 break :blk index_ptr;
1855 };2094 };
1856 const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr);2095 const array_ptr = try expr(mod, scope, .ref, for_node.array_expr);
1857 const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start;2096 const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start;
1858 const len = try addZIRUnOp(mod, &for_scope.base, cond_src, .indexable_ptr_len, array_ptr);2097 const len = try addZIRUnOp(mod, scope, cond_src, .indexable_ptr_len, array_ptr);
18592098
1860 var loop_scope: Scope.GenZIR = .{2099 var loop_scope: Scope.GenZIR = .{
1861 .parent = &for_scope.base,2100 .parent = scope,
1862 .decl = for_scope.decl,2101 .decl = scope.ownerDecl().?,
1863 .arena = for_scope.arena,2102 .arena = scope.arena(),
2103 .force_comptime = scope.isComptime(),
1864 .instructions = .{},2104 .instructions = .{},
1865 .break_result_loc = rl,
1866 };2105 };
2106 setBlockResultLoc(&loop_scope, rl);
1867 defer loop_scope.instructions.deinit(mod.gpa);2107 defer loop_scope.instructions.deinit(mod.gpa);
18682108
1869 var cond_scope: Scope.GenZIR = .{2109 var cond_scope: Scope.GenZIR = .{
1870 .parent = &loop_scope.base,2110 .parent = &loop_scope.base,
1871 .decl = loop_scope.decl,2111 .decl = loop_scope.decl,
1872 .arena = loop_scope.arena,2112 .arena = loop_scope.arena,
2113 .force_comptime = loop_scope.force_comptime,
1873 .instructions = .{},2114 .instructions = .{},
1874 };2115 };
1875 defer cond_scope.instructions.deinit(mod.gpa);2116 defer cond_scope.instructions.deinit(mod.gpa);
...@@ -1896,12 +2137,21 @@ fn forExpr(...@@ -1896,12 +2137,21 @@ fn forExpr(
1896 const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one);2137 const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one);
1897 _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one);2138 _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one);
18982139
1899 // looping stuff2140 const loop = try scope.arena().create(zir.Inst.Loop);
1900 const loop = try addZIRInstLoop(mod, &for_scope.base, for_src, .{2141 loop.* = .{
1901 .instructions = try for_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),2142 .base = .{
1902 });2143 .tag = .loop,
2144 .src = for_src,
2145 },
2146 .positionals = .{
2147 .body = .{
2148 .instructions = try scope.arena().dupe(*zir.Inst, loop_scope.instructions.items),
2149 },
2150 },
2151 .kw_args = .{},
2152 };
1903 const for_block = try addZIRInstBlock(mod, scope, for_src, .block, .{2153 const for_block = try addZIRInstBlock(mod, scope, for_src, .block, .{
1904 .instructions = try for_scope.arena.dupe(*zir.Inst, for_scope.instructions.items),2154 .instructions = try scope.arena().dupe(*zir.Inst, &[1]*zir.Inst{&loop.base}),
1905 });2155 });
1906 loop_scope.break_block = for_block;2156 loop_scope.break_block = for_block;
1907 loop_scope.continue_block = cond_block;2157 loop_scope.continue_block = cond_block;
...@@ -1918,19 +2168,11 @@ fn forExpr(...@@ -1918,19 +2168,11 @@ fn forExpr(
1918 .parent = &cond_scope.base,2168 .parent = &cond_scope.base,
1919 .decl = cond_scope.decl,2169 .decl = cond_scope.decl,
1920 .arena = cond_scope.arena,2170 .arena = cond_scope.arena,
2171 .force_comptime = cond_scope.force_comptime,
1921 .instructions = .{},2172 .instructions = .{},
1922 };2173 };
1923 defer then_scope.instructions.deinit(mod.gpa);2174 defer then_scope.instructions.deinit(mod.gpa);
19242175
1925 // Most result location types can be forwarded directly; however
1926 // if we need to write to a pointer which has an inferred type,
1927 // proper type inference requires peer type resolution on the while's
1928 // branches.
1929 const branch_rl: ResultLoc = switch (rl) {
1930 .discard, .none, .ty, .ptr, .ref => rl,
1931 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = for_block },
1932 };
1933
1934 var index_scope: Scope.LocalPtr = undefined;2176 var index_scope: Scope.LocalPtr = undefined;
1935 const then_sub_scope = blk: {2177 const then_sub_scope = blk: {
1936 const payload = for_node.payload.castTag(.PointerIndexPayload).?;2178 const payload = for_node.payload.castTag(.PointerIndexPayload).?;
...@@ -1959,319 +2201,49 @@ fn forExpr(...@@ -1959,319 +2201,49 @@ fn forExpr(
1959 break :blk &index_scope.base;2201 break :blk &index_scope.base;
1960 };2202 };
19612203
1962 const then_result = try expr(mod, then_sub_scope, branch_rl, for_node.body);2204 loop_scope.break_count += 1;
1963 if (!then_result.tag.isNoReturn()) {2205 const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_node.body);
1964 _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{
1965 .block = cond_block,
1966 .operand = then_result,
1967 }, .{});
1968 }
1969 condbr.positionals.then_body = .{
1970 .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items),
1971 };
19722206
1973 // else branch2207 // else branch
1974 var else_scope: Scope.GenZIR = .{2208 var else_scope: Scope.GenZIR = .{
1975 .parent = &cond_scope.base,2209 .parent = &cond_scope.base,
1976 .decl = cond_scope.decl,2210 .decl = cond_scope.decl,
1977 .arena = cond_scope.arena,2211 .arena = cond_scope.arena,
2212 .force_comptime = cond_scope.force_comptime,
1978 .instructions = .{},2213 .instructions = .{},
1979 };2214 };
1980 defer else_scope.instructions.deinit(mod.gpa);2215 defer else_scope.instructions.deinit(mod.gpa);
19812216
1982 if (for_node.@"else") |else_node| {2217 var else_src: usize = undefined;
1983 const else_src = tree.token_locs[else_node.body.lastToken()].start;2218 const else_result: ?*zir.Inst = if (for_node.@"else") |else_node| blk: {
1984 const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body);2219 else_src = tree.token_locs[else_node.body.lastToken()].start;
1985 if (!else_result.tag.isNoReturn()) {2220 loop_scope.break_count += 1;
1986 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{2221 break :blk try expr(mod, &else_scope.base, loop_scope.break_result_loc, else_node.body);
1987 .block = for_block,2222 } else blk: {
1988 .operand = else_result,2223 else_src = tree.token_locs[for_node.lastToken()].start;
1989 }, .{});2224 break :blk null;
1990 }
1991 } else {
1992 const else_src = tree.token_locs[for_node.lastToken()].start;
1993 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{
1994 .block = for_block,
1995 }, .{});
1996 }
1997 condbr.positionals.else_body = .{
1998 .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
1999 };2225 };
2000 if (loop_scope.label) |some| {2226 if (loop_scope.label) |some| {
2001 if (!some.used) {2227 if (!some.used) {
2002 return mod.fail(scope, tree.token_locs[some.token].start, "unused for label", .{});2228 return mod.fail(scope, tree.token_locs[some.token].start, "unused for label", .{});
2003 }2229 }
2004 }2230 }
2005 return &for_block.base;2231 return finishThenElseBlock(
2006}2232 mod,
20072233 scope,
2008fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp {2234 rl,
2009 var cur = node;2235 &loop_scope,
2010 while (true) {2236 &then_scope,
2011 switch (cur.tag) {2237 &else_scope,
2012 .Range => return @fieldParentPtr(ast.Node.SimpleInfixOp, "base", cur),2238 &condbr.positionals.then_body,
2013 .GroupedExpression => cur = @fieldParentPtr(ast.Node.GroupedExpression, "base", cur).expr,2239 &condbr.positionals.else_body,
2014 else => return null,2240 then_src,
2015 }2241 else_src,
2016 }2242 then_result,
2017}2243 else_result,
20182244 for_block,
2019fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node.Switch) InnerError!*zir.Inst {2245 cond_block,
2020 var block_scope: Scope.GenZIR = .{2246 );
2021 .parent = scope,
2022 .decl = scope.ownerDecl().?,
2023 .arena = scope.arena(),
2024 .instructions = .{},
2025 };
2026 defer block_scope.instructions.deinit(mod.gpa);
2027
2028 const tree = scope.tree();
2029 const switch_src = tree.token_locs[switch_node.switch_token].start;
2030 const target_ptr = try expr(mod, &block_scope.base, .ref, switch_node.expr);
2031 const target = try addZIRUnOp(mod, &block_scope.base, target_ptr.src, .deref, target_ptr);
2032 // Add the switch instruction here so that it comes before any range checks.
2033 const switch_inst = (try addZIRInst(mod, &block_scope.base, switch_src, zir.Inst.SwitchBr, .{
2034 .target_ptr = target_ptr,
2035 .cases = undefined, // populated below
2036 .items = &[_]*zir.Inst{}, // populated below
2037 .else_body = undefined, // populated below
2038 }, .{})).castTag(.switchbr).?;
2039
2040 var items = std.ArrayList(*zir.Inst).init(mod.gpa);
2041 defer items.deinit();
2042 var cases = std.ArrayList(zir.Inst.SwitchBr.Case).init(mod.gpa);
2043 defer cases.deinit();
2044
2045 // Add comptime block containing all prong items first,
2046 const item_block = try addZIRInstBlock(mod, scope, switch_src, .block_comptime_flat, .{
2047 .instructions = undefined, // populated below
2048 });
2049 // then add block containing the switch.
2050 const block = try addZIRInstBlock(mod, scope, switch_src, .block, .{
2051 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
2052 });
2053
2054 // Most result location types can be forwarded directly; however
2055 // if we need to write to a pointer which has an inferred type,
2056 // proper type inference requires peer type resolution on the switch case.
2057 const case_rl: ResultLoc = switch (rl) {
2058 .discard, .none, .ty, .ptr, .ref => rl,
2059 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
2060 };
2061
2062 var item_scope: Scope.GenZIR = .{
2063 .parent = scope,
2064 .decl = scope.ownerDecl().?,
2065 .arena = scope.arena(),
2066 .instructions = .{},
2067 };
2068 defer item_scope.instructions.deinit(mod.gpa);
2069
2070 var case_scope: Scope.GenZIR = .{
2071 .parent = scope,
2072 .decl = block_scope.decl,
2073 .arena = block_scope.arena,
2074 .instructions = .{},
2075 };
2076 defer case_scope.instructions.deinit(mod.gpa);
2077
2078 var else_scope: Scope.GenZIR = .{
2079 .parent = scope,
2080 .decl = block_scope.decl,
2081 .arena = block_scope.arena,
2082 .instructions = .{},
2083 };
2084 defer else_scope.instructions.deinit(mod.gpa);
2085
2086 // first we gather all the switch items and check else/'_' prongs
2087 var else_src: ?usize = null;
2088 var underscore_src: ?usize = null;
2089 var first_range: ?*zir.Inst = null;
2090 var special_case: ?*ast.Node.SwitchCase = null;
2091 for (switch_node.cases()) |uncasted_case| {
2092 const case = uncasted_case.castTag(.SwitchCase).?;
2093 const case_src = tree.token_locs[case.firstToken()].start;
2094 // reset without freeing to reduce allocations.
2095 case_scope.instructions.items.len = 0;
2096 assert(case.items_len != 0);
2097
2098 // Check for else/_ prong, those are handled last.
2099 if (case.items_len == 1 and case.items()[0].tag == .SwitchElse) {
2100 if (else_src) |src| {
2101 const msg = msg: {
2102 const msg = try mod.errMsg(
2103 scope,
2104 case_src,
2105 "multiple else prongs in switch expression",
2106 .{},
2107 );
2108 errdefer msg.destroy(mod.gpa);
2109 try mod.errNote(scope, src, msg, "previous else prong is here", .{});
2110 break :msg msg;
2111 };
2112 return mod.failWithOwnedErrorMsg(scope, msg);
2113 }
2114 else_src = case_src;
2115 special_case = case;
2116 continue;
2117 } else if (case.items_len == 1 and case.items()[0].tag == .Identifier and
2118 mem.eql(u8, tree.tokenSlice(case.items()[0].firstToken()), "_"))
2119 {
2120 if (underscore_src) |src| {
2121 const msg = msg: {
2122 const msg = try mod.errMsg(
2123 scope,
2124 case_src,
2125 "multiple '_' prongs in switch expression",
2126 .{},
2127 );
2128 errdefer msg.destroy(mod.gpa);
2129 try mod.errNote(scope, src, msg, "previous '_' prong is here", .{});
2130 break :msg msg;
2131 };
2132 return mod.failWithOwnedErrorMsg(scope, msg);
2133 }
2134 underscore_src = case_src;
2135 special_case = case;
2136 continue;
2137 }
2138
2139 if (else_src) |some_else| {
2140 if (underscore_src) |some_underscore| {
2141 const msg = msg: {
2142 const msg = try mod.errMsg(
2143 scope,
2144 switch_src,
2145 "else and '_' prong in switch expression",
2146 .{},
2147 );
2148 errdefer msg.destroy(mod.gpa);
2149 try mod.errNote(scope, some_else, msg, "else prong is here", .{});
2150 try mod.errNote(scope, some_underscore, msg, "'_' prong is here", .{});
2151 break :msg msg;
2152 };
2153 return mod.failWithOwnedErrorMsg(scope, msg);
2154 }
2155 }
2156
2157 // If this is a simple one item prong then it is handled by the switchbr.
2158 if (case.items_len == 1 and getRangeNode(case.items()[0]) == null) {
2159 const item = try expr(mod, &item_scope.base, .none, case.items()[0]);
2160 try items.append(item);
2161 try switchCaseExpr(mod, &case_scope.base, case_rl, block, case);
2162
2163 try cases.append(.{
2164 .item = item,
2165 .body = .{ .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items) },
2166 });
2167 continue;
2168 }
2169
2170 // TODO if the case has few items and no ranges it might be better
2171 // to just handle them as switch prongs.
2172
2173 // Check if the target matches any of the items.
2174 // 1, 2, 3..6 will result in
2175 // target == 1 or target == 2 or (target >= 3 and target <= 6)
2176 var any_ok: ?*zir.Inst = null;
2177 for (case.items()) |item| {
2178 if (getRangeNode(item)) |range| {
2179 const start = try expr(mod, &item_scope.base, .none, range.lhs);
2180 const end = try expr(mod, &item_scope.base, .none, range.rhs);
2181 const range_src = tree.token_locs[range.op_token].start;
2182 const range_inst = try addZIRBinOp(mod, &item_scope.base, range_src, .switch_range, start, end);
2183 try items.append(range_inst);
2184 if (first_range == null) first_range = range_inst;
2185
2186 // target >= start and target <= end
2187 const range_start_ok = try addZIRBinOp(mod, &else_scope.base, range_src, .cmp_gte, target, start);
2188 const range_end_ok = try addZIRBinOp(mod, &else_scope.base, range_src, .cmp_lte, target, end);
2189 const range_ok = try addZIRBinOp(mod, &else_scope.base, range_src, .booland, range_start_ok, range_end_ok);
2190
2191 if (any_ok) |some| {
2192 any_ok = try addZIRBinOp(mod, &else_scope.base, range_src, .boolor, some, range_ok);
2193 } else {
2194 any_ok = range_ok;
2195 }
2196 continue;
2197 }
2198
2199 const item_inst = try expr(mod, &item_scope.base, .none, item);
2200 try items.append(item_inst);
2201 const cpm_ok = try addZIRBinOp(mod, &else_scope.base, item_inst.src, .cmp_eq, target, item_inst);
2202
2203 if (any_ok) |some| {
2204 any_ok = try addZIRBinOp(mod, &else_scope.base, item_inst.src, .boolor, some, cpm_ok);
2205 } else {
2206 any_ok = cpm_ok;
2207 }
2208 }
2209
2210 const condbr = try addZIRInstSpecial(mod, &case_scope.base, case_src, zir.Inst.CondBr, .{
2211 .condition = any_ok.?,
2212 .then_body = undefined, // populated below
2213 .else_body = undefined, // populated below
2214 }, .{});
2215 const cond_block = try addZIRInstBlock(mod, &else_scope.base, case_src, .block, .{
2216 .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items),
2217 });
2218
2219 // reset cond_scope for then_body
2220 case_scope.instructions.items.len = 0;
2221 try switchCaseExpr(mod, &case_scope.base, case_rl, block, case);
2222 condbr.positionals.then_body = .{
2223 .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items),
2224 };
2225
2226 // reset cond_scope for else_body
2227 case_scope.instructions.items.len = 0;
2228 _ = try addZIRInst(mod, &case_scope.base, case_src, zir.Inst.BreakVoid, .{
2229 .block = cond_block,
2230 }, .{});
2231 condbr.positionals.else_body = .{
2232 .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items),
2233 };
2234 }
2235
2236 // Generate else block or a break last to finish the block.
2237 if (special_case) |case| {
2238 try switchCaseExpr(mod, &else_scope.base, case_rl, block, case);
2239 } else {
2240 // Not handling all possible cases is a compile error.
2241 _ = try addZIRNoOp(mod, &else_scope.base, switch_src, .unreach_nocheck);
2242 }
2243
2244 // All items have been generated, add the instructions to the comptime block.
2245 item_block.positionals.body = .{
2246 .instructions = try block_scope.arena.dupe(*zir.Inst, item_scope.instructions.items),
2247 };
2248
2249 // Actually populate switch instruction values.
2250 if (else_src != null) switch_inst.kw_args.special_prong = .@"else";
2251 if (underscore_src != null) switch_inst.kw_args.special_prong = .underscore;
2252 switch_inst.positionals.cases = try block_scope.arena.dupe(zir.Inst.SwitchBr.Case, cases.items);
2253 switch_inst.positionals.items = try block_scope.arena.dupe(*zir.Inst, items.items);
2254 switch_inst.kw_args.range = first_range;
2255 switch_inst.positionals.else_body = .{
2256 .instructions = try block_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
2257 };
2258 return &block.base;
2259}
2260
2261fn switchCaseExpr(mod: *Module, scope: *Scope, rl: ResultLoc, block: *zir.Inst.Block, case: *ast.Node.SwitchCase) !void {
2262 const tree = scope.tree();
2263 const case_src = tree.token_locs[case.firstToken()].start;
2264 if (case.payload != null) {
2265 return mod.fail(scope, case_src, "TODO switch case payload capture", .{});
2266 }
2267
2268 const case_body = try expr(mod, scope, rl, case.expr);
2269 if (!case_body.tag.isNoReturn()) {
2270 _ = try addZIRInst(mod, scope, case_src, zir.Inst.Break, .{
2271 .block = block,
2272 .operand = case_body,
2273 }, .{});
2274 }
2275}2247}
22762248
2277fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst {2249fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst {
...@@ -2288,7 +2260,7 @@ fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerE...@@ -2288,7 +2260,7 @@ fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerE
2288 return addZIRUnOp(mod, scope, src, .@"return", operand);2260 return addZIRUnOp(mod, scope, src, .@"return", operand);
2289 }2261 }
2290 } else {2262 } else {
2291 return addZIRNoOp(mod, scope, src, .returnvoid);2263 return addZIRNoOp(mod, scope, src, .return_void);
2292 }2264 }
2293}2265}
22942266
...@@ -2305,7 +2277,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -2305,7 +2277,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
23052277
2306 if (getSimplePrimitiveValue(ident_name)) |typed_value| {2278 if (getSimplePrimitiveValue(ident_name)) |typed_value| {
2307 const result = try addZIRInstConst(mod, scope, src, typed_value);2279 const result = try addZIRInstConst(mod, scope, src, typed_value);
2308 return rlWrap(mod, scope, rl, result);2280 return rvalue(mod, scope, rl, result);
2309 }2281 }
23102282
2311 if (ident_name.len >= 2) integer: {2283 if (ident_name.len >= 2) integer: {
...@@ -2327,7 +2299,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -2327,7 +2299,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
2327 32 => if (is_signed) Value.initTag(.i32_type) else Value.initTag(.u32_type),2299 32 => if (is_signed) Value.initTag(.i32_type) else Value.initTag(.u32_type),
2328 64 => if (is_signed) Value.initTag(.i64_type) else Value.initTag(.u64_type),2300 64 => if (is_signed) Value.initTag(.i64_type) else Value.initTag(.u64_type),
2329 else => {2301 else => {
2330 return rlWrap(mod, scope, rl, try addZIRInstConst(mod, scope, src, .{2302 return rvalue(mod, scope, rl, try addZIRInstConst(mod, scope, src, .{
2331 .ty = Type.initTag(.type),2303 .ty = Type.initTag(.type),
2332 .val = try Value.Tag.int_type.create(scope.arena(), .{2304 .val = try Value.Tag.int_type.create(scope.arena(), .{
2333 .signed = is_signed,2305 .signed = is_signed,
...@@ -2340,7 +2312,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -2340,7 +2312,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
2340 .ty = Type.initTag(.type),2312 .ty = Type.initTag(.type),
2341 .val = val,2313 .val = val,
2342 });2314 });
2343 return rlWrap(mod, scope, rl, result);2315 return rvalue(mod, scope, rl, result);
2344 }2316 }
2345 }2317 }
23462318
...@@ -2351,7 +2323,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -2351,7 +2323,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
2351 .local_val => {2323 .local_val => {
2352 const local_val = s.cast(Scope.LocalVal).?;2324 const local_val = s.cast(Scope.LocalVal).?;
2353 if (mem.eql(u8, local_val.name, ident_name)) {2325 if (mem.eql(u8, local_val.name, ident_name)) {
2354 return rlWrap(mod, scope, rl, local_val.inst);2326 return rvalue(mod, scope, rl, local_val.inst);
2355 }2327 }
2356 s = local_val.parent;2328 s = local_val.parent;
2357 },2329 },
...@@ -2360,7 +2332,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -2360,7 +2332,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
2360 if (mem.eql(u8, local_ptr.name, ident_name)) {2332 if (mem.eql(u8, local_ptr.name, ident_name)) {
2361 if (rl == .ref) return local_ptr.ptr;2333 if (rl == .ref) return local_ptr.ptr;
2362 const loaded = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);2334 const loaded = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);
2363 return rlWrap(mod, scope, rl, loaded);2335 return rvalue(mod, scope, rl, loaded);
2364 }2336 }
2365 s = local_ptr.parent;2337 s = local_ptr.parent;
2366 },2338 },
...@@ -2373,7 +2345,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -2373,7 +2345,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
2373 if (rl == .ref) {2345 if (rl == .ref) {
2374 return addZIRInst(mod, scope, src, zir.Inst.DeclRef, .{ .decl = decl }, .{});2346 return addZIRInst(mod, scope, src, zir.Inst.DeclRef, .{ .decl = decl }, .{});
2375 } else {2347 } else {
2376 return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclVal, .{2348 return rvalue(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclVal, .{
2377 .decl = decl,2349 .decl = decl,
2378 }, .{}));2350 }, .{}));
2379 }2351 }
...@@ -2590,7 +2562,7 @@ fn simpleCast(...@@ -2590,7 +2562,7 @@ fn simpleCast(
2590 const dest_type = try typeExpr(mod, scope, params[0]);2562 const dest_type = try typeExpr(mod, scope, params[0]);
2591 const rhs = try expr(mod, scope, .none, params[1]);2563 const rhs = try expr(mod, scope, .none, params[1]);
2592 const result = try addZIRBinOp(mod, scope, src, inst_tag, dest_type, rhs);2564 const result = try addZIRBinOp(mod, scope, src, inst_tag, dest_type, rhs);
2593 return rlWrap(mod, scope, rl, result);2565 return rvalue(mod, scope, rl, result);
2594}2566}
25952567
2596fn ptrToInt(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {2568fn ptrToInt(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
...@@ -2601,31 +2573,30 @@ fn ptrToInt(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError...@@ -2601,31 +2573,30 @@ fn ptrToInt(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError
2601 return addZIRUnOp(mod, scope, src, .ptrtoint, operand);2573 return addZIRUnOp(mod, scope, src, .ptrtoint, operand);
2602}2574}
26032575
2604fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {2576fn as(
2577 mod: *Module,
2578 scope: *Scope,
2579 rl: ResultLoc,
2580 call: *ast.Node.BuiltinCall,
2581) InnerError!*zir.Inst {
2605 try ensureBuiltinParamCount(mod, scope, call, 2);2582 try ensureBuiltinParamCount(mod, scope, call, 2);
2606 const tree = scope.tree();2583 const tree = scope.tree();
2607 const src = tree.token_locs[call.builtin_token].start;2584 const src = tree.token_locs[call.builtin_token].start;
2608 const params = call.params();2585 const params = call.params();
2609 const dest_type = try typeExpr(mod, scope, params[0]);2586 const dest_type = try typeExpr(mod, scope, params[0]);
2610 switch (rl) {2587 switch (rl) {
2611 .none => return try expr(mod, scope, .{ .ty = dest_type }, params[1]),2588 .none, .discard, .ref, .ty => {
2612 .discard => {
2613 const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
2614 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
2615 return result;
2616 },
2617 .ref => {
2618 const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
2619 return addZIRUnOp(mod, scope, result.src, .ref, result);
2620 },
2621 .ty => |result_ty| {
2622 const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);2589 const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
2623 return addZIRBinOp(mod, scope, src, .as, result_ty, result);2590 return rvalue(mod, scope, rl, result);
2624 },2591 },
2592
2625 .ptr => |result_ptr| {2593 .ptr => |result_ptr| {
2626 const casted_result_ptr = try addZIRBinOp(mod, scope, src, .coerce_result_ptr, dest_type, result_ptr);2594 return asRlPtr(mod, scope, rl, src, result_ptr, params[1], dest_type);
2627 return expr(mod, scope, .{ .ptr = casted_result_ptr }, params[1]);2595 },
2596 .block_ptr => |block_scope| {
2597 return asRlPtr(mod, scope, rl, src, block_scope.rl_ptr.?, params[1], dest_type);
2628 },2598 },
2599
2629 .bitcasted_ptr => |bitcasted_ptr| {2600 .bitcasted_ptr => |bitcasted_ptr| {
2630 // TODO here we should be able to resolve the inference; we now have a type for the result.2601 // TODO here we should be able to resolve the inference; we now have a type for the result.
2631 return mod.failTok(scope, call.builtin_token, "TODO implement @as with result location @bitCast", .{});2602 return mod.failTok(scope, call.builtin_token, "TODO implement @as with result location @bitCast", .{});
...@@ -2634,13 +2605,50 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I...@@ -2634,13 +2605,50 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I
2634 // TODO here we should be able to resolve the inference; we now have a type for the result.2605 // TODO here we should be able to resolve the inference; we now have a type for the result.
2635 return mod.failTok(scope, call.builtin_token, "TODO implement @as with inferred-type result location pointer", .{});2606 return mod.failTok(scope, call.builtin_token, "TODO implement @as with inferred-type result location pointer", .{});
2636 },2607 },
2637 .block_ptr => |block_ptr| {2608 }
2638 const casted_block_ptr = try addZIRInst(mod, scope, src, zir.Inst.CoerceResultBlockPtr, .{2609}
2639 .dest_type = dest_type,2610
2640 .block = block_ptr,2611fn asRlPtr(
2641 }, .{});2612 mod: *Module,
2642 return expr(mod, scope, .{ .ptr = casted_block_ptr }, params[1]);2613 scope: *Scope,
2643 },2614 rl: ResultLoc,
2615 src: usize,
2616 result_ptr: *zir.Inst,
2617 operand_node: *ast.Node,
2618 dest_type: *zir.Inst,
2619) InnerError!*zir.Inst {
2620 // Detect whether this expr() call goes into rvalue() to store the result into the
2621 // result location. If it does, elide the coerce_result_ptr instruction
2622 // as well as the store instruction, instead passing the result as an rvalue.
2623 var as_scope: Scope.GenZIR = .{
2624 .parent = scope,
2625 .decl = scope.ownerDecl().?,
2626 .arena = scope.arena(),
2627 .force_comptime = scope.isComptime(),
2628 .instructions = .{},
2629 };
2630 defer as_scope.instructions.deinit(mod.gpa);
2631
2632 as_scope.rl_ptr = try addZIRBinOp(mod, &as_scope.base, src, .coerce_result_ptr, dest_type, result_ptr);
2633 const result = try expr(mod, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node);
2634 const parent_zir = &scope.getGenZIR().instructions;
2635 if (as_scope.rvalue_rl_count == 1) {
2636 // Busted! This expression didn't actually need a pointer.
2637 const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2;
2638 try parent_zir.ensureCapacity(mod.gpa, expected_len);
2639 for (as_scope.instructions.items) |src_inst| {
2640 if (src_inst == as_scope.rl_ptr.?) continue;
2641 if (src_inst.castTag(.store_to_block_ptr)) |store| {
2642 if (store.positionals.lhs == as_scope.rl_ptr.?) continue;
2643 }
2644 parent_zir.appendAssumeCapacity(src_inst);
2645 }
2646 assert(parent_zir.items.len == expected_len);
2647 const casted_result = try addZIRBinOp(mod, scope, dest_type.src, .as, dest_type, result);
2648 return rvalue(mod, scope, rl, casted_result);
2649 } else {
2650 try parent_zir.appendSlice(mod.gpa, as_scope.instructions.items);
2651 return result;
2644 }2652 }
2645}2653}
26462654
...@@ -2703,7 +2711,7 @@ fn compileError(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerE...@@ -2703,7 +2711,7 @@ fn compileError(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerE
2703 const src = tree.token_locs[call.builtin_token].start;2711 const src = tree.token_locs[call.builtin_token].start;
2704 const params = call.params();2712 const params = call.params();
2705 const target = try expr(mod, scope, .none, params[0]);2713 const target = try expr(mod, scope, .none, params[0]);
2706 return addZIRUnOp(mod, scope, src, .compileerror, target);2714 return addZIRUnOp(mod, scope, src, .compile_error, target);
2707}2715}
27082716
2709fn setEvalBranchQuota(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {2717fn setEvalBranchQuota(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
...@@ -2728,12 +2736,12 @@ fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCal...@@ -2728,12 +2736,12 @@ fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCal
2728 return mod.failTok(scope, call.builtin_token, "expected at least 1 argument, found 0", .{});2736 return mod.failTok(scope, call.builtin_token, "expected at least 1 argument, found 0", .{});
2729 }2737 }
2730 if (params.len == 1) {2738 if (params.len == 1) {
2731 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .typeof, try expr(mod, scope, .none, params[0])));2739 return rvalue(mod, scope, rl, try addZIRUnOp(mod, scope, src, .typeof, try expr(mod, scope, .none, params[0])));
2732 }2740 }
2733 var items = try arena.alloc(*zir.Inst, params.len);2741 var items = try arena.alloc(*zir.Inst, params.len);
2734 for (params) |param, param_i|2742 for (params) |param, param_i|
2735 items[param_i] = try expr(mod, scope, .none, param);2743 items[param_i] = try expr(mod, scope, .none, param);
2736 return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.TypeOfPeer, .{ .items = items }, .{}));2744 return rvalue(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.TypeOfPeer, .{ .items = items }, .{}));
2737}2745}
2738fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {2746fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
2739 const tree = scope.tree();2747 const tree = scope.tree();
...@@ -2756,7 +2764,7 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built...@@ -2756,7 +2764,7 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built
2756 // Also, some builtins have a variable number of parameters.2764 // Also, some builtins have a variable number of parameters.
27572765
2758 if (mem.eql(u8, builtin_name, "@ptrToInt")) {2766 if (mem.eql(u8, builtin_name, "@ptrToInt")) {
2759 return rlWrap(mod, scope, rl, try ptrToInt(mod, scope, call));2767 return rvalue(mod, scope, rl, try ptrToInt(mod, scope, call));
2760 } else if (mem.eql(u8, builtin_name, "@as")) {2768 } else if (mem.eql(u8, builtin_name, "@as")) {
2761 return as(mod, scope, rl, call);2769 return as(mod, scope, rl, call);
2762 } else if (mem.eql(u8, builtin_name, "@floatCast")) {2770 } else if (mem.eql(u8, builtin_name, "@floatCast")) {
...@@ -2769,9 +2777,9 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built...@@ -2769,9 +2777,9 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built
2769 return typeOf(mod, scope, rl, call);2777 return typeOf(mod, scope, rl, call);
2770 } else if (mem.eql(u8, builtin_name, "@breakpoint")) {2778 } else if (mem.eql(u8, builtin_name, "@breakpoint")) {
2771 const src = tree.token_locs[call.builtin_token].start;2779 const src = tree.token_locs[call.builtin_token].start;
2772 return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint));2780 return rvalue(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint));
2773 } else if (mem.eql(u8, builtin_name, "@import")) {2781 } else if (mem.eql(u8, builtin_name, "@import")) {
2774 return rlWrap(mod, scope, rl, try import(mod, scope, call));2782 return rvalue(mod, scope, rl, try import(mod, scope, call));
2775 } else if (mem.eql(u8, builtin_name, "@compileError")) {2783 } else if (mem.eql(u8, builtin_name, "@compileError")) {
2776 return compileError(mod, scope, call);2784 return compileError(mod, scope, call);
2777 } else if (mem.eql(u8, builtin_name, "@setEvalBranchQuota")) {2785 } else if (mem.eql(u8, builtin_name, "@setEvalBranchQuota")) {
...@@ -2806,13 +2814,13 @@ fn callExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Call) In...@@ -2806,13 +2814,13 @@ fn callExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Call) In
2806 .args = args,2814 .args = args,
2807 }, .{});2815 }, .{});
2808 // TODO function call with result location2816 // TODO function call with result location
2809 return rlWrap(mod, scope, rl, result);2817 return rvalue(mod, scope, rl, result);
2810}2818}
28112819
2812fn unreach(mod: *Module, scope: *Scope, unreach_node: *ast.Node.OneToken) InnerError!*zir.Inst {2820fn unreach(mod: *Module, scope: *Scope, unreach_node: *ast.Node.OneToken) InnerError!*zir.Inst {
2813 const tree = scope.tree();2821 const tree = scope.tree();
2814 const src = tree.token_locs[unreach_node.token].start;2822 const src = tree.token_locs[unreach_node.token].start;
2815 return addZIRNoOp(mod, scope, src, .@"unreachable");2823 return addZIRNoOp(mod, scope, src, .unreachable_safe);
2816}2824}
28172825
2818fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {2826fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {
...@@ -3099,7 +3107,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {...@@ -3099,7 +3107,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
3099/// result locations must call this function on their result.3107/// result locations must call this function on their result.
3100/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.3108/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
3101/// If the `ResultLoc` is `ty`, it will coerce the result to the type.3109/// If the `ResultLoc` is `ty`, it will coerce the result to the type.
3102fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerError!*zir.Inst {3110fn rvalue(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerError!*zir.Inst {
3103 switch (rl) {3111 switch (rl) {
3104 .none => return result,3112 .none => return result,
3105 .discard => {3113 .discard => {
...@@ -3113,42 +3121,97 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr...@@ -3113,42 +3121,97 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
3113 },3121 },
3114 .ty => |ty_inst| return addZIRBinOp(mod, scope, result.src, .as, ty_inst, result),3122 .ty => |ty_inst| return addZIRBinOp(mod, scope, result.src, .as, ty_inst, result),
3115 .ptr => |ptr_inst| {3123 .ptr => |ptr_inst| {
3116 const casted_result = try addZIRInst(mod, scope, result.src, zir.Inst.CoerceToPtrElem, .{3124 _ = try addZIRBinOp(mod, scope, result.src, .store, ptr_inst, result);
3117 .ptr = ptr_inst,3125 return result;
3118 .value = result,
3119 }, .{});
3120 _ = try addZIRBinOp(mod, scope, result.src, .store, ptr_inst, casted_result);
3121 return casted_result;
3122 },3126 },
3123 .bitcasted_ptr => |bitcasted_ptr| {3127 .bitcasted_ptr => |bitcasted_ptr| {
3124 return mod.fail(scope, result.src, "TODO implement rlWrap .bitcasted_ptr", .{});3128 return mod.fail(scope, result.src, "TODO implement rvalue .bitcasted_ptr", .{});
3125 },3129 },
3126 .inferred_ptr => |alloc| {3130 .inferred_ptr => |alloc| {
3127 _ = try addZIRBinOp(mod, scope, result.src, .store_to_inferred_ptr, &alloc.base, result);3131 _ = try addZIRBinOp(mod, scope, result.src, .store_to_inferred_ptr, &alloc.base, result);
3128 return result;3132 return result;
3129 },3133 },
3130 .block_ptr => |block_ptr| {3134 .block_ptr => |block_scope| {
3131 return mod.fail(scope, result.src, "TODO implement rlWrap .block_ptr", .{});3135 block_scope.rvalue_rl_count += 1;
3136 _ = try addZIRBinOp(mod, scope, result.src, .store_to_block_ptr, block_scope.rl_ptr.?, result);
3137 return result;
3132 },3138 },
3133 }3139 }
3134}3140}
31353141
3136fn rlWrapVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, result: void) InnerError!*zir.Inst {3142fn rvalueVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, result: void) InnerError!*zir.Inst {
3137 const src = scope.tree().token_locs[node.firstToken()].start;3143 const src = scope.tree().token_locs[node.firstToken()].start;
3138 const void_inst = try addZIRInstConst(mod, scope, src, .{3144 const void_inst = try addZIRInstConst(mod, scope, src, .{
3139 .ty = Type.initTag(.void),3145 .ty = Type.initTag(.void),
3140 .val = Value.initTag(.void_value),3146 .val = Value.initTag(.void_value),
3141 });3147 });
3142 return rlWrap(mod, scope, rl, void_inst);3148 return rvalue(mod, scope, rl, void_inst);
3149}
3150
3151fn rlStrategy(rl: ResultLoc, block_scope: *Scope.GenZIR) ResultLoc.Strategy {
3152 var elide_store_to_block_ptr_instructions = false;
3153 switch (rl) {
3154 // In this branch there will not be any store_to_block_ptr instructions.
3155 .discard, .none, .ty, .ref => return .{
3156 .tag = .break_operand,
3157 .elide_store_to_block_ptr_instructions = false,
3158 },
3159 // The pointer got passed through to the sub-expressions, so we will use
3160 // break_void here.
3161 // In this branch there will not be any store_to_block_ptr instructions.
3162 .ptr => return .{
3163 .tag = .break_void,
3164 .elide_store_to_block_ptr_instructions = false,
3165 },
3166 .inferred_ptr, .bitcasted_ptr, .block_ptr => {
3167 if (block_scope.rvalue_rl_count == block_scope.break_count) {
3168 // Neither prong of the if consumed the result location, so we can
3169 // use break instructions to create an rvalue.
3170 return .{
3171 .tag = .break_operand,
3172 .elide_store_to_block_ptr_instructions = true,
3173 };
3174 } else {
3175 // Allow the store_to_block_ptr instructions to remain so that
3176 // semantic analysis can turn them into bitcasts.
3177 return .{
3178 .tag = .break_void,
3179 .elide_store_to_block_ptr_instructions = false,
3180 };
3181 }
3182 },
3183 }
3143}3184}
31443185
3145/// TODO go over all the callsites and see where we can introduce "by-value" ZIR instructions3186fn setBlockResultLoc(block_scope: *Scope.GenZIR, parent_rl: ResultLoc) void {
3146/// to save ZIR memory. For example, see DeclVal vs DeclRef.3187 // Depending on whether the result location is a pointer or value, different
3147/// Do not add additional callsites to this function.3188 // ZIR needs to be generated. In the former case we rely on storing to the
3148fn rlWrapPtr(mod: *Module, scope: *Scope, rl: ResultLoc, ptr: *zir.Inst) InnerError!*zir.Inst {3189 // pointer to communicate the result, and use breakvoid; in the latter case
3149 if (rl == .ref) return ptr;3190 // the block break instructions will have the result values.
3191 // One more complication: when the result location is a pointer, we detect
3192 // the scenario where the result location is not consumed. In this case
3193 // we emit ZIR for the block break instructions to have the result values,
3194 // and then rvalue() on that to pass the value to the result location.
3195 switch (parent_rl) {
3196 .discard, .none, .ty, .ptr, .ref => {
3197 block_scope.break_result_loc = parent_rl;
3198 },
3199
3200 .inferred_ptr => |ptr| {
3201 block_scope.rl_ptr = &ptr.base;
3202 block_scope.break_result_loc = .{ .block_ptr = block_scope };
3203 },
3204
3205 .bitcasted_ptr => |ptr| {
3206 block_scope.rl_ptr = &ptr.base;
3207 block_scope.break_result_loc = .{ .block_ptr = block_scope };
3208 },
31503209
3151 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, ptr.src, .deref, ptr));3210 .block_ptr => |parent_block_scope| {
3211 block_scope.rl_ptr = parent_block_scope.rl_ptr.?;
3212 block_scope.break_result_loc = .{ .block_ptr = block_scope };
3213 },
3214 }
3152}3215}
31533216
3154pub fn addZirInstTag(3217pub fn addZirInstTag(
src/codegen.zig+34-23
...@@ -840,14 +840,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -840,14 +840,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
840 .arg => return self.genArg(inst.castTag(.arg).?),840 .arg => return self.genArg(inst.castTag(.arg).?),
841 .assembly => return self.genAsm(inst.castTag(.assembly).?),841 .assembly => return self.genAsm(inst.castTag(.assembly).?),
842 .bitcast => return self.genBitCast(inst.castTag(.bitcast).?),842 .bitcast => return self.genBitCast(inst.castTag(.bitcast).?),
843 .bitand => return self.genBitAnd(inst.castTag(.bitand).?),843 .bit_and => return self.genBitAnd(inst.castTag(.bit_and).?),
844 .bitor => return self.genBitOr(inst.castTag(.bitor).?),844 .bit_or => return self.genBitOr(inst.castTag(.bit_or).?),
845 .block => return self.genBlock(inst.castTag(.block).?),845 .block => return self.genBlock(inst.castTag(.block).?),
846 .br => return self.genBr(inst.castTag(.br).?),846 .br => return self.genBr(inst.castTag(.br).?),
847 .br_block_flat => return self.genBrBlockFlat(inst.castTag(.br_block_flat).?),
847 .breakpoint => return self.genBreakpoint(inst.src),848 .breakpoint => return self.genBreakpoint(inst.src),
848 .brvoid => return self.genBrVoid(inst.castTag(.brvoid).?),849 .br_void => return self.genBrVoid(inst.castTag(.br_void).?),
849 .booland => return self.genBoolOp(inst.castTag(.booland).?),850 .bool_and => return self.genBoolOp(inst.castTag(.bool_and).?),
850 .boolor => return self.genBoolOp(inst.castTag(.boolor).?),851 .bool_or => return self.genBoolOp(inst.castTag(.bool_or).?),
851 .call => return self.genCall(inst.castTag(.call).?),852 .call => return self.genCall(inst.castTag(.call).?),
852 .cmp_lt => return self.genCmp(inst.castTag(.cmp_lt).?, .lt),853 .cmp_lt => return self.genCmp(inst.castTag(.cmp_lt).?, .lt),
853 .cmp_lte => return self.genCmp(inst.castTag(.cmp_lte).?, .lte),854 .cmp_lte => return self.genCmp(inst.castTag(.cmp_lte).?, .lte),
...@@ -1097,7 +1098,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1097,7 +1098,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1097 if (inst.base.isUnused())1098 if (inst.base.isUnused())
1098 return MCValue.dead;1099 return MCValue.dead;
1099 switch (arch) {1100 switch (arch) {
1100 .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .bitand),1101 .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .bit_and),
1101 else => return self.fail(inst.base.src, "TODO implement bitwise and for {}", .{self.target.cpu.arch}),1102 else => return self.fail(inst.base.src, "TODO implement bitwise and for {}", .{self.target.cpu.arch}),
1102 }1103 }
1103 }1104 }
...@@ -1107,7 +1108,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1107,7 +1108,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1107 if (inst.base.isUnused())1108 if (inst.base.isUnused())
1108 return MCValue.dead;1109 return MCValue.dead;
1109 switch (arch) {1110 switch (arch) {
1110 .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .bitor),1111 .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .bit_or),
1111 else => return self.fail(inst.base.src, "TODO implement bitwise or for {}", .{self.target.cpu.arch}),1112 else => return self.fail(inst.base.src, "TODO implement bitwise or for {}", .{self.target.cpu.arch}),
1112 }1113 }
1113 }1114 }
...@@ -1371,10 +1372,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1371,10 +1372,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1371 writeInt(u32, try self.code.addManyAsArray(4), Instruction.rsb(.al, dst_reg, dst_reg, operand).toU32());1372 writeInt(u32, try self.code.addManyAsArray(4), Instruction.rsb(.al, dst_reg, dst_reg, operand).toU32());
1372 }1373 }
1373 },1374 },
1374 .booland, .bitand => {1375 .bool_and, .bit_and => {
1375 writeInt(u32, try self.code.addManyAsArray(4), Instruction.@"and"(.al, dst_reg, dst_reg, operand).toU32());1376 writeInt(u32, try self.code.addManyAsArray(4), Instruction.@"and"(.al, dst_reg, dst_reg, operand).toU32());
1376 },1377 },
1377 .boolor, .bitor => {1378 .bool_or, .bit_or => {
1378 writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, dst_reg, dst_reg, operand).toU32());1379 writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, dst_reg, dst_reg, operand).toU32());
1379 },1380 },
1380 .not, .xor => {1381 .not, .xor => {
...@@ -2441,17 +2442,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2441,17 +2442,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2441 }2442 }
2442 }2443 }
24432444
2445 fn genBrBlockFlat(self: *Self, inst: *ir.Inst.BrBlockFlat) !MCValue {
2446 try self.genBody(inst.body);
2447 const last = inst.body.instructions[inst.body.instructions.len - 1];
2448 return self.br(inst.base.src, inst.block, last);
2449 }
2450
2444 fn genBr(self: *Self, inst: *ir.Inst.Br) !MCValue {2451 fn genBr(self: *Self, inst: *ir.Inst.Br) !MCValue {
2445 if (inst.operand.ty.hasCodeGenBits()) {2452 return self.br(inst.base.src, inst.block, inst.operand);
2446 const operand = try self.resolveInst(inst.operand);
2447 const block_mcv = @bitCast(MCValue, inst.block.codegen.mcv);
2448 if (block_mcv == .none) {
2449 inst.block.codegen.mcv = @bitCast(AnyMCValue, operand);
2450 } else {
2451 try self.setRegOrMem(inst.base.src, inst.block.base.ty, block_mcv, operand);
2452 }
2453 }
2454 return self.brVoid(inst.base.src, inst.block);
2455 }2453 }
24562454
2457 fn genBrVoid(self: *Self, inst: *ir.Inst.BrVoid) !MCValue {2455 fn genBrVoid(self: *Self, inst: *ir.Inst.BrVoid) !MCValue {
...@@ -2464,20 +2462,33 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2464,20 +2462,33 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2464 switch (arch) {2462 switch (arch) {
2465 .x86_64 => switch (inst.base.tag) {2463 .x86_64 => switch (inst.base.tag) {
2466 // lhs AND rhs2464 // lhs AND rhs
2467 .booland => return try self.genX8664BinMath(&inst.base, inst.lhs, inst.rhs, 4, 0x20),2465 .bool_and => return try self.genX8664BinMath(&inst.base, inst.lhs, inst.rhs, 4, 0x20),
2468 // lhs OR rhs2466 // lhs OR rhs
2469 .boolor => return try self.genX8664BinMath(&inst.base, inst.lhs, inst.rhs, 1, 0x08),2467 .bool_or => return try self.genX8664BinMath(&inst.base, inst.lhs, inst.rhs, 1, 0x08),
2470 else => unreachable, // Not a boolean operation2468 else => unreachable, // Not a boolean operation
2471 },2469 },
2472 .arm, .armeb => switch (inst.base.tag) {2470 .arm, .armeb => switch (inst.base.tag) {
2473 .booland => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .booland),2471 .bool_and => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .bool_and),
2474 .boolor => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .boolor),2472 .bool_or => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .bool_or),
2475 else => unreachable, // Not a boolean operation2473 else => unreachable, // Not a boolean operation
2476 },2474 },
2477 else => return self.fail(inst.base.src, "TODO implement boolean operations for {}", .{self.target.cpu.arch}),2475 else => return self.fail(inst.base.src, "TODO implement boolean operations for {}", .{self.target.cpu.arch}),
2478 }2476 }
2479 }2477 }
24802478
2479 fn br(self: *Self, src: usize, block: *ir.Inst.Block, operand: *ir.Inst) !MCValue {
2480 if (operand.ty.hasCodeGenBits()) {
2481 const operand_mcv = try self.resolveInst(operand);
2482 const block_mcv = @bitCast(MCValue, block.codegen.mcv);
2483 if (block_mcv == .none) {
2484 block.codegen.mcv = @bitCast(AnyMCValue, operand_mcv);
2485 } else {
2486 try self.setRegOrMem(src, block.base.ty, block_mcv, operand_mcv);
2487 }
2488 }
2489 return self.brVoid(src, block);
2490 }
2491
2481 fn brVoid(self: *Self, src: usize, block: *ir.Inst.Block) !MCValue {2492 fn brVoid(self: *Self, src: usize, block: *ir.Inst.Block) !MCValue {
2482 // Emit a jump with a relocation. It will be patched up after the block ends.2493 // Emit a jump with a relocation. It will be patched up after the block ends.
2483 try block.codegen.relocs.ensureCapacity(self.gpa, block.codegen.relocs.items.len + 1);2494 try block.codegen.relocs.ensureCapacity(self.gpa, block.codegen.relocs.items.len + 1);
src/ir.zig+43-13
...@@ -56,13 +56,20 @@ pub const Inst = struct {...@@ -56,13 +56,20 @@ pub const Inst = struct {
56 alloc,56 alloc,
57 arg,57 arg,
58 assembly,58 assembly,
59 bitand,59 bit_and,
60 bitcast,60 bitcast,
61 bitor,61 bit_or,
62 block,62 block,
63 br,63 br,
64 /// Same as `br` except the operand is a list of instructions to be treated as
65 /// a flat block; that is there is only 1 break instruction from the block, and
66 /// it is implied to be after the last instruction, and the last instruction is
67 /// the break operand.
68 /// This instruction exists for late-stage semantic analysis patch ups, to
69 /// replace one br operand with multiple instructions, without moving anything else around.
70 br_block_flat,
64 breakpoint,71 breakpoint,
65 brvoid,72 br_void,
66 call,73 call,
67 cmp_lt,74 cmp_lt,
68 cmp_lte,75 cmp_lte,
...@@ -85,8 +92,8 @@ pub const Inst = struct {...@@ -85,8 +92,8 @@ pub const Inst = struct {
85 is_err,92 is_err,
86 // *E!T => bool93 // *E!T => bool
87 is_err_ptr,94 is_err_ptr,
88 booland,95 bool_and,
89 boolor,96 bool_or,
90 /// Read a value from a pointer.97 /// Read a value from a pointer.
91 load,98 load,
92 loop,99 loop,
...@@ -147,10 +154,10 @@ pub const Inst = struct {...@@ -147,10 +154,10 @@ pub const Inst = struct {
147 .cmp_gt,154 .cmp_gt,
148 .cmp_neq,155 .cmp_neq,
149 .store,156 .store,
150 .booland,157 .bool_and,
151 .boolor,158 .bool_or,
152 .bitand,159 .bit_and,
153 .bitor,160 .bit_or,
154 .xor,161 .xor,
155 => BinOp,162 => BinOp,
156163
...@@ -158,7 +165,8 @@ pub const Inst = struct {...@@ -158,7 +165,8 @@ pub const Inst = struct {
158 .assembly => Assembly,165 .assembly => Assembly,
159 .block => Block,166 .block => Block,
160 .br => Br,167 .br => Br,
161 .brvoid => BrVoid,168 .br_block_flat => BrBlockFlat,
169 .br_void => BrVoid,
162 .call => Call,170 .call => Call,
163 .condbr => CondBr,171 .condbr => CondBr,
164 .constant => Constant,172 .constant => Constant,
...@@ -251,7 +259,8 @@ pub const Inst = struct {...@@ -251,7 +259,8 @@ pub const Inst = struct {
251 pub fn breakBlock(base: *Inst) ?*Block {259 pub fn breakBlock(base: *Inst) ?*Block {
252 return switch (base.tag) {260 return switch (base.tag) {
253 .br => base.castTag(.br).?.block,261 .br => base.castTag(.br).?.block,
254 .brvoid => base.castTag(.brvoid).?.block,262 .br_void => base.castTag(.br_void).?.block,
263 .br_block_flat => base.castTag(.br_block_flat).?.block,
255 else => null,264 else => null,
256 };265 };
257 }266 }
...@@ -355,6 +364,27 @@ pub const Inst = struct {...@@ -355,6 +364,27 @@ pub const Inst = struct {
355 }364 }
356 };365 };
357366
367 pub const convertable_br_size = std.math.max(@sizeOf(BrBlockFlat), @sizeOf(Br));
368 pub const convertable_br_align = std.math.max(@alignOf(BrBlockFlat), @alignOf(Br));
369 comptime {
370 assert(@byteOffsetOf(BrBlockFlat, "base") == @byteOffsetOf(Br, "base"));
371 }
372
373 pub const BrBlockFlat = struct {
374 pub const base_tag = Tag.br_block_flat;
375
376 base: Inst,
377 block: *Block,
378 body: Body,
379
380 pub fn operandCount(self: *const BrBlockFlat) usize {
381 return 0;
382 }
383 pub fn getOperand(self: *const BrBlockFlat, index: usize) ?*Inst {
384 return null;
385 }
386 };
387
358 pub const Br = struct {388 pub const Br = struct {
359 pub const base_tag = Tag.br;389 pub const base_tag = Tag.br;
360390
...@@ -363,7 +393,7 @@ pub const Inst = struct {...@@ -363,7 +393,7 @@ pub const Inst = struct {
363 operand: *Inst,393 operand: *Inst,
364394
365 pub fn operandCount(self: *const Br) usize {395 pub fn operandCount(self: *const Br) usize {
366 return 0;396 return 1;
367 }397 }
368 pub fn getOperand(self: *const Br, index: usize) ?*Inst {398 pub fn getOperand(self: *const Br, index: usize) ?*Inst {
369 if (index == 0)399 if (index == 0)
...@@ -373,7 +403,7 @@ pub const Inst = struct {...@@ -373,7 +403,7 @@ pub const Inst = struct {
373 };403 };
374404
375 pub const BrVoid = struct {405 pub const BrVoid = struct {
376 pub const base_tag = Tag.brvoid;406 pub const base_tag = Tag.br_void;
377407
378 base: Inst,408 base: Inst,
379 block: *Block,409 block: *Block,
src/zir.zig+110-165
...@@ -59,7 +59,7 @@ pub const Inst = struct {...@@ -59,7 +59,7 @@ pub const Inst = struct {
59 /// Inline assembly.59 /// Inline assembly.
60 @"asm",60 @"asm",
61 /// Bitwise AND. `&`61 /// Bitwise AND. `&`
62 bitand,62 bit_and,
63 /// TODO delete this instruction, it has no purpose.63 /// TODO delete this instruction, it has no purpose.
64 bitcast,64 bitcast,
65 /// An arbitrary typed pointer is pointer-casted to a new Pointer.65 /// An arbitrary typed pointer is pointer-casted to a new Pointer.
...@@ -71,9 +71,9 @@ pub const Inst = struct {...@@ -71,9 +71,9 @@ pub const Inst = struct {
71 /// The new result location pointer has an inferred type.71 /// The new result location pointer has an inferred type.
72 bitcast_result_ptr,72 bitcast_result_ptr,
73 /// Bitwise NOT. `~`73 /// Bitwise NOT. `~`
74 bitnot,74 bit_not,
75 /// Bitwise OR. `|`75 /// Bitwise OR. `|`
76 bitor,76 bit_or,
77 /// A labeled block of code, which can return a value.77 /// A labeled block of code, which can return a value.
78 block,78 block,
79 /// A block of code, which can return a value. There are no instructions that break out of79 /// A block of code, which can return a value. There are no instructions that break out of
...@@ -83,17 +83,17 @@ pub const Inst = struct {...@@ -83,17 +83,17 @@ pub const Inst = struct {
83 block_comptime,83 block_comptime,
84 /// Same as `block_flat` but additionally makes the inner instructions execute at comptime.84 /// Same as `block_flat` but additionally makes the inner instructions execute at comptime.
85 block_comptime_flat,85 block_comptime_flat,
86 /// Boolean AND. See also `bitand`.86 /// Boolean AND. See also `bit_and`.
87 booland,87 bool_and,
88 /// Boolean NOT. See also `bitnot`.88 /// Boolean NOT. See also `bit_not`.
89 boolnot,89 bool_not,
90 /// Boolean OR. See also `bitor`.90 /// Boolean OR. See also `bit_or`.
91 boolor,91 bool_or,
92 /// Return a value from a `Block`.92 /// Return a value from a `Block`.
93 @"break",93 @"break",
94 breakpoint,94 breakpoint,
95 /// Same as `break` but without an operand; the operand is assumed to be the void value.95 /// Same as `break` but without an operand; the operand is assumed to be the void value.
96 breakvoid,96 break_void,
97 /// Function call.97 /// Function call.
98 call,98 call,
99 /// `<`99 /// `<`
...@@ -112,16 +112,10 @@ pub const Inst = struct {...@@ -112,16 +112,10 @@ pub const Inst = struct {
112 /// as type coercion from the new element type to the old element type.112 /// as type coercion from the new element type to the old element type.
113 /// LHS is destination element type, RHS is result pointer.113 /// LHS is destination element type, RHS is result pointer.
114 coerce_result_ptr,114 coerce_result_ptr,
115 /// This instruction does a `coerce_result_ptr` operation on a `Block`'s
116 /// result location pointer, whose type is inferred by peer type resolution on the
117 /// `Block`'s corresponding `break` instructions.
118 coerce_result_block_ptr,
119 /// Equivalent to `as(ptr_child_type(typeof(ptr)), value)`.
120 coerce_to_ptr_elem,
121 /// Emit an error message and fail compilation.115 /// Emit an error message and fail compilation.
122 compileerror,116 compile_error,
123 /// Log compile time variables and emit an error message.117 /// Log compile time variables and emit an error message.
124 compilelog,118 compile_log,
125 /// Conditional branch. Splits control flow based on a boolean condition value.119 /// Conditional branch. Splits control flow based on a boolean condition value.
126 condbr,120 condbr,
127 /// Special case, has no textual representation.121 /// Special case, has no textual representation.
...@@ -135,11 +129,11 @@ pub const Inst = struct {...@@ -135,11 +129,11 @@ pub const Inst = struct {
135 /// Declares the beginning of a statement. Used for debug info.129 /// Declares the beginning of a statement. Used for debug info.
136 dbg_stmt,130 dbg_stmt,
137 /// Represents a pointer to a global decl.131 /// Represents a pointer to a global decl.
138 declref,132 decl_ref,
139 /// Represents a pointer to a global decl by string name.133 /// Represents a pointer to a global decl by string name.
140 declref_str,134 decl_ref_str,
141 /// Equivalent to a declref followed by deref.135 /// Equivalent to a decl_ref followed by deref.
142 declval,136 decl_val,
143 /// Load the value from a pointer.137 /// Load the value from a pointer.
144 deref,138 deref,
145 /// Arithmetic division. Asserts no integer overflow.139 /// Arithmetic division. Asserts no integer overflow.
...@@ -185,7 +179,7 @@ pub const Inst = struct {...@@ -185,7 +179,7 @@ pub const Inst = struct {
185 /// can hold the same mathematical value.179 /// can hold the same mathematical value.
186 intcast,180 intcast,
187 /// Make an integer type out of signedness and bit count.181 /// Make an integer type out of signedness and bit count.
188 inttype,182 int_type,
189 /// Return a boolean false if an optional is null. `x != null`183 /// Return a boolean false if an optional is null. `x != null`
190 is_non_null,184 is_non_null,
191 /// Return a boolean true if an optional is null. `x == null`185 /// Return a boolean true if an optional is null. `x == null`
...@@ -232,7 +226,7 @@ pub const Inst = struct {...@@ -232,7 +226,7 @@ pub const Inst = struct {
232 /// Sends control flow back to the function's callee. Takes an operand as the return value.226 /// Sends control flow back to the function's callee. Takes an operand as the return value.
233 @"return",227 @"return",
234 /// Same as `return` but there is no operand; the operand is implicitly the void value.228 /// Same as `return` but there is no operand; the operand is implicitly the void value.
235 returnvoid,229 return_void,
236 /// Changes the maximum number of backwards branches that compile-time230 /// Changes the maximum number of backwards branches that compile-time
237 /// code execution can use before giving up and making a compile error.231 /// code execution can use before giving up and making a compile error.
238 set_eval_branch_quota,232 set_eval_branch_quota,
...@@ -270,6 +264,9 @@ pub const Inst = struct {...@@ -270,6 +264,9 @@ pub const Inst = struct {
270 /// Write a value to a pointer. For loading, see `deref`.264 /// Write a value to a pointer. For loading, see `deref`.
271 store,265 store,
272 /// Same as `store` but the type of the value being stored will be used to infer266 /// Same as `store` but the type of the value being stored will be used to infer
267 /// the block type. The LHS is the pointer to store to.
268 store_to_block_ptr,
269 /// Same as `store` but the type of the value being stored will be used to infer
273 /// the pointer type.270 /// the pointer type.
274 store_to_inferred_ptr,271 store_to_inferred_ptr,
275 /// String Literal. Makes an anonymous Decl and then takes a pointer to it.272 /// String Literal. Makes an anonymous Decl and then takes a pointer to it.
...@@ -286,11 +283,11 @@ pub const Inst = struct {...@@ -286,11 +283,11 @@ pub const Inst = struct {
286 typeof_peer,283 typeof_peer,
287 /// Asserts control-flow will not reach this instruction. Not safety checked - the compiler284 /// Asserts control-flow will not reach this instruction. Not safety checked - the compiler
288 /// will assume the correctness of this instruction.285 /// will assume the correctness of this instruction.
289 unreach_nocheck,286 unreachable_unsafe,
290 /// Asserts control-flow will not reach this instruction. In safety-checked modes,287 /// Asserts control-flow will not reach this instruction. In safety-checked modes,
291 /// this will generate a call to the panic function unless it can be proven unreachable288 /// this will generate a call to the panic function unless it can be proven unreachable
292 /// by the compiler.289 /// by the compiler.
293 @"unreachable",290 unreachable_safe,
294 /// Bitwise XOR. `^`291 /// Bitwise XOR. `^`
295 xor,292 xor,
296 /// Create an optional type '?T'293 /// Create an optional type '?T'
...@@ -339,12 +336,8 @@ pub const Inst = struct {...@@ -339,12 +336,8 @@ pub const Inst = struct {
339 enum_literal,336 enum_literal,
340 /// Create an enum type.337 /// Create an enum type.
341 enum_type,338 enum_type,
342 /// A switch expression.339 /// Does nothing; returns a void value.
343 switchbr,340 void_value,
344 /// A range in a switch case, `lhs...rhs`.
345 /// Only checks that `lhs >= rhs` if they are ints, everything else is
346 /// validated by the .switch instruction.
347 switch_range,
348341
349 pub fn Type(tag: Tag) type {342 pub fn Type(tag: Tag) type {
350 return switch (tag) {343 return switch (tag) {
...@@ -352,17 +345,18 @@ pub const Inst = struct {...@@ -352,17 +345,18 @@ pub const Inst = struct {
352 .alloc_inferred_mut,345 .alloc_inferred_mut,
353 .breakpoint,346 .breakpoint,
354 .dbg_stmt,347 .dbg_stmt,
355 .returnvoid,348 .return_void,
356 .ret_ptr,349 .ret_ptr,
357 .ret_type,350 .ret_type,
358 .unreach_nocheck,351 .unreachable_unsafe,
359 .@"unreachable",352 .unreachable_safe,
353 .void_value,
360 => NoOp,354 => NoOp,
361355
362 .alloc,356 .alloc,
363 .alloc_mut,357 .alloc_mut,
364 .boolnot,358 .bool_not,
365 .compileerror,359 .compile_error,
366 .deref,360 .deref,
367 .@"return",361 .@"return",
368 .is_null,362 .is_null,
...@@ -400,7 +394,7 @@ pub const Inst = struct {...@@ -400,7 +394,7 @@ pub const Inst = struct {
400 .err_union_code_ptr,394 .err_union_code_ptr,
401 .ensure_err_payload_void,395 .ensure_err_payload_void,
402 .anyframe_type,396 .anyframe_type,
403 .bitnot,397 .bit_not,
404 .import,398 .import,
405 .set_eval_branch_quota,399 .set_eval_branch_quota,
406 .indexable_ptr_len,400 .indexable_ptr_len,
...@@ -411,10 +405,10 @@ pub const Inst = struct {...@@ -411,10 +405,10 @@ pub const Inst = struct {
411 .array_cat,405 .array_cat,
412 .array_mul,406 .array_mul,
413 .array_type,407 .array_type,
414 .bitand,408 .bit_and,
415 .bitor,409 .bit_or,
416 .booland,410 .bool_and,
417 .boolor,411 .bool_or,
418 .div,412 .div,
419 .mod_rem,413 .mod_rem,
420 .mul,414 .mul,
...@@ -422,6 +416,7 @@ pub const Inst = struct {...@@ -422,6 +416,7 @@ pub const Inst = struct {
422 .shl,416 .shl,
423 .shr,417 .shr,
424 .store,418 .store,
419 .store_to_block_ptr,
425 .store_to_inferred_ptr,420 .store_to_inferred_ptr,
426 .sub,421 .sub,
427 .subwrap,422 .subwrap,
...@@ -440,7 +435,6 @@ pub const Inst = struct {...@@ -440,7 +435,6 @@ pub const Inst = struct {
440 .error_union_type,435 .error_union_type,
441 .merge_error_sets,436 .merge_error_sets,
442 .slice_start,437 .slice_start,
443 .switch_range,
444 => BinOp,438 => BinOp,
445439
446 .block,440 .block,
...@@ -452,19 +446,17 @@ pub const Inst = struct {...@@ -452,19 +446,17 @@ pub const Inst = struct {
452 .arg => Arg,446 .arg => Arg,
453 .array_type_sentinel => ArrayTypeSentinel,447 .array_type_sentinel => ArrayTypeSentinel,
454 .@"break" => Break,448 .@"break" => Break,
455 .breakvoid => BreakVoid,449 .break_void => BreakVoid,
456 .call => Call,450 .call => Call,
457 .coerce_to_ptr_elem => CoerceToPtrElem,451 .decl_ref => DeclRef,
458 .declref => DeclRef,452 .decl_ref_str => DeclRefStr,
459 .declref_str => DeclRefStr,453 .decl_val => DeclVal,
460 .declval => DeclVal,454 .compile_log => CompileLog,
461 .coerce_result_block_ptr => CoerceResultBlockPtr,
462 .compilelog => CompileLog,
463 .loop => Loop,455 .loop => Loop,
464 .@"const" => Const,456 .@"const" => Const,
465 .str => Str,457 .str => Str,
466 .int => Int,458 .int => Int,
467 .inttype => IntType,459 .int_type => IntType,
468 .field_ptr, .field_val => Field,460 .field_ptr, .field_val => Field,
469 .field_ptr_named, .field_val_named => FieldNamed,461 .field_ptr_named, .field_val_named => FieldNamed,
470 .@"asm" => Asm,462 .@"asm" => Asm,
...@@ -479,7 +471,6 @@ pub const Inst = struct {...@@ -479,7 +471,6 @@ pub const Inst = struct {
479 .enum_literal => EnumLiteral,471 .enum_literal => EnumLiteral,
480 .error_set => ErrorSet,472 .error_set => ErrorSet,
481 .slice => Slice,473 .slice => Slice,
482 .switchbr => SwitchBr,
483 .typeof_peer => TypeOfPeer,474 .typeof_peer => TypeOfPeer,
484 .container_field_named => ContainerFieldNamed,475 .container_field_named => ContainerFieldNamed,
485 .container_field_typed => ContainerFieldTyped,476 .container_field_typed => ContainerFieldTyped,
...@@ -508,18 +499,18 @@ pub const Inst = struct {...@@ -508,18 +499,18 @@ pub const Inst = struct {
508 .arg,499 .arg,
509 .as,500 .as,
510 .@"asm",501 .@"asm",
511 .bitand,502 .bit_and,
512 .bitcast,503 .bitcast,
513 .bitcast_ref,504 .bitcast_ref,
514 .bitcast_result_ptr,505 .bitcast_result_ptr,
515 .bitor,506 .bit_or,
516 .block,507 .block,
517 .block_flat,508 .block_flat,
518 .block_comptime,509 .block_comptime,
519 .block_comptime_flat,510 .block_comptime_flat,
520 .boolnot,511 .bool_not,
521 .booland,512 .bool_and,
522 .boolor,513 .bool_or,
523 .breakpoint,514 .breakpoint,
524 .call,515 .call,
525 .cmp_lt,516 .cmp_lt,
...@@ -529,13 +520,11 @@ pub const Inst = struct {...@@ -529,13 +520,11 @@ pub const Inst = struct {
529 .cmp_gt,520 .cmp_gt,
530 .cmp_neq,521 .cmp_neq,
531 .coerce_result_ptr,522 .coerce_result_ptr,
532 .coerce_result_block_ptr,
533 .coerce_to_ptr_elem,
534 .@"const",523 .@"const",
535 .dbg_stmt,524 .dbg_stmt,
536 .declref,525 .decl_ref,
537 .declref_str,526 .decl_ref_str,
538 .declval,527 .decl_val,
539 .deref,528 .deref,
540 .div,529 .div,
541 .elem_ptr,530 .elem_ptr,
...@@ -552,7 +541,7 @@ pub const Inst = struct {...@@ -552,7 +541,7 @@ pub const Inst = struct {
552 .fntype,541 .fntype,
553 .int,542 .int,
554 .intcast,543 .intcast,
555 .inttype,544 .int_type,
556 .is_non_null,545 .is_non_null,
557 .is_null,546 .is_null,
558 .is_non_null_ptr,547 .is_non_null_ptr,
...@@ -579,6 +568,7 @@ pub const Inst = struct {...@@ -579,6 +568,7 @@ pub const Inst = struct {
579 .mut_slice_type,568 .mut_slice_type,
580 .const_slice_type,569 .const_slice_type,
581 .store,570 .store,
571 .store_to_block_ptr,
582 .store_to_inferred_ptr,572 .store_to_inferred_ptr,
583 .str,573 .str,
584 .sub,574 .sub,
...@@ -602,31 +592,30 @@ pub const Inst = struct {...@@ -602,31 +592,30 @@ pub const Inst = struct {
602 .merge_error_sets,592 .merge_error_sets,
603 .anyframe_type,593 .anyframe_type,
604 .error_union_type,594 .error_union_type,
605 .bitnot,595 .bit_not,
606 .error_set,596 .error_set,
607 .slice,597 .slice,
608 .slice_start,598 .slice_start,
609 .import,599 .import,
610 .switch_range,
611 .typeof_peer,600 .typeof_peer,
612 .resolve_inferred_alloc,601 .resolve_inferred_alloc,
613 .set_eval_branch_quota,602 .set_eval_branch_quota,
614 .compilelog,603 .compile_log,
615 .enum_type,604 .enum_type,
616 .union_type,605 .union_type,
617 .struct_type,606 .struct_type,
607 .void_value,
618 => false,608 => false,
619609
620 .@"break",610 .@"break",
621 .breakvoid,611 .break_void,
622 .condbr,612 .condbr,
623 .compileerror,613 .compile_error,
624 .@"return",614 .@"return",
625 .returnvoid,615 .return_void,
626 .unreach_nocheck,616 .unreachable_unsafe,
627 .@"unreachable",617 .unreachable_safe,
628 .loop,618 .loop,
629 .switchbr,
630 .container_field_named,619 .container_field_named,
631 .container_field_typed,620 .container_field_typed,
632 .container_field,621 .container_field,
...@@ -717,7 +706,7 @@ pub const Inst = struct {...@@ -717,7 +706,7 @@ pub const Inst = struct {
717 };706 };
718707
719 pub const BreakVoid = struct {708 pub const BreakVoid = struct {
720 pub const base_tag = Tag.breakvoid;709 pub const base_tag = Tag.break_void;
721 base: Inst,710 base: Inst,
722711
723 positionals: struct {712 positionals: struct {
...@@ -739,19 +728,8 @@ pub const Inst = struct {...@@ -739,19 +728,8 @@ pub const Inst = struct {
739 },728 },
740 };729 };
741730
742 pub const CoerceToPtrElem = struct {
743 pub const base_tag = Tag.coerce_to_ptr_elem;
744 base: Inst,
745
746 positionals: struct {
747 ptr: *Inst,
748 value: *Inst,
749 },
750 kw_args: struct {},
751 };
752
753 pub const DeclRef = struct {731 pub const DeclRef = struct {
754 pub const base_tag = Tag.declref;732 pub const base_tag = Tag.decl_ref;
755 base: Inst,733 base: Inst,
756734
757 positionals: struct {735 positionals: struct {
...@@ -761,7 +739,7 @@ pub const Inst = struct {...@@ -761,7 +739,7 @@ pub const Inst = struct {
761 };739 };
762740
763 pub const DeclRefStr = struct {741 pub const DeclRefStr = struct {
764 pub const base_tag = Tag.declref_str;742 pub const base_tag = Tag.decl_ref_str;
765 base: Inst,743 base: Inst,
766744
767 positionals: struct {745 positionals: struct {
...@@ -771,7 +749,7 @@ pub const Inst = struct {...@@ -771,7 +749,7 @@ pub const Inst = struct {
771 };749 };
772750
773 pub const DeclVal = struct {751 pub const DeclVal = struct {
774 pub const base_tag = Tag.declval;752 pub const base_tag = Tag.decl_val;
775 base: Inst,753 base: Inst,
776754
777 positionals: struct {755 positionals: struct {
...@@ -780,19 +758,8 @@ pub const Inst = struct {...@@ -780,19 +758,8 @@ pub const Inst = struct {
780 kw_args: struct {},758 kw_args: struct {},
781 };759 };
782760
783 pub const CoerceResultBlockPtr = struct {
784 pub const base_tag = Tag.coerce_result_block_ptr;
785 base: Inst,
786
787 positionals: struct {
788 dest_type: *Inst,
789 block: *Block,
790 },
791 kw_args: struct {},
792 };
793
794 pub const CompileLog = struct {761 pub const CompileLog = struct {
795 pub const base_tag = Tag.compilelog;762 pub const base_tag = Tag.compile_log;
796 base: Inst,763 base: Inst,
797764
798 positionals: struct {765 positionals: struct {
...@@ -905,7 +872,7 @@ pub const Inst = struct {...@@ -905,7 +872,7 @@ pub const Inst = struct {
905 };872 };
906873
907 pub const IntType = struct {874 pub const IntType = struct {
908 pub const base_tag = Tag.inttype;875 pub const base_tag = Tag.int_type;
909 base: Inst,876 base: Inst,
910877
911 positionals: struct {878 positionals: struct {
...@@ -1114,32 +1081,6 @@ pub const Inst = struct {...@@ -1114,32 +1081,6 @@ pub const Inst = struct {
1114 },1081 },
1115 };1082 };
11161083
1117 pub const SwitchBr = struct {
1118 pub const base_tag = Tag.switchbr;
1119 base: Inst,
1120
1121 positionals: struct {
1122 target_ptr: *Inst,
1123 /// List of all individual items and ranges
1124 items: []*Inst,
1125 cases: []Case,
1126 else_body: Body,
1127 },
1128 kw_args: struct {
1129 /// Pointer to first range if such exists.
1130 range: ?*Inst = null,
1131 special_prong: enum {
1132 none,
1133 @"else",
1134 underscore,
1135 } = .none,
1136 },
1137
1138 pub const Case = struct {
1139 item: *Inst,
1140 body: Body,
1141 };
1142 };
1143 pub const TypeOfPeer = struct {1084 pub const TypeOfPeer = struct {
1144 pub const base_tag = .typeof_peer;1085 pub const base_tag = .typeof_peer;
1145 base: Inst,1086 base: Inst,
...@@ -1473,7 +1414,7 @@ const Writer = struct {...@@ -1473,7 +1414,7 @@ const Writer = struct {
1473 TypedValue => return stream.print("TypedValue{{ .ty = {}, .val = {}}}", .{ param.ty, param.val }),1414 TypedValue => return stream.print("TypedValue{{ .ty = {}, .val = {}}}", .{ param.ty, param.val }),
1474 *IrModule.Decl => return stream.print("Decl({s})", .{param.name}),1415 *IrModule.Decl => return stream.print("Decl({s})", .{param.name}),
1475 *Inst.Block => {1416 *Inst.Block => {
1476 const name = self.block_table.get(param).?;1417 const name = self.block_table.get(param) orelse "!BADREF!";
1477 return stream.print("\"{}\"", .{std.zig.fmtEscapes(name)});1418 return stream.print("\"{}\"", .{std.zig.fmtEscapes(name)});
1478 },1419 },
1479 *Inst.Loop => {1420 *Inst.Loop => {
...@@ -1490,26 +1431,6 @@ const Writer = struct {...@@ -1490,26 +1431,6 @@ const Writer = struct {
1490 }1431 }
1491 try stream.writeByte(']');1432 try stream.writeByte(']');
1492 },1433 },
1493 []Inst.SwitchBr.Case => {
1494 if (param.len == 0) {
1495 return stream.writeAll("{}");
1496 }
1497 try stream.writeAll("{\n");
1498 for (param) |*case, i| {
1499 if (i != 0) {
1500 try stream.writeAll(",\n");
1501 }
1502 try stream.writeByteNTimes(' ', self.indent);
1503 self.indent += 2;
1504 try self.writeParamToStream(stream, &case.item);
1505 try stream.writeAll(" => ");
1506 try self.writeParamToStream(stream, &case.body);
1507 self.indent -= 2;
1508 }
1509 try stream.writeByte('\n');
1510 try stream.writeByteNTimes(' ', self.indent - 2);
1511 try stream.writeByte('}');
1512 },
1513 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),1434 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),
1514 }1435 }
1515 }1436 }
...@@ -1641,10 +1562,10 @@ const DumpTzir = struct {...@@ -1641,10 +1562,10 @@ const DumpTzir = struct {
1641 .cmp_gt,1562 .cmp_gt,
1642 .cmp_neq,1563 .cmp_neq,
1643 .store,1564 .store,
1644 .booland,1565 .bool_and,
1645 .boolor,1566 .bool_or,
1646 .bitand,1567 .bit_and,
1647 .bitor,1568 .bit_or,
1648 .xor,1569 .xor,
1649 => {1570 => {
1650 const bin_op = inst.cast(ir.Inst.BinOp).?;1571 const bin_op = inst.cast(ir.Inst.BinOp).?;
...@@ -1660,9 +1581,15 @@ const DumpTzir = struct {...@@ -1660,9 +1581,15 @@ const DumpTzir = struct {
1660 try dtz.findConst(br.operand);1581 try dtz.findConst(br.operand);
1661 },1582 },
16621583
1663 .brvoid => {1584 .br_block_flat => {
1664 const brvoid = inst.castTag(.brvoid).?;1585 const br_block_flat = inst.castTag(.br_block_flat).?;
1665 try dtz.findConst(&brvoid.block.base);1586 try dtz.findConst(&br_block_flat.block.base);
1587 try dtz.fetchInstsAndResolveConsts(br_block_flat.body);
1588 },
1589
1590 .br_void => {
1591 const br_void = inst.castTag(.br_void).?;
1592 try dtz.findConst(&br_void.block.base);
1666 },1593 },
16671594
1668 .block => {1595 .block => {
...@@ -1753,10 +1680,10 @@ const DumpTzir = struct {...@@ -1753,10 +1680,10 @@ const DumpTzir = struct {
1753 .cmp_gt,1680 .cmp_gt,
1754 .cmp_neq,1681 .cmp_neq,
1755 .store,1682 .store,
1756 .booland,1683 .bool_and,
1757 .boolor,1684 .bool_or,
1758 .bitand,1685 .bit_and,
1759 .bitor,1686 .bit_or,
1760 .xor,1687 .xor,
1761 => {1688 => {
1762 const bin_op = inst.cast(ir.Inst.BinOp).?;1689 const bin_op = inst.cast(ir.Inst.BinOp).?;
...@@ -1805,9 +1732,27 @@ const DumpTzir = struct {...@@ -1805,9 +1732,27 @@ const DumpTzir = struct {
1805 }1732 }
1806 },1733 },
18071734
1808 .brvoid => {1735 .br_block_flat => {
1809 const brvoid = inst.castTag(.brvoid).?;1736 const br_block_flat = inst.castTag(.br_block_flat).?;
1810 const kinky = try dtz.writeInst(writer, &brvoid.block.base);1737 const block_kinky = try dtz.writeInst(writer, &br_block_flat.block.base);
1738 if (block_kinky != null) {
1739 try writer.writeAll(", { // Instruction does not dominate all uses!\n");
1740 } else {
1741 try writer.writeAll(", {\n");
1742 }
1743
1744 const old_indent = dtz.indent;
1745 dtz.indent += 2;
1746 try dtz.dumpBody(br_block_flat.body, writer);
1747 dtz.indent = old_indent;
1748
1749 try writer.writeByteNTimes(' ', dtz.indent);
1750 try writer.writeAll("})\n");
1751 },
1752
1753 .br_void => {
1754 const br_void = inst.castTag(.br_void).?;
1755 const kinky = try dtz.writeInst(writer, &br_void.block.base);
1811 if (kinky) |_| {1756 if (kinky) |_| {
1812 try writer.writeAll(") // Instruction does not dominate all uses!\n");1757 try writer.writeAll(") // Instruction does not dominate all uses!\n");
1813 } else {1758 } else {
...@@ -1818,7 +1763,7 @@ const DumpTzir = struct {...@@ -1818,7 +1763,7 @@ const DumpTzir = struct {
1818 .block => {1763 .block => {
1819 const block = inst.castTag(.block).?;1764 const block = inst.castTag(.block).?;
18201765
1821 try writer.writeAll("\n");1766 try writer.writeAll("{\n");
18221767
1823 const old_indent = dtz.indent;1768 const old_indent = dtz.indent;
1824 dtz.indent += 2;1769 dtz.indent += 2;
...@@ -1826,7 +1771,7 @@ const DumpTzir = struct {...@@ -1826,7 +1771,7 @@ const DumpTzir = struct {
1826 dtz.indent = old_indent;1771 dtz.indent = old_indent;
18271772
1828 try writer.writeByteNTimes(' ', dtz.indent);1773 try writer.writeByteNTimes(' ', dtz.indent);
1829 try writer.writeAll(")\n");1774 try writer.writeAll("})\n");
1830 },1775 },
18311776
1832 .condbr => {1777 .condbr => {
...@@ -1856,7 +1801,7 @@ const DumpTzir = struct {...@@ -1856,7 +1801,7 @@ const DumpTzir = struct {
1856 .loop => {1801 .loop => {
1857 const loop = inst.castTag(.loop).?;1802 const loop = inst.castTag(.loop).?;
18581803
1859 try writer.writeAll("\n");1804 try writer.writeAll("{\n");
18601805
1861 const old_indent = dtz.indent;1806 const old_indent = dtz.indent;
1862 dtz.indent += 2;1807 dtz.indent += 2;
...@@ -1864,7 +1809,7 @@ const DumpTzir = struct {...@@ -1864,7 +1809,7 @@ const DumpTzir = struct {
1864 dtz.indent = old_indent;1809 dtz.indent = old_indent;
18651810
1866 try writer.writeByteNTimes(' ', dtz.indent);1811 try writer.writeByteNTimes(' ', dtz.indent);
1867 try writer.writeAll(")\n");1812 try writer.writeAll("})\n");
1868 },1813 },
18691814
1870 .call => {1815 .call => {
src/zir_sema.zig+357-538
...@@ -28,144 +28,132 @@ const Decl = Module.Decl;...@@ -28,144 +28,132 @@ const Decl = Module.Decl;
2828
29pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {29pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {
30 switch (old_inst.tag) {30 switch (old_inst.tag) {
31 .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?),31 .alloc => return zirAlloc(mod, scope, old_inst.castTag(.alloc).?),
32 .alloc_mut => return analyzeInstAllocMut(mod, scope, old_inst.castTag(.alloc_mut).?),32 .alloc_mut => return zirAllocMut(mod, scope, old_inst.castTag(.alloc_mut).?),
33 .alloc_inferred => return analyzeInstAllocInferred(33 .alloc_inferred => return zirAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?, .inferred_alloc_const),
34 mod,34 .alloc_inferred_mut => return zirAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred_mut).?, .inferred_alloc_mut),
35 scope,35 .arg => return zirArg(mod, scope, old_inst.castTag(.arg).?),
36 old_inst.castTag(.alloc_inferred).?,36 .bitcast_ref => return zirBitcastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
37 .inferred_alloc_const,37 .bitcast_result_ptr => return zirBitcastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
38 ),38 .block => return zirBlock(mod, scope, old_inst.castTag(.block).?, false),
39 .alloc_inferred_mut => return analyzeInstAllocInferred(39 .block_comptime => return zirBlock(mod, scope, old_inst.castTag(.block_comptime).?, true),
40 mod,40 .block_flat => return zirBlockFlat(mod, scope, old_inst.castTag(.block_flat).?, false),
41 scope,41 .block_comptime_flat => return zirBlockFlat(mod, scope, old_inst.castTag(.block_comptime_flat).?, true),
42 old_inst.castTag(.alloc_inferred_mut).?,42 .@"break" => return zirBreak(mod, scope, old_inst.castTag(.@"break").?),
43 .inferred_alloc_mut,43 .breakpoint => return zirBreakpoint(mod, scope, old_inst.castTag(.breakpoint).?),
44 ),44 .break_void => return zirBreakVoid(mod, scope, old_inst.castTag(.break_void).?),
45 .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),45 .call => return zirCall(mod, scope, old_inst.castTag(.call).?),
46 .bitcast_ref => return bitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),46 .coerce_result_ptr => return zirCoerceResultPtr(mod, scope, old_inst.castTag(.coerce_result_ptr).?),
47 .bitcast_result_ptr => return bitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),47 .compile_error => return zirCompileError(mod, scope, old_inst.castTag(.compile_error).?),
48 .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?, false),48 .compile_log => return zirCompileLog(mod, scope, old_inst.castTag(.compile_log).?),
49 .block_comptime => return analyzeInstBlock(mod, scope, old_inst.castTag(.block_comptime).?, true),49 .@"const" => return zirConst(mod, scope, old_inst.castTag(.@"const").?),
50 .block_flat => return analyzeInstBlockFlat(mod, scope, old_inst.castTag(.block_flat).?, false),50 .dbg_stmt => return zirDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?),
51 .block_comptime_flat => return analyzeInstBlockFlat(mod, scope, old_inst.castTag(.block_comptime_flat).?, true),51 .decl_ref => return zirDeclRef(mod, scope, old_inst.castTag(.decl_ref).?),
52 .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?),52 .decl_ref_str => return zirDeclRefStr(mod, scope, old_inst.castTag(.decl_ref_str).?),
53 .breakpoint => return analyzeInstBreakpoint(mod, scope, old_inst.castTag(.breakpoint).?),53 .decl_val => return zirDeclVal(mod, scope, old_inst.castTag(.decl_val).?),
54 .breakvoid => return analyzeInstBreakVoid(mod, scope, old_inst.castTag(.breakvoid).?),54 .ensure_result_used => return zirEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?),
55 .call => return call(mod, scope, old_inst.castTag(.call).?),55 .ensure_result_non_error => return zirEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?),
56 .coerce_result_block_ptr => return analyzeInstCoerceResultBlockPtr(mod, scope, old_inst.castTag(.coerce_result_block_ptr).?),56 .indexable_ptr_len => return zirIndexablePtrLen(mod, scope, old_inst.castTag(.indexable_ptr_len).?),
57 .coerce_result_ptr => return analyzeInstCoerceResultPtr(mod, scope, old_inst.castTag(.coerce_result_ptr).?),57 .ref => return zirRef(mod, scope, old_inst.castTag(.ref).?),
58 .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?),58 .resolve_inferred_alloc => return zirResolveInferredAlloc(mod, scope, old_inst.castTag(.resolve_inferred_alloc).?),
59 .compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?),59 .ret_ptr => return zirRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),
60 .compilelog => return analyzeInstCompileLog(mod, scope, old_inst.castTag(.compilelog).?),60 .ret_type => return zirRetType(mod, scope, old_inst.castTag(.ret_type).?),
61 .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?),61 .store_to_block_ptr => return zirStoreToBlockPtr(mod, scope, old_inst.castTag(.store_to_block_ptr).?),
62 .dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?),62 .store_to_inferred_ptr => return zirStoreToInferredPtr(mod, scope, old_inst.castTag(.store_to_inferred_ptr).?),
63 .declref => return declRef(mod, scope, old_inst.castTag(.declref).?),63 .single_const_ptr_type => return zirSimplePtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?, false, .One),
64 .declref_str => return analyzeInstDeclRefStr(mod, scope, old_inst.castTag(.declref_str).?),64 .single_mut_ptr_type => return zirSimplePtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?, true, .One),
65 .declval => return declVal(mod, scope, old_inst.castTag(.declval).?),65 .many_const_ptr_type => return zirSimplePtrType(mod, scope, old_inst.castTag(.many_const_ptr_type).?, false, .Many),
66 .ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?),66 .many_mut_ptr_type => return zirSimplePtrType(mod, scope, old_inst.castTag(.many_mut_ptr_type).?, true, .Many),
67 .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?),67 .c_const_ptr_type => return zirSimplePtrType(mod, scope, old_inst.castTag(.c_const_ptr_type).?, false, .C),
68 .indexable_ptr_len => return indexablePtrLen(mod, scope, old_inst.castTag(.indexable_ptr_len).?),68 .c_mut_ptr_type => return zirSimplePtrType(mod, scope, old_inst.castTag(.c_mut_ptr_type).?, true, .C),
69 .ref => return ref(mod, scope, old_inst.castTag(.ref).?),69 .const_slice_type => return zirSimplePtrType(mod, scope, old_inst.castTag(.const_slice_type).?, false, .Slice),
70 .resolve_inferred_alloc => return analyzeInstResolveInferredAlloc(mod, scope, old_inst.castTag(.resolve_inferred_alloc).?),70 .mut_slice_type => return zirSimplePtrType(mod, scope, old_inst.castTag(.mut_slice_type).?, true, .Slice),
71 .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),71 .ptr_type => return zirPtrType(mod, scope, old_inst.castTag(.ptr_type).?),
72 .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?),72 .store => return zirStore(mod, scope, old_inst.castTag(.store).?),
73 .store_to_inferred_ptr => return analyzeInstStoreToInferredPtr(mod, scope, old_inst.castTag(.store_to_inferred_ptr).?),73 .set_eval_branch_quota => return zirSetEvalBranchQuota(mod, scope, old_inst.castTag(.set_eval_branch_quota).?),
74 .single_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?, false, .One),74 .str => return zirStr(mod, scope, old_inst.castTag(.str).?),
75 .single_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?, true, .One),75 .int => return zirInt(mod, scope, old_inst.castTag(.int).?),
76 .many_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_const_ptr_type).?, false, .Many),76 .int_type => return zirIntType(mod, scope, old_inst.castTag(.int_type).?),
77 .many_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_mut_ptr_type).?, true, .Many),77 .loop => return zirLoop(mod, scope, old_inst.castTag(.loop).?),
78 .c_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.c_const_ptr_type).?, false, .C),78 .param_type => return zirParamType(mod, scope, old_inst.castTag(.param_type).?),
79 .c_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.c_mut_ptr_type).?, true, .C),79 .ptrtoint => return zirPtrtoint(mod, scope, old_inst.castTag(.ptrtoint).?),
80 .const_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.const_slice_type).?, false, .Slice),80 .field_ptr => return zirFieldPtr(mod, scope, old_inst.castTag(.field_ptr).?),
81 .mut_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.mut_slice_type).?, true, .Slice),81 .field_val => return zirFieldVal(mod, scope, old_inst.castTag(.field_val).?),
82 .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?),82 .field_ptr_named => return zirFieldPtrNamed(mod, scope, old_inst.castTag(.field_ptr_named).?),
83 .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?),83 .field_val_named => return zirFieldValNamed(mod, scope, old_inst.castTag(.field_val_named).?),
84 .set_eval_branch_quota => return analyzeInstSetEvalBranchQuota(mod, scope, old_inst.castTag(.set_eval_branch_quota).?),84 .deref => return zirDeref(mod, scope, old_inst.castTag(.deref).?),
85 .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?),85 .as => return zirAs(mod, scope, old_inst.castTag(.as).?),
86 .int => return analyzeInstInt(mod, scope, old_inst.castTag(.int).?),86 .@"asm" => return zirAsm(mod, scope, old_inst.castTag(.@"asm").?),
87 .inttype => return analyzeInstIntType(mod, scope, old_inst.castTag(.inttype).?),87 .unreachable_safe => return zirUnreachable(mod, scope, old_inst.castTag(.unreachable_safe).?, true),
88 .loop => return analyzeInstLoop(mod, scope, old_inst.castTag(.loop).?),88 .unreachable_unsafe => return zirUnreachable(mod, scope, old_inst.castTag(.unreachable_unsafe).?, false),
89 .param_type => return analyzeInstParamType(mod, scope, old_inst.castTag(.param_type).?),89 .@"return" => return zirReturn(mod, scope, old_inst.castTag(.@"return").?),
90 .ptrtoint => return analyzeInstPtrToInt(mod, scope, old_inst.castTag(.ptrtoint).?),90 .return_void => return zirReturnVoid(mod, scope, old_inst.castTag(.return_void).?),
91 .field_ptr => return fieldPtr(mod, scope, old_inst.castTag(.field_ptr).?),91 .@"fn" => return zirFn(mod, scope, old_inst.castTag(.@"fn").?),
92 .field_val => return fieldVal(mod, scope, old_inst.castTag(.field_val).?),92 .@"export" => return zirExport(mod, scope, old_inst.castTag(.@"export").?),
93 .field_ptr_named => return fieldPtrNamed(mod, scope, old_inst.castTag(.field_ptr_named).?),93 .primitive => return zirPrimitive(mod, scope, old_inst.castTag(.primitive).?),
94 .field_val_named => return fieldValNamed(mod, scope, old_inst.castTag(.field_val_named).?),94 .fntype => return zirFnType(mod, scope, old_inst.castTag(.fntype).?),
95 .deref => return analyzeInstDeref(mod, scope, old_inst.castTag(.deref).?),95 .intcast => return zirIntcast(mod, scope, old_inst.castTag(.intcast).?),
96 .as => return analyzeInstAs(mod, scope, old_inst.castTag(.as).?),96 .bitcast => return zirBitcast(mod, scope, old_inst.castTag(.bitcast).?),
97 .@"asm" => return analyzeInstAsm(mod, scope, old_inst.castTag(.@"asm").?),97 .floatcast => return zirFloatcast(mod, scope, old_inst.castTag(.floatcast).?),
98 .@"unreachable" => return analyzeInstUnreachable(mod, scope, old_inst.castTag(.@"unreachable").?, true),98 .elem_ptr => return zirElemPtr(mod, scope, old_inst.castTag(.elem_ptr).?),
99 .unreach_nocheck => return analyzeInstUnreachable(mod, scope, old_inst.castTag(.unreach_nocheck).?, false),99 .elem_val => return zirElemVal(mod, scope, old_inst.castTag(.elem_val).?),
100 .@"return" => return analyzeInstRet(mod, scope, old_inst.castTag(.@"return").?),100 .add => return zirArithmetic(mod, scope, old_inst.castTag(.add).?),
101 .returnvoid => return analyzeInstRetVoid(mod, scope, old_inst.castTag(.returnvoid).?),101 .addwrap => return zirArithmetic(mod, scope, old_inst.castTag(.addwrap).?),
102 .@"fn" => return analyzeInstFn(mod, scope, old_inst.castTag(.@"fn").?),102 .sub => return zirArithmetic(mod, scope, old_inst.castTag(.sub).?),
103 .@"export" => return analyzeInstExport(mod, scope, old_inst.castTag(.@"export").?),103 .subwrap => return zirArithmetic(mod, scope, old_inst.castTag(.subwrap).?),
104 .primitive => return analyzeInstPrimitive(mod, scope, old_inst.castTag(.primitive).?),104 .mul => return zirArithmetic(mod, scope, old_inst.castTag(.mul).?),
105 .fntype => return analyzeInstFnType(mod, scope, old_inst.castTag(.fntype).?),105 .mulwrap => return zirArithmetic(mod, scope, old_inst.castTag(.mulwrap).?),
106 .intcast => return analyzeInstIntCast(mod, scope, old_inst.castTag(.intcast).?),106 .div => return zirArithmetic(mod, scope, old_inst.castTag(.div).?),
107 .bitcast => return analyzeInstBitCast(mod, scope, old_inst.castTag(.bitcast).?),107 .mod_rem => return zirArithmetic(mod, scope, old_inst.castTag(.mod_rem).?),
108 .floatcast => return analyzeInstFloatCast(mod, scope, old_inst.castTag(.floatcast).?),108 .array_cat => return zirArrayCat(mod, scope, old_inst.castTag(.array_cat).?),
109 .elem_ptr => return elemPtr(mod, scope, old_inst.castTag(.elem_ptr).?),109 .array_mul => return zirArrayMul(mod, scope, old_inst.castTag(.array_mul).?),
110 .elem_val => return elemVal(mod, scope, old_inst.castTag(.elem_val).?),110 .bit_and => return zirBitwise(mod, scope, old_inst.castTag(.bit_and).?),
111 .add => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.add).?),111 .bit_not => return zirBitNot(mod, scope, old_inst.castTag(.bit_not).?),
112 .addwrap => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.addwrap).?),112 .bit_or => return zirBitwise(mod, scope, old_inst.castTag(.bit_or).?),
113 .sub => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.sub).?),113 .xor => return zirBitwise(mod, scope, old_inst.castTag(.xor).?),
114 .subwrap => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.subwrap).?),114 .shl => return zirShl(mod, scope, old_inst.castTag(.shl).?),
115 .mul => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.mul).?),115 .shr => return zirShr(mod, scope, old_inst.castTag(.shr).?),
116 .mulwrap => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.mulwrap).?),116 .cmp_lt => return zirCmp(mod, scope, old_inst.castTag(.cmp_lt).?, .lt),
117 .div => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.div).?),117 .cmp_lte => return zirCmp(mod, scope, old_inst.castTag(.cmp_lte).?, .lte),
118 .mod_rem => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.mod_rem).?),118 .cmp_eq => return zirCmp(mod, scope, old_inst.castTag(.cmp_eq).?, .eq),
119 .array_cat => return analyzeInstArrayCat(mod, scope, old_inst.castTag(.array_cat).?),119 .cmp_gte => return zirCmp(mod, scope, old_inst.castTag(.cmp_gte).?, .gte),
120 .array_mul => return analyzeInstArrayMul(mod, scope, old_inst.castTag(.array_mul).?),120 .cmp_gt => return zirCmp(mod, scope, old_inst.castTag(.cmp_gt).?, .gt),
121 .bitand => return analyzeInstBitwise(mod, scope, old_inst.castTag(.bitand).?),121 .cmp_neq => return zirCmp(mod, scope, old_inst.castTag(.cmp_neq).?, .neq),
122 .bitnot => return analyzeInstBitNot(mod, scope, old_inst.castTag(.bitnot).?),122 .condbr => return zirCondbr(mod, scope, old_inst.castTag(.condbr).?),
123 .bitor => return analyzeInstBitwise(mod, scope, old_inst.castTag(.bitor).?),123 .is_null => return zirIsNull(mod, scope, old_inst.castTag(.is_null).?, false),
124 .xor => return analyzeInstBitwise(mod, scope, old_inst.castTag(.xor).?),124 .is_non_null => return zirIsNull(mod, scope, old_inst.castTag(.is_non_null).?, true),
125 .shl => return analyzeInstShl(mod, scope, old_inst.castTag(.shl).?),125 .is_null_ptr => return zirIsNullPtr(mod, scope, old_inst.castTag(.is_null_ptr).?, false),
126 .shr => return analyzeInstShr(mod, scope, old_inst.castTag(.shr).?),126 .is_non_null_ptr => return zirIsNullPtr(mod, scope, old_inst.castTag(.is_non_null_ptr).?, true),
127 .cmp_lt => return analyzeInstCmp(mod, scope, old_inst.castTag(.cmp_lt).?, .lt),127 .is_err => return zirIsErr(mod, scope, old_inst.castTag(.is_err).?),
128 .cmp_lte => return analyzeInstCmp(mod, scope, old_inst.castTag(.cmp_lte).?, .lte),128 .is_err_ptr => return zirIsErrPtr(mod, scope, old_inst.castTag(.is_err_ptr).?),
129 .cmp_eq => return analyzeInstCmp(mod, scope, old_inst.castTag(.cmp_eq).?, .eq),129 .bool_not => return zirBoolNot(mod, scope, old_inst.castTag(.bool_not).?),
130 .cmp_gte => return analyzeInstCmp(mod, scope, old_inst.castTag(.cmp_gte).?, .gte),130 .typeof => return zirTypeof(mod, scope, old_inst.castTag(.typeof).?),
131 .cmp_gt => return analyzeInstCmp(mod, scope, old_inst.castTag(.cmp_gt).?, .gt),131 .typeof_peer => return zirTypeofPeer(mod, scope, old_inst.castTag(.typeof_peer).?),
132 .cmp_neq => return analyzeInstCmp(mod, scope, old_inst.castTag(.cmp_neq).?, .neq),132 .optional_type => return zirOptionalType(mod, scope, old_inst.castTag(.optional_type).?),
133 .condbr => return analyzeInstCondBr(mod, scope, old_inst.castTag(.condbr).?),133 .optional_payload_safe => return zirOptionalPayload(mod, scope, old_inst.castTag(.optional_payload_safe).?, true),
134 .is_null => return isNull(mod, scope, old_inst.castTag(.is_null).?, false),134 .optional_payload_unsafe => return zirOptionalPayload(mod, scope, old_inst.castTag(.optional_payload_unsafe).?, false),
135 .is_non_null => return isNull(mod, scope, old_inst.castTag(.is_non_null).?, true),135 .optional_payload_safe_ptr => return zirOptionalPayloadPtr(mod, scope, old_inst.castTag(.optional_payload_safe_ptr).?, true),
136 .is_null_ptr => return isNullPtr(mod, scope, old_inst.castTag(.is_null_ptr).?, false),136 .optional_payload_unsafe_ptr => return zirOptionalPayloadPtr(mod, scope, old_inst.castTag(.optional_payload_unsafe_ptr).?, false),
137 .is_non_null_ptr => return isNullPtr(mod, scope, old_inst.castTag(.is_non_null_ptr).?, true),137 .err_union_payload_safe => return zirErrUnionPayload(mod, scope, old_inst.castTag(.err_union_payload_safe).?, true),
138 .is_err => return isErr(mod, scope, old_inst.castTag(.is_err).?),138 .err_union_payload_unsafe => return zirErrUnionPayload(mod, scope, old_inst.castTag(.err_union_payload_unsafe).?, false),
139 .is_err_ptr => return isErrPtr(mod, scope, old_inst.castTag(.is_err_ptr).?),139 .err_union_payload_safe_ptr => return zirErrUnionPayloadPtr(mod, scope, old_inst.castTag(.err_union_payload_safe_ptr).?, true),
140 .boolnot => return analyzeInstBoolNot(mod, scope, old_inst.castTag(.boolnot).?),140 .err_union_payload_unsafe_ptr => return zirErrUnionPayloadPtr(mod, scope, old_inst.castTag(.err_union_payload_unsafe_ptr).?, false),
141 .typeof => return analyzeInstTypeOf(mod, scope, old_inst.castTag(.typeof).?),141 .err_union_code => return zirErrUnionCode(mod, scope, old_inst.castTag(.err_union_code).?),
142 .typeof_peer => return analyzeInstTypeOfPeer(mod, scope, old_inst.castTag(.typeof_peer).?),142 .err_union_code_ptr => return zirErrUnionCodePtr(mod, scope, old_inst.castTag(.err_union_code_ptr).?),
143 .optional_type => return analyzeInstOptionalType(mod, scope, old_inst.castTag(.optional_type).?),143 .ensure_err_payload_void => return zirEnsureErrPayloadVoid(mod, scope, old_inst.castTag(.ensure_err_payload_void).?),
144 .optional_payload_safe => return optionalPayload(mod, scope, old_inst.castTag(.optional_payload_safe).?, true),144 .array_type => return zirArrayType(mod, scope, old_inst.castTag(.array_type).?),
145 .optional_payload_unsafe => return optionalPayload(mod, scope, old_inst.castTag(.optional_payload_unsafe).?, false),145 .array_type_sentinel => return zirArrayTypeSentinel(mod, scope, old_inst.castTag(.array_type_sentinel).?),
146 .optional_payload_safe_ptr => return optionalPayloadPtr(mod, scope, old_inst.castTag(.optional_payload_safe_ptr).?, true),146 .enum_literal => return zirEnumLiteral(mod, scope, old_inst.castTag(.enum_literal).?),
147 .optional_payload_unsafe_ptr => return optionalPayloadPtr(mod, scope, old_inst.castTag(.optional_payload_unsafe_ptr).?, false),147 .merge_error_sets => return zirMergeErrorSets(mod, scope, old_inst.castTag(.merge_error_sets).?),
148 .err_union_payload_safe => return errorUnionPayload(mod, scope, old_inst.castTag(.err_union_payload_safe).?, true),148 .error_union_type => return zirErrorUnionType(mod, scope, old_inst.castTag(.error_union_type).?),
149 .err_union_payload_unsafe => return errorUnionPayload(mod, scope, old_inst.castTag(.err_union_payload_unsafe).?, false),149 .anyframe_type => return zirAnyframeType(mod, scope, old_inst.castTag(.anyframe_type).?),
150 .err_union_payload_safe_ptr => return errorUnionPayloadPtr(mod, scope, old_inst.castTag(.err_union_payload_safe_ptr).?, true),150 .error_set => return zirErrorSet(mod, scope, old_inst.castTag(.error_set).?),
151 .err_union_payload_unsafe_ptr => return errorUnionPayloadPtr(mod, scope, old_inst.castTag(.err_union_payload_unsafe_ptr).?, false),151 .slice => return zirSlice(mod, scope, old_inst.castTag(.slice).?),
152 .err_union_code => return errorUnionCode(mod, scope, old_inst.castTag(.err_union_code).?),152 .slice_start => return zirSliceStart(mod, scope, old_inst.castTag(.slice_start).?),
153 .err_union_code_ptr => return errorUnionCodePtr(mod, scope, old_inst.castTag(.err_union_code_ptr).?),153 .import => return zirImport(mod, scope, old_inst.castTag(.import).?),
154 .ensure_err_payload_void => return analyzeInstEnsureErrPayloadVoid(mod, scope, old_inst.castTag(.ensure_err_payload_void).?),154 .bool_and => return zirBoolOp(mod, scope, old_inst.castTag(.bool_and).?),
155 .array_type => return analyzeInstArrayType(mod, scope, old_inst.castTag(.array_type).?),155 .bool_or => return zirBoolOp(mod, scope, old_inst.castTag(.bool_or).?),
156 .array_type_sentinel => return analyzeInstArrayTypeSentinel(mod, scope, old_inst.castTag(.array_type_sentinel).?),156 .void_value => return mod.constVoid(scope, old_inst.src),
157 .enum_literal => return analyzeInstEnumLiteral(mod, scope, old_inst.castTag(.enum_literal).?),
158 .merge_error_sets => return analyzeInstMergeErrorSets(mod, scope, old_inst.castTag(.merge_error_sets).?),
159 .error_union_type => return analyzeInstErrorUnionType(mod, scope, old_inst.castTag(.error_union_type).?),
160 .anyframe_type => return analyzeInstAnyframeType(mod, scope, old_inst.castTag(.anyframe_type).?),
161 .error_set => return analyzeInstErrorSet(mod, scope, old_inst.castTag(.error_set).?),
162 .slice => return analyzeInstSlice(mod, scope, old_inst.castTag(.slice).?),
163 .slice_start => return analyzeInstSliceStart(mod, scope, old_inst.castTag(.slice_start).?),
164 .import => return analyzeInstImport(mod, scope, old_inst.castTag(.import).?),
165 .switchbr => return analyzeInstSwitchBr(mod, scope, old_inst.castTag(.switchbr).?),
166 .switch_range => return analyzeInstSwitchRange(mod, scope, old_inst.castTag(.switch_range).?),
167 .booland => return analyzeInstBoolOp(mod, scope, old_inst.castTag(.booland).?),
168 .boolor => return analyzeInstBoolOp(mod, scope, old_inst.castTag(.boolor).?),
169157
170 .container_field_named,158 .container_field_named,
171 .container_field_typed,159 .container_field_typed,
...@@ -258,7 +246,7 @@ pub fn resolveInstConst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerE...@@ -258,7 +246,7 @@ pub fn resolveInstConst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerE
258 };246 };
259}247}
260248
261fn analyzeInstConst(mod: *Module, scope: *Scope, const_inst: *zir.Inst.Const) InnerError!*Inst {249fn zirConst(mod: *Module, scope: *Scope, const_inst: *zir.Inst.Const) InnerError!*Inst {
262 const tracy = trace(@src());250 const tracy = trace(@src());
263 defer tracy.end();251 defer tracy.end();
264 // Move the TypedValue from old memory to new memory. This allows freeing the ZIR instructions252 // Move the TypedValue from old memory to new memory. This allows freeing the ZIR instructions
...@@ -275,44 +263,25 @@ fn analyzeConstInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError...@@ -275,44 +263,25 @@ fn analyzeConstInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError
275 };263 };
276}264}
277265
278fn analyzeInstCoerceResultBlockPtr(266fn zirBitcastRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
279 mod: *Module,
280 scope: *Scope,
281 inst: *zir.Inst.CoerceResultBlockPtr,
282) InnerError!*Inst {
283 const tracy = trace(@src());
284 defer tracy.end();
285 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultBlockPtr", .{});
286}
287
288fn bitCastRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
289 const tracy = trace(@src());267 const tracy = trace(@src());
290 defer tracy.end();268 defer tracy.end();
291 return mod.fail(scope, inst.base.src, "TODO implement zir_sema.bitCastRef", .{});269 return mod.fail(scope, inst.base.src, "TODO implement zir_sema.zirBitcastRef", .{});
292}270}
293271
294fn bitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {272fn zirBitcastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
295 const tracy = trace(@src());273 const tracy = trace(@src());
296 defer tracy.end();274 defer tracy.end();
297 return mod.fail(scope, inst.base.src, "TODO implement zir_sema.bitCastResultPtr", .{});275 return mod.fail(scope, inst.base.src, "TODO implement zir_sema.zirBitcastResultPtr", .{});
298}276}
299277
300fn analyzeInstCoerceResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {278fn zirCoerceResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
301 const tracy = trace(@src());279 const tracy = trace(@src());
302 defer tracy.end();280 defer tracy.end();
303 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultPtr", .{});281 return mod.fail(scope, inst.base.src, "TODO implement zirCoerceResultPtr", .{});
304}282}
305283
306/// Equivalent to `as(ptr_child_type(typeof(ptr)), value)`.284fn zirRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
307fn analyzeInstCoerceToPtrElem(mod: *Module, scope: *Scope, inst: *zir.Inst.CoerceToPtrElem) InnerError!*Inst {
308 const tracy = trace(@src());
309 defer tracy.end();
310 const ptr = try resolveInst(mod, scope, inst.positionals.ptr);
311 const operand = try resolveInst(mod, scope, inst.positionals.value);
312 return mod.coerce(scope, ptr.ty.elemType(), operand);
313}
314
315fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
316 const tracy = trace(@src());285 const tracy = trace(@src());
317 defer tracy.end();286 defer tracy.end();
318 const b = try mod.requireFunctionBlock(scope, inst.base.src);287 const b = try mod.requireFunctionBlock(scope, inst.base.src);
...@@ -322,7 +291,7 @@ fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerErr...@@ -322,7 +291,7 @@ fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerErr
322 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);291 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
323}292}
324293
325fn ref(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {294fn zirRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
326 const tracy = trace(@src());295 const tracy = trace(@src());
327 defer tracy.end();296 defer tracy.end();
328297
...@@ -330,7 +299,7 @@ fn ref(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {...@@ -330,7 +299,7 @@ fn ref(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
330 return mod.analyzeRef(scope, inst.base.src, operand);299 return mod.analyzeRef(scope, inst.base.src, operand);
331}300}
332301
333fn analyzeInstRetType(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {302fn zirRetType(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
334 const tracy = trace(@src());303 const tracy = trace(@src());
335 defer tracy.end();304 defer tracy.end();
336 const b = try mod.requireFunctionBlock(scope, inst.base.src);305 const b = try mod.requireFunctionBlock(scope, inst.base.src);
...@@ -339,7 +308,7 @@ fn analyzeInstRetType(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerEr...@@ -339,7 +308,7 @@ fn analyzeInstRetType(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerEr
339 return mod.constType(scope, inst.base.src, ret_type);308 return mod.constType(scope, inst.base.src, ret_type);
340}309}
341310
342fn analyzeInstEnsureResultUsed(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {311fn zirEnsureResultUsed(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
343 const tracy = trace(@src());312 const tracy = trace(@src());
344 defer tracy.end();313 defer tracy.end();
345 const operand = try resolveInst(mod, scope, inst.positionals.operand);314 const operand = try resolveInst(mod, scope, inst.positionals.operand);
...@@ -349,7 +318,7 @@ fn analyzeInstEnsureResultUsed(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp...@@ -349,7 +318,7 @@ fn analyzeInstEnsureResultUsed(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp
349 }318 }
350}319}
351320
352fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {321fn zirEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
353 const tracy = trace(@src());322 const tracy = trace(@src());
354 defer tracy.end();323 defer tracy.end();
355 const operand = try resolveInst(mod, scope, inst.positionals.operand);324 const operand = try resolveInst(mod, scope, inst.positionals.operand);
...@@ -359,7 +328,7 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst....@@ -359,7 +328,7 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.
359 }328 }
360}329}
361330
362fn indexablePtrLen(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {331fn zirIndexablePtrLen(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
363 const tracy = trace(@src());332 const tracy = trace(@src());
364 defer tracy.end();333 defer tracy.end();
365334
...@@ -389,7 +358,7 @@ fn indexablePtrLen(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError...@@ -389,7 +358,7 @@ fn indexablePtrLen(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError
389 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);358 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);
390}359}
391360
392fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {361fn zirAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
393 const tracy = trace(@src());362 const tracy = trace(@src());
394 defer tracy.end();363 defer tracy.end();
395 const var_type = try resolveType(mod, scope, inst.positionals.operand);364 const var_type = try resolveType(mod, scope, inst.positionals.operand);
...@@ -398,7 +367,7 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro...@@ -398,7 +367,7 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro
398 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);367 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
399}368}
400369
401fn analyzeInstAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {370fn zirAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
402 const tracy = trace(@src());371 const tracy = trace(@src());
403 defer tracy.end();372 defer tracy.end();
404 const var_type = try resolveType(mod, scope, inst.positionals.operand);373 const var_type = try resolveType(mod, scope, inst.positionals.operand);
...@@ -408,7 +377,7 @@ fn analyzeInstAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerE...@@ -408,7 +377,7 @@ fn analyzeInstAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerE
408 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);377 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
409}378}
410379
411fn analyzeInstAllocInferred(380fn zirAllocInferred(
412 mod: *Module,381 mod: *Module,
413 scope: *Scope,382 scope: *Scope,
414 inst: *zir.Inst.NoOp,383 inst: *zir.Inst.NoOp,
...@@ -437,7 +406,7 @@ fn analyzeInstAllocInferred(...@@ -437,7 +406,7 @@ fn analyzeInstAllocInferred(
437 return result;406 return result;
438}407}
439408
440fn analyzeInstResolveInferredAlloc(409fn zirResolveInferredAlloc(
441 mod: *Module,410 mod: *Module,
442 scope: *Scope,411 scope: *Scope,
443 inst: *zir.Inst.UnOp,412 inst: *zir.Inst.UnOp,
...@@ -466,28 +435,46 @@ fn analyzeInstResolveInferredAlloc(...@@ -466,28 +435,46 @@ fn analyzeInstResolveInferredAlloc(
466 return mod.constVoid(scope, inst.base.src);435 return mod.constVoid(scope, inst.base.src);
467}436}
468437
469fn analyzeInstStoreToInferredPtr(438fn zirStoreToBlockPtr(
470 mod: *Module,439 mod: *Module,
471 scope: *Scope,440 scope: *Scope,
472 inst: *zir.Inst.BinOp,441 inst: *zir.Inst.BinOp,
473) InnerError!*Inst {442) InnerError!*Inst {
474 const tracy = trace(@src());443 const tracy = trace(@src());
475 defer tracy.end();444 defer tracy.end();
445
446 const ptr = try resolveInst(mod, scope, inst.positionals.lhs);
447 const value = try resolveInst(mod, scope, inst.positionals.rhs);
448 const ptr_ty = try mod.simplePtrType(scope, inst.base.src, value.ty, true, .One);
449 // TODO detect when this store should be done at compile-time. For example,
450 // if expressions should force it when the condition is compile-time known.
451 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
452 const bitcasted_ptr = try mod.addUnOp(b, inst.base.src, ptr_ty, .bitcast, ptr);
453 return mod.storePtr(scope, inst.base.src, bitcasted_ptr, value);
454}
455
456fn zirStoreToInferredPtr(
457 mod: *Module,
458 scope: *Scope,
459 inst: *zir.Inst.BinOp,
460) InnerError!*Inst {
461 const tracy = trace(@src());
462 defer tracy.end();
463
476 const ptr = try resolveInst(mod, scope, inst.positionals.lhs);464 const ptr = try resolveInst(mod, scope, inst.positionals.lhs);
477 const value = try resolveInst(mod, scope, inst.positionals.rhs);465 const value = try resolveInst(mod, scope, inst.positionals.rhs);
478 const inferred_alloc = ptr.castTag(.constant).?.val.castTag(.inferred_alloc).?;466 const inferred_alloc = ptr.castTag(.constant).?.val.castTag(.inferred_alloc).?;
479 // Add the stored instruction to the set we will use to resolve peer types467 // Add the stored instruction to the set we will use to resolve peer types
480 // for the inferred allocation.468 // for the inferred allocation.
481 try inferred_alloc.data.stored_inst_list.append(scope.arena(), value);469 try inferred_alloc.data.stored_inst_list.append(scope.arena(), value);
482 // Create a new alloc with exactly the type the pointer wants.470 // Create a runtime bitcast instruction with exactly the type the pointer wants.
483 // Later it gets cleaned up by aliasing the alloc we are supposed to be storing to.
484 const ptr_ty = try mod.simplePtrType(scope, inst.base.src, value.ty, true, .One);471 const ptr_ty = try mod.simplePtrType(scope, inst.base.src, value.ty, true, .One);
485 const b = try mod.requireRuntimeBlock(scope, inst.base.src);472 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
486 const bitcasted_ptr = try mod.addUnOp(b, inst.base.src, ptr_ty, .bitcast, ptr);473 const bitcasted_ptr = try mod.addUnOp(b, inst.base.src, ptr_ty, .bitcast, ptr);
487 return mod.storePtr(scope, inst.base.src, bitcasted_ptr, value);474 return mod.storePtr(scope, inst.base.src, bitcasted_ptr, value);
488}475}
489476
490fn analyzeInstSetEvalBranchQuota(477fn zirSetEvalBranchQuota(
491 mod: *Module,478 mod: *Module,
492 scope: *Scope,479 scope: *Scope,
493 inst: *zir.Inst.UnOp,480 inst: *zir.Inst.UnOp,
...@@ -499,15 +486,16 @@ fn analyzeInstSetEvalBranchQuota(...@@ -499,15 +486,16 @@ fn analyzeInstSetEvalBranchQuota(
499 return mod.constVoid(scope, inst.base.src);486 return mod.constVoid(scope, inst.base.src);
500}487}
501488
502fn analyzeInstStore(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {489fn zirStore(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
503 const tracy = trace(@src());490 const tracy = trace(@src());
504 defer tracy.end();491 defer tracy.end();
492
505 const ptr = try resolveInst(mod, scope, inst.positionals.lhs);493 const ptr = try resolveInst(mod, scope, inst.positionals.lhs);
506 const value = try resolveInst(mod, scope, inst.positionals.rhs);494 const value = try resolveInst(mod, scope, inst.positionals.rhs);
507 return mod.storePtr(scope, inst.base.src, ptr, value);495 return mod.storePtr(scope, inst.base.src, ptr, value);
508}496}
509497
510fn analyzeInstParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType) InnerError!*Inst {498fn zirParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType) InnerError!*Inst {
511 const tracy = trace(@src());499 const tracy = trace(@src());
512 defer tracy.end();500 defer tracy.end();
513 const fn_inst = try resolveInst(mod, scope, inst.positionals.func);501 const fn_inst = try resolveInst(mod, scope, inst.positionals.func);
...@@ -516,7 +504,7 @@ fn analyzeInstParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType)...@@ -516,7 +504,7 @@ fn analyzeInstParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType)
516 const fn_ty: Type = switch (fn_inst.ty.zigTypeTag()) {504 const fn_ty: Type = switch (fn_inst.ty.zigTypeTag()) {
517 .Fn => fn_inst.ty,505 .Fn => fn_inst.ty,
518 .BoundFn => {506 .BoundFn => {
519 return mod.fail(scope, fn_inst.src, "TODO implement analyzeInstParamType for method call syntax", .{});507 return mod.fail(scope, fn_inst.src, "TODO implement zirParamType for method call syntax", .{});
520 },508 },
521 else => {509 else => {
522 return mod.fail(scope, fn_inst.src, "expected function, found '{}'", .{fn_inst.ty});510 return mod.fail(scope, fn_inst.src, "expected function, found '{}'", .{fn_inst.ty});
...@@ -538,7 +526,7 @@ fn analyzeInstParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType)...@@ -538,7 +526,7 @@ fn analyzeInstParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType)
538 return mod.constType(scope, inst.base.src, param_type);526 return mod.constType(scope, inst.base.src, param_type);
539}527}
540528
541fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerError!*Inst {529fn zirStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerError!*Inst {
542 const tracy = trace(@src());530 const tracy = trace(@src());
543 defer tracy.end();531 defer tracy.end();
544 // The bytes references memory inside the ZIR module, which can get deallocated532 // The bytes references memory inside the ZIR module, which can get deallocated
...@@ -557,14 +545,14 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr...@@ -557,14 +545,14 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr
557 return mod.analyzeDeclRef(scope, str_inst.base.src, new_decl);545 return mod.analyzeDeclRef(scope, str_inst.base.src, new_decl);
558}546}
559547
560fn analyzeInstInt(mod: *Module, scope: *Scope, inst: *zir.Inst.Int) InnerError!*Inst {548fn zirInt(mod: *Module, scope: *Scope, inst: *zir.Inst.Int) InnerError!*Inst {
561 const tracy = trace(@src());549 const tracy = trace(@src());
562 defer tracy.end();550 defer tracy.end();
563551
564 return mod.constIntBig(scope, inst.base.src, Type.initTag(.comptime_int), inst.positionals.int);552 return mod.constIntBig(scope, inst.base.src, Type.initTag(.comptime_int), inst.positionals.int);
565}553}
566554
567fn analyzeInstExport(mod: *Module, scope: *Scope, export_inst: *zir.Inst.Export) InnerError!*Inst {555fn zirExport(mod: *Module, scope: *Scope, export_inst: *zir.Inst.Export) InnerError!*Inst {
568 const tracy = trace(@src());556 const tracy = trace(@src());
569 defer tracy.end();557 defer tracy.end();
570 const symbol_name = try resolveConstString(mod, scope, export_inst.positionals.symbol_name);558 const symbol_name = try resolveConstString(mod, scope, export_inst.positionals.symbol_name);
...@@ -574,14 +562,14 @@ fn analyzeInstExport(mod: *Module, scope: *Scope, export_inst: *zir.Inst.Export)...@@ -574,14 +562,14 @@ fn analyzeInstExport(mod: *Module, scope: *Scope, export_inst: *zir.Inst.Export)
574 return mod.constVoid(scope, export_inst.base.src);562 return mod.constVoid(scope, export_inst.base.src);
575}563}
576564
577fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {565fn zirCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
578 const tracy = trace(@src());566 const tracy = trace(@src());
579 defer tracy.end();567 defer tracy.end();
580 const msg = try resolveConstString(mod, scope, inst.positionals.operand);568 const msg = try resolveConstString(mod, scope, inst.positionals.operand);
581 return mod.fail(scope, inst.base.src, "{s}", .{msg});569 return mod.fail(scope, inst.base.src, "{s}", .{msg});
582}570}
583571
584fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog) InnerError!*Inst {572fn zirCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog) InnerError!*Inst {
585 var managed = mod.compile_log_text.toManaged(mod.gpa);573 var managed = mod.compile_log_text.toManaged(mod.gpa);
586 defer mod.compile_log_text = managed.moveToUnmanaged();574 defer mod.compile_log_text = managed.moveToUnmanaged();
587 const writer = managed.writer();575 const writer = managed.writer();
...@@ -608,7 +596,7 @@ fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog...@@ -608,7 +596,7 @@ fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog
608 return mod.constVoid(scope, inst.base.src);596 return mod.constVoid(scope, inst.base.src);
609}597}
610598
611fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {599fn zirArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {
612 const tracy = trace(@src());600 const tracy = trace(@src());
613 defer tracy.end();601 defer tracy.end();
614 const b = try mod.requireFunctionBlock(scope, inst.base.src);602 const b = try mod.requireFunctionBlock(scope, inst.base.src);
...@@ -631,7 +619,7 @@ fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*...@@ -631,7 +619,7 @@ fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*
631 return mod.addArg(b, inst.base.src, param_type, name);619 return mod.addArg(b, inst.base.src, param_type, name);
632}620}
633621
634fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError!*Inst {622fn zirLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError!*Inst {
635 const tracy = trace(@src());623 const tracy = trace(@src());
636 defer tracy.end();624 defer tracy.end();
637 const parent_block = scope.cast(Scope.Block).?;625 const parent_block = scope.cast(Scope.Block).?;
...@@ -672,25 +660,14 @@ fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError...@@ -672,25 +660,14 @@ fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError
672 return &loop_inst.base;660 return &loop_inst.base;
673}661}
674662
675fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_comptime: bool) InnerError!*Inst {663fn zirBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_comptime: bool) InnerError!*Inst {
676 const tracy = trace(@src());664 const tracy = trace(@src());
677 defer tracy.end();665 defer tracy.end();
678 const parent_block = scope.cast(Scope.Block).?;666 const parent_block = scope.cast(Scope.Block).?;
679667
680 var child_block: Scope.Block = .{668 var child_block = parent_block.makeSubBlock();
681 .parent = parent_block,
682 .inst_table = parent_block.inst_table,
683 .func = parent_block.func,
684 .owner_decl = parent_block.owner_decl,
685 .src_decl = parent_block.src_decl,
686 .instructions = .{},
687 .arena = parent_block.arena,
688 .label = null,
689 .inlining = parent_block.inlining,
690 .is_comptime = parent_block.is_comptime or is_comptime,
691 .branch_quota = parent_block.branch_quota,
692 };
693 defer child_block.instructions.deinit(mod.gpa);669 defer child_block.instructions.deinit(mod.gpa);
670 child_block.is_comptime = child_block.is_comptime or is_comptime;
694671
695 try analyzeBody(mod, &child_block, inst.positionals.body);672 try analyzeBody(mod, &child_block, inst.positionals.body);
696673
...@@ -704,9 +681,15 @@ fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_c...@@ -704,9 +681,15 @@ fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_c
704 return resolveInst(mod, scope, last_zir_inst);681 return resolveInst(mod, scope, last_zir_inst);
705}682}
706683
707fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_comptime: bool) InnerError!*Inst {684fn zirBlock(
685 mod: *Module,
686 scope: *Scope,
687 inst: *zir.Inst.Block,
688 is_comptime: bool,
689) InnerError!*Inst {
708 const tracy = trace(@src());690 const tracy = trace(@src());
709 defer tracy.end();691 defer tracy.end();
692
710 const parent_block = scope.cast(Scope.Block).?;693 const parent_block = scope.cast(Scope.Block).?;
711694
712 // Reserve space for a Block instruction so that generated Break instructions can695 // Reserve space for a Block instruction so that generated Break instructions can
...@@ -735,6 +718,7 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_compt...@@ -735,6 +718,7 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_compt
735 .zir_block = inst,718 .zir_block = inst,
736 .merges = .{719 .merges = .{
737 .results = .{},720 .results = .{},
721 .br_list = .{},
738 .block_inst = block_inst,722 .block_inst = block_inst,
739 },723 },
740 }),724 }),
...@@ -746,6 +730,7 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_compt...@@ -746,6 +730,7 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_compt
746730
747 defer child_block.instructions.deinit(mod.gpa);731 defer child_block.instructions.deinit(mod.gpa);
748 defer merges.results.deinit(mod.gpa);732 defer merges.results.deinit(mod.gpa);
733 defer merges.br_list.deinit(mod.gpa);
749734
750 try analyzeBody(mod, &child_block, inst.positionals.body);735 try analyzeBody(mod, &child_block, inst.positionals.body);
751736
...@@ -779,49 +764,127 @@ fn analyzeBlockBody(...@@ -779,49 +764,127 @@ fn analyzeBlockBody(
779 const last_inst = child_block.instructions.items[last_inst_index];764 const last_inst = child_block.instructions.items[last_inst_index];
780 if (last_inst.breakBlock()) |br_block| {765 if (last_inst.breakBlock()) |br_block| {
781 if (br_block == merges.block_inst) {766 if (br_block == merges.block_inst) {
782 // No need for a block instruction. We can put the new instructions directly into the parent block.767 // No need for a block instruction. We can put the new instructions directly
783 // Here we omit the break instruction.768 // into the parent block. Here we omit the break instruction.
784 const copied_instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items[0..last_inst_index]);769 const copied_instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items[0..last_inst_index]);
785 try parent_block.instructions.appendSlice(mod.gpa, copied_instructions);770 try parent_block.instructions.appendSlice(mod.gpa, copied_instructions);
786 return merges.results.items[0];771 return merges.results.items[0];
787 }772 }
788 }773 }
789 }774 }
790 // It should be impossible to have the number of results be > 1 in a comptime scope.775 // It is impossible to have the number of results be > 1 in a comptime scope.
791 assert(!child_block.is_comptime); // We should have already got a compile error in the condbr condition.776 assert(!child_block.is_comptime); // Should already got a compile error in the condbr condition.
792777
793 // Need to set the type and emit the Block instruction. This allows machine code generation778 // Need to set the type and emit the Block instruction. This allows machine code generation
794 // to emit a jump instruction to after the block when it encounters the break.779 // to emit a jump instruction to after the block when it encounters the break.
795 try parent_block.instructions.append(mod.gpa, &merges.block_inst.base);780 try parent_block.instructions.append(mod.gpa, &merges.block_inst.base);
796 merges.block_inst.base.ty = try mod.resolvePeerTypes(scope, merges.results.items);781 const resolved_ty = try mod.resolvePeerTypes(scope, merges.results.items);
797 merges.block_inst.body = .{ .instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items) };782 merges.block_inst.base.ty = resolved_ty;
783 merges.block_inst.body = .{
784 .instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items),
785 };
786 // Now that the block has its type resolved, we need to go back into all the break
787 // instructions, and insert type coercion on the operands.
788 for (merges.br_list.items) |br| {
789 if (br.operand.ty.eql(resolved_ty)) {
790 // No type coercion needed.
791 continue;
792 }
793 var coerce_block = parent_block.makeSubBlock();
794 defer coerce_block.instructions.deinit(mod.gpa);
795 const coerced_operand = try mod.coerce(&coerce_block.base, resolved_ty, br.operand);
796 // If no instructions were produced, such as in the case of a coercion of a
797 // constant value to a new type, we can simply point the br operand to it.
798 if (coerce_block.instructions.items.len == 0) {
799 br.operand = coerced_operand;
800 continue;
801 }
802 assert(coerce_block.instructions.items[coerce_block.instructions.items.len - 1] == coerced_operand);
803 // Here we depend on the br instruction having been over-allocated (if necessary)
804 // inide analyzeBreak so that it can be converted into a br_block_flat instruction.
805 const br_src = br.base.src;
806 const br_ty = br.base.ty;
807 const br_block_flat = @ptrCast(*Inst.BrBlockFlat, br);
808 br_block_flat.* = .{
809 .base = .{
810 .src = br_src,
811 .ty = br_ty,
812 .tag = .br_block_flat,
813 },
814 .block = merges.block_inst,
815 .body = .{
816 .instructions = try parent_block.arena.dupe(*Inst, coerce_block.instructions.items),
817 },
818 };
819 }
798 return &merges.block_inst.base;820 return &merges.block_inst.base;
799}821}
800822
801fn analyzeInstBreakpoint(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {823fn zirBreakpoint(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
802 const tracy = trace(@src());824 const tracy = trace(@src());
803 defer tracy.end();825 defer tracy.end();
804 const b = try mod.requireRuntimeBlock(scope, inst.base.src);826 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
805 return mod.addNoOp(b, inst.base.src, Type.initTag(.void), .breakpoint);827 return mod.addNoOp(b, inst.base.src, Type.initTag(.void), .breakpoint);
806}828}
807829
808fn analyzeInstBreak(mod: *Module, scope: *Scope, inst: *zir.Inst.Break) InnerError!*Inst {830fn zirBreak(mod: *Module, scope: *Scope, inst: *zir.Inst.Break) InnerError!*Inst {
809 const tracy = trace(@src());831 const tracy = trace(@src());
810 defer tracy.end();832 defer tracy.end();
833
811 const operand = try resolveInst(mod, scope, inst.positionals.operand);834 const operand = try resolveInst(mod, scope, inst.positionals.operand);
812 const block = inst.positionals.block;835 const block = inst.positionals.block;
813 return analyzeBreak(mod, scope, inst.base.src, block, operand);836 return analyzeBreak(mod, scope, inst.base.src, block, operand);
814}837}
815838
816fn analyzeInstBreakVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.BreakVoid) InnerError!*Inst {839fn zirBreakVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.BreakVoid) InnerError!*Inst {
817 const tracy = trace(@src());840 const tracy = trace(@src());
818 defer tracy.end();841 defer tracy.end();
842
819 const block = inst.positionals.block;843 const block = inst.positionals.block;
820 const void_inst = try mod.constVoid(scope, inst.base.src);844 const void_inst = try mod.constVoid(scope, inst.base.src);
821 return analyzeBreak(mod, scope, inst.base.src, block, void_inst);845 return analyzeBreak(mod, scope, inst.base.src, block, void_inst);
822}846}
823847
824fn analyzeInstDbgStmt(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {848fn analyzeBreak(
849 mod: *Module,
850 scope: *Scope,
851 src: usize,
852 zir_block: *zir.Inst.Block,
853 operand: *Inst,
854) InnerError!*Inst {
855 var opt_block = scope.cast(Scope.Block);
856 while (opt_block) |block| {
857 if (block.label) |*label| {
858 if (label.zir_block == zir_block) {
859 const b = try mod.requireFunctionBlock(scope, src);
860 // Here we add a br instruction, but we over-allocate a little bit
861 // (if necessary) to make it possible to convert the instruction into
862 // a br_block_flat instruction later.
863 const br = @ptrCast(*Inst.Br, try b.arena.alignedAlloc(
864 u8,
865 Inst.convertable_br_align,
866 Inst.convertable_br_size,
867 ));
868 br.* = .{
869 .base = .{
870 .tag = .br,
871 .ty = Type.initTag(.noreturn),
872 .src = src,
873 },
874 .operand = operand,
875 .block = label.merges.block_inst,
876 };
877 try b.instructions.append(mod.gpa, &br.base);
878 try label.merges.results.append(mod.gpa, operand);
879 try label.merges.br_list.append(mod.gpa, br);
880 return &br.base;
881 }
882 }
883 opt_block = block.parent;
884 } else unreachable;
885}
886
887fn zirDbgStmt(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
825 const tracy = trace(@src());888 const tracy = trace(@src());
826 defer tracy.end();889 defer tracy.end();
827 if (scope.cast(Scope.Block)) |b| {890 if (scope.cast(Scope.Block)) |b| {
...@@ -832,26 +895,26 @@ fn analyzeInstDbgStmt(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerEr...@@ -832,26 +895,26 @@ fn analyzeInstDbgStmt(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerEr
832 return mod.constVoid(scope, inst.base.src);895 return mod.constVoid(scope, inst.base.src);
833}896}
834897
835fn analyzeInstDeclRefStr(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr) InnerError!*Inst {898fn zirDeclRefStr(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr) InnerError!*Inst {
836 const tracy = trace(@src());899 const tracy = trace(@src());
837 defer tracy.end();900 defer tracy.end();
838 const decl_name = try resolveConstString(mod, scope, inst.positionals.name);901 const decl_name = try resolveConstString(mod, scope, inst.positionals.name);
839 return mod.analyzeDeclRefByName(scope, inst.base.src, decl_name);902 return mod.analyzeDeclRefByName(scope, inst.base.src, decl_name);
840}903}
841904
842fn declRef(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRef) InnerError!*Inst {905fn zirDeclRef(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRef) InnerError!*Inst {
843 const tracy = trace(@src());906 const tracy = trace(@src());
844 defer tracy.end();907 defer tracy.end();
845 return mod.analyzeDeclRef(scope, inst.base.src, inst.positionals.decl);908 return mod.analyzeDeclRef(scope, inst.base.src, inst.positionals.decl);
846}909}
847910
848fn declVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerError!*Inst {911fn zirDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerError!*Inst {
849 const tracy = trace(@src());912 const tracy = trace(@src());
850 defer tracy.end();913 defer tracy.end();
851 return mod.analyzeDeclVal(scope, inst.base.src, inst.positionals.decl);914 return mod.analyzeDeclVal(scope, inst.base.src, inst.positionals.decl);
852}915}
853916
854fn call(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {917fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
855 const tracy = trace(@src());918 const tracy = trace(@src());
856 defer tracy.end();919 defer tracy.end();
857920
...@@ -965,6 +1028,7 @@ fn call(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {...@@ -965,6 +1028,7 @@ fn call(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
965 .casted_args = casted_args,1028 .casted_args = casted_args,
966 .merges = .{1029 .merges = .{
967 .results = .{},1030 .results = .{},
1031 .br_list = .{},
968 .block_inst = block_inst,1032 .block_inst = block_inst,
969 },1033 },
970 };1034 };
...@@ -989,6 +1053,7 @@ fn call(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {...@@ -989,6 +1053,7 @@ fn call(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
9891053
990 defer child_block.instructions.deinit(mod.gpa);1054 defer child_block.instructions.deinit(mod.gpa);
991 defer merges.results.deinit(mod.gpa);1055 defer merges.results.deinit(mod.gpa);
1056 defer merges.br_list.deinit(mod.gpa);
9921057
993 try mod.emitBackwardBranch(&child_block, inst.base.src);1058 try mod.emitBackwardBranch(&child_block, inst.base.src);
9941059
...@@ -1002,7 +1067,7 @@ fn call(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {...@@ -1002,7 +1067,7 @@ fn call(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
1002 return mod.addCall(b, inst.base.src, ret_type, func, casted_args);1067 return mod.addCall(b, inst.base.src, ret_type, func, casted_args);
1003}1068}
10041069
1005fn analyzeInstFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {1070fn zirFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {
1006 const tracy = trace(@src());1071 const tracy = trace(@src());
1007 defer tracy.end();1072 defer tracy.end();
1008 const fn_type = try resolveType(mod, scope, fn_inst.positionals.fn_type);1073 const fn_type = try resolveType(mod, scope, fn_inst.positionals.fn_type);
...@@ -1019,13 +1084,13 @@ fn analyzeInstFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!...@@ -1019,13 +1084,13 @@ fn analyzeInstFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!
1019 });1084 });
1020}1085}
10211086
1022fn analyzeInstIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst {1087fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst {
1023 const tracy = trace(@src());1088 const tracy = trace(@src());
1024 defer tracy.end();1089 defer tracy.end();
1025 return mod.fail(scope, inttype.base.src, "TODO implement inttype", .{});1090 return mod.fail(scope, inttype.base.src, "TODO implement inttype", .{});
1026}1091}
10271092
1028fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp) InnerError!*Inst {1093fn zirOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp) InnerError!*Inst {
1029 const tracy = trace(@src());1094 const tracy = trace(@src());
1030 defer tracy.end();1095 defer tracy.end();
1031 const child_type = try resolveType(mod, scope, optional.positionals.operand);1096 const child_type = try resolveType(mod, scope, optional.positionals.operand);
...@@ -1033,7 +1098,7 @@ fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp...@@ -1033,7 +1098,7 @@ fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp
1033 return mod.constType(scope, optional.base.src, try mod.optionalType(scope, child_type));1098 return mod.constType(scope, optional.base.src, try mod.optionalType(scope, child_type));
1034}1099}
10351100
1036fn analyzeInstArrayType(mod: *Module, scope: *Scope, array: *zir.Inst.BinOp) InnerError!*Inst {1101fn zirArrayType(mod: *Module, scope: *Scope, array: *zir.Inst.BinOp) InnerError!*Inst {
1037 const tracy = trace(@src());1102 const tracy = trace(@src());
1038 defer tracy.end();1103 defer tracy.end();
1039 // TODO these should be lazily evaluated1104 // TODO these should be lazily evaluated
...@@ -1043,7 +1108,7 @@ fn analyzeInstArrayType(mod: *Module, scope: *Scope, array: *zir.Inst.BinOp) Inn...@@ -1043,7 +1108,7 @@ fn analyzeInstArrayType(mod: *Module, scope: *Scope, array: *zir.Inst.BinOp) Inn
1043 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), null, elem_type));1108 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), null, elem_type));
1044}1109}
10451110
1046fn analyzeInstArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.ArrayTypeSentinel) InnerError!*Inst {1111fn zirArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.ArrayTypeSentinel) InnerError!*Inst {
1047 const tracy = trace(@src());1112 const tracy = trace(@src());
1048 defer tracy.end();1113 defer tracy.end();
1049 // TODO these should be lazily evaluated1114 // TODO these should be lazily evaluated
...@@ -1054,7 +1119,7 @@ fn analyzeInstArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.Ar...@@ -1054,7 +1119,7 @@ fn analyzeInstArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.Ar
1054 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), sentinel.val, elem_type));1119 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), sentinel.val, elem_type));
1055}1120}
10561121
1057fn analyzeInstErrorUnionType(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1122fn zirErrorUnionType(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1058 const tracy = trace(@src());1123 const tracy = trace(@src());
1059 defer tracy.end();1124 defer tracy.end();
1060 const error_union = try resolveType(mod, scope, inst.positionals.lhs);1125 const error_union = try resolveType(mod, scope, inst.positionals.lhs);
...@@ -1067,7 +1132,7 @@ fn analyzeInstErrorUnionType(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp)...@@ -1067,7 +1132,7 @@ fn analyzeInstErrorUnionType(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp)
1067 return mod.constType(scope, inst.base.src, try mod.errorUnionType(scope, error_union, payload));1132 return mod.constType(scope, inst.base.src, try mod.errorUnionType(scope, error_union, payload));
1068}1133}
10691134
1070fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {1135fn zirAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1071 const tracy = trace(@src());1136 const tracy = trace(@src());
1072 defer tracy.end();1137 defer tracy.end();
1073 const return_type = try resolveType(mod, scope, inst.positionals.operand);1138 const return_type = try resolveType(mod, scope, inst.positionals.operand);
...@@ -1075,7 +1140,7 @@ fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In...@@ -1075,7 +1140,7 @@ fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In
1075 return mod.constType(scope, inst.base.src, try mod.anyframeType(scope, return_type));1140 return mod.constType(scope, inst.base.src, try mod.anyframeType(scope, return_type));
1076}1141}
10771142
1078fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError!*Inst {1143fn zirErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError!*Inst {
1079 const tracy = trace(@src());1144 const tracy = trace(@src());
1080 defer tracy.end();1145 defer tracy.end();
1081 // The declarations arena will store the hashmap.1146 // The declarations arena will store the hashmap.
...@@ -1107,13 +1172,13 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In...@@ -1107,13 +1172,13 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
1107 return mod.analyzeDeclVal(scope, inst.base.src, new_decl);1172 return mod.analyzeDeclVal(scope, inst.base.src, new_decl);
1108}1173}
11091174
1110fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1175fn zirMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1111 const tracy = trace(@src());1176 const tracy = trace(@src());
1112 defer tracy.end();1177 defer tracy.end();
1113 return mod.fail(scope, inst.base.src, "TODO implement merge_error_sets", .{});1178 return mod.fail(scope, inst.base.src, "TODO implement merge_error_sets", .{});
1114}1179}
11151180
1116fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {1181fn zirEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
1117 const tracy = trace(@src());1182 const tracy = trace(@src());
1118 defer tracy.end();1183 defer tracy.end();
1119 const duped_name = try scope.arena().dupe(u8, inst.positionals.name);1184 const duped_name = try scope.arena().dupe(u8, inst.positionals.name);
...@@ -1124,7 +1189,7 @@ fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiter...@@ -1124,7 +1189,7 @@ fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiter
1124}1189}
11251190
1126/// Pointer in, pointer out.1191/// Pointer in, pointer out.
1127fn optionalPayloadPtr(1192fn zirOptionalPayloadPtr(
1128 mod: *Module,1193 mod: *Module,
1129 scope: *Scope,1194 scope: *Scope,
1130 unwrap: *zir.Inst.UnOp,1195 unwrap: *zir.Inst.UnOp,
...@@ -1165,7 +1230,7 @@ fn optionalPayloadPtr(...@@ -1165,7 +1230,7 @@ fn optionalPayloadPtr(
1165}1230}
11661231
1167/// Value in, value out.1232/// Value in, value out.
1168fn optionalPayload(1233fn zirOptionalPayload(
1169 mod: *Module,1234 mod: *Module,
1170 scope: *Scope,1235 scope: *Scope,
1171 unwrap: *zir.Inst.UnOp,1236 unwrap: *zir.Inst.UnOp,
...@@ -1201,40 +1266,40 @@ fn optionalPayload(...@@ -1201,40 +1266,40 @@ fn optionalPayload(
1201}1266}
12021267
1203/// Value in, value out1268/// Value in, value out
1204fn errorUnionPayload(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst {1269fn zirErrUnionPayload(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst {
1205 const tracy = trace(@src());1270 const tracy = trace(@src());
1206 defer tracy.end();1271 defer tracy.end();
1207 return mod.fail(scope, unwrap.base.src, "TODO implement zir_sema.errorUnionPayload", .{});1272 return mod.fail(scope, unwrap.base.src, "TODO implement zir_sema.zirErrUnionPayload", .{});
1208}1273}
12091274
1210/// Pointer in, pointer out1275/// Pointer in, pointer out
1211fn errorUnionPayloadPtr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst {1276fn zirErrUnionPayloadPtr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst {
1212 const tracy = trace(@src());1277 const tracy = trace(@src());
1213 defer tracy.end();1278 defer tracy.end();
1214 return mod.fail(scope, unwrap.base.src, "TODO implement zir_sema.errorUnionPayloadPtr", .{});1279 return mod.fail(scope, unwrap.base.src, "TODO implement zir_sema.zirErrUnionPayloadPtr", .{});
1215}1280}
12161281
1217/// Value in, value out1282/// Value in, value out
1218fn errorUnionCode(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst {1283fn zirErrUnionCode(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst {
1219 const tracy = trace(@src());1284 const tracy = trace(@src());
1220 defer tracy.end();1285 defer tracy.end();
1221 return mod.fail(scope, unwrap.base.src, "TODO implement zir_sema.errorUnionCode", .{});1286 return mod.fail(scope, unwrap.base.src, "TODO implement zir_sema.zirErrUnionCode", .{});
1222}1287}
12231288
1224/// Pointer in, value out1289/// Pointer in, value out
1225fn errorUnionCodePtr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst {1290fn zirErrUnionCodePtr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst {
1226 const tracy = trace(@src());1291 const tracy = trace(@src());
1227 defer tracy.end();1292 defer tracy.end();
1228 return mod.fail(scope, unwrap.base.src, "TODO implement zir_sema.errorUnionCodePtr", .{});1293 return mod.fail(scope, unwrap.base.src, "TODO implement zir_sema.zirErrUnionCodePtr", .{});
1229}1294}
12301295
1231fn analyzeInstEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst {1296fn zirEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst {
1232 const tracy = trace(@src());1297 const tracy = trace(@src());
1233 defer tracy.end();1298 defer tracy.end();
1234 return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstEnsureErrPayloadVoid", .{});1299 return mod.fail(scope, unwrap.base.src, "TODO implement zirEnsureErrPayloadVoid", .{});
1235}1300}
12361301
1237fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {1302fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {
1238 const tracy = trace(@src());1303 const tracy = trace(@src());
1239 defer tracy.end();1304 defer tracy.end();
1240 const return_type = try resolveType(mod, scope, fntype.positionals.return_type);1305 const return_type = try resolveType(mod, scope, fntype.positionals.return_type);
...@@ -1277,13 +1342,13 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne...@@ -1277,13 +1342,13 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne
1277 return mod.constType(scope, fntype.base.src, fn_ty);1342 return mod.constType(scope, fntype.base.src, fn_ty);
1278}1343}
12791344
1280fn analyzeInstPrimitive(mod: *Module, scope: *Scope, primitive: *zir.Inst.Primitive) InnerError!*Inst {1345fn zirPrimitive(mod: *Module, scope: *Scope, primitive: *zir.Inst.Primitive) InnerError!*Inst {
1281 const tracy = trace(@src());1346 const tracy = trace(@src());
1282 defer tracy.end();1347 defer tracy.end();
1283 return mod.constInst(scope, primitive.base.src, primitive.positionals.tag.toTypedValue());1348 return mod.constInst(scope, primitive.base.src, primitive.positionals.tag.toTypedValue());
1284}1349}
12851350
1286fn analyzeInstAs(mod: *Module, scope: *Scope, as: *zir.Inst.BinOp) InnerError!*Inst {1351fn zirAs(mod: *Module, scope: *Scope, as: *zir.Inst.BinOp) InnerError!*Inst {
1287 const tracy = trace(@src());1352 const tracy = trace(@src());
1288 defer tracy.end();1353 defer tracy.end();
1289 const dest_type = try resolveType(mod, scope, as.positionals.lhs);1354 const dest_type = try resolveType(mod, scope, as.positionals.lhs);
...@@ -1291,7 +1356,7 @@ fn analyzeInstAs(mod: *Module, scope: *Scope, as: *zir.Inst.BinOp) InnerError!*I...@@ -1291,7 +1356,7 @@ fn analyzeInstAs(mod: *Module, scope: *Scope, as: *zir.Inst.BinOp) InnerError!*I
1291 return mod.coerce(scope, dest_type, new_inst);1356 return mod.coerce(scope, dest_type, new_inst);
1292}1357}
12931358
1294fn analyzeInstPtrToInt(mod: *Module, scope: *Scope, ptrtoint: *zir.Inst.UnOp) InnerError!*Inst {1359fn zirPtrtoint(mod: *Module, scope: *Scope, ptrtoint: *zir.Inst.UnOp) InnerError!*Inst {
1295 const tracy = trace(@src());1360 const tracy = trace(@src());
1296 defer tracy.end();1361 defer tracy.end();
1297 const ptr = try resolveInst(mod, scope, ptrtoint.positionals.operand);1362 const ptr = try resolveInst(mod, scope, ptrtoint.positionals.operand);
...@@ -1304,7 +1369,7 @@ fn analyzeInstPtrToInt(mod: *Module, scope: *Scope, ptrtoint: *zir.Inst.UnOp) In...@@ -1304,7 +1369,7 @@ fn analyzeInstPtrToInt(mod: *Module, scope: *Scope, ptrtoint: *zir.Inst.UnOp) In
1304 return mod.addUnOp(b, ptrtoint.base.src, ty, .ptrtoint, ptr);1369 return mod.addUnOp(b, ptrtoint.base.src, ty, .ptrtoint, ptr);
1305}1370}
13061371
1307fn fieldVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst {1372fn zirFieldVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst {
1308 const tracy = trace(@src());1373 const tracy = trace(@src());
1309 defer tracy.end();1374 defer tracy.end();
13101375
...@@ -1315,7 +1380,7 @@ fn fieldVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst...@@ -1315,7 +1380,7 @@ fn fieldVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst
1315 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);1380 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);
1316}1381}
13171382
1318fn fieldPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst {1383fn zirFieldPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst {
1319 const tracy = trace(@src());1384 const tracy = trace(@src());
1320 defer tracy.end();1385 defer tracy.end();
13211386
...@@ -1324,7 +1389,7 @@ fn fieldPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst...@@ -1324,7 +1389,7 @@ fn fieldPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst
1324 return mod.namedFieldPtr(scope, inst.base.src, object_ptr, field_name, inst.base.src);1389 return mod.namedFieldPtr(scope, inst.base.src, object_ptr, field_name, inst.base.src);
1325}1390}
13261391
1327fn fieldValNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerError!*Inst {1392fn zirFieldValNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerError!*Inst {
1328 const tracy = trace(@src());1393 const tracy = trace(@src());
1329 defer tracy.end();1394 defer tracy.end();
13301395
...@@ -1336,7 +1401,7 @@ fn fieldValNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerE...@@ -1336,7 +1401,7 @@ fn fieldValNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerE
1336 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);1401 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);
1337}1402}
13381403
1339fn fieldPtrNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerError!*Inst {1404fn zirFieldPtrNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerError!*Inst {
1340 const tracy = trace(@src());1405 const tracy = trace(@src());
1341 defer tracy.end();1406 defer tracy.end();
13421407
...@@ -1346,7 +1411,7 @@ fn fieldPtrNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerE...@@ -1346,7 +1411,7 @@ fn fieldPtrNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerE
1346 return mod.namedFieldPtr(scope, inst.base.src, object_ptr, field_name, fsrc);1411 return mod.namedFieldPtr(scope, inst.base.src, object_ptr, field_name, fsrc);
1347}1412}
13481413
1349fn analyzeInstIntCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1414fn zirIntcast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1350 const tracy = trace(@src());1415 const tracy = trace(@src());
1351 defer tracy.end();1416 defer tracy.end();
1352 const dest_type = try resolveType(mod, scope, inst.positionals.lhs);1417 const dest_type = try resolveType(mod, scope, inst.positionals.lhs);
...@@ -1384,7 +1449,7 @@ fn analyzeInstIntCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE...@@ -1384,7 +1449,7 @@ fn analyzeInstIntCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE
1384 return mod.fail(scope, inst.base.src, "TODO implement analyze widen or shorten int", .{});1449 return mod.fail(scope, inst.base.src, "TODO implement analyze widen or shorten int", .{});
1385}1450}
13861451
1387fn analyzeInstBitCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1452fn zirBitcast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1388 const tracy = trace(@src());1453 const tracy = trace(@src());
1389 defer tracy.end();1454 defer tracy.end();
1390 const dest_type = try resolveType(mod, scope, inst.positionals.lhs);1455 const dest_type = try resolveType(mod, scope, inst.positionals.lhs);
...@@ -1392,7 +1457,7 @@ fn analyzeInstBitCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE...@@ -1392,7 +1457,7 @@ fn analyzeInstBitCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE
1392 return mod.bitcast(scope, dest_type, operand);1457 return mod.bitcast(scope, dest_type, operand);
1393}1458}
13941459
1395fn analyzeInstFloatCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1460fn zirFloatcast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1396 const tracy = trace(@src());1461 const tracy = trace(@src());
1397 defer tracy.end();1462 defer tracy.end();
1398 const dest_type = try resolveType(mod, scope, inst.positionals.lhs);1463 const dest_type = try resolveType(mod, scope, inst.positionals.lhs);
...@@ -1430,7 +1495,7 @@ fn analyzeInstFloatCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inne...@@ -1430,7 +1495,7 @@ fn analyzeInstFloatCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inne
1430 return mod.fail(scope, inst.base.src, "TODO implement analyze widen or shorten float", .{});1495 return mod.fail(scope, inst.base.src, "TODO implement analyze widen or shorten float", .{});
1431}1496}
14321497
1433fn elemVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {1498fn zirElemVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {
1434 const tracy = trace(@src());1499 const tracy = trace(@src());
1435 defer tracy.end();1500 defer tracy.end();
14361501
...@@ -1441,7 +1506,7 @@ fn elemVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {...@@ -1441,7 +1506,7 @@ fn elemVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {
1441 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);1506 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);
1442}1507}
14431508
1444fn elemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {1509fn zirElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {
1445 const tracy = trace(@src());1510 const tracy = trace(@src());
1446 defer tracy.end();1511 defer tracy.end();
14471512
...@@ -1450,7 +1515,7 @@ fn elemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {...@@ -1450,7 +1515,7 @@ fn elemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {
1450 return mod.elemPtr(scope, inst.base.src, array_ptr, elem_index);1515 return mod.elemPtr(scope, inst.base.src, array_ptr, elem_index);
1451}1516}
14521517
1453fn analyzeInstSlice(mod: *Module, scope: *Scope, inst: *zir.Inst.Slice) InnerError!*Inst {1518fn zirSlice(mod: *Module, scope: *Scope, inst: *zir.Inst.Slice) InnerError!*Inst {
1454 const tracy = trace(@src());1519 const tracy = trace(@src());
1455 defer tracy.end();1520 defer tracy.end();
1456 const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr);1521 const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr);
...@@ -1461,7 +1526,7 @@ fn analyzeInstSlice(mod: *Module, scope: *Scope, inst: *zir.Inst.Slice) InnerErr...@@ -1461,7 +1526,7 @@ fn analyzeInstSlice(mod: *Module, scope: *Scope, inst: *zir.Inst.Slice) InnerErr
1461 return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, end, sentinel);1526 return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, end, sentinel);
1462}1527}
14631528
1464fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1529fn zirSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1465 const tracy = trace(@src());1530 const tracy = trace(@src());
1466 defer tracy.end();1531 defer tracy.end();
1467 const array_ptr = try resolveInst(mod, scope, inst.positionals.lhs);1532 const array_ptr = try resolveInst(mod, scope, inst.positionals.lhs);
...@@ -1470,235 +1535,7 @@ fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inn...@@ -1470,235 +1535,7 @@ fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inn
1470 return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, null, null);1535 return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, null, null);
1471}1536}
14721537
1473fn analyzeInstSwitchRange(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1538fn zirImport(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1474 const tracy = trace(@src());
1475 defer tracy.end();
1476 const start = try resolveInst(mod, scope, inst.positionals.lhs);
1477 const end = try resolveInst(mod, scope, inst.positionals.rhs);
1478
1479 switch (start.ty.zigTypeTag()) {
1480 .Int, .ComptimeInt => {},
1481 else => return mod.constVoid(scope, inst.base.src),
1482 }
1483 switch (end.ty.zigTypeTag()) {
1484 .Int, .ComptimeInt => {},
1485 else => return mod.constVoid(scope, inst.base.src),
1486 }
1487 if (start.value()) |start_val| {
1488 if (end.value()) |end_val| {
1489 if (start_val.compare(.gte, end_val)) {
1490 return mod.fail(scope, inst.base.src, "range start value must be smaller than the end value", .{});
1491 }
1492 }
1493 }
1494 return mod.constVoid(scope, inst.base.src);
1495}
1496
1497fn analyzeInstSwitchBr(mod: *Module, scope: *Scope, inst: *zir.Inst.SwitchBr) InnerError!*Inst {
1498 const tracy = trace(@src());
1499 defer tracy.end();
1500 const target_ptr = try resolveInst(mod, scope, inst.positionals.target_ptr);
1501 const target = try mod.analyzeDeref(scope, inst.base.src, target_ptr, inst.positionals.target_ptr.src);
1502 try validateSwitch(mod, scope, target, inst);
1503
1504 if (try mod.resolveDefinedValue(scope, target)) |target_val| {
1505 for (inst.positionals.cases) |case| {
1506 const resolved = try resolveInst(mod, scope, case.item);
1507 const casted = try mod.coerce(scope, target.ty, resolved);
1508 const item = try mod.resolveConstValue(scope, casted);
1509
1510 if (target_val.eql(item)) {
1511 try analyzeBody(mod, scope.cast(Scope.Block).?, case.body);
1512 return mod.constNoReturn(scope, inst.base.src);
1513 }
1514 }
1515 try analyzeBody(mod, scope.cast(Scope.Block).?, inst.positionals.else_body);
1516 return mod.constNoReturn(scope, inst.base.src);
1517 }
1518
1519 if (inst.positionals.cases.len == 0) {
1520 // no cases just analyze else_branch
1521 try analyzeBody(mod, scope.cast(Scope.Block).?, inst.positionals.else_body);
1522 return mod.constNoReturn(scope, inst.base.src);
1523 }
1524
1525 const parent_block = try mod.requireRuntimeBlock(scope, inst.base.src);
1526 const cases = try parent_block.arena.alloc(Inst.SwitchBr.Case, inst.positionals.cases.len);
1527
1528 var case_block: Scope.Block = .{
1529 .parent = parent_block,
1530 .inst_table = parent_block.inst_table,
1531 .func = parent_block.func,
1532 .owner_decl = parent_block.owner_decl,
1533 .src_decl = parent_block.src_decl,
1534 .instructions = .{},
1535 .arena = parent_block.arena,
1536 .inlining = parent_block.inlining,
1537 .is_comptime = parent_block.is_comptime,
1538 .branch_quota = parent_block.branch_quota,
1539 };
1540 defer case_block.instructions.deinit(mod.gpa);
1541
1542 for (inst.positionals.cases) |case, i| {
1543 // Reset without freeing.
1544 case_block.instructions.items.len = 0;
1545
1546 const resolved = try resolveInst(mod, scope, case.item);
1547 const casted = try mod.coerce(scope, target.ty, resolved);
1548 const item = try mod.resolveConstValue(scope, casted);
1549
1550 try analyzeBody(mod, &case_block, case.body);
1551
1552 cases[i] = .{
1553 .item = item,
1554 .body = .{ .instructions = try parent_block.arena.dupe(*Inst, case_block.instructions.items) },
1555 };
1556 }
1557
1558 case_block.instructions.items.len = 0;
1559 try analyzeBody(mod, &case_block, inst.positionals.else_body);
1560
1561 const else_body: ir.Body = .{
1562 .instructions = try parent_block.arena.dupe(*Inst, case_block.instructions.items),
1563 };
1564
1565 return mod.addSwitchBr(parent_block, inst.base.src, target_ptr, cases, else_body);
1566}
1567
1568fn validateSwitch(mod: *Module, scope: *Scope, target: *Inst, inst: *zir.Inst.SwitchBr) InnerError!void {
1569 // validate usage of '_' prongs
1570 if (inst.kw_args.special_prong == .underscore and target.ty.zigTypeTag() != .Enum) {
1571 return mod.fail(scope, inst.base.src, "'_' prong only allowed when switching on non-exhaustive enums", .{});
1572 // TODO notes "'_' prong here" inst.positionals.cases[last].src
1573 }
1574
1575 // check that target type supports ranges
1576 if (inst.kw_args.range) |range_inst| {
1577 switch (target.ty.zigTypeTag()) {
1578 .Int, .ComptimeInt => {},
1579 else => {
1580 return mod.fail(scope, target.src, "ranges not allowed when switching on type {}", .{target.ty});
1581 // TODO notes "range used here" range_inst.src
1582 },
1583 }
1584 }
1585
1586 // validate for duplicate items/missing else prong
1587 switch (target.ty.zigTypeTag()) {
1588 .Enum => return mod.fail(scope, inst.base.src, "TODO validateSwitch .Enum", .{}),
1589 .ErrorSet => return mod.fail(scope, inst.base.src, "TODO validateSwitch .ErrorSet", .{}),
1590 .Union => return mod.fail(scope, inst.base.src, "TODO validateSwitch .Union", .{}),
1591 .Int, .ComptimeInt => {
1592 var range_set = @import("RangeSet.zig").init(mod.gpa);
1593 defer range_set.deinit();
1594
1595 for (inst.positionals.items) |item| {
1596 const maybe_src = if (item.castTag(.switch_range)) |range| blk: {
1597 const start_resolved = try resolveInst(mod, scope, range.positionals.lhs);
1598 const start_casted = try mod.coerce(scope, target.ty, start_resolved);
1599 const end_resolved = try resolveInst(mod, scope, range.positionals.rhs);
1600 const end_casted = try mod.coerce(scope, target.ty, end_resolved);
1601
1602 break :blk try range_set.add(
1603 try mod.resolveConstValue(scope, start_casted),
1604 try mod.resolveConstValue(scope, end_casted),
1605 item.src,
1606 );
1607 } else blk: {
1608 const resolved = try resolveInst(mod, scope, item);
1609 const casted = try mod.coerce(scope, target.ty, resolved);
1610 const value = try mod.resolveConstValue(scope, casted);
1611 break :blk try range_set.add(value, value, item.src);
1612 };
1613
1614 if (maybe_src) |previous_src| {
1615 return mod.fail(scope, item.src, "duplicate switch value", .{});
1616 // TODO notes "previous value is here" previous_src
1617 }
1618 }
1619
1620 if (target.ty.zigTypeTag() == .Int) {
1621 var arena = std.heap.ArenaAllocator.init(mod.gpa);
1622 defer arena.deinit();
1623
1624 const start = try target.ty.minInt(&arena, mod.getTarget());
1625 const end = try target.ty.maxInt(&arena, mod.getTarget());
1626 if (try range_set.spans(start, end)) {
1627 if (inst.kw_args.special_prong == .@"else") {
1628 return mod.fail(scope, inst.base.src, "unreachable else prong, all cases already handled", .{});
1629 }
1630 return;
1631 }
1632 }
1633
1634 if (inst.kw_args.special_prong != .@"else") {
1635 return mod.fail(scope, inst.base.src, "switch must handle all possibilities", .{});
1636 }
1637 },
1638 .Bool => {
1639 var true_count: u8 = 0;
1640 var false_count: u8 = 0;
1641 for (inst.positionals.items) |item| {
1642 const resolved = try resolveInst(mod, scope, item);
1643 const casted = try mod.coerce(scope, Type.initTag(.bool), resolved);
1644 if ((try mod.resolveConstValue(scope, casted)).toBool()) {
1645 true_count += 1;
1646 } else {
1647 false_count += 1;
1648 }
1649
1650 if (true_count + false_count > 2) {
1651 return mod.fail(scope, item.src, "duplicate switch value", .{});
1652 }
1653 }
1654 if ((true_count + false_count < 2) and inst.kw_args.special_prong != .@"else") {
1655 return mod.fail(scope, inst.base.src, "switch must handle all possibilities", .{});
1656 }
1657 if ((true_count + false_count == 2) and inst.kw_args.special_prong == .@"else") {
1658 return mod.fail(scope, inst.base.src, "unreachable else prong, all cases already handled", .{});
1659 }
1660 },
1661 .EnumLiteral, .Void, .Fn, .Pointer, .Type => {
1662 if (inst.kw_args.special_prong != .@"else") {
1663 return mod.fail(scope, inst.base.src, "else prong required when switching on type '{}'", .{target.ty});
1664 }
1665
1666 var seen_values = std.HashMap(Value, usize, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage).init(mod.gpa);
1667 defer seen_values.deinit();
1668
1669 for (inst.positionals.items) |item| {
1670 const resolved = try resolveInst(mod, scope, item);
1671 const casted = try mod.coerce(scope, target.ty, resolved);
1672 const val = try mod.resolveConstValue(scope, casted);
1673
1674 if (try seen_values.fetchPut(val, item.src)) |prev| {
1675 return mod.fail(scope, item.src, "duplicate switch value", .{});
1676 // TODO notes "previous value here" prev.value
1677 }
1678 }
1679 },
1680
1681 .ErrorUnion,
1682 .NoReturn,
1683 .Array,
1684 .Struct,
1685 .Undefined,
1686 .Null,
1687 .Optional,
1688 .BoundFn,
1689 .Opaque,
1690 .Vector,
1691 .Frame,
1692 .AnyFrame,
1693 .ComptimeFloat,
1694 .Float,
1695 => {
1696 return mod.fail(scope, target.src, "invalid switch target type '{}'", .{target.ty});
1697 },
1698 }
1699}
1700
1701fn analyzeInstImport(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1702 const tracy = trace(@src());1539 const tracy = trace(@src());
1703 defer tracy.end();1540 defer tracy.end();
1704 const operand = try resolveConstString(mod, scope, inst.positionals.operand);1541 const operand = try resolveConstString(mod, scope, inst.positionals.operand);
...@@ -1718,19 +1555,19 @@ fn analyzeInstImport(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErr...@@ -1718,19 +1555,19 @@ fn analyzeInstImport(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErr
1718 return mod.constType(scope, inst.base.src, file_scope.root_container.ty);1555 return mod.constType(scope, inst.base.src, file_scope.root_container.ty);
1719}1556}
17201557
1721fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1558fn zirShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1722 const tracy = trace(@src());1559 const tracy = trace(@src());
1723 defer tracy.end();1560 defer tracy.end();
1724 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstShl", .{});1561 return mod.fail(scope, inst.base.src, "TODO implement zirShl", .{});
1725}1562}
17261563
1727fn analyzeInstShr(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1564fn zirShr(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1728 const tracy = trace(@src());1565 const tracy = trace(@src());
1729 defer tracy.end();1566 defer tracy.end();
1730 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstShr", .{});1567 return mod.fail(scope, inst.base.src, "TODO implement zirShr", .{});
1731}1568}
17321569
1733fn analyzeInstBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1570fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1734 const tracy = trace(@src());1571 const tracy = trace(@src());
1735 defer tracy.end();1572 defer tracy.end();
17361573
...@@ -1784,8 +1621,8 @@ fn analyzeInstBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE...@@ -1784,8 +1621,8 @@ fn analyzeInstBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE
17841621
1785 const b = try mod.requireRuntimeBlock(scope, inst.base.src);1622 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
1786 const ir_tag = switch (inst.base.tag) {1623 const ir_tag = switch (inst.base.tag) {
1787 .bitand => Inst.Tag.bitand,1624 .bit_and => Inst.Tag.bit_and,
1788 .bitor => Inst.Tag.bitor,1625 .bit_or => Inst.Tag.bit_or,
1789 .xor => Inst.Tag.xor,1626 .xor => Inst.Tag.xor,
1790 else => unreachable,1627 else => unreachable,
1791 };1628 };
...@@ -1793,25 +1630,25 @@ fn analyzeInstBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE...@@ -1793,25 +1630,25 @@ fn analyzeInstBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE
1793 return mod.addBinOp(b, inst.base.src, scalar_type, ir_tag, casted_lhs, casted_rhs);1630 return mod.addBinOp(b, inst.base.src, scalar_type, ir_tag, casted_lhs, casted_rhs);
1794}1631}
17951632
1796fn analyzeInstBitNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {1633fn zirBitNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1797 const tracy = trace(@src());1634 const tracy = trace(@src());
1798 defer tracy.end();1635 defer tracy.end();
1799 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitNot", .{});1636 return mod.fail(scope, inst.base.src, "TODO implement zirBitNot", .{});
1800}1637}
18011638
1802fn analyzeInstArrayCat(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1639fn zirArrayCat(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1803 const tracy = trace(@src());1640 const tracy = trace(@src());
1804 defer tracy.end();1641 defer tracy.end();
1805 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstArrayCat", .{});1642 return mod.fail(scope, inst.base.src, "TODO implement zirArrayCat", .{});
1806}1643}
18071644
1808fn analyzeInstArrayMul(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1645fn zirArrayMul(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1809 const tracy = trace(@src());1646 const tracy = trace(@src());
1810 defer tracy.end();1647 defer tracy.end();
1811 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstArrayMul", .{});1648 return mod.fail(scope, inst.base.src, "TODO implement zirArrayMul", .{});
1812}1649}
18131650
1814fn analyzeInstArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1651fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1815 const tracy = trace(@src());1652 const tracy = trace(@src());
1816 defer tracy.end();1653 defer tracy.end();
18171654
...@@ -1912,14 +1749,14 @@ fn analyzeInstComptimeOp(mod: *Module, scope: *Scope, res_type: Type, inst: *zir...@@ -1912,14 +1749,14 @@ fn analyzeInstComptimeOp(mod: *Module, scope: *Scope, res_type: Type, inst: *zir
1912 });1749 });
1913}1750}
19141751
1915fn analyzeInstDeref(mod: *Module, scope: *Scope, deref: *zir.Inst.UnOp) InnerError!*Inst {1752fn zirDeref(mod: *Module, scope: *Scope, deref: *zir.Inst.UnOp) InnerError!*Inst {
1916 const tracy = trace(@src());1753 const tracy = trace(@src());
1917 defer tracy.end();1754 defer tracy.end();
1918 const ptr = try resolveInst(mod, scope, deref.positionals.operand);1755 const ptr = try resolveInst(mod, scope, deref.positionals.operand);
1919 return mod.analyzeDeref(scope, deref.base.src, ptr, deref.positionals.operand.src);1756 return mod.analyzeDeref(scope, deref.base.src, ptr, deref.positionals.operand.src);
1920}1757}
19211758
1922fn analyzeInstAsm(mod: *Module, scope: *Scope, assembly: *zir.Inst.Asm) InnerError!*Inst {1759fn zirAsm(mod: *Module, scope: *Scope, assembly: *zir.Inst.Asm) InnerError!*Inst {
1923 const tracy = trace(@src());1760 const tracy = trace(@src());
1924 defer tracy.end();1761 defer tracy.end();
1925 const return_type = try resolveType(mod, scope, assembly.positionals.return_type);1762 const return_type = try resolveType(mod, scope, assembly.positionals.return_type);
...@@ -1960,7 +1797,7 @@ fn analyzeInstAsm(mod: *Module, scope: *Scope, assembly: *zir.Inst.Asm) InnerErr...@@ -1960,7 +1797,7 @@ fn analyzeInstAsm(mod: *Module, scope: *Scope, assembly: *zir.Inst.Asm) InnerErr
1960 return &inst.base;1797 return &inst.base;
1961}1798}
19621799
1963fn analyzeInstCmp(1800fn zirCmp(
1964 mod: *Module,1801 mod: *Module,
1965 scope: *Scope,1802 scope: *Scope,
1966 inst: *zir.Inst.BinOp,1803 inst: *zir.Inst.BinOp,
...@@ -2018,14 +1855,14 @@ fn analyzeInstCmp(...@@ -2018,14 +1855,14 @@ fn analyzeInstCmp(
2018 return mod.fail(scope, inst.base.src, "TODO implement more cmp analysis", .{});1855 return mod.fail(scope, inst.base.src, "TODO implement more cmp analysis", .{});
2019}1856}
20201857
2021fn analyzeInstTypeOf(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {1858fn zirTypeof(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
2022 const tracy = trace(@src());1859 const tracy = trace(@src());
2023 defer tracy.end();1860 defer tracy.end();
2024 const operand = try resolveInst(mod, scope, inst.positionals.operand);1861 const operand = try resolveInst(mod, scope, inst.positionals.operand);
2025 return mod.constType(scope, inst.base.src, operand.ty);1862 return mod.constType(scope, inst.base.src, operand.ty);
2026}1863}
20271864
2028fn analyzeInstTypeOfPeer(mod: *Module, scope: *Scope, inst: *zir.Inst.TypeOfPeer) InnerError!*Inst {1865fn zirTypeofPeer(mod: *Module, scope: *Scope, inst: *zir.Inst.TypeOfPeer) InnerError!*Inst {
2029 const tracy = trace(@src());1866 const tracy = trace(@src());
2030 defer tracy.end();1867 defer tracy.end();
2031 var insts_to_res = try mod.gpa.alloc(*ir.Inst, inst.positionals.items.len);1868 var insts_to_res = try mod.gpa.alloc(*ir.Inst, inst.positionals.items.len);
...@@ -2037,7 +1874,7 @@ fn analyzeInstTypeOfPeer(mod: *Module, scope: *Scope, inst: *zir.Inst.TypeOfPeer...@@ -2037,7 +1874,7 @@ fn analyzeInstTypeOfPeer(mod: *Module, scope: *Scope, inst: *zir.Inst.TypeOfPeer
2037 return mod.constType(scope, inst.base.src, pt_res);1874 return mod.constType(scope, inst.base.src, pt_res);
2038}1875}
20391876
2040fn analyzeInstBoolNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {1877fn zirBoolNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
2041 const tracy = trace(@src());1878 const tracy = trace(@src());
2042 defer tracy.end();1879 defer tracy.end();
2043 const uncasted_operand = try resolveInst(mod, scope, inst.positionals.operand);1880 const uncasted_operand = try resolveInst(mod, scope, inst.positionals.operand);
...@@ -2050,7 +1887,7 @@ fn analyzeInstBoolNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerEr...@@ -2050,7 +1887,7 @@ fn analyzeInstBoolNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerEr
2050 return mod.addUnOp(b, inst.base.src, bool_type, .not, operand);1887 return mod.addUnOp(b, inst.base.src, bool_type, .not, operand);
2051}1888}
20521889
2053fn analyzeInstBoolOp(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1890fn zirBoolOp(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
2054 const tracy = trace(@src());1891 const tracy = trace(@src());
2055 defer tracy.end();1892 defer tracy.end();
2056 const bool_type = Type.initTag(.bool);1893 const bool_type = Type.initTag(.bool);
...@@ -2059,7 +1896,7 @@ fn analyzeInstBoolOp(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerEr...@@ -2059,7 +1896,7 @@ fn analyzeInstBoolOp(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerEr
2059 const uncasted_rhs = try resolveInst(mod, scope, inst.positionals.rhs);1896 const uncasted_rhs = try resolveInst(mod, scope, inst.positionals.rhs);
2060 const rhs = try mod.coerce(scope, bool_type, uncasted_rhs);1897 const rhs = try mod.coerce(scope, bool_type, uncasted_rhs);
20611898
2062 const is_bool_or = inst.base.tag == .boolor;1899 const is_bool_or = inst.base.tag == .bool_or;
20631900
2064 if (lhs.value()) |lhs_val| {1901 if (lhs.value()) |lhs_val| {
2065 if (rhs.value()) |rhs_val| {1902 if (rhs.value()) |rhs_val| {
...@@ -2071,17 +1908,17 @@ fn analyzeInstBoolOp(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerEr...@@ -2071,17 +1908,17 @@ fn analyzeInstBoolOp(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerEr
2071 }1908 }
2072 }1909 }
2073 const b = try mod.requireRuntimeBlock(scope, inst.base.src);1910 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
2074 return mod.addBinOp(b, inst.base.src, bool_type, if (is_bool_or) .boolor else .booland, lhs, rhs);1911 return mod.addBinOp(b, inst.base.src, bool_type, if (is_bool_or) .bool_or else .bool_and, lhs, rhs);
2075}1912}
20761913
2077fn isNull(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, invert_logic: bool) InnerError!*Inst {1914fn zirIsNull(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, invert_logic: bool) InnerError!*Inst {
2078 const tracy = trace(@src());1915 const tracy = trace(@src());
2079 defer tracy.end();1916 defer tracy.end();
2080 const operand = try resolveInst(mod, scope, inst.positionals.operand);1917 const operand = try resolveInst(mod, scope, inst.positionals.operand);
2081 return mod.analyzeIsNull(scope, inst.base.src, operand, invert_logic);1918 return mod.analyzeIsNull(scope, inst.base.src, operand, invert_logic);
2082}1919}
20831920
2084fn isNullPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, invert_logic: bool) InnerError!*Inst {1921fn zirIsNullPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, invert_logic: bool) InnerError!*Inst {
2085 const tracy = trace(@src());1922 const tracy = trace(@src());
2086 defer tracy.end();1923 defer tracy.end();
2087 const ptr = try resolveInst(mod, scope, inst.positionals.operand);1924 const ptr = try resolveInst(mod, scope, inst.positionals.operand);
...@@ -2089,14 +1926,14 @@ fn isNullPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, invert_logic: bo...@@ -2089,14 +1926,14 @@ fn isNullPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, invert_logic: bo
2089 return mod.analyzeIsNull(scope, inst.base.src, loaded, invert_logic);1926 return mod.analyzeIsNull(scope, inst.base.src, loaded, invert_logic);
2090}1927}
20911928
2092fn isErr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {1929fn zirIsErr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
2093 const tracy = trace(@src());1930 const tracy = trace(@src());
2094 defer tracy.end();1931 defer tracy.end();
2095 const operand = try resolveInst(mod, scope, inst.positionals.operand);1932 const operand = try resolveInst(mod, scope, inst.positionals.operand);
2096 return mod.analyzeIsErr(scope, inst.base.src, operand);1933 return mod.analyzeIsErr(scope, inst.base.src, operand);
2097}1934}
20981935
2099fn isErrPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {1936fn zirIsErrPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
2100 const tracy = trace(@src());1937 const tracy = trace(@src());
2101 defer tracy.end();1938 defer tracy.end();
2102 const ptr = try resolveInst(mod, scope, inst.positionals.operand);1939 const ptr = try resolveInst(mod, scope, inst.positionals.operand);
...@@ -2104,7 +1941,7 @@ fn isErrPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst...@@ -2104,7 +1941,7 @@ fn isErrPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst
2104 return mod.analyzeIsErr(scope, inst.base.src, loaded);1941 return mod.analyzeIsErr(scope, inst.base.src, loaded);
2105}1942}
21061943
2107fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerError!*Inst {1944fn zirCondbr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerError!*Inst {
2108 const tracy = trace(@src());1945 const tracy = trace(@src());
2109 defer tracy.end();1946 defer tracy.end();
2110 const uncasted_cond = try resolveInst(mod, scope, inst.positionals.condition);1947 const uncasted_cond = try resolveInst(mod, scope, inst.positionals.condition);
...@@ -2153,7 +1990,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE...@@ -2153,7 +1990,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE
2153 return mod.addCondBr(parent_block, inst.base.src, cond, then_body, else_body);1990 return mod.addCondBr(parent_block, inst.base.src, cond, then_body, else_body);
2154}1991}
21551992
2156fn analyzeInstUnreachable(1993fn zirUnreachable(
2157 mod: *Module,1994 mod: *Module,
2158 scope: *Scope,1995 scope: *Scope,
2159 unreach: *zir.Inst.NoOp,1996 unreach: *zir.Inst.NoOp,
...@@ -2170,7 +2007,7 @@ fn analyzeInstUnreachable(...@@ -2170,7 +2007,7 @@ fn analyzeInstUnreachable(
2170 }2007 }
2171}2008}
21722009
2173fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {2010fn zirReturn(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
2174 const tracy = trace(@src());2011 const tracy = trace(@src());
2175 defer tracy.end();2012 defer tracy.end();
2176 const operand = try resolveInst(mod, scope, inst.positionals.operand);2013 const operand = try resolveInst(mod, scope, inst.positionals.operand);
...@@ -2179,13 +2016,14 @@ fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!...@@ -2179,13 +2016,14 @@ fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!
2179 if (b.inlining) |inlining| {2016 if (b.inlining) |inlining| {
2180 // We are inlining a function call; rewrite the `ret` as a `break`.2017 // We are inlining a function call; rewrite the `ret` as a `break`.
2181 try inlining.merges.results.append(mod.gpa, operand);2018 try inlining.merges.results.append(mod.gpa, operand);
2182 return mod.addBr(b, inst.base.src, inlining.merges.block_inst, operand);2019 const br = try mod.addBr(b, inst.base.src, inlining.merges.block_inst, operand);
2020 return &br.base;
2183 }2021 }
21842022
2185 return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, operand);2023 return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, operand);
2186}2024}
21872025
2188fn analyzeInstRetVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {2026fn zirReturnVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
2189 const tracy = trace(@src());2027 const tracy = trace(@src());
2190 defer tracy.end();2028 defer tracy.end();
2191 const b = try mod.requireFunctionBlock(scope, inst.base.src);2029 const b = try mod.requireFunctionBlock(scope, inst.base.src);
...@@ -2193,7 +2031,8 @@ fn analyzeInstRetVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerEr...@@ -2193,7 +2031,8 @@ fn analyzeInstRetVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerEr
2193 // We are inlining a function call; rewrite the `retvoid` as a `breakvoid`.2031 // We are inlining a function call; rewrite the `retvoid` as a `breakvoid`.
2194 const void_inst = try mod.constVoid(scope, inst.base.src);2032 const void_inst = try mod.constVoid(scope, inst.base.src);
2195 try inlining.merges.results.append(mod.gpa, void_inst);2033 try inlining.merges.results.append(mod.gpa, void_inst);
2196 return mod.addBr(b, inst.base.src, inlining.merges.block_inst, void_inst);2034 const br = try mod.addBr(b, inst.base.src, inlining.merges.block_inst, void_inst);
2035 return &br.base;
2197 }2036 }
21982037
2199 if (b.func) |func| {2038 if (b.func) |func| {
...@@ -2216,27 +2055,7 @@ fn floatOpAllowed(tag: zir.Inst.Tag) bool {...@@ -2216,27 +2055,7 @@ fn floatOpAllowed(tag: zir.Inst.Tag) bool {
2216 };2055 };
2217}2056}
22182057
2219fn analyzeBreak(2058fn zirSimplePtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*Inst {
2220 mod: *Module,
2221 scope: *Scope,
2222 src: usize,
2223 zir_block: *zir.Inst.Block,
2224 operand: *Inst,
2225) InnerError!*Inst {
2226 var opt_block = scope.cast(Scope.Block);
2227 while (opt_block) |block| {
2228 if (block.label) |*label| {
2229 if (label.zir_block == zir_block) {
2230 try label.merges.results.append(mod.gpa, operand);
2231 const b = try mod.requireFunctionBlock(scope, src);
2232 return mod.addBr(b, src, label.merges.block_inst, operand);
2233 }
2234 }
2235 opt_block = block.parent;
2236 } else unreachable;
2237}
2238
2239fn analyzeInstSimplePtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*Inst {
2240 const tracy = trace(@src());2059 const tracy = trace(@src());
2241 defer tracy.end();2060 defer tracy.end();
2242 const elem_type = try resolveType(mod, scope, inst.positionals.operand);2061 const elem_type = try resolveType(mod, scope, inst.positionals.operand);
...@@ -2244,7 +2063,7 @@ fn analyzeInstSimplePtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, m...@@ -2244,7 +2063,7 @@ fn analyzeInstSimplePtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, m
2244 return mod.constType(scope, inst.base.src, ty);2063 return mod.constType(scope, inst.base.src, ty);
2245}2064}
22462065
2247fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst {2066fn zirPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst {
2248 const tracy = trace(@src());2067 const tracy = trace(@src());
2249 defer tracy.end();2068 defer tracy.end();
2250 // TODO lazy values2069 // TODO lazy values
test/stage2/test.zig-37
...@@ -962,43 +962,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -962,43 +962,6 @@ pub fn addCases(ctx: *TestContext) !void {
962 ,962 ,
963 "hello\nhello\nhello\nhello\nhello\n",963 "hello\nhello\nhello\nhello\nhello\n",
964 );964 );
965
966 // comptime switch
967
968 // Basic for loop
969 case.addCompareOutput(
970 \\pub export fn _start() noreturn {
971 \\ assert(foo() == 1);
972 \\ exit();
973 \\}
974 \\
975 \\fn foo() u32 {
976 \\ const a: comptime_int = 1;
977 \\ var b: u32 = 0;
978 \\ switch (a) {
979 \\ 1 => b = 1,
980 \\ 2 => b = 2,
981 \\ else => unreachable,
982 \\ }
983 \\ return b;
984 \\}
985 \\
986 \\pub fn assert(ok: bool) void {
987 \\ if (!ok) unreachable; // assertion failure
988 \\}
989 \\
990 \\fn exit() noreturn {
991 \\ asm volatile ("syscall"
992 \\ :
993 \\ : [number] "{rax}" (231),
994 \\ [arg1] "{rdi}" (0)
995 \\ : "rcx", "r11", "memory"
996 \\ );
997 \\ unreachable;
998 \\}
999 ,
1000 "",
1001 );
1002 }965 }
1003966
1004 {967 {