authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-22 17:12:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-22 17:29:56-07:00
log2f391df2a7ea7cc6e7500da214100fb49ea8f661
tree3f8a6f32559b15d1a6388e874489dfd7a1e91efb
parent9f0b9b8da1a111d16eb8d1254212ff98a8b4be08

stage2: Sema improvements and boolean logic astgen

* add `Module.setBlockBody` and related functions * redo astgen for `and` and `or` to use fewer ZIR instructions and require less processing for comptime known values * Sema: rework `analyzeBody` function. See the new doc comments in this commit. Divides ZIR instructions up into 3 categories: - always noreturn - never noreturn - sometimes noreturn

4 files changed, 512 insertions(+), 415 deletions(-)

src/Module.zig+78-47
......@@ -477,7 +477,7 @@ pub const Scope = struct {
477477 switch (scope.tag) {
478478 .file => return &scope.cast(File).?.tree,
479479 .block => return &scope.cast(Block).?.src_decl.container.file_scope.tree,
480 .gen_zir => return &scope.cast(GenZir).?.zir_code.decl.container.file_scope.tree,
480 .gen_zir => return scope.cast(GenZir).?.tree(),
481481 .local_val => return &scope.cast(LocalVal).?.gen_zir.zir_code.decl.container.file_scope.tree,
482482 .local_ptr => return &scope.cast(LocalPtr).?.gen_zir.zir_code.decl.container.file_scope.tree,
483483 .container => return &scope.cast(Container).?.file_scope.tree,
......@@ -983,6 +983,30 @@ pub const Scope = struct {
983983 return gz.zir_code.decl.nodeSrcLoc(node_index);
984984 }
985985
986 pub fn tree(gz: *const GenZir) *const ast.Tree {
987 return &gz.zir_code.decl.container.file_scope.tree;
988 }
989
990 pub fn setBoolBrBody(gz: GenZir, inst: zir.Inst.Index) !void {
991 try gz.zir_code.extra.ensureCapacity(gz.zir_code.gpa, gz.zir_code.extra.items.len +
992 @typeInfo(zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
993 const zir_datas = gz.zir_code.instructions.items(.data);
994 zir_datas[inst].bool_br.payload_index = gz.zir_code.addExtraAssumeCapacity(
995 zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
996 );
997 gz.zir_code.extra.appendSliceAssumeCapacity(gz.instructions.items);
998 }
999
1000 pub fn setBlockBody(gz: GenZir, inst: zir.Inst.Index) !void {
1001 try gz.zir_code.extra.ensureCapacity(gz.zir_code.gpa, gz.zir_code.extra.items.len +
1002 @typeInfo(zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
1003 const zir_datas = gz.zir_code.instructions.items(.data);
1004 zir_datas[inst].pl_node.payload_index = gz.zir_code.addExtraAssumeCapacity(
1005 zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
1006 );
1007 gz.zir_code.extra.appendSliceAssumeCapacity(gz.instructions.items);
1008 }
1009
9861010 pub fn addFnTypeCc(gz: *GenZir, tag: zir.Inst.Tag, args: struct {
9871011 param_types: []const zir.Inst.Ref,
9881012 ret_ty: zir.Inst.Ref,
......@@ -1044,73 +1068,62 @@ pub const Scope = struct {
10441068 return new_index + gz.zir_code.ref_start_index;
10451069 }
10461070
1047 pub fn addCondBr(
1071 pub fn addCall(
10481072 gz: *GenZir,
1049 condition: zir.Inst.Ref,
1050 then_body: []const zir.Inst.Ref,
1051 else_body: []const zir.Inst.Ref,
1073 tag: zir.Inst.Tag,
1074 callee: zir.Inst.Ref,
1075 args: []const zir.Inst.Ref,
10521076 /// Absolute node index. This function does the conversion to offset from Decl.
10531077 abs_node_index: ast.Node.Index,
1054 ) !zir.Inst.Ref {
1078 ) !zir.Inst.Index {
1079 assert(callee != 0);
1080 assert(abs_node_index != 0);
10551081 const gpa = gz.zir_code.gpa;
10561082 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
10571083 try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
10581084 try gz.zir_code.extra.ensureCapacity(gpa, gz.zir_code.extra.items.len +
1059 @typeInfo(zir.Inst.CondBr).Struct.fields.len + then_body.len + else_body.len);
1085 @typeInfo(zir.Inst.Call).Struct.fields.len + args.len);
10601086
1061 const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.CondBr{
1062 .condition = condition,
1063 .then_body_len = @intCast(u32, then_body.len),
1064 .else_body_len = @intCast(u32, else_body.len),
1087 const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.Call{
1088 .callee = callee,
1089 .args_len = @intCast(u32, args.len),
10651090 });
1066 gz.zir_code.extra.appendSliceAssumeCapacity(then_body);
1067 gz.zir_code.extra.appendSliceAssumeCapacity(else_body);
1091 gz.zir_code.extra.appendSliceAssumeCapacity(args);
10681092
10691093 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
10701094 gz.zir_code.instructions.appendAssumeCapacity(.{
1071 .tag = .condbr,
1095 .tag = tag,
10721096 .data = .{ .pl_node = .{
10731097 .src_node = gz.zir_code.decl.nodeIndexToRelative(abs_node_index),
10741098 .payload_index = payload_index,
10751099 } },
10761100 });
10771101 gz.instructions.appendAssumeCapacity(new_index);
1078
10791102 return new_index + gz.zir_code.ref_start_index;
10801103 }
10811104
1082 pub fn addCall(
1105 /// Note that this returns a `zir.Inst.Index` not a ref.
1106 /// Leaves the `payload_index` field undefined.
1107 pub fn addBoolBr(
10831108 gz: *GenZir,
10841109 tag: zir.Inst.Tag,
1085 callee: zir.Inst.Ref,
1086 args: []const zir.Inst.Ref,
1087 /// Absolute node index. This function does the conversion to offset from Decl.
1088 abs_node_index: ast.Node.Index,
1110 lhs: zir.Inst.Ref,
10891111 ) !zir.Inst.Index {
1090 assert(callee != 0);
1091 assert(abs_node_index != 0);
1112 assert(lhs != 0);
10921113 const gpa = gz.zir_code.gpa;
10931114 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
10941115 try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
1095 try gz.zir_code.extra.ensureCapacity(gpa, gz.zir_code.extra.items.len +
1096 @typeInfo(zir.Inst.Call).Struct.fields.len + args.len);
1097
1098 const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.Call{
1099 .callee = callee,
1100 .args_len = @intCast(u32, args.len),
1101 });
1102 gz.zir_code.extra.appendSliceAssumeCapacity(args);
11031116
11041117 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
11051118 gz.zir_code.instructions.appendAssumeCapacity(.{
11061119 .tag = tag,
1107 .data = .{ .pl_node = .{
1108 .src_node = gz.zir_code.decl.nodeIndexToRelative(abs_node_index),
1109 .payload_index = payload_index,
1120 .data = .{ .bool_br = .{
1121 .lhs = lhs,
1122 .payload_index = undefined,
11101123 } },
11111124 });
11121125 gz.instructions.appendAssumeCapacity(new_index);
1113 return new_index + gz.zir_code.ref_start_index;
1126 return new_index;
11141127 }
11151128
11161129 pub fn addInt(gz: *GenZir, integer: u64) !zir.Inst.Ref {
......@@ -1291,6 +1304,20 @@ pub const Scope = struct {
12911304 return new_index;
12921305 }
12931306
1307 /// Note that this returns a `zir.Inst.Index` not a ref.
1308 /// Leaves the `payload_index` field undefined.
1309 pub fn addCondBr(gz: *GenZir, node: ast.Node.Index) !zir.Inst.Index {
1310 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
1311 try gz.zir_code.instructions.append(gz.zir_code.gpa, .{
1312 .tag = .condbr,
1313 .data = .{ .pl_node = .{
1314 .src_node = gz.zir_code.decl.nodeIndexToRelative(node),
1315 .payload_index = undefined,
1316 } },
1317 });
1318 return new_index;
1319 }
1320
12941321 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
12951322 const gpa = gz.zir_code.gpa;
12961323 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
......@@ -1409,9 +1436,9 @@ pub const WipZirCode = struct {
14091436 .bitcast_result_ptr,
14101437 .bit_or,
14111438 .block,
1412 .block_flat,
14131439 .block_comptime,
1414 .block_comptime_flat,
1440 .bool_br_and,
1441 .bool_br_or,
14151442 .bool_not,
14161443 .bool_and,
14171444 .bool_or,
......@@ -1461,9 +1488,6 @@ pub const WipZirCode = struct {
14611488 .ret_type,
14621489 .shl,
14631490 .shr,
1464 .store,
1465 .store_to_block_ptr,
1466 .store_to_inferred_ptr,
14671491 .str,
14681492 .sub,
14691493 .subwrap,
......@@ -1497,7 +1521,6 @@ pub const WipZirCode = struct {
14971521 .slice_sentinel,
14981522 .import,
14991523 .typeof_peer,
1500 .resolve_inferred_alloc,
15011524 => return false,
15021525
15031526 .breakpoint,
......@@ -1509,6 +1532,7 @@ pub const WipZirCode = struct {
15091532 .ensure_err_payload_void,
15101533 .@"break",
15111534 .break_void_tok,
1535 .break_flat,
15121536 .condbr,
15131537 .compile_error,
15141538 .ret_node,
......@@ -1517,6 +1541,10 @@ pub const WipZirCode = struct {
15171541 .@"unreachable",
15181542 .loop,
15191543 .elided,
1544 .store,
1545 .store_to_block_ptr,
1546 .store_to_inferred_ptr,
1547 .resolve_inferred_alloc,
15201548 => return true,
15211549 }
15221550 }
......@@ -2150,7 +2178,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
21502178 };
21512179 defer block_scope.instructions.deinit(mod.gpa);
21522180
2153 try sema.root(&block_scope);
2181 _ = try sema.root(&block_scope);
21542182
21552183 decl.analysis = .complete;
21562184 decl.generation = mod.generation;
......@@ -2338,6 +2366,7 @@ fn astgenAndSemaFn(
23382366 const tag: zir.Inst.Tag = if (is_var_args) .fn_type_var_args else .fn_type;
23392367 break :fn_type try fn_type_scope.addFnType(tag, return_type_inst, param_types);
23402368 };
2369 _ = try fn_type_scope.addUnNode(.break_flat, fn_type_inst, 0);
23412370
23422371 // We need the memory for the Type to go into the arena for the Decl
23432372 var decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
......@@ -2370,7 +2399,7 @@ fn astgenAndSemaFn(
23702399 };
23712400 defer block_scope.instructions.deinit(mod.gpa);
23722401
2373 const fn_type = try fn_type_sema.rootAsType(&block_scope, fn_type_inst);
2402 const fn_type = try fn_type_sema.rootAsType(&block_scope);
23742403 if (body_node == 0) {
23752404 if (!is_extern) {
23762405 return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function has no body", .{});
......@@ -2650,6 +2679,7 @@ fn astgenAndSemaVarDecl(
26502679 init_result_loc,
26512680 var_decl.ast.init_node,
26522681 );
2682 _ = try gen_scope.addUnNode(.break_flat, init_inst, var_decl.ast.init_node);
26532683 var code = try gen_scope.finish();
26542684 defer code.deinit(mod.gpa);
26552685 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
......@@ -2676,10 +2706,9 @@ fn astgenAndSemaVarDecl(
26762706 };
26772707 defer block_scope.instructions.deinit(mod.gpa);
26782708
2679 try sema.root(&block_scope);
2680
2709 const init_inst_zir_ref = try sema.root(&block_scope);
26812710 // The result location guarantees the type coercion.
2682 const analyzed_init_inst = try sema.resolveInst(init_inst);
2711 const analyzed_init_inst = try sema.resolveInst(init_inst_zir_ref);
26832712 // The is_comptime in the Scope.Block guarantees the result is comptime-known.
26842713 const val = analyzed_init_inst.value().?;
26852714
......@@ -2713,6 +2742,8 @@ fn astgenAndSemaVarDecl(
27132742 defer type_scope.instructions.deinit(mod.gpa);
27142743
27152744 const var_type = try astgen.typeExpr(mod, &type_scope.base, var_decl.ast.type_node);
2745 _ = try type_scope.addUnNode(.break_flat, var_type, 0);
2746
27162747 var code = try type_scope.finish();
27172748 defer code.deinit(mod.gpa);
27182749 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
......@@ -2739,7 +2770,7 @@ fn astgenAndSemaVarDecl(
27392770 };
27402771 defer block_scope.instructions.deinit(mod.gpa);
27412772
2742 const ty = try sema.rootAsType(&block_scope, var_type);
2773 const ty = try sema.rootAsType(&block_scope);
27432774
27442775 break :vi .{
27452776 .ty = try ty.copy(&decl_arena.allocator),
......@@ -3328,7 +3359,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
33283359 func.state = .in_progress;
33293360 log.debug("set {s} to in_progress", .{decl.name});
33303361
3331 try sema.root(&inner_block);
3362 _ = try sema.root(&inner_block);
33323363
33333364 const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);
33343365 func.state = .success;
src/Sema.zig+343-258
......@@ -53,172 +53,230 @@ const InnerError = Module.InnerError;
5353const Decl = Module.Decl;
5454const LazySrcLoc = Module.LazySrcLoc;
5555
56pub fn root(sema: *Sema, root_block: *Scope.Block) !void {
56pub fn root(sema: *Sema, root_block: *Scope.Block) !zir.Inst.Ref {
5757 const root_body = sema.code.extra[sema.code.root_start..][0..sema.code.root_len];
5858 return sema.analyzeBody(root_block, root_body);
5959}
6060
61pub fn rootAsType(sema: *Sema, root_block: *Scope.Block, result_inst: zir.Inst.Ref) !Type {
62 const root_body = sema.code.extra[sema.code.root_start..][0..sema.code.root_len];
63 try sema.analyzeBody(root_block, root_body);
64
61/// Assumes that `root_block` ends with `break_flat`.
62pub fn rootAsType(sema: *Sema, root_block: *Scope.Block) !Type {
63 const zir_inst_ref = try sema.root(root_block);
6564 // Source location is unneeded because resolveConstValue must have already
6665 // been successfully called when coercing the value to a type, from the
6766 // result location.
68 return sema.resolveType(root_block, .unneeded, result_inst);
69}
70
71pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Index) !void {
72 const tracy = trace(@src());
73 defer tracy.end();
67 return sema.resolveType(root_block, .unneeded, zir_inst_ref);
68}
69
70/// ZIR instructions which are always `noreturn` return this. This matches the
71/// return type of `analyzeBody` so that we can tail call them.
72/// Only appropriate to return when the instruction is known to be NoReturn
73/// solely based on the ZIR tag.
74const always_noreturn: InnerError!zir.Inst.Ref = @as(zir.Inst.Index, 0);
75
76/// This function is the main loop of `Sema` and it can be used in two different ways:
77/// * The traditional way where there are N breaks out of the block and peer type
78/// resolution is done on the break operands. In this case, the `zir.Inst.Index`
79/// part of the return value will be `undefined`, and callsites should ignore it,
80/// finding the block result value via the block scope.
81/// * The "flat" way. There is only 1 break out of the block, and it is with a `break_flat`
82/// instruction. In this case, the `zir.Inst.Index` part of the return value will be
83/// the block result value. No block scope needs to be created for this strategy.
84pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Index) !zir.Inst.Index {
85 // No tracy calls here, to avoid interfering with the tail call mechanism.
7486
7587 const map = block.sema.inst_map;
7688 const tags = block.sema.code.instructions.items(.tag);
7789
78 // TODO: As an optimization, look into making these switch prongs directly jump
79 // to the next one, rather than detouring through the loop condition.
80 // Also, look into leaving only the "noreturn" loop break condition, and removing
81 // the iteration based one. Better yet, have an extra entry in the tags array as a
82 // sentinel, so that exiting the loop is just another jump table prong.
83 // Related: https://github.com/ziglang/zig/issues/8220
84 for (body) |zir_inst| {
85 map[zir_inst] = switch (tags[zir_inst]) {
86 .alloc => try sema.zirAlloc(block, zir_inst),
87 .alloc_mut => try sema.zirAllocMut(block, zir_inst),
88 .alloc_inferred => try sema.zirAllocInferred(block, zir_inst, Type.initTag(.inferred_alloc_const)),
89 .alloc_inferred_mut => try sema.zirAllocInferred(block, zir_inst, Type.initTag(.inferred_alloc_mut)),
90 .bitcast_ref => try sema.zirBitcastRef(block, zir_inst),
91 .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, zir_inst),
92 .block => try sema.zirBlock(block, zir_inst, false),
93 .block_comptime => try sema.zirBlock(block, zir_inst, true),
94 .block_flat => try sema.zirBlockFlat(block, zir_inst, false),
95 .block_comptime_flat => try sema.zirBlockFlat(block, zir_inst, true),
96 .@"break" => try sema.zirBreak(block, zir_inst),
97 .break_void_tok => try sema.zirBreakVoidTok(block, zir_inst),
98 .breakpoint => try sema.zirBreakpoint(block, zir_inst),
99 .call => try sema.zirCall(block, zir_inst, .auto),
100 .call_compile_time => try sema.zirCall(block, zir_inst, .compile_time),
101 .call_none => try sema.zirCallNone(block, zir_inst),
102 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, zir_inst),
103 .compile_error => try sema.zirCompileError(block, zir_inst),
104 .compile_log => try sema.zirCompileLog(block, zir_inst),
105 .@"const" => try sema.zirConst(block, zir_inst),
106 .dbg_stmt_node => try sema.zirDbgStmtNode(block, zir_inst),
107 .decl_ref => try sema.zirDeclRef(block, zir_inst),
108 .decl_val => try sema.zirDeclVal(block, zir_inst),
90 // We use a while(true) loop here to avoid a redundant way of breaking out of
91 // the loop. The only way to break out of the loop is with a `noreturn`
92 // instruction.
93 // TODO: As an optimization, make sure the codegen for these switch prongs
94 // directly jump to the next one, rather than detouring through the loop
95 // continue expression. Related: https://github.com/ziglang/zig/issues/8220
96 var i: usize = 0;
97 while (true) : (i += 1) {
98 const inst = body[i];
99 map[inst] = switch (tags[inst]) {
109100 .elided => continue,
110 .ensure_result_used => try sema.zirEnsureResultUsed(block, zir_inst),
111 .ensure_result_non_error => try sema.zirEnsureResultNonError(block, zir_inst),
112 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, zir_inst),
113 .ref => try sema.zirRef(block, zir_inst),
114 .resolve_inferred_alloc => try sema.zirResolveInferredAlloc(block, zir_inst),
115 .ret_ptr => try sema.zirRetPtr(block, zir_inst),
116 .ret_type => try sema.zirRetType(block, zir_inst),
117 .store_to_block_ptr => try sema.zirStoreToBlockPtr(block, zir_inst),
118 .store_to_inferred_ptr => try sema.zirStoreToInferredPtr(block, zir_inst),
119 .ptr_type_simple => try sema.zirPtrTypeSimple(block, zir_inst),
120 .ptr_type => try sema.zirPtrType(block, zir_inst),
121 .store => try sema.zirStore(block, zir_inst),
122 .set_eval_branch_quota => try sema.zirSetEvalBranchQuota(block, zir_inst),
123 .str => try sema.zirStr(block, zir_inst),
124 .int => try sema.zirInt(block, zir_inst),
125 .int_type => try sema.zirIntType(block, zir_inst),
126 .loop => try sema.zirLoop(block, zir_inst),
127 .param_type => try sema.zirParamType(block, zir_inst),
128 .ptrtoint => try sema.zirPtrtoint(block, zir_inst),
129 .field_ptr => try sema.zirFieldPtr(block, zir_inst),
130 .field_val => try sema.zirFieldVal(block, zir_inst),
131 .field_ptr_named => try sema.zirFieldPtrNamed(block, zir_inst),
132 .field_val_named => try sema.zirFieldValNamed(block, zir_inst),
133 .deref_node => try sema.zirDerefNode(block, zir_inst),
134 .as => try sema.zirAs(block, zir_inst),
135 .as_node => try sema.zirAsNode(block, zir_inst),
136 .@"asm" => try sema.zirAsm(block, zir_inst, false),
137 .asm_volatile => try sema.zirAsm(block, zir_inst, true),
138 .@"unreachable" => try sema.zirUnreachable(block, zir_inst),
139 .ret_coerce => try sema.zirRetTok(block, zir_inst, true),
140 .ret_tok => try sema.zirRetTok(block, zir_inst, false),
141 .ret_node => try sema.zirRetNode(block, zir_inst),
142 .fn_type => try sema.zirFnType(block, zir_inst, false),
143 .fn_type_cc => try sema.zirFnTypeCc(block, zir_inst, false),
144 .fn_type_var_args => try sema.zirFnType(block, zir_inst, true),
145 .fn_type_cc_var_args => try sema.zirFnTypeCc(block, zir_inst, true),
146 .intcast => try sema.zirIntcast(block, zir_inst),
147 .bitcast => try sema.zirBitcast(block, zir_inst),
148 .floatcast => try sema.zirFloatcast(block, zir_inst),
149 .elem_ptr => try sema.zirElemPtr(block, zir_inst),
150 .elem_ptr_node => try sema.zirElemPtrNode(block, zir_inst),
151 .elem_val => try sema.zirElemVal(block, zir_inst),
152 .elem_val_node => try sema.zirElemValNode(block, zir_inst),
153 .add => try sema.zirArithmetic(block, zir_inst),
154 .addwrap => try sema.zirArithmetic(block, zir_inst),
155 .sub => try sema.zirArithmetic(block, zir_inst),
156 .subwrap => try sema.zirArithmetic(block, zir_inst),
101
102 .add => try sema.zirArithmetic(block, inst),
103 .addwrap => try sema.zirArithmetic(block, inst),
104 .alloc => try sema.zirAlloc(block, inst),
105 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
106 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
107 .alloc_mut => try sema.zirAllocMut(block, inst),
108 .array_cat => try sema.zirArrayCat(block, inst),
109 .array_mul => try sema.zirArrayMul(block, inst),
110 .array_type => try sema.zirArrayType(block, inst),
111 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
112 .as => try sema.zirAs(block, inst),
113 .as_node => try sema.zirAsNode(block, inst),
114 .@"asm" => try sema.zirAsm(block, inst, false),
115 .asm_volatile => try sema.zirAsm(block, inst, true),
116 .bit_and => try sema.zirBitwise(block, inst),
117 .bit_not => try sema.zirBitNot(block, inst),
118 .bit_or => try sema.zirBitwise(block, inst),
119 .bitcast => try sema.zirBitcast(block, inst),
120 .bitcast_ref => try sema.zirBitcastRef(block, inst),
121 .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst),
122 .block => try sema.zirBlock(block, inst, false),
123 .block_comptime => try sema.zirBlock(block, inst, true),
124 .bool_not => try sema.zirBoolNot(block, inst),
125 .bool_and => try sema.zirBoolOp(block, inst, false),
126 .bool_or => try sema.zirBoolOp(block, inst, true),
127 .bool_br_and => try sema.zirBoolBr(block, inst, false),
128 .bool_br_or => try sema.zirBoolBr(block, inst, true),
129 .call => try sema.zirCall(block, inst, .auto),
130 .call_compile_time => try sema.zirCall(block, inst, .compile_time),
131 .call_none => try sema.zirCallNone(block, inst),
132 .cmp_eq => try sema.zirCmp(block, inst, .eq),
133 .cmp_gt => try sema.zirCmp(block, inst, .gt),
134 .cmp_gte => try sema.zirCmp(block, inst, .gte),
135 .cmp_lt => try sema.zirCmp(block, inst, .lt),
136 .cmp_lte => try sema.zirCmp(block, inst, .lte),
137 .cmp_neq => try sema.zirCmp(block, inst, .neq),
138 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
139 .@"const" => try sema.zirConst(block, inst),
140 .decl_ref => try sema.zirDeclRef(block, inst),
141 .decl_val => try sema.zirDeclVal(block, inst),
142 .deref_node => try sema.zirDerefNode(block, inst),
143 .div => try sema.zirArithmetic(block, inst),
144 .elem_ptr => try sema.zirElemPtr(block, inst),
145 .elem_ptr_node => try sema.zirElemPtrNode(block, inst),
146 .elem_val => try sema.zirElemVal(block, inst),
147 .elem_val_node => try sema.zirElemValNode(block, inst),
148 .enum_literal => try sema.zirEnumLiteral(block, inst),
149 .enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),
150 .err_union_code => try sema.zirErrUnionCode(block, inst),
151 .err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst),
152 .err_union_payload_safe => try sema.zirErrUnionPayload(block, inst, true),
153 .err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, true),
154 .err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst, false),
155 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, false),
156 .error_set => try sema.zirErrorSet(block, inst),
157 .error_union_type => try sema.zirErrorUnionType(block, inst),
158 .error_value => try sema.zirErrorValue(block, inst),
159 .field_ptr => try sema.zirFieldPtr(block, inst),
160 .field_ptr_named => try sema.zirFieldPtrNamed(block, inst),
161 .field_val => try sema.zirFieldVal(block, inst),
162 .field_val_named => try sema.zirFieldValNamed(block, inst),
163 .floatcast => try sema.zirFloatcast(block, inst),
164 .fn_type => try sema.zirFnType(block, inst, false),
165 .fn_type_cc => try sema.zirFnTypeCc(block, inst, false),
166 .fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true),
167 .fn_type_var_args => try sema.zirFnType(block, inst, true),
168 .import => try sema.zirImport(block, inst),
169 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
170 .int => try sema.zirInt(block, inst),
171 .int_type => try sema.zirIntType(block, inst),
172 .intcast => try sema.zirIntcast(block, inst),
173 .is_err => try sema.zirIsErr(block, inst),
174 .is_err_ptr => try sema.zirIsErrPtr(block, inst),
175 .is_non_null => try sema.zirIsNull(block, inst, true),
176 .is_non_null_ptr => try sema.zirIsNullPtr(block, inst, true),
177 .is_null => try sema.zirIsNull(block, inst, false),
178 .is_null_ptr => try sema.zirIsNullPtr(block, inst, false),
179 .merge_error_sets => try sema.zirMergeErrorSets(block, inst),
180 .mod_rem => try sema.zirArithmetic(block, inst),
181 .mul => try sema.zirArithmetic(block, inst),
182 .mulwrap => try sema.zirArithmetic(block, inst),
157183 .negate => @panic("TODO"),
158184 .negate_wrap => @panic("TODO"),
159 .mul => try sema.zirArithmetic(block, zir_inst),
160 .mulwrap => try sema.zirArithmetic(block, zir_inst),
161 .div => try sema.zirArithmetic(block, zir_inst),
162 .mod_rem => try sema.zirArithmetic(block, zir_inst),
163 .array_cat => try sema.zirArrayCat(block, zir_inst),
164 .array_mul => try sema.zirArrayMul(block, zir_inst),
165 .bit_and => try sema.zirBitwise(block, zir_inst),
166 .bit_not => try sema.zirBitNot(block, zir_inst),
167 .bit_or => try sema.zirBitwise(block, zir_inst),
168 .xor => try sema.zirBitwise(block, zir_inst),
169 .shl => try sema.zirShl(block, zir_inst),
170 .shr => try sema.zirShr(block, zir_inst),
171 .cmp_lt => try sema.zirCmp(block, zir_inst, .lt),
172 .cmp_lte => try sema.zirCmp(block, zir_inst, .lte),
173 .cmp_eq => try sema.zirCmp(block, zir_inst, .eq),
174 .cmp_gte => try sema.zirCmp(block, zir_inst, .gte),
175 .cmp_gt => try sema.zirCmp(block, zir_inst, .gt),
176 .cmp_neq => try sema.zirCmp(block, zir_inst, .neq),
177 .condbr => try sema.zirCondbr(block, zir_inst),
178 .is_null => try sema.zirIsNull(block, zir_inst, false),
179 .is_non_null => try sema.zirIsNull(block, zir_inst, true),
180 .is_null_ptr => try sema.zirIsNullPtr(block, zir_inst, false),
181 .is_non_null_ptr => try sema.zirIsNullPtr(block, zir_inst, true),
182 .is_err => try sema.zirIsErr(block, zir_inst),
183 .is_err_ptr => try sema.zirIsErrPtr(block, zir_inst),
184 .bool_not => try sema.zirBoolNot(block, zir_inst),
185 .typeof => try sema.zirTypeof(block, zir_inst),
186 .typeof_peer => try sema.zirTypeofPeer(block, zir_inst),
187 .optional_type => try sema.zirOptionalType(block, zir_inst),
188 .optional_type_from_ptr_elem => try sema.zirOptionalTypeFromPtrElem(block, zir_inst),
189 .optional_payload_safe => try sema.zirOptionalPayload(block, zir_inst, true),
190 .optional_payload_unsafe => try sema.zirOptionalPayload(block, zir_inst, false),
191 .optional_payload_safe_ptr => try sema.zirOptionalPayloadPtr(block, zir_inst, true),
192 .optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, zir_inst, false),
193 .err_union_payload_safe => try sema.zirErrUnionPayload(block, zir_inst, true),
194 .err_union_payload_unsafe => try sema.zirErrUnionPayload(block, zir_inst, false),
195 .err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, zir_inst, true),
196 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, zir_inst, false),
197 .err_union_code => try sema.zirErrUnionCode(block, zir_inst),
198 .err_union_code_ptr => try sema.zirErrUnionCodePtr(block, zir_inst),
199 .ensure_err_payload_void => try sema.zirEnsureErrPayloadVoid(block, zir_inst),
200 .array_type => try sema.zirArrayType(block, zir_inst),
201 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, zir_inst),
202 .enum_literal => try sema.zirEnumLiteral(block, zir_inst),
203 .enum_literal_small => try sema.zirEnumLiteralSmall(block, zir_inst),
204 .merge_error_sets => try sema.zirMergeErrorSets(block, zir_inst),
205 .error_union_type => try sema.zirErrorUnionType(block, zir_inst),
206 .error_set => try sema.zirErrorSet(block, zir_inst),
207 .error_value => try sema.zirErrorValue(block, zir_inst),
208 .slice_start => try sema.zirSliceStart(block, zir_inst),
209 .slice_end => try sema.zirSliceEnd(block, zir_inst),
210 .slice_sentinel => try sema.zirSliceSentinel(block, zir_inst),
211 .import => try sema.zirImport(block, zir_inst),
212 .bool_and => try sema.zirBoolOp(block, zir_inst, false),
213 .bool_or => try sema.zirBoolOp(block, zir_inst, true),
185 .optional_payload_safe => try sema.zirOptionalPayload(block, inst, true),
186 .optional_payload_safe_ptr => try sema.zirOptionalPayloadPtr(block, inst, true),
187 .optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false),
188 .optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false),
189 .optional_type => try sema.zirOptionalType(block, inst),
190 .optional_type_from_ptr_elem => try sema.zirOptionalTypeFromPtrElem(block, inst),
191 .param_type => try sema.zirParamType(block, inst),
192 .ptr_type => try sema.zirPtrType(block, inst),
193 .ptr_type_simple => try sema.zirPtrTypeSimple(block, inst),
194 .ptrtoint => try sema.zirPtrtoint(block, inst),
195 .ref => try sema.zirRef(block, inst),
196 .ret_ptr => try sema.zirRetPtr(block, inst),
197 .ret_type => try sema.zirRetType(block, inst),
198 .shl => try sema.zirShl(block, inst),
199 .shr => try sema.zirShr(block, inst),
200 .slice_end => try sema.zirSliceEnd(block, inst),
201 .slice_sentinel => try sema.zirSliceSentinel(block, inst),
202 .slice_start => try sema.zirSliceStart(block, inst),
203 .str => try sema.zirStr(block, inst),
204 .sub => try sema.zirArithmetic(block, inst),
205 .subwrap => try sema.zirArithmetic(block, inst),
206 .typeof => try sema.zirTypeof(block, inst),
207 .typeof_peer => try sema.zirTypeofPeer(block, inst),
208 .xor => try sema.zirBitwise(block, inst),
214209 // TODO
215 //.switchbr => try sema.zirSwitchBr(block, zir_inst, false),
216 //.switchbr_ref => try sema.zirSwitchBr(block, zir_inst, true),
217 //.switch_range => try sema.zirSwitchRange(block, zir_inst),
210 //.switchbr => try sema.zirSwitchBr(block, inst, false),
211 //.switchbr_ref => try sema.zirSwitchBr(block, inst, true),
212 //.switch_range => try sema.zirSwitchRange(block, inst),
213
214 // Instructions that we know to *always* be noreturn based solely on their tag.
215 // These functions match the return type of analyzeBody so that we can
216 // tail call them here.
217 .condbr => return sema.zirCondbr(block, inst),
218 .@"break" => return sema.zirBreak(block, inst),
219 .break_void_tok => return sema.zirBreakVoidTok(block, inst),
220 .break_flat => return sema.code.instructions.items(.data)[inst].un_node.operand,
221 .compile_error => return sema.zirCompileError(block, inst),
222 .ret_coerce => return sema.zirRetTok(block, inst, true),
223 .ret_node => return sema.zirRetNode(block, inst),
224 .ret_tok => return sema.zirRetTok(block, inst, false),
225 .@"unreachable" => return sema.zirUnreachable(block, inst),
226 .loop => return sema.zirLoop(block, inst),
227
228 // Instructions that we know can *never* be noreturn based solely on
229 // their tag. We avoid needlessly checking if they are noreturn and
230 // continue the loop.
231 // We also know that they cannot be referenced later, so we avoid
232 // putting them into the map.
233 .breakpoint => {
234 try sema.zirBreakpoint(block, inst);
235 continue;
236 },
237 .dbg_stmt_node => {
238 try sema.zirDbgStmtNode(block, inst);
239 continue;
240 },
241 .ensure_err_payload_void => {
242 try sema.zirEnsureErrPayloadVoid(block, inst);
243 continue;
244 },
245 .ensure_result_non_error => {
246 try sema.zirEnsureResultNonError(block, inst);
247 continue;
248 },
249 .ensure_result_used => {
250 try sema.zirEnsureResultUsed(block, inst);
251 continue;
252 },
253 .compile_log => {
254 try sema.zirCompileLog(block, inst);
255 continue;
256 },
257 .set_eval_branch_quota => {
258 try sema.zirSetEvalBranchQuota(block, inst);
259 continue;
260 },
261 .store => {
262 try sema.zirStore(block, inst);
263 continue;
264 },
265 .store_to_block_ptr => {
266 try sema.zirStoreToBlockPtr(block, inst);
267 continue;
268 },
269 .store_to_inferred_ptr => {
270 try sema.zirStoreToInferredPtr(block, inst);
271 continue;
272 },
273 .resolve_inferred_alloc => {
274 try sema.zirResolveInferredAlloc(block, inst);
275 continue;
276 },
218277 };
219 if (map[zir_inst].ty.isNoReturn()) {
220 break;
221 }
278 if (map[inst].ty.isNoReturn())
279 return always_noreturn;
222280 }
223281}
224282
......@@ -392,7 +450,7 @@ fn zirRetType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
392450 return sema.mod.constType(sema.arena, src, ret_type);
393451}
394452
395fn zirEnsureResultUsed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
453fn zirEnsureResultUsed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
396454 const tracy = trace(@src());
397455 defer tracy.end();
398456
......@@ -400,12 +458,12 @@ fn zirEnsureResultUsed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) I
400458 const operand = try sema.resolveInst(inst_data.operand);
401459 const src = inst_data.src();
402460 switch (operand.ty.zigTypeTag()) {
403 .Void, .NoReturn => return sema.mod.constVoid(sema.arena, .unneeded),
461 .Void, .NoReturn => return,
404462 else => return sema.mod.fail(&block.base, src, "expression value is ignored", .{}),
405463 }
406464}
407465
408fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
466fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
409467 const tracy = trace(@src());
410468 defer tracy.end();
411469
......@@ -414,7 +472,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde
414472 const src = inst_data.src();
415473 switch (operand.ty.zigTypeTag()) {
416474 .ErrorSet, .ErrorUnion => return sema.mod.fail(&block.base, src, "error is discarded", .{}),
417 else => return sema.mod.constVoid(sema.arena, .unneeded),
475 else => return,
418476 }
419477}
420478
......@@ -508,11 +566,7 @@ fn zirAllocInferred(
508566 return result;
509567}
510568
511fn zirResolveInferredAlloc(
512 sema: *Sema,
513 block: *Scope.Block,
514 inst: zir.Inst.Index,
515) InnerError!*Inst {
569fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
516570 const tracy = trace(@src());
517571 defer tracy.end();
518572
......@@ -536,15 +590,9 @@ fn zirResolveInferredAlloc(
536590 // Change it to a normal alloc.
537591 ptr.ty = final_ptr_ty;
538592 ptr.tag = .alloc;
539
540 return sema.mod.constVoid(sema.arena, .unneeded);
541593}
542594
543fn zirStoreToBlockPtr(
544 sema: *Sema,
545 block: *Scope.Block,
546 inst: zir.Inst.Index,
547) InnerError!*Inst {
595fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
548596 const tracy = trace(@src());
549597 defer tracy.end();
550598
......@@ -560,11 +608,7 @@ fn zirStoreToBlockPtr(
560608 return sema.storePtr(block, src, bitcasted_ptr, value);
561609}
562610
563fn zirStoreToInferredPtr(
564 sema: *Sema,
565 block: *Scope.Block,
566 inst: zir.Inst.Index,
567) InnerError!*Inst {
611fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
568612 const tracy = trace(@src());
569613 defer tracy.end();
570614
......@@ -583,21 +627,16 @@ fn zirStoreToInferredPtr(
583627 return sema.storePtr(block, src, bitcasted_ptr, value);
584628}
585629
586fn zirSetEvalBranchQuota(
587 sema: *Sema,
588 block: *Scope.Block,
589 inst: zir.Inst.Index,
590) InnerError!*Inst {
630fn zirSetEvalBranchQuota(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
591631 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
592632 const src = inst_data.src();
593633 try sema.requireFunctionBlock(block, src);
594634 const quota = try sema.resolveAlreadyCoercedInt(block, src, inst_data.operand, u32);
595635 if (sema.branch_quota < quota)
596636 sema.branch_quota = quota;
597 return sema.mod.constVoid(sema.arena, .unneeded);
598637}
599638
600fn zirStore(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
639fn zirStore(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
601640 const tracy = trace(@src());
602641 defer tracy.end();
603642
......@@ -677,7 +716,7 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
677716 return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int);
678717}
679718
680fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
719fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {
681720 const tracy = trace(@src());
682721 defer tracy.end();
683722
......@@ -688,7 +727,7 @@ fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inner
688727 return sema.mod.fail(&block.base, src, "{s}", .{msg});
689728}
690729
691fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
730fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
692731 var managed = sema.mod.compile_log_text.toManaged(sema.gpa);
693732 defer sema.mod.compile_log_text = managed.moveToUnmanaged();
694733 const writer = managed.writer();
......@@ -711,10 +750,9 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
711750 if (!gop.found_existing) {
712751 gop.entry.value = inst_data.src().toSrcLoc(&block.base);
713752 }
714 return sema.mod.constVoid(sema.arena, .unneeded);
715753}
716754
717fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
755fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Ref {
718756 const tracy = trace(@src());
719757 defer tracy.end();
720758
......@@ -746,41 +784,13 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerE
746784 };
747785 defer child_block.instructions.deinit(sema.gpa);
748786
749 try sema.analyzeBody(&child_block, body);
787 _ = try sema.analyzeBody(&child_block, body);
750788
751789 // Loop repetition is implied so the last instruction may or may not be a noreturn instruction.
752790
753791 try parent_block.instructions.append(sema.gpa, &loop_inst.base);
754792 loop_inst.body = .{ .instructions = try sema.arena.dupe(*Inst, child_block.instructions.items) };
755 return &loop_inst.base;
756}
757
758fn zirBlockFlat(
759 sema: *Sema,
760 parent_block: *Scope.Block,
761 inst: zir.Inst.Index,
762 is_comptime: bool,
763) InnerError!*Inst {
764 const tracy = trace(@src());
765 defer tracy.end();
766
767 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
768 const src = inst_data.src();
769 const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index);
770 const body = sema.code.extra[extra.end..][0..extra.data.operands_len];
771
772 var child_block = parent_block.makeSubBlock();
773 defer child_block.instructions.deinit(sema.gpa);
774 child_block.is_comptime = child_block.is_comptime or is_comptime;
775
776 try sema.analyzeBody(&child_block, body);
777
778 // Move the analyzed instructions into the parent block arena.
779 const copied_instructions = try sema.arena.dupe(*Inst, child_block.instructions.items);
780 try parent_block.instructions.appendSlice(sema.gpa, copied_instructions);
781
782 // The result of a flat block is the last instruction.
783 return sema.inst_map[body[body.len - 1]];
793 return always_noreturn;
784794}
785795
786796fn zirBlock(
......@@ -794,8 +804,8 @@ fn zirBlock(
794804
795805 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
796806 const src = inst_data.src();
797 const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index);
798 const body = sema.code.extra[extra.end..][0..extra.data.operands_len];
807 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
808 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
799809
800810 // Reserve space for a Block instruction so that generated Break instructions can
801811 // point to it, even if it doesn't end up getting used because the code ends up being
......@@ -833,7 +843,7 @@ fn zirBlock(
833843 defer merges.results.deinit(sema.gpa);
834844 defer merges.br_list.deinit(sema.gpa);
835845
836 try sema.analyzeBody(&child_block, body);
846 _ = try sema.analyzeBody(&child_block, body);
837847
838848 return sema.analyzeBlockBody(parent_block, &child_block, merges);
839849}
......@@ -919,17 +929,17 @@ fn analyzeBlockBody(
919929 return &merges.block_inst.base;
920930}
921931
922fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
932fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
923933 const tracy = trace(@src());
924934 defer tracy.end();
925935
926936 const src_node = sema.code.instructions.items(.data)[inst].node;
927937 const src: LazySrcLoc = .{ .node_offset = src_node };
928938 try sema.requireRuntimeBlock(block, src);
929 return block.addNoOp(src, Type.initTag(.void), .breakpoint);
939 _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint);
930940}
931941
932fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
942fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {
933943 const tracy = trace(@src());
934944 defer tracy.end();
935945
......@@ -939,7 +949,7 @@ fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*
939949 return sema.analyzeBreak(block, sema.src, zir_block, operand);
940950}
941951
942fn zirBreakVoidTok(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
952fn zirBreakVoidTok(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {
943953 const tracy = trace(@src());
944954 defer tracy.end();
945955
......@@ -955,7 +965,7 @@ fn analyzeBreak(
955965 src: LazySrcLoc,
956966 zir_block: zir.Inst.Index,
957967 operand: *Inst,
958) InnerError!*Inst {
968) InnerError!zir.Inst.Ref {
959969 var block = start_block;
960970 while (true) {
961971 if (block.label) |*label| {
......@@ -981,26 +991,24 @@ fn analyzeBreak(
981991 try block.instructions.append(sema.gpa, &br.base);
982992 try label.merges.results.append(sema.gpa, operand);
983993 try label.merges.br_list.append(sema.gpa, br);
984 return &br.base;
994 return always_noreturn;
985995 }
986996 }
987997 block = block.parent.?;
988998 }
989999}
9901000
991fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1001fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
9921002 const tracy = trace(@src());
9931003 defer tracy.end();
9941004
995 if (block.is_comptime) {
996 return sema.mod.constVoid(sema.arena, .unneeded);
997 }
1005 if (block.is_comptime) return;
9981006
9991007 const src_node = sema.code.instructions.items(.data)[inst].node;
10001008 const src: LazySrcLoc = .{ .node_offset = src_node };
10011009 const src_loc = src.toSrcLoc(&block.base);
10021010 const abs_byte_off = try src_loc.byteOffset();
1003 return block.addDbgStmt(src, abs_byte_off);
1011 _ = try block.addDbgStmt(src, abs_byte_off);
10041012}
10051013
10061014fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
......@@ -1185,7 +1193,7 @@ fn analyzeCall(
11851193
11861194 // This will have return instructions analyzed as break instructions to
11871195 // the block_inst above.
1188 try sema.root(&child_block);
1196 _ = try sema.root(&child_block);
11891197
11901198 return sema.analyzeBlockBody(block, &child_block, merges);
11911199 }
......@@ -1638,7 +1646,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
16381646 return block.addUnOp(src, operand.ty.castTag(.error_union).?.data.payload, .unwrap_errunion_err_ptr, operand);
16391647}
16401648
1641fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1649fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
16421650 const tracy = trace(@src());
16431651 defer tracy.end();
16441652
......@@ -1650,7 +1658,6 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde
16501658 if (operand.ty.castTag(.error_union).?.data.payload.zigTypeTag() != .Void) {
16511659 return sema.mod.fail(&block.base, src, "expression value is ignored", .{});
16521660 }
1653 return sema.mod.constVoid(sema.arena, .unneeded);
16541661}
16551662
16561663fn zirFnType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: bool) InnerError!*Inst {
......@@ -2067,7 +2074,7 @@ fn zirSwitchBr(
20672074 parent_block: *Scope.Block,
20682075 inst: zir.Inst.Index,
20692076 ref: bool,
2070) InnerError!*Inst {
2077) InnerError!zir.Inst.Ref {
20712078 const tracy = trace(@src());
20722079 defer tracy.end();
20732080
......@@ -2087,18 +2094,18 @@ fn zirSwitchBr(
20872094 const item = try sema.resolveConstValue(parent_block, case_src, casted);
20882095
20892096 if (target_val.eql(item)) {
2090 try sema.analyzeBody(parent_block, case.body);
2091 return sema.mod.constNoReturn(sema.arena, inst.base.src);
2097 _ = try sema.analyzeBody(parent_block, case.body);
2098 return always_noreturn;
20922099 }
20932100 }
2094 try sema.analyzeBody(parent_block, inst.positionals.else_body);
2095 return sema.mod.constNoReturn(sema.arena, inst.base.src);
2101 _ = try sema.analyzeBody(parent_block, inst.positionals.else_body);
2102 return always_noreturn;
20962103 }
20972104
20982105 if (inst.positionals.cases.len == 0) {
20992106 // no cases just analyze else_branch
2100 try sema.analyzeBody(parent_block, inst.positionals.else_body);
2101 return sema.mod.constNoReturn(sema.arena, inst.base.src);
2107 _ = try sema.analyzeBody(parent_block, inst.positionals.else_body);
2108 return always_noreturn;
21022109 }
21032110
21042111 try sema.requireRuntimeBlock(parent_block, inst.base.src);
......@@ -2122,7 +2129,7 @@ fn zirSwitchBr(
21222129 const casted = try sema.coerce(block, target.ty, resolved, resolved_src);
21232130 const item = try sema.resolveConstValue(parent_block, case_src, casted);
21242131
2125 try sema.analyzeBody(&case_block, case.body);
2132 _ = try sema.analyzeBody(&case_block, case.body);
21262133
21272134 cases[i] = .{
21282135 .item = item,
......@@ -2131,7 +2138,7 @@ fn zirSwitchBr(
21312138 }
21322139
21332140 case_block.instructions.items.len = 0;
2134 try sema.analyzeBody(&case_block, inst.positionals.else_body);
2141 _ = try sema.analyzeBody(&case_block, inst.positionals.else_body);
21352142
21362143 const else_body: ir.Body = .{
21372144 .instructions = try sema.arena.dupe(*Inst, case_block.instructions.items),
......@@ -2719,6 +2726,75 @@ fn zirBoolOp(
27192726 return block.addBinOp(src, bool_type, tag, lhs, rhs);
27202727}
27212728
2729fn zirBoolBr(
2730 sema: *Sema,
2731 parent_block: *Scope.Block,
2732 inst: zir.Inst.Index,
2733 is_bool_or: bool,
2734) InnerError!*Inst {
2735 const tracy = trace(@src());
2736 defer tracy.end();
2737
2738 const inst_data = sema.code.instructions.items(.data)[inst].bool_br;
2739 const src: LazySrcLoc = .unneeded;
2740 const lhs = try sema.resolveInst(inst_data.lhs);
2741 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
2742 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
2743
2744 if (try sema.resolveDefinedValue(parent_block, src, lhs)) |lhs_val| {
2745 if (lhs_val.toBool() == is_bool_or) {
2746 return sema.mod.constBool(sema.arena, src, is_bool_or);
2747 }
2748 // comptime-known left-hand side. No need for a block here; the result
2749 // is simply the rhs expression. Here we rely on there only being 1
2750 // break instruction (`break_flat`).
2751 const zir_inst_ref = try sema.analyzeBody(parent_block, body);
2752 return sema.resolveInst(zir_inst_ref);
2753 }
2754
2755 const block_inst = try sema.arena.create(Inst.Block);
2756 block_inst.* = .{
2757 .base = .{
2758 .tag = Inst.Block.base_tag,
2759 .ty = Type.initTag(.bool),
2760 .src = src,
2761 },
2762 .body = undefined,
2763 };
2764
2765 var child_block = parent_block.makeSubBlock();
2766 defer child_block.instructions.deinit(sema.gpa);
2767
2768 var then_block = child_block.makeSubBlock();
2769 defer then_block.instructions.deinit(sema.gpa);
2770
2771 var else_block = child_block.makeSubBlock();
2772 defer else_block.instructions.deinit(sema.gpa);
2773
2774 const lhs_block = if (is_bool_or) &then_block else &else_block;
2775 const rhs_block = if (is_bool_or) &else_block else &then_block;
2776
2777 const lhs_result = try sema.mod.constInst(sema.arena, src, .{
2778 .ty = Type.initTag(.bool),
2779 .val = if (is_bool_or) Value.initTag(.bool_true) else Value.initTag(.bool_false),
2780 });
2781 _ = try lhs_block.addBr(src, block_inst, lhs_result);
2782
2783 const rhs_result_zir_ref = try sema.analyzeBody(rhs_block, body);
2784 const rhs_result = try sema.resolveInst(rhs_result_zir_ref);
2785 _ = try rhs_block.addBr(src, block_inst, rhs_result);
2786
2787 const tzir_then_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, then_block.instructions.items) };
2788 const tzir_else_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, rhs_block.instructions.items) };
2789 _ = try child_block.addCondBr(src, lhs, tzir_then_body, tzir_else_body);
2790
2791 block_inst.body = .{
2792 .instructions = try sema.arena.dupe(*Inst, child_block.instructions.items),
2793 };
2794 try parent_block.instructions.append(sema.gpa, &block_inst.base);
2795 return &block_inst.base;
2796}
2797
27222798fn zirIsNull(
27232799 sema: *Sema,
27242800 block: *Scope.Block,
......@@ -2770,7 +2846,11 @@ fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
27702846 return sema.analyzeIsErr(block, src, loaded);
27712847}
27722848
2773fn zirCondbr(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
2849fn zirCondbr(
2850 sema: *Sema,
2851 parent_block: *Scope.Block,
2852 inst: zir.Inst.Index,
2853) InnerError!zir.Inst.Ref {
27742854 const tracy = trace(@src());
27752855 defer tracy.end();
27762856
......@@ -2787,8 +2867,8 @@ fn zirCondbr(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inne
27872867
27882868 if (try sema.resolveDefinedValue(parent_block, src, cond)) |cond_val| {
27892869 const body = if (cond_val.toBool()) then_body else else_body;
2790 try sema.analyzeBody(parent_block, body);
2791 return sema.mod.constNoReturn(sema.arena, src);
2870 _ = try sema.analyzeBody(parent_block, body);
2871 return always_noreturn;
27922872 }
27932873
27942874 var true_block: Scope.Block = .{
......@@ -2800,7 +2880,7 @@ fn zirCondbr(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inne
28002880 .is_comptime = parent_block.is_comptime,
28012881 };
28022882 defer true_block.instructions.deinit(sema.gpa);
2803 try sema.analyzeBody(&true_block, then_body);
2883 _ = try sema.analyzeBody(&true_block, then_body);
28042884
28052885 var false_block: Scope.Block = .{
28062886 .parent = parent_block,
......@@ -2811,14 +2891,15 @@ fn zirCondbr(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inne
28112891 .is_comptime = parent_block.is_comptime,
28122892 };
28132893 defer false_block.instructions.deinit(sema.gpa);
2814 try sema.analyzeBody(&false_block, else_body);
2894 _ = try sema.analyzeBody(&false_block, else_body);
28152895
28162896 const tzir_then_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, true_block.instructions.items) };
28172897 const tzir_else_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, false_block.instructions.items) };
2818 return parent_block.addCondBr(src, cond, tzir_then_body, tzir_else_body);
2898 _ = try parent_block.addCondBr(src, cond, tzir_then_body, tzir_else_body);
2899 return always_noreturn;
28192900}
28202901
2821fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
2902fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Ref {
28222903 const tracy = trace(@src());
28232904 defer tracy.end();
28242905
......@@ -2830,7 +2911,8 @@ fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
28302911 if (safety_check and block.wantSafety()) {
28312912 return sema.safetyPanic(block, src, .unreach);
28322913 } else {
2833 return block.addNoOp(src, Type.initTag(.noreturn), .unreach);
2914 _ = try block.addNoOp(src, Type.initTag(.noreturn), .unreach);
2915 return always_noreturn;
28342916 }
28352917}
28362918
......@@ -2839,7 +2921,7 @@ fn zirRetTok(
28392921 block: *Scope.Block,
28402922 inst: zir.Inst.Index,
28412923 need_coercion: bool,
2842) InnerError!*Inst {
2924) InnerError!zir.Inst.Ref {
28432925 const tracy = trace(@src());
28442926 defer tracy.end();
28452927
......@@ -2850,7 +2932,7 @@ fn zirRetTok(
28502932 return sema.analyzeRet(block, operand, src, need_coercion);
28512933}
28522934
2853fn zirRetNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
2935fn zirRetNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Ref {
28542936 const tracy = trace(@src());
28552937 defer tracy.end();
28562938
......@@ -2867,22 +2949,24 @@ fn analyzeRet(
28672949 operand: *Inst,
28682950 src: LazySrcLoc,
28692951 need_coercion: bool,
2870) InnerError!*Inst {
2952) InnerError!zir.Inst.Ref {
28712953 if (block.inlining) |inlining| {
28722954 // We are inlining a function call; rewrite the `ret` as a `break`.
28732955 try inlining.merges.results.append(sema.gpa, operand);
2874 const br = try block.addBr(src, inlining.merges.block_inst, operand);
2875 return &br.base;
2956 _ = try block.addBr(src, inlining.merges.block_inst, operand);
2957 return always_noreturn;
28762958 }
28772959
28782960 if (need_coercion) {
28792961 if (sema.func) |func| {
28802962 const fn_ty = func.owner_decl.typed_value.most_recent.typed_value.ty;
28812963 const casted_operand = try sema.coerce(block, fn_ty.fnReturnType(), operand, src);
2882 return block.addUnOp(src, Type.initTag(.noreturn), .ret, casted_operand);
2964 _ = try block.addUnOp(src, Type.initTag(.noreturn), .ret, casted_operand);
2965 return always_noreturn;
28832966 }
28842967 }
2885 return block.addUnOp(src, Type.initTag(.noreturn), .ret, operand);
2968 _ = try block.addUnOp(src, Type.initTag(.noreturn), .ret, operand);
2969 return always_noreturn;
28862970}
28872971
28882972fn floatOpAllowed(tag: zir.Inst.Tag) bool {
......@@ -3051,10 +3135,11 @@ fn addSafetyCheck(sema: *Sema, parent_block: *Scope.Block, ok: *Inst, panic_id:
30513135 try parent_block.instructions.append(sema.gpa, &block_inst.base);
30523136}
30533137
3054fn safetyPanic(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, panic_id: PanicId) !*Inst {
3138fn safetyPanic(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, panic_id: PanicId) !zir.Inst.Ref {
30553139 // TODO Once we have a panic function to call, call it here instead of breakpoint.
30563140 _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint);
3057 return block.addNoOp(src, Type.initTag(.noreturn), .unreach);
3141 _ = try block.addNoOp(src, Type.initTag(.noreturn), .unreach);
3142 return always_noreturn;
30583143}
30593144
30603145fn emitBackwardBranch(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
......@@ -3405,20 +3490,20 @@ fn storePtr(
34053490 src: LazySrcLoc,
34063491 ptr: *Inst,
34073492 uncasted_value: *Inst,
3408) !*Inst {
3493) !void {
34093494 if (ptr.ty.isConstPtr())
34103495 return sema.mod.fail(&block.base, src, "cannot assign to constant", .{});
34113496
34123497 const elem_ty = ptr.ty.elemType();
34133498 const value = try sema.coerce(block, elem_ty, uncasted_value, uncasted_value.src);
34143499 if (elem_ty.onePossibleValue() != null)
3415 return sema.mod.constVoid(sema.arena, .unneeded);
3500 return;
34163501
34173502 // TODO handle comptime pointer writes
34183503 // TODO handle if the element type requires comptime
34193504
34203505 try sema.requireRuntimeBlock(block, src);
3421 return block.addBinOp(src, Type.initTag(.void), .store, ptr, value);
3506 _ = try block.addBinOp(src, Type.initTag(.void), .store, ptr, value);
34223507}
34233508
34243509fn bitcast(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: *Inst) !*Inst {
src/astgen.zig+33-93
......@@ -370,8 +370,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
370370 .array_cat => return simpleBinOp(mod, scope, rl, node, .array_cat),
371371 .array_mult => return simpleBinOp(mod, scope, rl, node, .array_mul),
372372
373 .bool_and => return boolBinOp(mod, scope, rl, node, .bool_and),
374 .bool_or => return boolBinOp(mod, scope, rl, node, .bool_or),
373 .bool_and => return boolBinOp(mod, scope, rl, node, .bool_br_and),
374 .bool_or => return boolBinOp(mod, scope, rl, node, .bool_br_or),
375375
376376 .bool_not => return boolNot(mod, scope, rl, node),
377377 .bit_not => return bitNot(mod, scope, rl, node),
......@@ -425,8 +425,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
425425 .field_access => return fieldAccess(mod, scope, rl, node),
426426 .float_literal => return floatLiteral(mod, scope, rl, node),
427427
428 .if_simple => return ifExpr(mod, scope, rl, tree.ifSimple(node)),
429 .@"if" => return ifExpr(mod, scope, rl, tree.ifFull(node)),
428 .if_simple => return ifExpr(mod, scope, rl, node, tree.ifSimple(node)),
429 .@"if" => return ifExpr(mod, scope, rl, node, tree.ifFull(node)),
430430
431431 .while_simple => return whileExpr(mod, scope, rl, tree.whileSimple(node)),
432432 .while_cont => return whileExpr(mod, scope, rl, tree.whileCont(node)),
......@@ -923,6 +923,7 @@ fn labeledBlockExpr(
923923 // so that break statements can reference it.
924924 const gz = parent_scope.getGenZir();
925925 const block_inst = try gz.addBlock(zir_tag, block_node);
926 try gz.instructions.append(mod.gpa, block_inst);
926927
927928 var block_scope: Scope.GenZir = .{
928929 .parent = parent_scope,
......@@ -946,8 +947,6 @@ fn labeledBlockExpr(
946947 return mod.failTok(parent_scope, label_token, "unused block label", .{});
947948 }
948949
949 try gz.instructions.append(mod.gpa, block_inst);
950
951950 const zir_tags = gz.zir_code.instructions.items(.tag);
952951 const zir_datas = gz.zir_code.instructions.items(.data);
953952
......@@ -961,7 +960,7 @@ fn labeledBlockExpr(
961960 }
962961 // TODO technically not needed since we changed the tag to break_void but
963962 // would be better still to elide the ones that are in this list.
964 try copyBodyNoEliding(block_inst, block_scope);
963 try block_scope.setBlockBody(block_inst);
965964
966965 return gz.zir_code.ref_start_index + block_inst;
967966 },
......@@ -975,7 +974,7 @@ fn labeledBlockExpr(
975974 // TODO technically not needed since we changed the tag to elided but
976975 // would be better still to elide the ones that are in this list.
977976 }
978 try copyBodyNoEliding(block_inst, block_scope);
977 try block_scope.setBlockBody(block_inst);
979978 const block_ref = gz.zir_code.ref_start_index + block_inst;
980979 switch (rl) {
981980 .ref => return block_ref,
......@@ -1635,8 +1634,8 @@ fn finishThenElseBlock(
16351634 });
16361635 }
16371636 assert(!strat.elide_store_to_block_ptr_instructions);
1638 try copyBodyNoEliding(then_body, then_scope.*);
1639 try copyBodyNoEliding(else_body, else_scope.*);
1637 try then_scope.setBlockBody(then_body);
1638 try else_scope.setBlockBody(else_body);
16401639 return &main_block.base;
16411640 },
16421641 .break_operand => {
......@@ -1662,8 +1661,8 @@ fn finishThenElseBlock(
16621661 try copyBodyWithElidedStoreBlockPtr(then_body, then_scope.*);
16631662 try copyBodyWithElidedStoreBlockPtr(else_body, else_scope.*);
16641663 } else {
1665 try copyBodyNoEliding(then_body, then_scope.*);
1666 try copyBodyNoEliding(else_body, else_scope.*);
1664 try then_scope.setBlockBody(then_body);
1665 try else_scope.setBlockBody(else_body);
16671666 }
16681667 switch (rl) {
16691668 .ref => return &main_block.base,
......@@ -1801,95 +1800,49 @@ fn boolBinOp(
18011800 mod: *Module,
18021801 scope: *Scope,
18031802 rl: ResultLoc,
1804 infix_node: ast.Node.Index,
1805 kind: enum { bool_and, bool_or },
1803 node: ast.Node.Index,
1804 zir_tag: zir.Inst.Tag,
18061805) InnerError!zir.Inst.Ref {
1807 const tree = scope.tree();
1808 const node_datas = tree.nodes.items(.data);
1809 const bool_type = @enumToInt(zir.Const.bool_type);
18101806 const gz = scope.getGenZir();
1807 const node_datas = gz.tree().nodes.items(.data);
1808 const bool_type = @enumToInt(zir.Const.bool_type);
18111809
1812 const lhs = try expr(mod, scope, .{ .ty = bool_type }, node_datas[infix_node].lhs);
1813
1814 const block_inst = try gz.addBlock(.block, infix_node);
1815 const block_ref = gz.zir_code.ref_start_index + block_inst;
1816 var block_scope: Scope.GenZir = .{
1817 .parent = scope,
1818 .zir_code = gz.zir_code,
1819 .force_comptime = gz.force_comptime,
1820 };
1821 defer block_scope.instructions.deinit(mod.gpa);
1810 const lhs = try expr(mod, scope, .{ .ty = bool_type }, node_datas[node].lhs);
1811 const bool_br = try gz.addBoolBr(zir_tag, lhs);
18221812
18231813 var rhs_scope: Scope.GenZir = .{
1824 .parent = &block_scope.base,
1814 .parent = scope,
18251815 .zir_code = gz.zir_code,
18261816 .force_comptime = gz.force_comptime,
18271817 };
18281818 defer rhs_scope.instructions.deinit(mod.gpa);
1829 const rhs = try expr(mod, &rhs_scope.base, .{ .ty = bool_type }, node_datas[infix_node].rhs);
1830 _ = try rhs_scope.addBin(.@"break", block_inst, rhs);
1831
1832 // TODO: should we have zir.Const instructions for `break true` and `break false`?
1833 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
1834 const break_true_false_ref = new_index + gz.zir_code.ref_start_index;
1835 try gz.zir_code.instructions.append(gz.zir_code.gpa, .{ .tag = .@"break", .data = .{ .bin = .{
1836 .lhs = block_inst,
1837 .rhs = switch (kind) {
1838 .bool_and => @enumToInt(zir.Const.bool_false),
1839 .bool_or => @enumToInt(zir.Const.bool_true),
1840 },
1841 } } });
1842
1843 switch (kind) {
1844 // if lhs // AND
1845 // break rhs
1846 // else
1847 // break false
1848 .bool_and => _ = try block_scope.addCondBr(
1849 lhs,
1850 rhs_scope.instructions.items,
1851 &[_]zir.Inst.Ref{break_true_false_ref},
1852 infix_node,
1853 ),
1854 // if lhs // OR
1855 // break true
1856 // else
1857 // break rhs
1858 .bool_or => _ = try block_scope.addCondBr(
1859 lhs,
1860 &[_]zir.Inst.Ref{break_true_false_ref},
1861 rhs_scope.instructions.items,
1862 infix_node,
1863 ),
1864 }
1819 const rhs = try expr(mod, &rhs_scope.base, .{ .ty = bool_type }, node_datas[node].rhs);
1820 _ = try rhs_scope.addUnNode(.break_flat, rhs, node);
1821 try rhs_scope.setBoolBrBody(bool_br);
18651822
1866 try gz.instructions.append(mod.gpa, block_inst);
1867 try copyBodyNoEliding(block_inst, block_scope);
1868
1869 return rvalue(mod, scope, rl, block_ref, infix_node);
1823 const block_ref = gz.zir_code.ref_start_index + bool_br;
1824 return rvalue(mod, scope, rl, block_ref, node);
18701825}
18711826
18721827fn ifExpr(
18731828 mod: *Module,
18741829 scope: *Scope,
18751830 rl: ResultLoc,
1831 node: ast.Node.Index,
18761832 if_full: ast.full.If,
18771833) InnerError!zir.Inst.Ref {
18781834 if (true) @panic("TODO update for zir-memory-layout");
1835 const parent_gz = scope.getGenZir();
18791836 var block_scope: Scope.GenZir = .{
18801837 .parent = scope,
1881 .decl = scope.ownerDecl().?,
1882 .arena = scope.arena(),
1838 .zir_code = parent_gz.zir_code,
18831839 .force_comptime = scope.isComptime(),
18841840 .instructions = .{},
18851841 };
18861842 setBlockResultLoc(&block_scope, rl);
18871843 defer block_scope.instructions.deinit(mod.gpa);
18881844
1889 const tree = scope.tree();
1890 const main_tokens = tree.nodes.items(.main_token);
1891
1892 const if_src = token_starts[if_full.ast.if_token];
1845 const tree = parent_gz.tree();
18931846
18941847 const cond = c: {
18951848 // TODO https://github.com/ziglang/zig/issues/7929
......@@ -1898,23 +1851,16 @@ fn ifExpr(
18981851 } else if (if_full.payload_token) |payload_token| {
18991852 return mod.failTok(scope, payload_token, "TODO implement if optional", .{});
19001853 } else {
1901 const bool_type = try addZIRInstConst(mod, &block_scope.base, if_src, .{
1902 .ty = Type.initTag(.type),
1903 .val = Value.initTag(.bool_type),
1904 });
1905 break :c try expr(mod, &block_scope.base, .{ .ty = bool_type }, if_full.ast.cond_expr);
1854 const bool_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.bool_type) };
1855 break :c try expr(mod, &block_scope.base, bool_rl, if_full.ast.cond_expr);
19061856 }
19071857 };
19081858
1909 const condbr = try addZIRInstSpecial(mod, &block_scope.base, if_src, zir.Inst.CondBr, .{
1910 .condition = cond,
1911 .then_body = undefined, // populated below
1912 .else_body = undefined, // populated below
1913 }, .{});
1859 const condbr = try block_scope.addCondBr(node);
19141860
1915 const block = try addZIRInstBlock(mod, scope, if_src, .block, .{
1916 .instructions = try block_scope.arena.dupe(zir.Inst.Ref, block_scope.instructions.items),
1917 });
1861 const block = try parent_gz.addBlock(.block, node);
1862 try parent_gz.instructions.append(mod.gpa, block);
1863 try block_scope.setBlockBody(block);
19181864
19191865 const then_src = token_starts[tree.lastToken(if_full.ast.then_expr)];
19201866 var then_scope: Scope.GenZir = .{
......@@ -1990,12 +1936,6 @@ fn copyBodyWithElidedStoreBlockPtr(body: *zir.Body, scope: Module.Scope.GenZir)
19901936 assert(dst_index == body.instructions.len);
19911937}
19921938
1993fn copyBodyNoEliding(block_inst: zir.Inst.Index, gz: Module.Scope.GenZir) !void {
1994 const zir_datas = gz.zir_code.instructions.items(.data);
1995 zir_datas[block_inst].pl_node.payload_index = @intCast(u32, gz.zir_code.extra.items.len);
1996 try gz.zir_code.extra.appendSlice(gz.zir_code.gpa, gz.instructions.items);
1997}
1998
19991939fn whileExpr(
20001940 mod: *Module,
20011941 scope: *Scope,
src/zir.zig+58-17
......@@ -99,11 +99,7 @@ pub const Code = struct {
9999 try stderr.print("ZIR {s} {s} {{\n", .{ kind, decl_name });
100100
101101 const root_body = code.extra[code.root_start..][0..code.root_len];
102 for (root_body) |inst| {
103 try stderr.print(" %{d} ", .{inst});
104 try writer.writeInstToStream(stderr, inst);
105 try stderr.writeByte('\n');
106 }
102 try writer.writeBody(stderr, root_body);
107103
108104 try stderr.print("}} // ZIR {s} {s}\n\n", .{ kind, decl_name });
109105 }
......@@ -451,16 +447,10 @@ pub const Inst = struct {
451447 /// Bitwise OR. `|`
452448 bit_or,
453449 /// A labeled block of code, which can return a value.
454 /// Uses the `pl_node` union field. Payload is `MultiOp`.
450 /// Uses the `pl_node` union field. Payload is `Block`.
455451 block,
456 /// A block of code, which can return a value. There are no instructions that break out of
457 /// this block; it is implied that the final instruction is the result.
458 /// Uses the `pl_node` union field. Payload is `MultiOp`.
459 block_flat,
460452 /// Same as `block` but additionally makes the inner instructions execute at comptime.
461453 block_comptime,
462 /// Same as `block_flat` but additionally makes the inner instructions execute at comptime.
463 block_comptime_flat,
464454 /// Boolean AND. See also `bit_and`.
465455 /// Uses the `pl_node` union field. Payload is `Bin`.
466456 bool_and,
......@@ -470,6 +460,14 @@ pub const Inst = struct {
470460 /// Boolean OR. See also `bit_or`.
471461 /// Uses the `pl_node` union field. Payload is `Bin`.
472462 bool_or,
463 /// Short-circuiting boolean `and`. `lhs` is a boolean `Ref` and the other operand
464 /// is a block, which is evaluated if `lhs` is `true`.
465 /// Uses the `bool_br` union field.
466 bool_br_and,
467 /// Short-circuiting boolean `or`. `lhs` is a boolean `Ref` and the other operand
468 /// is a block, which is evaluated if `lhs` is `false`.
469 /// Uses the `bool_br` union field.
470 bool_br_or,
473471 /// Return a value from a block.
474472 /// Uses the `bin` union field: `lhs` is `Index` to the block (*not* `Ref`!),
475473 /// `rhs` is operand.
......@@ -480,6 +478,12 @@ pub const Inst = struct {
480478 /// Uses the `un_tok` union field.
481479 /// Note that the block operand is a `Index`, not `Ref`.
482480 break_void_tok,
481 /// Return a value from a block. This is a special form that is only valid
482 /// when there is exactly 1 break from a block (this one). This instruction
483 /// allows using the return value from `Sema.analyzeBody`. The block is
484 /// assumed to be the direct parent of this instruction.
485 /// Uses the `un_node` union field. The AST node is unused.
486 break_flat,
483487 /// Uses the `node` union field.
484488 breakpoint,
485489 /// Function call with modifier `.auto`.
......@@ -637,7 +641,7 @@ pub const Inst = struct {
637641 /// A labeled block of code that loops forever. At the end of the body it is implied
638642 /// to repeat; no explicit "repeat" instruction terminates loop bodies.
639643 /// Uses the `pl_node` field. The AST node is either a for loop or while loop.
640 /// The payload is `MultiOp`.
644 /// The payload is `Block`.
641645 loop,
642646 /// Merge two error sets into one, `E1 || E2`.
643647 merge_error_sets,
......@@ -886,9 +890,9 @@ pub const Inst = struct {
886890 .bitcast_result_ptr,
887891 .bit_or,
888892 .block,
889 .block_flat,
890893 .block_comptime,
891 .block_comptime_flat,
894 .bool_br_and,
895 .bool_br_or,
892896 .bool_not,
893897 .bool_and,
894898 .bool_or,
......@@ -988,6 +992,7 @@ pub const Inst = struct {
988992
989993 .@"break",
990994 .break_void_tok,
995 .break_flat,
991996 .condbr,
992997 .compile_error,
993998 .ret_node,
......@@ -1127,6 +1132,11 @@ pub const Inst = struct {
11271132 /// For `fn_type_cc` this points to `FnTypeCc` in `extra`.
11281133 payload_index: u32,
11291134 },
1135 bool_br: struct {
1136 lhs: Ref,
1137 /// Points to a `Block`.
1138 payload_index: u32,
1139 },
11301140 param_type: struct {
11311141 callee: Ref,
11321142 param_index: u32,
......@@ -1191,6 +1201,12 @@ pub const Inst = struct {
11911201 operands_len: u32,
11921202 };
11931203
1204 /// This data is stored inside extra, with trailing operands according to `body_len`.
1205 /// Each operand is an `Index`.
1206 pub const Block = struct {
1207 body_len: u32,
1208 };
1209
11941210 /// Stored inside extra, with trailing arguments according to `args_len`.
11951211 /// Each argument is a `Ref`.
11961212 pub const Call = struct {
......@@ -1342,6 +1358,7 @@ const Writer = struct {
13421358 .err_union_payload_unsafe_ptr,
13431359 .err_union_code,
13441360 .err_union_code_ptr,
1361 .break_flat,
13451362 => try self.writeUnNode(stream, inst),
13461363
13471364 .break_void_tok,
......@@ -1358,6 +1375,10 @@ const Writer = struct {
13581375 .ensure_err_payload_void,
13591376 => try self.writeUnTok(stream, inst),
13601377
1378 .bool_br_and,
1379 .bool_br_or,
1380 => try self.writeBoolBr(stream, inst),
1381
13611382 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
13621383 .@"const" => try self.writeConst(stream, inst),
13631384 .param_type => try self.writeParamType(stream, inst),
......@@ -1370,9 +1391,7 @@ const Writer = struct {
13701391 .@"asm",
13711392 .asm_volatile,
13721393 .block,
1373 .block_flat,
13741394 .block_comptime,
1375 .block_comptime_flat,
13761395 .call,
13771396 .call_compile_time,
13781397 .compile_log,
......@@ -1618,6 +1637,19 @@ const Writer = struct {
16181637 return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc);
16191638 }
16201639
1640 fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1641 const inst_data = self.code.instructions.items(.data)[inst].bool_br;
1642 const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
1643 const body = self.code.extra[extra.end..][0..extra.data.body_len];
1644 try self.writeInstRef(stream, inst_data.lhs);
1645 try stream.writeAll(", {\n");
1646 self.indent += 2;
1647 try self.writeBody(stream, body);
1648 self.indent -= 2;
1649 try stream.writeByteNTimes(' ', self.indent);
1650 try stream.writeAll("})");
1651 }
1652
16211653 fn writeFnTypeCc(
16221654 self: *Writer,
16231655 stream: anytype,
......@@ -1713,4 +1745,13 @@ const Writer = struct {
17131745 @tagName(src), delta_line.line + 1, delta_line.column + 1,
17141746 });
17151747 }
1748
1749 fn writeBody(self: *Writer, stream: anytype, body: []const Inst.Index) !void {
1750 for (body) |inst| {
1751 try stream.writeByteNTimes(' ', self.indent);
1752 try stream.print("%{d} ", .{inst});
1753 try self.writeInstToStream(stream, inst);
1754 try stream.writeByte('\n');
1755 }
1756 }
17161757};