aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2024-08-01 07:17:40 +0200
committerGitHub <noreply@github.com>2024-08-01 07:17:40 +0200
commit8ea323822ba1fc2f54940841b2cedb3494230a3c (patch)
tree6ba1a9006af4f9e0e7737310cd646f4f836edf8e
parenteb1a199dff2b54271bd275c2528bdd898bf1d4eb (diff)
parent2b8a71489a24649342e797f609fc6bb1b141a422 (diff)
downloadzig-8ea323822ba1fc2f54940841b2cedb3494230a3c.tar.gz
zig-8ea323822ba1fc2f54940841b2cedb3494230a3c.zip
Merge pull request #20884 from Rexicon226/riscv
-rw-r--r--lib/std/start.zig27
-rw-r--r--src/arch/riscv64/CodeGen.zig8
-rw-r--r--src/arch/riscv64/Emit.zig3
-rw-r--r--src/link/Elf.zig31
-rw-r--r--src/link/Elf/Atom.zig20
-rw-r--r--src/link/Elf/relocation.zig4
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)))}),