authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-01 19:28:24+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-14 22:18:05+07:00
log94a84e783e32169268809e4aa4bdbfdff92d81e9
tree058f39b3608d1fbc0e360d45d6eaccf53a02067d
parent927706e6d0cf289be979bb6f12be6636c0e07f59

stage2: sparcv9: Implement basic prologue/epilogue Mir emission


3 files changed, 162 insertions(+), 3 deletions(-)

src/arch/sparcv9/CodeGen.zig+101-1
...@@ -382,9 +382,109 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, is_caller: bool) !Ca...@@ -382,9 +382,109 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, is_caller: bool) !Ca
382382
383/// Caller must call `CallMCValues.deinit`.383/// Caller must call `CallMCValues.deinit`.
384fn gen(self: *Self) !void {384fn gen(self: *Self) !void {
385 const cc = self.fn_type.fnCallingConvention();
386 if (cc != .Naked) {
387 // TODO Finish function prologue and epilogue for sparcv9.
388
389 // TODO Backpatch stack offset
390 // save %sp, -176, %sp
391 _ = try self.addInst(.{
392 .tag = .save,
393 .data = .{
394 .arithmetic_3op = .{
395 .is_imm = true,
396 .rd = .sp,
397 .rs1 = .sp,
398 .rs2_or_imm = .{ .imm = -176 },
399 },
400 },
401 });
402
403 _ = try self.addInst(.{
404 .tag = .dbg_prologue_end,
405 .data = .{ .nop = {} },
406 });
407
408 try self.genBody(self.air.getMainBody());
409
410 _ = try self.addInst(.{
411 .tag = .dbg_epilogue_begin,
412 .data = .{ .nop = {} },
413 });
414
415 // exitlude jumps
416 if (self.exitlude_jump_relocs.items.len > 0 and
417 self.exitlude_jump_relocs.items[self.exitlude_jump_relocs.items.len - 1] == self.mir_instructions.len - 2)
418 {
419 // If the last Mir instruction (apart from the
420 // dbg_epilogue_begin) is the last exitlude jump
421 // relocation (which would just jump one instruction
422 // further), it can be safely removed
423 self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.pop());
424 }
425
426 for (self.exitlude_jump_relocs.items) |jmp_reloc| {
427 _ = jmp_reloc;
428 return self.fail("TODO add branches in sparcv9", .{});
429 }
430
431 // return %i7 + 8
432 _ = try self.addInst(.{
433 .tag = .@"return",
434 .data = .{
435 .arithmetic_2op = .{
436 .is_imm = true,
437 .rs1 = .@"i7",
438 .rs2_or_imm = .{ .imm = 8 },
439 },
440 },
441 });
442
443 // TODO Find a way to fill this slot
444 // nop
445 _ = try self.addInst(.{
446 .tag = .nop,
447 .data = .{ .nop = {} },
448 });
449 } else {
450 _ = try self.addInst(.{
451 .tag = .dbg_prologue_end,
452 .data = .{ .nop = {} },
453 });
454
455 try self.genBody(self.air.getMainBody());
456
457 _ = try self.addInst(.{
458 .tag = .dbg_epilogue_begin,
459 .data = .{ .nop = {} },
460 });
461 }
462
463 // Drop them off at the rbrace.
464 _ = try self.addInst(.{
465 .tag = .dbg_line,
466 .data = .{ .dbg_line_column = .{
467 .line = self.end_di_line,
468 .column = self.end_di_column,
469 } },
470 });
471}
472
473fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
385 _ = self;474 _ = self;
475 _ = body;
476
477 @panic("TODO implement genBody");
478}
479
480fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
481 const gpa = self.gpa;
482
483 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);
386484
387 @panic("TODO implement gen");485 const result_index = @intCast(Air.Inst.Index, self.mir_instructions.len);
486 self.mir_instructions.appendAssumeCapacity(inst);
487 return result_index;
388}488}
389489
390fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError {490fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError {
src/arch/sparcv9/Emit.zig+15-1
...@@ -2,6 +2,7 @@...@@ -2,6 +2,7 @@
2//! machine code2//! machine code
33
4const std = @import("std");4const std = @import("std");
5const assert = std.debug.assert;
5const link = @import("../../link.zig");6const link = @import("../../link.zig");
6const Module = @import("../../Module.zig");7const Module = @import("../../Module.zig");
7const ErrorMsg = Module.ErrorMsg;8const ErrorMsg = Module.ErrorMsg;
...@@ -41,9 +42,15 @@ pub fn emitMir(...@@ -41,9 +42,15 @@ pub fn emitMir(
41 const inst = @intCast(u32, index);42 const inst = @intCast(u32, index);
42 switch (tag) {43 switch (tag) {
43 .dbg_line => try emit.mirDbgLine(inst),44 .dbg_line => try emit.mirDbgLine(inst),
44
45 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),45 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
46 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),46 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
47
48 .nop => @panic("TODO implement nop"),
49
50 .save => @panic("TODO implement save"),
51 .restore => @panic("TODO implement restore"),
52
53 .@"return" => @panic("TODO implement return"),
47 }54 }
48 }55 }
49}56}
...@@ -91,3 +98,10 @@ fn mirDebugEpilogueBegin(self: *Emit) !void {...@@ -91,3 +98,10 @@ fn mirDebugEpilogueBegin(self: *Emit) !void {
91 .none => {},98 .none => {},
92 }99 }
93}100}
101
102fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
103 @setCold(true);
104 assert(emit.err_msg == null);
105 emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args);
106 return error.EmitFail;
107}
src/arch/sparcv9/Mir.zig+46-1
...@@ -29,6 +29,22 @@ pub const Inst = struct {...@@ -29,6 +29,22 @@ pub const Inst = struct {
29 dbg_epilogue_begin,29 dbg_epilogue_begin,
30 /// Pseudo-instruction: Update debug line30 /// Pseudo-instruction: Update debug line
31 dbg_line,31 dbg_line,
32
33 // All the real instructions are ordered by their section number
34 // in The SPARC Architecture Manual, Version 9.
35
36 /// A.40 No Operation
37 /// It uses the nop field.
38 nop,
39
40 /// A.46 SAVE and RESTORE
41 /// Those uses the arithmetic_3op field.
42 save,
43 restore,
44
45 /// A.45 RETURN
46 /// It uses the arithmetic_2op field.
47 @"return",
32 };48 };
3349
34 /// The position of an MIR instruction within the `Mir` instructions array.50 /// The position of an MIR instruction within the `Mir` instructions array.
...@@ -42,6 +58,36 @@ pub const Inst = struct {...@@ -42,6 +58,36 @@ pub const Inst = struct {
42 ///58 ///
43 /// Used by e.g. flushw59 /// Used by e.g. flushw
44 nop: void,60 nop: void,
61
62 /// Three operand arithmetic.
63 /// if is_imm true then it uses the imm field of rs2_or_imm,
64 /// otherwise it uses rs2 field.
65 ///
66 /// Used by e.g. add, sub
67 arithmetic_3op: struct {
68 is_imm: bool,
69 rd: Register,
70 rs1: Register,
71 rs2_or_imm: union {
72 rs2: Register,
73 imm: i13,
74 },
75 },
76
77 /// Two operand arithmetic.
78 /// if is_imm true then it uses the imm field of rs2_or_imm,
79 /// otherwise it uses rs2 field.
80 ///
81 /// Used by e.g. return
82 arithmetic_2op: struct {
83 is_imm: bool,
84 rs1: Register,
85 rs2_or_imm: union {
86 rs2: Register,
87 imm: i13,
88 },
89 },
90
45 /// Debug info: line and column91 /// Debug info: line and column
46 ///92 ///
47 /// Used by e.g. dbg_line93 /// Used by e.g. dbg_line
...@@ -77,4 +123,3 @@ pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end...@@ -77,4 +123,3 @@ pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end
77 .end = i,123 .end = i,
78 };124 };
79}125}
80