authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-09 18:12:37+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-09 18:12:37+01:00
log2d3914213378f560fafb9a952cb1ad03a11aa634
tree0366b7da81517db151e2b20490cd787e0479ec45
parent4d1e5ef730630badf92a613cdc57a42d2321df12
parentec3e638b97c638a6d292902b18a6a685854d60b4
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10843 from ziglang/fix-1914

stage2: handle decl ref to void types

5 files changed, 66 insertions(+), 30 deletions(-)

lib/std/special/c.zig+20
......@@ -6,7 +6,9 @@
66
77const std = @import("std");
88const builtin = @import("builtin");
9const math = std.math;
910const native_os = builtin.os.tag;
11const long_double_is_f128 = builtin.target.longDoubleIsF128();
1012
1113comptime {
1214 // When the self-hosted compiler is further along, all the logic from c_stage1.zig will
......@@ -15,6 +17,9 @@ comptime {
1517 if (builtin.zig_backend != .stage1) {
1618 @export(memset, .{ .name = "memset", .linkage = .Strong });
1719 @export(memcpy, .{ .name = "memcpy", .linkage = .Strong });
20 @export(trunc, .{ .name = "trunc", .linkage = .Strong });
21 @export(truncf, .{ .name = "truncf", .linkage = .Strong });
22 @export(truncl, .{ .name = "truncl", .linkage = .Strong });
1823 } else {
1924 _ = @import("c_stage1.zig");
2025 }
......@@ -74,3 +79,18 @@ fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(
7479
7580 return dest;
7681}
82
83fn trunc(a: f64) f64 {
84 return math.trunc(a);
85}
86
87fn truncf(a: f32) f32 {
88 return math.trunc(a);
89}
90
91fn truncl(a: c_longdouble) c_longdouble {
92 if (!long_double_is_f128) {
93 @panic("TODO implement this");
94 }
95 return math.trunc(a);
96}
src/Sema.zig+1
......@@ -13647,6 +13647,7 @@ fn structFieldPtr(
1364713647 assert(unresolved_struct_ty.zigTypeTag() == .Struct);
1364813648
1364913649 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
13650 try sema.resolveStructLayout(block, src, struct_ty);
1365013651 const struct_obj = struct_ty.castTag(.@"struct").?.data;
1365113652
1365213653 const field_index_big = struct_obj.fields.getIndex(field_name) orelse
src/codegen.zig+6-11
......@@ -487,19 +487,14 @@ fn lowerDeclRef(
487487 return Result{ .appended = {} };
488488 }
489489
490 const target = bin_file.options.target;
491 const ptr_width = target.cpu.arch.ptrBitWidth();
490492 const is_fn_body = decl.ty.zigTypeTag() == .Fn;
491493 if (!is_fn_body and !decl.ty.hasRuntimeBits()) {
492 return Result{
493 .fail = try ErrorMsg.create(
494 bin_file.allocator,
495 src_loc,
496 "TODO handle void types when lowering decl ref",
497 .{},
498 ),
499 };
494 try code.writer().writeByteNTimes(0xaa, @divExact(ptr_width, 8));
495 return Result{ .appended = {} };
500496 }
501497
502 if (decl.analysis != .complete) return error.AnalysisFail;
503498 decl.markAlive();
504499 const vaddr = vaddr: {
505500 if (bin_file.cast(link.File.MachO)) |macho_file| {
......@@ -510,8 +505,8 @@ fn lowerDeclRef(
510505 break :vaddr bin_file.getDeclVAddr(decl);
511506 };
512507
513 const endian = bin_file.options.target.cpu.arch.endian();
514 switch (bin_file.options.target.cpu.arch.ptrBitWidth()) {
508 const endian = target.cpu.arch.endian();
509 switch (ptr_width) {
515510 16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(u16, vaddr), endian),
516511 32 => mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, vaddr), endian),
517512 64 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian),
src/link/Elf.zig+39-15
......@@ -2,6 +2,7 @@ const Elf = @This();
22
33const std = @import("std");
44const builtin = @import("builtin");
5const math = std.math;
56const mem = std.mem;
67const assert = std.debug.assert;
78const Allocator = std.mem.Allocator;
......@@ -64,6 +65,7 @@ phdr_load_rw_index: ?u16 = null,
6465phdr_shdr_table: std.AutoHashMapUnmanaged(u16, u16) = .{},
6566
6667entry_addr: ?u64 = null,
68page_size: u16,
6769
6870debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){},
6971shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){},
......@@ -334,6 +336,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
334336 };
335337 const self = try gpa.create(Elf);
336338 errdefer gpa.destroy(self);
339 const page_size: u16 = 0x1000; // TODO ppc64le requires 64KB
337340
338341 self.* = .{
339342 .base = .{
......@@ -343,6 +346,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
343346 .file = null,
344347 },
345348 .ptr_width = ptr_width,
349 .page_size = page_size,
346350 };
347351 const use_llvm = build_options.have_llvm and options.use_llvm;
348352 const use_stage1 = build_options.is_stage1 and options.use_stage1;
......@@ -523,10 +527,11 @@ pub fn populateMissingMetadata(self: *Elf) !void {
523527 .p64 => false,
524528 };
525529 const ptr_size: u8 = self.ptrWidthBytes();
530
526531 if (self.phdr_load_re_index == null) {
527532 self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len);
528533 const file_size = self.base.options.program_code_size_hint;
529 const p_align = 0x1000;
534 const p_align = self.page_size;
530535 const off = self.findFreeSpace(file_size, p_align);
531536 log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size });
532537 const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr;
......@@ -544,12 +549,13 @@ pub fn populateMissingMetadata(self: *Elf) !void {
544549 self.entry_addr = null;
545550 self.phdr_table_dirty = true;
546551 }
552
547553 if (self.phdr_got_index == null) {
548554 self.phdr_got_index = @intCast(u16, self.program_headers.items.len);
549555 const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint;
550556 // We really only need ptr alignment but since we are using PROGBITS, linux requires
551557 // page align.
552 const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size);
558 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);
553559 const off = self.findFreeSpace(file_size, p_align);
554560 log.debug("found PT_LOAD GOT free space 0x{x} to 0x{x}", .{ off, off + file_size });
555561 // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at.
......@@ -568,16 +574,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {
568574 });
569575 self.phdr_table_dirty = true;
570576 }
577
571578 if (self.phdr_load_ro_index == null) {
572579 self.phdr_load_ro_index = @intCast(u16, self.program_headers.items.len);
573580 // TODO Find a hint about how much data need to be in rodata ?
574581 const file_size = 1024;
575582 // Same reason as for GOT
576 const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size);
583 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);
577584 const off = self.findFreeSpace(file_size, p_align);
578 log.debug("found PT_LOAD RO free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
585 log.debug("found PT_LOAD RO free space 0x{x} to 0x{x}", .{ off, off + file_size });
579586 // TODO Same as for GOT
580 const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x5000000 else 0xa000;
587 const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0xc000000 else 0xa000;
581588 try self.program_headers.append(self.base.allocator, .{
582589 .p_type = elf.PT_LOAD,
583590 .p_offset = off,
......@@ -591,16 +598,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {
591598 try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_ro_index.?, .{});
592599 self.phdr_table_dirty = true;
593600 }
601
594602 if (self.phdr_load_rw_index == null) {
595603 self.phdr_load_rw_index = @intCast(u16, self.program_headers.items.len);
596604 // TODO Find a hint about how much data need to be in data ?
597605 const file_size = 1024;
598606 // Same reason as for GOT
599 const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size);
607 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);
600608 const off = self.findFreeSpace(file_size, p_align);
601 log.debug("found PT_LOAD RW free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
609 log.debug("found PT_LOAD RW free space 0x{x} to 0x{x}", .{ off, off + file_size });
602610 // TODO Same as for GOT
603 const rwdata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x6000000 else 0xc000;
611 const rwdata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x10000000 else 0xc000;
604612 try self.program_headers.append(self.base.allocator, .{
605613 .p_type = elf.PT_LOAD,
606614 .p_offset = off,
......@@ -614,6 +622,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
614622 try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_rw_index.?, .{});
615623 self.phdr_table_dirty = true;
616624 }
625
617626 if (self.shstrtab_index == null) {
618627 self.shstrtab_index = @intCast(u16, self.sections.items.len);
619628 assert(self.shstrtab.items.len == 0);
......@@ -635,6 +644,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
635644 self.shstrtab_dirty = true;
636645 self.shdr_table_dirty = true;
637646 }
647
638648 if (self.text_section_index == null) {
639649 self.text_section_index = @intCast(u16, self.sections.items.len);
640650 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
......@@ -648,7 +658,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
648658 .sh_size = phdr.p_filesz,
649659 .sh_link = 0,
650660 .sh_info = 0,
651 .sh_addralign = phdr.p_align,
661 .sh_addralign = 1,
652662 .sh_entsize = 0,
653663 });
654664 try self.phdr_shdr_table.putNoClobber(
......@@ -658,6 +668,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
658668 );
659669 self.shdr_table_dirty = true;
660670 }
671
661672 if (self.got_section_index == null) {
662673 self.got_section_index = @intCast(u16, self.sections.items.len);
663674 const phdr = &self.program_headers.items[self.phdr_got_index.?];
......@@ -671,7 +682,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
671682 .sh_size = phdr.p_filesz,
672683 .sh_link = 0,
673684 .sh_info = 0,
674 .sh_addralign = phdr.p_align,
685 .sh_addralign = @as(u16, ptr_size),
675686 .sh_entsize = 0,
676687 });
677688 try self.phdr_shdr_table.putNoClobber(
......@@ -681,6 +692,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
681692 );
682693 self.shdr_table_dirty = true;
683694 }
695
684696 if (self.rodata_section_index == null) {
685697 self.rodata_section_index = @intCast(u16, self.sections.items.len);
686698 const phdr = &self.program_headers.items[self.phdr_load_ro_index.?];
......@@ -694,7 +706,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
694706 .sh_size = phdr.p_filesz,
695707 .sh_link = 0,
696708 .sh_info = 0,
697 .sh_addralign = phdr.p_align,
709 .sh_addralign = 1,
698710 .sh_entsize = 0,
699711 });
700712 try self.phdr_shdr_table.putNoClobber(
......@@ -704,6 +716,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
704716 );
705717 self.shdr_table_dirty = true;
706718 }
719
707720 if (self.data_section_index == null) {
708721 self.data_section_index = @intCast(u16, self.sections.items.len);
709722 const phdr = &self.program_headers.items[self.phdr_load_rw_index.?];
......@@ -717,7 +730,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
717730 .sh_size = phdr.p_filesz,
718731 .sh_link = 0,
719732 .sh_info = 0,
720 .sh_addralign = phdr.p_align,
733 .sh_addralign = @as(u16, ptr_size),
721734 .sh_entsize = 0,
722735 });
723736 try self.phdr_shdr_table.putNoClobber(
......@@ -727,6 +740,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
727740 );
728741 self.shdr_table_dirty = true;
729742 }
743
730744 if (self.symtab_section_index == null) {
731745 self.symtab_section_index = @intCast(u16, self.sections.items.len);
732746 const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);
......@@ -751,6 +765,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
751765 self.shdr_table_dirty = true;
752766 try self.writeSymbol(0);
753767 }
768
754769 if (self.debug_str_section_index == null) {
755770 self.debug_str_section_index = @intCast(u16, self.sections.items.len);
756771 assert(self.debug_strtab.items.len == 0);
......@@ -769,6 +784,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
769784 self.debug_strtab_dirty = true;
770785 self.shdr_table_dirty = true;
771786 }
787
772788 if (self.debug_info_section_index == null) {
773789 self.debug_info_section_index = @intCast(u16, self.sections.items.len);
774790
......@@ -794,6 +810,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
794810 self.shdr_table_dirty = true;
795811 self.debug_info_header_dirty = true;
796812 }
813
797814 if (self.debug_abbrev_section_index == null) {
798815 self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len);
799816
......@@ -819,6 +836,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
819836 self.shdr_table_dirty = true;
820837 self.debug_abbrev_section_dirty = true;
821838 }
839
822840 if (self.debug_aranges_section_index == null) {
823841 self.debug_aranges_section_index = @intCast(u16, self.sections.items.len);
824842
......@@ -844,6 +862,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
844862 self.shdr_table_dirty = true;
845863 self.debug_aranges_section_dirty = true;
846864 }
865
847866 if (self.debug_line_section_index == null) {
848867 self.debug_line_section_index = @intCast(u16, self.sections.items.len);
849868
......@@ -869,6 +888,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
869888 self.shdr_table_dirty = true;
870889 self.debug_line_header_dirty = true;
871890 }
891
872892 const shsize: u64 = switch (self.ptr_width) {
873893 .p32 => @sizeOf(elf.Elf32_Shdr),
874894 .p64 => @sizeOf(elf.Elf64_Shdr),
......@@ -881,6 +901,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
881901 self.shdr_table_offset = self.findFreeSpace(self.sections.items.len * shsize, shalign);
882902 self.shdr_table_dirty = true;
883903 }
904
884905 const phsize: u64 = switch (self.ptr_width) {
885906 .p32 => @sizeOf(elf.Elf32_Phdr),
886907 .p64 => @sizeOf(elf.Elf64_Phdr),
......@@ -893,6 +914,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
893914 self.phdr_table_offset = self.findFreeSpace(self.program_headers.items.len * phsize, phalign);
894915 self.phdr_table_dirty = true;
895916 }
917
896918 {
897919 // Iterate over symbols, populating free_list and last_text_block.
898920 if (self.local_symbols.items.len != 1) {
......@@ -2378,12 +2400,13 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
23782400 const text_capacity = self.allocatedSize(shdr.sh_offset);
23792401 const needed_size = (vaddr + new_block_size) - phdr.p_vaddr;
23802402 if (needed_size > text_capacity) {
2381 // Must move the entire text section.
2382 const new_offset = self.findFreeSpace(needed_size, 0x1000);
2403 // Must move the entire section.
2404 const new_offset = self.findFreeSpace(needed_size, self.page_size);
23832405 const text_size = if (self.atoms.get(phdr_index)) |last| blk: {
23842406 const sym = self.local_symbols.items[last.local_sym_index];
23852407 break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr;
23862408 } else 0;
2409 log.debug("new PT_LOAD file offset 0x{x} to 0x{x}", .{ new_offset, new_offset + text_size });
23872410 const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, text_size);
23882411 if (amt != text_size) return error.InputOutput;
23892412 shdr.sh_offset = new_offset;
......@@ -2407,6 +2430,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
24072430 self.phdr_table_dirty = true; // TODO look into making only the one program header dirty
24082431 self.shdr_table_dirty = true; // TODO look into making only the one section dirty
24092432 }
2433 shdr.sh_addralign = math.max(shdr.sh_addralign, alignment);
24102434
24112435 // This function can also reallocate a text block.
24122436 // In this case we need to "unplug" it from its previous location before
......@@ -3478,7 +3502,7 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void {
34783502 const needed_size = self.offset_table.items.len * entry_size;
34793503 if (needed_size > allocated_size) {
34803504 // Must move the entire got section.
3481 const new_offset = self.findFreeSpace(needed_size, entry_size);
3505 const new_offset = self.findFreeSpace(needed_size, self.page_size);
34823506 const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, shdr.sh_size);
34833507 if (amt != shdr.sh_size) return error.InputOutput;
34843508 shdr.sh_offset = new_offset;
test/behavior/bugs/1914.zig-4
......@@ -13,8 +13,6 @@ const a = A{ .b_list_pointer = &b_list };
1313
1414test "segfault bug" {
1515 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1816 const assert = std.debug.assert;
1917 const obj = B{ .a_pointer = &a };
2018 assert(obj.a_pointer == &a); // this makes zig crash
......@@ -31,8 +29,6 @@ pub const B2 = struct {
3129var b_value = B2{ .pointer_array = &[_]*A2{} };
3230
3331test "basic stuff" {
34 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
35 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3632 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3733 std.debug.assert(&b_value == &b_value);
3834}