Commit 94a84e783e

Koakuma <koachan@protonmail.com>
2022-04-01 14:28:24
stage2: sparcv9: Implement basic prologue/epilogue Mir emission
1 parent 927706e
Changed files (3)
src/arch/sparcv9/CodeGen.zig
@@ -382,9 +382,109 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, is_caller: bool) !Ca
 
 /// Caller must call `CallMCValues.deinit`.
 fn gen(self: *Self) !void {
+    const cc = self.fn_type.fnCallingConvention();
+    if (cc != .Naked) {
+        // TODO Finish function prologue and epilogue for sparcv9.
+
+        // TODO Backpatch stack offset
+        // save %sp, -176, %sp
+        _ = try self.addInst(.{
+            .tag = .save,
+            .data = .{
+                .arithmetic_3op = .{
+                    .is_imm = true,
+                    .rd = .sp,
+                    .rs1 = .sp,
+                    .rs2_or_imm = .{ .imm = -176 },
+                },
+            },
+        });
+
+        _ = try self.addInst(.{
+            .tag = .dbg_prologue_end,
+            .data = .{ .nop = {} },
+        });
+
+        try self.genBody(self.air.getMainBody());
+
+        _ = try self.addInst(.{
+            .tag = .dbg_epilogue_begin,
+            .data = .{ .nop = {} },
+        });
+
+        // exitlude jumps
+        if (self.exitlude_jump_relocs.items.len > 0 and
+            self.exitlude_jump_relocs.items[self.exitlude_jump_relocs.items.len - 1] == self.mir_instructions.len - 2)
+        {
+            // If the last Mir instruction (apart from the
+            // dbg_epilogue_begin) is the last exitlude jump
+            // relocation (which would just jump one instruction
+            // further), it can be safely removed
+            self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.pop());
+        }
+
+        for (self.exitlude_jump_relocs.items) |jmp_reloc| {
+            _ = jmp_reloc;
+            return self.fail("TODO add branches in sparcv9", .{});
+        }
+
+        // return %i7 + 8
+        _ = try self.addInst(.{
+            .tag = .@"return",
+            .data = .{
+                .arithmetic_2op = .{
+                    .is_imm = true,
+                    .rs1 = .@"i7",
+                    .rs2_or_imm = .{ .imm = 8 },
+                },
+            },
+        });
+
+        // TODO Find a way to fill this slot
+        // nop
+        _ = try self.addInst(.{
+            .tag = .nop,
+            .data = .{ .nop = {} },
+        });
+    } else {
+        _ = try self.addInst(.{
+            .tag = .dbg_prologue_end,
+            .data = .{ .nop = {} },
+        });
+
+        try self.genBody(self.air.getMainBody());
+
+        _ = try self.addInst(.{
+            .tag = .dbg_epilogue_begin,
+            .data = .{ .nop = {} },
+        });
+    }
+
+    // Drop them off at the rbrace.
+    _ = try self.addInst(.{
+        .tag = .dbg_line,
+        .data = .{ .dbg_line_column = .{
+            .line = self.end_di_line,
+            .column = self.end_di_column,
+        } },
+    });
+}
+
+fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
     _ = self;
+    _ = body;
+
+    @panic("TODO implement genBody");
+}
+
+fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
+    const gpa = self.gpa;
+
+    try self.mir_instructions.ensureUnusedCapacity(gpa, 1);
 
-    @panic("TODO implement gen");
+    const result_index = @intCast(Air.Inst.Index, self.mir_instructions.len);
+    self.mir_instructions.appendAssumeCapacity(inst);
+    return result_index;
 }
 
 fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError {
src/arch/sparcv9/Emit.zig
@@ -2,6 +2,7 @@
 //! machine code
 
 const std = @import("std");
+const assert = std.debug.assert;
 const link = @import("../../link.zig");
 const Module = @import("../../Module.zig");
 const ErrorMsg = Module.ErrorMsg;
@@ -41,9 +42,15 @@ pub fn emitMir(
         const inst = @intCast(u32, index);
         switch (tag) {
             .dbg_line => try emit.mirDbgLine(inst),
-
             .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
             .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
+
+            .nop => @panic("TODO implement nop"),
+
+            .save => @panic("TODO implement save"),
+            .restore => @panic("TODO implement restore"),
+
+            .@"return" => @panic("TODO implement return"),
         }
     }
 }
@@ -91,3 +98,10 @@ fn mirDebugEpilogueBegin(self: *Emit) !void {
         .none => {},
     }
 }
+
+fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
+    @setCold(true);
+    assert(emit.err_msg == null);
+    emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args);
+    return error.EmitFail;
+}
src/arch/sparcv9/Mir.zig
@@ -29,6 +29,22 @@ pub const Inst = struct {
         dbg_epilogue_begin,
         /// Pseudo-instruction: Update debug line
         dbg_line,
+
+        // All the real instructions are ordered by their section number
+        // in The SPARC Architecture Manual, Version 9.
+
+        /// A.40 No Operation
+        /// It uses the nop field.
+        nop,
+
+        /// A.46 SAVE and RESTORE
+        /// Those uses the arithmetic_3op field.
+        save,
+        restore,
+
+        /// A.45 RETURN
+        /// It uses the arithmetic_2op field.
+        @"return",
     };
 
     /// The position of an MIR instruction within the `Mir` instructions array.
@@ -42,6 +58,36 @@ pub const Inst = struct {
         ///
         /// Used by e.g. flushw
         nop: void,
+
+        /// Three operand arithmetic.
+        /// if is_imm true then it uses the imm field of rs2_or_imm,
+        /// otherwise it uses rs2 field.
+        ///
+        /// Used by e.g. add, sub
+        arithmetic_3op: struct {
+            is_imm: bool,
+            rd: Register,
+            rs1: Register,
+            rs2_or_imm: union {
+                rs2: Register,
+                imm: i13,
+            },
+        },
+
+        /// Two operand arithmetic.
+        /// if is_imm true then it uses the imm field of rs2_or_imm,
+        /// otherwise it uses rs2 field.
+        ///
+        /// Used by e.g. return
+        arithmetic_2op: struct {
+            is_imm: bool,
+            rs1: Register,
+            rs2_or_imm: union {
+                rs2: Register,
+                imm: i13,
+            },
+        },
+
         /// Debug info: line and column
         ///
         /// Used by e.g. dbg_line
@@ -77,4 +123,3 @@ pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end
         .end = i,
     };
 }
-