authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-16 21:19:44+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-16 21:19:44+02:00
log90989be0e31a91335f8d1c1eafb84c3b34792a8c
tree7b3e4b1769b02db219442bd9c83d4df185848d3d
parentf1eed99f3d2d355054c6cf36d6f332d83b2ec595
parent73f385eec57d4fc28069b60f059fa8553d3a0c1b
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21065 from ziglang/elf-zig-got

elf: replace .got.zig with a zig jump table

27 files changed, 488 insertions(+), 787 deletions(-)

src/Builtin.zig+1-1
......@@ -218,7 +218,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
218218
219219 if (opts.is_test) {
220220 try buffer.appendSlice(
221 \\pub var test_functions: []const std.builtin.TestFn = undefined; // overwritten later
221 \\pub var test_functions: []const std.builtin.TestFn = &.{}; // overwritten later
222222 \\
223223 );
224224 }
src/Compilation.zig+7
......@@ -3092,6 +3092,10 @@ pub fn totalErrorCount(comp: *Compilation) u32 {
30923092 if (zcu.intern_pool.global_error_set.getNamesFromMainThread().len > zcu.error_limit) {
30933093 total += 1;
30943094 }
3095
3096 for (zcu.failed_codegen.keys()) |_| {
3097 total += 1;
3098 }
30953099 }
30963100
30973101 // The "no entry point found" error only counts if there are no semantic analysis errors.
......@@ -3237,6 +3241,9 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
32373241 }
32383242 }
32393243 }
3244 for (zcu.failed_codegen.values()) |error_msg| {
3245 try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
3246 }
32403247 for (zcu.failed_exports.values()) |value| {
32413248 try addModuleErrorMsg(zcu, &bundle, value.*, &all_references);
32423249 }
src/arch/aarch64/CodeGen.zig+7-34
......@@ -4352,24 +4352,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43524352 // on linking.
43534353 if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) {
43544354 .func => |func| {
4355 if (self.bin_file.cast(.elf)) |elf_file| {
4356 const zo = elf_file.zigObjectPtr().?;
4357 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
4358 const sym = zo.symbol(sym_index);
4359 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
4360 const got_addr = @as(u32, @intCast(sym.zigGotAddress(elf_file)));
4361 try self.genSetReg(Type.usize, .x30, .{ .memory = got_addr });
4362 } else if (self.bin_file.cast(.macho)) |macho_file| {
4363 _ = macho_file;
4364 @panic("TODO airCall");
4365 // const atom = try macho_file.getOrCreateAtomForNav(func.owner_nav);
4366 // const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
4367 // try self.genSetReg(Type.u64, .x30, .{
4368 // .linker_load = .{
4369 // .type = .got,
4370 // .sym_index = sym_index,
4371 // },
4372 // });
4355 if (self.bin_file.cast(.elf)) |_| {
4356 return self.fail("TODO implement calling functions for Elf", .{});
4357 } else if (self.bin_file.cast(.macho)) |_| {
4358 return self.fail("TODO implement calling functions for MachO", .{});
43734359 } else if (self.bin_file.cast(.coff)) |coff_file| {
43744360 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
43754361 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
......@@ -4393,21 +4379,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43934379 .@"extern" => |@"extern"| {
43944380 const nav_name = ip.getNav(@"extern".owner_nav).name.toSlice(ip);
43954381 const lib_name = @"extern".lib_name.toSlice(ip);
4396 if (self.bin_file.cast(.macho)) |macho_file| {
4397 _ = macho_file;
4398 @panic("TODO airCall");
4399 // const sym_index = try macho_file.getGlobalSymbol(nav_name, lib_name);
4400 // const atom = try macho_file.getOrCreateAtomForNav(self.owner_nav);
4401 // const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
4402 // _ = try self.addInst(.{
4403 // .tag = .call_extern,
4404 // .data = .{
4405 // .relocation = .{
4406 // .atom_index = atom_index,
4407 // .sym_index = sym_index,
4408 // },
4409 // },
4410 // });
4382 if (self.bin_file.cast(.macho)) |_| {
4383 return self.fail("TODO implement calling extern functions for MachO", .{});
44114384 } else if (self.bin_file.cast(.coff)) |coff_file| {
44124385 const sym_index = try coff_file.getGlobalSymbol(nav_name, lib_name);
44134386 try self.genSetReg(Type.u64, .x30, .{
......@@ -6234,7 +6207,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
62346207 .memory => |addr| .{ .memory = addr },
62356208 .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },
62366209 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
6237 .load_symbol, .load_tlv => unreachable, // TODO
6210 .load_symbol, .load_tlv, .lea_symbol => unreachable, // TODO
62386211 },
62396212 .fail => |msg| {
62406213 self.err_msg = msg;
src/arch/arm/CodeGen.zig+3-17
......@@ -4333,22 +4333,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43334333 // Due to incremental compilation, how function calls are generated depends
43344334 // on linking.
43354335 if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) {
4336 .func => |func| {
4337 if (self.bin_file.cast(.elf)) |elf_file| {
4338 const zo = elf_file.zigObjectPtr().?;
4339 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
4340 const sym = zo.symbol(sym_index);
4341 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
4342 const got_addr: u32 = @intCast(sym.zigGotAddress(elf_file));
4343 try self.genSetReg(Type.usize, .lr, .{ .memory = got_addr });
4344 } else if (self.bin_file.cast(.macho)) |_| {
4345 unreachable; // unsupported architecture for MachO
4346 } else {
4347 return self.fail("TODO implement call on {s} for {s}", .{
4348 @tagName(self.bin_file.tag),
4349 @tagName(self.target.cpu.arch),
4350 });
4351 }
4336 .func => {
4337 return self.fail("TODO implement calling functions", .{});
43524338 },
43534339 .@"extern" => {
43544340 return self.fail("TODO implement calling extern functions", .{});
......@@ -6184,7 +6170,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
61846170 .mcv => |mcv| switch (mcv) {
61856171 .none => .none,
61866172 .undef => .undef,
6187 .load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
6173 .load_got, .load_symbol, .load_direct, .load_tlv, .lea_symbol => unreachable, // TODO
61886174 .immediate => |imm| .{ .immediate = @truncate(imm) },
61896175 .memory => |addr| .{ .memory = addr },
61906176 },
src/arch/riscv64/CodeGen.zig+6-5
......@@ -4937,7 +4937,7 @@ fn genCall(
49374937 if (func.mod.pic) {
49384938 return func.fail("TODO: genCall pic", .{});
49394939 } else {
4940 try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym_index } });
4940 try func.genSetReg(Type.u64, .ra, .{ .lea_symbol = .{ .sym = sym_index } });
49414941 _ = try func.addInst(.{
49424942 .tag = .jalr,
49434943 .data = .{ .i_type = .{
......@@ -6120,7 +6120,7 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
61206120 arg_map.get(op_str["%[".len .. mod_index orelse op_str.len - "]".len]) orelse
61216121 return func.fail("no matching constraint: '{s}'", .{op_str})
61226122 ]) {
6123 .load_symbol => |sym_off| if (mem.eql(u8, modifier, "plt")) blk: {
6123 .lea_symbol => |sym_off| if (mem.eql(u8, modifier, "plt")) blk: {
61246124 assert(sym_off.off == 0);
61256125 break :blk .{ .sym = sym_off };
61266126 } else return func.fail("invalid modifier: '{s}'", .{modifier}),
......@@ -6388,7 +6388,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
63886388 ty,
63896389 src_mcv,
63906390 ),
6391 .load_tlv => {
6391 .load_symbol, .load_tlv => {
63926392 const addr_reg, const addr_lock = try func.allocReg(.int);
63936393 defer func.register_manager.unlockReg(addr_lock);
63946394
......@@ -6433,7 +6433,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
64336433 part_disp += @intCast(dst_ty.abiSize(func.pt));
64346434 }
64356435 },
6436 else => return func.fail("TODO: genCopy to {s} from {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
6436 else => return std.debug.panic("TODO: genCopy to {s} from {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
64376437 }
64386438}
64396439
......@@ -6594,7 +6594,7 @@ fn genInlineMemset(
65946594 .tag = .beq,
65956595 .data = .{
65966596 .b_type = .{
6597 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst
6597 .inst = @intCast(func.mir_instructions.len + 3), // points after the last inst
65986598 .rs1 = count,
65996599 .rs2 = .zero,
66006600 },
......@@ -8026,6 +8026,7 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
80268026 .mcv => |mcv| switch (mcv) {
80278027 .none => .none,
80288028 .undef => unreachable,
8029 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
80298030 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
80308031 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
80318032 .immediate => |imm| .{ .immediate = imm },
src/arch/riscv64/Emit.zig+5-17
......@@ -43,31 +43,19 @@ pub fn emitMir(emit: *Emit) Error!void {
4343 .fmt = std.meta.activeTag(lowered_inst),
4444 }),
4545 .load_symbol_reloc => |symbol| {
46 const is_obj_or_static_lib = switch (emit.lower.output_mode) {
47 .Exe => false,
48 .Obj => true,
49 .Lib => emit.lower.link_mode == .static,
50 };
51
5246 const elf_file = emit.bin_file.cast(.elf).?;
5347 const zo = elf_file.zigObjectPtr().?;
5448
5549 const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
5650 const sym = zo.symbol(symbol.sym_index);
5751
58 var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
59 var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
60
61 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
62 _ = try sym.getOrCreateZigGotEntry(symbol.sym_index, elf_file);
63
64 hi_r_type = Elf.R_ZIG_GOT_HI20;
65 lo_r_type = Elf.R_ZIG_GOT_LO12;
66 } else if (sym.flags.needs_got) {
67 hi_r_type = Elf.R_GOT_HI20_STATIC; // TODO: rework this #20887
68 lo_r_type = Elf.R_GOT_LO12_I_STATIC; // TODO: rework this #20887
52 if (sym.flags.is_extern_ptr and emit.lower.pic) {
53 return emit.fail("emit GOT relocation for symbol '{s}'", .{sym.name(elf_file)});
6954 }
7055
56 const hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
57 const lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
58
7159 try atom_ptr.addReloc(elf_file, .{
7260 .r_offset = start_offset,
7361 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type,
src/arch/sparc64/CodeGen.zig+3-29
......@@ -1349,34 +1349,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13491349 // Due to incremental compilation, how function calls are generated depends
13501350 // on linking.
13511351 if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) {
1352 .func => |func| {
1353 const got_addr = if (self.bin_file.cast(.elf)) |elf_file| blk: {
1354 const zo = elf_file.zigObjectPtr().?;
1355 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
1356 const sym = zo.symbol(sym_index);
1357 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
1358 break :blk @as(u32, @intCast(sym.zigGotAddress(elf_file)));
1359 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
1360
1361 try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
1362
1363 _ = try self.addInst(.{
1364 .tag = .jmpl,
1365 .data = .{
1366 .arithmetic_3op = .{
1367 .is_imm = false,
1368 .rd = .o7,
1369 .rs1 = .o7,
1370 .rs2_or_imm = .{ .rs2 = .g0 },
1371 },
1372 },
1373 });
1374
1375 // TODO Find a way to fill this delay slot
1376 _ = try self.addInst(.{
1377 .tag = .nop,
1378 .data = .{ .nop = {} },
1379 });
1352 .func => {
1353 return self.fail("TODO implement calling functions", .{});
13801354 },
13811355 .@"extern" => {
13821356 return self.fail("TODO implement calling extern functions", .{});
......@@ -4153,7 +4127,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
41534127 .mcv => |mcv| switch (mcv) {
41544128 .none => .none,
41554129 .undef => .undef,
4156 .load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
4130 .load_got, .load_symbol, .load_direct, .load_tlv, .lea_symbol => unreachable, // TODO
41574131 .immediate => |imm| .{ .immediate = imm },
41584132 .memory => |addr| .{ .memory = addr },
41594133 },
src/arch/x86_64/CodeGen.zig+52-53
......@@ -1379,14 +1379,22 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
13791379 .ops = switch (imm) {
13801380 .signed => .i_s,
13811381 .unsigned => .i_u,
1382 .reloc => .rel,
13821383 },
1383 .data = .{ .i = .{
1384 .fixes = tag[0],
1385 .i = switch (imm) {
1386 .signed => |s| @bitCast(s),
1387 .unsigned => |u| @intCast(u),
1384 .data = switch (imm) {
1385 .reloc => |x| reloc: {
1386 assert(tag[0] == ._);
1387 break :reloc .{ .reloc = x };
13881388 },
1389 } },
1389 .signed, .unsigned => .{ .i = .{
1390 .fixes = tag[0],
1391 .i = switch (imm) {
1392 .signed => |s| @bitCast(s),
1393 .unsigned => |u| @intCast(u),
1394 .reloc => unreachable,
1395 },
1396 } },
1397 },
13901398 });
13911399}
13921400
......@@ -1406,6 +1414,7 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm:
14061414 const ops: Mir.Inst.Ops = switch (imm) {
14071415 .signed => .ri_s,
14081416 .unsigned => |u| if (math.cast(u32, u)) |_| .ri_u else .ri64,
1417 .reloc => unreachable,
14091418 };
14101419 _ = try self.addInst(.{
14111420 .tag = tag[1],
......@@ -1417,6 +1426,7 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm:
14171426 .i = switch (imm) {
14181427 .signed => |s| @bitCast(s),
14191428 .unsigned => |u| @intCast(u),
1429 .reloc => unreachable,
14201430 },
14211431 } },
14221432 .ri64 => .{ .rx = .{
......@@ -1488,6 +1498,7 @@ fn asmRegisterRegisterRegisterImmediate(
14881498 .i = switch (imm) {
14891499 .signed => |s| @bitCast(@as(i8, @intCast(s))),
14901500 .unsigned => |u| @intCast(u),
1501 .reloc => unreachable,
14911502 },
14921503 } },
14931504 });
......@@ -1505,6 +1516,7 @@ fn asmRegisterRegisterImmediate(
15051516 .ops = switch (imm) {
15061517 .signed => .rri_s,
15071518 .unsigned => .rri_u,
1519 .reloc => unreachable,
15081520 },
15091521 .data = .{ .rri = .{
15101522 .fixes = tag[0],
......@@ -1513,6 +1525,7 @@ fn asmRegisterRegisterImmediate(
15131525 .i = switch (imm) {
15141526 .signed => |s| @bitCast(s),
15151527 .unsigned => |u| @intCast(u),
1528 .reloc => unreachable,
15161529 },
15171530 } },
15181531 });
......@@ -1610,6 +1623,7 @@ fn asmRegisterMemoryImmediate(
16101623 if (switch (imm) {
16111624 .signed => |s| if (math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
16121625 .unsigned => |u| math.cast(u16, u),
1626 .reloc => unreachable,
16131627 }) |small_imm| {
16141628 _ = try self.addInst(.{
16151629 .tag = tag[1],
......@@ -1625,6 +1639,7 @@ fn asmRegisterMemoryImmediate(
16251639 const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
16261640 .signed => |s| @bitCast(s),
16271641 .unsigned => unreachable,
1642 .reloc => unreachable,
16281643 } });
16291644 assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
16301645 _ = try self.addInst(.{
......@@ -1632,6 +1647,7 @@ fn asmRegisterMemoryImmediate(
16321647 .ops = switch (imm) {
16331648 .signed => .rmi_s,
16341649 .unsigned => .rmi_u,
1650 .reloc => unreachable,
16351651 },
16361652 .data = .{ .rx = .{
16371653 .fixes = tag[0],
......@@ -1679,6 +1695,7 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immed
16791695 const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
16801696 .signed => |s| @bitCast(s),
16811697 .unsigned => |u| @intCast(u),
1698 .reloc => unreachable,
16821699 } });
16831700 assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
16841701 _ = try self.addInst(.{
......@@ -1686,6 +1703,7 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immed
16861703 .ops = switch (imm) {
16871704 .signed => .mi_s,
16881705 .unsigned => .mi_u,
1706 .reloc => unreachable,
16891707 },
16901708 .data = .{ .x = .{
16911709 .fixes = tag[0],
......@@ -12310,33 +12328,10 @@ fn genCall(self: *Self, info: union(enum) {
1231012328 if (self.bin_file.cast(.elf)) |elf_file| {
1231112329 const zo = elf_file.zigObjectPtr().?;
1231212330 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
12313 if (self.mod.pic) {
12314 const callee_reg: Register = switch (resolved_cc) {
12315 .SysV => callee: {
12316 if (!fn_info.is_var_args) break :callee .rax;
12317 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);
12318 break :callee if (call_info.gp_count < param_regs.len)
12319 param_regs[call_info.gp_count]
12320 else
12321 .r10;
12322 },
12323 .Win64 => .rax,
12324 else => unreachable,
12325 };
12326 try self.genSetReg(
12327 callee_reg,
12328 Type.usize,
12329 .{ .load_symbol = .{ .sym = sym_index } },
12330 .{},
12331 );
12332 try self.asmRegister(.{ ._, .call }, callee_reg);
12333 } else try self.asmMemory(.{ ._, .call }, .{
12334 .base = .{ .reloc = .{
12335 .atom_index = try self.owner.getSymbolIndex(self),
12336 .sym_index = sym_index,
12337 } },
12338 .mod = .{ .rm = .{ .size = .qword } },
12339 });
12331 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12332 .atom_index = try self.owner.getSymbolIndex(self),
12333 .sym_index = sym_index,
12334 }));
1234012335 } else if (self.bin_file.cast(.coff)) |coff_file| {
1234112336 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
1234212337 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
......@@ -12365,7 +12360,16 @@ fn genCall(self: *Self, info: union(enum) {
1236512360 });
1236612361 } else unreachable;
1236712362 },
12368 .@"extern" => |@"extern"| try self.genExternSymbolRef(
12363 .@"extern" => |@"extern"| if (self.bin_file.cast(.elf)) |elf_file| {
12364 const target_sym_index = try elf_file.getGlobalSymbol(
12365 @"extern".name.toSlice(ip),
12366 @"extern".lib_name.toSlice(ip),
12367 );
12368 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12369 .atom_index = try self.owner.getSymbolIndex(self),
12370 .sym_index = target_sym_index,
12371 }));
12372 } else try self.genExternSymbolRef(
1236912373 .call,
1237012374 @"extern".lib_name.toSlice(ip),
1237112375 @"extern".name.toSlice(ip),
......@@ -12377,7 +12381,13 @@ fn genCall(self: *Self, info: union(enum) {
1237712381 try self.genSetReg(.rax, Type.usize, .{ .air_ref = callee }, .{});
1237812382 try self.asmRegister(.{ ._, .call }, .rax);
1237912383 },
12380 .lib => |lib| try self.genExternSymbolRef(.call, lib.lib, lib.callee),
12384 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
12385 const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
12386 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12387 .atom_index = try self.owner.getSymbolIndex(self),
12388 .sym_index = target_sym_index,
12389 }));
12390 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
1238112391 }
1238212392 return call_info.return_value.short;
1238312393}
......@@ -14096,8 +14106,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1409614106 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) }
1409714107 else
1409814108 return self.fail("invalid modifier: '{s}'", .{modifier}),
14099 .load_symbol => |sym_off| if (mem.eql(u8, modifier, "P"))
14100 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .load_symbol = sym_off }) }
14109 .lea_symbol => |sym_off| if (mem.eql(u8, modifier, "P"))
14110 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_symbol = sym_off }) }
1410114111 else
1410214112 return self.fail("invalid modifier: '{s}'", .{modifier}),
1410314113 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
......@@ -15253,16 +15263,7 @@ fn genExternSymbolRef(
1525315263 callee: []const u8,
1525415264) InnerError!void {
1525515265 const atom_index = try self.owner.getSymbolIndex(self);
15256 if (self.bin_file.cast(.elf)) |elf_file| {
15257 _ = try self.addInst(.{
15258 .tag = tag,
15259 .ops = .extern_fn_reloc,
15260 .data = .{ .reloc = .{
15261 .atom_index = atom_index,
15262 .sym_index = try elf_file.getGlobalSymbol(callee, lib),
15263 } },
15264 });
15265 } else if (self.bin_file.cast(.coff)) |coff_file| {
15266 if (self.bin_file.cast(.coff)) |coff_file| {
1526615267 const global_index = try coff_file.getGlobalSymbol(callee, lib);
1526715268 _ = try self.addInst(.{
1526815269 .tag = .mov,
......@@ -15306,7 +15307,7 @@ fn genLazySymbolRef(
1530615307 if (self.mod.pic) {
1530715308 switch (tag) {
1530815309 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15309 .load_symbol = .{ .sym = sym_index },
15310 .lea_symbol = .{ .sym = sym_index },
1531015311 }, .{}),
1531115312 .mov => try self.genSetReg(reg, Type.usize, .{
1531215313 .load_symbol = .{ .sym = sym_index },
......@@ -15324,14 +15325,11 @@ fn genLazySymbolRef(
1532415325 .sym_index = sym_index,
1532515326 };
1532615327 switch (tag) {
15327 .lea, .mov => try self.asmRegisterMemory(.{ ._, .mov }, reg.to64(), .{
15328 .base = .{ .reloc = reloc },
15329 .mod = .{ .rm = .{ .size = .qword } },
15330 }),
15331 .call => try self.asmMemory(.{ ._, .call }, .{
15328 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
1533215329 .base = .{ .reloc = reloc },
1533315330 .mod = .{ .rm = .{ .size = .qword } },
1533415331 }),
15332 .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(reloc)),
1533515333 else => unreachable,
1533615334 }
1533715335 }
......@@ -18790,6 +18788,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
1879018788 .immediate => |imm| .{ .immediate = imm },
1879118789 .memory => |addr| .{ .memory = addr },
1879218790 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
18791 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
1879318792 .load_direct => |sym_index| .{ .load_direct = sym_index },
1879418793 .load_got => |sym_index| .{ .lea_got = sym_index },
1879518794 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
src/arch/x86_64/Disassembler.zig+1-1
......@@ -8,7 +8,7 @@ const bits = @import("bits.zig");
88const encoder = @import("encoder.zig");
99
1010const Encoding = @import("Encoding.zig");
11const Immediate = bits.Immediate;
11const Immediate = Instruction.Immediate;
1212const Instruction = encoder.Instruction;
1313const LegacyPrefixes = encoder.LegacyPrefixes;
1414const Memory = Instruction.Memory;
src/arch/x86_64/Emit.zig+10-33
......@@ -110,21 +110,11 @@ pub fn emitMir(emit: *Emit) Error!void {
110110 });
111111 },
112112 .linker_reloc => |data| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
113 const is_obj_or_static_lib = switch (emit.lower.output_mode) {
114 .Exe => false,
115 .Obj => true,
116 .Lib => emit.lower.link_mode == .static,
117 };
118113 const zo = elf_file.zigObjectPtr().?;
119114 const atom = zo.symbol(data.atom_index).atom(elf_file).?;
120115 const sym = zo.symbol(data.sym_index);
121 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
122 _ = try sym.getOrCreateZigGotEntry(data.sym_index, elf_file);
123 }
124116 if (emit.lower.pic) {
125 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
126 link.File.Elf.R_ZIG_GOTPCREL
127 else if (sym.flags.needs_got)
117 const r_type: u32 = if (sym.flags.is_extern_ptr)
128118 @intFromEnum(std.elf.R_X86_64.GOTPCREL)
129119 else
130120 @intFromEnum(std.elf.R_X86_64.PC32);
......@@ -134,28 +124,15 @@ pub fn emitMir(emit: *Emit) Error!void {
134124 .r_addend = -4,
135125 });
136126 } else {
137 if (lowered_inst.encoding.mnemonic == .call and sym.flags.needs_zig_got and is_obj_or_static_lib) {
138 const r_type = @intFromEnum(std.elf.R_X86_64.PC32);
139 try atom.addReloc(elf_file, .{
140 .r_offset = end_offset - 4,
141 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
142 .r_addend = -4,
143 });
144 } else {
145 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
146 link.File.Elf.R_ZIG_GOT32
147 else if (sym.flags.needs_got)
148 @intFromEnum(std.elf.R_X86_64.GOT32)
149 else if (sym.flags.is_tls)
150 @intFromEnum(std.elf.R_X86_64.TPOFF32)
151 else
152 @intFromEnum(std.elf.R_X86_64.@"32");
153 try atom.addReloc(elf_file, .{
154 .r_offset = end_offset - 4,
155 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
156 .r_addend = 0,
157 });
158 }
127 const r_type: u32 = if (sym.flags.is_tls)
128 @intFromEnum(std.elf.R_X86_64.TPOFF32)
129 else
130 @intFromEnum(std.elf.R_X86_64.@"32");
131 try atom.addReloc(elf_file, .{
132 .r_offset = end_offset - 4,
133 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
134 .r_addend = 0,
135 });
159136 }
160137 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
161138 const is_obj_or_static_lib = switch (emit.lower.output_mode) {
src/arch/x86_64/Lower.zig+22-15
......@@ -397,33 +397,40 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
397397 }
398398
399399 _ = lower.reloc(.{ .linker_reloc = sym });
400 break :op if (lower.pic) switch (mnemonic) {
400 if (lower.pic) switch (mnemonic) {
401401 .lea => {
402 if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
402403 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
403404 },
404405 .mov => {
405 if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea;
406 if (elf_sym.flags.is_extern_ptr) {
407 const reg = ops[0].reg;
408 lower.result_insts[lower.result_insts_len] =
409 try Instruction.new(.none, .mov, &[_]Operand{
410 .{ .reg = reg.to64() },
411 .{ .mem = Memory.rip(.qword, 0) },
412 });
413 lower.result_insts_len += 1;
414 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ .base = .{
415 .reg = reg.to64(),
416 } }) };
417 }
406418 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
407419 },
408420 else => unreachable,
409421 } else switch (mnemonic) {
410 .call => break :op if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) .{
411 .imm = Immediate.s(0),
412 } else .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
422 .call => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
413423 .base = .{ .reg = .ds },
414424 }) },
415425 .lea => {
416426 emit_mnemonic = .mov;
417427 break :op .{ .imm = Immediate.s(0) };
418428 },
419 .mov => {
420 if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea;
421 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
422 .base = .{ .reg = .ds },
423 }) };
424 },
429 .mov => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
430 .base = .{ .reg = .ds },
431 }) },
425432 else => unreachable,
426 };
433 }
427434 } else if (lower.bin_file.cast(.macho)) |macho_file| {
428435 const zo = macho_file.getZigObject().?;
429436 const macho_sym = zo.symbols.items[sym.sym_index];
......@@ -485,7 +492,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
485492 .rrmi => inst.data.rrix.fixes,
486493 .mi_u, .mi_s => inst.data.x.fixes,
487494 .m => inst.data.x.fixes,
488 .extern_fn_reloc, .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ._,
495 .extern_fn_reloc, .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc, .rel => ._,
489496 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
490497 };
491498 try lower.emit(switch (fixes) {
......@@ -617,7 +624,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
617624 .{ .mem = lower.mem(inst.data.rrix.payload) },
618625 .{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
619626 },
620 .extern_fn_reloc => &.{
627 .extern_fn_reloc, .rel => &.{
621628 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
622629 },
623630 .got_reloc, .direct_reloc, .import_reloc => ops: {
......@@ -660,7 +667,7 @@ const std = @import("std");
660667const Air = @import("../../Air.zig");
661668const Allocator = std.mem.Allocator;
662669const ErrorMsg = Zcu.ErrorMsg;
663const Immediate = bits.Immediate;
670const Immediate = Instruction.Immediate;
664671const Instruction = encoder.Instruction;
665672const Lower = @This();
666673const Memory = Instruction.Memory;
src/arch/x86_64/Mir.zig+1-1
......@@ -769,7 +769,7 @@ pub const Inst = struct {
769769 /// Uses `imm` payload.
770770 i_u,
771771 /// Relative displacement operand.
772 /// Uses `imm` payload.
772 /// Uses `reloc` payload.
773773 rel,
774774 /// Register, memory operands.
775775 /// Uses `rx` payload with extra data of type `Memory`.
src/arch/x86_64/bits.zig+13-32
......@@ -569,6 +569,7 @@ pub const Memory = struct {
569569pub const Immediate = union(enum) {
570570 signed: i32,
571571 unsigned: u64,
572 reloc: Symbol,
572573
573574 pub fn u(x: u64) Immediate {
574575 return .{ .unsigned = x };
......@@ -578,39 +579,19 @@ pub const Immediate = union(enum) {
578579 return .{ .signed = x };
579580 }
580581
581 pub fn asSigned(imm: Immediate, bit_size: u64) i64 {
582 return switch (imm) {
583 .signed => |x| switch (bit_size) {
584 1, 8 => @as(i8, @intCast(x)),
585 16 => @as(i16, @intCast(x)),
586 32, 64 => x,
587 else => unreachable,
588 },
589 .unsigned => |x| switch (bit_size) {
590 1, 8 => @as(i8, @bitCast(@as(u8, @intCast(x)))),
591 16 => @as(i16, @bitCast(@as(u16, @intCast(x)))),
592 32 => @as(i32, @bitCast(@as(u32, @intCast(x)))),
593 64 => @bitCast(x),
594 else => unreachable,
595 },
596 };
582 pub fn rel(symbol: Symbol) Immediate {
583 return .{ .reloc = symbol };
597584 }
598585
599 pub fn asUnsigned(imm: Immediate, bit_size: u64) u64 {
600 return switch (imm) {
601 .signed => |x| switch (bit_size) {
602 1, 8 => @as(u8, @bitCast(@as(i8, @intCast(x)))),
603 16 => @as(u16, @bitCast(@as(i16, @intCast(x)))),
604 32, 64 => @as(u32, @bitCast(x)),
605 else => unreachable,
606 },
607 .unsigned => |x| switch (bit_size) {
608 1, 8 => @as(u8, @intCast(x)),
609 16 => @as(u16, @intCast(x)),
610 32 => @as(u32, @intCast(x)),
611 64 => x,
612 else => unreachable,
613 },
614 };
586 pub fn format(
587 imm: Immediate,
588 comptime fmt: []const u8,
589 options: std.fmt.FormatOptions,
590 writer: anytype,
591 ) @TypeOf(writer).Error!void {
592 switch (imm) {
593 .reloc => |x| try std.fmt.formatType(x, fmt, options, writer, 0),
594 inline else => |x| try writer.print("{d}", .{x}),
595 }
615596 }
616597};
src/arch/x86_64/encoder.zig+91-43
......@@ -7,7 +7,6 @@ const testing = std.testing;
77const bits = @import("bits.zig");
88const Encoding = @import("Encoding.zig");
99const FrameIndex = bits.FrameIndex;
10const Immediate = bits.Immediate;
1110const Register = bits.Register;
1211const Symbol = bits.Symbol;
1312
......@@ -28,6 +27,55 @@ pub const Instruction = struct {
2827 repnz,
2928 };
3029
30 pub const Immediate = union(enum) {
31 signed: i32,
32 unsigned: u64,
33
34 pub fn u(x: u64) Immediate {
35 return .{ .unsigned = x };
36 }
37
38 pub fn s(x: i32) Immediate {
39 return .{ .signed = x };
40 }
41
42 pub fn asSigned(imm: Immediate, bit_size: u64) i64 {
43 return switch (imm) {
44 .signed => |x| switch (bit_size) {
45 1, 8 => @as(i8, @intCast(x)),
46 16 => @as(i16, @intCast(x)),
47 32, 64 => x,
48 else => unreachable,
49 },
50 .unsigned => |x| switch (bit_size) {
51 1, 8 => @as(i8, @bitCast(@as(u8, @intCast(x)))),
52 16 => @as(i16, @bitCast(@as(u16, @intCast(x)))),
53 32 => @as(i32, @bitCast(@as(u32, @intCast(x)))),
54 64 => @bitCast(x),
55 else => unreachable,
56 },
57 };
58 }
59
60 pub fn asUnsigned(imm: Immediate, bit_size: u64) u64 {
61 return switch (imm) {
62 .signed => |x| switch (bit_size) {
63 1, 8 => @as(u8, @bitCast(@as(i8, @intCast(x)))),
64 16 => @as(u16, @bitCast(@as(i16, @intCast(x)))),
65 32, 64 => @as(u32, @bitCast(x)),
66 else => unreachable,
67 },
68 .unsigned => |x| switch (bit_size) {
69 1, 8 => @as(u8, @intCast(x)),
70 16 => @as(u16, @intCast(x)),
71 32 => @as(u32, @intCast(x)),
72 64 => x,
73 else => unreachable,
74 },
75 };
76 }
77 };
78
3179 pub const Memory = union(enum) {
3280 sib: Sib,
3381 rip: Rip,
......@@ -1119,7 +1167,7 @@ test "encode" {
11191167
11201168 const inst = try Instruction.new(.none, .mov, &.{
11211169 .{ .reg = .rbx },
1122 .{ .imm = Immediate.u(4) },
1170 .{ .imm = Instruction.Immediate.u(4) },
11231171 });
11241172 try inst.encode(buf.writer(), .{});
11251173 try testing.expectEqualSlices(u8, &.{ 0x48, 0xc7, 0xc3, 0x4, 0x0, 0x0, 0x0 }, buf.items);
......@@ -1129,47 +1177,47 @@ test "lower I encoding" {
11291177 var enc = TestEncode{};
11301178
11311179 try enc.encode(.push, &.{
1132 .{ .imm = Immediate.u(0x10) },
1180 .{ .imm = Instruction.Immediate.u(0x10) },
11331181 });
11341182 try expectEqualHexStrings("\x6A\x10", enc.code(), "push 0x10");
11351183
11361184 try enc.encode(.push, &.{
1137 .{ .imm = Immediate.u(0x1000) },
1185 .{ .imm = Instruction.Immediate.u(0x1000) },
11381186 });
11391187 try expectEqualHexStrings("\x66\x68\x00\x10", enc.code(), "push 0x1000");
11401188
11411189 try enc.encode(.push, &.{
1142 .{ .imm = Immediate.u(0x10000000) },
1190 .{ .imm = Instruction.Immediate.u(0x10000000) },
11431191 });
11441192 try expectEqualHexStrings("\x68\x00\x00\x00\x10", enc.code(), "push 0x10000000");
11451193
11461194 try enc.encode(.adc, &.{
11471195 .{ .reg = .rax },
1148 .{ .imm = Immediate.u(0x10000000) },
1196 .{ .imm = Instruction.Immediate.u(0x10000000) },
11491197 });
11501198 try expectEqualHexStrings("\x48\x15\x00\x00\x00\x10", enc.code(), "adc rax, 0x10000000");
11511199
11521200 try enc.encode(.add, &.{
11531201 .{ .reg = .al },
1154 .{ .imm = Immediate.u(0x10) },
1202 .{ .imm = Instruction.Immediate.u(0x10) },
11551203 });
11561204 try expectEqualHexStrings("\x04\x10", enc.code(), "add al, 0x10");
11571205
11581206 try enc.encode(.add, &.{
11591207 .{ .reg = .rax },
1160 .{ .imm = Immediate.u(0x10) },
1208 .{ .imm = Instruction.Immediate.u(0x10) },
11611209 });
11621210 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
11631211
11641212 try enc.encode(.sbb, &.{
11651213 .{ .reg = .ax },
1166 .{ .imm = Immediate.u(0x10) },
1214 .{ .imm = Instruction.Immediate.u(0x10) },
11671215 });
11681216 try expectEqualHexStrings("\x66\x1D\x10\x00", enc.code(), "sbb ax, 0x10");
11691217
11701218 try enc.encode(.xor, &.{
11711219 .{ .reg = .al },
1172 .{ .imm = Immediate.u(0x10) },
1220 .{ .imm = Instruction.Immediate.u(0x10) },
11731221 });
11741222 try expectEqualHexStrings("\x34\x10", enc.code(), "xor al, 0x10");
11751223}
......@@ -1179,43 +1227,43 @@ test "lower MI encoding" {
11791227
11801228 try enc.encode(.mov, &.{
11811229 .{ .reg = .r12 },
1182 .{ .imm = Immediate.u(0x1000) },
1230 .{ .imm = Instruction.Immediate.u(0x1000) },
11831231 });
11841232 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
11851233
11861234 try enc.encode(.mov, &.{
11871235 .{ .mem = Instruction.Memory.sib(.byte, .{ .base = .{ .reg = .r12 } }) },
1188 .{ .imm = Immediate.u(0x10) },
1236 .{ .imm = Instruction.Immediate.u(0x10) },
11891237 });
11901238 try expectEqualHexStrings("\x41\xC6\x04\x24\x10", enc.code(), "mov BYTE PTR [r12], 0x10");
11911239
11921240 try enc.encode(.mov, &.{
11931241 .{ .reg = .r12 },
1194 .{ .imm = Immediate.u(0x1000) },
1242 .{ .imm = Instruction.Immediate.u(0x1000) },
11951243 });
11961244 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
11971245
11981246 try enc.encode(.mov, &.{
11991247 .{ .reg = .r12 },
1200 .{ .imm = Immediate.u(0x1000) },
1248 .{ .imm = Instruction.Immediate.u(0x1000) },
12011249 });
12021250 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
12031251
12041252 try enc.encode(.mov, &.{
12051253 .{ .reg = .rax },
1206 .{ .imm = Immediate.u(0x10) },
1254 .{ .imm = Instruction.Immediate.u(0x10) },
12071255 });
12081256 try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", enc.code(), "mov rax, 0x10");
12091257
12101258 try enc.encode(.mov, &.{
12111259 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .r11 } }) },
1212 .{ .imm = Immediate.u(0x10) },
1260 .{ .imm = Instruction.Immediate.u(0x10) },
12131261 });
12141262 try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", enc.code(), "mov DWORD PTR [r11], 0x10");
12151263
12161264 try enc.encode(.mov, &.{
12171265 .{ .mem = Instruction.Memory.rip(.qword, 0x10) },
1218 .{ .imm = Immediate.u(0x10) },
1266 .{ .imm = Instruction.Immediate.u(0x10) },
12191267 });
12201268 try expectEqualHexStrings(
12211269 "\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00",
......@@ -1225,19 +1273,19 @@ test "lower MI encoding" {
12251273
12261274 try enc.encode(.mov, &.{
12271275 .{ .mem = Instruction.Memory.sib(.qword, .{ .base = .{ .reg = .rbp }, .disp = -8 }) },
1228 .{ .imm = Immediate.u(0x10) },
1276 .{ .imm = Instruction.Immediate.u(0x10) },
12291277 });
12301278 try expectEqualHexStrings("\x48\xc7\x45\xf8\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rbp - 8], 0x10");
12311279
12321280 try enc.encode(.mov, &.{
12331281 .{ .mem = Instruction.Memory.sib(.word, .{ .base = .{ .reg = .rbp }, .disp = -2 }) },
1234 .{ .imm = Immediate.s(-16) },
1282 .{ .imm = Instruction.Immediate.s(-16) },
12351283 });
12361284 try expectEqualHexStrings("\x66\xC7\x45\xFE\xF0\xFF", enc.code(), "mov WORD PTR [rbp - 2], -16");
12371285
12381286 try enc.encode(.mov, &.{
12391287 .{ .mem = Instruction.Memory.sib(.byte, .{ .base = .{ .reg = .rbp }, .disp = -1 }) },
1240 .{ .imm = Immediate.u(0x10) },
1288 .{ .imm = Instruction.Immediate.u(0x10) },
12411289 });
12421290 try expectEqualHexStrings("\xC6\x45\xFF\x10", enc.code(), "mov BYTE PTR [rbp - 1], 0x10");
12431291
......@@ -1247,7 +1295,7 @@ test "lower MI encoding" {
12471295 .disp = 0x10000000,
12481296 .scale_index = .{ .scale = 2, .index = .rcx },
12491297 }) },
1250 .{ .imm = Immediate.u(0x10) },
1298 .{ .imm = Instruction.Immediate.u(0x10) },
12511299 });
12521300 try expectEqualHexStrings(
12531301 "\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00",
......@@ -1257,43 +1305,43 @@ test "lower MI encoding" {
12571305
12581306 try enc.encode(.adc, &.{
12591307 .{ .mem = Instruction.Memory.sib(.byte, .{ .base = .{ .reg = .rbp }, .disp = -0x10 }) },
1260 .{ .imm = Immediate.u(0x10) },
1308 .{ .imm = Instruction.Immediate.u(0x10) },
12611309 });
12621310 try expectEqualHexStrings("\x80\x55\xF0\x10", enc.code(), "adc BYTE PTR [rbp - 0x10], 0x10");
12631311
12641312 try enc.encode(.adc, &.{
12651313 .{ .mem = Instruction.Memory.rip(.qword, 0) },
1266 .{ .imm = Immediate.u(0x10) },
1314 .{ .imm = Instruction.Immediate.u(0x10) },
12671315 });
12681316 try expectEqualHexStrings("\x48\x83\x15\x00\x00\x00\x00\x10", enc.code(), "adc QWORD PTR [rip], 0x10");
12691317
12701318 try enc.encode(.adc, &.{
12711319 .{ .reg = .rax },
1272 .{ .imm = Immediate.u(0x10) },
1320 .{ .imm = Instruction.Immediate.u(0x10) },
12731321 });
12741322 try expectEqualHexStrings("\x48\x83\xD0\x10", enc.code(), "adc rax, 0x10");
12751323
12761324 try enc.encode(.add, &.{
12771325 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .rdx }, .disp = -8 }) },
1278 .{ .imm = Immediate.u(0x10) },
1326 .{ .imm = Instruction.Immediate.u(0x10) },
12791327 });
12801328 try expectEqualHexStrings("\x83\x42\xF8\x10", enc.code(), "add DWORD PTR [rdx - 8], 0x10");
12811329
12821330 try enc.encode(.add, &.{
12831331 .{ .reg = .rax },
1284 .{ .imm = Immediate.u(0x10) },
1332 .{ .imm = Instruction.Immediate.u(0x10) },
12851333 });
12861334 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
12871335
12881336 try enc.encode(.add, &.{
12891337 .{ .mem = Instruction.Memory.sib(.qword, .{ .base = .{ .reg = .rbp }, .disp = -0x10 }) },
1290 .{ .imm = Immediate.s(-0x10) },
1338 .{ .imm = Instruction.Immediate.s(-0x10) },
12911339 });
12921340 try expectEqualHexStrings("\x48\x83\x45\xF0\xF0", enc.code(), "add QWORD PTR [rbp - 0x10], -0x10");
12931341
12941342 try enc.encode(.@"and", &.{
12951343 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .ds }, .disp = 0x10000000 }) },
1296 .{ .imm = Immediate.u(0x10) },
1344 .{ .imm = Instruction.Immediate.u(0x10) },
12971345 });
12981346 try expectEqualHexStrings(
12991347 "\x83\x24\x25\x00\x00\x00\x10\x10",
......@@ -1303,7 +1351,7 @@ test "lower MI encoding" {
13031351
13041352 try enc.encode(.@"and", &.{
13051353 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .es }, .disp = 0x10000000 }) },
1306 .{ .imm = Immediate.u(0x10) },
1354 .{ .imm = Instruction.Immediate.u(0x10) },
13071355 });
13081356 try expectEqualHexStrings(
13091357 "\x26\x83\x24\x25\x00\x00\x00\x10\x10",
......@@ -1313,7 +1361,7 @@ test "lower MI encoding" {
13131361
13141362 try enc.encode(.@"and", &.{
13151363 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .r12 }, .disp = 0x10000000 }) },
1316 .{ .imm = Immediate.u(0x10) },
1364 .{ .imm = Instruction.Immediate.u(0x10) },
13171365 });
13181366 try expectEqualHexStrings(
13191367 "\x41\x83\xA4\x24\x00\x00\x00\x10\x10",
......@@ -1323,7 +1371,7 @@ test "lower MI encoding" {
13231371
13241372 try enc.encode(.sub, &.{
13251373 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .r11 }, .disp = 0x10000000 }) },
1326 .{ .imm = Immediate.u(0x10) },
1374 .{ .imm = Instruction.Immediate.u(0x10) },
13271375 });
13281376 try expectEqualHexStrings(
13291377 "\x41\x83\xAB\x00\x00\x00\x10\x10",
......@@ -1542,14 +1590,14 @@ test "lower RMI encoding" {
15421590 try enc.encode(.imul, &.{
15431591 .{ .reg = .r11 },
15441592 .{ .reg = .r12 },
1545 .{ .imm = Immediate.s(-2) },
1593 .{ .imm = Instruction.Immediate.s(-2) },
15461594 });
15471595 try expectEqualHexStrings("\x4D\x6B\xDC\xFE", enc.code(), "imul r11, r12, -2");
15481596
15491597 try enc.encode(.imul, &.{
15501598 .{ .reg = .r11 },
15511599 .{ .mem = Instruction.Memory.rip(.qword, -16) },
1552 .{ .imm = Immediate.s(-1024) },
1600 .{ .imm = Instruction.Immediate.s(-1024) },
15531601 });
15541602 try expectEqualHexStrings(
15551603 "\x4C\x69\x1D\xF0\xFF\xFF\xFF\x00\xFC\xFF\xFF",
......@@ -1560,7 +1608,7 @@ test "lower RMI encoding" {
15601608 try enc.encode(.imul, &.{
15611609 .{ .reg = .bx },
15621610 .{ .mem = Instruction.Memory.sib(.word, .{ .base = .{ .reg = .rbp }, .disp = -16 }) },
1563 .{ .imm = Immediate.s(-1024) },
1611 .{ .imm = Instruction.Immediate.s(-1024) },
15641612 });
15651613 try expectEqualHexStrings(
15661614 "\x66\x69\x5D\xF0\x00\xFC",
......@@ -1571,7 +1619,7 @@ test "lower RMI encoding" {
15711619 try enc.encode(.imul, &.{
15721620 .{ .reg = .bx },
15731621 .{ .mem = Instruction.Memory.sib(.word, .{ .base = .{ .reg = .rbp }, .disp = -16 }) },
1574 .{ .imm = Immediate.u(1024) },
1622 .{ .imm = Instruction.Immediate.u(1024) },
15751623 });
15761624 try expectEqualHexStrings(
15771625 "\x66\x69\x5D\xF0\x00\x04",
......@@ -1687,7 +1735,7 @@ test "lower M encoding" {
16871735 try expectEqualHexStrings("\x65\xFF\x14\x25\x00\x00\x00\x00", enc.code(), "call gs:0x0");
16881736
16891737 try enc.encode(.call, &.{
1690 .{ .imm = Immediate.s(0) },
1738 .{ .imm = Instruction.Immediate.s(0) },
16911739 });
16921740 try expectEqualHexStrings("\xE8\x00\x00\x00\x00", enc.code(), "call 0x0");
16931741
......@@ -1746,7 +1794,7 @@ test "lower OI encoding" {
17461794
17471795 try enc.encode(.mov, &.{
17481796 .{ .reg = .rax },
1749 .{ .imm = Immediate.u(0x1000000000000000) },
1797 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },
17501798 });
17511799 try expectEqualHexStrings(
17521800 "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10",
......@@ -1756,7 +1804,7 @@ test "lower OI encoding" {
17561804
17571805 try enc.encode(.mov, &.{
17581806 .{ .reg = .r11 },
1759 .{ .imm = Immediate.u(0x1000000000000000) },
1807 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },
17601808 });
17611809 try expectEqualHexStrings(
17621810 "\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10",
......@@ -1766,19 +1814,19 @@ test "lower OI encoding" {
17661814
17671815 try enc.encode(.mov, &.{
17681816 .{ .reg = .r11d },
1769 .{ .imm = Immediate.u(0x10000000) },
1817 .{ .imm = Instruction.Immediate.u(0x10000000) },
17701818 });
17711819 try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", enc.code(), "mov r11d, 0x10000000");
17721820
17731821 try enc.encode(.mov, &.{
17741822 .{ .reg = .r11w },
1775 .{ .imm = Immediate.u(0x1000) },
1823 .{ .imm = Instruction.Immediate.u(0x1000) },
17761824 });
17771825 try expectEqualHexStrings("\x66\x41\xBB\x00\x10", enc.code(), "mov r11w, 0x1000");
17781826
17791827 try enc.encode(.mov, &.{
17801828 .{ .reg = .r11b },
1781 .{ .imm = Immediate.u(0x10) },
1829 .{ .imm = Instruction.Immediate.u(0x10) },
17821830 });
17831831 try expectEqualHexStrings("\x41\xB3\x10", enc.code(), "mov r11b, 0x10");
17841832}
......@@ -1900,7 +1948,7 @@ test "invalid instruction" {
19001948 .{ .reg = .r12d },
19011949 });
19021950 try invalidInstruction(.push, &.{
1903 .{ .imm = Immediate.u(0x1000000000000000) },
1951 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },
19041952 });
19051953}
19061954
......@@ -2213,7 +2261,7 @@ const Assembler = struct {
22132261 .immediate => {
22142262 const is_neg = if (as.expect(.minus)) |_| true else |_| false;
22152263 const imm_tok = try as.expect(.numeral);
2216 const imm: Immediate = if (is_neg) blk: {
2264 const imm: Instruction.Immediate = if (is_neg) blk: {
22172265 const imm = try std.fmt.parseInt(i32, as.source(imm_tok), 0);
22182266 break :blk .{ .signed = imm * -1 };
22192267 } else .{ .unsigned = try std.fmt.parseInt(u64, as.source(imm_tok), 0) };
src/codegen.zig+6-4
......@@ -828,6 +828,9 @@ pub const GenResult = union(enum) {
828828 /// Reference to memory location but deferred until linker allocated the Decl in memory.
829829 /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
830830 load_symbol: u32,
831 /// Reference to memory location but deferred until linker allocated the Decl in memory.
832 /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
833 lea_symbol: u32,
831834 };
832835
833836 fn mcv(val: MCValue) GenResult {
......@@ -895,16 +898,15 @@ fn genNavRef(
895898 if (lf.cast(.elf)) |elf_file| {
896899 const zo = elf_file.zigObjectPtr().?;
897900 if (is_extern) {
898 // TODO audit this
899901 const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
900 zo.symbol(sym_index).flags.needs_got = true;
901 return GenResult.mcv(.{ .load_symbol = sym_index });
902 zo.symbol(sym_index).flags.is_extern_ptr = true;
903 return GenResult.mcv(.{ .lea_symbol = sym_index });
902904 }
903905 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, nav_index);
904906 if (!single_threaded and is_threadlocal) {
905907 return GenResult.mcv(.{ .load_tlv = sym_index });
906908 }
907 return GenResult.mcv(.{ .load_symbol = sym_index });
909 return GenResult.mcv(.{ .lea_symbol = sym_index });
908910 } else if (lf.cast(.macho)) |macho_file| {
909911 const zo = macho_file.getZigObject().?;
910912 if (is_extern) {
src/link/Elf.zig+11-104
......@@ -64,9 +64,6 @@ phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},
6464/// Tracked loadable segments during incremental linking.
6565/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
6666phdr_zig_load_re_index: ?u16 = null,
67/// The index into the program headers of the global offset table.
68/// It needs PT_LOAD and Read flags.
69phdr_zig_got_index: ?u16 = null,
7067/// The index into the program headers of a PT_LOAD program header with Read flag
7168phdr_zig_load_ro_index: ?u16 = null,
7269/// The index into the program headers of a PT_LOAD program header with Write flag
......@@ -130,8 +127,6 @@ plt_got: PltGotSection = .{},
130127copy_rel: CopyRelSection = .{},
131128/// .rela.plt section
132129rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
133/// .got.zig section
134zig_got: ZigGotSection = .{},
135130/// SHT_GROUP sections
136131/// Applies only to a relocatable.
137132comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{},
......@@ -142,7 +137,6 @@ zig_text_section_index: ?u32 = null,
142137zig_data_rel_ro_section_index: ?u32 = null,
143138zig_data_section_index: ?u32 = null,
144139zig_bss_section_index: ?u32 = null,
145zig_got_section_index: ?u32 = null,
146140
147141debug_info_section_index: ?u32 = null,
148142debug_abbrev_section_index: ?u32 = null,
......@@ -474,7 +468,6 @@ pub fn deinit(self: *Elf) void {
474468 self.copy_rel.deinit(gpa);
475469 self.rela_dyn.deinit(gpa);
476470 self.rela_plt.deinit(gpa);
477 self.zig_got.deinit(gpa);
478471 self.comdat_group_sections.deinit(gpa);
479472}
480473
......@@ -611,28 +604,13 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
611604 .type = elf.PT_LOAD,
612605 .offset = off,
613606 .filesz = filesz,
614 .addr = if (ptr_bit_width >= 32) 0x8000000 else 0x8000,
607 .addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000,
615608 .memsz = filesz,
616609 .@"align" = self.page_size,
617610 .flags = elf.PF_X | elf.PF_R | elf.PF_W,
618611 });
619612 }
620613
621 if (self.phdr_zig_got_index == null) {
622 const alignment = self.page_size;
623 const filesz = @as(u64, ptr_size) * options.symbol_count_hint;
624 const off = self.findFreeSpace(filesz, alignment);
625 self.phdr_zig_got_index = try self.addPhdr(.{
626 .type = elf.PT_LOAD,
627 .offset = off,
628 .filesz = filesz,
629 .addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000,
630 .memsz = filesz,
631 .@"align" = alignment,
632 .flags = elf.PF_R | elf.PF_W,
633 });
634 }
635
636614 if (self.phdr_zig_load_ro_index == null) {
637615 const alignment = self.page_size;
638616 const filesz: u64 = 1024;
......@@ -701,27 +679,6 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
701679 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{});
702680 }
703681
704 if (self.zig_got_section_index == null and !self.base.isRelocatable()) {
705 self.zig_got_section_index = try self.addSection(.{
706 .name = try self.insertShString(".got.zig"),
707 .type = elf.SHT_PROGBITS,
708 .addralign = ptr_size,
709 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
710 .offset = std.math.maxInt(u64),
711 });
712 const shdr = &self.shdrs.items[self.zig_got_section_index.?];
713 const phndx = self.phdr_zig_got_index.?;
714 const phdr = self.phdrs.items[phndx];
715 shdr.sh_addr = phdr.p_vaddr;
716 shdr.sh_offset = phdr.p_offset;
717 shdr.sh_size = phdr.p_memsz;
718 try self.phdr_to_shdr_table.putNoClobber(
719 gpa,
720 self.zig_got_section_index.?,
721 self.phdr_zig_got_index.?,
722 );
723 }
724
725682 if (self.zig_data_rel_ro_section_index == null) {
726683 self.zig_data_rel_ro_section_index = try self.addSection(.{
727684 .name = try self.insertShString(".data.rel.ro.zig"),
......@@ -900,6 +857,11 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {
900857 const shdr = &self.shdrs.items[shdr_index];
901858 const maybe_phdr = if (self.phdr_to_shdr_table.get(shdr_index)) |phndx| &self.phdrs.items[phndx] else null;
902859 const is_zerofill = shdr.sh_type == elf.SHT_NOBITS;
860 log.debug("allocated size {x} of {s}, needed size {x}", .{
861 self.allocatedSize(shdr.sh_offset),
862 self.getShString(shdr.sh_name),
863 needed_size,
864 });
903865
904866 if (needed_size > self.allocatedSize(shdr.sh_offset) and !is_zerofill) {
905867 const existing_size = shdr.sh_size;
......@@ -3156,8 +3118,8 @@ fn initSyntheticSections(self: *Elf) !void {
31563118 });
31573119
31583120 const needs_rela_dyn = blk: {
3159 if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or
3160 self.zig_got.flags.needs_rela or self.copy_rel.symbols.items.len > 0) break :blk true;
3121 if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or self.copy_rel.symbols.items.len > 0)
3122 break :blk true;
31613123 if (self.zigObjectPtr()) |zig_object| {
31623124 if (zig_object.num_dynrelocs > 0) break :blk true;
31633125 }
......@@ -3562,7 +3524,6 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
35623524
35633525 for (&[_]*?u16{
35643526 &self.phdr_zig_load_re_index,
3565 &self.phdr_zig_got_index,
35663527 &self.phdr_zig_load_ro_index,
35673528 &self.phdr_zig_load_zerofill_index,
35683529 &self.phdr_table_index,
......@@ -3694,7 +3655,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void {
36943655 &self.versym_section_index,
36953656 &self.verneed_section_index,
36963657 &self.zig_text_section_index,
3697 &self.zig_got_section_index,
36983658 &self.zig_data_rel_ro_section_index,
36993659 &self.zig_data_section_index,
37003660 &self.zig_bss_section_index,
......@@ -3893,7 +3853,7 @@ fn updateSectionSizes(self: *Elf) !void {
38933853 }
38943854
38953855 if (self.rela_dyn_section_index) |shndx| {
3896 var num = self.got.numRela(self) + self.copy_rel.numRela() + self.zig_got.numRela();
3856 var num = self.got.numRela(self) + self.copy_rel.numRela();
38973857 if (self.zigObjectPtr()) |zig_object| {
38983858 num += zig_object.num_dynrelocs;
38993859 }
......@@ -4431,15 +4391,6 @@ pub fn updateSymtabSize(self: *Elf) !void {
44314391 strsize += ctx.strsize;
44324392 }
44334393
4434 if (self.zigObjectPtr()) |_| {
4435 if (self.zig_got_section_index) |_| {
4436 self.zig_got.output_symtab_ctx.ilocal = nlocals + 1;
4437 self.zig_got.updateSymtabSize(self);
4438 nlocals += self.zig_got.output_symtab_ctx.nlocals;
4439 strsize += self.zig_got.output_symtab_ctx.strsize;
4440 }
4441 }
4442
44434394 if (self.got_section_index) |_| {
44444395 self.got.output_symtab_ctx.ilocal = nlocals + 1;
44454396 self.got.updateSymtabSize(self);
......@@ -4576,9 +4527,6 @@ fn writeSyntheticSections(self: *Elf) !void {
45764527 const shdr = self.shdrs.items[shndx];
45774528 try self.got.addRela(self);
45784529 try self.copy_rel.addRela(self);
4579 if (self.zigObjectPtr()) |_| {
4580 try self.zig_got.addRela(self);
4581 }
45824530 self.sortRelaDyn();
45834531 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset);
45844532 }
......@@ -4674,10 +4622,6 @@ pub fn writeSymtab(self: *Elf) !void {
46744622 obj.asFile().writeSymtab(self);
46754623 }
46764624
4677 if (self.zig_got_section_index) |_| {
4678 self.zig_got.writeSymtab(self);
4679 }
4680
46814625 if (self.got_section_index) |_| {
46824626 self.got.writeSymtab(self);
46834627 }
......@@ -5085,7 +5029,6 @@ pub fn isZigSection(self: Elf, shndx: u32) bool {
50855029 self.zig_data_rel_ro_section_index,
50865030 self.zig_data_section_index,
50875031 self.zig_bss_section_index,
5088 self.zig_got_section_index,
50895032 }) |maybe_index| {
50905033 if (maybe_index) |index| {
50915034 if (index == shndx) return true;
......@@ -5657,10 +5600,11 @@ fn fmtDumpState(
56575600
56585601 if (self.zigObjectPtr()) |zig_object| {
56595602 try writer.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.path });
5660 try writer.print("{}{}\n", .{
5603 try writer.print("{}{}", .{
56615604 zig_object.fmtAtoms(self),
56625605 zig_object.fmtSymtab(self),
56635606 });
5607 try writer.writeByte('\n');
56645608 }
56655609
56665610 for (self.objects.items) |index| {
......@@ -5700,7 +5644,6 @@ fn fmtDumpState(
57005644 }
57015645 }
57025646
5703 try writer.print("{}\n", .{self.zig_got.fmt(self)});
57045647 try writer.print("{}\n", .{self.got.fmt(self)});
57055648 try writer.print("{}\n", .{self.plt.fmt(self)});
57065649
......@@ -5991,41 +5934,6 @@ const RelaSection = struct {
59915934};
59925935const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
59935936
5994pub const R_ZIG_GOT32: u32 = 0xff00;
5995pub const R_ZIG_GOTPCREL: u32 = 0xff01;
5996pub const R_ZIG_GOT_HI20: u32 = 0xff02;
5997pub const R_ZIG_GOT_LO12: u32 = 0xff03;
5998pub const R_GOT_HI20_STATIC: u32 = 0xff04;
5999pub const R_GOT_LO12_I_STATIC: u32 = 0xff05;
6000
6001// Comptime asserts that no Zig relocs overlap with another ISA's reloc number
6002comptime {
6003 const zig_relocs = .{
6004 R_ZIG_GOT32,
6005 R_ZIG_GOT_HI20,
6006 R_ZIG_GOT_LO12,
6007 R_ZIG_GOTPCREL,
6008 R_GOT_HI20_STATIC,
6009 R_GOT_LO12_I_STATIC,
6010 };
6011
6012 const other_relocs = .{
6013 elf.R_X86_64,
6014 elf.R_AARCH64,
6015 elf.R_RISCV,
6016 elf.R_PPC64,
6017 };
6018
6019 @setEvalBranchQuota(@min(other_relocs.len * zig_relocs.len * 256, 6200));
6020 for (other_relocs) |relocs| {
6021 for (@typeInfo(relocs).Enum.fields) |reloc| {
6022 for (zig_relocs) |zig_reloc| {
6023 assert(reloc.value != zig_reloc);
6024 }
6025 }
6026 }
6027}
6028
60295937fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
60305938 return switch (cpu_arch) {
60315939 .mips, .mipsel, .mips64, .mips64el => "__start",
......@@ -6095,6 +6003,5 @@ const StringTable = @import("StringTable.zig");
60956003const Thunk = thunks.Thunk;
60966004const Value = @import("../Value.zig");
60976005const VerneedSection = synthetic_sections.VerneedSection;
6098const ZigGotSection = synthetic_sections.ZigGotSection;
60996006const ZigObject = @import("Elf/ZigObject.zig");
61006007const riscv = @import("riscv.zig");
src/link/Elf/Atom.zig+22-81
......@@ -746,12 +746,10 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
746746 const P = self.address(elf_file) + @as(i64, @intCast(rel.r_offset));
747747 // Addend from the relocation.
748748 const A = rel.r_addend;
749 // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub.
749 // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub, or address of a Zig trampoline.
750750 const S = target.address(.{}, elf_file);
751751 // Address of the global offset table.
752752 const GOT = elf_file.gotAddress();
753 // Address of the .zig.got table entry if any.
754 const ZIG_GOT = target.zigGotAddress(elf_file);
755753 // Relative offset to the start of the global offset table.
756754 const G = target.gotAddress(elf_file) - GOT;
757755 // // Address of the thread pointer.
......@@ -759,19 +757,18 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
759757 // Address of the dynamic thread pointer.
760758 const DTP = elf_file.dtpAddress();
761759
762 relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{
760 relocs_log.debug(" {s}: {x}: [{x} => {x}] GOT({x}) ({s})", .{
763761 relocation.fmtRelocType(rel.r_type(), cpu_arch),
764762 r_offset,
765763 P,
766764 S + A,
767765 G + GOT + A,
768 ZIG_GOT + A,
769766 target.name(elf_file),
770767 });
771768
772769 try stream.seekTo(r_offset);
773770
774 const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP, ZIG_GOT };
771 const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP };
775772
776773 switch (cpu_arch) {
777774 .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {
......@@ -956,7 +953,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
956953 // Address of the dynamic thread pointer.
957954 const DTP = elf_file.dtpAddress();
958955
959 const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP, 0 };
956 const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP };
960957
961958 relocs_log.debug(" {}: {x}: [{x} => {x}] ({s})", .{
962959 relocation.fmtRelocType(rel.r_type(), cpu_arch),
......@@ -1025,7 +1022,7 @@ pub fn format(
10251022 _ = unused_fmt_string;
10261023 _ = options;
10271024 _ = writer;
1028 @compileError("do not format symbols directly");
1025 @compileError("do not format Atom directly");
10291026}
10301027
10311028pub fn fmt(atom: Atom, elf_file: *Elf) std.fmt.Formatter(format2) {
......@@ -1051,8 +1048,8 @@ fn format2(
10511048 const atom = ctx.atom;
10521049 const elf_file = ctx.elf_file;
10531050 try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x})", .{
1054 atom.atom_index, atom.name(elf_file), atom.address(elf_file),
1055 atom.output_section_index, atom.alignment, atom.size,
1051 atom.atom_index, atom.name(elf_file), atom.address(elf_file),
1052 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,
10561053 });
10571054 if (atom.fdes(elf_file).len > 0) {
10581055 try writer.writeAll(" : fdes{ ");
......@@ -1180,16 +1177,7 @@ const x86_64 = struct {
11801177 .TLSDESC_CALL,
11811178 => {},
11821179
1183 else => |x| switch (@intFromEnum(x)) {
1184 // Zig custom relocations
1185 Elf.R_ZIG_GOT32,
1186 Elf.R_ZIG_GOTPCREL,
1187 => {
1188 assert(symbol.flags.has_zig_got);
1189 },
1190
1191 else => try atom.reportUnhandledRelocError(rel, elf_file),
1192 },
1180 else => try atom.reportUnhandledRelocError(rel, elf_file),
11931181 }
11941182 }
11951183
......@@ -1209,7 +1197,7 @@ const x86_64 = struct {
12091197
12101198 const cwriter = stream.writer();
12111199
1212 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
1200 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
12131201
12141202 switch (r_type) {
12151203 .NONE => unreachable,
......@@ -1224,9 +1212,8 @@ const x86_64 = struct {
12241212 );
12251213 },
12261214
1227 .PLT32,
1228 .PC32,
1229 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
1215 .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
1216 .PC32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
12301217
12311218 .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),
12321219 .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),
......@@ -1327,15 +1314,9 @@ const x86_64 = struct {
13271314 }
13281315 },
13291316
1330 .GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A)), .little),
1331
1332 else => |x| switch (@intFromEnum(x)) {
1333 // Zig custom relocations
1334 Elf.R_ZIG_GOT32 => try cwriter.writeInt(u32, @as(u32, @intCast(ZIG_GOT + A)), .little),
1335 Elf.R_ZIG_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(ZIG_GOT + A - P)), .little),
1317 .GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + A)), .little),
13361318
1337 else => try atom.reportUnhandledRelocError(rel, elf_file),
1338 },
1319 else => try atom.reportUnhandledRelocError(rel, elf_file),
13391320 }
13401321 }
13411322
......@@ -1355,7 +1336,7 @@ const x86_64 = struct {
13551336 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
13561337 const cwriter = stream.writer();
13571338
1358 _, const A, const S, const GOT, _, _, const DTP, _ = args;
1339 _, const A, const S, const GOT, _, _, const DTP = args;
13591340
13601341 switch (r_type) {
13611342 .NONE => unreachable,
......@@ -1629,7 +1610,7 @@ const x86_64 = struct {
16291610 const bits = @import("../../arch/x86_64/bits.zig");
16301611 const encoder = @import("../../arch/x86_64/encoder.zig");
16311612 const Disassembler = @import("../../arch/x86_64/Disassembler.zig");
1632 const Immediate = bits.Immediate;
1613 const Immediate = Instruction.Immediate;
16331614 const Instruction = encoder.Instruction;
16341615};
16351616
......@@ -1738,9 +1719,8 @@ const aarch64 = struct {
17381719 const code = code_buffer[r_offset..][0..4];
17391720 const file_ptr = atom.file(elf_file).?;
17401721
1741 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
1722 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
17421723 _ = DTP;
1743 _ = ZIG_GOT;
17441724
17451725 switch (r_type) {
17461726 .NONE => unreachable,
......@@ -1942,7 +1922,7 @@ const aarch64 = struct {
19421922 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
19431923 const cwriter = stream.writer();
19441924
1945 _, const A, const S, _, _, _, _, _ = args;
1925 _, const A, const S, _, _, _, _ = args;
19461926
19471927 switch (r_type) {
19481928 .NONE => unreachable,
......@@ -1998,19 +1978,7 @@ const riscv = struct {
19981978 .SUB32,
19991979 => {},
20001980
2001 else => |x| switch (@intFromEnum(x)) {
2002 Elf.R_ZIG_GOT_HI20,
2003 Elf.R_ZIG_GOT_LO12,
2004 => {
2005 assert(symbol.flags.has_zig_got);
2006 },
2007
2008 Elf.R_GOT_HI20_STATIC,
2009 Elf.R_GOT_LO12_I_STATIC,
2010 => symbol.flags.needs_got = true,
2011
2012 else => try atom.reportUnhandledRelocError(rel, elf_file),
2013 },
1981 else => try atom.reportUnhandledRelocError(rel, elf_file),
20141982 }
20151983 }
20161984
......@@ -2028,7 +1996,7 @@ const riscv = struct {
20281996 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
20291997 const cwriter = stream.writer();
20301998
2031 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
1999 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
20322000 _ = TP;
20332001 _ = DTP;
20342002
......@@ -2147,34 +2115,7 @@ const riscv = struct {
21472115 // TODO: annotates an ADD instruction that can be removed when TPREL is relaxed
21482116 },
21492117
2150 else => |x| switch (@intFromEnum(x)) {
2151 // Zig custom relocations
2152 Elf.R_ZIG_GOT_HI20 => {
2153 assert(target.flags.has_zig_got);
2154 const disp: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow);
2155 riscv_util.writeInstU(code[r_offset..][0..4], disp);
2156 },
2157
2158 Elf.R_ZIG_GOT_LO12 => {
2159 assert(target.flags.has_zig_got);
2160 const value: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow);
2161 riscv_util.writeInstI(code[r_offset..][0..4], value);
2162 },
2163
2164 Elf.R_GOT_HI20_STATIC => {
2165 assert(target.flags.has_got);
2166 const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow);
2167 riscv_util.writeInstU(code[r_offset..][0..4], disp);
2168 },
2169
2170 Elf.R_GOT_LO12_I_STATIC => {
2171 assert(target.flags.has_got);
2172 const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow);
2173 riscv_util.writeInstI(code[r_offset..][0..4], disp);
2174 },
2175
2176 else => try atom.reportUnhandledRelocError(rel, elf_file),
2177 },
2118 else => try atom.reportUnhandledRelocError(rel, elf_file),
21782119 }
21792120 }
21802121
......@@ -2194,7 +2135,7 @@ const riscv = struct {
21942135 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
21952136 const cwriter = stream.writer();
21962137
2197 _, const A, const S, const GOT, _, _, const DTP, _ = args;
2138 _, const A, const S, const GOT, _, _, const DTP = args;
21982139 _ = GOT;
21992140 _ = DTP;
22002141
......@@ -2230,7 +2171,7 @@ const riscv = struct {
22302171 const riscv_util = @import("../riscv.zig");
22312172};
22322173
2233const ResolveArgs = struct { i64, i64, i64, i64, i64, i64, i64, i64 };
2174const ResolveArgs = struct { i64, i64, i64, i64, i64, i64, i64 };
22342175
22352176const RelocError = error{
22362177 Overflow,
src/link/Elf/Symbol.zig+22-30
......@@ -101,7 +101,7 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {
101101 return file_ptr.symbolRank(sym, in_archive);
102102}
103103
104pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf) i64 {
104pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool = true }, elf_file: *Elf) i64 {
105105 if (symbol.mergeSubsection(elf_file)) |msub| {
106106 if (!msub.alive) return 0;
107107 return msub.address(elf_file) + symbol.value;
......@@ -109,6 +109,9 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf
109109 if (symbol.flags.has_copy_rel) {
110110 return symbol.copyRelAddress(elf_file);
111111 }
112 if (symbol.flags.has_trampoline and opts.trampoline) {
113 return symbol.trampolineAddress(elf_file);
114 }
112115 if (symbol.flags.has_plt and opts.plt) {
113116 if (!symbol.flags.is_canonical and symbol.flags.has_got) {
114117 // We have a non-lazy bound function pointer, use that!
......@@ -217,23 +220,11 @@ pub fn tlsDescAddress(symbol: Symbol, elf_file: *Elf) i64 {
217220 return entry.address(elf_file);
218221}
219222
220const GetOrCreateZigGotEntryResult = struct {
221 found_existing: bool,
222 index: ZigGotSection.Index,
223};
224
225pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult {
226 assert(!elf_file.base.isRelocatable());
227 assert(symbol.flags.needs_zig_got);
228 if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).zig_got };
229 const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file);
230 return .{ .found_existing = false, .index = index };
231}
232
233pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
234 if (!symbol.flags.has_zig_got) return 0;
235 const extras = symbol.extra(elf_file);
236 return elf_file.zig_got.entryAddress(extras.zig_got, elf_file);
223pub fn trampolineAddress(symbol: Symbol, elf_file: *Elf) i64 {
224 if (!symbol.flags.has_trampoline) return 0;
225 const zo = elf_file.zigObjectPtr().?;
226 const index = symbol.extra(elf_file).trampoline;
227 return zo.symbol(index).address(.{}, elf_file);
237228}
238229
239230pub fn dsoAlignment(symbol: Symbol, elf_file: *Elf) !u64 {
......@@ -259,7 +250,7 @@ const AddExtraOpts = struct {
259250 tlsgd: ?u32 = null,
260251 gottp: ?u32 = null,
261252 tlsdesc: ?u32 = null,
262 zig_got: ?u32 = null,
253 trampoline: ?u32 = null,
263254};
264255
265256pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void {
......@@ -312,7 +303,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
312303 const shdr = elf_file.shdrs.items[st_shndx];
313304 if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined)
314305 break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress();
315 break :blk symbol.address(.{ .plt = false }, elf_file);
306 break :blk symbol.address(.{ .plt = false, .trampoline = false }, elf_file);
316307 };
317308 out.st_info = (st_bind << 4) | st_type;
318309 out.st_other = esym.st_other;
......@@ -331,7 +322,7 @@ pub fn format(
331322 _ = unused_fmt_string;
332323 _ = options;
333324 _ = writer;
334 @compileError("do not format symbols directly");
325 @compileError("do not format Symbol directly");
335326}
336327
337328const FormatContext = struct {
......@@ -388,7 +379,7 @@ fn format2(
388379 try writer.print("%{d} : {s} : @{x}", .{
389380 symbol.esym_index,
390381 symbol.fmtName(elf_file),
391 symbol.address(.{}, elf_file),
382 symbol.address(.{ .plt = false, .trampoline = false }, elf_file),
392383 });
393384 if (symbol.file(elf_file)) |file_ptr| {
394385 if (symbol.isAbs(elf_file)) {
......@@ -456,17 +447,18 @@ pub const Flags = packed struct {
456447 needs_tlsdesc: bool = false,
457448 has_tlsdesc: bool = false,
458449
459 /// Whether the symbol contains .zig.got indirection.
460 needs_zig_got: bool = false,
461 has_zig_got: bool = false,
450 /// Whether the symbol is a merge subsection.
451 merge_subsection: bool = false,
452
453 /// ZigObject specific flags
454 /// Whether the symbol has a trampoline.
455 has_trampoline: bool = false,
462456
463457 /// Whether the symbol is a TLS variable.
464 /// TODO this is really not needed if only we operated on esyms between
465 /// codegen and ZigObject.
466458 is_tls: bool = false,
467459
468 /// Whether the symbol is a merge subsection.
469 merge_subsection: bool = false,
460 /// Whether the symbol is an extern pointer (as opposed to function).
461 is_extern_ptr: bool = false,
470462};
471463
472464pub const Extra = struct {
......@@ -479,8 +471,8 @@ pub const Extra = struct {
479471 tlsgd: u32 = 0,
480472 gottp: u32 = 0,
481473 tlsdesc: u32 = 0,
482 zig_got: u32 = 0,
483474 merge_section: u32 = 0,
475 trampoline: u32 = 0,
484476};
485477
486478pub const Index = u32;
src/link/Elf/ZigObject.zig+180-55
......@@ -102,23 +102,17 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
102102 }
103103 self.relocs.deinit(allocator);
104104
105 {
106 var it = self.navs.iterator();
107 while (it.next()) |entry| {
108 entry.value_ptr.exports.deinit(allocator);
109 }
110 self.navs.deinit(allocator);
105 for (self.navs.values()) |*meta| {
106 meta.exports.deinit(allocator);
111107 }
108 self.navs.deinit(allocator);
112109
113110 self.lazy_syms.deinit(allocator);
114111
115 {
116 var it = self.uavs.iterator();
117 while (it.next()) |entry| {
118 entry.value_ptr.exports.deinit(allocator);
119 }
120 self.uavs.deinit(allocator);
112 for (self.uavs.values()) |*meta| {
113 meta.exports.deinit(allocator);
121114 }
115 self.uavs.deinit(allocator);
122116
123117 for (self.tls_variables.values()) |*tlv| {
124118 tlv.deinit(allocator);
......@@ -161,6 +155,16 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
161155 if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed;
162156 }
163157
158 if (build_options.enable_logging) {
159 const pt: Zcu.PerThread = .{ .zcu = elf_file.base.comp.module.?, .tid = tid };
160 for (self.navs.keys(), self.navs.values()) |nav_index, meta| {
161 checkNavAllocated(pt, nav_index, meta);
162 }
163 for (self.uavs.keys(), self.uavs.values()) |uav_index, meta| {
164 checkUavAllocated(pt, uav_index, meta);
165 }
166 }
167
164168 if (self.dwarf) |*dw| {
165169 const pt: Zcu.PerThread = .{ .zcu = elf_file.base.comp.module.?, .tid = tid };
166170 try dw.flushModule(pt);
......@@ -698,6 +702,7 @@ pub fn lowerUav(
698702 else => explicit_alignment,
699703 };
700704 if (self.uavs.get(uav)) |metadata| {
705 assert(metadata.allocated);
701706 const sym = self.symbol(metadata.symbol_index);
702707 const existing_alignment = sym.atom(elf_file).?.alignment;
703708 if (uav_alignment.order(existing_alignment).compare(.lte))
......@@ -729,7 +734,7 @@ pub fn lowerUav(
729734 .ok => |sym_index| sym_index,
730735 .fail => |em| return .{ .fail = em },
731736 };
732 try self.uavs.put(gpa, uav, .{ .symbol_index = sym_index });
737 try self.uavs.put(gpa, uav, .{ .symbol_index = sym_index, .allocated = true });
733738 return .{ .mcv = .{ .load_symbol = sym_index } };
734739}
735740
......@@ -747,13 +752,7 @@ pub fn getOrCreateMetadataForLazySymbol(
747752 .const_data => .{ &gop.value_ptr.rodata_symbol_index, &gop.value_ptr.rodata_state },
748753 };
749754 switch (state_ptr.*) {
750 .unused => {
751 const gpa = elf_file.base.comp.gpa;
752 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
753 const sym = self.symbol(symbol_index);
754 sym.flags.needs_zig_got = true;
755 symbol_index_ptr.* = symbol_index;
756 },
755 .unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, 0),
757756 .pending_flush => return symbol_index_ptr.*,
758757 .flushed => {},
759758 }
......@@ -807,9 +806,6 @@ pub fn getOrCreateMetadataForNav(
807806 sym.flags.is_tls = true;
808807 }
809808 }
810 if (!sym.flags.is_tls) {
811 sym.flags.needs_zig_got = true;
812 }
813809 gop.value_ptr.* = .{ .symbol_index = symbol_index };
814810 }
815811 return gop.value_ptr.symbol_index;
......@@ -820,9 +816,9 @@ fn getNavShdrIndex(
820816 elf_file: *Elf,
821817 zcu: *Zcu,
822818 nav_index: InternPool.Nav.Index,
819 sym_index: Symbol.Index,
823820 code: []const u8,
824821) error{OutOfMemory}!u32 {
825 _ = self;
826822 const ip = &zcu.intern_pool;
827823 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
828824 const nav_val = zcu.navValue(nav_index);
......@@ -832,10 +828,12 @@ fn getNavShdrIndex(
832828 .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none },
833829 else => .{ true, false, nav_val.toIntern() },
834830 };
831 const has_relocs = self.symbol(sym_index).atom(elf_file).?.relocs(elf_file).len > 0;
835832 if (any_non_single_threaded and is_threadlocal) {
836 for (code) |byte| {
837 if (byte != 0) break;
838 } else return elf_file.sectionByName(".tbss") orelse try elf_file.addSection(.{
833 const is_bss = !has_relocs and for (code) |byte| {
834 if (byte != 0) break false;
835 } else true;
836 if (is_bss) return elf_file.sectionByName(".tbss") orelse try elf_file.addSection(.{
839837 .type = elf.SHT_NOBITS,
840838 .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS,
841839 .name = try elf_file.insertShString(".tbss"),
......@@ -854,9 +852,10 @@ fn getNavShdrIndex(
854852 .Debug, .ReleaseSafe => elf_file.zig_data_section_index.?,
855853 .ReleaseFast, .ReleaseSmall => elf_file.zig_bss_section_index.?,
856854 };
857 for (code) |byte| {
858 if (byte != 0) break;
859 } else return elf_file.zig_bss_section_index.?;
855 const is_bss = !has_relocs and for (code) |byte| {
856 if (byte != 0) break false;
857 } else true;
858 if (is_bss) return elf_file.zig_bss_section_index.?;
860859 return elf_file.zig_data_section_index.?;
861860}
862861
......@@ -909,13 +908,6 @@ fn updateNavCode(
909908 if (old_vaddr != atom_ptr.value) {
910909 sym.value = 0;
911910 esym.st_value = 0;
912
913 if (!elf_file.base.isRelocatable()) {
914 log.debug(" (writing new offset table entry)", .{});
915 assert(sym.flags.has_zig_got);
916 const extra = sym.extra(elf_file);
917 try elf_file.zig_got.writeOne(elf_file, extra.zig_got);
918 }
919911 }
920912 } else if (code.len < old_size) {
921913 atom_ptr.shrink(elf_file);
......@@ -925,15 +917,11 @@ fn updateNavCode(
925917 errdefer self.freeNavMetadata(elf_file, sym_index);
926918
927919 sym.value = 0;
928 sym.flags.needs_zig_got = true;
929920 esym.st_value = 0;
930
931 if (!elf_file.base.isRelocatable()) {
932 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
933 try elf_file.zig_got.writeOne(elf_file, gop.index);
934 }
935921 }
936922
923 self.navs.getPtr(nav_index).?.allocated = true;
924
937925 if (elf_file.base.child_pid) |pid| {
938926 switch (builtin.os.tag) {
939927 .linux => {
......@@ -959,6 +947,7 @@ fn updateNavCode(
959947 if (shdr.sh_type != elf.SHT_NOBITS) {
960948 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
961949 try elf_file.base.file.?.pwriteAll(code, file_offset);
950 log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });
962951 }
963952}
964953
......@@ -1001,6 +990,8 @@ fn updateTlv(
1001990 atom_ptr.alignment = required_alignment;
1002991 atom_ptr.size = code.len;
1003992
993 self.navs.getPtr(nav_index).?.allocated = true;
994
1004995 {
1005996 const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);
1006997 assert(!gop.found_existing); // TODO incremental updates
......@@ -1065,8 +1056,21 @@ pub fn updateFunc(
10651056 },
10661057 };
10671058
1068 const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, code);
1059 const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code);
1060 log.debug("setting shdr({x},{s}) for {}", .{
1061 shndx,
1062 elf_file.getShString(elf_file.shdrs.items[shndx].sh_name),
1063 ip.getNav(func.owner_nav).fqn.fmt(ip),
1064 });
1065 const old_rva, const old_alignment = blk: {
1066 const atom_ptr = self.symbol(sym_index).atom(elf_file).?;
1067 break :blk .{ atom_ptr.value, atom_ptr.alignment };
1068 };
10691069 try self.updateNavCode(elf_file, pt, func.owner_nav, sym_index, shndx, code, elf.STT_FUNC);
1070 const new_rva, const new_alignment = blk: {
1071 const atom_ptr = self.symbol(sym_index).atom(elf_file).?;
1072 break :blk .{ atom_ptr.value, atom_ptr.alignment };
1073 };
10701074
10711075 if (dwarf_state) |*ds| {
10721076 const sym = self.symbol(sym_index);
......@@ -1080,6 +1084,41 @@ pub fn updateFunc(
10801084 }
10811085
10821086 // Exports will be updated by `Zcu.processExports` after the update.
1087
1088 if (old_rva != new_rva and old_rva > 0) {
1089 // If we had to reallocate the function, we re-use the existing slot for a trampoline.
1090 // In the rare case that the function has been further overaligned we skip creating a
1091 // trampoline and update all symbols referring this function.
1092 if (old_alignment.order(new_alignment) == .lt) {
1093 @panic("TODO update all symbols referring this function");
1094 }
1095
1096 // Create a trampoline to the new location at `old_rva`.
1097 if (!self.symbol(sym_index).flags.has_trampoline) {
1098 const name = try std.fmt.allocPrint(gpa, "{s}$trampoline", .{
1099 self.symbol(sym_index).name(elf_file),
1100 });
1101 defer gpa.free(name);
1102 const name_off = try self.addString(gpa, name);
1103 const tr_size = trampolineSize(elf_file.getTarget().cpu.arch);
1104 const tr_sym_index = try self.newSymbolWithAtom(gpa, name_off);
1105 const tr_sym = self.symbol(tr_sym_index);
1106 const tr_esym = &self.symtab.items(.elf_sym)[tr_sym.esym_index];
1107 tr_esym.st_info |= elf.STT_OBJECT;
1108 tr_esym.st_size = tr_size;
1109 const tr_atom_ptr = tr_sym.atom(elf_file).?;
1110 tr_atom_ptr.value = old_rva;
1111 tr_atom_ptr.alive = true;
1112 tr_atom_ptr.alignment = old_alignment;
1113 tr_atom_ptr.output_section_index = elf_file.zig_text_section_index.?;
1114 tr_atom_ptr.size = tr_size;
1115 const target_sym = self.symbol(sym_index);
1116 target_sym.addExtra(.{ .trampoline = tr_sym_index }, elf_file);
1117 target_sym.flags.has_trampoline = true;
1118 }
1119 const target_sym = self.symbol(sym_index);
1120 try writeTrampoline(self.symbol(target_sym.extra(elf_file).trampoline).*, target_sym.*, elf_file);
1121 }
10831122}
10841123
10851124pub fn updateNav(
......@@ -1102,13 +1141,12 @@ pub fn updateNav(
11021141 .variable => |variable| Value.fromInterned(variable.init),
11031142 .@"extern" => |@"extern"| {
11041143 if (ip.isFunctionType(@"extern".ty)) return;
1105 // Extern variable gets a .got entry only.
11061144 const sym_index = try self.getGlobalSymbol(
11071145 elf_file,
11081146 nav.name.toSlice(ip),
11091147 @"extern".lib_name.toSlice(ip),
11101148 );
1111 self.symbol(sym_index).flags.needs_got = true;
1149 self.symbol(sym_index).flags.is_extern_ptr = true;
11121150 return;
11131151 },
11141152 else => nav_val,
......@@ -1142,7 +1180,12 @@ pub fn updateNav(
11421180 },
11431181 };
11441182
1145 const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, code);
1183 const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code);
1184 log.debug("setting shdr({x},{s}) for {}", .{
1185 shndx,
1186 elf_file.getShString(elf_file.shdrs.items[shndx].sh_name),
1187 nav.fqn.fmt(ip),
1188 });
11461189 if (elf_file.shdrs.items[shndx].sh_flags & elf.SHF_TLS != 0)
11471190 try self.updateTlv(elf_file, pt, nav_index, sym_index, shndx, code)
11481191 else
......@@ -1225,14 +1268,8 @@ fn updateLazySymbol(
12251268 errdefer self.freeNavMetadata(elf_file, symbol_index);
12261269
12271270 local_sym.value = 0;
1228 local_sym.flags.needs_zig_got = true;
12291271 local_esym.st_value = 0;
12301272
1231 if (!elf_file.base.isRelocatable()) {
1232 const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);
1233 try elf_file.zig_got.writeOne(elf_file, gop.index);
1234 }
1235
12361273 const shdr = elf_file.shdrs.items[output_section_index];
12371274 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
12381275 try elf_file.base.file.?.pwriteAll(code, file_offset);
......@@ -1440,6 +1477,52 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n
14401477 return lookup_gop.value_ptr.*;
14411478}
14421479
1480const max_trampoline_len = 12;
1481
1482fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {
1483 const len = switch (cpu_arch) {
1484 .x86_64 => 5, // jmp rel32
1485 else => @panic("TODO implement trampoline size for this CPU arch"),
1486 };
1487 comptime assert(len <= max_trampoline_len);
1488 return len;
1489}
1490
1491fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
1492 const atom_ptr = tr_sym.atom(elf_file).?;
1493 const shdr = elf_file.shdrs.items[atom_ptr.output_section_index];
1494 const fileoff = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
1495 const source_addr = tr_sym.address(.{}, elf_file);
1496 const target_addr = target.address(.{ .trampoline = false }, elf_file);
1497 var buf: [max_trampoline_len]u8 = undefined;
1498 const out = switch (elf_file.getTarget().cpu.arch) {
1499 .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
1500 else => @panic("TODO implement write trampoline for this CPU arch"),
1501 };
1502 try elf_file.base.file.?.pwriteAll(out, fileoff);
1503
1504 if (elf_file.base.child_pid) |pid| {
1505 switch (builtin.os.tag) {
1506 .linux => {
1507 var local_vec: [1]std.posix.iovec_const = .{.{
1508 .base = out.ptr,
1509 .len = out.len,
1510 }};
1511 var remote_vec: [1]std.posix.iovec_const = .{.{
1512 .base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(source_addr)))),
1513 .len = out.len,
1514 }};
1515 const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);
1516 switch (std.os.linux.E.init(rc)) {
1517 .SUCCESS => assert(rc == out.len),
1518 else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
1519 }
1520 },
1521 else => return error.HotSwapUnavailableOnHostOperatingSystem,
1522 }
1523 }
1524}
1525
14431526pub fn asFile(self: *ZigObject) File {
14441527 return .{ .zig_object = self };
14451528}
......@@ -1662,6 +1745,8 @@ const AvMetadata = struct {
16621745 symbol_index: Symbol.Index,
16631746 /// A list of all exports aliases of this Av.
16641747 exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
1748 /// Set to true if the AV has been initialized and allocated.
1749 allocated: bool = false,
16651750
16661751 fn @"export"(m: AvMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 {
16671752 for (m.exports.items) |*exp| {
......@@ -1672,6 +1757,32 @@ const AvMetadata = struct {
16721757 }
16731758};
16741759
1760fn checkNavAllocated(pt: Zcu.PerThread, index: InternPool.Nav.Index, meta: AvMetadata) void {
1761 if (!meta.allocated) {
1762 const zcu = pt.zcu;
1763 const ip = &zcu.intern_pool;
1764 const nav = ip.getNav(index);
1765 log.err("NAV {}({d}) assigned symbol {d} but not allocated!", .{
1766 nav.fqn.fmt(ip),
1767 index,
1768 meta.symbol_index,
1769 });
1770 }
1771}
1772
1773fn checkUavAllocated(pt: Zcu.PerThread, index: InternPool.Index, meta: AvMetadata) void {
1774 if (!meta.allocated) {
1775 const zcu = pt.zcu;
1776 const uav = Value.fromInterned(index);
1777 const ty = uav.typeOf(zcu);
1778 log.err("UAV {}({d}) assigned symbol {d} but not allocated!", .{
1779 ty.fmt(pt),
1780 index,
1781 meta.symbol_index,
1782 });
1783 }
1784}
1785
16751786const TlsVariable = struct {
16761787 symbol_index: Symbol.Index,
16771788 code: []const u8 = &[0]u8{},
......@@ -1682,12 +1793,26 @@ const TlsVariable = struct {
16821793};
16831794
16841795const AtomList = std.ArrayListUnmanaged(Atom.Index);
1685const NavTable = std.AutoHashMapUnmanaged(InternPool.Nav.Index, AvMetadata);
1686const UavTable = std.AutoHashMapUnmanaged(InternPool.Index, AvMetadata);
1796const NavTable = std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvMetadata);
1797const UavTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, AvMetadata);
16871798const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata);
16881799const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);
16891800
1801const x86_64 = struct {
1802 fn writeTrampolineCode(source_addr: i64, target_addr: i64, buf: *[max_trampoline_len]u8) ![]u8 {
1803 const disp = @as(i64, @intCast(target_addr)) - source_addr - 5;
1804 var bytes = [_]u8{
1805 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp rel32
1806 };
1807 assert(bytes.len == trampolineSize(.x86_64));
1808 mem.writeInt(i32, bytes[1..][0..4], @intCast(disp), .little);
1809 @memcpy(buf[0..bytes.len], &bytes);
1810 return buf[0..bytes.len];
1811 }
1812};
1813
16901814const assert = std.debug.assert;
1815const build_options = @import("build_options");
16911816const builtin = @import("builtin");
16921817const codegen = @import("../../codegen.zig");
16931818const elf = std.elf;
src/link/Elf/relocation.zig+5-13
......@@ -112,19 +112,11 @@ fn formatRelocType(
112112 _ = unused_fmt_string;
113113 _ = options;
114114 const r_type = ctx.r_type;
115 switch (r_type) {
116 Elf.R_ZIG_GOT32 => try writer.writeAll("R_ZIG_GOT32"),
117 Elf.R_ZIG_GOTPCREL => try writer.writeAll("R_ZIG_GOTPCREL"),
118 Elf.R_ZIG_GOT_HI20 => try writer.writeAll("R_ZIG_GOT_HI20"),
119 Elf.R_ZIG_GOT_LO12 => try writer.writeAll("R_ZIG_GOT_LO12"),
120 Elf.R_GOT_HI20_STATIC => try writer.writeAll("R_GOT_HI20_STATIC"),
121 Elf.R_GOT_LO12_I_STATIC => try writer.writeAll("R_GOT_LO12_I_STATIC"),
122 else => switch (ctx.cpu_arch) {
123 .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),
124 .aarch64 => try writer.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}),
125 .riscv64 => try writer.print("R_RISCV_{s}", .{@tagName(@as(elf.R_RISCV, @enumFromInt(r_type)))}),
126 else => unreachable,
127 },
115 switch (ctx.cpu_arch) {
116 .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),
117 .aarch64 => try writer.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}),
118 .riscv64 => try writer.print("R_RISCV_{s}", .{@tagName(@as(elf.R_RISCV, @enumFromInt(r_type)))}),
119 else => unreachable,
128120 }
129121}
130122
src/link/Elf/synthetic_sections.zig-209
......@@ -223,215 +223,6 @@ pub const DynamicSection = struct {
223223 }
224224};
225225
226pub const ZigGotSection = struct {
227 entries: std.ArrayListUnmanaged(Symbol.Index) = .{},
228 output_symtab_ctx: Elf.SymtabCtx = .{},
229 flags: Flags = .{},
230
231 const Flags = packed struct {
232 needs_rela: bool = false,
233 dirty: bool = false,
234 };
235
236 pub const Index = u32;
237
238 pub fn deinit(zig_got: *ZigGotSection, allocator: Allocator) void {
239 zig_got.entries.deinit(allocator);
240 }
241
242 fn allocateEntry(zig_got: *ZigGotSection, allocator: Allocator) !Index {
243 try zig_got.entries.ensureUnusedCapacity(allocator, 1);
244 // TODO add free list
245 const index = @as(Index, @intCast(zig_got.entries.items.len));
246 _ = zig_got.entries.addOneAssumeCapacity();
247 zig_got.flags.dirty = true;
248 return index;
249 }
250
251 pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {
252 const comp = elf_file.base.comp;
253 const gpa = comp.gpa;
254 const zo = elf_file.zigObjectPtr().?;
255 const index = try zig_got.allocateEntry(gpa);
256 const entry = &zig_got.entries.items[index];
257 entry.* = sym_index;
258 const symbol = zo.symbol(sym_index);
259 symbol.flags.has_zig_got = true;
260 if (elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) {
261 zig_got.flags.needs_rela = true;
262 }
263 symbol.addExtra(.{ .zig_got = index }, elf_file);
264 return index;
265 }
266
267 pub fn entryOffset(zig_got: ZigGotSection, index: Index, elf_file: *Elf) u64 {
268 _ = zig_got;
269 const entry_size = elf_file.archPtrWidthBytes();
270 const shdr = elf_file.shdrs.items[elf_file.zig_got_section_index.?];
271 return shdr.sh_offset + @as(u64, entry_size) * index;
272 }
273
274 pub fn entryAddress(zig_got: ZigGotSection, index: Index, elf_file: *Elf) i64 {
275 _ = zig_got;
276 const entry_size = elf_file.archPtrWidthBytes();
277 const shdr = elf_file.shdrs.items[elf_file.zig_got_section_index.?];
278 return @as(i64, @intCast(shdr.sh_addr)) + entry_size * index;
279 }
280
281 pub fn size(zig_got: ZigGotSection, elf_file: *Elf) usize {
282 return elf_file.archPtrWidthBytes() * zig_got.entries.items.len;
283 }
284
285 pub fn writeOne(zig_got: *ZigGotSection, elf_file: *Elf, index: Index) !void {
286 const zo = elf_file.zigObjectPtr().?;
287 if (zig_got.flags.dirty) {
288 const needed_size = zig_got.size(elf_file);
289 try elf_file.growAllocSection(elf_file.zig_got_section_index.?, needed_size);
290 zig_got.flags.dirty = false;
291 }
292 const entry_size: u16 = elf_file.archPtrWidthBytes();
293 const target = elf_file.getTarget();
294 const endian = target.cpu.arch.endian();
295 const off = zig_got.entryOffset(index, elf_file);
296 const vaddr: u64 = @intCast(zig_got.entryAddress(index, elf_file));
297 const entry = zig_got.entries.items[index];
298 const value = zo.symbol(entry).address(.{}, elf_file);
299 switch (entry_size) {
300 2 => {
301 var buf: [2]u8 = undefined;
302 std.mem.writeInt(u16, &buf, @intCast(value), endian);
303 try elf_file.base.file.?.pwriteAll(&buf, off);
304 },
305 4 => {
306 var buf: [4]u8 = undefined;
307 std.mem.writeInt(u32, &buf, @intCast(value), endian);
308 try elf_file.base.file.?.pwriteAll(&buf, off);
309 },
310 8 => {
311 var buf: [8]u8 = undefined;
312 std.mem.writeInt(u64, &buf, @intCast(value), endian);
313 try elf_file.base.file.?.pwriteAll(&buf, off);
314
315 if (elf_file.base.child_pid) |pid| {
316 switch (builtin.os.tag) {
317 .linux => {
318 var local_vec: [1]std.posix.iovec_const = .{.{
319 .base = &buf,
320 .len = buf.len,
321 }};
322 var remote_vec: [1]std.posix.iovec_const = .{.{
323 .base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(vaddr)))),
324 .len = buf.len,
325 }};
326 const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);
327 switch (std.os.linux.E.init(rc)) {
328 .SUCCESS => assert(rc == buf.len),
329 else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
330 }
331 },
332 else => return error.HotSwapUnavailableOnHostOperatingSystem,
333 }
334 }
335 },
336 else => unreachable,
337 }
338 }
339
340 pub fn writeAll(zig_got: ZigGotSection, elf_file: *Elf, writer: anytype) !void {
341 const zo = elf_file.zigObjectPtr().?;
342 for (zig_got.entries.items) |entry| {
343 const symbol = zo.symbol(entry);
344 const value = symbol.address(.{ .plt = false }, elf_file);
345 try writeInt(value, elf_file, writer);
346 }
347 }
348
349 pub fn numRela(zig_got: ZigGotSection) usize {
350 return zig_got.entries.items.len;
351 }
352
353 pub fn addRela(zig_got: ZigGotSection, elf_file: *Elf) !void {
354 const comp = elf_file.base.comp;
355 const gpa = comp.gpa;
356 const cpu_arch = elf_file.getTarget().cpu.arch;
357 const zo = elf_file.zigObjectPtr().?;
358 try elf_file.rela_dyn.ensureUnusedCapacity(gpa, zig_got.numRela());
359 for (zig_got.entries.items) |entry| {
360 const symbol = zo.symbol(entry);
361 const offset = symbol.zigGotAddress(elf_file);
362 elf_file.addRelaDynAssumeCapacity(.{
363 .offset = @intCast(offset),
364 .type = relocation.encode(.rel, cpu_arch),
365 .addend = symbol.address(.{ .plt = false }, elf_file),
366 });
367 }
368 }
369
370 pub fn updateSymtabSize(zig_got: *ZigGotSection, elf_file: *Elf) void {
371 const zo = elf_file.zigObjectPtr().?;
372 zig_got.output_symtab_ctx.nlocals = @as(u32, @intCast(zig_got.entries.items.len));
373 for (zig_got.entries.items) |entry| {
374 const name = zo.symbol(entry).name(elf_file);
375 zig_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$ziggot".len)) + 1;
376 }
377 }
378
379 pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf) void {
380 const zo = elf_file.zigObjectPtr().?;
381 for (zig_got.entries.items, zig_got.output_symtab_ctx.ilocal.., 0..) |entry, ilocal, index| {
382 const symbol = zo.symbol(entry);
383 const symbol_name = symbol.name(elf_file);
384 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
385 elf_file.strtab.appendSliceAssumeCapacity(symbol_name);
386 elf_file.strtab.appendSliceAssumeCapacity("$ziggot");
387 elf_file.strtab.appendAssumeCapacity(0);
388 const st_value = zig_got.entryAddress(@intCast(index), elf_file);
389 const st_size = elf_file.archPtrWidthBytes();
390 elf_file.symtab.items[ilocal] = .{
391 .st_name = st_name,
392 .st_info = elf.STT_OBJECT,
393 .st_other = 0,
394 .st_shndx = @intCast(elf_file.zig_got_section_index.?),
395 .st_value = @intCast(st_value),
396 .st_size = st_size,
397 };
398 }
399 }
400
401 const FormatCtx = struct {
402 zig_got: ZigGotSection,
403 elf_file: *Elf,
404 };
405
406 pub fn fmt(zig_got: ZigGotSection, elf_file: *Elf) std.fmt.Formatter(format2) {
407 return .{ .data = .{ .zig_got = zig_got, .elf_file = elf_file } };
408 }
409
410 pub fn format2(
411 ctx: FormatCtx,
412 comptime unused_fmt_string: []const u8,
413 options: std.fmt.FormatOptions,
414 writer: anytype,
415 ) !void {
416 _ = options;
417 _ = unused_fmt_string;
418 const zig_got = ctx.zig_got;
419 const elf_file = ctx.elf_file;
420 try writer.writeAll(".zig.got\n");
421 for (zig_got.entries.items, 0..) |entry, index| {
422 const zo = elf_file.zigObjectPtr().?;
423 const symbol = zo.symbol(entry);
424 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
425 index,
426 zig_got.entryAddress(@intCast(index), elf_file),
427 entry,
428 symbol.address(.{}, elf_file),
429 symbol.name(elf_file),
430 });
431 }
432 }
433};
434
435226pub const GotSection = struct {
436227 entries: std.ArrayListUnmanaged(Entry) = .{},
437228 output_symtab_ctx: Elf.SymtabCtx = .{},
test/behavior/basic.zig-1
......@@ -733,7 +733,6 @@ test "extern variable with non-pointer opaque type" {
733733 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
734734 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
735735 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
736 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
737736
738737 @export(var_to_export, .{ .name = "opaque_extern_var" });
739738 try expect(@as(*align(1) u32, @ptrCast(&opaque_extern_var)).* == 42);
test/behavior/export_builtin.zig-2
......@@ -48,7 +48,6 @@ test "exporting using field access" {
4848test "exporting comptime-known value" {
4949 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
5050 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
51 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
5251 if (builtin.zig_backend == .stage2_x86_64 and
5352 (builtin.target.ofmt != .elf and
5453 builtin.target.ofmt != .macho and
......@@ -68,7 +67,6 @@ test "exporting comptime-known value" {
6867test "exporting comptime var" {
6968 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
7069 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7270 if (builtin.zig_backend == .stage2_x86_64 and
7371 (builtin.target.ofmt != .elf and
7472 builtin.target.ofmt != .macho and
test/behavior/extern.zig-1
......@@ -7,7 +7,6 @@ test "anyopaque extern symbol" {
77 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
88 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1110
1211 const a = @extern(*anyopaque, .{ .name = "a_mystery_symbol" });
1312 const b: *i32 = @alignCast(@ptrCast(a));
test/behavior/fn.zig-1
......@@ -429,7 +429,6 @@ test "implicit cast function to function ptr" {
429429 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
430430 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
431431 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
432 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
433432
434433 const S1 = struct {
435434 export fn someFunctionThatReturnsAValue() c_int {
test/behavior/pointers.zig-1
......@@ -45,7 +45,6 @@ test "pointer-integer arithmetic" {
4545
4646test "pointer subtraction" {
4747 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4948
5049 {
5150 const a: *u8 = @ptrFromInt(100);
test/link/elf.zig+20-4
......@@ -1773,25 +1773,41 @@ fn testImportingDataDynamic(b: *Build, opts: Options) *Step {
17731773 .use_llvm = true,
17741774 }, .{
17751775 .name = "a",
1776 .c_source_bytes = "int foo = 42;",
1776 .c_source_bytes =
1777 \\#include <stdio.h>
1778 \\int foo = 42;
1779 \\void printFoo() { fprintf(stderr, "lib foo=%d\n", foo); }
1780 ,
17771781 });
1782 dso.linkLibC();
17781783
17791784 const main = addExecutable(b, opts, .{
17801785 .name = "main",
17811786 .zig_source_bytes =
1787 \\const std = @import("std");
17821788 \\extern var foo: i32;
1789 \\extern fn printFoo() void;
17831790 \\pub fn main() void {
1784 \\ @import("std").debug.print("{d}\n", .{foo});
1791 \\ std.debug.print("exe foo={d}\n", .{foo});
1792 \\ printFoo();
1793 \\ foo += 1;
1794 \\ std.debug.print("exe foo={d}\n", .{foo});
1795 \\ printFoo();
17851796 \\}
17861797 ,
17871798 .strip = true, // TODO temp hack
17881799 });
17891800 main.pie = true;
17901801 main.linkLibrary(dso);
1791 main.linkLibC();
17921802
17931803 const run = addRunArtifact(main);
1794 run.expectStdErrEqual("42\n");
1804 run.expectStdErrEqual(
1805 \\exe foo=42
1806 \\lib foo=42
1807 \\exe foo=43
1808 \\lib foo=43
1809 \\
1810 );
17951811 test_step.dependOn(&run.step);
17961812
17971813 return test_step;