Commit 2a410baa2b

Jakub Konka <kubkon@jakubkonka.com>
2021-01-03 23:01:22
stage2: implement basic function params aarch64
Implement missing `.register` prong for `aarch64` `genSetReg`.
1 parent 5aac2fc
Changed files (1)
src/codegen.zig
@@ -2837,7 +2837,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                             mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movk(reg, @intCast(u16, x >> 48), 48).toU32());
                         }
                     },
-                    .register => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}),
+                    .register => |src_reg| {
+                        // If the registers are the same, nothing to do.
+                        if (src_reg.id() == reg.id())
+                            return;
+
+                        // mov reg, src_reg
+                        writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(
+                            reg,
+                            .xzr,
+                            src_reg,
+                            Instruction.Shift.none,
+                        ).toU32());
+                    },
                     .memory => |addr| {
                         if (self.bin_file.options.pie) {
                             // For MachO, the binary, with the exception of object files, has to be a PIE.
@@ -3475,6 +3487,59 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                         else => return self.fail(src, "TODO implement function parameters for {} on arm", .{cc}),
                     }
                 },
+                .aarch64 => {
+                    switch (cc) {
+                        .Naked => {
+                            assert(result.args.len == 0);
+                            result.return_value = .{ .unreach = {} };
+                            result.stack_byte_count = 0;
+                            result.stack_align = 1;
+                            return result;
+                        },
+                        .Unspecified, .C => {
+                            // ARM64 Procedure Call Standard
+                            var ncrn: usize = 0; // Next Core Register Number
+                            var nsaa: u32 = 0; // Next stacked argument address
+
+                            for (param_types) |ty, i| {
+                                // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
+                                // values to spread across odd-numbered registers.
+                                if (ty.abiAlignment(self.target.*) == 16 and !self.target.isDarwin()) {
+                                    // Round up NCRN to the next even number
+                                    ncrn += ncrn % 2;
+                                }
+
+                                const param_size = @intCast(u32, ty.abiSize(self.target.*));
+                                if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
+                                    if (param_size <= 8) {
+                                        result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
+                                        ncrn += 1;
+                                    } else {
+                                        return self.fail(src, "TODO MCValues with multiple registers", .{});
+                                    }
+                                } else if (ncrn < 8 and nsaa == 0) {
+                                    return self.fail(src, "TODO MCValues split between registers and stack", .{});
+                                } else {
+                                    ncrn = 8;
+                                    // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided
+                                    // that the entire stack space consumed by the arguments is 8-byte aligned.
+                                    if (ty.abiAlignment(self.target.*) == 8) {
+                                        if (nsaa % 8 != 0) {
+                                            nsaa += 8 - (nsaa % 8);
+                                        }
+                                    }
+
+                                    result.args[i] = .{ .stack_offset = nsaa };
+                                    nsaa += param_size;
+                                }
+                            }
+
+                            result.stack_byte_count = nsaa;
+                            result.stack_align = 16;
+                        },
+                        else => return self.fail(src, "TODO implement function parameters for {} on aarch64", .{cc}),
+                    }
+                },
                 else => if (param_types.len != 0)
                     return self.fail(src, "TODO implement codegen parameters for {}", .{self.target.cpu.arch}),
             }