aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorRue <78876133+IOKG04@users.noreply.github.com>2025-07-28 14:54:52 +0200
committerGitHub <noreply@github.com>2025-07-28 14:54:52 +0200
commit5381e7891dcdd7b6a9e74250cdcce221fe464cdc (patch)
tree4c74744ed84120dccae6dc9811ce945911108a17 /src/link
parent84ae54fbe64a15301317716e7f901d81585332d5 (diff)
parentdea3ed7f59347e87a1b8fa237202873988084ae8 (diff)
downloadzig-5381e7891dcdd7b6a9e74250cdcce221fe464cdc.tar.gz
zig-5381e7891dcdd7b6a9e74250cdcce221fe464cdc.zip
Merge branch 'ziglang:master' into some-documentation-updates-0
Diffstat (limited to 'src/link')
-rw-r--r--src/link/Coff.zig76
-rw-r--r--src/link/Dwarf.zig8
-rw-r--r--src/link/Elf/Atom.zig70
-rw-r--r--src/link/Elf/Thunk.zig15
-rw-r--r--src/link/Elf/ZigObject.zig10
-rw-r--r--src/link/Elf/relocation.zig24
-rw-r--r--src/link/Elf/synthetic_sections.zig75
-rw-r--r--src/link/MachO.zig4
-rw-r--r--src/link/MachO/Atom.zig100
-rw-r--r--src/link/MachO/Thunk.zig10
-rw-r--r--src/link/MachO/ZigObject.zig10
-rw-r--r--src/link/MachO/synthetic.zig95
-rw-r--r--src/link/aarch64.zig64
13 files changed, 227 insertions, 334 deletions
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index dd8ddd30f4..1b8986d337 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -1335,9 +1335,13 @@ fn updateNavCode(
log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
- const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
- const required_alignment = switch (pt.navAlignment(nav_index)) {
- .none => target_util.defaultFunctionAlignment(target),
+ const mod = zcu.navFileScope(nav_index).mod.?;
+ const target = &mod.resolved_target.result;
+ const required_alignment = switch (nav.status.fully_resolved.alignment) {
+ .none => switch (mod.optimize_mode) {
+ .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
+ .ReleaseSmall => target_util.minFunctionAlignment(target),
+ },
else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
};
@@ -2832,58 +2836,33 @@ pub const Relocation = struct {
};
fn resolveAarch64(reloc: Relocation, ctx: Context) void {
+ const Instruction = aarch64_util.encoding.Instruction;
var buffer = ctx.code[reloc.offset..];
switch (reloc.type) {
.got_page, .import_page, .page => {
const source_page = @as(i32, @intCast(ctx.source_vaddr >> 12));
const target_page = @as(i32, @intCast(ctx.target_vaddr >> 12));
- const pages = @as(u21, @bitCast(@as(i21, @intCast(target_page - source_page))));
- var inst = aarch64_util.Instruction{
- .pc_relative_address = mem.bytesToValue(@FieldType(
- aarch64_util.Instruction,
- @tagName(aarch64_util.Instruction.pc_relative_address),
- ), buffer[0..4]),
- };
- inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2));
- inst.pc_relative_address.immlo = @as(u2, @truncate(pages));
- mem.writeInt(u32, buffer[0..4], inst.toU32(), .little);
+ const pages: i21 = @intCast(target_page - source_page);
+ var inst: Instruction = .read(buffer[0..Instruction.size]);
+ inst.data_processing_immediate.pc_relative_addressing.group.immhi = @intCast(pages >> 2);
+ inst.data_processing_immediate.pc_relative_addressing.group.immlo = @truncate(@as(u21, @bitCast(pages)));
+ inst.write(buffer[0..Instruction.size]);
},
.got_pageoff, .import_pageoff, .pageoff => {
assert(!reloc.pcrel);
- const narrowed = @as(u12, @truncate(@as(u64, @intCast(ctx.target_vaddr))));
- if (isArithmeticOp(buffer[0..4])) {
- var inst = aarch64_util.Instruction{
- .add_subtract_immediate = mem.bytesToValue(@FieldType(
- aarch64_util.Instruction,
- @tagName(aarch64_util.Instruction.add_subtract_immediate),
- ), buffer[0..4]),
- };
- inst.add_subtract_immediate.imm12 = narrowed;
- mem.writeInt(u32, buffer[0..4], inst.toU32(), .little);
- } else {
- var inst = aarch64_util.Instruction{
- .load_store_register = mem.bytesToValue(@FieldType(
- aarch64_util.Instruction,
- @tagName(aarch64_util.Instruction.load_store_register),
- ), buffer[0..4]),
- };
- const offset: u12 = blk: {
- if (inst.load_store_register.size == 0) {
- if (inst.load_store_register.v == 1) {
- // 128-bit SIMD is scaled by 16.
- break :blk @divExact(narrowed, 16);
- }
- // Otherwise, 8-bit SIMD or ldrb.
- break :blk narrowed;
- } else {
- const denom: u4 = math.powi(u4, 2, inst.load_store_register.size) catch unreachable;
- break :blk @divExact(narrowed, denom);
- }
- };
- inst.load_store_register.offset = offset;
- mem.writeInt(u32, buffer[0..4], inst.toU32(), .little);
+ const narrowed: u12 = @truncate(@as(u64, @intCast(ctx.target_vaddr)));
+ var inst: Instruction = .read(buffer[0..Instruction.size]);
+ switch (inst.decode()) {
+ else => unreachable,
+ .data_processing_immediate => inst.data_processing_immediate.add_subtract_immediate.group.imm12 = narrowed,
+ .load_store => |load_store| inst.load_store.register_unsigned_immediate.group.imm12 =
+ switch (load_store.register_unsigned_immediate.decode()) {
+ .integer => |integer| @shrExact(narrowed, @intFromEnum(integer.group.size)),
+ .vector => |vector| @shrExact(narrowed, @intFromEnum(vector.group.opc1.decode(vector.group.size))),
+ },
}
+ inst.write(buffer[0..Instruction.size]);
},
.direct => {
assert(!reloc.pcrel);
@@ -2934,11 +2913,6 @@ pub const Relocation = struct {
},
}
}
-
- fn isArithmeticOp(inst: *const [4]u8) bool {
- const group_decode = @as(u5, @truncate(inst[3]));
- return ((group_decode >> 2) == 4);
- }
};
pub fn addRelocation(coff: *Coff, atom_index: Atom.Index, reloc: Relocation) !void {
@@ -3112,7 +3086,7 @@ const Path = std.Build.Cache.Path;
const Directory = std.Build.Cache.Directory;
const Cache = std.Build.Cache;
-const aarch64_util = @import("../arch/aarch64/bits.zig");
+const aarch64_util = link.aarch64;
const allocPrint = std.fmt.allocPrint;
const codegen = @import("../codegen.zig");
const link = @import("../link.zig");
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
index a1a9dedd4b..4262c329fa 100644
--- a/src/link/Dwarf.zig
+++ b/src/link/Dwarf.zig
@@ -2487,7 +2487,13 @@ fn initWipNavInner(
try wip_nav.strp(nav.fqn.toSlice(ip));
const ty: Type = nav_val.typeOf(zcu);
const addr: Loc = .{ .addr_reloc = sym_index };
- const loc: Loc = if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr;
+ const loc: Loc = if (decl.is_threadlocal) loc: {
+ const target = zcu.comp.root_mod.resolved_target.result;
+ break :loc switch (target.cpu.arch) {
+ .x86_64 => .{ .form_tls_address = &addr },
+ else => .empty,
+ };
+ } else addr;
switch (decl.kind) {
.unnamed_test, .@"test", .decltest, .@"comptime" => unreachable,
.@"const" => {
diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig
index 5966bae02c..4bb88f2af3 100644
--- a/src/link/Elf/Atom.zig
+++ b/src/link/Elf/Atom.zig
@@ -1627,7 +1627,7 @@ const aarch64 = struct {
const S_ = th.targetAddress(target_index, elf_file);
break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
};
- aarch64_util.writeBranchImm(disp, code);
+ util.writeBranchImm(disp, code);
},
.PREL32 => {
@@ -1640,15 +1640,18 @@ const aarch64 = struct {
mem.writeInt(u64, code_buffer[r_offset..][0..8], @bitCast(value), .little);
},
+ .ADR_PREL_LO21 => {
+ const value = math.cast(i21, S + A - P) orelse return error.Overflow;
+ util.writeAdrInst(value, code);
+ },
+
.ADR_PREL_PG_HI21 => {
// TODO: check for relaxation of ADRP+ADD
- const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(P, S + A)));
- aarch64_util.writeAdrpInst(pages, code);
+ util.writeAdrInst(try util.calcNumberOfPages(P, S + A), code);
},
.ADR_GOT_PAGE => if (target.flags.has_got) {
- const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(P, G + GOT + A)));
- aarch64_util.writeAdrpInst(pages, code);
+ util.writeAdrInst(try util.calcNumberOfPages(P, G + GOT + A), code);
} else {
// TODO: relax
var err = try diags.addErrorWithNotes(1);
@@ -1663,12 +1666,12 @@ const aarch64 = struct {
.LD64_GOT_LO12_NC => {
assert(target.flags.has_got);
const taddr = @as(u64, @intCast(G + GOT + A));
- aarch64_util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code);
+ util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code);
},
.ADD_ABS_LO12_NC => {
const taddr = @as(u64, @intCast(S + A));
- aarch64_util.writeAddImmInst(@truncate(taddr), code);
+ util.writeAddImmInst(@truncate(taddr), code);
},
.LDST8_ABS_LO12_NC,
@@ -1687,57 +1690,54 @@ const aarch64 = struct {
.LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),
else => unreachable,
};
- aarch64_util.writeLoadStoreRegInst(off, code);
+ util.writeLoadStoreRegInst(off, code);
},
.TLSLE_ADD_TPREL_HI12 => {
const value = math.cast(i12, (S + A - TP) >> 12) orelse
return error.Overflow;
- aarch64_util.writeAddImmInst(@bitCast(value), code);
+ util.writeAddImmInst(@bitCast(value), code);
},
.TLSLE_ADD_TPREL_LO12_NC => {
const value: i12 = @truncate(S + A - TP);
- aarch64_util.writeAddImmInst(@bitCast(value), code);
+ util.writeAddImmInst(@bitCast(value), code);
},
.TLSIE_ADR_GOTTPREL_PAGE21 => {
const S_ = target.gotTpAddress(elf_file);
relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
- const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A));
- aarch64_util.writeAdrpInst(pages, code);
+ util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code);
},
.TLSIE_LD64_GOTTPREL_LO12_NC => {
const S_ = target.gotTpAddress(elf_file);
relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8);
- aarch64_util.writeLoadStoreRegInst(off, code);
+ util.writeLoadStoreRegInst(off, code);
},
.TLSGD_ADR_PAGE21 => {
const S_ = target.tlsGdAddress(elf_file);
relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
- const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A));
- aarch64_util.writeAdrpInst(pages, code);
+ util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code);
},
.TLSGD_ADD_LO12_NC => {
const S_ = target.tlsGdAddress(elf_file);
relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
const off: u12 = @truncate(@as(u64, @bitCast(S_ + A)));
- aarch64_util.writeAddImmInst(off, code);
+ util.writeAddImmInst(off, code);
},
.TLSDESC_ADR_PAGE21 => {
if (target.flags.has_tlsdesc) {
const S_ = target.tlsDescAddress(elf_file);
relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
- const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A));
- aarch64_util.writeAdrpInst(pages, code);
+ util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code);
} else {
relocs_log.debug(" relaxing adrp => nop", .{});
- mem.writeInt(u32, code, Instruction.nop().toU32(), .little);
+ util.encoding.Instruction.nop().write(code);
}
},
@@ -1746,10 +1746,10 @@ const aarch64 = struct {
const S_ = target.tlsDescAddress(elf_file);
relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8);
- aarch64_util.writeLoadStoreRegInst(off, code);
+ util.writeLoadStoreRegInst(off, code);
} else {
relocs_log.debug(" relaxing ldr => nop", .{});
- mem.writeInt(u32, code, Instruction.nop().toU32(), .little);
+ util.encoding.Instruction.nop().write(code);
}
},
@@ -1758,32 +1758,18 @@ const aarch64 = struct {
const S_ = target.tlsDescAddress(elf_file);
relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
const off: u12 = @truncate(@as(u64, @bitCast(S_ + A)));
- aarch64_util.writeAddImmInst(off, code);
+ util.writeAddImmInst(off, code);
} else {
- const old_inst: Instruction = .{
- .add_subtract_immediate = mem.bytesToValue(@FieldType(
- Instruction,
- @tagName(Instruction.add_subtract_immediate),
- ), code),
- };
- const rd: Register = @enumFromInt(old_inst.add_subtract_immediate.rd);
- relocs_log.debug(" relaxing add({s}) => movz(x0, {x})", .{ @tagName(rd), S + A - TP });
+ relocs_log.debug(" relaxing add => movz(x0, {x})", .{S + A - TP});
const value: u16 = @bitCast(math.cast(i16, (S + A - TP) >> 16) orelse return error.Overflow);
- mem.writeInt(u32, code, Instruction.movz(.x0, value, 16).toU32(), .little);
+ util.encoding.Instruction.movz(.x0, value, .{ .lsl = .@"16" }).write(code);
}
},
.TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
- const old_inst: Instruction = .{
- .unconditional_branch_register = mem.bytesToValue(@FieldType(
- Instruction,
- @tagName(Instruction.unconditional_branch_register),
- ), code),
- };
- const rn: Register = @enumFromInt(old_inst.unconditional_branch_register.rn);
- relocs_log.debug(" relaxing br({s}) => movk(x0, {x})", .{ @tagName(rn), S + A - TP });
+ relocs_log.debug(" relaxing br => movk(x0, {x})", .{S + A - TP});
const value: u16 = @bitCast(@as(i16, @truncate(S + A - TP)));
- mem.writeInt(u32, code, Instruction.movk(.x0, value, 0).toU32(), .little);
+ util.encoding.Instruction.movk(.x0, value, .{}).write(code);
},
else => try atom.reportUnhandledRelocError(rel, elf_file),
@@ -1819,9 +1805,7 @@ const aarch64 = struct {
}
}
- const aarch64_util = @import("../aarch64.zig");
- const Instruction = aarch64_util.Instruction;
- const Register = aarch64_util.Register;
+ const util = @import("../aarch64.zig");
};
const riscv = struct {
diff --git a/src/link/Elf/Thunk.zig b/src/link/Elf/Thunk.zig
index 2af0c9c9d3..59b867be78 100644
--- a/src/link/Elf/Thunk.zig
+++ b/src/link/Elf/Thunk.zig
@@ -95,18 +95,21 @@ const aarch64 = struct {
const sym = elf_file.symbol(ref).?;
const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size));
const taddr = sym.address(.{}, elf_file);
- const pages = try util.calcNumberOfPages(saddr, taddr);
- try writer.writeInt(u32, Instruction.adrp(.x16, pages).toU32(), .little);
- const off: u12 = @truncate(@as(u64, @bitCast(taddr)));
- try writer.writeInt(u32, Instruction.add(.x16, .x16, off, false).toU32(), .little);
- try writer.writeInt(u32, Instruction.br(.x16).toU32(), .little);
+ try writer.writeInt(u32, @bitCast(
+ util.encoding.Instruction.adrp(.x16, try util.calcNumberOfPages(saddr, taddr) << 12),
+ ), .little);
+ try writer.writeInt(u32, @bitCast(util.encoding.Instruction.add(
+ .x16,
+ .x16,
+ .{ .immediate = @truncate(@as(u64, @bitCast(taddr))) },
+ )), .little);
+ try writer.writeInt(u32, @bitCast(util.encoding.Instruction.br(.x16)), .little);
}
}
const trampoline_size = 3 * @sizeOf(u32);
const util = @import("../aarch64.zig");
- const Instruction = util.Instruction;
};
const assert = std.debug.assert;
diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig
index c8f37125ed..f49406b751 100644
--- a/src/link/Elf/ZigObject.zig
+++ b/src/link/Elf/ZigObject.zig
@@ -1270,9 +1270,13 @@ fn updateNavCode(
log.debug("updateNavCode {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
- const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
- const required_alignment = switch (pt.navAlignment(nav_index)) {
- .none => target_util.defaultFunctionAlignment(target),
+ const mod = zcu.navFileScope(nav_index).mod.?;
+ const target = &mod.resolved_target.result;
+ const required_alignment = switch (nav.status.fully_resolved.alignment) {
+ .none => switch (mod.optimize_mode) {
+ .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
+ .ReleaseSmall => target_util.minFunctionAlignment(target),
+ },
else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
};
diff --git a/src/link/Elf/relocation.zig b/src/link/Elf/relocation.zig
index 305dcda789..366d19d9b3 100644
--- a/src/link/Elf/relocation.zig
+++ b/src/link/Elf/relocation.zig
@@ -94,14 +94,18 @@ pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 {
pub const dwarf = struct {
pub fn crossSectionRelocType(format: DW.Format, cpu_arch: std.Target.Cpu.Arch) u32 {
return switch (cpu_arch) {
- .x86_64 => @intFromEnum(switch (format) {
- .@"32" => elf.R_X86_64.@"32",
+ .x86_64 => @intFromEnum(@as(elf.R_X86_64, switch (format) {
+ .@"32" => .@"32",
.@"64" => .@"64",
- }),
- .riscv64 => @intFromEnum(switch (format) {
- .@"32" => elf.R_RISCV.@"32",
+ })),
+ .aarch64 => @intFromEnum(@as(elf.R_AARCH64, switch (format) {
+ .@"32" => .ABS32,
+ .@"64" => .ABS64,
+ })),
+ .riscv64 => @intFromEnum(@as(elf.R_RISCV, switch (format) {
+ .@"32" => .@"32",
.@"64" => .@"64",
- }),
+ })),
else => @panic("TODO unhandled cpu arch"),
};
}
@@ -121,6 +125,14 @@ pub const dwarf = struct {
},
.debug_frame => .PC32,
})),
+ .aarch64 => @intFromEnum(@as(elf.R_AARCH64, switch (source_section) {
+ else => switch (address_size) {
+ .@"32" => .ABS32,
+ .@"64" => .ABS64,
+ else => unreachable,
+ },
+ .debug_frame => .PREL32,
+ })),
.riscv64 => @intFromEnum(@as(elf.R_RISCV, switch (source_section) {
else => switch (address_size) {
.@"32" => .@"32",
diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig
index 3f2ac7cb16..2ab71d8c49 100644
--- a/src/link/Elf/synthetic_sections.zig
+++ b/src/link/Elf/synthetic_sections.zig
@@ -810,54 +810,43 @@ pub const PltSection = struct {
const got_plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.got_plt.?].sh_addr);
// TODO: relax if possible
// .got.plt[2]
- const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
- const ldr_off = try math.divExact(u12, @truncate(@as(u64, @bitCast(got_plt_addr + 16))), 8);
+ const pages = try util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
+ const ldr_off: u12 = @truncate(@as(u64, @bitCast(got_plt_addr + 16)));
const add_off: u12 = @truncate(@as(u64, @bitCast(got_plt_addr + 16)));
- const preamble = &[_]Instruction{
- Instruction.stp(
- .x16,
- .x30,
- Register.sp,
- Instruction.LoadStorePairOffset.pre_index(-16),
- ),
- Instruction.adrp(.x16, pages),
- Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)),
- Instruction.add(.x16, .x16, add_off, false),
- Instruction.br(.x17),
- Instruction.nop(),
- Instruction.nop(),
- Instruction.nop(),
+ const preamble = [_]util.encoding.Instruction{
+ .stp(.x16, .x30, .{ .pre_index = .{ .base = .sp, .index = -16 } }),
+ .adrp(.x16, pages << 12),
+ .ldr(.x17, .{ .unsigned_offset = .{ .base = .x16, .offset = ldr_off } }),
+ .add(.x16, .x16, .{ .immediate = add_off }),
+ .br(.x17),
+ .nop(),
+ .nop(),
+ .nop(),
};
comptime assert(preamble.len == 8);
- for (preamble) |inst| {
- try writer.writeInt(u32, inst.toU32(), .little);
- }
+ for (preamble) |inst| try writer.writeInt(util.encoding.Instruction.Backing, @bitCast(inst), .little);
}
for (plt.symbols.items) |ref| {
const sym = elf_file.symbol(ref).?;
const target_addr = sym.gotPltAddress(elf_file);
const source_addr = sym.pltAddress(elf_file);
- const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
- const ldr_off = try math.divExact(u12, @truncate(@as(u64, @bitCast(target_addr))), 8);
+ const pages = try util.calcNumberOfPages(source_addr, target_addr);
+ const ldr_off: u12 = @truncate(@as(u64, @bitCast(target_addr)));
const add_off: u12 = @truncate(@as(u64, @bitCast(target_addr)));
- const insts = &[_]Instruction{
- Instruction.adrp(.x16, pages),
- Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)),
- Instruction.add(.x16, .x16, add_off, false),
- Instruction.br(.x17),
+ const insts = [_]util.encoding.Instruction{
+ .adrp(.x16, pages << 12),
+ .ldr(.x17, .{ .unsigned_offset = .{ .base = .x16, .offset = ldr_off } }),
+ .add(.x16, .x16, .{ .immediate = add_off }),
+ .br(.x17),
};
comptime assert(insts.len == 4);
- for (insts) |inst| {
- try writer.writeInt(u32, inst.toU32(), .little);
- }
+ for (insts) |inst| try writer.writeInt(util.encoding.Instruction.Backing, @bitCast(inst), .little);
}
}
- const aarch64_util = @import("../aarch64.zig");
- const Instruction = aarch64_util.Instruction;
- const Register = aarch64_util.Register;
+ const util = @import("../aarch64.zig");
};
};
@@ -979,24 +968,20 @@ pub const PltGotSection = struct {
const sym = elf_file.symbol(ref).?;
const target_addr = sym.gotAddress(elf_file);
const source_addr = sym.pltGotAddress(elf_file);
- const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
- const off = try math.divExact(u12, @truncate(@as(u64, @bitCast(target_addr))), 8);
- const insts = &[_]Instruction{
- Instruction.adrp(.x16, pages),
- Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)),
- Instruction.br(.x17),
- Instruction.nop(),
+ const pages = try util.calcNumberOfPages(source_addr, target_addr);
+ const off: u12 = @truncate(@as(u64, @bitCast(target_addr)));
+ const insts = [_]util.encoding.Instruction{
+ .adrp(.x16, pages << 12),
+ .ldr(.x17, .{ .unsigned_offset = .{ .base = .x16, .offset = off } }),
+ .br(.x17),
+ .nop(),
};
comptime assert(insts.len == 4);
- for (insts) |inst| {
- try writer.writeInt(u32, inst.toU32(), .little);
- }
+ for (insts) |inst| try writer.writeInt(util.encoding.Instruction.Backing, @bitCast(inst), .little);
}
}
- const aarch64_util = @import("../aarch64.zig");
- const Instruction = aarch64_util.Instruction;
- const Register = aarch64_util.Register;
+ const util = @import("../aarch64.zig");
};
};
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 734b4b6a04..a3845727aa 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -328,6 +328,7 @@ pub fn deinit(self: *MachO) void {
self.unwind_info.deinit(gpa);
self.data_in_code.deinit(gpa);
+ for (self.thunks.items) |*thunk| thunk.deinit(gpa);
self.thunks.deinit(gpa);
}
@@ -612,7 +613,6 @@ pub fn flush(
};
const emit = self.base.emit;
invalidateKernelCache(emit.root_dir.handle, emit.sub_path) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
else => |e| return diags.fail("failed to invalidate kernel cache: {s}", .{@errorName(e)}),
};
}
@@ -5374,7 +5374,7 @@ const mem = std.mem;
const meta = std.meta;
const Writer = std.io.Writer;
-const aarch64 = @import("../arch/aarch64/bits.zig");
+const aarch64 = codegen.aarch64.encoding;
const bind = @import("MachO/dyld_info/bind.zig");
const calcUuid = @import("MachO/uuid.zig").calcUuid;
const codegen = @import("../codegen.zig");
diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig
index e084ae0385..2ecd8da532 100644
--- a/src/link/MachO/Atom.zig
+++ b/src/link/MachO/Atom.zig
@@ -780,8 +780,7 @@ fn resolveRelocInner(
};
break :target math.cast(u64, target) orelse return error.Overflow;
};
- const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(@intCast(source), @intCast(target))));
- aarch64.writeAdrpInst(pages, code[rel_offset..][0..4]);
+ aarch64.writeAdrInst(try aarch64.calcNumberOfPages(@intCast(source), @intCast(target)), code[rel_offset..][0..aarch64.encoding.Instruction.size]);
},
.pageoff => {
@@ -789,26 +788,18 @@ fn resolveRelocInner(
assert(rel.meta.length == 2);
assert(!rel.meta.pcrel);
const target = math.cast(u64, S + A) orelse return error.Overflow;
- const inst_code = code[rel_offset..][0..4];
- if (aarch64.isArithmeticOp(inst_code)) {
- aarch64.writeAddImmInst(@truncate(target), inst_code);
- } else {
- var inst = aarch64.Instruction{
- .load_store_register = mem.bytesToValue(@FieldType(
- aarch64.Instruction,
- @tagName(aarch64.Instruction.load_store_register),
- ), inst_code),
- };
- inst.load_store_register.offset = switch (inst.load_store_register.size) {
- 0 => if (inst.load_store_register.v == 1)
- try divExact(self, rel, @truncate(target), 16, macho_file)
- else
- @truncate(target),
- 1 => try divExact(self, rel, @truncate(target), 2, macho_file),
- 2 => try divExact(self, rel, @truncate(target), 4, macho_file),
- 3 => try divExact(self, rel, @truncate(target), 8, macho_file),
- };
- try writer.writeInt(u32, inst.toU32(), .little);
+ const inst_code = code[rel_offset..][0..aarch64.encoding.Instruction.size];
+ var inst: aarch64.encoding.Instruction = .read(inst_code);
+ switch (inst.decode()) {
+ else => unreachable,
+ .data_processing_immediate => aarch64.writeAddImmInst(@truncate(target), inst_code),
+ .load_store => |load_store| {
+ inst.load_store.register_unsigned_immediate.group.imm12 = switch (load_store.register_unsigned_immediate.decode()) {
+ .integer => |integer| try divExact(self, rel, @truncate(target), @as(u4, 1) << @intFromEnum(integer.group.size), macho_file),
+ .vector => |vector| try divExact(self, rel, @truncate(target), @as(u5, 1) << @intFromEnum(vector.group.opc1.decode(vector.group.size)), macho_file),
+ };
+ try writer.writeInt(u32, @bitCast(inst), .little);
+ },
}
},
@@ -834,59 +825,26 @@ fn resolveRelocInner(
break :target math.cast(u64, target) orelse return error.Overflow;
};
- const RegInfo = struct {
- rd: u5,
- rn: u5,
- size: u2,
- };
-
const inst_code = code[rel_offset..][0..4];
- const reg_info: RegInfo = blk: {
- if (aarch64.isArithmeticOp(inst_code)) {
- const inst = mem.bytesToValue(@FieldType(
- aarch64.Instruction,
- @tagName(aarch64.Instruction.add_subtract_immediate),
- ), inst_code);
- break :blk .{
- .rd = inst.rd,
- .rn = inst.rn,
- .size = inst.sf,
- };
- } else {
- const inst = mem.bytesToValue(@FieldType(
- aarch64.Instruction,
- @tagName(aarch64.Instruction.load_store_register),
- ), inst_code);
- break :blk .{
- .rd = inst.rt,
- .rn = inst.rn,
- .size = inst.size,
- };
- }
- };
-
- var inst = if (sym.getSectionFlags().tlv_ptr) aarch64.Instruction{
- .load_store_register = .{
- .rt = reg_info.rd,
- .rn = reg_info.rn,
- .offset = try divExact(self, rel, @truncate(target), 8, macho_file),
- .opc = 0b01,
- .op1 = 0b01,
- .v = 0,
- .size = reg_info.size,
+ const rd, const rn = switch (aarch64.encoding.Instruction.read(inst_code).decode()) {
+ else => unreachable,
+ .data_processing_immediate => |decoded| .{
+ decoded.add_subtract_immediate.group.Rd.decodeInteger(.doubleword, .{ .sp = true }),
+ decoded.add_subtract_immediate.group.Rn.decodeInteger(.doubleword, .{ .sp = true }),
},
- } else aarch64.Instruction{
- .add_subtract_immediate = .{
- .rd = reg_info.rd,
- .rn = reg_info.rn,
- .imm12 = @truncate(target),
- .sh = 0,
- .s = 0,
- .op = 0,
- .sf = @as(u1, @truncate(reg_info.size)),
+ .load_store => |decoded| .{
+ decoded.register_unsigned_immediate.integer.group.Rt.decodeInteger(.doubleword, .{}),
+ decoded.register_unsigned_immediate.group.Rn.decodeInteger(.doubleword, .{ .sp = true }),
},
};
- try writer.writeInt(u32, inst.toU32(), .little);
+
+ try writer.writeInt(u32, @bitCast(@as(
+ aarch64.encoding.Instruction,
+ if (sym.getSectionFlags().tlv_ptr) .ldr(rd, .{ .unsigned_offset = .{
+ .base = rn,
+ .offset = try divExact(self, rel, @truncate(target), 8, macho_file) * 8,
+ } }) else .add(rd, rn, .{ .immediate = @truncate(target) }),
+ )), .little);
},
}
}
diff --git a/src/link/MachO/Thunk.zig b/src/link/MachO/Thunk.zig
index e9f67dd5e5..26432da1f5 100644
--- a/src/link/MachO/Thunk.zig
+++ b/src/link/MachO/Thunk.zig
@@ -21,15 +21,17 @@ pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 {
}
pub fn write(thunk: Thunk, macho_file: *MachO, writer: anytype) !void {
+ const Instruction = aarch64.encoding.Instruction;
for (thunk.symbols.keys(), 0..) |ref, i| {
const sym = ref.getSymbol(macho_file).?;
const saddr = thunk.getAddress(macho_file) + i * trampoline_size;
const taddr = sym.getAddress(.{}, macho_file);
const pages = try aarch64.calcNumberOfPages(@intCast(saddr), @intCast(taddr));
- try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
- const off: u12 = @truncate(taddr);
- try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);
- try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.adrp(.x16, pages << 12)), .little);
+ try writer.writeInt(u32, @bitCast(
+ Instruction.add(.x16, .x16, .{ .immediate = @truncate(taddr) }),
+ ), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.br(.x16)), .little);
}
}
diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig
index d6a56f8411..ef82f82e72 100644
--- a/src/link/MachO/ZigObject.zig
+++ b/src/link/MachO/ZigObject.zig
@@ -945,9 +945,13 @@ fn updateNavCode(
log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
- const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
- const required_alignment = switch (pt.navAlignment(nav_index)) {
- .none => target_util.defaultFunctionAlignment(target),
+ const mod = zcu.navFileScope(nav_index).mod.?;
+ const target = &mod.resolved_target.result;
+ const required_alignment = switch (nav.status.fully_resolved.alignment) {
+ .none => switch (mod.optimize_mode) {
+ .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
+ .ReleaseSmall => target_util.minFunctionAlignment(target),
+ },
else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
};
diff --git a/src/link/MachO/synthetic.zig b/src/link/MachO/synthetic.zig
index c91c41df5f..22c44d2f7a 100644
--- a/src/link/MachO/synthetic.zig
+++ b/src/link/MachO/synthetic.zig
@@ -105,16 +105,15 @@ pub const StubsSection = struct {
try writer.writeInt(i32, @intCast(target - source - 2 - 4), .little);
},
.aarch64 => {
+ const Instruction = aarch64.encoding.Instruction;
// TODO relax if possible
const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
- try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
- const off = try math.divExact(u12, @truncate(target), 8);
- try writer.writeInt(
- u32,
- aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
- .little,
- );
- try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.adrp(.x16, pages << 12)), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.ldr(
+ .x16,
+ .{ .unsigned_offset = .{ .base = .x16, .offset = @as(u12, @truncate(target)) } },
+ )), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.br(.x16)), .little);
},
else => unreachable,
}
@@ -201,18 +200,16 @@ pub const StubsHelperSection = struct {
try writer.writeInt(i32, @intCast(target - source - 6 - 4), .little);
},
.aarch64 => {
- const literal = blk: {
- const div_res = try std.math.divExact(u64, entry_size - @sizeOf(u32), 4);
- break :blk std.math.cast(u18, div_res) orelse return error.Overflow;
- };
- try writer.writeInt(u32, aarch64.Instruction.ldrLiteral(
- .w16,
- literal,
- ).toU32(), .little);
+ const Instruction = aarch64.encoding.Instruction;
+ if (entry_size % Instruction.size != 0) return error.UnexpectedRemainder;
+ try writer.writeInt(u32, @bitCast(
+ Instruction.ldr(.w16, .{ .literal = std.math.cast(i21, entry_size - Instruction.size) orelse
+ return error.Overflow }),
+ ), .little);
const disp = math.cast(i28, @as(i64, @intCast(target)) - @as(i64, @intCast(source + 4))) orelse
return error.Overflow;
- try writer.writeInt(u32, aarch64.Instruction.b(disp).toU32(), .little);
- try writer.writeAll(&.{ 0x0, 0x0, 0x0, 0x0 });
+ try writer.writeInt(u32, @bitCast(Instruction.b(disp)), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.udf(0x0)), .little);
},
else => unreachable,
}
@@ -242,31 +239,28 @@ pub const StubsHelperSection = struct {
try writer.writeByte(0x90);
},
.aarch64 => {
+ const Instruction = aarch64.encoding.Instruction;
{
// TODO relax if possible
const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr), @intCast(dyld_private_addr));
- try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little);
- const off: u12 = @truncate(dyld_private_addr);
- try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);
+ try writer.writeInt(Instruction.Backing, @bitCast(Instruction.adrp(.x17, pages << 12)), .little);
+ try writer.writeInt(Instruction.Backing, @bitCast(
+ Instruction.add(.x17, .x17, .{ .immediate = @as(u12, @truncate(dyld_private_addr)) }),
+ ), .little);
}
- try writer.writeInt(u32, aarch64.Instruction.stp(
- .x16,
- .x17,
- aarch64.Register.sp,
- aarch64.Instruction.LoadStorePairOffset.pre_index(-16),
- ).toU32(), .little);
+ try writer.writeInt(Instruction.Backing, @bitCast(
+ Instruction.stp(.x16, .x17, .{ .pre_index = .{ .base = .sp, .index = -16 } }),
+ ), .little);
{
// TODO relax if possible
const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr + 12), @intCast(dyld_stub_binder_addr));
- try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
- const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8);
- try writer.writeInt(u32, aarch64.Instruction.ldr(
- .x16,
+ try writer.writeInt(Instruction.Backing, @bitCast(Instruction.adrp(.x16, pages << 12)), .little);
+ try writer.writeInt(Instruction.Backing, @bitCast(Instruction.ldr(
.x16,
- aarch64.Instruction.LoadStoreOffset.imm(off),
- ).toU32(), .little);
+ .{ .unsigned_offset = .{ .base = .x16, .offset = @as(u12, @truncate(dyld_stub_binder_addr)) } },
+ )), .little);
}
- try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
+ try writer.writeInt(Instruction.Backing, @bitCast(Instruction.br(.x16)), .little);
},
else => unreachable,
}
@@ -426,35 +420,32 @@ pub const ObjcStubsSection = struct {
}
},
.aarch64 => {
+ const Instruction = aarch64.encoding.Instruction;
{
const target = sym.getObjcSelrefsAddress(macho_file);
const source = addr;
const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
- try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little);
- const off = try math.divExact(u12, @truncate(target), 8);
- try writer.writeInt(
- u32,
- aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
- .little,
- );
+ try writer.writeInt(u32, @bitCast(Instruction.adrp(.x1, pages << 12)), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.ldr(
+ .x1,
+ .{ .unsigned_offset = .{ .base = .x1, .offset = @as(u12, @truncate(target)) } },
+ )), .little);
}
{
const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;
const target = target_sym.getGotAddress(macho_file);
const source = addr + 2 * @sizeOf(u32);
const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
- try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
- const off = try math.divExact(u12, @truncate(target), 8);
- try writer.writeInt(
- u32,
- aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
- .little,
- );
+ try writer.writeInt(u32, @bitCast(Instruction.adrp(.x16, pages << 12)), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.ldr(
+ .x16,
+ .{ .unsigned_offset = .{ .base = .x16, .offset = @as(u12, @truncate(target)) } },
+ )), .little);
}
- try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
- try writer.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);
- try writer.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);
- try writer.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.br(.x16)), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.brk(0x1)), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.brk(0x1)), .little);
+ try writer.writeInt(u32, @bitCast(Instruction.brk(0x1)), .little);
},
else => unreachable,
}
diff --git a/src/link/aarch64.zig b/src/link/aarch64.zig
index d86939a156..c9defc27b3 100644
--- a/src/link/aarch64.zig
+++ b/src/link/aarch64.zig
@@ -1,66 +1,36 @@
-pub inline fn isArithmeticOp(inst: *const [4]u8) bool {
- const group_decode = @as(u5, @truncate(inst[3]));
- return ((group_decode >> 2) == 4);
-}
+pub const encoding = @import("../codegen.zig").aarch64.encoding;
pub fn writeAddImmInst(value: u12, code: *[4]u8) void {
- var inst = Instruction{
- .add_subtract_immediate = mem.bytesToValue(@FieldType(
- Instruction,
- @tagName(Instruction.add_subtract_immediate),
- ), code),
- };
- inst.add_subtract_immediate.imm12 = value;
- mem.writeInt(u32, code, inst.toU32(), .little);
+ var inst: encoding.Instruction = .read(code);
+ inst.data_processing_immediate.add_subtract_immediate.group.imm12 = value;
+ inst.write(code);
}
pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void {
- var inst: Instruction = .{
- .load_store_register = mem.bytesToValue(@FieldType(
- Instruction,
- @tagName(Instruction.load_store_register),
- ), code),
- };
- inst.load_store_register.offset = value;
- mem.writeInt(u32, code, inst.toU32(), .little);
+ var inst: encoding.Instruction = .read(code);
+ inst.load_store.register_unsigned_immediate.group.imm12 = value;
+ inst.write(code);
}
-pub fn calcNumberOfPages(saddr: i64, taddr: i64) error{Overflow}!i21 {
- const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow;
- const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow;
- const pages = math.cast(i21, tpage - spage) orelse return error.Overflow;
- return pages;
+pub fn calcNumberOfPages(saddr: i64, taddr: i64) error{Overflow}!i33 {
+ return math.cast(i21, (taddr >> 12) - (saddr >> 12)) orelse error.Overflow;
}
-pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {
- var inst = Instruction{
- .pc_relative_address = mem.bytesToValue(@FieldType(
- Instruction,
- @tagName(Instruction.pc_relative_address),
- ), code),
- };
- inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2));
- inst.pc_relative_address.immlo = @as(u2, @truncate(pages));
- mem.writeInt(u32, code, inst.toU32(), .little);
+pub fn writeAdrInst(imm: i33, code: *[4]u8) void {
+ var inst: encoding.Instruction = .read(code);
+ inst.data_processing_immediate.pc_relative_addressing.group.immhi = @intCast(imm >> 2);
+ inst.data_processing_immediate.pc_relative_addressing.group.immlo = @bitCast(@as(i2, @truncate(imm)));
+ inst.write(code);
}
pub fn writeBranchImm(disp: i28, code: *[4]u8) void {
- var inst = Instruction{
- .unconditional_branch_immediate = mem.bytesToValue(@FieldType(
- Instruction,
- @tagName(Instruction.unconditional_branch_immediate),
- ), code),
- };
- inst.unconditional_branch_immediate.imm26 = @as(u26, @truncate(@as(u28, @bitCast(disp >> 2))));
- mem.writeInt(u32, code, inst.toU32(), .little);
+ var inst: encoding.Instruction = .read(code);
+ inst.branch_exception_generating_system.unconditional_branch_immediate.group.imm26 = @intCast(@shrExact(disp, 2));
+ inst.write(code);
}
const assert = std.debug.assert;
-const bits = @import("../arch/aarch64/bits.zig");
const builtin = @import("builtin");
const math = std.math;
const mem = std.mem;
const std = @import("std");
-
-pub const Instruction = bits.Instruction;
-pub const Register = bits.Register;