authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-11-13 06:17:08-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-11-13 06:17:08-08:00
logd3a099c14fe9b7b575a0cd7bb9cd05b49625a71e
treea7ba0e0d9771c6a83493dd0feb931723a1ad2256
parent71388b980bfc4c7eb267ed7c168c2395098f6db2
parent96e715d5a3a5e75e691bedd6a2dcebffc09639bb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10142 from joachimschmidt557/stage2-aarch64

stage2 AArch64: fix loading/storing to/from stack

5 files changed, 190 insertions(+), 124 deletions(-)

src/arch/aarch64/CodeGen.zig+24-38
......@@ -302,6 +302,7 @@ pub fn generate(
302302 .prev_di_pc = 0,
303303 .prev_di_line = module_fn.lbrace_line,
304304 .prev_di_column = module_fn.lbrace_column,
305 .stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align),
305306 };
306307 defer emit.deinit();
307308
......@@ -1346,9 +1347,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
13461347 const stack_offset = try self.allocMem(inst, abi_size, abi_align);
13471348 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
13481349
1349 // TODO correct loading and storing from memory
1350 // break :blk MCValue{ .stack_offset = stack_offset };
1351 break :blk result;
1350 break :blk MCValue{ .stack_offset = stack_offset };
13521351 },
13531352 else => result,
13541353 };
......@@ -2261,28 +2260,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
22612260
22622261 switch (abi_size) {
22632262 1, 2, 4, 8 => {
2264 const offset = if (math.cast(i9, adj_off)) |imm|
2265 Instruction.LoadStoreOffset.imm_post_index(-imm)
2266 else |_|
2267 Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u64), MCValue{ .immediate = adj_off }));
2268 const rn: Register = switch (self.target.cpu.arch) {
2269 .aarch64, .aarch64_be => .x29,
2270 .aarch64_32 => .w29,
2271 else => unreachable,
2272 };
22732263 const tag: Mir.Inst.Tag = switch (abi_size) {
2274 1 => .strb,
2275 2 => .strh,
2276 4, 8 => .str,
2264 1 => .strb_stack,
2265 2 => .strh_stack,
2266 4, 8 => .str_stack,
2267 else => unreachable, // unexpected abi size
2268 };
2269 const rt: Register = switch (abi_size) {
2270 1, 2, 4 => reg.to32(),
2271 8 => reg.to64(),
22772272 else => unreachable, // unexpected abi size
22782273 };
22792274
22802275 _ = try self.addInst(.{
22812276 .tag = tag,
2282 .data = .{ .load_store_register = .{
2283 .rt = reg,
2284 .rn = rn,
2285 .offset = offset,
2277 .data = .{ .load_store_stack = .{
2278 .rt = rt,
2279 .offset = @intCast(u32, adj_off),
22862280 } },
22872281 });
22882282 },
......@@ -2384,36 +2378,28 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
23842378 });
23852379 },
23862380 .stack_offset => |unadjusted_off| {
2387 // TODO: maybe addressing from sp instead of fp
23882381 const abi_size = ty.abiSize(self.target.*);
23892382 const adj_off = unadjusted_off + abi_size;
23902383
2391 const rn: Register = switch (self.target.cpu.arch) {
2392 .aarch64, .aarch64_be => .x29,
2393 .aarch64_32 => .w29,
2394 else => unreachable,
2395 };
2396
2397 const offset = if (math.cast(i9, adj_off)) |imm|
2398 Instruction.LoadStoreOffset.imm_post_index(-imm)
2399 else |_|
2400 Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u64), MCValue{ .immediate = adj_off }));
2401
24022384 switch (abi_size) {
24032385 1, 2, 4, 8 => {
24042386 const tag: Mir.Inst.Tag = switch (abi_size) {
2405 1 => .ldrb,
2406 2 => .ldrh,
2407 4, 8 => .ldr,
2387 1 => .ldrb_stack,
2388 2 => .ldrh_stack,
2389 4, 8 => .ldr_stack,
2390 else => unreachable, // unexpected abi size
2391 };
2392 const rt: Register = switch (abi_size) {
2393 1, 2, 4 => reg.to32(),
2394 8 => reg.to64(),
24082395 else => unreachable, // unexpected abi size
24092396 };
24102397
24112398 _ = try self.addInst(.{
24122399 .tag = tag,
2413 .data = .{ .load_store_register = .{
2414 .rt = reg,
2415 .rn = rn,
2416 .offset = offset,
2400 .data = .{ .load_store_stack = .{
2401 .rt = rt,
2402 .offset = @intCast(u32, adj_off),
24172403 } },
24182404 });
24192405 },
src/arch/aarch64/Emit.zig+96-13
......@@ -42,6 +42,8 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUn
4242/// instruction
4343code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},
4444
45stack_size: u32,
46
4547const InnerError = error{
4648 OutOfMemory,
4749 EmitFail,
......@@ -103,6 +105,13 @@ pub fn emitMir(
103105 .ldp => try emit.mirLoadStoreRegisterPair(inst),
104106 .stp => try emit.mirLoadStoreRegisterPair(inst),
105107
108 .ldr_stack => try emit.mirLoadStoreStack(inst),
109 .ldrb_stack => try emit.mirLoadStoreStack(inst),
110 .ldrh_stack => try emit.mirLoadStoreStack(inst),
111 .str_stack => try emit.mirLoadStoreStack(inst),
112 .strb_stack => try emit.mirLoadStoreStack(inst),
113 .strh_stack => try emit.mirLoadStoreStack(inst),
114
106115 .ldr => try emit.mirLoadStoreRegister(inst),
107116 .ldrb => try emit.mirLoadStoreRegister(inst),
108117 .ldrh => try emit.mirLoadStoreRegister(inst),
......@@ -587,12 +596,11 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
587596 try emit.writeInstruction(Instruction.adrp(reg, 0));
588597
589598 // ldr reg, reg, offset
590 try emit.writeInstruction(Instruction.ldr(reg, .{
591 .register = .{
592 .rn = reg,
593 .offset = Instruction.LoadStoreOffset.imm(0),
594 },
595 }));
599 try emit.writeInstruction(Instruction.ldr(
600 reg,
601 reg,
602 Instruction.LoadStoreOffset.imm(0),
603 ));
596604
597605 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
598606 // TODO I think the reloc might be in the wrong place.
......@@ -626,7 +634,8 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
626634 try emit.moveImmediate(reg, addr);
627635 try emit.writeInstruction(Instruction.ldr(
628636 reg,
629 .{ .register = .{ .rn = reg, .offset = Instruction.LoadStoreOffset.none } },
637 reg,
638 Instruction.LoadStoreOffset.none,
630639 ));
631640 }
632641}
......@@ -652,6 +661,79 @@ fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
652661 }
653662}
654663
664fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {
665 const tag = emit.mir.instructions.items(.tag)[inst];
666 const load_store_stack = emit.mir.instructions.items(.data)[inst].load_store_stack;
667
668 const raw_offset = emit.stack_size - load_store_stack.offset;
669 const offset = switch (tag) {
670 .ldrb_stack, .strb_stack => blk: {
671 if (math.cast(u12, raw_offset)) |imm| {
672 break :blk Instruction.LoadStoreOffset.imm(imm);
673 } else |_| {
674 return emit.fail("TODO load/store stack byte with larger offset", .{});
675 }
676 },
677 .ldrh_stack, .strh_stack => blk: {
678 assert(std.mem.isAlignedGeneric(u32, raw_offset, 2)); // misaligned stack entry
679 if (math.cast(u12, @divExact(raw_offset, 2))) |imm| {
680 break :blk Instruction.LoadStoreOffset.imm(imm);
681 } else |_| {
682 return emit.fail("TODO load/store stack halfword with larger offset", .{});
683 }
684 },
685 .ldr_stack, .str_stack => blk: {
686 const alignment: u32 = switch (load_store_stack.rt.size()) {
687 32 => 4,
688 64 => 8,
689 else => unreachable,
690 };
691
692 assert(std.mem.isAlignedGeneric(u32, raw_offset, alignment)); // misaligned stack entry
693 if (math.cast(u12, @divExact(raw_offset, alignment))) |imm| {
694 break :blk Instruction.LoadStoreOffset.imm(imm);
695 } else |_| {
696 return emit.fail("TODO load/store stack with larger offset", .{});
697 }
698 },
699 else => unreachable,
700 };
701
702 switch (tag) {
703 .ldr_stack => try emit.writeInstruction(Instruction.ldr(
704 load_store_stack.rt,
705 Register.sp,
706 offset,
707 )),
708 .ldrb_stack => try emit.writeInstruction(Instruction.ldrb(
709 load_store_stack.rt,
710 Register.sp,
711 offset,
712 )),
713 .ldrh_stack => try emit.writeInstruction(Instruction.ldrh(
714 load_store_stack.rt,
715 Register.sp,
716 offset,
717 )),
718 .str_stack => try emit.writeInstruction(Instruction.str(
719 load_store_stack.rt,
720 Register.sp,
721 offset,
722 )),
723 .strb_stack => try emit.writeInstruction(Instruction.strb(
724 load_store_stack.rt,
725 Register.sp,
726 offset,
727 )),
728 .strh_stack => try emit.writeInstruction(Instruction.strh(
729 load_store_stack.rt,
730 Register.sp,
731 offset,
732 )),
733 else => unreachable,
734 }
735}
736
655737fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
656738 const tag = emit.mir.instructions.items(.tag)[inst];
657739 const load_store_register = emit.mir.instructions.items(.data)[inst].load_store_register;
......@@ -659,32 +741,33 @@ fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
659741 switch (tag) {
660742 .ldr => try emit.writeInstruction(Instruction.ldr(
661743 load_store_register.rt,
662 .{ .register = .{ .rn = load_store_register.rn, .offset = load_store_register.offset } },
744 load_store_register.rn,
745 load_store_register.offset,
663746 )),
664747 .ldrb => try emit.writeInstruction(Instruction.ldrb(
665748 load_store_register.rt,
666749 load_store_register.rn,
667 .{ .offset = load_store_register.offset },
750 load_store_register.offset,
668751 )),
669752 .ldrh => try emit.writeInstruction(Instruction.ldrh(
670753 load_store_register.rt,
671754 load_store_register.rn,
672 .{ .offset = load_store_register.offset },
755 load_store_register.offset,
673756 )),
674757 .str => try emit.writeInstruction(Instruction.str(
675758 load_store_register.rt,
676759 load_store_register.rn,
677 .{ .offset = load_store_register.offset },
760 load_store_register.offset,
678761 )),
679762 .strb => try emit.writeInstruction(Instruction.strb(
680763 load_store_register.rt,
681764 load_store_register.rn,
682 .{ .offset = load_store_register.offset },
765 load_store_register.offset,
683766 )),
684767 .strh => try emit.writeInstruction(Instruction.strh(
685768 load_store_register.rt,
686769 load_store_register.rn,
687 .{ .offset = load_store_register.offset },
770 load_store_register.offset,
688771 )),
689772 else => unreachable,
690773 }
src/arch/aarch64/Mir.zig+20-1
......@@ -56,12 +56,18 @@ pub const Inst = struct {
5656 load_memory,
5757 /// Load Pair of Registers
5858 ldp,
59 /// Pseudo-instruction: Load from stack
60 ldr_stack,
5961 /// Load Register
6062 // TODO: split into ldr_immediate and ldr_register
6163 ldr,
64 /// Pseudo-instruction: Load byte from stack
65 ldrb_stack,
6266 /// Load Register Byte
6367 // TODO: split into ldrb_immediate and ldrb_register
6468 ldrb,
69 /// Pseudo-instruction: Load halfword from stack
70 ldrh_stack,
6571 /// Load Register Halfword
6672 // TODO: split into ldrh_immediate and ldrh_register
6773 ldrh,
......@@ -79,12 +85,18 @@ pub const Inst = struct {
7985 ret,
8086 /// Store Pair of Registers
8187 stp,
88 /// Pseudo-instruction: Store to stack
89 str_stack,
8290 /// Store Register
8391 // TODO: split into str_immediate and str_register
8492 str,
93 /// Pseudo-instruction: Store byte to stack
94 strb_stack,
8595 /// Store Register Byte
8696 // TODO: split into strb_immediate and strb_register
8797 strb,
98 /// Pseudo-instruction: Store halfword to stack
99 strh_stack,
88100 /// Store Register Halfword
89101 // TODO: split into strh_immediate and strh_register
90102 strh,
......@@ -175,7 +187,7 @@ pub const Inst = struct {
175187 rm: Register,
176188 cond: bits.Instruction.Condition,
177189 },
178 /// Three registers and a LoadStoreOffset
190 /// Two registers and a LoadStoreOffset
179191 ///
180192 /// Used by e.g. str_register
181193 load_store_register: struct {
......@@ -183,6 +195,13 @@ pub const Inst = struct {
183195 rn: Register,
184196 offset: bits.Instruction.LoadStoreOffset,
185197 },
198 /// A registers and a stack offset
199 ///
200 /// Used by e.g. str_register
201 load_store_stack: struct {
202 rt: Register,
203 offset: u32,
204 },
186205 /// Three registers and a LoadStorePairOffset
187206 ///
188207 /// Used by e.g. stp
src/arch/aarch64/bits.zig+36-57
......@@ -742,27 +742,17 @@ pub const Instruction = union(enum) {
742742 }
743743
744744 fn loadLiteral(rt: Register, imm19: u19) Instruction {
745 switch (rt.size()) {
746 32 => {
747 return Instruction{
748 .load_literal = .{
749 .rt = rt.id(),
750 .imm19 = imm19,
751 .opc = 0b00,
752 },
753 };
754 },
755 64 => {
756 return Instruction{
757 .load_literal = .{
758 .rt = rt.id(),
759 .imm19 = imm19,
760 .opc = 0b01,
761 },
762 };
745 return Instruction{
746 .load_literal = .{
747 .rt = rt.id(),
748 .imm19 = imm19,
749 .opc = switch (rt.size()) {
750 32 => 0b00,
751 64 => 0b01,
752 else => unreachable, // unexpected register size
753 },
763754 },
764 else => unreachable, // unexpected register size
765 }
755 };
766756 }
767757
768758 fn exceptionGeneration(
......@@ -1001,43 +991,32 @@ pub const Instruction = union(enum) {
1001991
1002992 // Load or store register
1003993
1004 pub const LdrArgs = union(enum) {
1005 register: struct {
1006 rn: Register,
1007 offset: LoadStoreOffset = LoadStoreOffset.none,
1008 },
1009 literal: u19,
1010 };
1011
1012 pub fn ldr(rt: Register, args: LdrArgs) Instruction {
1013 switch (args) {
1014 .register => |info| return loadStoreRegister(rt, info.rn, info.offset, .ldr),
1015 .literal => |literal| return loadLiteral(rt, literal),
1016 }
994 pub fn ldrLiteral(rt: Register, literal: u19) Instruction {
995 return loadLiteral(rt, literal);
1017996 }
1018997
1019 pub fn ldrh(rt: Register, rn: Register, args: StrArgs) Instruction {
1020 return loadStoreRegister(rt, rn, args.offset, .ldrh);
998 pub fn ldr(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
999 return loadStoreRegister(rt, rn, offset, .ldr);
10211000 }
10221001
1023 pub fn ldrb(rt: Register, rn: Register, args: StrArgs) Instruction {
1024 return loadStoreRegister(rt, rn, args.offset, .ldrb);
1002 pub fn ldrh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1003 return loadStoreRegister(rt, rn, offset, .ldrh);
10251004 }
10261005
1027 pub const StrArgs = struct {
1028 offset: LoadStoreOffset = LoadStoreOffset.none,
1029 };
1006 pub fn ldrb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1007 return loadStoreRegister(rt, rn, offset, .ldrb);
1008 }
10301009
1031 pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {
1032 return loadStoreRegister(rt, rn, args.offset, .str);
1010 pub fn str(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1011 return loadStoreRegister(rt, rn, offset, .str);
10331012 }
10341013
1035 pub fn strh(rt: Register, rn: Register, args: StrArgs) Instruction {
1036 return loadStoreRegister(rt, rn, args.offset, .strh);
1014 pub fn strh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1015 return loadStoreRegister(rt, rn, offset, .strh);
10371016 }
10381017
1039 pub fn strb(rt: Register, rn: Register, args: StrArgs) Instruction {
1040 return loadStoreRegister(rt, rn, args.offset, .strb);
1018 pub fn strb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1019 return loadStoreRegister(rt, rn, offset, .strb);
10411020 }
10421021
10431022 // Load or store pair of registers
......@@ -1324,47 +1303,47 @@ test "serialize instructions" {
13241303 .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100,
13251304 },
13261305 .{ // ldr x2, [x1]
1327 .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1 } }),
1306 .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.none),
13281307 .expected = 0b11_111_0_01_01_000000000000_00001_00010,
13291308 },
13301309 .{ // ldr x2, [x1, #1]!
1331 .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_pre_index(1) } }),
1310 .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_pre_index(1)),
13321311 .expected = 0b11_111_0_00_01_0_000000001_11_00001_00010,
13331312 },
13341313 .{ // ldr x2, [x1], #-1
1335 .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_post_index(-1) } }),
1314 .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_post_index(-1)),
13361315 .expected = 0b11_111_0_00_01_0_111111111_01_00001_00010,
13371316 },
13381317 .{ // ldr x2, [x1], (x3)
1339 .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.reg(.x3) } }),
1318 .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)),
13401319 .expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010,
13411320 },
13421321 .{ // ldr x2, label
1343 .inst = Instruction.ldr(.x2, .{ .literal = 0x1 }),
1322 .inst = Instruction.ldrLiteral(.x2, 0x1),
13441323 .expected = 0b01_011_0_00_0000000000000000001_00010,
13451324 },
13461325 .{ // ldrh x7, [x4], #0xaa
1347 .inst = Instruction.ldrh(.x7, .x4, .{ .offset = Instruction.LoadStoreOffset.imm_post_index(0xaa) }),
1326 .inst = Instruction.ldrh(.x7, .x4, Instruction.LoadStoreOffset.imm_post_index(0xaa)),
13481327 .expected = 0b01_111_0_00_01_0_010101010_01_00100_00111,
13491328 },
13501329 .{ // ldrb x9, [x15, #0xff]!
1351 .inst = Instruction.ldrb(.x9, .x15, .{ .offset = Instruction.LoadStoreOffset.imm_pre_index(0xff) }),
1330 .inst = Instruction.ldrb(.x9, .x15, Instruction.LoadStoreOffset.imm_pre_index(0xff)),
13521331 .expected = 0b00_111_0_00_01_0_011111111_11_01111_01001,
13531332 },
13541333 .{ // str x2, [x1]
1355 .inst = Instruction.str(.x2, .x1, .{}),
1334 .inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.none),
13561335 .expected = 0b11_111_0_01_00_000000000000_00001_00010,
13571336 },
13581337 .{ // str x2, [x1], (x3)
1359 .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }),
1338 .inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)),
13601339 .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
13611340 },
13621341 .{ // strh w0, [x1]
1363 .inst = Instruction.strh(.w0, .x1, .{}),
1342 .inst = Instruction.strh(.w0, .x1, Instruction.LoadStoreOffset.none),
13641343 .expected = 0b01_111_0_01_00_000000000000_00001_00000,
13651344 },
13661345 .{ // strb w8, [x9]
1367 .inst = Instruction.strb(.w8, .x9, .{}),
1346 .inst = Instruction.strb(.w8, .x9, Instruction.LoadStoreOffset.none),
13681347 .expected = 0b00_111_0_01_00_000000000000_01001_01000,
13691348 },
13701349 .{ // adr x2, #0x8
src/link/MachO.zig+14-15
......@@ -2041,12 +2041,11 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
20412041 .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),
20422042 });
20432043 // ldr x16, [x16, 0]
2044 mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr(.x16, .{
2045 .register = .{
2046 .rn = .x16,
2047 .offset = aarch64.Instruction.LoadStoreOffset.imm(0),
2048 },
2049 }).toU32());
2044 mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr(
2045 .x16,
2046 .x16,
2047 aarch64.Instruction.LoadStoreOffset.imm(0),
2048 ).toU32());
20502049 atom.relocs.appendAssumeCapacity(.{
20512050 .offset = 16,
20522051 .target = .{ .global = self.undefs.items[self.dyld_stub_binder_index.?].n_strx },
......@@ -2119,9 +2118,10 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
21192118 break :blk try math.cast(u18, div_res);
21202119 };
21212120 // ldr w16, literal
2122 mem.writeIntLittle(u32, atom.code.items[0..4], aarch64.Instruction.ldr(.w16, .{
2123 .literal = literal,
2124 }).toU32());
2121 mem.writeIntLittle(u32, atom.code.items[0..4], aarch64.Instruction.ldrLiteral(
2122 .w16,
2123 literal,
2124 ).toU32());
21252125 // b disp
21262126 mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.b(0).toU32());
21272127 atom.relocs.appendAssumeCapacity(.{
......@@ -2222,12 +2222,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
22222222 .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
22232223 });
22242224 // ldr x16, x16, offset
2225 mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.ldr(.x16, .{
2226 .register = .{
2227 .rn = .x16,
2228 .offset = aarch64.Instruction.LoadStoreOffset.imm(0),
2229 },
2230 }).toU32());
2225 mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.ldr(
2226 .x16,
2227 .x16,
2228 aarch64.Instruction.LoadStoreOffset.imm(0),
2229 ).toU32());
22312230 atom.relocs.appendAssumeCapacity(.{
22322231 .offset = 4,
22332232 .target = .{ .local = laptr_sym_index },