diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-06-07 13:08:22 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-07 13:08:22 -0400 |
| commit | 8b875b17ade95c4e0098c7c3b20134f03745aac3 (patch) | |
| tree | 02ee642b33451b453994f484a2204ddca42e4857 /lib/std | |
| parent | 173bc4274446a14aca2eea128b70b35b0ba18ebe (diff) | |
| parent | 5a52da1b7a8c467087da8f3a20ab902ec8c1e25d (diff) | |
| download | zig-8b875b17ade95c4e0098c7c3b20134f03745aac3.tar.gz zig-8b875b17ade95c4e0098c7c3b20134f03745aac3.zip | |
Merge pull request #24072 from jacobly0/x86_64-default
Compilation: enable the x86_64 backend by default for debug builds
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/Target.zig | 6 | ||||
| -rw-r--r-- | lib/std/builtin.zig | 15 | ||||
| -rw-r--r-- | lib/std/dynamic_library.zig | 13 | ||||
| -rw-r--r-- | lib/std/pie.zig | 343 | ||||
| -rw-r--r-- | lib/std/start.zig | 12 | ||||
| -rw-r--r-- | lib/std/zig/llvm/Builder.zig | 12 |
6 files changed, 218 insertions, 183 deletions
diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 084344535e..347b3357f5 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -2581,12 +2581,16 @@ pub fn standardDynamicLinkerPath(target: Target) DynamicLinker { } pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { + return ptrBitWidth_arch_abi(cpu.arch, abi); +} + +pub fn ptrBitWidth_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) u16 { switch (abi) { .gnux32, .muslx32, .gnuabin32, .muslabin32, .ilp32 => return 32, .gnuabi64, .muslabi64 => return 64, else => {}, } - return switch (cpu.arch) { + return switch (cpu_arch) { .avr, .msp430, => 16, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 1683cc500b..88e2304332 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -61,7 +61,7 @@ pub const StackTrace = struct { /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. -pub const GlobalLinkage = enum { +pub const GlobalLinkage = enum(u2) { internal, strong, weak, @@ -70,7 +70,7 @@ pub const GlobalLinkage = enum { /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. -pub const SymbolVisibility = enum { +pub const SymbolVisibility = enum(u2) { default, hidden, protected, @@ -1030,8 +1030,19 @@ pub const ExternOptions = struct { name: []const u8, library_name: ?[]const u8 = null, linkage: GlobalLinkage = .strong, + visibility: SymbolVisibility = .default, + /// Setting this to `true` makes the `@extern` a runtime value. is_thread_local: bool = false, is_dll_import: bool = false, + relocation: Relocation = .any, + + pub const Relocation = enum(u1) { + /// Any type of relocation is allowed. + any, + /// A program-counter-relative relocation is required. + /// Using this value makes the `@extern` a runtime value. + pcrel, + }; }; /// This data structure is used by the Zig language code generation and diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index 4b1faa87ba..bac31f5760 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -83,13 +83,16 @@ const RDebug = extern struct { r_ldbase: usize, }; -/// TODO make it possible to reference this same external symbol 2x so we don't need this -/// helper function. -pub fn get_DYNAMIC() ?[*]elf.Dyn { - return @extern([*]elf.Dyn, .{ .name = "_DYNAMIC", .linkage = .weak }); +/// TODO fix comparisons of extern symbol pointers so we don't need this helper function. +pub fn get_DYNAMIC() ?[*]const elf.Dyn { + return @extern([*]const elf.Dyn, .{ + .name = "_DYNAMIC", + .linkage = .weak, + .visibility = .hidden, + }); } -pub fn linkmap_iterator(phdrs: []elf.Phdr) error{InvalidExe}!LinkMap.Iterator { +pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator { _ = phdrs; const _DYNAMIC = get_DYNAMIC() orelse { // No PT_DYNAMIC means this is either a statically-linked program or a diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 572f3ddf96..0f4b4ff4b3 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -39,167 +39,175 @@ const R_RELATIVE = switch (builtin.cpu.arch) { // Obtain a pointer to the _DYNAMIC array. // We have to compute its address as a PC-relative quantity not to require a // relocation that, at this point, is not yet applied. -inline fn getDynamicSymbol() [*]elf.Dyn { - return switch (builtin.cpu.arch) { - .x86 => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ call 1f - \\ 1: pop %[ret] - \\ lea _DYNAMIC-1b(%[ret]), %[ret] - : [ret] "=r" (-> [*]elf.Dyn), - ), - .x86_64 => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ lea _DYNAMIC(%%rip), %[ret] - : [ret] "=r" (-> [*]elf.Dyn), - ), - .arc => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ add %[ret], pcl, _DYNAMIC@pcl - : [ret] "=r" (-> [*]elf.Dyn), - ), - // Work around the limited offset range of `ldr` - .arm, .armeb, .thumb, .thumbeb => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ ldr %[ret], 1f - \\ add %[ret], pc - \\ b 2f - \\ 1: .word _DYNAMIC-1b - \\ 2: - : [ret] "=r" (-> [*]elf.Dyn), - ), - // A simple `adr` is not enough as it has a limited offset range - .aarch64, .aarch64_be => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ adrp %[ret], _DYNAMIC - \\ add %[ret], %[ret], #:lo12:_DYNAMIC - : [ret] "=r" (-> [*]elf.Dyn), - ), - // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first - // entry in the GOT is defined to hold the address of _DYNAMIC. - .csky => asm volatile ( - \\ mov %[ret], gb - \\ ldw %[ret], %[ret] - : [ret] "=r" (-> [*]elf.Dyn), - ), - .hexagon => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ jump 1f - \\ .word _DYNAMIC - . - \\ 1: - \\ r1 = pc - \\ r1 = add(r1, #-4) - \\ %[ret] = memw(r1) - \\ %[ret] = add(r1, %[ret]) - : [ret] "=r" (-> [*]elf.Dyn), - : - : "r1" - ), - .loongarch32, .loongarch64 => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ la.local %[ret], _DYNAMIC - : [ret] "=r" (-> [*]elf.Dyn), - ), - // Note that the - 8 is needed because pc in the second lea instruction points into the - // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.) - .m68k => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ lea _DYNAMIC - . - 8, %[ret] - \\ lea (%[ret], %%pc), %[ret] - : [ret] "=r" (-> [*]elf.Dyn), - ), - .mips, .mipsel => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ bal 1f - \\ .gpword _DYNAMIC - \\ 1: - \\ lw %[ret], 0($ra) - \\ addu %[ret], %[ret], $gp - : [ret] "=r" (-> [*]elf.Dyn), - : - : "lr" - ), - .mips64, .mips64el => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ .balign 8 - \\ bal 1f - \\ .gpdword _DYNAMIC - \\ 1: - \\ ld %[ret], 0($ra) - \\ daddu %[ret], %[ret], $gp - : [ret] "=r" (-> [*]elf.Dyn), - : - : "lr" - ), - .powerpc, .powerpcle => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ bl 1f - \\ .long _DYNAMIC - . - \\ 1: - \\ mflr %[ret] - \\ lwz 4, 0(%[ret]) - \\ add %[ret], 4, %[ret] - : [ret] "=r" (-> [*]elf.Dyn), - : - : "lr", "r4" - ), - .powerpc64, .powerpc64le => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ bl 1f - \\ .quad _DYNAMIC - . - \\ 1: - \\ mflr %[ret] - \\ ld 4, 0(%[ret]) - \\ add %[ret], 4, %[ret] - : [ret] "=r" (-> [*]elf.Dyn), - : - : "lr", "r4" - ), - .riscv32, .riscv64 => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ lla %[ret], _DYNAMIC - : [ret] "=r" (-> [*]elf.Dyn), - ), - .s390x => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ larl %[ret], 1f - \\ ag %[ret], 0(%[ret]) - \\ jg 2f - \\ 1: .quad _DYNAMIC - . - \\ 2: - : [ret] "=r" (-> [*]elf.Dyn), - ), - // The compiler does not necessarily have any obligation to load the `l7` register (pointing - // to the GOT), so do it ourselves just in case. - .sparc, .sparc64 => asm volatile ( - \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7 - \\ call 1f - \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7 - \\ 1: - \\ add %%l7, %%o7, %[ret] - : [ret] "=r" (-> [*]elf.Dyn), - ), - else => { - @compileError("PIE startup is not yet supported for this target!"); +inline fn getDynamicSymbol() [*]const elf.Dyn { + return switch (builtin.zig_backend) { + else => switch (builtin.cpu.arch) { + .x86 => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ call 1f + \\ 1: pop %[ret] + \\ lea _DYNAMIC-1b(%[ret]), %[ret] + : [ret] "=r" (-> [*]const elf.Dyn), + ), + .x86_64 => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ lea _DYNAMIC(%%rip), %[ret] + : [ret] "=r" (-> [*]const elf.Dyn), + ), + .arc => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ add %[ret], pcl, _DYNAMIC@pcl + : [ret] "=r" (-> [*]const elf.Dyn), + ), + // Work around the limited offset range of `ldr` + .arm, .armeb, .thumb, .thumbeb => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ ldr %[ret], 1f + \\ add %[ret], pc + \\ b 2f + \\ 1: .word _DYNAMIC-1b + \\ 2: + : [ret] "=r" (-> [*]const elf.Dyn), + ), + // A simple `adr` is not enough as it has a limited offset range + .aarch64, .aarch64_be => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ adrp %[ret], _DYNAMIC + \\ add %[ret], %[ret], #:lo12:_DYNAMIC + : [ret] "=r" (-> [*]const elf.Dyn), + ), + // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first + // entry in the GOT is defined to hold the address of _DYNAMIC. + .csky => asm volatile ( + \\ mov %[ret], gb + \\ ldw %[ret], %[ret] + : [ret] "=r" (-> [*]const elf.Dyn), + ), + .hexagon => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ jump 1f + \\ .word _DYNAMIC - . + \\ 1: + \\ r1 = pc + \\ r1 = add(r1, #-4) + \\ %[ret] = memw(r1) + \\ %[ret] = add(r1, %[ret]) + : [ret] "=r" (-> [*]const elf.Dyn), + : + : "r1" + ), + .loongarch32, .loongarch64 => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ la.local %[ret], _DYNAMIC + : [ret] "=r" (-> [*]const elf.Dyn), + ), + // Note that the - 8 is needed because pc in the second lea instruction points into the + // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.) + .m68k => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ lea _DYNAMIC - . - 8, %[ret] + \\ lea (%[ret], %%pc), %[ret] + : [ret] "=r" (-> [*]const elf.Dyn), + ), + .mips, .mipsel => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ bal 1f + \\ .gpword _DYNAMIC + \\ 1: + \\ lw %[ret], 0($ra) + \\ addu %[ret], %[ret], $gp + : [ret] "=r" (-> [*]const elf.Dyn), + : + : "lr" + ), + .mips64, .mips64el => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ .balign 8 + \\ bal 1f + \\ .gpdword _DYNAMIC + \\ 1: + \\ ld %[ret], 0($ra) + \\ daddu %[ret], %[ret], $gp + : [ret] "=r" (-> [*]const elf.Dyn), + : + : "lr" + ), + .powerpc, .powerpcle => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ bl 1f + \\ .long _DYNAMIC - . + \\ 1: + \\ mflr %[ret] + \\ lwz 4, 0(%[ret]) + \\ add %[ret], 4, %[ret] + : [ret] "=r" (-> [*]const elf.Dyn), + : + : "lr", "r4" + ), + .powerpc64, .powerpc64le => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ bl 1f + \\ .quad _DYNAMIC - . + \\ 1: + \\ mflr %[ret] + \\ ld 4, 0(%[ret]) + \\ add %[ret], 4, %[ret] + : [ret] "=r" (-> [*]const elf.Dyn), + : + : "lr", "r4" + ), + .riscv32, .riscv64 => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ lla %[ret], _DYNAMIC + : [ret] "=r" (-> [*]const elf.Dyn), + ), + .s390x => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ larl %[ret], 1f + \\ ag %[ret], 0(%[ret]) + \\ jg 2f + \\ 1: .quad _DYNAMIC - . + \\ 2: + : [ret] "=r" (-> [*]const elf.Dyn), + ), + // The compiler does not necessarily have any obligation to load the `l7` register (pointing + // to the GOT), so do it ourselves just in case. + .sparc, .sparc64 => asm volatile ( + \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7 + \\ call 1f + \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7 + \\ 1: + \\ add %%l7, %%o7, %[ret] + : [ret] "=r" (-> [*]const elf.Dyn), + ), + else => { + @compileError("PIE startup is not yet supported for this target!"); + }, }, + .stage2_x86_64 => @extern([*]const elf.Dyn, .{ + .name = "_DYNAMIC", + .linkage = .weak, + .visibility = .hidden, + .relocation = .pcrel, + }).?, }; } -pub fn relocate(phdrs: []elf.Phdr) void { +pub fn relocate(phdrs: []const elf.Phdr) void { @setRuntimeSafety(false); @disableInstrumentation(); @@ -256,10 +264,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { const rel = sorted_dynv[elf.DT_REL]; if (rel != 0) { - const rels = @call(.always_inline, std.mem.bytesAsSlice, .{ - elf.Rel, - @as([*]u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]], - }); + const rels: []const elf.Rel = @alignCast(@ptrCast( + @as([*]align(@alignOf(elf.Rel)) const u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]], + )); for (rels) |r| { if (r.r_type() != R_RELATIVE) continue; @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* += base_addr; @@ -268,10 +275,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { const rela = sorted_dynv[elf.DT_RELA]; if (rela != 0) { - const relas = @call(.always_inline, std.mem.bytesAsSlice, .{ - elf.Rela, - @as([*]u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]], - }); + const relas: []const elf.Rela = @alignCast(@ptrCast( + @as([*]align(@alignOf(elf.Rela)) const u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]], + )); for (relas) |r| { if (r.r_type() != R_RELATIVE) continue; @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* = base_addr + @as(usize, @bitCast(r.r_addend)); @@ -280,10 +286,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { const relr = sorted_dynv[elf.DT_RELR]; if (relr != 0) { - const relrs = @call(.always_inline, std.mem.bytesAsSlice, .{ - elf.Relr, - @as([*]u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]], - }); + const relrs: []const elf.Relr = @ptrCast( + @as([*]align(@alignOf(elf.Relr)) const u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]], + ); var current: [*]usize = undefined; for (relrs) |r| { if ((r & 1) == 0) { diff --git a/lib/std/start.zig b/lib/std/start.zig index 2280bea9e7..9b4897260e 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -163,7 +163,7 @@ fn exit2(code: usize) noreturn { // exits(0) .plan9 => std.os.plan9.exits(null), .windows => { - std.os.windows.ntdll.RtlExitUserProcess(@as(u32, @truncate(code))); + std.os.windows.ntdll.RtlExitUserProcess(@truncate(code)); }, else => @compileError("TODO"), } @@ -511,7 +511,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { // Code coverage instrumentation might try to use thread local variables. @disableInstrumentation(); const argc = argc_argv_ptr[0]; - const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1)); + const argv: [*][*:0]u8 = @ptrCast(argc_argv_ptr + 1); const envp_optional: [*:null]?[*:0]u8 = @ptrCast(@alignCast(argv + argc + 1)); var envp_count: usize = 0; @@ -573,11 +573,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { expandStackSize(phdrs); } - const opt_init_array_start = @extern([*]*const fn () callconv(.c) void, .{ + const opt_init_array_start = @extern([*]const *const fn () callconv(.c) void, .{ .name = "__init_array_start", .linkage = .weak, }); - const opt_init_array_end = @extern([*]*const fn () callconv(.c) void, .{ + const opt_init_array_end = @extern([*]const *const fn () callconv(.c) void, .{ .name = "__init_array_end", .linkage = .weak, }); @@ -651,7 +651,7 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal } fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int { - std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@as(usize, @intCast(c_argc))]; + std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@intCast(c_argc)]; return callMain(); } @@ -701,7 +701,7 @@ pub inline fn callMain() u8 { pub fn call_wWinMain() std.os.windows.INT { const peb = std.os.windows.peb(); const MAIN_HINSTANCE = @typeInfo(@TypeOf(root.wWinMain)).@"fn".params[0].type.?; - const hInstance = @as(MAIN_HINSTANCE, @ptrCast(peb.ImageBaseAddress)); + const hInstance: MAIN_HINSTANCE = @ptrCast(peb.ImageBaseAddress); const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer); // There are various types used for the 'show window' variable through the Win32 APIs: diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index d8d5ff19c7..865e1efa6d 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -1823,6 +1823,14 @@ pub const Visibility = enum(u2) { hidden = 1, protected = 2, + pub fn fromSymbolVisibility(sv: std.builtin.SymbolVisibility) Visibility { + return switch (sv) { + .default => .default, + .hidden => .hidden, + .protected => .protected, + }; + } + pub fn format( self: Visibility, comptime _: []const u8, @@ -2555,6 +2563,10 @@ pub const Variable = struct { return self.ptrConst(builder).global.setLinkage(linkage, builder); } + pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void { + return self.ptrConst(builder).global.setVisibility(visibility, builder); + } + pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { return self.ptrConst(builder).global.setDllStorageClass(class, builder); } |
