authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-07 08:01:54+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-07 08:01:54+00:00
logb55d0193e41311532e7b3603b9386863626afcd2
tree99e727cfd24fb359a6ed2b2fdd698c3d11888a88
parent4d01385e147ae36ad96a1c28d2b6fdec69ce69c9

stage2: progress towards Block and CondBr codegen


4 files changed, 55 insertions(+), 15 deletions(-)

src-self-hosted/Module.zig+6-13
...@@ -2545,18 +2545,6 @@ fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerEr...@@ -2545,18 +2545,6 @@ fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerEr
2545 assert(child_block.instructions.items.len != 0);2545 assert(child_block.instructions.items.len != 0);
2546 assert(child_block.instructions.items[child_block.instructions.items.len - 1].tag.isNoReturn());2546 assert(child_block.instructions.items[child_block.instructions.items.len - 1].tag.isNoReturn());
25472547
2548 if (label.results.items.len <= 1) {
2549 // No need to add the Block instruction; we can add the instructions to the parent block directly.
2550 // Blocks are terminated with a noreturn instruction which we do not want to include.
2551 const instrs = child_block.instructions.items;
2552 try parent_block.instructions.appendSlice(self.gpa, instrs[0 .. instrs.len - 1]);
2553 if (label.results.items.len == 1) {
2554 return label.results.items[0];
2555 } else {
2556 return self.constNoReturn(scope, inst.base.src);
2557 }
2558 }
2559
2560 // Need to set the type and emit the Block instruction. This allows machine code generation2548 // Need to set the type and emit the Block instruction. This allows machine code generation
2561 // to emit a jump instruction to after the block when it encounters the break.2549 // to emit a jump instruction to after the block when it encounters the break.
2562 try parent_block.instructions.append(self.gpa, &block_inst.base);2550 try parent_block.instructions.append(self.gpa, &block_inst.base);
...@@ -2579,7 +2567,10 @@ fn analyzeInstBreakVoid(self: *Module, scope: *Scope, inst: *zir.Inst.BreakVoid)...@@ -2579,7 +2567,10 @@ fn analyzeInstBreakVoid(self: *Module, scope: *Scope, inst: *zir.Inst.BreakVoid)
2579 if (block.label) |*label| {2567 if (block.label) |*label| {
2580 if (mem.eql(u8, label.name, label_name)) {2568 if (mem.eql(u8, label.name, label_name)) {
2581 try label.results.append(self.gpa, void_inst);2569 try label.results.append(self.gpa, void_inst);
2582 return self.constNoReturn(scope, inst.base.src);2570 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2571 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.noreturn), Inst.BreakVoid, .{
2572 .block = label.block_inst,
2573 });
2583 }2574 }
2584 }2575 }
2585 opt_block = block.parent;2576 opt_block = block.parent;
...@@ -3366,6 +3357,8 @@ fn makeIntType(self: *Module, scope: *Scope, signed: bool, bits: u16) !Type {...@@ -3366,6 +3357,8 @@ fn makeIntType(self: *Module, scope: *Scope, signed: bool, bits: u16) !Type {
3366fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Type {3357fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Type {
3367 if (instructions.len == 0)3358 if (instructions.len == 0)
3368 return Type.initTag(.noreturn);3359 return Type.initTag(.noreturn);
3360 if (instructions.len == 1)
3361 return instructions[0].ty;
3369 return self.fail(scope, instructions[0].src, "TODO peer type resolution", .{});3362 return self.fail(scope, instructions[0].src, "TODO peer type resolution", .{});
3370}3363}
33713364
src-self-hosted/codegen.zig+19-2
...@@ -218,6 +218,11 @@ pub fn generateSymbol(...@@ -218,6 +218,11 @@ pub fn generateSymbol(
218 }218 }
219}219}
220220
221const InnerError = error {
222 OutOfMemory,
223 CodegenFail,
224};
225
221const Function = struct {226const Function = struct {
222 gpa: *Allocator,227 gpa: *Allocator,
223 bin_file: *link.ElfFile,228 bin_file: *link.ElfFile,
...@@ -379,8 +384,12 @@ const Function = struct {...@@ -379,8 +384,12 @@ const Function = struct {
379 }384 }
380385
381 fn genArch(self: *Function, comptime arch: std.Target.Cpu.Arch) !void {386 fn genArch(self: *Function, comptime arch: std.Target.Cpu.Arch) !void {
387 return self.genBody(self.mod_fn.analysis.success, arch);
388 }
389
390 fn genBody(self: *Function, body: ir.Body, comptime arch: std.Target.Cpu.Arch) InnerError!void {
382 const inst_table = &self.branch_stack.items[0].inst_table;391 const inst_table = &self.branch_stack.items[0].inst_table;
383 for (self.mod_fn.analysis.success.instructions) |inst| {392 for (body.instructions) |inst| {
384 const new_inst = try self.genFuncInst(inst, arch);393 const new_inst = try self.genFuncInst(inst, arch);
385 try inst_table.putNoClobber(self.gpa, inst, new_inst);394 try inst_table.putNoClobber(self.gpa, inst, new_inst);
386 }395 }
...@@ -394,6 +403,7 @@ const Function = struct {...@@ -394,6 +403,7 @@ const Function = struct {
394 .bitcast => return self.genBitCast(inst.cast(ir.Inst.BitCast).?),403 .bitcast => return self.genBitCast(inst.cast(ir.Inst.BitCast).?),
395 .block => return self.genBlock(inst.cast(ir.Inst.Block).?, arch),404 .block => return self.genBlock(inst.cast(ir.Inst.Block).?, arch),
396 .breakpoint => return self.genBreakpoint(inst.src, arch),405 .breakpoint => return self.genBreakpoint(inst.src, arch),
406 .breakvoid => return self.genBreakVoid(inst.cast(ir.Inst.BreakVoid).?, arch),
397 .call => return self.genCall(inst.cast(ir.Inst.Call).?, arch),407 .call => return self.genCall(inst.cast(ir.Inst.Call).?, arch),
398 .cmp => return self.genCmp(inst.cast(ir.Inst.Cmp).?, arch),408 .cmp => return self.genCmp(inst.cast(ir.Inst.Cmp).?, arch),
399 .condbr => return self.genCondBr(inst.cast(ir.Inst.CondBr).?, arch),409 .condbr => return self.genCondBr(inst.cast(ir.Inst.CondBr).?, arch),
...@@ -686,9 +696,16 @@ const Function = struct {...@@ -686,9 +696,16 @@ const Function = struct {
686 }696 }
687697
688 fn genBlock(self: *Function, inst: *ir.Inst.Block, comptime arch: std.Target.Cpu.Arch) !MCValue {698 fn genBlock(self: *Function, inst: *ir.Inst.Block, comptime arch: std.Target.Cpu.Arch) !MCValue {
699 // A block is nothing but a setup to be able to jump to the end.
700 try self.genBody(inst.args.body, arch);
701 return self.fail(inst.base.src, "TODO process jump relocs after block end", .{});
702 }
703
704 fn genBreakVoid(self: *Function, inst: *ir.Inst.BreakVoid, comptime arch: std.Target.Cpu.Arch) !MCValue {
689 switch (arch) {705 switch (arch) {
690 else => return self.fail(inst.base.src, "TODO implement codegen Block for {}", .{self.target.cpu.arch}),706 else => return self.fail(inst.base.src, "TODO implement breakvoid for {}", .{self.target.cpu.arch}),
691 }707 }
708 return .none;
692 }709 }
693710
694 fn genAsm(self: *Function, inst: *ir.Inst.Assembly, comptime arch: Target.Cpu.Arch) !MCValue {711 fn genAsm(self: *Function, inst: *ir.Inst.Assembly, comptime arch: Target.Cpu.Arch) !MCValue {
src-self-hosted/ir.zig+14
...@@ -35,6 +35,10 @@ pub const Inst = struct {...@@ -35,6 +35,10 @@ pub const Inst = struct {
35 return @truncate(u1, self.deaths << index) != 0;35 return @truncate(u1, self.deaths << index) != 0;
36 }36 }
3737
38 pub fn specialOperandDeaths(self: Inst) bool {
39 return (self.deaths & 0b1000_0000) != 0;
40 }
41
38 pub const Tag = enum {42 pub const Tag = enum {
39 add,43 add,
40 arg,44 arg,
...@@ -42,6 +46,7 @@ pub const Inst = struct {...@@ -42,6 +46,7 @@ pub const Inst = struct {
42 bitcast,46 bitcast,
43 block,47 block,
44 breakpoint,48 breakpoint,
49 breakvoid,
45 call,50 call,
46 cmp,51 cmp,
47 condbr,52 condbr,
...@@ -74,6 +79,7 @@ pub const Inst = struct {...@@ -74,6 +79,7 @@ pub const Inst = struct {
74 .sub,79 .sub,
75 => false,80 => false,
7681
82 .breakvoid,
77 .condbr,83 .condbr,
78 .ret,84 .ret,
79 .retvoid,85 .retvoid,
...@@ -159,6 +165,14 @@ pub const Inst = struct {...@@ -159,6 +165,14 @@ pub const Inst = struct {
159 args: void,165 args: void,
160 };166 };
161167
168 pub const BreakVoid = struct {
169 pub const base_tag = Tag.breakvoid;
170 base: Inst,
171 args: struct {
172 block: *Block,
173 },
174 };
175
162 pub const Call = struct {176 pub const Call = struct {
163 pub const base_tag = Tag.call;177 pub const base_tag = Tag.call;
164 base: Inst,178 base: Inst,
src-self-hosted/zir.zig+16
...@@ -1608,6 +1608,22 @@ const EmitZIR = struct {...@@ -1608,6 +1608,22 @@ const EmitZIR = struct {
1608 break :blk &new_inst.base;1608 break :blk &new_inst.base;
1609 },1609 },
1610 .breakpoint => try self.emitTrivial(inst.src, Inst.Breakpoint),1610 .breakpoint => try self.emitTrivial(inst.src, Inst.Breakpoint),
1611 .breakvoid => blk: {
1612 const old_inst = inst.cast(ir.Inst.BreakVoid).?;
1613 const new_block = inst_table.get(&old_inst.args.block.base).?;
1614 const new_inst = try self.arena.allocator.create(Inst.BreakVoid);
1615 new_inst.* = .{
1616 .base = .{
1617 .src = inst.src,
1618 .tag = Inst.BreakVoid.base_tag,
1619 },
1620 .positionals = .{
1621 .label = new_block.cast(Inst.Block).?.positionals.label,
1622 },
1623 .kw_args = .{},
1624 };
1625 break :blk &new_inst.base;
1626 },
1611 .call => blk: {1627 .call => blk: {
1612 const old_inst = inst.cast(ir.Inst.Call).?;1628 const old_inst = inst.cast(ir.Inst.Call).?;
1613 const new_inst = try self.arena.allocator.create(Inst.Call);1629 const new_inst = try self.arena.allocator.create(Inst.Call);