authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-31 23:34:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-31 23:34:58-07:00
log717b0e827511b55375de82258f570709c07cc59d
treee546a29c60ebb9ada0188f76e1696077007e73d0
parent26140678a5c72604f2baac3cb9d1e5f7b37b6b8d

stage2: introduce the ability for Scope.Block to be comptime

This gives zir_sema analysis the ability to check if the current scope is expected to be comptime.

6 files changed, 162 insertions(+), 25 deletions(-)

src-self-hosted/Module.zig+8-3
......@@ -725,6 +725,7 @@ pub const Scope = struct {
725725 /// Points to the arena allocator of DeclAnalysis
726726 arena: *Allocator,
727727 label: ?Label = null,
728 is_comptime: bool,
728729
729730 pub const Label = struct {
730731 zir_block: *zir.Inst.Block,
......@@ -1320,6 +1321,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
13201321 .decl = decl,
13211322 .instructions = .{},
13221323 .arena = &decl_arena.allocator,
1324 .is_comptime = false,
13231325 };
13241326 defer block_scope.instructions.deinit(self.gpa);
13251327
......@@ -1457,6 +1459,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
14571459 .decl = decl,
14581460 .instructions = .{},
14591461 .arena = &decl_arena.allocator,
1462 .is_comptime = true,
14601463 };
14611464 defer block_scope.instructions.deinit(self.gpa);
14621465
......@@ -1528,7 +1531,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
15281531 defer gen_scope.instructions.deinit(self.gpa);
15291532 const src = tree.token_locs[init_node.firstToken()].start;
15301533
1531 // TODO comptime scope here
15321534 const init_inst = try astgen.expr(self, &gen_scope.base, .none, init_node);
15331535 _ = try astgen.addZIRUnOp(self, &gen_scope.base, src, .@"return", init_inst);
15341536
......@@ -1538,6 +1540,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
15381540 .decl = decl,
15391541 .instructions = .{},
15401542 .arena = &gen_scope_arena.allocator,
1543 .is_comptime = true,
15411544 };
15421545 defer inner_block.instructions.deinit(self.gpa);
15431546 try zir_sema.analyzeBody(self, &inner_block.base, .{ .instructions = gen_scope.instructions.items });
......@@ -1628,8 +1631,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
16281631 };
16291632 defer gen_scope.instructions.deinit(self.gpa);
16301633
1631 // TODO comptime scope here
1632 _ = try astgen.expr(self, &gen_scope.base, .none, comptime_decl.expr);
1634 _ = try astgen.comptimeExpr(self, &gen_scope.base, .none, comptime_decl.expr);
16331635
16341636 var block_scope: Scope.Block = .{
16351637 .parent = null,
......@@ -1637,6 +1639,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
16371639 .decl = decl,
16381640 .instructions = .{},
16391641 .arena = &analysis_arena.allocator,
1642 .is_comptime = true,
16401643 };
16411644 defer block_scope.instructions.deinit(self.gpa);
16421645
......@@ -2007,6 +2010,7 @@ fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
20072010 .decl = decl,
20082011 .instructions = .{},
20092012 .arena = &arena.allocator,
2013 .is_comptime = false,
20102014 };
20112015 defer inner_block.instructions.deinit(self.gpa);
20122016
......@@ -3432,6 +3436,7 @@ pub fn addSafetyCheck(mod: *Module, parent_block: *Scope.Block, ok: *Inst, panic
34323436 .decl = parent_block.decl,
34333437 .instructions = .{},
34343438 .arena = parent_block.arena,
3439 .is_comptime = parent_block.is_comptime,
34353440 };
34363441 defer fail_block.instructions.deinit(mod.gpa);
34373442
src-self-hosted/astgen.zig+73-16
......@@ -258,7 +258,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
258258 .OptionalType => return rlWrap(mod, scope, rl, try optionalType(mod, scope, node.castTag(.OptionalType).?)),
259259 .UnwrapOptional => return unwrapOptional(mod, scope, rl, node.castTag(.UnwrapOptional).?),
260260 .Block => return rlWrapVoid(mod, scope, rl, node, try blockExpr(mod, scope, node.castTag(.Block).?)),
261 .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?),
261 .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?, .block),
262262 .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)),
263263 .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)),
264264 .GroupedExpression => return expr(mod, scope, rl, node.castTag(.GroupedExpression).?.expr),
......@@ -276,6 +276,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
276276 .For => return forExpr(mod, scope, rl, node.castTag(.For).?),
277277 .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),
278278 .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?),
279 .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?),
279280
280281 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
281282 .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}),
......@@ -294,11 +295,46 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
294295 .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),
295296 .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),
296297 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),
297 .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),
298298 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),
299299 }
300300}
301301
302fn comptimeKeyword(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Comptime) InnerError!*zir.Inst {
303 const tracy = trace(@src());
304 defer tracy.end();
305
306 return comptimeExpr(mod, scope, rl, node.expr);
307}
308
309pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {
310 const tree = parent_scope.tree();
311 const src = tree.token_locs[node.firstToken()].start;
312
313 // Optimization for labeled blocks: don't need to have 2 layers of blocks, we can reuse the existing one.
314 if (node.castTag(.LabeledBlock)) |block_node| {
315 return labeledBlockExpr(mod, parent_scope, rl, block_node, .block_comptime);
316 }
317
318 // Make a scope to collect generated instructions in the sub-expression.
319 var block_scope: Scope.GenZIR = .{
320 .parent = parent_scope,
321 .decl = parent_scope.decl().?,
322 .arena = parent_scope.arena(),
323 .instructions = .{},
324 };
325 defer block_scope.instructions.deinit(mod.gpa);
326
327 // No need to capture the result here because block_comptime_flat implies that the final
328 // instruction is the block's result value.
329 _ = try expr(mod, &block_scope.base, rl, node);
330
331 const block = try addZIRInstBlock(mod, parent_scope, src, .block_comptime_flat, .{
332 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
333 });
334
335 return &block.base;
336}
337
302338fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst {
303339 const tree = parent_scope.tree();
304340 const src = tree.token_locs[node.ltoken].start;
......@@ -360,10 +396,13 @@ fn labeledBlockExpr(
360396 parent_scope: *Scope,
361397 rl: ResultLoc,
362398 block_node: *ast.Node.LabeledBlock,
399 zir_tag: zir.Inst.Tag,
363400) InnerError!*zir.Inst {
364401 const tracy = trace(@src());
365402 defer tracy.end();
366403
404 assert(zir_tag == .block or zir_tag == .block_comptime);
405
367406 const tree = parent_scope.tree();
368407 const src = tree.token_locs[block_node.lbrace].start;
369408
......@@ -373,7 +412,7 @@ fn labeledBlockExpr(
373412 const block_inst = try gen_zir.arena.create(zir.Inst.Block);
374413 block_inst.* = .{
375414 .base = .{
376 .tag = .block,
415 .tag = zir_tag,
377416 .src = src,
378417 },
379418 .positionals = .{
......@@ -773,7 +812,7 @@ fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch)
773812 .else_body = undefined, // populated below
774813 }, .{});
775814
776 const block = try addZIRInstBlock(mod, scope, src, .{
815 const block = try addZIRInstBlock(mod, scope, src, .block, .{
777816 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
778817 });
779818
......@@ -946,7 +985,7 @@ fn boolBinOp(
946985 .else_body = undefined, // populated below
947986 }, .{});
948987
949 const block = try addZIRInstBlock(mod, scope, src, .{
988 const block = try addZIRInstBlock(mod, scope, src, .block, .{
950989 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
951990 });
952991
......@@ -1095,7 +1134,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
10951134 .else_body = undefined, // populated below
10961135 }, .{});
10971136
1098 const block = try addZIRInstBlock(mod, scope, if_src, .{
1137 const block = try addZIRInstBlock(mod, scope, if_src, .block, .{
10991138 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
11001139 });
11011140
......@@ -1218,7 +1257,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
12181257 .then_body = undefined, // populated below
12191258 .else_body = undefined, // populated below
12201259 }, .{});
1221 const cond_block = try addZIRInstBlock(mod, &loop_scope.base, while_src, .{
1260 const cond_block = try addZIRInstBlock(mod, &loop_scope.base, while_src, .block, .{
12221261 .instructions = try loop_scope.arena.dupe(*zir.Inst, continue_scope.instructions.items),
12231262 });
12241263 // TODO avoid emitting the continue expr when there
......@@ -1231,7 +1270,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
12311270 const loop = try addZIRInstLoop(mod, &expr_scope.base, while_src, .{
12321271 .instructions = try expr_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),
12331272 });
1234 const while_block = try addZIRInstBlock(mod, scope, while_src, .{
1273 const while_block = try addZIRInstBlock(mod, scope, while_src, .block, .{
12351274 .instructions = try expr_scope.arena.dupe(*zir.Inst, expr_scope.instructions.items),
12361275 });
12371276
......@@ -1365,7 +1404,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
13651404 .then_body = undefined, // populated below
13661405 .else_body = undefined, // populated below
13671406 }, .{});
1368 const cond_block = try addZIRInstBlock(mod, &loop_scope.base, for_src, .{
1407 const cond_block = try addZIRInstBlock(mod, &loop_scope.base, for_src, .block, .{
13691408 .instructions = try loop_scope.arena.dupe(*zir.Inst, cond_scope.instructions.items),
13701409 });
13711410
......@@ -1382,7 +1421,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
13821421 const loop = try addZIRInstLoop(mod, &for_scope.base, for_src, .{
13831422 .instructions = try for_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),
13841423 });
1385 const for_block = try addZIRInstBlock(mod, scope, for_src, .{
1424 const for_block = try addZIRInstBlock(mod, scope, for_src, .block, .{
13861425 .instructions = try for_scope.arena.dupe(*zir.Inst, for_scope.instructions.items),
13871426 });
13881427
......@@ -2260,6 +2299,30 @@ pub fn addZIRBinOp(
22602299 return &inst.base;
22612300}
22622301
2302pub fn addZIRInstBlock(
2303 mod: *Module,
2304 scope: *Scope,
2305 src: usize,
2306 tag: zir.Inst.Tag,
2307 body: zir.Module.Body,
2308) !*zir.Inst.Block {
2309 const gen_zir = scope.getGenZIR();
2310 try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
2311 const inst = try gen_zir.arena.create(zir.Inst.Block);
2312 inst.* = .{
2313 .base = .{
2314 .tag = tag,
2315 .src = src,
2316 },
2317 .positionals = .{
2318 .body = body,
2319 },
2320 .kw_args = .{},
2321 };
2322 gen_zir.instructions.appendAssumeCapacity(&inst.base);
2323 return inst;
2324}
2325
22632326pub fn addZIRInst(
22642327 mod: *Module,
22652328 scope: *Scope,
......@@ -2278,12 +2341,6 @@ pub fn addZIRInstConst(mod: *Module, scope: *Scope, src: usize, typed_value: Typ
22782341 return addZIRInst(mod, scope, src, zir.Inst.Const, P{ .typed_value = typed_value }, .{});
22792342}
22802343
2281/// TODO The existence of this function is a workaround for a bug in stage1.
2282pub fn addZIRInstBlock(mod: *Module, scope: *Scope, src: usize, body: zir.Module.Body) !*zir.Inst.Block {
2283 const P = std.meta.fieldInfo(zir.Inst.Block, "positionals").field_type;
2284 return addZIRInstSpecial(mod, scope, src, zir.Inst.Block, P{ .body = body }, .{});
2285}
2286
22872344/// TODO The existence of this function is a workaround for a bug in stage1.
22882345pub fn addZIRInstLoop(mod: *Module, scope: *Scope, src: usize, body: zir.Module.Body) !*zir.Inst.Loop {
22892346 const P = std.meta.fieldInfo(zir.Inst.Loop, "positionals").field_type;
src-self-hosted/ir.zig+9-1
......@@ -189,7 +189,7 @@ pub const Inst = struct {
189189 }
190190
191191 pub fn cmpOperator(base: *Inst) ?std.math.CompareOperator {
192 return switch (self.base.tag) {
192 return switch (base.tag) {
193193 .cmp_lt => .lt,
194194 .cmp_lte => .lte,
195195 .cmp_eq => .eq,
......@@ -220,6 +220,14 @@ pub const Inst = struct {
220220 unreachable;
221221 }
222222
223 pub fn breakBlock(base: *Inst) ?*Block {
224 return switch (base.tag) {
225 .br => base.castTag(.br).?.block,
226 .brvoid => base.castTag(.brvoid).?.block,
227 else => null,
228 };
229 }
230
223231 pub const NoOp = struct {
224232 base: Inst,
225233
src-self-hosted/zir.zig+16-1
......@@ -78,6 +78,13 @@ pub const Inst = struct {
7878 bitor,
7979 /// A labeled block of code, which can return a value.
8080 block,
81 /// A block of code, which can return a value. There are no instructions that break out of
82 /// this block; it is implied that the final instruction is the result.
83 block_flat,
84 /// Same as `block` but additionally makes the inner instructions execute at comptime.
85 block_comptime,
86 /// Same as `block_flat` but additionally makes the inner instructions execute at comptime.
87 block_comptime_flat,
8188 /// Boolean NOT. See also `bitnot`.
8289 boolnot,
8390 /// Return a value from a `Block`.
......@@ -338,9 +345,14 @@ pub const Inst = struct {
338345 .merge_error_sets,
339346 => BinOp,
340347
348 .block,
349 .block_flat,
350 .block_comptime,
351 .block_comptime_flat,
352 => Block,
353
341354 .arg => Arg,
342355 .array_type_sentinel => ArrayTypeSentinel,
343 .block => Block,
344356 .@"break" => Break,
345357 .breakvoid => BreakVoid,
346358 .call => Call,
......@@ -392,6 +404,9 @@ pub const Inst = struct {
392404 .bitcast_result_ptr,
393405 .bitor,
394406 .block,
407 .block_flat,
408 .block_comptime,
409 .block_comptime_flat,
395410 .boolnot,
396411 .breakpoint,
397412 .call,
src-self-hosted/zir_sema.zig+55-3
......@@ -31,7 +31,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
3131 .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),
3232 .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
3333 .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
34 .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?),
34 .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?, false),
35 .block_comptime => return analyzeInstBlock(mod, scope, old_inst.castTag(.block_comptime).?, true),
36 .block_flat => return analyzeInstBlockFlat(mod, scope, old_inst.castTag(.block_flat).?, false),
37 .block_comptime_flat => return analyzeInstBlockFlat(mod, scope, old_inst.castTag(.block_comptime_flat).?, true),
3538 .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?),
3639 .breakpoint => return analyzeInstBreakpoint(mod, scope, old_inst.castTag(.breakpoint).?),
3740 .breakvoid => return analyzeInstBreakVoid(mod, scope, old_inst.castTag(.breakvoid).?),
......@@ -147,6 +150,7 @@ pub fn analyzeBody(mod: *Module, scope: *Scope, body: zir.Module.Body) !void {
147150 }
148151}
149152
153/// TODO improve this to use .block_comptime_flat
150154pub fn analyzeBodyValueAsType(mod: *Module, block_scope: *Scope.Block, body: zir.Module.Body) !Type {
151155 try analyzeBody(mod, &block_scope.base, body);
152156 for (block_scope.instructions.items) |inst| {
......@@ -517,6 +521,7 @@ fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError
517521 .decl = parent_block.decl,
518522 .instructions = .{},
519523 .arena = parent_block.arena,
524 .is_comptime = parent_block.is_comptime,
520525 };
521526 defer child_block.instructions.deinit(mod.gpa);
522527
......@@ -529,7 +534,29 @@ fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError
529534 return &loop_inst.base;
530535}
531536
532fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {
537fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_comptime: bool) InnerError!*Inst {
538 const parent_block = scope.cast(Scope.Block).?;
539
540 var child_block: Scope.Block = .{
541 .parent = parent_block,
542 .func = parent_block.func,
543 .decl = parent_block.decl,
544 .instructions = .{},
545 .arena = parent_block.arena,
546 .label = null,
547 .is_comptime = parent_block.is_comptime or is_comptime,
548 };
549 defer child_block.instructions.deinit(mod.gpa);
550
551 try analyzeBody(mod, &child_block.base, inst.positionals.body);
552
553 const copied_instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items);
554 try parent_block.instructions.appendSlice(mod.gpa, copied_instructions);
555
556 return copied_instructions[copied_instructions.len - 1];
557}
558
559fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_comptime: bool) InnerError!*Inst {
533560 const parent_block = scope.cast(Scope.Block).?;
534561
535562 // Reserve space for a Block instruction so that generated Break instructions can
......@@ -557,6 +584,7 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerErr
557584 .results = .{},
558585 .block_inst = block_inst,
559586 }),
587 .is_comptime = is_comptime or parent_block.is_comptime,
560588 };
561589 const label = &child_block.label.?;
562590
......@@ -569,6 +597,28 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerErr
569597 assert(child_block.instructions.items.len != 0);
570598 assert(child_block.instructions.items[child_block.instructions.items.len - 1].ty.isNoReturn());
571599
600 if (label.results.items.len == 0) {
601 // No need for a block instruction. We can put the new instructions directly into the parent block.
602 const copied_instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items);
603 try parent_block.instructions.appendSlice(mod.gpa, copied_instructions);
604 return copied_instructions[copied_instructions.len - 1];
605 }
606 if (label.results.items.len == 1) {
607 const last_inst_index = child_block.instructions.items.len - 1;
608 const last_inst = child_block.instructions.items[last_inst_index];
609 if (last_inst.breakBlock()) |br_block| {
610 if (br_block == block_inst) {
611 // No need for a block instruction. We can put the new instructions directly into the parent block.
612 // Here we omit the break instruction.
613 const copied_instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items[0..last_inst_index]);
614 try parent_block.instructions.appendSlice(mod.gpa, copied_instructions);
615 return label.results.items[0];
616 }
617 }
618 }
619 // It should be impossible to have the number of results be > 1 in a comptime scope.
620 assert(!child_block.is_comptime); // We should have already got a compile error in the condbr condition.
621
572622 // Need to set the type and emit the Block instruction. This allows machine code generation
573623 // to emit a jump instruction to after the block when it encounters the break.
574624 try parent_block.instructions.append(mod.gpa, &block_inst.base);
......@@ -1083,7 +1133,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
10831133 const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr);
10841134 const uncasted_index = try resolveInst(mod, scope, inst.positionals.index);
10851135 const elem_index = try mod.coerce(scope, Type.initTag(.usize), uncasted_index);
1086
1136
10871137 const elem_ty = switch (array_ptr.ty.zigTypeTag()) {
10881138 .Pointer => array_ptr.ty.elemType(),
10891139 else => return mod.fail(scope, inst.positionals.array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}),
......@@ -1376,6 +1426,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE
13761426 .decl = parent_block.decl,
13771427 .instructions = .{},
13781428 .arena = parent_block.arena,
1429 .is_comptime = parent_block.is_comptime,
13791430 };
13801431 defer true_block.instructions.deinit(mod.gpa);
13811432 try analyzeBody(mod, &true_block.base, inst.positionals.then_body);
......@@ -1386,6 +1437,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE
13861437 .decl = parent_block.decl,
13871438 .instructions = .{},
13881439 .arena = parent_block.arena,
1440 .is_comptime = parent_block.is_comptime,
13891441 };
13901442 defer false_block.instructions.deinit(mod.gpa);
13911443 try analyzeBody(mod, &false_block.base, inst.positionals.else_body);
test/stage2/test.zig+1-1
......@@ -274,7 +274,7 @@ pub fn addCases(ctx: *TestContext) !void {
274274 }
275275
276276 {
277 var case = ctx.exe("substracting numbers at runtime", linux_x64);
277 var case = ctx.exe("subtracting numbers at runtime", linux_x64);
278278 case.addCompareOutput(
279279 \\export fn _start() noreturn {
280280 \\ sub(7, 4);