authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-25 21:53:46+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-25 21:59:19+01:00
loge0f5627d4a9cb1b3a1361d70d40043c8c170b2af
treec46515f91973faaf597ab9758743bd2190652a2e
parent4b14384989362f93cd014628810c63b5cd9d3fff

x64+aarch64: check for pointer to zero-bit type when lowering decl

Unless the pointer is a pointer to a function, if the pointee type has zero-bits, we need to return `MCValue.none` as the `Decl` has not been lowered to memory, and therefore, any GOT reference will be wrong.

6 files changed, 27 insertions(+), 4 deletions(-)

src/arch/aarch64/CodeGen.zig+10
...@@ -3550,6 +3550,15 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -3550,6 +3550,15 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
3550fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {3550fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
3551 const ptr_bits = self.target.cpu.arch.ptrBitWidth();3551 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3552 const ptr_bytes: u64 = @divExact(ptr_bits, 8);3552 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
3553
3554 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
3555 if (tv.ty.zigTypeTag() == .Pointer) blk: {
3556 if (tv.ty.castPtrToFn()) |_| break :blk;
3557 if (!tv.ty.elemType2().hasRuntimeBits()) {
3558 return MCValue.none;
3559 }
3560 }
3561
3553 decl.alive = true;3562 decl.alive = true;
3554 if (self.bin_file.cast(link.File.Elf)) |elf_file| {3563 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3555 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];3564 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
...@@ -3558,6 +3567,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa...@@ -3558,6 +3567,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa
3558 } else if (self.bin_file.cast(link.File.MachO)) |_| {3567 } else if (self.bin_file.cast(link.File.MachO)) |_| {
3559 // Because MachO is PIE-always-on, we defer memory address resolution until3568 // Because MachO is PIE-always-on, we defer memory address resolution until
3560 // the linker has enough info to perform relocations.3569 // the linker has enough info to perform relocations.
3570 assert(decl.link.macho.local_sym_index != 0);
3561 return MCValue{ .got_load = decl.link.macho.local_sym_index };3571 return MCValue{ .got_load = decl.link.macho.local_sym_index };
3562 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {3572 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
3563 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;3573 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
src/arch/x86_64/CodeGen.zig+9
...@@ -5333,6 +5333,14 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa...@@ -5333,6 +5333,14 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa
5333 const ptr_bits = self.target.cpu.arch.ptrBitWidth();5333 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
5334 const ptr_bytes: u64 = @divExact(ptr_bits, 8);5334 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
53355335
5336 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
5337 if (tv.ty.zigTypeTag() == .Pointer) blk: {
5338 if (tv.ty.castPtrToFn()) |_| break :blk;
5339 if (!tv.ty.elemType2().hasRuntimeBits()) {
5340 return MCValue.none;
5341 }
5342 }
5343
5336 decl.alive = true;5344 decl.alive = true;
5337 if (self.bin_file.cast(link.File.Elf)) |elf_file| {5345 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
5338 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];5346 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
...@@ -5341,6 +5349,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa...@@ -5341,6 +5349,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa
5341 } else if (self.bin_file.cast(link.File.MachO)) |_| {5349 } else if (self.bin_file.cast(link.File.MachO)) |_| {
5342 // Because MachO is PIE-always-on, we defer memory address resolution until5350 // Because MachO is PIE-always-on, we defer memory address resolution until
5343 // the linker has enough info to perform relocations.5351 // the linker has enough info to perform relocations.
5352 assert(decl.link.macho.local_sym_index != 0);
5344 return MCValue{ .got_load = decl.link.macho.local_sym_index };5353 return MCValue{ .got_load = decl.link.macho.local_sym_index };
5345 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {5354 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
5346 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;5355 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
src/arch/x86_64/Emit.zig+1
...@@ -857,6 +857,7 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -857,6 +857,7 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
857 else => return emit.fail("TODO unused LEA PIE variants 0b10 and 0b11", .{}),857 else => return emit.fail("TODO unused LEA PIE variants 0b10 and 0b11", .{}),
858 };858 };
859 const atom = macho_file.atom_by_index_table.get(load_reloc.atom_index).?;859 const atom = macho_file.atom_by_index_table.get(load_reloc.atom_index).?;
860 log.debug("adding reloc of type {} to local @{d}", .{ reloc_type, load_reloc.sym_index });
860 try atom.relocs.append(emit.bin_file.allocator, .{861 try atom.relocs.append(emit.bin_file.allocator, .{
861 .offset = @intCast(u32, end_offset - 4),862 .offset = @intCast(u32, end_offset - 4),
862 .target = .{ .local = load_reloc.sym_index },863 .target = .{ .local = load_reloc.sym_index },
src/link/MachO.zig+7
...@@ -4286,6 +4286,7 @@ pub fn deleteExport(self: *MachO, exp: Export) void {...@@ -4286,6 +4286,7 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
4286}4286}
42874287
4288fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void {4288fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void {
4289 log.debug("freeUnnamedConsts for decl {*}", .{decl});
4289 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl) orelse return;4290 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl) orelse return;
4290 for (unnamed_consts.items) |atom| {4291 for (unnamed_consts.items) |atom| {
4291 self.freeAtom(atom, .{4292 self.freeAtom(atom, .{
...@@ -4295,6 +4296,7 @@ fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void {...@@ -4295,6 +4296,7 @@ fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void {
4295 self.locals_free_list.append(self.base.allocator, atom.local_sym_index) catch {};4296 self.locals_free_list.append(self.base.allocator, atom.local_sym_index) catch {};
4296 self.locals.items[atom.local_sym_index].n_type = 0;4297 self.locals.items[atom.local_sym_index].n_type = 0;
4297 _ = self.atom_by_index_table.remove(atom.local_sym_index);4298 _ = self.atom_by_index_table.remove(atom.local_sym_index);
4299 log.debug(" adding local symbol index {d} to free list", .{atom.local_sym_index});
4298 atom.local_sym_index = 0;4300 atom.local_sym_index = 0;
4299 }4301 }
4300 unnamed_consts.clearAndFree(self.base.allocator);4302 unnamed_consts.clearAndFree(self.base.allocator);
...@@ -4319,10 +4321,15 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {...@@ -4319,10 +4321,15 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
4319 self.got_entries_free_list.append(self.base.allocator, @intCast(u32, got_index)) catch {};4321 self.got_entries_free_list.append(self.base.allocator, @intCast(u32, got_index)) catch {};
4320 self.got_entries.items[got_index] = .{ .target = .{ .local = 0 }, .atom = undefined };4322 self.got_entries.items[got_index] = .{ .target = .{ .local = 0 }, .atom = undefined };
4321 _ = self.got_entries_table.swapRemove(.{ .local = decl.link.macho.local_sym_index });4323 _ = self.got_entries_table.swapRemove(.{ .local = decl.link.macho.local_sym_index });
4324 log.debug(" adding GOT index {d} to free list (target local@{d})", .{
4325 got_index,
4326 decl.link.macho.local_sym_index,
4327 });
4322 }4328 }
43234329
4324 self.locals.items[decl.link.macho.local_sym_index].n_type = 0;4330 self.locals.items[decl.link.macho.local_sym_index].n_type = 0;
4325 _ = self.atom_by_index_table.remove(decl.link.macho.local_sym_index);4331 _ = self.atom_by_index_table.remove(decl.link.macho.local_sym_index);
4332 log.debug(" adding local symbol index {d} to free list", .{decl.link.macho.local_sym_index});
4326 decl.link.macho.local_sym_index = 0;4333 decl.link.macho.local_sym_index = 0;
4327 }4334 }
4328 if (self.d_sym) |*d_sym| {4335 if (self.d_sym) |*d_sym| {
test/behavior/basic.zig-2
...@@ -399,8 +399,6 @@ fn testTakeAddressOfParameter(f: f32) !void {...@@ -399,8 +399,6 @@ fn testTakeAddressOfParameter(f: f32) !void {
399399
400test "pointer to void return type" {400test "pointer to void return type" {
401 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO401 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
402 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
403 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest;
404402
405 try testPointerToVoidReturnType();403 try testPointerToVoidReturnType();
406}404}
test/behavior/struct.zig-2
...@@ -370,8 +370,6 @@ test "empty struct method call" {...@@ -370,8 +370,6 @@ test "empty struct method call" {
370 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO370 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
371 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO371 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
372 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO372 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
373 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; // TODO
374 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest; // TODO
375373
376 const es = EmptyStruct{};374 const es = EmptyStruct{};
377 try expect(es.method() == 1234);375 try expect(es.method() == 1234);