| author | |
| committer | |
| log | 0474943ddfb12552262e3e13f74ecb3842b18019 |
| tree | c46515f91973faaf597ab9758743bd2190652a2e |
| parent | bf6540ce50f8613386be09aac7dc03604af12e1e |
| parent | e0f5627d4a9cb1b3a1361d70d40043c8c170b2af |
| signature |
10 files changed, 141 insertions(+), 117 deletions(-)
src/arch/aarch64/CodeGen.zig+15| ... | ... | @@ -786,6 +786,11 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u |
| 786 | 786 | /// Use a pointer instruction as the basis for allocating stack memory. |
| 787 | 787 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 788 | 788 | const elem_ty = self.air.typeOfIndex(inst).elemType(); |
| 789 | ||
| 790 | if (!elem_ty.hasRuntimeBits()) { | |
| 791 | return self.allocMem(inst, @sizeOf(usize), @alignOf(usize)); | |
| 792 | } | |
| 793 | ||
| 789 | 794 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 790 | 795 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty}); |
| 791 | 796 | }; |
| ... | ... | @@ -3545,6 +3550,15 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 3545 | 3550 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { |
| 3546 | 3551 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 3547 | 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 | ||
| 3548 | 3562 | decl.alive = true; |
| 3549 | 3563 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 3550 | 3564 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| ... | ... | @@ -3553,6 +3567,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 3553 | 3567 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 3554 | 3568 | // Because MachO is PIE-always-on, we defer memory address resolution until |
| 3555 | 3569 | // the linker has enough info to perform relocations. |
| 3570 | assert(decl.link.macho.local_sym_index != 0); | |
| 3556 | 3571 | return MCValue{ .got_load = decl.link.macho.local_sym_index }; |
| 3557 | 3572 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 3558 | 3573 | const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes; |
src/arch/aarch64/Emit.zig+21-5| ... | ... | @@ -208,8 +208,8 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | 210 | switch (tag) { |
| 211 | .load_memory_direct => return 3 * 4, | |
| 211 | 212 | .load_memory_got, |
| 212 | .load_memory_direct, | |
| 213 | 213 | .load_memory_ptr_got, |
| 214 | 214 | .load_memory_ptr_direct, |
| 215 | 215 | => return 2 * 4, |
| ... | ... | @@ -654,15 +654,31 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 654 | 654 | const data = emit.mir.extraData(Mir.LoadMemoryPie, payload).data; |
| 655 | 655 | const reg = @intToEnum(Register, data.register); |
| 656 | 656 | |
| 657 | // PC-relative displacement to the entry in the GOT table. | |
| 657 | // PC-relative displacement to the entry in memory. | |
| 658 | 658 | // adrp |
| 659 | 659 | const offset = @intCast(u32, emit.code.items.len); |
| 660 | 660 | try emit.writeInstruction(Instruction.adrp(reg, 0)); |
| 661 | 661 | |
| 662 | 662 | switch (tag) { |
| 663 | .load_memory_got, | |
| 664 | .load_memory_direct, | |
| 665 | => { | |
| 663 | .load_memory_got => { | |
| 664 | // ldr reg, reg, offset | |
| 665 | try emit.writeInstruction(Instruction.ldr( | |
| 666 | reg, | |
| 667 | reg, | |
| 668 | Instruction.LoadStoreOffset.imm(0), | |
| 669 | )); | |
| 670 | }, | |
| 671 | .load_memory_direct => { | |
| 672 | // We cannot load the offset directly as it may not be aligned properly. | |
| 673 | // For example, load for 64bit register will require the target address offset | |
| 674 | // to be 8-byte aligned, while the value might have non-8-byte natural alignment, | |
| 675 | // meaning the linker might have put it at a non-8-byte aligned address. To circumvent | |
| 676 | // this, we use `adrp, add` to form the address value which we then dereference with | |
| 677 | // `ldr`. | |
| 678 | // Note that this can potentially be optimised out by the codegen/linker if the | |
| 679 | // target address is appropriately aligned. | |
| 680 | // add reg, reg, offset | |
| 681 | try emit.writeInstruction(Instruction.add(reg, reg, 0, false)); | |
| 666 | 682 | // ldr reg, reg, offset |
| 667 | 683 | try emit.writeInstruction(Instruction.ldr( |
| 668 | 684 | reg, |
src/arch/x86_64/CodeGen.zig+10-1| ... | ... | @@ -852,7 +852,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 852 | 852 | const elem_ty = ptr_ty.elemType(); |
| 853 | 853 | |
| 854 | 854 | if (!elem_ty.hasRuntimeBits()) { |
| 855 | return self.allocMem(inst, 8, 8); | |
| 855 | return self.allocMem(inst, @sizeOf(usize), @alignOf(usize)); | |
| 856 | 856 | } |
| 857 | 857 | |
| 858 | 858 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| ... | ... | @@ -5333,6 +5333,14 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 5333 | 5333 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 5334 | 5334 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 5335 | 5335 | |
| 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 | 5344 | decl.alive = true; |
| 5337 | 5345 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 5338 | 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 | 5349 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 5342 | 5350 | // Because MachO is PIE-always-on, we defer memory address resolution until |
| 5343 | 5351 | // the linker has enough info to perform relocations. |
| 5352 | assert(decl.link.macho.local_sym_index != 0); | |
| 5344 | 5353 | return MCValue{ .got_load = decl.link.macho.local_sym_index }; |
| 5345 | 5354 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 5346 | 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 | 857 | else => return emit.fail("TODO unused LEA PIE variants 0b10 and 0b11", .{}), |
| 858 | 858 | }; |
| 859 | 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 | 861 | try atom.relocs.append(emit.bin_file.allocator, .{ |
| 861 | 862 | .offset = @intCast(u32, end_offset - 4), |
| 862 | 863 | .target = .{ .local = load_reloc.sym_index }, |
src/link/MachO.zig+89-87| ... | ... | @@ -3797,10 +3797,11 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De |
| 3797 | 3797 | atom.code.clearRetainingCapacity(); |
| 3798 | 3798 | try atom.code.appendSlice(self.base.allocator, code); |
| 3799 | 3799 | |
| 3800 | const match = try self.getMatchingSectionAtom(atom, typed_value.ty, typed_value.val); | |
| 3800 | const match = try self.getMatchingSectionAtom(atom, decl_name, typed_value.ty, typed_value.val); | |
| 3801 | 3801 | const addr = try self.allocateAtom(atom, code.len, required_alignment, match); |
| 3802 | 3802 | |
| 3803 | 3803 | log.debug("allocated atom for {s} at 0x{x}", .{ name, addr }); |
| 3804 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | |
| 3804 | 3805 | |
| 3805 | 3806 | errdefer self.freeAtom(atom, match, true); |
| 3806 | 3807 | |
| ... | ... | @@ -3903,28 +3904,60 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3903 | 3904 | try self.updateDeclExports(module, decl, decl_exports); |
| 3904 | 3905 | } |
| 3905 | 3906 | |
| 3906 | fn isElemTyPointer(ty: Type) bool { | |
| 3907 | /// Checks if the value, or any of its embedded values stores a pointer, and thus requires | |
| 3908 | /// a rebase opcode for the dynamic linker. | |
| 3909 | fn needsPointerRebase(ty: Type, val: Value) bool { | |
| 3910 | if (ty.zigTypeTag() == .Fn) { | |
| 3911 | return false; | |
| 3912 | } | |
| 3913 | if (val.pointerDecl()) |_| { | |
| 3914 | return true; | |
| 3915 | } | |
| 3916 | ||
| 3907 | 3917 | switch (ty.zigTypeTag()) { |
| 3908 | .Fn => return false, | |
| 3918 | .Fn => unreachable, | |
| 3909 | 3919 | .Pointer => return true, |
| 3910 | .Array => { | |
| 3911 | const elem_ty = ty.elemType(); | |
| 3912 | return isElemTyPointer(elem_ty); | |
| 3920 | .Array, .Vector => { | |
| 3921 | if (ty.arrayLen() == 0) return false; | |
| 3922 | const elem_ty = ty.childType(); | |
| 3923 | var elem_value_buf: Value.ElemValueBuffer = undefined; | |
| 3924 | const elem_val = val.elemValueBuffer(0, &elem_value_buf); | |
| 3925 | return needsPointerRebase(elem_ty, elem_val); | |
| 3913 | 3926 | }, |
| 3914 | .Struct, .Union => { | |
| 3915 | const len = ty.structFieldCount(); | |
| 3916 | var i: usize = 0; | |
| 3917 | while (i < len) : (i += 1) { | |
| 3918 | const field_ty = ty.structFieldType(i); | |
| 3919 | if (isElemTyPointer(field_ty)) return true; | |
| 3920 | } | |
| 3921 | return false; | |
| 3927 | .Struct => { | |
| 3928 | const fields = ty.structFields().values(); | |
| 3929 | if (fields.len == 0) return false; | |
| 3930 | if (val.castTag(.@"struct")) |payload| { | |
| 3931 | const field_values = payload.data; | |
| 3932 | for (field_values) |field_val, i| { | |
| 3933 | if (needsPointerRebase(fields[i].ty, field_val)) return true; | |
| 3934 | } else return false; | |
| 3935 | } else return false; | |
| 3936 | }, | |
| 3937 | .Optional => { | |
| 3938 | if (val.castTag(.opt_payload)) |payload| { | |
| 3939 | const sub_val = payload.data; | |
| 3940 | var buffer: Type.Payload.ElemType = undefined; | |
| 3941 | const sub_ty = ty.optionalChild(&buffer); | |
| 3942 | return needsPointerRebase(sub_ty, sub_val); | |
| 3943 | } else return false; | |
| 3944 | }, | |
| 3945 | .Union => { | |
| 3946 | const union_obj = val.cast(Value.Payload.Union).?.data; | |
| 3947 | const active_field_ty = ty.unionFieldType(union_obj.tag); | |
| 3948 | return needsPointerRebase(active_field_ty, union_obj.val); | |
| 3949 | }, | |
| 3950 | .ErrorUnion => { | |
| 3951 | if (val.castTag(.eu_payload)) |payload| { | |
| 3952 | const payload_ty = ty.errorUnionPayload(); | |
| 3953 | return needsPointerRebase(payload_ty, payload.data); | |
| 3954 | } else return false; | |
| 3922 | 3955 | }, |
| 3923 | 3956 | else => return false, |
| 3924 | 3957 | } |
| 3925 | 3958 | } |
| 3926 | 3959 | |
| 3927 | fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !MatchingSection { | |
| 3960 | fn getMatchingSectionAtom(self: *MachO, atom: *Atom, name: []const u8, ty: Type, val: Value) !MatchingSection { | |
| 3928 | 3961 | const code = atom.code.items; |
| 3929 | 3962 | const alignment = ty.abiAlignment(self.base.options.target); |
| 3930 | 3963 | const align_log_2 = math.log2(alignment); |
| ... | ... | @@ -3938,10 +3971,25 @@ fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !Matc |
| 3938 | 3971 | .seg = self.data_segment_cmd_index.?, |
| 3939 | 3972 | .sect = self.bss_section_index.?, |
| 3940 | 3973 | }; |
| 3974 | } else { | |
| 3975 | break :blk MatchingSection{ | |
| 3976 | .seg = self.data_segment_cmd_index.?, | |
| 3977 | .sect = self.data_section_index.?, | |
| 3978 | }; | |
| 3941 | 3979 | } |
| 3980 | } | |
| 3981 | ||
| 3982 | if (val.castTag(.variable)) |_| { | |
| 3983 | break :blk MatchingSection{ | |
| 3984 | .seg = self.data_segment_cmd_index.?, | |
| 3985 | .sect = self.data_section_index.?, | |
| 3986 | }; | |
| 3987 | } | |
| 3988 | ||
| 3989 | if (needsPointerRebase(ty, val)) { | |
| 3942 | 3990 | break :blk (try self.getMatchingSection(.{ |
| 3943 | .segname = makeStaticString("__DATA"), | |
| 3944 | .sectname = makeStaticString("__data"), | |
| 3991 | .segname = makeStaticString("__DATA_CONST"), | |
| 3992 | .sectname = makeStaticString("__const"), | |
| 3945 | 3993 | .size = code.len, |
| 3946 | 3994 | .@"align" = align_log_2, |
| 3947 | 3995 | })).?; |
| ... | ... | @@ -3954,8 +4002,8 @@ fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !Matc |
| 3954 | 4002 | .sect = self.text_section_index.?, |
| 3955 | 4003 | }; |
| 3956 | 4004 | }, |
| 3957 | .Array => switch (val.tag()) { | |
| 3958 | .bytes => { | |
| 4005 | .Array => { | |
| 4006 | if (val.tag() == .bytes) { | |
| 3959 | 4007 | switch (ty.tag()) { |
| 3960 | 4008 | .array_u8_sentinel_0, |
| 3961 | 4009 | .const_slice_u8_sentinel_0, |
| ... | ... | @@ -3969,79 +4017,23 @@ fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !Matc |
| 3969 | 4017 | .@"align" = align_log_2, |
| 3970 | 4018 | })).?; |
| 3971 | 4019 | }, |
| 3972 | else => { | |
| 3973 | break :blk (try self.getMatchingSection(.{ | |
| 3974 | .segname = makeStaticString("__TEXT"), | |
| 3975 | .sectname = makeStaticString("__const"), | |
| 3976 | .size = code.len, | |
| 3977 | .@"align" = align_log_2, | |
| 3978 | })).?; | |
| 3979 | }, | |
| 3980 | } | |
| 3981 | }, | |
| 3982 | .array => { | |
| 3983 | if (isElemTyPointer(ty)) { | |
| 3984 | break :blk (try self.getMatchingSection(.{ | |
| 3985 | .segname = makeStaticString("__DATA_CONST"), | |
| 3986 | .sectname = makeStaticString("__const"), | |
| 3987 | .size = code.len, | |
| 3988 | .@"align" = align_log_2, | |
| 3989 | })).?; | |
| 3990 | } else { | |
| 3991 | break :blk (try self.getMatchingSection(.{ | |
| 3992 | .segname = makeStaticString("__TEXT"), | |
| 3993 | .sectname = makeStaticString("__const"), | |
| 3994 | .size = code.len, | |
| 3995 | .@"align" = align_log_2, | |
| 3996 | })).?; | |
| 4020 | else => {}, | |
| 3997 | 4021 | } |
| 3998 | }, | |
| 3999 | else => { | |
| 4000 | break :blk (try self.getMatchingSection(.{ | |
| 4001 | .segname = makeStaticString("__TEXT"), | |
| 4002 | .sectname = makeStaticString("__const"), | |
| 4003 | .size = code.len, | |
| 4004 | .@"align" = align_log_2, | |
| 4005 | })).?; | |
| 4006 | }, | |
| 4007 | }, | |
| 4008 | .Pointer => { | |
| 4009 | if (val.castTag(.variable)) |_| { | |
| 4010 | break :blk MatchingSection{ | |
| 4011 | .seg = self.data_segment_cmd_index.?, | |
| 4012 | .sect = self.data_section_index.?, | |
| 4013 | }; | |
| 4014 | } else { | |
| 4015 | break :blk (try self.getMatchingSection(.{ | |
| 4016 | .segname = makeStaticString("__DATA_CONST"), | |
| 4017 | .sectname = makeStaticString("__const"), | |
| 4018 | .size = code.len, | |
| 4019 | .@"align" = align_log_2, | |
| 4020 | })).?; | |
| 4021 | } | |
| 4022 | }, | |
| 4023 | else => { | |
| 4024 | if (val.castTag(.variable)) |_| { | |
| 4025 | break :blk MatchingSection{ | |
| 4026 | .seg = self.data_segment_cmd_index.?, | |
| 4027 | .sect = self.data_section_index.?, | |
| 4028 | }; | |
| 4029 | } else { | |
| 4030 | break :blk (try self.getMatchingSection(.{ | |
| 4031 | .segname = makeStaticString("__TEXT"), | |
| 4032 | .sectname = makeStaticString("__const"), | |
| 4033 | .size = code.len, | |
| 4034 | .@"align" = align_log_2, | |
| 4035 | })).?; | |
| 4036 | 4022 | } |
| 4037 | 4023 | }, |
| 4024 | else => {}, | |
| 4038 | 4025 | } |
| 4026 | break :blk (try self.getMatchingSection(.{ | |
| 4027 | .segname = makeStaticString("__TEXT"), | |
| 4028 | .sectname = makeStaticString("__const"), | |
| 4029 | .size = code.len, | |
| 4030 | .@"align" = align_log_2, | |
| 4031 | })).?; | |
| 4039 | 4032 | }; |
| 4040 | const local = self.locals.items[atom.local_sym_index]; | |
| 4041 | 4033 | const seg = self.load_commands.items[match.seg].segment; |
| 4042 | 4034 | const sect = seg.sections.items[match.sect]; |
| 4043 | 4035 | log.debug(" allocating atom '{s}' in '{s},{s}' ({d},{d})", .{ |
| 4044 | self.getString(local.n_strx), | |
| 4036 | name, | |
| 4045 | 4037 | sect.segName(), |
| 4046 | 4038 | sect.sectName(), |
| 4047 | 4039 | match.seg, |
| ... | ... | @@ -4055,13 +4047,14 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 4055 | 4047 | assert(decl.link.macho.local_sym_index != 0); // Caller forgot to call allocateDeclIndexes() |
| 4056 | 4048 | const symbol = &self.locals.items[decl.link.macho.local_sym_index]; |
| 4057 | 4049 | |
| 4050 | const sym_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 4051 | defer self.base.allocator.free(sym_name); | |
| 4052 | ||
| 4058 | 4053 | const decl_ptr = self.decls.getPtr(decl).?; |
| 4059 | 4054 | if (decl_ptr.* == null) { |
| 4060 | decl_ptr.* = try self.getMatchingSectionAtom(&decl.link.macho, decl.ty, decl.val); | |
| 4055 | decl_ptr.* = try self.getMatchingSectionAtom(&decl.link.macho, sym_name, decl.ty, decl.val); | |
| 4061 | 4056 | } |
| 4062 | 4057 | const match = decl_ptr.*.?; |
| 4063 | const sym_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 4064 | defer self.base.allocator.free(sym_name); | |
| 4065 | 4058 | |
| 4066 | 4059 | if (decl.link.macho.size != 0) { |
| 4067 | 4060 | const capacity = decl.link.macho.capacity(self.*); |
| ... | ... | @@ -4071,6 +4064,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 4071 | 4064 | const vaddr = try self.growAtom(&decl.link.macho, code_len, required_alignment, match); |
| 4072 | 4065 | |
| 4073 | 4066 | log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ sym_name, symbol.n_value, vaddr }); |
| 4067 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | |
| 4074 | 4068 | |
| 4075 | 4069 | if (vaddr != symbol.n_value) { |
| 4076 | 4070 | log.debug(" (writing new GOT entry)", .{}); |
| ... | ... | @@ -4105,6 +4099,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 4105 | 4099 | const addr = try self.allocateAtom(&decl.link.macho, code_len, required_alignment, match); |
| 4106 | 4100 | |
| 4107 | 4101 | log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, addr }); |
| 4102 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | |
| 4108 | 4103 | |
| 4109 | 4104 | errdefer self.freeAtom(&decl.link.macho, match, false); |
| 4110 | 4105 | |
| ... | ... | @@ -4291,6 +4286,7 @@ pub fn deleteExport(self: *MachO, exp: Export) void { |
| 4291 | 4286 | } |
| 4292 | 4287 | |
| 4293 | 4288 | fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void { |
| 4289 | log.debug("freeUnnamedConsts for decl {*}", .{decl}); | |
| 4294 | 4290 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl) orelse return; |
| 4295 | 4291 | for (unnamed_consts.items) |atom| { |
| 4296 | 4292 | self.freeAtom(atom, .{ |
| ... | ... | @@ -4300,6 +4296,7 @@ fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void { |
| 4300 | 4296 | self.locals_free_list.append(self.base.allocator, atom.local_sym_index) catch {}; |
| 4301 | 4297 | self.locals.items[atom.local_sym_index].n_type = 0; |
| 4302 | 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}); | |
| 4303 | 4300 | atom.local_sym_index = 0; |
| 4304 | 4301 | } |
| 4305 | 4302 | unnamed_consts.clearAndFree(self.base.allocator); |
| ... | ... | @@ -4324,10 +4321,15 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { |
| 4324 | 4321 | self.got_entries_free_list.append(self.base.allocator, @intCast(u32, got_index)) catch {}; |
| 4325 | 4322 | self.got_entries.items[got_index] = .{ .target = .{ .local = 0 }, .atom = undefined }; |
| 4326 | 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 | }); | |
| 4327 | 4328 | } |
| 4328 | 4329 | |
| 4329 | 4330 | self.locals.items[decl.link.macho.local_sym_index].n_type = 0; |
| 4330 | 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}); | |
| 4331 | 4333 | decl.link.macho.local_sym_index = 0; |
| 4332 | 4334 | } |
| 4333 | 4335 | if (self.d_sym) |*d_sym| { |
src/link/MachO/Atom.zig+5-5| ... | ... | @@ -691,11 +691,11 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { |
| 691 | 691 | |
| 692 | 692 | if (is_via_got) { |
| 693 | 693 | const got_index = macho_file.got_entries_table.get(rel.target) orelse { |
| 694 | const n_strx = switch (rel.target) { | |
| 695 | .local => |sym_index| macho_file.locals.items[sym_index].n_strx, | |
| 696 | .global => |n_strx| n_strx, | |
| 697 | }; | |
| 698 | log.err("expected GOT entry for symbol '{s}'", .{macho_file.getString(n_strx)}); | |
| 694 | log.err("expected GOT entry for symbol", .{}); | |
| 695 | switch (rel.target) { | |
| 696 | .local => |sym_index| log.err(" local @{d}", .{sym_index}), | |
| 697 | .global => |n_strx| log.err(" global @'{s}'", .{macho_file.getString(n_strx)}), | |
| 698 | } | |
| 699 | 699 | log.err(" this is an internal linker error", .{}); |
| 700 | 700 | return error.FailedToResolveRelocationTarget; |
| 701 | 701 | }; |
test/behavior/align.zig-1| ... | ... | @@ -7,7 +7,6 @@ var foo: u8 align(4) = 100; |
| 7 | 7 | |
| 8 | 8 | test "global variable alignment" { |
| 9 | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 10 | if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 11 | 10 | |
| 12 | 11 | comptime try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4); |
| 13 | 12 | comptime try expect(@TypeOf(&foo) == *align(4) u8); |
test/behavior/basic.zig-5| ... | ... | @@ -195,9 +195,6 @@ test "multiline string comments at multiple places" { |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | 197 | test "string concatenation" { |
| 198 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 199 | if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 200 | ||
| 201 | 198 | try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); |
| 202 | 199 | } |
| 203 | 200 | |
| ... | ... | @@ -402,8 +399,6 @@ fn testTakeAddressOfParameter(f: f32) !void { |
| 402 | 399 | |
| 403 | 400 | test "pointer to void return type" { |
| 404 | 401 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 405 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 406 | if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 407 | 402 | |
| 408 | 403 | try testPointerToVoidReturnType(); |
| 409 | 404 | } |
test/behavior/struct.zig-2| ... | ... | @@ -370,8 +370,6 @@ test "empty struct method call" { |
| 370 | 370 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 371 | 371 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 372 | 372 | 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 | |
| 375 | 373 | |
| 376 | 374 | const es = EmptyStruct{}; |
| 377 | 375 | try expect(es.method() == 1234); |
test/behavior/union.zig-11| ... | ... | @@ -44,7 +44,6 @@ fn setInt(foo: *Foo, x: i32) void { |
| 44 | 44 | |
| 45 | 45 | test "comptime union field access" { |
| 46 | 46 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 47 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 48 | 47 | |
| 49 | 48 | comptime { |
| 50 | 49 | var foo = Foo{ .int = 0 }; |
| ... | ... | @@ -77,14 +76,12 @@ const ExternPtrOrInt = extern union { |
| 77 | 76 | }; |
| 78 | 77 | test "extern union size" { |
| 79 | 78 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 80 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 81 | 79 | |
| 82 | 80 | comptime try expect(@sizeOf(ExternPtrOrInt) == 8); |
| 83 | 81 | } |
| 84 | 82 | |
| 85 | 83 | test "0-sized extern union definition" { |
| 86 | 84 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 87 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 88 | 85 | |
| 89 | 86 | const U = extern union { |
| 90 | 87 | a: void, |
| ... | ... | @@ -115,9 +112,7 @@ const err = @as(anyerror!Agg, Agg{ |
| 115 | 112 | const array = [_]Value{ v1, v2, v1, v2 }; |
| 116 | 113 | |
| 117 | 114 | test "unions embedded in aggregate types" { |
| 118 | if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 119 | 115 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 120 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 121 | 116 | |
| 122 | 117 | switch (array[1]) { |
| 123 | 118 | Value.Array => |arr| try expect(arr[4] == 3), |
| ... | ... | @@ -131,7 +126,6 @@ test "unions embedded in aggregate types" { |
| 131 | 126 | |
| 132 | 127 | test "access a member of tagged union with conflicting enum tag name" { |
| 133 | 128 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 134 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 135 | 129 | |
| 136 | 130 | const Bar = union(enum) { |
| 137 | 131 | A: A, |
| ... | ... | @@ -176,7 +170,6 @@ const TaggedUnionWithPayload = union(enum) { |
| 176 | 170 | |
| 177 | 171 | test "union alignment" { |
| 178 | 172 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 179 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 180 | 173 | |
| 181 | 174 | comptime { |
| 182 | 175 | try expect(@alignOf(AlignTestTaggedUnion) >= @alignOf([9]u8)); |
| ... | ... | @@ -276,7 +269,6 @@ fn testCastUnionToTag() !void { |
| 276 | 269 | |
| 277 | 270 | test "union field access gives the enum values" { |
| 278 | 271 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 279 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 280 | 272 | |
| 281 | 273 | try expect(TheUnion.A == TheTag.A); |
| 282 | 274 | try expect(TheUnion.B == TheTag.B); |
| ... | ... | @@ -352,7 +344,6 @@ const PackedPtrOrInt = packed union { |
| 352 | 344 | }; |
| 353 | 345 | test "packed union size" { |
| 354 | 346 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 355 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 356 | 347 | |
| 357 | 348 | comptime try expect(@sizeOf(PackedPtrOrInt) == 8); |
| 358 | 349 | } |
| ... | ... | @@ -362,7 +353,6 @@ const ZeroBits = union { |
| 362 | 353 | }; |
| 363 | 354 | test "union with only 1 field which is void should be zero bits" { |
| 364 | 355 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 365 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 366 | 356 | |
| 367 | 357 | comptime try expect(@sizeOf(ZeroBits) == 0); |
| 368 | 358 | } |
| ... | ... | @@ -422,7 +412,6 @@ test "union with only 1 field casted to its enum type" { |
| 422 | 412 | |
| 423 | 413 | test "union with one member defaults to u0 tag type" { |
| 424 | 414 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 425 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 426 | 415 | |
| 427 | 416 | const U0 = union(enum) { |
| 428 | 417 | X: u32, |