| author | |
| committer | |
| log | fcafaae747c0d032401ca7936b667f5dfcf0466b |
| tree | bfbf921a30a4cf275aaabb4012429e72709687e4 |
| parent | 004d0c8978d4b5e4212c06abb33d7a594930f8c5 |
| signature |
7 files changed, 128 insertions(+), 34 deletions(-)
src/arch/riscv64/CodeGen.zig+32-11| ... | ... | @@ -3590,22 +3590,42 @@ fn genCall( |
| 3590 | 3590 | const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); |
| 3591 | 3591 | const sym = elf_file.symbol(sym_index); |
| 3592 | 3592 | |
| 3593 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | |
| 3594 | const got_addr = sym.zigGotAddress(elf_file); | |
| 3595 | try self.genSetReg(Type.usize, .ra, .{ .memory = @intCast(got_addr) }); | |
| 3593 | if (self.mod.pic) { | |
| 3594 | return self.fail("TODO: genCall pic", .{}); | |
| 3595 | } else { | |
| 3596 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | |
| 3597 | const got_addr = sym.zigGotAddress(elf_file); | |
| 3598 | try self.genSetReg(Type.usize, .ra, .{ .memory = @intCast(got_addr) }); | |
| 3599 | ||
| 3600 | _ = try self.addInst(.{ | |
| 3601 | .tag = .jalr, | |
| 3602 | .ops = .rri, | |
| 3603 | .data = .{ .i_type = .{ | |
| 3604 | .rd = .ra, | |
| 3605 | .rs1 = .ra, | |
| 3606 | .imm12 = Immediate.s(0), | |
| 3607 | } }, | |
| 3608 | }); | |
| 3609 | } | |
| 3610 | } else unreachable; // not a valid riscv64 format | |
| 3611 | }, | |
| 3612 | .extern_func => |extern_func| { | |
| 3613 | const owner_decl = zcu.declPtr(extern_func.decl); | |
| 3614 | const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool); | |
| 3615 | const decl_name = owner_decl.name.toSlice(&zcu.intern_pool); | |
| 3616 | const atom_index = try self.symbolIndex(); | |
| 3596 | 3617 | |
| 3618 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 3597 | 3619 | _ = try self.addInst(.{ |
| 3598 | .tag = .jalr, | |
| 3599 | .ops = .rri, | |
| 3600 | .data = .{ .i_type = .{ | |
| 3601 | .rd = .ra, | |
| 3602 | .rs1 = .ra, | |
| 3603 | .imm12 = Immediate.s(0), | |
| 3620 | .tag = .pseudo, | |
| 3621 | .ops = .pseudo_extern_fn_reloc, | |
| 3622 | .data = .{ .reloc = .{ | |
| 3623 | .atom_index = atom_index, | |
| 3624 | .sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name), | |
| 3604 | 3625 | } }, |
| 3605 | 3626 | }); |
| 3606 | } else unreachable; | |
| 3627 | } else unreachable; // not a valid riscv64 format | |
| 3607 | 3628 | }, |
| 3608 | .extern_func => return self.fail("TODO: extern func calls", .{}), | |
| 3609 | 3629 | else => return self.fail("TODO implement calling bitcasted functions", .{}), |
| 3610 | 3630 | } |
| 3611 | 3631 | } else { |
| ... | ... | @@ -3613,6 +3633,7 @@ fn genCall( |
| 3613 | 3633 | const addr_reg, const addr_lock = try self.allocReg(); |
| 3614 | 3634 | defer self.register_manager.unlockReg(addr_lock); |
| 3615 | 3635 | try self.genSetReg(Type.usize, addr_reg, .{ .air_ref = callee }); |
| 3636 | ||
| 3616 | 3637 | _ = try self.addInst(.{ |
| 3617 | 3638 | .tag = .jalr, |
| 3618 | 3639 | .ops = .rri, |
src/arch/riscv64/Emit.zig+13| ... | ... | @@ -70,6 +70,19 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 70 | 70 | }); |
| 71 | 71 | } else return emit.fail("TODO: load_symbol_reloc non-ELF", .{}); |
| 72 | 72 | }, |
| 73 | .call_extern_fn_reloc => |symbol| { | |
| 74 | if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 75 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | |
| 76 | ||
| 77 | const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT); | |
| 78 | ||
| 79 | try atom_ptr.addReloc(elf_file, .{ | |
| 80 | .r_offset = start_offset, | |
| 81 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type, | |
| 82 | .r_addend = 0, | |
| 83 | }); | |
| 84 | } else return emit.fail("TODO: call_extern_fn_reloc non-ELF", .{}); | |
| 85 | }, | |
| 73 | 86 | }; |
| 74 | 87 | } |
| 75 | 88 | std.debug.assert(lowered_relocs.len == 0); |
src/arch/riscv64/Encoding.zig+3| ... | ... | @@ -22,6 +22,7 @@ pub const Mnemonic = enum { |
| 22 | 22 | |
| 23 | 23 | // U Type |
| 24 | 24 | lui, |
| 25 | auipc, | |
| 25 | 26 | |
| 26 | 27 | // S Type |
| 27 | 28 | sd, |
| ... | ... | @@ -78,6 +79,7 @@ pub const Mnemonic = enum { |
| 78 | 79 | .srai => .{ .opcode = 0b0010011, .funct3 = 0b101, .funct7 = null, .offset = 1 << 10 }, |
| 79 | 80 | |
| 80 | 81 | .lui => .{ .opcode = 0b0110111, .funct3 = null, .funct7 = null }, |
| 82 | .auipc => .{ .opcode = 0b0010111, .funct3 = null, .funct7 = null }, | |
| 81 | 83 | |
| 82 | 84 | .sd => .{ .opcode = 0b0100011, .funct3 = 0b011, .funct7 = null }, |
| 83 | 85 | .sw => .{ .opcode = 0b0100011, .funct3 = 0b010, .funct7 = null }, |
| ... | ... | @@ -133,6 +135,7 @@ pub const InstEnc = enum { |
| 133 | 135 | => .I, |
| 134 | 136 | |
| 135 | 137 | .lui, |
| 138 | .auipc, | |
| 136 | 139 | => .U, |
| 137 | 140 | |
| 138 | 141 | .sd, |
src/arch/riscv64/Lower.zig+23-1| ... | ... | @@ -32,8 +32,10 @@ pub const Reloc = struct { |
| 32 | 32 | const Target = union(enum) { |
| 33 | 33 | inst: Mir.Inst.Index, |
| 34 | 34 | |
| 35 | /// Relocs the lowered_inst_index and the next one. | |
| 35 | /// Relocs the lowered_inst_index and the next instruction. | |
| 36 | 36 | load_symbol_reloc: bits.Symbol, |
| 37 | /// Relocs the lowered_inst_index and the next instruction. | |
| 38 | call_extern_fn_reloc: bits.Symbol, | |
| 37 | 39 | }; |
| 38 | 40 | }; |
| 39 | 41 | |
| ... | ... | @@ -247,6 +249,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 247 | 249 | }); |
| 248 | 250 | }, |
| 249 | 251 | |
| 252 | .pseudo_extern_fn_reloc => { | |
| 253 | const inst_reloc = inst.data.reloc; | |
| 254 | ||
| 255 | try lower.emit(.auipc, &.{ | |
| 256 | .{ .reg = .ra }, | |
| 257 | .{ .imm = lower.reloc( | |
| 258 | .{ .call_extern_fn_reloc = .{ | |
| 259 | .atom_index = inst_reloc.atom_index, | |
| 260 | .sym_index = inst_reloc.sym_index, | |
| 261 | } }, | |
| 262 | ) }, | |
| 263 | }); | |
| 264 | ||
| 265 | try lower.emit(.jalr, &.{ | |
| 266 | .{ .reg = .ra }, | |
| 267 | .{ .reg = .ra }, | |
| 268 | .{ .imm = Immediate.s(0) }, | |
| 269 | }); | |
| 270 | }, | |
| 271 | ||
| 250 | 272 | else => return lower.fail("TODO lower: psuedo {s}", .{@tagName(inst.ops)}), |
| 251 | 273 | }, |
| 252 | 274 | } |
src/arch/riscv64/Mir.zig+9-4| ... | ... | @@ -202,6 +202,11 @@ pub const Inst = struct { |
| 202 | 202 | lte, |
| 203 | 203 | }, |
| 204 | 204 | }, |
| 205 | ||
| 206 | reloc: struct { | |
| 207 | atom_index: u32, | |
| 208 | sym_index: u32, | |
| 209 | }, | |
| 205 | 210 | }; |
| 206 | 211 | |
| 207 | 212 | pub const Ops = enum { |
| ... | ... | @@ -214,10 +219,7 @@ pub const Inst = struct { |
| 214 | 219 | |
| 215 | 220 | /// Two registers + immediate, uses the i_type payload. |
| 216 | 221 | rri, |
| 217 | /// Two registers + Two Immediates | |
| 218 | rrii, | |
| 219 | ||
| 220 | /// Two registers + another instruction. | |
| 222 | //extern_fn_reloc/ Two registers + another instruction. | |
| 221 | 223 | rr_inst, |
| 222 | 224 | |
| 223 | 225 | /// Register + Memory |
| ... | ... | @@ -283,6 +285,9 @@ pub const Inst = struct { |
| 283 | 285 | |
| 284 | 286 | pseudo_compare, |
| 285 | 287 | pseudo_not, |
| 288 | ||
| 289 | /// Generates an auipc + jalr pair, with a R_RISCV_CALL_PLT reloc | |
| 290 | pseudo_extern_fn_reloc, | |
| 286 | 291 | }; |
| 287 | 292 | |
| 288 | 293 | // Make sure we don't accidentally make instructions bigger than expected. |
src/link/Elf.zig+2-1| ... | ... | @@ -5842,7 +5842,8 @@ pub fn tpAddress(self: *Elf) i64 { |
| 5842 | 5842 | const addr = switch (self.getTarget().cpu.arch) { |
| 5843 | 5843 | .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align), |
| 5844 | 5844 | .aarch64 => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align), |
| 5845 | else => @panic("TODO implement getTpAddress for this arch"), | |
| 5845 | .riscv64 => phdr.p_vaddr, | |
| 5846 | else => |arch| std.debug.panic("TODO implement getTpAddress for {s}", .{@tagName(arch)}), | |
| 5846 | 5847 | }; |
| 5847 | 5848 | return @intCast(addr); |
| 5848 | 5849 | } |
src/link/Elf/Atom.zig+46-17| ... | ... | @@ -1409,11 +1409,11 @@ const x86_64 = struct { |
| 1409 | 1409 | .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), |
| 1410 | 1410 | .SIZE32 => { |
| 1411 | 1411 | const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); |
| 1412 | try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(size + A)))), .little); | |
| 1412 | try cwriter.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little); | |
| 1413 | 1413 | }, |
| 1414 | 1414 | .SIZE64 => { |
| 1415 | 1415 | const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); |
| 1416 | try cwriter.writeInt(i64, @as(i64, @intCast(size + A)), .little); | |
| 1416 | try cwriter.writeInt(i64, @intCast(size + A), .little); | |
| 1417 | 1417 | }, |
| 1418 | 1418 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| 1419 | 1419 | } |
| ... | ... | @@ -2001,26 +2001,25 @@ const riscv = struct { |
| 2001 | 2001 | const r_type: elf.R_RISCV = @enumFromInt(rel.r_type()); |
| 2002 | 2002 | |
| 2003 | 2003 | switch (r_type) { |
| 2004 | .@"64" => { | |
| 2005 | try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); | |
| 2006 | }, | |
| 2007 | ||
| 2008 | .HI20 => { | |
| 2009 | try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file); | |
| 2010 | }, | |
| 2004 | .@"32" => try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file), | |
| 2005 | .@"64" => try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file), | |
| 2006 | .HI20 => try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file), | |
| 2011 | 2007 | |
| 2012 | 2008 | .CALL_PLT => if (symbol.flags.import) { |
| 2013 | 2009 | symbol.flags.needs_plt = true; |
| 2014 | 2010 | }, |
| 2011 | .GOT_HI20 => symbol.flags.needs_got = true, | |
| 2015 | 2012 | |
| 2016 | .GOT_HI20 => { | |
| 2017 | symbol.flags.needs_got = true; | |
| 2018 | }, | |
| 2013 | .TPREL_HI20, | |
| 2014 | .TPREL_LO12_I, | |
| 2015 | .TPREL_LO12_S, | |
| 2016 | .TPREL_ADD, | |
| 2019 | 2017 | |
| 2020 | 2018 | .PCREL_HI20, |
| 2021 | 2019 | .PCREL_LO12_I, |
| 2022 | 2020 | .PCREL_LO12_S, |
| 2023 | 2021 | .LO12_I, |
| 2022 | .LO12_S, | |
| 2024 | 2023 | .ADD32, |
| 2025 | 2024 | .SUB32, |
| 2026 | 2025 | => {}, |
| ... | ... | @@ -2058,6 +2057,8 @@ const riscv = struct { |
| 2058 | 2057 | switch (r_type) { |
| 2059 | 2058 | .NONE => unreachable, |
| 2060 | 2059 | |
| 2060 | .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), | |
| 2061 | ||
| 2061 | 2062 | .@"64" => { |
| 2062 | 2063 | try atom.resolveDynAbsReloc( |
| 2063 | 2064 | target, |
| ... | ... | @@ -2076,11 +2077,6 @@ const riscv = struct { |
| 2076 | 2077 | riscv_util.writeInstU(code[r_offset..][0..4], value); |
| 2077 | 2078 | }, |
| 2078 | 2079 | |
| 2079 | .LO12_I => { | |
| 2080 | const value: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow); | |
| 2081 | riscv_util.writeInstI(code[r_offset..][0..4], value); | |
| 2082 | }, | |
| 2083 | ||
| 2084 | 2080 | .GOT_HI20 => { |
| 2085 | 2081 | assert(target.flags.has_got); |
| 2086 | 2082 | const disp: u32 = @bitCast(math.cast(i32, G + GOT + A - P) orelse return error.Overflow); |
| ... | ... | @@ -2143,6 +2139,39 @@ const riscv = struct { |
| 2143 | 2139 | } |
| 2144 | 2140 | }, |
| 2145 | 2141 | |
| 2142 | .LO12_I, | |
| 2143 | .LO12_S, | |
| 2144 | => { | |
| 2145 | const disp: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow); | |
| 2146 | switch (r_type) { | |
| 2147 | .LO12_I => riscv_util.writeInstI(code[r_offset..][0..4], disp), | |
| 2148 | .LO12_S => riscv_util.writeInstS(code[r_offset..][0..4], disp), | |
| 2149 | else => unreachable, | |
| 2150 | } | |
| 2151 | }, | |
| 2152 | ||
| 2153 | .TPREL_HI20 => { | |
| 2154 | const target_addr: u32 = @intCast(target.address(.{}, elf_file)); | |
| 2155 | const val: i32 = @intCast(S + A - target_addr); | |
| 2156 | riscv_util.writeInstU(code[r_offset..][0..4], @bitCast(val)); | |
| 2157 | }, | |
| 2158 | ||
| 2159 | .TPREL_LO12_I, | |
| 2160 | .TPREL_LO12_S, | |
| 2161 | => { | |
| 2162 | const target_addr: u32 = @intCast(target.address(.{}, elf_file)); | |
| 2163 | const val: i32 = @intCast(S + A - target_addr); | |
| 2164 | switch (r_type) { | |
| 2165 | .TPREL_LO12_I => riscv_util.writeInstI(code[r_offset..][0..4], @bitCast(val)), | |
| 2166 | .TPREL_LO12_S => riscv_util.writeInstS(code[r_offset..][0..4], @bitCast(val)), | |
| 2167 | else => unreachable, | |
| 2168 | } | |
| 2169 | }, | |
| 2170 | ||
| 2171 | .TPREL_ADD => { | |
| 2172 | // TODO: annotates an ADD instruction that can be removed when TPREL is relaxed | |
| 2173 | }, | |
| 2174 | ||
| 2146 | 2175 | else => |x| switch (@intFromEnum(x)) { |
| 2147 | 2176 | // Zig custom relocations |
| 2148 | 2177 | Elf.R_ZIG_GOT_HI20 => { |