Commit fbd5fbe729

joachimschmidt557 <joachim.schmidt557@outlook.com>
2021-01-16 14:15:40
stage2 AArch64: add very basic return values
1 parent b204ea0
Changed files (2)
src/codegen/aarch64.zig
@@ -64,7 +64,7 @@ pub const callee_preserved_regs = [_]Register{
 };
 
 pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
-pub const c_abi_int_return_regs = [_]Register{ .x0, .x1 };
+pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
 
 test "Register.id" {
     testing.expectEqual(@as(u5, 0), Register.x0.id());
@@ -699,17 +699,18 @@ pub const Instruction = union(enum) {
 
     // Load or store register
 
-    pub const LdrArgs = struct {
-        rn: ?Register = null,
-        offset: LoadStoreOffset = LoadStoreOffset.none,
-        literal: ?u19 = null,
+    pub const LdrArgs = union(enum) {
+        register: struct {
+            rn: Register,
+            offset: LoadStoreOffset = LoadStoreOffset.none,
+        },
+        literal: u19,
     };
 
     pub fn ldr(rt: Register, args: LdrArgs) Instruction {
-        if (args.rn) |rn| {
-            return loadStoreRegister(rt, rn, args.offset, true);
-        } else {
-            return loadLiteral(rt, args.literal.?);
+        switch (args) {
+            .register => |info| return loadStoreRegister(rt, info.rn, info.offset, true),
+            .literal => |literal| return loadLiteral(rt, literal),
         }
     }
 
@@ -911,19 +912,19 @@ test "serialize instructions" {
             .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100,
         },
         .{ // ldr x2, [x1]
-            .inst = Instruction.ldr(.x2, .{ .rn = .x1 }),
+            .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1 } }),
             .expected = 0b11_111_0_01_01_000000000000_00001_00010,
         },
         .{ // ldr x2, [x1, #1]!
-            .inst = Instruction.ldr(.x2, .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_pre_index(1) }),
+            .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_pre_index(1) } }),
             .expected = 0b11_111_0_00_01_0_000000001_11_00001_00010,
         },
         .{ // ldr x2, [x1], #-1
-            .inst = Instruction.ldr(.x2, .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_post_index(-1) }),
+            .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_post_index(-1) } }),
             .expected = 0b11_111_0_00_01_0_111111111_01_00001_00010,
         },
         .{ // ldr x2, [x1], (x3)
-            .inst = Instruction.ldr(.x2, .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.reg(.x3) }),
+            .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.reg(.x3) } }),
             .expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010,
         },
         .{ // ldr x2, label
src/codegen.zig
@@ -2935,8 +2935,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                                 ).toU32());
                                 // ldr x28, [sp], #16
                                 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.x28, .{
-                                    .rn = Register.sp,
-                                    .offset = Instruction.LoadStoreOffset.imm_post_index(16),
+                                    .register = .{
+                                        .rn = Register.sp,
+                                        .offset = Instruction.LoadStoreOffset.imm_post_index(16),
+                                    },
                                 }).toU32());
                             } else {
                                 // stp x0, x28, [sp, #-16]
@@ -2978,7 +2980,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                             // The value is in memory at a hard-coded address.
                             // If the type is a pointer, it means the pointer address is at this memory location.
                             try self.genSetReg(src, reg, .{ .immediate = addr });
-                            mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .rn = reg }).toU32());
+                            mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .register = .{ .rn = reg } }).toU32());
                         }
                     },
                     else => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}),
@@ -3620,6 +3622,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                     },
                     else => return self.fail(src, "TODO implement function return values for {}", .{cc}),
                 },
+                .aarch64 => switch (cc) {
+                    .Naked => unreachable,
+                    .Unspecified, .C => {
+                        const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
+                        if (ret_ty_size <= 8) {
+                            result.return_value = .{ .register = c_abi_int_return_regs[0] };
+                        } else {
+                            return self.fail(src, "TODO support more return types for ARM backend", .{});
+                        }
+                    },
+                    else => return self.fail(src, "TODO implement function return values for {}", .{cc}),
+                },
                 else => return self.fail(src, "TODO implement codegen return values for {}", .{self.target.cpu.arch}),
             }
             return result;