authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-12 21:13:07-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-12 21:13:16-07:00
logde4f3f11f735708cf9ffe4bbdbbfa693b6b07916
treea5c68b84d6f8b9d69093bc9bafea5bf3ad112bcd
parent30db5b1fb23502de02650473ff8282b2875650a9

stage2: astgen for while loops

See #6021

6 files changed, 269 insertions(+), 21 deletions(-)

src-self-hosted/astgen.zig+158-18
......@@ -48,20 +48,21 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z
4848pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {
4949 switch (node.tag) {
5050 .VarDecl => unreachable, // Handled in `blockExpr`.
51 .Assign => unreachable, // Handled in `blockExpr`.
52 .AssignBitAnd => unreachable, // Handled in `blockExpr`.
53 .AssignBitOr => unreachable, // Handled in `blockExpr`.
54 .AssignBitShiftLeft => unreachable, // Handled in `blockExpr`.
55 .AssignBitShiftRight => unreachable, // Handled in `blockExpr`.
56 .AssignBitXor => unreachable, // Handled in `blockExpr`.
57 .AssignDiv => unreachable, // Handled in `blockExpr`.
58 .AssignSub => unreachable, // Handled in `blockExpr`.
59 .AssignSubWrap => unreachable, // Handled in `blockExpr`.
60 .AssignMod => unreachable, // Handled in `blockExpr`.
61 .AssignAdd => unreachable, // Handled in `blockExpr`.
62 .AssignAddWrap => unreachable, // Handled in `blockExpr`.
63 .AssignMul => unreachable, // Handled in `blockExpr`.
64 .AssignMulWrap => unreachable, // Handled in `blockExpr`.
51
52 .Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)),
53 .AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)),
54 .AssignBitOr => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitOr).?, .bitor)),
55 .AssignBitShiftLeft => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftLeft).?, .shl)),
56 .AssignBitShiftRight => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftRight).?, .shr)),
57 .AssignBitXor => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitXor).?, .xor)),
58 .AssignDiv => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignDiv).?, .div)),
59 .AssignSub => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSub).?, .sub)),
60 .AssignSubWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSubWrap).?, .subwrap)),
61 .AssignMod => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMod).?, .mod_rem)),
62 .AssignAdd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAdd).?, .add)),
63 .AssignAddWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAddWrap).?, .addwrap)),
64 .AssignMul => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMul).?, .mul)),
65 .AssignMulWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMulWrap).?, .mulwrap)),
6566
6667 .Add => return simpleBinOp(mod, scope, rl, node.castTag(.Add).?, .add),
6768 .AddWrap => return simpleBinOp(mod, scope, rl, node.castTag(.AddWrap).?, .addwrap),
......@@ -96,6 +97,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
9697 .Unreachable => return unreach(mod, scope, node.castTag(.Unreachable).?),
9798 .Return => return ret(mod, scope, node.castTag(.Return).?),
9899 .If => return ifExpr(mod, scope, rl, node.castTag(.If).?),
100 .While => return whileExpr(mod, scope, rl, node.castTag(.While).?),
99101 .Period => return rlWrap(mod, scope, rl, try field(mod, scope, node.castTag(.Period).?)),
100102 .Deref => return rlWrap(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)),
101103 .BoolNot => return rlWrap(mod, scope, rl, try boolNot(mod, scope, node.castTag(.BoolNot).?)),
......@@ -127,10 +129,7 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block
127129 const var_decl_node = statement.castTag(.VarDecl).?;
128130 scope = try varDecl(mod, scope, var_decl_node, &block_arena.allocator);
129131 },
130 .Assign => {
131 const ass = statement.castTag(.Assign).?;
132 try assign(mod, scope, ass);
133 },
132 .Assign => try assign(mod, scope, statement.castTag(.Assign).?),
134133 .AssignBitAnd => try assignOp(mod, scope, statement.castTag(.AssignBitAnd).?, .bitand),
135134 .AssignBitOr => try assignOp(mod, scope, statement.castTag(.AssignBitOr).?, .bitor),
136135 .AssignBitShiftLeft => try assignOp(mod, scope, statement.castTag(.AssignBitShiftLeft).?, .shl),
......@@ -454,6 +453,132 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
454453 return &block.base;
455454}
456455
456fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.While) InnerError!*zir.Inst {
457 if (while_node.payload) |payload| {
458 return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for optionals", .{});
459 }
460 if (while_node.@"else") |else_node| {
461 if (else_node.payload) |payload| {
462 return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for error unions", .{});
463 }
464 }
465
466 var expr_scope: Scope.GenZIR = .{
467 .parent = scope,
468 .decl = scope.decl().?,
469 .arena = scope.arena(),
470 .instructions = .{},
471 };
472 defer expr_scope.instructions.deinit(mod.gpa);
473
474 var loop_scope: Scope.GenZIR = .{
475 .parent = &expr_scope.base,
476 .decl = expr_scope.decl,
477 .arena = expr_scope.arena,
478 .instructions = .{},
479 };
480 defer loop_scope.instructions.deinit(mod.gpa);
481
482 var continue_scope: Scope.GenZIR = .{
483 .parent = &loop_scope.base,
484 .decl = loop_scope.decl,
485 .arena = loop_scope.arena,
486 .instructions = .{},
487 };
488 defer continue_scope.instructions.deinit(mod.gpa);
489
490 const tree = scope.tree();
491 const while_src = tree.token_locs[while_node.while_token].start;
492 const bool_type = try addZIRInstConst(mod, scope, while_src, .{
493 .ty = Type.initTag(.type),
494 .val = Value.initTag(.bool_type),
495 });
496 const void_type = try addZIRInstConst(mod, scope, while_src, .{
497 .ty = Type.initTag(.type),
498 .val = Value.initTag(.void_type),
499 });
500 const cond = try expr(mod, &continue_scope.base, .{ .ty = bool_type }, while_node.condition);
501
502 const condbr = try addZIRInstSpecial(mod, &continue_scope.base, while_src, zir.Inst.CondBr, .{
503 .condition = cond,
504 .then_body = undefined, // populated below
505 .else_body = undefined, // populated below
506 }, .{});
507 const cond_block = try addZIRInstBlock(mod, &loop_scope.base, while_src, .{
508 .instructions = try loop_scope.arena.dupe(*zir.Inst, continue_scope.instructions.items),
509 });
510 if (while_node.continue_expr) |cont_expr| {
511 const cont_expr_result = try expr(mod, &loop_scope.base, .{ .ty = void_type }, cont_expr);
512 if (!cont_expr_result.tag.isNoReturn()) {
513 _ = try addZIRNoOp(mod, &loop_scope.base, while_src, .repeat);
514 }
515 } else {
516 _ = try addZIRNoOp(mod, &loop_scope.base, while_src, .repeat);
517 }
518 const loop = try addZIRInstLoop(mod, &expr_scope.base, while_src, .{
519 .instructions = try expr_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),
520 });
521 const while_block = try addZIRInstBlock(mod, scope, while_src, .{
522 .instructions = try expr_scope.arena.dupe(*zir.Inst, expr_scope.instructions.items),
523 });
524 var then_scope: Scope.GenZIR = .{
525 .parent = &continue_scope.base,
526 .decl = continue_scope.decl,
527 .arena = continue_scope.arena,
528 .instructions = .{},
529 };
530 defer then_scope.instructions.deinit(mod.gpa);
531
532 // Most result location types can be forwarded directly; however
533 // if we need to write to a pointer which has an inferred type,
534 // proper type inference requires peer type resolution on the while's
535 // branches.
536 const branch_rl: ResultLoc = switch (rl) {
537 .discard, .none, .ty, .ptr, .lvalue => rl,
538 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
539 };
540
541 const then_result = try expr(mod, &then_scope.base, branch_rl, while_node.body);
542 if (!then_result.tag.isNoReturn()) {
543 const then_src = tree.token_locs[while_node.body.lastToken()].start;
544 _ = try addZIRInst(mod, &then_scope.base, then_src, zir.Inst.Break, .{
545 .block = cond_block,
546 .operand = then_result,
547 }, .{});
548 }
549 condbr.positionals.then_body = .{
550 .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items),
551 };
552
553 var else_scope: Scope.GenZIR = .{
554 .parent = &continue_scope.base,
555 .decl = continue_scope.decl,
556 .arena = continue_scope.arena,
557 .instructions = .{},
558 };
559 defer else_scope.instructions.deinit(mod.gpa);
560
561 if (while_node.@"else") |else_node| {
562 const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body);
563 if (!else_result.tag.isNoReturn()) {
564 const else_src = tree.token_locs[else_node.body.lastToken()].start;
565 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{
566 .block = while_block,
567 .operand = else_result,
568 }, .{});
569 }
570 } else {
571 const else_src = tree.token_locs[while_node.lastToken()].start;
572 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{
573 .block = while_block,
574 }, .{});
575 }
576 condbr.positionals.else_body = .{
577 .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
578 };
579 return &while_block.base;
580}
581
457582fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst {
458583 const tree = scope.tree();
459584 const src = tree.token_locs[cfe.ltoken].start;
......@@ -1094,6 +1219,15 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
10941219 }
10951220}
10961221
1222fn rlWrapVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, result: void) InnerError!*zir.Inst {
1223 const src = scope.tree().token_locs[node.firstToken()].start;
1224 const void_inst = try addZIRInstConst(mod, scope, src, .{
1225 .ty = Type.initTag(.void),
1226 .val = Value.initTag(.void_value),
1227 });
1228 return rlWrap(mod, scope, rl, void_inst);
1229}
1230
10971231pub fn addZIRInstSpecial(
10981232 mod: *Module,
10991233 scope: *Scope,
......@@ -1211,3 +1345,9 @@ pub fn addZIRInstBlock(mod: *Module, scope: *Scope, src: usize, body: zir.Module
12111345 const P = std.meta.fieldInfo(zir.Inst.Block, "positionals").field_type;
12121346 return addZIRInstSpecial(mod, scope, src, zir.Inst.Block, P{ .body = body }, .{});
12131347}
1348
1349/// TODO The existence of this function is a workaround for a bug in stage1.
1350pub fn addZIRInstLoop(mod: *Module, scope: *Scope, src: usize, body: zir.Module.Body) !*zir.Inst.Loop {
1351 const P = std.meta.fieldInfo(zir.Inst.Loop, "positionals").field_type;
1352 return addZIRInstSpecial(mod, scope, src, zir.Inst.Loop, P{ .body = body }, .{});
1353}
src-self-hosted/codegen.zig+7
......@@ -23,6 +23,8 @@ pub const BlockData = struct {
2323 relocs: std.ArrayListUnmanaged(Reloc) = .{},
2424};
2525
26pub const LoopData = struct { };
27
2628pub const Reloc = union(enum) {
2729 /// The value is an offset into the `Function` `code` from the beginning.
2830 /// To perform the reloc, write 32-bit signed little-endian integer
......@@ -657,6 +659,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
657659 .isnonnull => return self.genIsNonNull(inst.castTag(.isnonnull).?),
658660 .isnull => return self.genIsNull(inst.castTag(.isnull).?),
659661 .load => return self.genLoad(inst.castTag(.load).?),
662 .loop => return self.genLoop(inst.castTag(.loop).?),
660663 .not => return self.genNot(inst.castTag(.not).?),
661664 .ptrtoint => return self.genPtrToInt(inst.castTag(.ptrtoint).?),
662665 .ref => return self.genRef(inst.castTag(.ref).?),
......@@ -1346,6 +1349,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
13461349 }
13471350 }
13481351
1352 fn genLoop(self: *Self, inst: *ir.Inst.Loop) !MCValue {
1353 return self.fail(inst.base.src, "TODO codegen loop", .{});
1354 }
1355
13491356 fn genBlock(self: *Self, inst: *ir.Inst.Block) !MCValue {
13501357 if (inst.base.ty.hasCodeGenBits()) {
13511358 return self.fail(inst.base.src, "TODO codegen Block with non-void type", .{});
src-self-hosted/ir.zig+19
......@@ -70,6 +70,7 @@ pub const Inst = struct {
7070 isnull,
7171 /// Read a value from a pointer.
7272 load,
73 loop,
7374 ptrtoint,
7475 ref,
7576 ret,
......@@ -122,6 +123,7 @@ pub const Inst = struct {
122123 .call => Call,
123124 .condbr => CondBr,
124125 .constant => Constant,
126 .loop => Loop,
125127 };
126128 }
127129
......@@ -401,6 +403,23 @@ pub const Inst = struct {
401403 return null;
402404 }
403405 };
406
407 pub const Loop = struct {
408 pub const base_tag = Tag.loop;
409
410 base: Inst,
411 body: Body,
412 /// This memory is reserved for codegen code to do whatever it needs to here.
413 codegen: codegen.LoopData = .{},
414
415 pub fn operandCount(self: *const Loop) usize {
416 return 0;
417 }
418 pub fn getOperand(self: *const Loop, index: usize) ?*Inst {
419 return null;
420 }
421 };
422
404423};
405424
406425pub const Body = struct {
src-self-hosted/link.zig-3
......@@ -1484,9 +1484,6 @@ pub const File = struct {
14841484 assert(!self.shdr_table_dirty);
14851485 assert(!self.shstrtab_dirty);
14861486 assert(!self.debug_strtab_dirty);
1487 assert(!self.offset_table_count_dirty);
1488 const syms_sect = &self.sections.items[self.symtab_section_index.?];
1489 assert(syms_sect.sh_info == self.local_symbols.items.len);
14901487 }
14911488
14921489 fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void {
src-self-hosted/zir.zig+75
......@@ -151,6 +151,8 @@ pub const Inst = struct {
151151 isnonnull,
152152 /// Return a boolean true if an optional is null. `x == null`
153153 isnull,
154 /// A labeled block of code that loops forever.
155 loop,
154156 /// Ambiguously remainder division or modulus. If the computation would possibly have
155157 /// a different value depending on whether the operation is remainder division or modulus,
156158 /// a compile error is emitted. Otherwise the computation is performed.
......@@ -173,6 +175,8 @@ pub const Inst = struct {
173175 /// the memory location is in the stack frame, local to the scope containing the
174176 /// instruction.
175177 ref,
178 /// Sends control flow back to the loop block operand.
179 repeat,
176180 /// Obtains a pointer to the return value.
177181 ret_ptr,
178182 /// Obtains the return type of the in-scope function.
......@@ -279,7 +283,9 @@ pub const Inst = struct {
279283 .declval_in_module => DeclValInModule,
280284 .coerce_result_block_ptr => CoerceResultBlockPtr,
281285 .compileerror => CompileError,
286 .loop => Loop,
282287 .@"const" => Const,
288 .repeat => Repeat,
283289 .str => Str,
284290 .int => Int,
285291 .inttype => IntType,
......@@ -372,10 +378,12 @@ pub const Inst = struct {
372378 .breakvoid,
373379 .condbr,
374380 .compileerror,
381 .repeat,
375382 .@"return",
376383 .returnvoid,
377384 .unreach_nocheck,
378385 .@"unreachable",
386 .loop,
379387 => true,
380388 };
381389 }
......@@ -567,6 +575,16 @@ pub const Inst = struct {
567575 kw_args: struct {},
568576 };
569577
578 pub const Repeat = struct {
579 pub const base_tag = Tag.repeat;
580 base: Inst,
581
582 positionals: struct {
583 loop: *Loop,
584 },
585 kw_args: struct {},
586 };
587
570588 pub const Str = struct {
571589 pub const base_tag = Tag.str;
572590 base: Inst,
......@@ -587,6 +605,16 @@ pub const Inst = struct {
587605 kw_args: struct {},
588606 };
589607
608 pub const Loop = struct {
609 pub const base_tag = Tag.loop;
610 base: Inst,
611
612 positionals: struct {
613 body: Module.Body,
614 },
615 kw_args: struct {},
616 };
617
590618 pub const FieldPtr = struct {
591619 pub const base_tag = Tag.fieldptr;
592620 base: Inst,
......@@ -848,12 +876,14 @@ pub const Module = struct {
848876 .module = &self,
849877 .inst_table = InstPtrTable.init(allocator),
850878 .block_table = std.AutoHashMap(*Inst.Block, []const u8).init(allocator),
879 .loop_table = std.AutoHashMap(*Inst.Loop, []const u8).init(allocator),
851880 .arena = std.heap.ArenaAllocator.init(allocator),
852881 .indent = 2,
853882 };
854883 defer write.arena.deinit();
855884 defer write.inst_table.deinit();
856885 defer write.block_table.deinit();
886 defer write.loop_table.deinit();
857887
858888 // First, build a map of *Inst to @ or % indexes
859889 try write.inst_table.ensureCapacity(self.decls.len);
......@@ -882,6 +912,7 @@ const Writer = struct {
882912 module: *const Module,
883913 inst_table: InstPtrTable,
884914 block_table: std.AutoHashMap(*Inst.Block, []const u8),
915 loop_table: std.AutoHashMap(*Inst.Loop, []const u8),
885916 arena: std.heap.ArenaAllocator,
886917 indent: usize,
887918
......@@ -962,6 +993,9 @@ const Writer = struct {
962993 if (inst.cast(Inst.Block)) |block| {
963994 const name = try std.fmt.allocPrint(&self.arena.allocator, "label_{}", .{i});
964995 try self.block_table.put(block, name);
996 } else if (inst.cast(Inst.Loop)) |loop| {
997 const name = try std.fmt.allocPrint(&self.arena.allocator, "loop_{}", .{i});
998 try self.loop_table.put(loop, name);
965999 }
9661000 self.indent += 2;
9671001 try self.writeInstToStream(stream, inst);
......@@ -980,6 +1014,10 @@ const Writer = struct {
9801014 const name = self.block_table.get(param).?;
9811015 return std.zig.renderStringLiteral(name, stream);
9821016 },
1017 *Inst.Loop => {
1018 const name = self.loop_table.get(param).?;
1019 return std.zig.renderStringLiteral(name, stream);
1020 },
9831021 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),
9841022 }
9851023 }
......@@ -1016,8 +1054,10 @@ pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module
10161054 .decls = .{},
10171055 .unnamed_index = 0,
10181056 .block_table = std.StringHashMap(*Inst.Block).init(allocator),
1057 .loop_table = std.StringHashMap(*Inst.Loop).init(allocator),
10191058 };
10201059 defer parser.block_table.deinit();
1060 defer parser.loop_table.deinit();
10211061 errdefer parser.arena.deinit();
10221062
10231063 parser.parseRoot() catch |err| switch (err) {
......@@ -1044,6 +1084,7 @@ const Parser = struct {
10441084 error_msg: ?ErrorMsg = null,
10451085 unnamed_index: usize,
10461086 block_table: std.StringHashMap(*Inst.Block),
1087 loop_table: std.StringHashMap(*Inst.Loop),
10471088
10481089 const Body = struct {
10491090 instructions: std.ArrayList(*Inst),
......@@ -1255,6 +1296,8 @@ const Parser = struct {
12551296
12561297 if (InstType == Inst.Block) {
12571298 try self.block_table.put(inst_name, inst_specific);
1299 } else if (InstType == Inst.Loop) {
1300 try self.loop_table.put(inst_name, inst_specific);
12581301 }
12591302
12601303 if (@hasField(InstType, "ty")) {
......@@ -1366,6 +1409,10 @@ const Parser = struct {
13661409 const name = try self.parseStringLiteral();
13671410 return self.block_table.get(name).?;
13681411 },
1412 *Inst.Loop => {
1413 const name = try self.parseStringLiteral();
1414 return self.loop_table.get(name).?;
1415 },
13691416 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
13701417 }
13711418 return self.fail("TODO parse parameter {}", .{@typeName(T)});
......@@ -1431,8 +1478,10 @@ pub fn emit(allocator: *Allocator, old_module: IrModule) !Module {
14311478 .primitive_table = std.AutoHashMap(Inst.Primitive.Builtin, *Decl).init(allocator),
14321479 .indent = 0,
14331480 .block_table = std.AutoHashMap(*ir.Inst.Block, *Inst.Block).init(allocator),
1481 .loop_table = std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop).init(allocator),
14341482 };
14351483 defer ctx.block_table.deinit();
1484 defer ctx.loop_table.deinit();
14361485 defer ctx.decls.deinit(allocator);
14371486 defer ctx.names.deinit();
14381487 defer ctx.primitive_table.deinit();
......@@ -1456,6 +1505,7 @@ const EmitZIR = struct {
14561505 primitive_table: std.AutoHashMap(Inst.Primitive.Builtin, *Decl),
14571506 indent: usize,
14581507 block_table: std.AutoHashMap(*ir.Inst.Block, *Inst.Block),
1508 loop_table: std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop),
14591509
14601510 fn emit(self: *EmitZIR) !void {
14611511 // Put all the Decls in a list and sort them by name to avoid nondeterminism introduced
......@@ -1936,6 +1986,31 @@ const EmitZIR = struct {
19361986 break :blk &new_inst.base;
19371987 },
19381988
1989 .loop => blk: {
1990 const old_inst = inst.castTag(.loop).?;
1991 const new_inst = try self.arena.allocator.create(Inst.Loop);
1992
1993 try self.loop_table.put(old_inst, new_inst);
1994
1995 var loop_body = std.ArrayList(*Inst).init(self.allocator);
1996 defer loop_body.deinit();
1997
1998 try self.emitBody(old_inst.body, inst_table, &loop_body);
1999
2000 new_inst.* = .{
2001 .base = .{
2002 .src = inst.src,
2003 .tag = Inst.Loop.base_tag,
2004 },
2005 .positionals = .{
2006 .body = .{ .instructions = loop_body.toOwnedSlice() },
2007 },
2008 .kw_args = .{},
2009 };
2010
2011 break :blk &new_inst.base;
2012 },
2013
19392014 .brvoid => blk: {
19402015 const old_inst = inst.cast(ir.Inst.BrVoid).?;
19412016 const new_block = self.block_table.get(old_inst.block).?;
src-self-hosted/zir_sema.zig+10
......@@ -60,6 +60,8 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
6060 return mod.constIntBig(scope, old_inst.src, Type.initTag(.comptime_int), big_int);
6161 },
6262 .inttype => return analyzeInstIntType(mod, scope, old_inst.castTag(.inttype).?),
63 .loop => return analyzeInstLoop(mod, scope, old_inst.castTag(.loop).?),
64 .repeat => return analyzeInstRepeat(mod, scope, old_inst.castTag(.repeat).?),
6365 .param_type => return analyzeInstParamType(mod, scope, old_inst.castTag(.param_type).?),
6466 .ptrtoint => return analyzeInstPtrToInt(mod, scope, old_inst.castTag(.ptrtoint).?),
6567 .fieldptr => return analyzeInstFieldPtr(mod, scope, old_inst.castTag(.fieldptr).?),
......@@ -424,6 +426,14 @@ fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*
424426 return mod.addArg(b, inst.base.src, param_type, name);
425427}
426428
429fn analyzeInstRepeat(mod: *Module, scope: *Scope, inst: *zir.Inst.Repeat) InnerError!*Inst {
430 return mod.fail(scope, inst.base.src, "TODO analyze .repeat ZIR", .{});
431}
432
433fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError!*Inst {
434 return mod.fail(scope, inst.base.src, "TODO analyze .loop ZIR", .{});
435}
436
427437fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {
428438 const parent_block = scope.cast(Scope.Block).?;
429439