| author | |
| committer | |
| log | e1b9800ffa74a637e2b0a6356249c2c37228ec01 |
| tree | 9a239b77750b0216e8e5fe24ea0c930ebf5943ca |
| parent | fb8d754a4bf823b66bcf3fa281c469af8be6f923 |
10 files changed, 175 insertions(+), 163 deletions(-)
src/Module.zig+1-1| ... | @@ -5324,7 +5324,7 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { | ... | @@ -5324,7 +5324,7 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { |
| 5324 | // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we | 5324 | // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we |
| 5325 | // must call `freeDecl` in the linker backend now. | 5325 | // must call `freeDecl` in the linker backend now. |
| 5326 | switch (mod.comp.bin_file.tag) { | 5326 | switch (mod.comp.bin_file.tag) { |
| 5327 | .macho, .c => {}, // this linker backend has already migrated to the new API | 5327 | .elf, .macho, .c => {}, // this linker backend has already migrated to the new API |
| 5328 | else => if (decl.has_tv) { | 5328 | else => if (decl.has_tv) { |
| 5329 | if (decl.ty.isFnOrHasRuntimeBits()) { | 5329 | if (decl.ty.isFnOrHasRuntimeBits()) { |
| 5330 | mod.comp.bin_file.freeDecl(decl_index); | 5330 | mod.comp.bin_file.freeDecl(decl_index); |
src/arch/aarch64/CodeGen.zig+4-13| ... | @@ -4307,12 +4307,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4307,12 +4307,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4307 | const fn_owner_decl = mod.declPtr(func.owner_decl); | 4307 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 4308 | 4308 | ||
| 4309 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 4309 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4310 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 4310 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); |
| 4311 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 4311 | const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); |
| 4312 | const got_addr = blk: { | ||
| 4313 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | ||
| 4314 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | ||
| 4315 | }; | ||
| 4316 | try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr }); | 4312 | try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr }); |
| 4317 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 4313 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4318 | try fn_owner_decl.link.macho.ensureInitialized(macho_file); | 4314 | try fn_owner_decl.link.macho.ensureInitialized(macho_file); |
| ... | @@ -6125,20 +6121,15 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne | ... | @@ -6125,20 +6121,15 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 6125 | mod.markDeclAlive(decl); | 6121 | mod.markDeclAlive(decl); |
| 6126 | 6122 | ||
| 6127 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 6123 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 6128 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 6124 | try decl.link.elf.ensureInitialized(elf_file); |
| 6129 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | 6125 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; |
| 6130 | return MCValue{ .memory = got_addr }; | ||
| 6131 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 6126 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 6132 | // Because MachO is PIE-always-on, we defer memory address resolution until | ||
| 6133 | // the linker has enough info to perform relocations. | ||
| 6134 | try decl.link.macho.ensureInitialized(macho_file); | 6127 | try decl.link.macho.ensureInitialized(macho_file); |
| 6135 | return MCValue{ .linker_load = .{ | 6128 | return MCValue{ .linker_load = .{ |
| 6136 | .type = .got, | 6129 | .type = .got, |
| 6137 | .sym_index = decl.link.macho.getSymbolIndex().?, | 6130 | .sym_index = decl.link.macho.getSymbolIndex().?, |
| 6138 | } }; | 6131 | } }; |
| 6139 | } else if (self.bin_file.cast(link.File.Coff)) |_| { | 6132 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 6140 | // Because COFF is PIE-always-on, we defer memory address resolution until | ||
| 6141 | // the linker has enough info to perform relocations. | ||
| 6142 | assert(decl.link.coff.sym_index != 0); | 6133 | assert(decl.link.coff.sym_index != 0); |
| 6143 | return MCValue{ .linker_load = .{ | 6134 | return MCValue{ .linker_load = .{ |
| 6144 | .type = .got, | 6135 | .type = .got, |
src/arch/arm/CodeGen.zig+50-53| ... | @@ -4253,59 +4253,57 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4253,59 +4253,57 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4253 | 4253 | ||
| 4254 | // Due to incremental compilation, how function calls are generated depends | 4254 | // Due to incremental compilation, how function calls are generated depends |
| 4255 | // on linking. | 4255 | // on linking. |
| 4256 | switch (self.bin_file.tag) { | 4256 | if (self.air.value(callee)) |func_value| { |
| 4257 | .elf => { | 4257 | if (func_value.castTag(.function)) |func_payload| { |
| 4258 | if (self.air.value(callee)) |func_value| { | 4258 | const func = func_payload.data; |
| 4259 | if (func_value.castTag(.function)) |func_payload| { | 4259 | const mod = self.bin_file.options.module.?; |
| 4260 | const func = func_payload.data; | 4260 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 4261 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 4261 | |
| 4262 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 4262 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4263 | const mod = self.bin_file.options.module.?; | 4263 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); |
| 4264 | const fn_owner_decl = mod.declPtr(func.owner_decl); | 4264 | const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); |
| 4265 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { | 4265 | try self.genSetReg(Type.initTag(.usize), .lr, .{ .memory = got_addr }); |
| 4266 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 4266 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 4267 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | 4267 | unreachable; // unsupported architecture for MachO |
| 4268 | } else unreachable; | ||
| 4269 | try self.genSetReg(Type.initTag(.usize), .lr, .{ .memory = got_addr }); | ||
| 4270 | } else if (func_value.castTag(.extern_fn)) |_| { | ||
| 4271 | return self.fail("TODO implement calling extern functions", .{}); | ||
| 4272 | } else { | ||
| 4273 | return self.fail("TODO implement calling bitcasted functions", .{}); | ||
| 4274 | } | ||
| 4275 | } else { | 4268 | } else { |
| 4276 | assert(ty.zigTypeTag() == .Pointer); | 4269 | return self.fail("TODO implement call on {s} for {s}", .{ |
| 4277 | const mcv = try self.resolveInst(callee); | 4270 | @tagName(self.bin_file.tag), |
| 4278 | 4271 | @tagName(self.target.cpu.arch), | |
| 4279 | try self.genSetReg(Type.initTag(.usize), .lr, mcv); | ||
| 4280 | } | ||
| 4281 | |||
| 4282 | // TODO: add Instruction.supportedOn | ||
| 4283 | // function for ARM | ||
| 4284 | if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) { | ||
| 4285 | _ = try self.addInst(.{ | ||
| 4286 | .tag = .blx, | ||
| 4287 | .data = .{ .reg = .lr }, | ||
| 4288 | }); | 4272 | }); |
| 4289 | } else { | ||
| 4290 | return self.fail("TODO fix blx emulation for ARM <v5", .{}); | ||
| 4291 | // _ = try self.addInst(.{ | ||
| 4292 | // .tag = .mov, | ||
| 4293 | // .data = .{ .rr_op = .{ | ||
| 4294 | // .rd = .lr, | ||
| 4295 | // .rn = .r0, | ||
| 4296 | // .op = Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none), | ||
| 4297 | // } }, | ||
| 4298 | // }); | ||
| 4299 | // _ = try self.addInst(.{ | ||
| 4300 | // .tag = .bx, | ||
| 4301 | // .data = .{ .reg = .lr }, | ||
| 4302 | // }); | ||
| 4303 | } | 4273 | } |
| 4304 | }, | 4274 | } else if (func_value.castTag(.extern_fn)) |_| { |
| 4305 | .macho => unreachable, // unsupported architecture for MachO | 4275 | return self.fail("TODO implement calling extern functions", .{}); |
| 4306 | .coff => return self.fail("TODO implement call in COFF for {}", .{self.target.cpu.arch}), | 4276 | } else { |
| 4307 | .plan9 => return self.fail("TODO implement call on plan9 for {}", .{self.target.cpu.arch}), | 4277 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 4308 | else => unreachable, | 4278 | } |
| 4279 | } else { | ||
| 4280 | assert(ty.zigTypeTag() == .Pointer); | ||
| 4281 | const mcv = try self.resolveInst(callee); | ||
| 4282 | |||
| 4283 | try self.genSetReg(Type.initTag(.usize), .lr, mcv); | ||
| 4284 | } | ||
| 4285 | |||
| 4286 | // TODO: add Instruction.supportedOn | ||
| 4287 | // function for ARM | ||
| 4288 | if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) { | ||
| 4289 | _ = try self.addInst(.{ | ||
| 4290 | .tag = .blx, | ||
| 4291 | .data = .{ .reg = .lr }, | ||
| 4292 | }); | ||
| 4293 | } else { | ||
| 4294 | return self.fail("TODO fix blx emulation for ARM <v5", .{}); | ||
| 4295 | // _ = try self.addInst(.{ | ||
| 4296 | // .tag = .mov, | ||
| 4297 | // .data = .{ .rr_op = .{ | ||
| 4298 | // .rd = .lr, | ||
| 4299 | // .rn = .r0, | ||
| 4300 | // .op = Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none), | ||
| 4301 | // } }, | ||
| 4302 | // }); | ||
| 4303 | // _ = try self.addInst(.{ | ||
| 4304 | // .tag = .bx, | ||
| 4305 | // .data = .{ .reg = .lr }, | ||
| 4306 | // }); | ||
| 4309 | } | 4307 | } |
| 4310 | 4308 | ||
| 4311 | const result: MCValue = result: { | 4309 | const result: MCValue = result: { |
| ... | @@ -6086,9 +6084,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne | ... | @@ -6086,9 +6084,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 6086 | mod.markDeclAlive(decl); | 6084 | mod.markDeclAlive(decl); |
| 6087 | 6085 | ||
| 6088 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 6086 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 6089 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 6087 | try decl.link.elf.ensureInitialized(elf_file); |
| 6090 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | 6088 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; |
| 6091 | return MCValue{ .memory = got_addr }; | ||
| 6092 | } else if (self.bin_file.cast(link.File.MachO)) |_| { | 6089 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 6093 | unreachable; // unsupported architecture for MachO | 6090 | unreachable; // unsupported architecture for MachO |
| 6094 | } else if (self.bin_file.cast(link.File.Coff)) |_| { | 6091 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
src/arch/riscv64/CodeGen.zig+4-9| ... | @@ -1722,14 +1722,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1722,14 +1722,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1722 | if (func_value.castTag(.function)) |func_payload| { | 1722 | if (func_value.castTag(.function)) |func_payload| { |
| 1723 | const func = func_payload.data; | 1723 | const func = func_payload.data; |
| 1724 | 1724 | ||
| 1725 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | ||
| 1726 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | ||
| 1727 | const mod = self.bin_file.options.module.?; | 1725 | const mod = self.bin_file.options.module.?; |
| 1728 | const fn_owner_decl = mod.declPtr(func.owner_decl); | 1726 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 1729 | const got_addr = blk: { | 1727 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); |
| 1730 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 1728 | const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); |
| 1731 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | ||
| 1732 | }; | ||
| 1733 | 1729 | ||
| 1734 | try self.genSetReg(Type.initTag(.usize), .ra, .{ .memory = got_addr }); | 1730 | try self.genSetReg(Type.initTag(.usize), .ra, .{ .memory = got_addr }); |
| 1735 | _ = try self.addInst(.{ | 1731 | _ = try self.addInst(.{ |
| ... | @@ -2557,9 +2553,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne | ... | @@ -2557,9 +2553,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 2557 | const decl = mod.declPtr(decl_index); | 2553 | const decl = mod.declPtr(decl_index); |
| 2558 | mod.markDeclAlive(decl); | 2554 | mod.markDeclAlive(decl); |
| 2559 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 2555 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 2560 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 2556 | try decl.link.elf.ensureInitialized(elf_file); |
| 2561 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | 2557 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; |
| 2562 | return MCValue{ .memory = got_addr }; | ||
| 2563 | } else if (self.bin_file.cast(link.File.MachO)) |_| { | 2558 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 2564 | // TODO I'm hacking my way through here by repurposing .memory for storing | 2559 | // TODO I'm hacking my way through here by repurposing .memory for storing |
| 2565 | // index to the GOT target symbol index. | 2560 | // index to the GOT target symbol index. |
src/arch/sparc64/CodeGen.zig+6-11| ... | @@ -1216,12 +1216,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1216,12 +1216,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1216 | if (self.bin_file.tag == link.File.Elf.base_tag) { | 1216 | if (self.bin_file.tag == link.File.Elf.base_tag) { |
| 1217 | if (func_value.castTag(.function)) |func_payload| { | 1217 | if (func_value.castTag(.function)) |func_payload| { |
| 1218 | const func = func_payload.data; | 1218 | const func = func_payload.data; |
| 1219 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 1219 | const mod = self.bin_file.options.module.?; |
| 1220 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 1220 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 1221 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { | 1221 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { |
| 1222 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 1222 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); |
| 1223 | const mod = self.bin_file.options.module.?; | 1223 | break :blk @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); |
| 1224 | break :blk @intCast(u32, got.p_vaddr + mod.declPtr(func.owner_decl).link.elf.offset_table_index * ptr_bytes); | ||
| 1225 | } else unreachable; | 1224 | } else unreachable; |
| 1226 | 1225 | ||
| 1227 | try self.genSetReg(Type.initTag(.usize), .o7, .{ .memory = got_addr }); | 1226 | try self.genSetReg(Type.initTag(.usize), .o7, .{ .memory = got_addr }); |
| ... | @@ -4193,9 +4192,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -4193,9 +4192,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 4193 | } | 4192 | } |
| 4194 | 4193 | ||
| 4195 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { | 4194 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { |
| 4196 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | ||
| 4197 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | ||
| 4198 | |||
| 4199 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? | 4195 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? |
| 4200 | if (tv.ty.zigTypeTag() == .Pointer) blk: { | 4196 | if (tv.ty.zigTypeTag() == .Pointer) blk: { |
| 4201 | if (tv.ty.castPtrToFn()) |_| break :blk; | 4197 | if (tv.ty.castPtrToFn()) |_| break :blk; |
| ... | @@ -4209,9 +4205,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne | ... | @@ -4209,9 +4205,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 4209 | 4205 | ||
| 4210 | mod.markDeclAlive(decl); | 4206 | mod.markDeclAlive(decl); |
| 4211 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 4207 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4212 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 4208 | try decl.link.elf.ensureInitialized(elf_file); |
| 4213 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | 4209 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; |
| 4214 | return MCValue{ .memory = got_addr }; | ||
| 4215 | } else { | 4210 | } else { |
| 4216 | return self.fail("TODO codegen non-ELF const Decl pointer", .{}); | 4211 | return self.fail("TODO codegen non-ELF const Decl pointer", .{}); |
| 4217 | } | 4212 | } |
src/arch/x86_64/CodeGen.zig+5-10| ... | @@ -3998,16 +3998,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -3998,16 +3998,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 3998 | const fn_owner_decl = mod.declPtr(func.owner_decl); | 3998 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 3999 | 3999 | ||
| 4000 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 4000 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4001 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 4001 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); |
| 4002 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 4002 | const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); |
| 4003 | const got_addr = blk: { | ||
| 4004 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | ||
| 4005 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | ||
| 4006 | }; | ||
| 4007 | _ = try self.addInst(.{ | 4003 | _ = try self.addInst(.{ |
| 4008 | .tag = .call, | 4004 | .tag = .call, |
| 4009 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), | 4005 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), |
| 4010 | .data = .{ .imm = @truncate(u32, got_addr) }, | 4006 | .data = .{ .imm = got_addr }, |
| 4011 | }); | 4007 | }); |
| 4012 | } else if (self.bin_file.cast(link.File.Coff)) |_| { | 4008 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 4013 | try self.genSetReg(Type.initTag(.usize), .rax, .{ | 4009 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| ... | @@ -6721,9 +6717,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne | ... | @@ -6721,9 +6717,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 6721 | module.markDeclAlive(decl); | 6717 | module.markDeclAlive(decl); |
| 6722 | 6718 | ||
| 6723 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 6719 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 6724 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 6720 | try decl.link.elf.ensureInitialized(elf_file); |
| 6725 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | 6721 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; |
| 6726 | return MCValue{ .memory = got_addr }; | ||
| 6727 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 6722 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 6728 | try decl.link.macho.ensureInitialized(macho_file); | 6723 | try decl.link.macho.ensureInitialized(macho_file); |
| 6729 | return MCValue{ .linker_load = .{ | 6724 | return MCValue{ .linker_load = .{ |
src/link.zig+1-1| ... | @@ -616,7 +616,7 @@ pub const File = struct { | ... | @@ -616,7 +616,7 @@ pub const File = struct { |
| 616 | } | 616 | } |
| 617 | switch (base.tag) { | 617 | switch (base.tag) { |
| 618 | .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index), | 618 | .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index), |
| 619 | .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl_index), | 619 | .elf => {}, // no-op |
| 620 | .macho => {}, // no-op | 620 | .macho => {}, // no-op |
| 621 | .wasm => return @fieldParentPtr(Wasm, "base", base).allocateDeclIndexes(decl_index), | 621 | .wasm => return @fieldParentPtr(Wasm, "base", base).allocateDeclIndexes(decl_index), |
| 622 | .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl_index), | 622 | .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl_index), |
src/link/Elf.zig+54-56| ... | @@ -344,9 +344,10 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: File. | ... | @@ -344,9 +344,10 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: File. |
| 344 | const decl = mod.declPtr(decl_index); | 344 | const decl = mod.declPtr(decl_index); |
| 345 | 345 | ||
| 346 | assert(self.llvm_object == null); | 346 | assert(self.llvm_object == null); |
| 347 | assert(decl.link.elf.local_sym_index != 0); | ||
| 348 | 347 | ||
| 349 | const target = decl.link.elf.local_sym_index; | 348 | try decl.link.elf.ensureInitialized(self); |
| 349 | const target = decl.link.elf.getSymbolIndex().?; | ||
| 350 | |||
| 350 | const vaddr = self.local_symbols.items[target].st_value; | 351 | const vaddr = self.local_symbols.items[target].st_value; |
| 351 | const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?; | 352 | const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?; |
| 352 | const gop = try self.relocs.getOrPut(self.base.allocator, atom); | 353 | const gop = try self.relocs.getOrPut(self.base.allocator, atom); |
| ... | @@ -447,7 +448,7 @@ fn makeString(self: *Elf, bytes: []const u8) !u32 { | ... | @@ -447,7 +448,7 @@ fn makeString(self: *Elf, bytes: []const u8) !u32 { |
| 447 | return @intCast(u32, result); | 448 | return @intCast(u32, result); |
| 448 | } | 449 | } |
| 449 | 450 | ||
| 450 | fn getString(self: Elf, str_off: u32) []const u8 { | 451 | pub fn getString(self: Elf, str_off: u32) []const u8 { |
| 451 | assert(str_off < self.shstrtab.items.len); | 452 | assert(str_off < self.shstrtab.items.len); |
| 452 | return mem.sliceTo(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off), 0); | 453 | return mem.sliceTo(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off), 0); |
| 453 | } | 454 | } |
| ... | @@ -2069,7 +2070,7 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { | ... | @@ -2069,7 +2070,7 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { |
| 2069 | if (text_block.prev) |prev| { | 2070 | if (text_block.prev) |prev| { |
| 2070 | prev.next = text_block.next; | 2071 | prev.next = text_block.next; |
| 2071 | 2072 | ||
| 2072 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { | 2073 | if (!already_have_free_list_node and prev.freeListEligible(self)) { |
| 2073 | // The free list is heuristics, it doesn't have to be perfect, so we can | 2074 | // The free list is heuristics, it doesn't have to be perfect, so we can |
| 2074 | // ignore the OOM here. | 2075 | // ignore the OOM here. |
| 2075 | free_list.append(self.base.allocator, prev) catch {}; | 2076 | free_list.append(self.base.allocator, prev) catch {}; |
| ... | @@ -2084,6 +2085,15 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { | ... | @@ -2084,6 +2085,15 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { |
| 2084 | text_block.next = null; | 2085 | text_block.next = null; |
| 2085 | } | 2086 | } |
| 2086 | 2087 | ||
| 2088 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | ||
| 2089 | const local_sym_index = text_block.getSymbolIndex().?; | ||
| 2090 | self.local_symbol_free_list.append(self.base.allocator, local_sym_index) catch {}; | ||
| 2091 | self.local_symbols.items[local_sym_index].st_info = 0; | ||
| 2092 | _ = self.atom_by_index_table.remove(local_sym_index); | ||
| 2093 | text_block.local_sym_index = 0; | ||
| 2094 | |||
| 2095 | self.offset_table_free_list.append(self.base.allocator, text_block.offset_table_index) catch {}; | ||
| 2096 | |||
| 2087 | if (self.dwarf) |*dw| { | 2097 | if (self.dwarf) |*dw| { |
| 2088 | dw.freeAtom(&text_block.dbg_info_atom); | 2098 | dw.freeAtom(&text_block.dbg_info_atom); |
| 2089 | } | 2099 | } |
| ... | @@ -2099,7 +2109,7 @@ fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, phdr | ... | @@ -2099,7 +2109,7 @@ fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, phdr |
| 2099 | fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64, phdr_index: u16) !u64 { | 2109 | fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64, phdr_index: u16) !u64 { |
| 2100 | const sym = self.local_symbols.items[text_block.local_sym_index]; | 2110 | const sym = self.local_symbols.items[text_block.local_sym_index]; |
| 2101 | const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; | 2111 | const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; |
| 2102 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*); | 2112 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self); |
| 2103 | if (!need_realloc) return sym.st_value; | 2113 | if (!need_realloc) return sym.st_value; |
| 2104 | return self.allocateTextBlock(text_block, new_block_size, alignment, phdr_index); | 2114 | return self.allocateTextBlock(text_block, new_block_size, alignment, phdr_index); |
| 2105 | } | 2115 | } |
| ... | @@ -2128,7 +2138,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al | ... | @@ -2128,7 +2138,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2128 | // We now have a pointer to a live text block that has too much capacity. | 2138 | // We now have a pointer to a live text block that has too much capacity. |
| 2129 | // Is it enough that we could fit this new text block? | 2139 | // Is it enough that we could fit this new text block? |
| 2130 | const sym = self.local_symbols.items[big_block.local_sym_index]; | 2140 | const sym = self.local_symbols.items[big_block.local_sym_index]; |
| 2131 | const capacity = big_block.capacity(self.*); | 2141 | const capacity = big_block.capacity(self); |
| 2132 | const ideal_capacity = padToIdeal(capacity); | 2142 | const ideal_capacity = padToIdeal(capacity); |
| 2133 | const ideal_capacity_end_vaddr = std.math.add(u64, sym.st_value, ideal_capacity) catch ideal_capacity; | 2143 | const ideal_capacity_end_vaddr = std.math.add(u64, sym.st_value, ideal_capacity) catch ideal_capacity; |
| 2134 | const capacity_end_vaddr = sym.st_value + capacity; | 2144 | const capacity_end_vaddr = sym.st_value + capacity; |
| ... | @@ -2138,7 +2148,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al | ... | @@ -2138,7 +2148,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2138 | // Additional bookkeeping here to notice if this free list node | 2148 | // Additional bookkeeping here to notice if this free list node |
| 2139 | // should be deleted because the block that it points to has grown to take up | 2149 | // should be deleted because the block that it points to has grown to take up |
| 2140 | // more of the extra capacity. | 2150 | // more of the extra capacity. |
| 2141 | if (!big_block.freeListEligible(self.*)) { | 2151 | if (!big_block.freeListEligible(self)) { |
| 2142 | _ = free_list.swapRemove(i); | 2152 | _ = free_list.swapRemove(i); |
| 2143 | } else { | 2153 | } else { |
| 2144 | i += 1; | 2154 | i += 1; |
| ... | @@ -2213,7 +2223,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al | ... | @@ -2213,7 +2223,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2213 | return vaddr; | 2223 | return vaddr; |
| 2214 | } | 2224 | } |
| 2215 | 2225 | ||
| 2216 | fn allocateLocalSymbol(self: *Elf) !u32 { | 2226 | pub fn allocateLocalSymbol(self: *Elf) !u32 { |
| 2217 | try self.local_symbols.ensureUnusedCapacity(self.base.allocator, 1); | 2227 | try self.local_symbols.ensureUnusedCapacity(self.base.allocator, 1); |
| 2218 | 2228 | ||
| 2219 | const index = blk: { | 2229 | const index = blk: { |
| ... | @@ -2240,7 +2250,7 @@ fn allocateLocalSymbol(self: *Elf) !u32 { | ... | @@ -2240,7 +2250,7 @@ fn allocateLocalSymbol(self: *Elf) !u32 { |
| 2240 | return index; | 2250 | return index; |
| 2241 | } | 2251 | } |
| 2242 | 2252 | ||
| 2243 | fn allocateGotOffset(self: *Elf) !u32 { | 2253 | pub fn allocateGotOffset(self: *Elf) !u32 { |
| 2244 | try self.offset_table.ensureUnusedCapacity(self.base.allocator, 1); | 2254 | try self.offset_table.ensureUnusedCapacity(self.base.allocator, 1); |
| 2245 | 2255 | ||
| 2246 | const index = blk: { | 2256 | const index = blk: { |
| ... | @@ -2260,32 +2270,10 @@ fn allocateGotOffset(self: *Elf) !u32 { | ... | @@ -2260,32 +2270,10 @@ fn allocateGotOffset(self: *Elf) !u32 { |
| 2260 | return index; | 2270 | return index; |
| 2261 | } | 2271 | } |
| 2262 | 2272 | ||
| 2263 | pub fn allocateDeclIndexes(self: *Elf, decl_index: Module.Decl.Index) !void { | ||
| 2264 | if (self.llvm_object) |_| return; | ||
| 2265 | |||
| 2266 | const mod = self.base.options.module.?; | ||
| 2267 | const decl = mod.declPtr(decl_index); | ||
| 2268 | const block = &decl.link.elf; | ||
| 2269 | if (block.local_sym_index != 0) return; | ||
| 2270 | |||
| 2271 | const decl_name = try decl.getFullyQualifiedName(mod); | ||
| 2272 | defer self.base.allocator.free(decl_name); | ||
| 2273 | |||
| 2274 | log.debug("allocating symbol indexes for {s}", .{decl_name}); | ||
| 2275 | |||
| 2276 | block.local_sym_index = try self.allocateLocalSymbol(); | ||
| 2277 | block.offset_table_index = try self.allocateGotOffset(); | ||
| 2278 | try self.atom_by_index_table.putNoClobber(self.base.allocator, block.local_sym_index, block); | ||
| 2279 | try self.decls.putNoClobber(self.base.allocator, decl_index, null); | ||
| 2280 | } | ||
| 2281 | |||
| 2282 | fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void { | 2273 | fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2283 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; | 2274 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; |
| 2284 | for (unnamed_consts.items) |atom| { | 2275 | for (unnamed_consts.items) |atom| { |
| 2285 | self.freeTextBlock(atom, self.phdr_load_ro_index.?); | 2276 | self.freeTextBlock(atom, self.phdr_load_ro_index.?); |
| 2286 | self.local_symbol_free_list.append(self.base.allocator, atom.local_sym_index) catch {}; | ||
| 2287 | self.local_symbols.items[atom.local_sym_index].st_info = 0; | ||
| 2288 | _ = self.atom_by_index_table.remove(atom.local_sym_index); | ||
| 2289 | } | 2277 | } |
| 2290 | unnamed_consts.clearAndFree(self.base.allocator); | 2278 | unnamed_consts.clearAndFree(self.base.allocator); |
| 2291 | } | 2279 | } |
| ... | @@ -2298,20 +2286,13 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { | ... | @@ -2298,20 +2286,13 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2298 | const mod = self.base.options.module.?; | 2286 | const mod = self.base.options.module.?; |
| 2299 | const decl = mod.declPtr(decl_index); | 2287 | const decl = mod.declPtr(decl_index); |
| 2300 | 2288 | ||
| 2301 | const kv = self.decls.fetchRemove(decl_index); | 2289 | log.debug("freeDecl {*}", .{decl}); |
| 2302 | if (kv.?.value) |index| { | ||
| 2303 | self.freeTextBlock(&decl.link.elf, index); | ||
| 2304 | self.freeUnnamedConsts(decl_index); | ||
| 2305 | } | ||
| 2306 | |||
| 2307 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | ||
| 2308 | if (decl.link.elf.local_sym_index != 0) { | ||
| 2309 | self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {}; | ||
| 2310 | self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0; | ||
| 2311 | _ = self.atom_by_index_table.remove(decl.link.elf.local_sym_index); | ||
| 2312 | decl.link.elf.local_sym_index = 0; | ||
| 2313 | 2290 | ||
| 2314 | self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; | 2291 | if (self.decls.fetchRemove(decl_index)) |kv| { |
| 2292 | if (kv.value) |index| { | ||
| 2293 | self.freeTextBlock(&decl.link.elf, index); | ||
| 2294 | self.freeUnnamedConsts(decl_index); | ||
| 2295 | } | ||
| 2315 | } | 2296 | } |
| 2316 | 2297 | ||
| 2317 | if (self.dwarf) |*dw| { | 2298 | if (self.dwarf) |*dw| { |
| ... | @@ -2363,7 +2344,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s | ... | @@ -2363,7 +2344,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s |
| 2363 | assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() | 2344 | assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() |
| 2364 | const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; | 2345 | const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; |
| 2365 | if (local_sym.st_size != 0) { | 2346 | if (local_sym.st_size != 0) { |
| 2366 | const capacity = decl.link.elf.capacity(self.*); | 2347 | const capacity = decl.link.elf.capacity(self); |
| 2367 | const need_realloc = code.len > capacity or | 2348 | const need_realloc = code.len > capacity or |
| 2368 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); | 2349 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); |
| 2369 | if (need_realloc) { | 2350 | if (need_realloc) { |
| ... | @@ -2424,12 +2405,19 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven | ... | @@ -2424,12 +2405,19 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2424 | const tracy = trace(@src()); | 2405 | const tracy = trace(@src()); |
| 2425 | defer tracy.end(); | 2406 | defer tracy.end(); |
| 2426 | 2407 | ||
| 2427 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | ||
| 2428 | defer code_buffer.deinit(); | ||
| 2429 | |||
| 2430 | const decl_index = func.owner_decl; | 2408 | const decl_index = func.owner_decl; |
| 2431 | const decl = module.declPtr(decl_index); | 2409 | const decl = module.declPtr(decl_index); |
| 2432 | self.freeUnnamedConsts(decl_index); | 2410 | const atom = &decl.link.elf; |
| 2411 | try atom.ensureInitialized(self); | ||
| 2412 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | ||
| 2413 | if (gop.found_existing) { | ||
| 2414 | self.freeUnnamedConsts(decl_index); | ||
| 2415 | } else { | ||
| 2416 | gop.value_ptr.* = null; | ||
| 2417 | } | ||
| 2418 | |||
| 2419 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | ||
| 2420 | defer code_buffer.deinit(); | ||
| 2433 | 2421 | ||
| 2434 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(module, decl_index) else null; | 2422 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(module, decl_index) else null; |
| 2435 | defer if (decl_state) |*ds| ds.deinit(); | 2423 | defer if (decl_state) |*ds| ds.deinit(); |
| ... | @@ -2490,6 +2478,13 @@ pub fn updateDecl(self: *Elf, module: *Module, decl_index: Module.Decl.Index) !v | ... | @@ -2490,6 +2478,13 @@ pub fn updateDecl(self: *Elf, module: *Module, decl_index: Module.Decl.Index) !v |
| 2490 | 2478 | ||
| 2491 | assert(!self.unnamed_const_atoms.contains(decl_index)); | 2479 | assert(!self.unnamed_const_atoms.contains(decl_index)); |
| 2492 | 2480 | ||
| 2481 | const atom = &decl.link.elf; | ||
| 2482 | try atom.ensureInitialized(self); | ||
| 2483 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | ||
| 2484 | if (!gop.found_existing) { | ||
| 2485 | gop.value_ptr.* = null; | ||
| 2486 | } | ||
| 2487 | |||
| 2493 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 2488 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2494 | defer code_buffer.deinit(); | 2489 | defer code_buffer.deinit(); |
| 2495 | 2490 | ||
| ... | @@ -2633,16 +2628,19 @@ pub fn updateDeclExports( | ... | @@ -2633,16 +2628,19 @@ pub fn updateDeclExports( |
| 2633 | const tracy = trace(@src()); | 2628 | const tracy = trace(@src()); |
| 2634 | defer tracy.end(); | 2629 | defer tracy.end(); |
| 2635 | 2630 | ||
| 2636 | try self.global_symbols.ensureUnusedCapacity(self.base.allocator, exports.len); | ||
| 2637 | const decl = module.declPtr(decl_index); | 2631 | const decl = module.declPtr(decl_index); |
| 2638 | if (decl.link.elf.local_sym_index == 0) return; | 2632 | const atom = &decl.link.elf; |
| 2639 | const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index]; | ||
| 2640 | 2633 | ||
| 2641 | const decl_ptr = self.decls.getPtr(decl_index).?; | 2634 | if (atom.getSymbolIndex() == null) return; |
| 2642 | if (decl_ptr.* == null) { | 2635 | |
| 2643 | decl_ptr.* = try self.getDeclPhdrIndex(decl); | 2636 | const decl_sym = atom.getSymbol(self); |
| 2637 | try self.global_symbols.ensureUnusedCapacity(self.base.allocator, exports.len); | ||
| 2638 | |||
| 2639 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | ||
| 2640 | if (!gop.found_existing) { | ||
| 2641 | gop.value_ptr.* = try self.getDeclPhdrIndex(decl); | ||
| 2644 | } | 2642 | } |
| 2645 | const phdr_index = decl_ptr.*.?; | 2643 | const phdr_index = gop.value_ptr.*.?; |
| 2646 | const shdr_index = self.phdr_shdr_table.get(phdr_index).?; | 2644 | const shdr_index = self.phdr_shdr_table.get(phdr_index).?; |
| 2647 | 2645 | ||
| 2648 | for (exports) |exp| { | 2646 | for (exports) |exp| { |
src/link/Elf/Atom.zig+46-6| ... | @@ -1,6 +1,8 @@ | ... | @@ -1,6 +1,8 @@ |
| 1 | const Atom = @This(); | 1 | const Atom = @This(); |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const assert = std.debug.assert; | ||
| 5 | const elf = std.elf; | ||
| 4 | 6 | ||
| 5 | const Dwarf = @import("../Dwarf.zig"); | 7 | const Dwarf = @import("../Dwarf.zig"); |
| 6 | const Elf = @import("../Elf.zig"); | 8 | const Elf = @import("../Elf.zig"); |
| ... | @@ -12,8 +14,10 @@ const Elf = @import("../Elf.zig"); | ... | @@ -12,8 +14,10 @@ const Elf = @import("../Elf.zig"); |
| 12 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or | 14 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or |
| 13 | /// offset table entry. | 15 | /// offset table entry. |
| 14 | local_sym_index: u32, | 16 | local_sym_index: u32, |
| 17 | |||
| 15 | /// This field is undefined for symbols with size = 0. | 18 | /// This field is undefined for symbols with size = 0. |
| 16 | offset_table_index: u32, | 19 | offset_table_index: u32, |
| 20 | |||
| 17 | /// Points to the previous and next neighbors, based on the `text_offset`. | 21 | /// Points to the previous and next neighbors, based on the `text_offset`. |
| 18 | /// This can be used to find, for example, the capacity of this `TextBlock`. | 22 | /// This can be used to find, for example, the capacity of this `TextBlock`. |
| 19 | prev: ?*Atom, | 23 | prev: ?*Atom, |
| ... | @@ -29,13 +33,49 @@ pub const empty = Atom{ | ... | @@ -29,13 +33,49 @@ pub const empty = Atom{ |
| 29 | .dbg_info_atom = undefined, | 33 | .dbg_info_atom = undefined, |
| 30 | }; | 34 | }; |
| 31 | 35 | ||
| 36 | pub fn ensureInitialized(self: *Atom, elf_file: *Elf) !void { | ||
| 37 | if (self.getSymbolIndex() != null) return; // Already initialized | ||
| 38 | self.local_sym_index = try elf_file.allocateLocalSymbol(); | ||
| 39 | self.offset_table_index = try elf_file.allocateGotOffset(); | ||
| 40 | try elf_file.atom_by_index_table.putNoClobber(elf_file.base.allocator, self.local_sym_index, self); | ||
| 41 | } | ||
| 42 | |||
| 43 | pub fn getSymbolIndex(self: Atom) ?u32 { | ||
| 44 | if (self.local_sym_index == 0) return null; | ||
| 45 | return self.local_sym_index; | ||
| 46 | } | ||
| 47 | |||
| 48 | pub fn getSymbol(self: Atom, elf_file: *Elf) elf.Elf64_Sym { | ||
| 49 | const sym_index = self.getSymbolIndex().?; | ||
| 50 | return elf_file.local_symbols.items[sym_index]; | ||
| 51 | } | ||
| 52 | |||
| 53 | pub fn getSymbolPtr(self: Atom, elf_file: *Elf) *elf.Elf64_Sym { | ||
| 54 | const sym_index = self.getSymbolIndex().?; | ||
| 55 | return &elf_file.local_symbols.items[sym_index]; | ||
| 56 | } | ||
| 57 | |||
| 58 | pub fn getName(self: Atom, elf_file: *Elf) []const u8 { | ||
| 59 | const sym = self.getSymbol(); | ||
| 60 | return elf_file.getString(sym.st_name); | ||
| 61 | } | ||
| 62 | |||
| 63 | pub fn getOffsetTableAddress(self: Atom, elf_file: *Elf) u64 { | ||
| 64 | assert(self.getSymbolIndex() != null); | ||
| 65 | const target = elf_file.base.options.target; | ||
| 66 | const ptr_bits = target.cpu.arch.ptrBitWidth(); | ||
| 67 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | ||
| 68 | const got = elf_file.program_headers.items[elf_file.phdr_got_index.?]; | ||
| 69 | return got.p_vaddr + self.offset_table_index * ptr_bytes; | ||
| 70 | } | ||
| 71 | |||
| 32 | /// Returns how much room there is to grow in virtual address space. | 72 | /// Returns how much room there is to grow in virtual address space. |
| 33 | /// File offset relocation happens transparently, so it is not included in | 73 | /// File offset relocation happens transparently, so it is not included in |
| 34 | /// this calculation. | 74 | /// this calculation. |
| 35 | pub fn capacity(self: Atom, elf_file: Elf) u64 { | 75 | pub fn capacity(self: Atom, elf_file: *Elf) u64 { |
| 36 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; | 76 | const self_sym = self.getSymbol(elf_file); |
| 37 | if (self.next) |next| { | 77 | if (self.next) |next| { |
| 38 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; | 78 | const next_sym = next.getSymbol(elf_file); |
| 39 | return next_sym.st_value - self_sym.st_value; | 79 | return next_sym.st_value - self_sym.st_value; |
| 40 | } else { | 80 | } else { |
| 41 | // We are the last block. The capacity is limited only by virtual address space. | 81 | // We are the last block. The capacity is limited only by virtual address space. |
| ... | @@ -43,11 +83,11 @@ pub fn capacity(self: Atom, elf_file: Elf) u64 { | ... | @@ -43,11 +83,11 @@ pub fn capacity(self: Atom, elf_file: Elf) u64 { |
| 43 | } | 83 | } |
| 44 | } | 84 | } |
| 45 | 85 | ||
| 46 | pub fn freeListEligible(self: Atom, elf_file: Elf) bool { | 86 | pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 47 | // No need to keep a free list node for the last block. | 87 | // No need to keep a free list node for the last block. |
| 48 | const next = self.next orelse return false; | 88 | const next = self.next orelse return false; |
| 49 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; | 89 | const self_sym = self.getSymbol(elf_file); |
| 50 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; | 90 | const next_sym = next.getSymbol(elf_file); |
| 51 | const cap = next_sym.st_value - self_sym.st_value; | 91 | const cap = next_sym.st_value - self_sym.st_value; |
| 52 | const ideal_cap = Elf.padToIdeal(self_sym.st_size); | 92 | const ideal_cap = Elf.padToIdeal(self_sym.st_size); |
| 53 | if (cap <= ideal_cap) return false; | 93 | if (cap <= ideal_cap) return false; |
src/link/MachO.zig+4-3| ... | @@ -2472,14 +2472,15 @@ pub fn updateDeclExports( | ... | @@ -2472,14 +2472,15 @@ pub fn updateDeclExports( |
| 2472 | 2472 | ||
| 2473 | const decl = module.declPtr(decl_index); | 2473 | const decl = module.declPtr(decl_index); |
| 2474 | const atom = &decl.link.macho; | 2474 | const atom = &decl.link.macho; |
| 2475 | try atom.ensureInitialized(self); | 2475 | |
| 2476 | if (atom.getSymbolIndex() == null) return; | ||
| 2476 | 2477 | ||
| 2477 | const gop = try self.decls.getOrPut(gpa, decl_index); | 2478 | const gop = try self.decls.getOrPut(gpa, decl_index); |
| 2478 | if (!gop.found_existing) { | 2479 | if (!gop.found_existing) { |
| 2479 | gop.value_ptr.* = null; | 2480 | gop.value_ptr.* = self.getDeclOutputSection(decl); |
| 2480 | } | 2481 | } |
| 2481 | 2482 | ||
| 2482 | const decl_sym = decl.link.macho.getSymbol(self); | 2483 | const decl_sym = atom.getSymbol(self); |
| 2483 | 2484 | ||
| 2484 | for (exports) |exp| { | 2485 | for (exports) |exp| { |
| 2485 | const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{exp.options.name}); | 2486 | const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{exp.options.name}); |