authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-03-29 06:48:41-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-11 02:17:11-07:00
log3bf008a3d07b2d9f91964141e1fb33d3fab82390
tree79ddbcce26ac695f979fa75a021463424359dc13
parent350ad90ceec37cb3f152b666377f7f619981a60e

riscv: implement slices


8 files changed, 232 insertions(+), 91 deletions(-)

lib/std/builtin.zig+8-8
......@@ -775,14 +775,14 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
775775 }
776776
777777 if (builtin.zig_backend == .stage2_riscv64) {
778 // asm volatile ("ecall"
779 // :
780 // : [number] "{a7}" (64),
781 // [arg1] "{a0}" (1),
782 // [arg2] "{a1}" (@intFromPtr(msg.ptr)),
783 // [arg3] "{a2}" (msg.len),
784 // : "rcx", "r11", "memory"
785 // );
778 asm volatile ("ecall"
779 :
780 : [number] "{a7}" (64),
781 [arg1] "{a0}" (1),
782 [arg2] "{a1}" (@intFromPtr(msg.ptr)),
783 [arg3] "{a2}" (msg.len),
784 : "rcx", "r11", "memory"
785 );
786786 std.posix.exit(127);
787787 }
788788
src/arch/riscv64/CodeGen.zig+138-70
......@@ -122,9 +122,10 @@ const MCValue = union(enum) {
122122 /// A pointer-sized integer that fits in a register.
123123 /// If the type is a pointer, this is the pointer address in virtual address space.
124124 immediate: u64,
125 /// The value is in memory at an address not-yet-allocated by the linker.
126 /// This traditionally corresponds to a relocation emitted in a relocatable object file.
125 /// The value doesn't exist in memory yet.
127126 load_symbol: SymbolOffset,
127 /// The address of the memory location not-yet-allocated by the linker.
128 addr_symbol: SymbolOffset,
128129 /// The value is in a target-specific register.
129130 register: Register,
130131 /// The value is split across two registers
......@@ -169,6 +170,7 @@ const MCValue = union(enum) {
169170 .indirect,
170171 .undef,
171172 .load_symbol,
173 .addr_symbol,
172174 .air_ref,
173175 => false,
174176
......@@ -188,10 +190,14 @@ const MCValue = union(enum) {
188190 .immediate,
189191 .ptr_stack_offset,
190192 .register_offset,
193 .register_pair,
194 .register,
191195 .undef,
192196 .air_ref,
197 .addr_symbol,
193198 => unreachable, // not in memory
194199
200 .load_symbol => |sym_off| .{ .addr_symbol = sym_off },
195201 .memory => |addr| .{ .immediate = addr },
196202 .stack_offset => |off| .{ .ptr_stack_offset = off },
197203 .indirect => |reg_off| switch (reg_off.off) {
......@@ -219,6 +225,7 @@ const MCValue = union(enum) {
219225 .ptr_stack_offset => |off| .{ .stack_offset = off },
220226 .register => |reg| .{ .indirect = .{ .reg = reg } },
221227 .register_offset => |reg_off| .{ .indirect = reg_off },
228 .addr_symbol => |sym_off| .{ .load_symbol = sym_off },
222229 };
223230 }
224231
......@@ -235,6 +242,7 @@ const MCValue = union(enum) {
235242 .indirect,
236243 .stack_offset,
237244 .load_symbol,
245 .addr_symbol,
238246 => switch (off) {
239247 0 => mcv,
240248 else => unreachable, // not offsettable
......@@ -801,6 +809,43 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
801809 try table.ensureUnusedCapacity(self.gpa, additional_count);
802810}
803811
812fn splitType(self: *Self, ty: Type) ![2]Type {
813 const mod = self.bin_file.comp.module.?;
814 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod), .none);
815 var parts: [2]Type = undefined;
816 if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {
817 part.* = switch (class) {
818 .integer => switch (part_i) {
819 0 => Type.u64,
820 1 => part: {
821 const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?;
822 const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8));
823 break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) {
824 1 => elem_ty,
825 else => |len| try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() }),
826 };
827 },
828 else => unreachable,
829 },
830 else => break,
831 };
832 } else if (parts[0].abiSize(mod) + parts[1].abiSize(mod) == ty.abiSize(mod)) return parts;
833 return std.debug.panic("TODO implement splitType for {}", .{ty.fmt(mod)});
834}
835
836fn symbolIndex(self: *Self) !u32 {
837 const mod = self.bin_file.comp.module.?;
838 const decl_index = mod.funcOwnerDeclIndex(self.func_index);
839 return switch (self.bin_file.tag) {
840 .elf => blk: {
841 const elf_file = self.bin_file.cast(link.File.Elf).?;
842 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
843 break :blk atom_index;
844 },
845 else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}),
846 };
847}
848
804849fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: Alignment) !u32 {
805850 self.stack_align = self.stack_align.max(abi_align);
806851 // TODO find a free slot instead of always appending
......@@ -1610,40 +1655,41 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
16101655
16111656fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
16121657 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1613 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1614 const mcv = try self.resolveInst(ty_op.operand);
1615 break :result try self.slicePtr(mcv);
1658 const result = result: {
1659 const src_mcv = try self.resolveInst(ty_op.operand);
1660 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1661
1662 const dst_mcv = try self.allocRegOrMem(inst, true);
1663 const dst_ty = self.typeOfIndex(inst);
1664 try self.genCopy(dst_ty, dst_mcv, src_mcv);
1665 break :result dst_mcv;
16161666 };
16171667 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
16181668}
16191669
1620fn slicePtr(self: *Self, mcv: MCValue) !MCValue {
1621 switch (mcv) {
1622 .dead, .unreach, .none => unreachable,
1623 .register => unreachable, // a slice doesn't fit in one register
1624 .stack_offset => |off| {
1625 return MCValue{ .stack_offset = off };
1626 },
1627 .memory => |addr| {
1628 return MCValue{ .memory = addr };
1629 },
1630 else => return self.fail("TODO slicePtr {s}", .{@tagName(mcv)}),
1631 }
1632}
1633
16341670fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
16351671 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
16361672 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1637 const ptr_bits = 64;
1638 const ptr_bytes = @divExact(ptr_bits, 8);
1639 const mcv = try self.resolveInst(ty_op.operand);
1640 switch (mcv) {
1641 .dead, .unreach, .none => unreachable,
1642 .register => unreachable, // a slice doesn't fit in one register
1673 const src_mcv = try self.resolveInst(ty_op.operand);
1674 switch (src_mcv) {
16431675 .stack_offset => |off| {
1644 break :result MCValue{ .stack_offset = off + ptr_bytes };
1676 const len_mcv: MCValue = .{ .stack_offset = off + 8 };
1677 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
1678
1679 const dst_mcv = try self.allocRegOrMem(inst, true);
1680 try self.genCopy(Type.usize, dst_mcv, len_mcv);
1681 break :result dst_mcv;
1682 },
1683 .register_pair => |pair| {
1684 const len_mcv: MCValue = .{ .register = pair[1] };
1685
1686 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
1687
1688 const dst_mcv = try self.allocRegOrMem(inst, true);
1689 try self.genCopy(Type.usize, dst_mcv, len_mcv);
1690 break :result dst_mcv;
16451691 },
1646 else => return self.fail("TODO airSliceLen for {}", .{mcv}),
1692 else => return self.fail("TODO airSliceLen for {}", .{src_mcv}),
16471693 }
16481694 };
16491695 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -1978,6 +2024,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro
19782024 .register,
19792025 .register_offset,
19802026 .ptr_stack_offset,
2027 .addr_symbol,
19812028 => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),
19822029
19832030 .memory,
......@@ -2019,11 +2066,6 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty:
20192066
20202067 log.debug("storing {}:{} in {}:{}", .{ value, value_ty.fmt(mod), pointer, ptr_ty.fmt(mod) });
20212068
2022 if (value_ty.isSlice(mod)) {
2023 // cheat a bit by loading in two parts
2024
2025 }
2026
20272069 switch (pointer) {
20282070 .none => unreachable,
20292071 .undef => unreachable,
......@@ -2192,7 +2234,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
21922234
21932235 const dst_mcv = switch (src_mcv) {
21942236 .register => |src_reg| dst: {
2195 try self.register_manager.getReg(src_reg, null);
2237 self.register_manager.getRegAssumeFree(src_reg, null);
2238 break :dst src_mcv;
2239 },
2240 .register_pair => |pair| dst: {
2241 for (pair) |reg| self.register_manager.getRegAssumeFree(reg, null);
21962242 break :dst src_mcv;
21972243 },
21982244 else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}),
......@@ -3056,6 +3102,8 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT
30563102
30573103/// Sets the value without any modifications to register allocation metadata or stack allocation metadata.
30583104fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
3105 const mod = self.bin_file.comp.module.?;
3106
30593107 // There isn't anything to store
30603108 if (dst_mcv == .none) return;
30613109
......@@ -3066,7 +3114,6 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
30663114
30673115 switch (dst_mcv) {
30683116 .register => |reg| return self.genSetReg(ty, reg, src_mcv),
3069 .register_pair => |pair| return self.genSetRegPair(ty, pair, src_mcv),
30703117 .register_offset => |dst_reg_off| try self.genSetReg(ty, dst_reg_off.reg, switch (src_mcv) {
30713118 .none,
30723119 .unreach,
......@@ -3084,7 +3131,47 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
30843131 }),
30853132 .stack_offset => |off| return self.genSetStack(ty, off, src_mcv),
30863133 .memory => |addr| return self.genSetMem(ty, addr, src_mcv),
3087 else => return self.fail("TODO: genCopy {s} with {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
3134 .register_pair => |dst_regs| {
3135 const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) {
3136 .register_pair, .memory, .indirect, .stack_offset => null,
3137 .load_symbol => src: {
3138 const src_addr_reg, const src_addr_lock = try self.allocReg();
3139 errdefer self.register_manager.unlockReg(src_addr_lock);
3140
3141 try self.genSetReg(Type.usize, src_addr_reg, src_mcv.address());
3142 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
3143 },
3144 .air_ref => |src_ref| return self.genCopy(
3145 ty,
3146 dst_mcv,
3147 try self.resolveInst(src_ref),
3148 ),
3149 else => return self.fail("TODO implement genCopy for {s} of {}", .{
3150 @tagName(src_mcv), ty.fmt(mod),
3151 }),
3152 };
3153 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
3154
3155 switch (ty.zigTypeTag(mod)) {
3156 .Optional => return,
3157 else => {},
3158 }
3159
3160 var part_disp: i32 = 0;
3161 for (dst_regs, try self.splitType(ty), 0..) |dst_reg, dst_ty, part_i| {
3162 try self.genSetReg(dst_ty, dst_reg, switch (src_mcv) {
3163 .register_pair => |src_regs| .{ .register = src_regs[part_i] },
3164 .memory, .indirect, .stack_offset => src_mcv.address().offset(part_disp).deref(),
3165 .load_symbol => .{ .indirect = .{
3166 .reg = src_info.?.addr_reg,
3167 .off = part_disp,
3168 } },
3169 else => unreachable,
3170 });
3171 part_disp += @intCast(dst_ty.abiSize(mod));
3172 }
3173 },
3174 else => return std.debug.panic("TODO: genCopy {s} with {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
30883175 }
30893176}
30903177
......@@ -3168,14 +3255,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_mcv: MCValue) Inner
31683255 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset });
31693256 },
31703257 .load_symbol => |sym_off| {
3171 const atom_index = atom: {
3172 const decl_index = mod.funcOwnerDeclIndex(self.func_index);
3173
3174 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3175 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
3176 break :atom atom_index;
3177 } else return self.fail("TODO genSetStack for {s}", .{@tagName(self.bin_file.tag)});
3178 };
3258 const atom_index = try self.symbolIndex();
31793259
31803260 // setup the src pointer
31813261 _ = try self.addInst(.{
......@@ -3443,16 +3523,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
34433523 .load_symbol => |sym_off| {
34443524 assert(sym_off.off == 0);
34453525
3446 const decl_index = mod.funcOwnerDeclIndex(self.func_index);
3526 const atom_index = try self.symbolIndex();
34473527
3448 const atom_index = switch (self.bin_file.tag) {
3449 .elf => blk: {
3450 const elf_file = self.bin_file.cast(link.File.Elf).?;
3451 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
3452 break :blk atom_index;
3453 },
3454 else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}),
3455 };
34563528 _ = try self.addInst(.{
34573529 .tag = .load_symbol,
34583530 .data = .{
......@@ -3485,27 +3557,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
34853557 },
34863558 });
34873559 },
3488 else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),
3489 }
3490}
3491
3492fn genSetRegPair(self: *Self, ty: Type, pair: [2]Register, src_mcv: MCValue) InnerError!void {
3493 const mod = self.bin_file.comp.module.?;
3494 const abi_size: u32 = @intCast(ty.abiSize(mod));
3495
3496 assert(abi_size > 8 and abi_size <= 16); // must fit only fit into two registers
3560 .addr_symbol => |sym_off| {
3561 assert(sym_off.off == 0);
34973562
3498 switch (src_mcv) {
3499 .air_ref => |ref| return self.genSetRegPair(ty, pair, try self.resolveInst(ref)),
3500 .load_symbol => |sym_off| {
3501 _ = sym_off;
3502 // return self.fail("TODO: genSetRegPair load_symbol", .{});
3503 // commented out just for testing.
3563 const atom_index = try self.symbolIndex();
35043564
3505 // plan here is to load the address into a temporary register and
3506 // copy into the pair.
3565 _ = try self.addInst(.{
3566 .tag = .load_symbol,
3567 .data = .{
3568 .payload = try self.addExtra(Mir.LoadSymbolPayload{
3569 .register = reg.id(),
3570 .atom_index = atom_index,
3571 .sym_index = sym_off.sym,
3572 }),
3573 },
3574 });
35073575 },
3508 else => return self.fail("TODO: genSetRegPair {s}", .{@tagName(src_mcv)}),
3576 else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),
35093577 }
35103578}
35113579
src/arch/riscv64/Emit.zig+22-8
......@@ -398,7 +398,7 @@ fn mirPsuedo(emit: *Emit, inst: Mir.Inst.Index) !void {
398398
399399 .j => {
400400 const offset = @as(i64, @intCast(emit.code_offset_mapping.get(data.inst).?)) - @as(i64, @intCast(emit.code.items.len));
401 try emit.writeInstruction(Instruction.jal(.s0, @intCast(offset)));
401 try emit.writeInstruction(Instruction.jal(.zero, @intCast(offset)));
402402 },
403403
404404 else => unreachable,
......@@ -443,27 +443,40 @@ fn mirLoadSymbol(emit: *Emit, inst: Mir.Inst.Index) !void {
443443 const data = emit.mir.extraData(Mir.LoadSymbolPayload, payload).data;
444444 const reg = @as(Register, @enumFromInt(data.register));
445445
446 const end_offset = @as(u32, @intCast(emit.code.items.len));
446 const start_offset = @as(u32, @intCast(emit.code.items.len));
447447 try emit.writeInstruction(Instruction.lui(reg, 0));
448 try emit.writeInstruction(Instruction.lw(reg, 0, reg));
449448
450449 switch (emit.bin_file.tag) {
451450 .elf => {
452451 const elf_file = emit.bin_file.cast(link.File.Elf).?;
453452 const atom_ptr = elf_file.symbol(data.atom_index).atom(elf_file).?;
453 const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index);
454 const sym = elf_file.symbol(sym_index);
454455
455 const hi_r_type = @intFromEnum(std.elf.R_RISCV.HI20);
456 var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
457 var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
458
459 if (sym.flags.needs_zig_got) {
460 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
461
462 hi_r_type = Elf.R_ZIG_GOT_HI20;
463 lo_r_type = Elf.R_ZIG_GOT_LO12;
464
465 // we need to deref once if we are getting from zig_got, as itll
466 // reloc an address of the address in the got.
467 try emit.writeInstruction(Instruction.ld(reg, 0, reg));
468 } else {
469 try emit.writeInstruction(Instruction.addi(reg, reg, 0));
470 }
456471
457472 try atom_ptr.addReloc(elf_file, .{
458 .r_offset = end_offset,
473 .r_offset = start_offset,
459474 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | hi_r_type,
460475 .r_addend = 0,
461476 });
462477
463 const lo_r_type = @intFromEnum(std.elf.R_RISCV.LO12_I);
464
465478 try atom_ptr.addReloc(elf_file, .{
466 .r_offset = end_offset + 4,
479 .r_offset = start_offset + 4,
467480 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | lo_r_type,
468481 .r_addend = 0,
469482 });
......@@ -587,6 +600,7 @@ const bits = @import("bits.zig");
587600const abi = @import("abi.zig");
588601const link = @import("../../link.zig");
589602const Module = @import("../../Module.zig");
603const Elf = @import("../../link/Elf.zig");
590604const ErrorMsg = Module.ErrorMsg;
591605const assert = std.debug.assert;
592606const Instruction = bits.Instruction;
src/arch/riscv64/Mir.zig+3-1
......@@ -118,7 +118,9 @@ pub const Inst = struct {
118118 /// function epilogue
119119 psuedo_epilogue,
120120
121 // TODO: add description
121 /// Loads the address of a value that hasn't yet been allocated in memory.
122 ///
123 /// uses the Mir.LoadSymbolPayload payload.
122124 load_symbol,
123125
124126 // TODO: add description
src/arch/riscv64/abi.zig+32-1
......@@ -5,7 +5,7 @@ const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
55const Type = @import("../../type.zig").Type;
66const Module = @import("../../Module.zig");
77
8pub const Class = enum { memory, byval, integer, double_integer, fields };
8pub const Class = enum { memory, byval, integer, double_integer, fields, none };
99
1010pub fn classifyType(ty: Type, mod: *Module) Class {
1111 const target = mod.getTarget();
......@@ -91,6 +91,37 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
9191 }
9292}
9393
94/// There are a maximum of 8 possible return slots. Returned values are in
95/// the beginning of the array; unused slots are filled with .none.
96pub fn classifySystemV(ty: Type, mod: *Module) [8]Class {
97 const memory_class = [_]Class{
98 .memory, .none, .none, .none,
99 .none, .none, .none, .none,
100 };
101 var result = [1]Class{.none} ** 8;
102 switch (ty.zigTypeTag(mod)) {
103 .Pointer => switch (ty.ptrSize(mod)) {
104 .Slice => {
105 result[0] = .integer;
106 result[1] = .integer;
107 return result;
108 },
109 else => {
110 result[0] = .integer;
111 return result;
112 },
113 },
114 .Optional => {
115 if (ty.isPtrLikeOptional(mod)) {
116 result[0] = .integer;
117 return result;
118 }
119 return memory_class;
120 },
121 else => return result,
122 }
123}
124
94125pub const callee_preserved_regs = [_]Register{
95126 .s0, .s1, .s2, .s3, .s4, .s5, .s6, .s7, .s8, .s9, .s10, .s11,
96127};
src/codegen/llvm.zig+2
......@@ -11132,6 +11132,7 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
1113211132 }
1113311133 return o.builder.structType(.normal, types[0..types_len]);
1113411134 },
11135 .none => unreachable,
1113511136 }
1113611137 },
1113711138 // TODO investigate C ABI for other architectures
......@@ -11389,6 +11390,7 @@ const ParamTypeIterator = struct {
1138911390 it.llvm_index += it.types_len - 1;
1139011391 return .multiple_llvm_types;
1139111392 },
11393 .none => unreachable,
1139211394 }
1139311395 },
1139411396 // TODO investigate C ABI for other architectures
src/link/Elf.zig+2
......@@ -6409,6 +6409,8 @@ const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
64096409// TODO: add comptime check we don't clobber any reloc for any ISA
64106410pub const R_ZIG_GOT32: u32 = 0xff00;
64116411pub const R_ZIG_GOTPCREL: u32 = 0xff01;
6412pub const R_ZIG_GOT_HI20: u32 = 0xff02;
6413pub const R_ZIG_GOT_LO12: u32 = 0xff03;
64126414
64136415fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
64146416 return switch (cpu_arch) {
src/link/Elf/Atom.zig+25-3
......@@ -2025,7 +2025,15 @@ const riscv = struct {
20252025 .SUB32,
20262026 => {},
20272027
2028 else => try atom.reportUnhandledRelocError(rel, elf_file),
2028 else => |x| switch (@intFromEnum(x)) {
2029 Elf.R_ZIG_GOT_HI20,
2030 Elf.R_ZIG_GOT_LO12,
2031 => {
2032 assert(symbol.flags.has_zig_got);
2033 },
2034
2035 else => try atom.reportUnhandledRelocError(rel, elf_file),
2036 },
20292037 }
20302038 }
20312039
......@@ -2046,7 +2054,6 @@ const riscv = struct {
20462054 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
20472055 _ = TP;
20482056 _ = DTP;
2049 _ = ZIG_GOT;
20502057
20512058 switch (r_type) {
20522059 .NONE => unreachable,
......@@ -2136,7 +2143,22 @@ const riscv = struct {
21362143 }
21372144 },
21382145
2139 else => try atom.reportUnhandledRelocError(rel, elf_file),
2146 else => |x| switch (@intFromEnum(x)) {
2147 // Zig custom relocations
2148 Elf.R_ZIG_GOT_HI20 => {
2149 assert(target.flags.has_zig_got);
2150 const disp: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow);
2151 riscv_util.writeInstU(code[r_offset..][0..4], disp);
2152 },
2153
2154 Elf.R_ZIG_GOT_LO12 => {
2155 assert(target.flags.has_zig_got);
2156 const value: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow);
2157 riscv_util.writeInstI(code[r_offset..][0..4], value);
2158 },
2159
2160 else => try atom.reportUnhandledRelocError(rel, elf_file),
2161 },
21402162 }
21412163 }
21422164