diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-01 07:17:40 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-01 07:17:40 +0200 |
| commit | 8ea323822ba1fc2f54940841b2cedb3494230a3c (patch) | |
| tree | 6ba1a9006af4f9e0e7737310cd646f4f836edf8e | |
| parent | eb1a199dff2b54271bd275c2528bdd898bf1d4eb (diff) | |
| parent | 2b8a71489a24649342e797f609fc6bb1b141a422 (diff) | |
| download | zig-8ea323822ba1fc2f54940841b2cedb3494230a3c.tar.gz zig-8ea323822ba1fc2f54940841b2cedb3494230a3c.zip | |
Merge pull request #20884 from Rexicon226/riscv
| -rw-r--r-- | lib/std/start.zig | 27 | ||||
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 8 | ||||
| -rw-r--r-- | src/arch/riscv64/Emit.zig | 3 | ||||
| -rw-r--r-- | src/link/Elf.zig | 31 | ||||
| -rw-r--r-- | src/link/Elf/Atom.zig | 20 | ||||
| -rw-r--r-- | src/link/Elf/relocation.zig | 4 |
6 files changed, 72 insertions, 21 deletions
diff --git a/lib/std/start.zig b/lib/std/start.zig index 8d55c178e4..61e41370b4 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -465,21 +465,18 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.C) noreturn { // to ask for more stack space. expandStackSize(phdrs); - // Disabled with the riscv backend because it cannot handle this code yet. - if (builtin.zig_backend != .stage2_riscv64) { - const opt_init_array_start = @extern([*]*const fn () callconv(.C) void, .{ - .name = "__init_array_start", - .linkage = .weak, - }); - const opt_init_array_end = @extern([*]*const fn () callconv(.C) void, .{ - .name = "__init_array_end", - .linkage = .weak, - }); - if (opt_init_array_start) |init_array_start| { - const init_array_end = opt_init_array_end.?; - const slice = init_array_start[0 .. init_array_end - init_array_start]; - for (slice) |func| func(); - } + const opt_init_array_start = @extern([*]*const fn () callconv(.C) void, .{ + .name = "__init_array_start", + .linkage = .weak, + }); + const opt_init_array_end = @extern([*]*const fn () callconv(.C) void, .{ + .name = "__init_array_end", + .linkage = .weak, + }); + if (opt_init_array_start) |init_array_start| { + const init_array_end = opt_init_array_end.?; + const slice = init_array_start[0 .. init_array_end - init_array_start]; + for (slice) |func| func(); } } diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 46140b4727..040afd3160 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1510,6 +1510,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { .mul, .mul_wrap, .div_trunc, + .div_exact, .rem, .shl, .shl_exact, @@ -1533,7 +1534,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { .mod, .div_float, .div_floor, - .div_exact, => return func.fail("TODO: {s}", .{@tagName(tag)}), .sqrt, @@ -2563,10 +2563,12 @@ fn genBinOp( .mul_wrap, .rem, .div_trunc, + .div_exact, => { switch (tag) { .rem, .div_trunc, + .div_exact, => { if (!math.isPowerOfTwo(bit_size)) { try func.truncateRegister(lhs_ty, lhs_reg); @@ -2576,7 +2578,7 @@ fn genBinOp( else => { if (!math.isPowerOfTwo(bit_size)) return func.fail( - "TODO: genBinOp verify {s} non-pow 2, found {}", + "TODO: genBinOp verify if needs to truncate {s} non-pow 2, found {}", .{ @tagName(tag), bit_size }, ); }, @@ -2604,7 +2606,7 @@ fn genBinOp( 8, 16, 32 => if (is_unsigned) .remuw else .remw, else => if (is_unsigned) .remu else .rem, }, - .div_trunc => switch (bit_size) { + .div_trunc, .div_exact => switch (bit_size) { 8, 16, 32 => if (is_unsigned) .divuw else .divw, else => if (is_unsigned) .divu else .div, }, diff --git a/src/arch/riscv64/Emit.zig b/src/arch/riscv64/Emit.zig index 6c04988e78..beb232b776 100644 --- a/src/arch/riscv64/Emit.zig +++ b/src/arch/riscv64/Emit.zig @@ -63,6 +63,9 @@ pub fn emitMir(emit: *Emit) Error!void { hi_r_type = Elf.R_ZIG_GOT_HI20; lo_r_type = Elf.R_ZIG_GOT_LO12; + } else if (sym.flags.needs_got) { + hi_r_type = Elf.R_GOT_HI20_STATIC; // TODO: rework this #20887 + lo_r_type = Elf.R_GOT_LO12_I_STATIC; // TODO: rework this #20887 } try atom_ptr.addReloc(elf_file, .{ diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 982015f61f..469e8da345 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -6059,11 +6059,40 @@ const RelaSection = struct { }; const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); -// TODO: add comptime check we don't clobber any reloc for any ISA pub const R_ZIG_GOT32: u32 = 0xff00; pub const R_ZIG_GOTPCREL: u32 = 0xff01; pub const R_ZIG_GOT_HI20: u32 = 0xff02; pub const R_ZIG_GOT_LO12: u32 = 0xff03; +pub const R_GOT_HI20_STATIC: u32 = 0xff04; +pub const R_GOT_LO12_I_STATIC: u32 = 0xff05; + +// Comptime asserts that no Zig relocs overlap with another ISA's reloc number +comptime { + const zig_relocs = .{ + R_ZIG_GOT32, + R_ZIG_GOT_HI20, + R_ZIG_GOT_LO12, + R_ZIG_GOTPCREL, + R_GOT_HI20_STATIC, + R_GOT_LO12_I_STATIC, + }; + + const other_relocs = .{ + elf.R_X86_64, + elf.R_AARCH64, + elf.R_RISCV, + elf.R_PPC64, + }; + + @setEvalBranchQuota(@min(other_relocs.len * zig_relocs.len * 256, 6200)); + for (other_relocs) |relocs| { + for (@typeInfo(relocs).Enum.fields) |reloc| { + for (zig_relocs) |zig_reloc| { + assert(reloc.value != zig_reloc); + } + } + } +} fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { return switch (cpu_arch) { diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 30285f204a..b91b546103 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -2016,6 +2016,10 @@ const riscv = struct { assert(symbol.flags.has_zig_got); }, + Elf.R_GOT_HI20_STATIC, + Elf.R_GOT_LO12_I_STATIC, + => symbol.flags.needs_got = true, + else => try atom.reportUnhandledRelocError(rel, elf_file), }, } @@ -2161,16 +2165,28 @@ const riscv = struct { // Zig custom relocations Elf.R_ZIG_GOT_HI20 => { assert(target.flags.has_zig_got); - const disp: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow); + const disp: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow); riscv_util.writeInstU(code[r_offset..][0..4], disp); }, Elf.R_ZIG_GOT_LO12 => { assert(target.flags.has_zig_got); - const value: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow); + const value: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow); riscv_util.writeInstI(code[r_offset..][0..4], value); }, + Elf.R_GOT_HI20_STATIC => { + assert(target.flags.has_got); + const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow); + riscv_util.writeInstU(code[r_offset..][0..4], disp); + }, + + Elf.R_GOT_LO12_I_STATIC => { + assert(target.flags.has_got); + const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow); + riscv_util.writeInstI(code[r_offset..][0..4], disp); + }, + else => try atom.reportUnhandledRelocError(rel, elf_file), }, } diff --git a/src/link/Elf/relocation.zig b/src/link/Elf/relocation.zig index 3c8afa3c12..5f6810d6f9 100644 --- a/src/link/Elf/relocation.zig +++ b/src/link/Elf/relocation.zig @@ -115,6 +115,10 @@ fn formatRelocType( switch (r_type) { Elf.R_ZIG_GOT32 => try writer.writeAll("R_ZIG_GOT32"), Elf.R_ZIG_GOTPCREL => try writer.writeAll("R_ZIG_GOTPCREL"), + Elf.R_ZIG_GOT_HI20 => try writer.writeAll("R_ZIG_GOT_HI20"), + Elf.R_ZIG_GOT_LO12 => try writer.writeAll("R_ZIG_GOT_LO12"), + Elf.R_GOT_HI20_STATIC => try writer.writeAll("R_GOT_HI20_STATIC"), + Elf.R_GOT_LO12_I_STATIC => try writer.writeAll("R_GOT_LO12_I_STATIC"), else => switch (ctx.cpu_arch) { .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}), .aarch64 => try writer.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}), |
