| author | |
| committer | |
| log | 5a67ae506a381aa0494b4b066a8c54ba7ed9fc31 |
| tree | c262a934444ee566af839d3a002b97e21690baa0 |
| parent | 4c116841840bfa7f0068bef23984dd832da8a54d |
| parent | a8987291390d80ad9e2bb45ba225313a108eed0b |
| signature |
self-hosted: remove allocateDeclIndexes from the linker API18 files changed, 688 insertions(+), 777 deletions(-)
src/Module.zig-20| ... | ... | @@ -4585,7 +4585,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4585 | 4585 | // We don't fully codegen the decl until later, but we do need to reserve a global |
| 4586 | 4586 | // offset table index for it. This allows us to codegen decls out of dependency |
| 4587 | 4587 | // order, increasing how many computations can be done in parallel. |
| 4588 | try mod.comp.bin_file.allocateDeclIndexes(decl_index); | |
| 4589 | 4588 | try mod.comp.work_queue.writeItem(.{ .codegen_func = func }); |
| 4590 | 4589 | if (type_changed and mod.emit_h != null) { |
| 4591 | 4590 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); |
| ... | ... | @@ -4697,7 +4696,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4697 | 4696 | // codegen backend wants full access to the Decl Type. |
| 4698 | 4697 | try sema.resolveTypeFully(decl.ty); |
| 4699 | 4698 | |
| 4700 | try mod.comp.bin_file.allocateDeclIndexes(decl_index); | |
| 4701 | 4699 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); |
| 4702 | 4700 | |
| 4703 | 4701 | if (type_changed and mod.emit_h != null) { |
| ... | ... | @@ -5315,23 +5313,6 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { |
| 5315 | 5313 | const decl = mod.declPtr(decl_index); |
| 5316 | 5314 | log.debug("deleteUnusedDecl {d} ({s})", .{ decl_index, decl.name }); |
| 5317 | 5315 | |
| 5318 | // TODO: remove `allocateDeclIndexes` and make the API that the linker backends | |
| 5319 | // are required to notice the first time `updateDecl` happens and keep track | |
| 5320 | // of it themselves. However they can rely on getting a `freeDecl` call if any | |
| 5321 | // `updateDecl` or `updateFunc` calls happen. This will allow us to avoid any call | |
| 5322 | // into the linker backend here, since the linker backend will never have been told | |
| 5323 | // about the Decl in the first place. | |
| 5324 | // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we | |
| 5325 | // must call `freeDecl` in the linker backend now. | |
| 5326 | switch (mod.comp.bin_file.tag) { | |
| 5327 | .c => {}, // this linker backend has already migrated to the new API | |
| 5328 | else => if (decl.has_tv) { | |
| 5329 | if (decl.ty.isFnOrHasRuntimeBits()) { | |
| 5330 | mod.comp.bin_file.freeDecl(decl_index); | |
| 5331 | } | |
| 5332 | }, | |
| 5333 | } | |
| 5334 | ||
| 5335 | 5316 | assert(!mod.declIsRoot(decl_index)); |
| 5336 | 5317 | assert(decl.src_namespace.anon_decls.swapRemove(decl_index)); |
| 5337 | 5318 | |
| ... | ... | @@ -5816,7 +5797,6 @@ pub fn initNewAnonDecl( |
| 5816 | 5797 | // the Decl will be garbage collected by the `codegen_decl` task instead of sent |
| 5817 | 5798 | // to the linker. |
| 5818 | 5799 | if (typed_value.ty.isFnOrHasRuntimeBits()) { |
| 5819 | try mod.comp.bin_file.allocateDeclIndexes(new_decl_index); | |
| 5820 | 5800 | try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index }); |
| 5821 | 5801 | } |
| 5822 | 5802 | } |
src/Sema.zig-1| ... | ... | @@ -7510,7 +7510,6 @@ fn resolveGenericInstantiationType( |
| 7510 | 7510 | // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field |
| 7511 | 7511 | // will be populated, ensuring it will have `analyzeBody` called with the ZIR |
| 7512 | 7512 | // parameters mapped appropriately. |
| 7513 | try mod.comp.bin_file.allocateDeclIndexes(new_decl_index); | |
| 7514 | 7513 | try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func }); |
| 7515 | 7514 | return new_func; |
| 7516 | 7515 | } |
src/arch/aarch64/CodeGen.zig+61-109| ... | ... | @@ -3999,8 +3999,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3999 | 3999 | const mod = self.bin_file.options.module.?; |
| 4000 | 4000 | const owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 4001 | 4001 | const atom_index = switch (self.bin_file.tag) { |
| 4002 | .macho => owner_decl.link.macho.sym_index, | |
| 4003 | .coff => owner_decl.link.coff.sym_index, | |
| 4002 | .macho => owner_decl.link.macho.getSymbolIndex().?, | |
| 4003 | .coff => owner_decl.link.coff.getSymbolIndex().?, | |
| 4004 | 4004 | else => unreachable, // unsupported target format |
| 4005 | 4005 | }; |
| 4006 | 4006 | _ = try self.addInst(.{ |
| ... | ... | @@ -4302,90 +4302,66 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4302 | 4302 | // on linking. |
| 4303 | 4303 | const mod = self.bin_file.options.module.?; |
| 4304 | 4304 | if (self.air.value(callee)) |func_value| { |
| 4305 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 4306 | if (func_value.castTag(.function)) |func_payload| { | |
| 4307 | const func = func_payload.data; | |
| 4308 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 4309 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 4310 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4311 | const got_addr = blk: { | |
| 4312 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 4313 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 4314 | }; | |
| 4305 | if (func_value.castTag(.function)) |func_payload| { | |
| 4306 | const func = func_payload.data; | |
| 4307 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4315 | 4308 | |
| 4309 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 4310 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); | |
| 4311 | const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); | |
| 4316 | 4312 | try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr }); |
| 4317 | ||
| 4318 | _ = try self.addInst(.{ | |
| 4319 | .tag = .blr, | |
| 4320 | .data = .{ .reg = .x30 }, | |
| 4313 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 4314 | try fn_owner_decl.link.macho.ensureInitialized(macho_file); | |
| 4315 | try self.genSetReg(Type.initTag(.u64), .x30, .{ | |
| 4316 | .linker_load = .{ | |
| 4317 | .type = .got, | |
| 4318 | .sym_index = fn_owner_decl.link.macho.getSymbolIndex().?, | |
| 4319 | }, | |
| 4321 | 4320 | }); |
| 4322 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 4323 | return self.fail("TODO implement calling extern functions", .{}); | |
| 4324 | } else { | |
| 4325 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4326 | } | |
| 4327 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 4328 | if (func_value.castTag(.function)) |func_payload| { | |
| 4329 | const func = func_payload.data; | |
| 4330 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4321 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 4322 | try fn_owner_decl.link.coff.ensureInitialized(coff_file); | |
| 4331 | 4323 | try self.genSetReg(Type.initTag(.u64), .x30, .{ |
| 4332 | 4324 | .linker_load = .{ |
| 4333 | 4325 | .type = .got, |
| 4334 | .sym_index = fn_owner_decl.link.macho.sym_index, | |
| 4326 | .sym_index = fn_owner_decl.link.coff.getSymbolIndex().?, | |
| 4335 | 4327 | }, |
| 4336 | 4328 | }); |
| 4337 | // blr x30 | |
| 4338 | _ = try self.addInst(.{ | |
| 4339 | .tag = .blr, | |
| 4340 | .data = .{ .reg = .x30 }, | |
| 4329 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | |
| 4330 | try p9.seeDecl(func.owner_decl); | |
| 4331 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 4332 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 4333 | const got_addr = p9.bases.data; | |
| 4334 | const got_index = fn_owner_decl.link.plan9.got_index.?; | |
| 4335 | const fn_got_addr = got_addr + got_index * ptr_bytes; | |
| 4336 | try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr }); | |
| 4337 | } else unreachable; | |
| 4338 | ||
| 4339 | _ = try self.addInst(.{ | |
| 4340 | .tag = .blr, | |
| 4341 | .data = .{ .reg = .x30 }, | |
| 4342 | }); | |
| 4343 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | |
| 4344 | const extern_fn = func_payload.data; | |
| 4345 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | |
| 4346 | if (extern_fn.lib_name) |lib_name| { | |
| 4347 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ | |
| 4348 | decl_name, | |
| 4349 | lib_name, | |
| 4341 | 4350 | }); |
| 4342 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | |
| 4343 | const extern_fn = func_payload.data; | |
| 4344 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | |
| 4345 | if (extern_fn.lib_name) |lib_name| { | |
| 4346 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ | |
| 4347 | decl_name, | |
| 4348 | lib_name, | |
| 4349 | }); | |
| 4350 | } | |
| 4351 | const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); | |
| 4351 | } | |
| 4352 | 4352 | |
| 4353 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 4354 | const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); | |
| 4353 | 4355 | _ = try self.addInst(.{ |
| 4354 | 4356 | .tag = .call_extern, |
| 4355 | 4357 | .data = .{ |
| 4356 | 4358 | .relocation = .{ |
| 4357 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index, | |
| 4359 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?, | |
| 4358 | 4360 | .sym_index = sym_index, |
| 4359 | 4361 | }, |
| 4360 | 4362 | }, |
| 4361 | 4363 | }); |
| 4362 | } else { | |
| 4363 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4364 | } | |
| 4365 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 4366 | if (func_value.castTag(.function)) |func_payload| { | |
| 4367 | const func = func_payload.data; | |
| 4368 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4369 | try self.genSetReg(Type.initTag(.u64), .x30, .{ | |
| 4370 | .linker_load = .{ | |
| 4371 | .type = .got, | |
| 4372 | .sym_index = fn_owner_decl.link.coff.sym_index, | |
| 4373 | }, | |
| 4374 | }); | |
| 4375 | // blr x30 | |
| 4376 | _ = try self.addInst(.{ | |
| 4377 | .tag = .blr, | |
| 4378 | .data = .{ .reg = .x30 }, | |
| 4379 | }); | |
| 4380 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | |
| 4381 | const extern_fn = func_payload.data; | |
| 4382 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | |
| 4383 | if (extern_fn.lib_name) |lib_name| { | |
| 4384 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ | |
| 4385 | decl_name, | |
| 4386 | lib_name, | |
| 4387 | }); | |
| 4388 | } | |
| 4364 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 4389 | 4365 | const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); |
| 4390 | 4366 | try self.genSetReg(Type.initTag(.u64), .x30, .{ |
| 4391 | 4367 | .linker_load = .{ |
| ... | ... | @@ -4393,35 +4369,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4393 | 4369 | .sym_index = sym_index, |
| 4394 | 4370 | }, |
| 4395 | 4371 | }); |
| 4396 | // blr x30 | |
| 4397 | 4372 | _ = try self.addInst(.{ |
| 4398 | 4373 | .tag = .blr, |
| 4399 | 4374 | .data = .{ .reg = .x30 }, |
| 4400 | 4375 | }); |
| 4401 | 4376 | } else { |
| 4402 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4403 | } | |
| 4404 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | |
| 4405 | if (func_value.castTag(.function)) |func_payload| { | |
| 4406 | try p9.seeDecl(func_payload.data.owner_decl); | |
| 4407 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 4408 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 4409 | const got_addr = p9.bases.data; | |
| 4410 | const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?; | |
| 4411 | const fn_got_addr = got_addr + got_index * ptr_bytes; | |
| 4412 | ||
| 4413 | try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr }); | |
| 4414 | ||
| 4415 | _ = try self.addInst(.{ | |
| 4416 | .tag = .blr, | |
| 4417 | .data = .{ .reg = .x30 }, | |
| 4418 | }); | |
| 4419 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 4420 | 4377 | return self.fail("TODO implement calling extern functions", .{}); |
| 4421 | } else { | |
| 4422 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4423 | 4378 | } |
| 4424 | } else unreachable; | |
| 4379 | } else { | |
| 4380 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4381 | } | |
| 4425 | 4382 | } else { |
| 4426 | 4383 | assert(ty.zigTypeTag() == .Pointer); |
| 4427 | 4384 | const mcv = try self.resolveInst(callee); |
| ... | ... | @@ -5537,8 +5494,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5537 | 5494 | const mod = self.bin_file.options.module.?; |
| 5538 | 5495 | const owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 5539 | 5496 | const atom_index = switch (self.bin_file.tag) { |
| 5540 | .macho => owner_decl.link.macho.sym_index, | |
| 5541 | .coff => owner_decl.link.coff.sym_index, | |
| 5497 | .macho => owner_decl.link.macho.getSymbolIndex().?, | |
| 5498 | .coff => owner_decl.link.coff.getSymbolIndex().?, | |
| 5542 | 5499 | else => unreachable, // unsupported target format |
| 5543 | 5500 | }; |
| 5544 | 5501 | _ = try self.addInst(.{ |
| ... | ... | @@ -5651,8 +5608,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5651 | 5608 | const mod = self.bin_file.options.module.?; |
| 5652 | 5609 | const owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 5653 | 5610 | const atom_index = switch (self.bin_file.tag) { |
| 5654 | .macho => owner_decl.link.macho.sym_index, | |
| 5655 | .coff => owner_decl.link.coff.sym_index, | |
| 5611 | .macho => owner_decl.link.macho.getSymbolIndex().?, | |
| 5612 | .coff => owner_decl.link.coff.getSymbolIndex().?, | |
| 5656 | 5613 | else => unreachable, // unsupported target format |
| 5657 | 5614 | }; |
| 5658 | 5615 | _ = try self.addInst(.{ |
| ... | ... | @@ -5845,8 +5802,8 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 5845 | 5802 | const mod = self.bin_file.options.module.?; |
| 5846 | 5803 | const owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 5847 | 5804 | const atom_index = switch (self.bin_file.tag) { |
| 5848 | .macho => owner_decl.link.macho.sym_index, | |
| 5849 | .coff => owner_decl.link.coff.sym_index, | |
| 5805 | .macho => owner_decl.link.macho.getSymbolIndex().?, | |
| 5806 | .coff => owner_decl.link.coff.getSymbolIndex().?, | |
| 5850 | 5807 | else => unreachable, // unsupported target format |
| 5851 | 5808 | }; |
| 5852 | 5809 | _ = try self.addInst(.{ |
| ... | ... | @@ -6165,24 +6122,19 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 6165 | 6122 | mod.markDeclAlive(decl); |
| 6166 | 6123 | |
| 6167 | 6124 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 6168 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 6169 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | |
| 6170 | return MCValue{ .memory = got_addr }; | |
| 6171 | } else if (self.bin_file.cast(link.File.MachO)) |_| { | |
| 6172 | // Because MachO is PIE-always-on, we defer memory address resolution until | |
| 6173 | // the linker has enough info to perform relocations. | |
| 6174 | assert(decl.link.macho.sym_index != 0); | |
| 6125 | try decl.link.elf.ensureInitialized(elf_file); | |
| 6126 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; | |
| 6127 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 6128 | try decl.link.macho.ensureInitialized(macho_file); | |
| 6175 | 6129 | return MCValue{ .linker_load = .{ |
| 6176 | 6130 | .type = .got, |
| 6177 | .sym_index = decl.link.macho.sym_index, | |
| 6131 | .sym_index = decl.link.macho.getSymbolIndex().?, | |
| 6178 | 6132 | } }; |
| 6179 | } else if (self.bin_file.cast(link.File.Coff)) |_| { | |
| 6180 | // Because COFF is PIE-always-on, we defer memory address resolution until | |
| 6181 | // the linker has enough info to perform relocations. | |
| 6182 | assert(decl.link.coff.sym_index != 0); | |
| 6133 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 6134 | try decl.link.coff.ensureInitialized(coff_file); | |
| 6183 | 6135 | return MCValue{ .linker_load = .{ |
| 6184 | 6136 | .type = .got, |
| 6185 | .sym_index = decl.link.coff.sym_index, | |
| 6137 | .sym_index = decl.link.coff.getSymbolIndex().?, | |
| 6186 | 6138 | } }; |
| 6187 | 6139 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 6188 | 6140 | try p9.seeDecl(decl_index); |
src/arch/arm/CodeGen.zig+50-53| ... | ... | @@ -4253,59 +4253,57 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4253 | 4253 | |
| 4254 | 4254 | // Due to incremental compilation, how function calls are generated depends |
| 4255 | 4255 | // on linking. |
| 4256 | switch (self.bin_file.tag) { | |
| 4257 | .elf => { | |
| 4258 | if (self.air.value(callee)) |func_value| { | |
| 4259 | if (func_value.castTag(.function)) |func_payload| { | |
| 4260 | const func = func_payload.data; | |
| 4261 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 4262 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 4263 | const mod = self.bin_file.options.module.?; | |
| 4264 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4265 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { | |
| 4266 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 4267 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 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 | } | |
| 4256 | if (self.air.value(callee)) |func_value| { | |
| 4257 | if (func_value.castTag(.function)) |func_payload| { | |
| 4258 | const func = func_payload.data; | |
| 4259 | const mod = self.bin_file.options.module.?; | |
| 4260 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4261 | ||
| 4262 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 4263 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); | |
| 4264 | const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); | |
| 4265 | try self.genSetReg(Type.initTag(.usize), .lr, .{ .memory = got_addr }); | |
| 4266 | } else if (self.bin_file.cast(link.File.MachO)) |_| { | |
| 4267 | unreachable; // unsupported architecture for MachO | |
| 4275 | 4268 | } else { |
| 4276 | assert(ty.zigTypeTag() == .Pointer); | |
| 4277 | const mcv = try self.resolveInst(callee); | |
| 4278 | ||
| 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 }, | |
| 4269 | return self.fail("TODO implement call on {s} for {s}", .{ | |
| 4270 | @tagName(self.bin_file.tag), | |
| 4271 | @tagName(self.target.cpu.arch), | |
| 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 | }, | |
| 4305 | .macho => unreachable, // unsupported architecture for MachO | |
| 4306 | .coff => return self.fail("TODO implement call in COFF for {}", .{self.target.cpu.arch}), | |
| 4307 | .plan9 => return self.fail("TODO implement call on plan9 for {}", .{self.target.cpu.arch}), | |
| 4308 | else => unreachable, | |
| 4274 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 4275 | return self.fail("TODO implement calling extern functions", .{}); | |
| 4276 | } else { | |
| 4277 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 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 | 4309 | const result: MCValue = result: { |
| ... | ... | @@ -6086,9 +6084,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 6086 | 6084 | mod.markDeclAlive(decl); |
| 6087 | 6085 | |
| 6088 | 6086 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 6089 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 6090 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | |
| 6091 | return MCValue{ .memory = got_addr }; | |
| 6087 | try decl.link.elf.ensureInitialized(elf_file); | |
| 6088 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; | |
| 6092 | 6089 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 6093 | 6090 | unreachable; // unsupported architecture for MachO |
| 6094 | 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 | 1722 | if (func_value.castTag(.function)) |func_payload| { |
| 1723 | 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 | 1725 | const mod = self.bin_file.options.module.?; |
| 1728 | 1726 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 1729 | const got_addr = blk: { | |
| 1730 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 1731 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 1732 | }; | |
| 1727 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); | |
| 1728 | const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); | |
| 1733 | 1729 | |
| 1734 | 1730 | try self.genSetReg(Type.initTag(.usize), .ra, .{ .memory = got_addr }); |
| 1735 | 1731 | _ = try self.addInst(.{ |
| ... | ... | @@ -2557,9 +2553,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 2557 | 2553 | const decl = mod.declPtr(decl_index); |
| 2558 | 2554 | mod.markDeclAlive(decl); |
| 2559 | 2555 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 2560 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 2561 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | |
| 2562 | return MCValue{ .memory = got_addr }; | |
| 2556 | try decl.link.elf.ensureInitialized(elf_file); | |
| 2557 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; | |
| 2563 | 2558 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 2564 | 2559 | // TODO I'm hacking my way through here by repurposing .memory for storing |
| 2565 | 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 | 1216 | if (self.bin_file.tag == link.File.Elf.base_tag) { |
| 1217 | 1217 | if (func_value.castTag(.function)) |func_payload| { |
| 1218 | 1218 | const func = func_payload.data; |
| 1219 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 1220 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 1219 | const mod = self.bin_file.options.module.?; | |
| 1220 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 1221 | 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.?]; | |
| 1223 | const mod = self.bin_file.options.module.?; | |
| 1224 | break :blk @intCast(u32, got.p_vaddr + mod.declPtr(func.owner_decl).link.elf.offset_table_index * ptr_bytes); | |
| 1222 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); | |
| 1223 | break :blk @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); | |
| 1225 | 1224 | } else unreachable; |
| 1226 | 1225 | |
| 1227 | 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 | 4192 | } |
| 4194 | 4193 | |
| 4195 | 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 | 4195 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? |
| 4200 | 4196 | if (tv.ty.zigTypeTag() == .Pointer) blk: { |
| 4201 | 4197 | if (tv.ty.castPtrToFn()) |_| break :blk; |
| ... | ... | @@ -4209,9 +4205,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 4209 | 4205 | |
| 4210 | 4206 | mod.markDeclAlive(decl); |
| 4211 | 4207 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4212 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 4213 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | |
| 4214 | return MCValue{ .memory = got_addr }; | |
| 4208 | try decl.link.elf.ensureInitialized(elf_file); | |
| 4209 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; | |
| 4215 | 4210 | } else { |
| 4216 | 4211 | return self.fail("TODO codegen non-ELF const Decl pointer", .{}); |
| 4217 | 4212 | } |
src/arch/wasm/CodeGen.zig+10-3| ... | ... | @@ -2120,22 +2120,28 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2120 | 2120 | const module = func.bin_file.base.options.module.?; |
| 2121 | 2121 | |
| 2122 | 2122 | if (func_val.castTag(.function)) |function| { |
| 2123 | break :blk module.declPtr(function.data.owner_decl); | |
| 2123 | const decl = module.declPtr(function.data.owner_decl); | |
| 2124 | try decl.link.wasm.ensureInitialized(func.bin_file); | |
| 2125 | break :blk decl; | |
| 2124 | 2126 | } else if (func_val.castTag(.extern_fn)) |extern_fn| { |
| 2125 | 2127 | const ext_decl = module.declPtr(extern_fn.data.owner_decl); |
| 2126 | 2128 | const ext_info = ext_decl.ty.fnInfo(); |
| 2127 | 2129 | var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, func.target); |
| 2128 | 2130 | defer func_type.deinit(func.gpa); |
| 2131 | const atom = &ext_decl.link.wasm; | |
| 2132 | try atom.ensureInitialized(func.bin_file); | |
| 2129 | 2133 | ext_decl.fn_link.wasm.type_index = try func.bin_file.putOrGetFuncType(func_type); |
| 2130 | 2134 | try func.bin_file.addOrUpdateImport( |
| 2131 | 2135 | mem.sliceTo(ext_decl.name, 0), |
| 2132 | ext_decl.link.wasm.sym_index, | |
| 2136 | atom.getSymbolIndex().?, | |
| 2133 | 2137 | ext_decl.getExternFn().?.lib_name, |
| 2134 | 2138 | ext_decl.fn_link.wasm.type_index, |
| 2135 | 2139 | ); |
| 2136 | 2140 | break :blk ext_decl; |
| 2137 | 2141 | } else if (func_val.castTag(.decl_ref)) |decl_ref| { |
| 2138 | break :blk module.declPtr(decl_ref.data); | |
| 2142 | const decl = module.declPtr(decl_ref.data); | |
| 2143 | try decl.link.wasm.ensureInitialized(func.bin_file); | |
| 2144 | break :blk decl; | |
| 2139 | 2145 | } |
| 2140 | 2146 | return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()}); |
| 2141 | 2147 | }; |
| ... | ... | @@ -2752,6 +2758,7 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Ind |
| 2752 | 2758 | } |
| 2753 | 2759 | |
| 2754 | 2760 | module.markDeclAlive(decl); |
| 2761 | try decl.link.wasm.ensureInitialized(func.bin_file); | |
| 2755 | 2762 | |
| 2756 | 2763 | const target_sym_index = decl.link.wasm.sym_index; |
| 2757 | 2764 | if (decl.ty.zigTypeTag() == .Fn) { |
src/arch/x86_64/CodeGen.zig+69-132| ... | ... | @@ -2671,9 +2671,9 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2671 | 2671 | const mod = self.bin_file.options.module.?; |
| 2672 | 2672 | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 2673 | 2673 | const atom_index = if (self.bin_file.tag == link.File.MachO.base_tag) |
| 2674 | fn_owner_decl.link.macho.sym_index | |
| 2674 | fn_owner_decl.link.macho.getSymbolIndex().? | |
| 2675 | 2675 | else |
| 2676 | fn_owner_decl.link.coff.sym_index; | |
| 2676 | fn_owner_decl.link.coff.getSymbolIndex().?; | |
| 2677 | 2677 | const flags: u2 = switch (load_struct.type) { |
| 2678 | 2678 | .got => 0b00, |
| 2679 | 2679 | .direct => 0b01, |
| ... | ... | @@ -3992,49 +3992,26 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 3992 | 3992 | // Due to incremental compilation, how function calls are generated depends |
| 3993 | 3993 | // on linking. |
| 3994 | 3994 | const mod = self.bin_file.options.module.?; |
| 3995 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 3996 | if (self.air.value(callee)) |func_value| { | |
| 3997 | if (func_value.castTag(.function)) |func_payload| { | |
| 3998 | const func = func_payload.data; | |
| 3999 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 4000 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 4001 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4002 | const got_addr = blk: { | |
| 4003 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 4004 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 4005 | }; | |
| 3995 | if (self.air.value(callee)) |func_value| { | |
| 3996 | if (func_value.castTag(.function)) |func_payload| { | |
| 3997 | const func = func_payload.data; | |
| 3998 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 3999 | ||
| 4000 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 4001 | try fn_owner_decl.link.elf.ensureInitialized(elf_file); | |
| 4002 | const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file)); | |
| 4006 | 4003 | _ = try self.addInst(.{ |
| 4007 | 4004 | .tag = .call, |
| 4008 | 4005 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), |
| 4009 | .data = .{ .imm = @truncate(u32, got_addr) }, | |
| 4006 | .data = .{ .imm = got_addr }, | |
| 4010 | 4007 | }); |
| 4011 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 4012 | return self.fail("TODO implement calling extern functions", .{}); | |
| 4013 | } else { | |
| 4014 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4015 | } | |
| 4016 | } else { | |
| 4017 | assert(ty.zigTypeTag() == .Pointer); | |
| 4018 | const mcv = try self.resolveInst(callee); | |
| 4019 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | |
| 4020 | _ = try self.addInst(.{ | |
| 4021 | .tag = .call, | |
| 4022 | .ops = Mir.Inst.Ops.encode(.{ | |
| 4023 | .reg1 = .rax, | |
| 4024 | .flags = 0b01, | |
| 4025 | }), | |
| 4026 | .data = undefined, | |
| 4027 | }); | |
| 4028 | } | |
| 4029 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 4030 | if (self.air.value(callee)) |func_value| { | |
| 4031 | if (func_value.castTag(.function)) |func_payload| { | |
| 4032 | const func = func_payload.data; | |
| 4033 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4008 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 4009 | try fn_owner_decl.link.coff.ensureInitialized(coff_file); | |
| 4010 | const sym_index = fn_owner_decl.link.coff.getSymbolIndex().?; | |
| 4034 | 4011 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4035 | 4012 | .linker_load = .{ |
| 4036 | 4013 | .type = .got, |
| 4037 | .sym_index = fn_owner_decl.link.coff.sym_index, | |
| 4014 | .sym_index = sym_index, | |
| 4038 | 4015 | }, |
| 4039 | 4016 | }); |
| 4040 | 4017 | _ = try self.addInst(.{ |
| ... | ... | @@ -4045,19 +4022,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4045 | 4022 | }), |
| 4046 | 4023 | .data = undefined, |
| 4047 | 4024 | }); |
| 4048 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | |
| 4049 | const extern_fn = func_payload.data; | |
| 4050 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | |
| 4051 | if (extern_fn.lib_name) |lib_name| { | |
| 4052 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ | |
| 4053 | decl_name, | |
| 4054 | lib_name, | |
| 4055 | }); | |
| 4056 | } | |
| 4057 | const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); | |
| 4025 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 4026 | try fn_owner_decl.link.macho.ensureInitialized(macho_file); | |
| 4027 | const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?; | |
| 4058 | 4028 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4059 | 4029 | .linker_load = .{ |
| 4060 | .type = .import, | |
| 4030 | .type = .got, | |
| 4061 | 4031 | .sym_index = sym_index, |
| 4062 | 4032 | }, |
| 4063 | 4033 | }); |
| ... | ... | @@ -4069,35 +4039,37 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4069 | 4039 | }), |
| 4070 | 4040 | .data = undefined, |
| 4071 | 4041 | }); |
| 4072 | } else { | |
| 4073 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4042 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | |
| 4043 | try p9.seeDecl(func.owner_decl); | |
| 4044 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 4045 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 4046 | const got_addr = p9.bases.data; | |
| 4047 | const got_index = fn_owner_decl.link.plan9.got_index.?; | |
| 4048 | const fn_got_addr = got_addr + got_index * ptr_bytes; | |
| 4049 | _ = try self.addInst(.{ | |
| 4050 | .tag = .call, | |
| 4051 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), | |
| 4052 | .data = .{ .imm = @intCast(u32, fn_got_addr) }, | |
| 4053 | }); | |
| 4054 | } else unreachable; | |
| 4055 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | |
| 4056 | const extern_fn = func_payload.data; | |
| 4057 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | |
| 4058 | if (extern_fn.lib_name) |lib_name| { | |
| 4059 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ | |
| 4060 | decl_name, | |
| 4061 | lib_name, | |
| 4062 | }); | |
| 4074 | 4063 | } |
| 4075 | } else { | |
| 4076 | assert(ty.zigTypeTag() == .Pointer); | |
| 4077 | const mcv = try self.resolveInst(callee); | |
| 4078 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | |
| 4079 | _ = try self.addInst(.{ | |
| 4080 | .tag = .call, | |
| 4081 | .ops = Mir.Inst.Ops.encode(.{ | |
| 4082 | .reg1 = .rax, | |
| 4083 | .flags = 0b01, | |
| 4084 | }), | |
| 4085 | .data = undefined, | |
| 4086 | }); | |
| 4087 | } | |
| 4088 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 4089 | if (self.air.value(callee)) |func_value| { | |
| 4090 | if (func_value.castTag(.function)) |func_payload| { | |
| 4091 | const func = func_payload.data; | |
| 4092 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 4093 | const sym_index = fn_owner_decl.link.macho.sym_index; | |
| 4064 | ||
| 4065 | if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 4066 | const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); | |
| 4094 | 4067 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4095 | 4068 | .linker_load = .{ |
| 4096 | .type = .got, | |
| 4069 | .type = .import, | |
| 4097 | 4070 | .sym_index = sym_index, |
| 4098 | 4071 | }, |
| 4099 | 4072 | }); |
| 4100 | // callq *%rax | |
| 4101 | 4073 | _ = try self.addInst(.{ |
| 4102 | 4074 | .tag = .call, |
| 4103 | 4075 | .ops = Mir.Inst.Ops.encode(.{ |
| ... | ... | @@ -4106,71 +4078,37 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4106 | 4078 | }), |
| 4107 | 4079 | .data = undefined, |
| 4108 | 4080 | }); |
| 4109 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | |
| 4110 | const extern_fn = func_payload.data; | |
| 4111 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | |
| 4112 | if (extern_fn.lib_name) |lib_name| { | |
| 4113 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ | |
| 4114 | decl_name, | |
| 4115 | lib_name, | |
| 4116 | }); | |
| 4117 | } | |
| 4081 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 4118 | 4082 | const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); |
| 4119 | 4083 | _ = try self.addInst(.{ |
| 4120 | 4084 | .tag = .call_extern, |
| 4121 | 4085 | .ops = undefined, |
| 4122 | 4086 | .data = .{ |
| 4123 | 4087 | .relocation = .{ |
| 4124 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index, | |
| 4088 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?, | |
| 4125 | 4089 | .sym_index = sym_index, |
| 4126 | 4090 | }, |
| 4127 | 4091 | }, |
| 4128 | 4092 | }); |
| 4129 | 4093 | } else { |
| 4130 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4094 | return self.fail("TODO implement calling extern functions", .{}); | |
| 4131 | 4095 | } |
| 4132 | 4096 | } else { |
| 4133 | assert(ty.zigTypeTag() == .Pointer); | |
| 4134 | const mcv = try self.resolveInst(callee); | |
| 4135 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | |
| 4136 | _ = try self.addInst(.{ | |
| 4137 | .tag = .call, | |
| 4138 | .ops = Mir.Inst.Ops.encode(.{ | |
| 4139 | .reg1 = .rax, | |
| 4140 | .flags = 0b01, | |
| 4141 | }), | |
| 4142 | .data = undefined, | |
| 4143 | }); | |
| 4097 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4144 | 4098 | } |
| 4145 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | |
| 4146 | if (self.air.value(callee)) |func_value| { | |
| 4147 | if (func_value.castTag(.function)) |func_payload| { | |
| 4148 | try p9.seeDecl(func_payload.data.owner_decl); | |
| 4149 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 4150 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 4151 | const got_addr = p9.bases.data; | |
| 4152 | const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?; | |
| 4153 | const fn_got_addr = got_addr + got_index * ptr_bytes; | |
| 4154 | _ = try self.addInst(.{ | |
| 4155 | .tag = .call, | |
| 4156 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), | |
| 4157 | .data = .{ .imm = @intCast(u32, fn_got_addr) }, | |
| 4158 | }); | |
| 4159 | } else return self.fail("TODO implement calling extern fn on plan9", .{}); | |
| 4160 | } else { | |
| 4161 | assert(ty.zigTypeTag() == .Pointer); | |
| 4162 | const mcv = try self.resolveInst(callee); | |
| 4163 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | |
| 4164 | _ = try self.addInst(.{ | |
| 4165 | .tag = .call, | |
| 4166 | .ops = Mir.Inst.Ops.encode(.{ | |
| 4167 | .reg1 = .rax, | |
| 4168 | .flags = 0b01, | |
| 4169 | }), | |
| 4170 | .data = undefined, | |
| 4171 | }); | |
| 4172 | } | |
| 4173 | } else unreachable; | |
| 4099 | } else { | |
| 4100 | assert(ty.zigTypeTag() == .Pointer); | |
| 4101 | const mcv = try self.resolveInst(callee); | |
| 4102 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | |
| 4103 | _ = try self.addInst(.{ | |
| 4104 | .tag = .call, | |
| 4105 | .ops = Mir.Inst.Ops.encode(.{ | |
| 4106 | .reg1 = .rax, | |
| 4107 | .flags = 0b01, | |
| 4108 | }), | |
| 4109 | .data = undefined, | |
| 4110 | }); | |
| 4111 | } | |
| 4174 | 4112 | |
| 4175 | 4113 | if (info.stack_byte_count > 0) { |
| 4176 | 4114 | // Readjust the stack |
| ... | ... | @@ -6781,20 +6719,19 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne |
| 6781 | 6719 | module.markDeclAlive(decl); |
| 6782 | 6720 | |
| 6783 | 6721 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 6784 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | |
| 6785 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | |
| 6786 | return MCValue{ .memory = got_addr }; | |
| 6787 | } else if (self.bin_file.cast(link.File.MachO)) |_| { | |
| 6788 | assert(decl.link.macho.sym_index != 0); | |
| 6722 | try decl.link.elf.ensureInitialized(elf_file); | |
| 6723 | return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) }; | |
| 6724 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 6725 | try decl.link.macho.ensureInitialized(macho_file); | |
| 6789 | 6726 | return MCValue{ .linker_load = .{ |
| 6790 | 6727 | .type = .got, |
| 6791 | .sym_index = decl.link.macho.sym_index, | |
| 6728 | .sym_index = decl.link.macho.getSymbolIndex().?, | |
| 6792 | 6729 | } }; |
| 6793 | } else if (self.bin_file.cast(link.File.Coff)) |_| { | |
| 6794 | assert(decl.link.coff.sym_index != 0); | |
| 6730 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 6731 | try decl.link.coff.ensureInitialized(coff_file); | |
| 6795 | 6732 | return MCValue{ .linker_load = .{ |
| 6796 | 6733 | .type = .got, |
| 6797 | .sym_index = decl.link.coff.sym_index, | |
| 6734 | .sym_index = decl.link.coff.getSymbolIndex().?, | |
| 6798 | 6735 | } }; |
| 6799 | 6736 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 6800 | 6737 | try p9.seeDecl(decl_index); |
src/link.zig+5-28| ... | ... | @@ -533,8 +533,7 @@ pub const File = struct { |
| 533 | 533 | } |
| 534 | 534 | } |
| 535 | 535 | |
| 536 | /// May be called before or after updateDeclExports but must be called | |
| 537 | /// after allocateDeclIndexes for any given Decl. | |
| 536 | /// May be called before or after updateDeclExports for any given Decl. | |
| 538 | 537 | pub fn updateDecl(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void { |
| 539 | 538 | const decl = module.declPtr(decl_index); |
| 540 | 539 | log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty.fmtDebug() }); |
| ... | ... | @@ -557,8 +556,7 @@ pub const File = struct { |
| 557 | 556 | } |
| 558 | 557 | } |
| 559 | 558 | |
| 560 | /// May be called before or after updateDeclExports but must be called | |
| 561 | /// after allocateDeclIndexes for any given Decl. | |
| 559 | /// May be called before or after updateDeclExports for any given Decl. | |
| 562 | 560 | pub fn updateFunc(base: *File, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) UpdateDeclError!void { |
| 563 | 561 | const owner_decl = module.declPtr(func.owner_decl); |
| 564 | 562 | log.debug("updateFunc {*} ({s}), type={}", .{ |
| ... | ... | @@ -602,28 +600,6 @@ pub const File = struct { |
| 602 | 600 | } |
| 603 | 601 | } |
| 604 | 602 | |
| 605 | /// Must be called before any call to updateDecl or updateDeclExports for | |
| 606 | /// any given Decl. | |
| 607 | /// TODO we're transitioning to deleting this function and instead having | |
| 608 | /// each linker backend notice the first time updateDecl or updateFunc is called, or | |
| 609 | /// a callee referenced from AIR. | |
| 610 | pub fn allocateDeclIndexes(base: *File, decl_index: Module.Decl.Index) error{OutOfMemory}!void { | |
| 611 | const decl = base.options.module.?.declPtr(decl_index); | |
| 612 | log.debug("allocateDeclIndexes {*} ({s})", .{ decl, decl.name }); | |
| 613 | if (build_options.only_c) { | |
| 614 | assert(base.tag == .c); | |
| 615 | return; | |
| 616 | } | |
| 617 | switch (base.tag) { | |
| 618 | .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index), | |
| 619 | .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl_index), | |
| 620 | .macho => return @fieldParentPtr(MachO, "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), | |
| 623 | .c, .spirv, .nvptx => {}, | |
| 624 | } | |
| 625 | } | |
| 626 | ||
| 627 | 603 | pub fn releaseLock(self: *File) void { |
| 628 | 604 | if (self.lock) |*lock| { |
| 629 | 605 | lock.release(); |
| ... | ... | @@ -874,8 +850,7 @@ pub const File = struct { |
| 874 | 850 | AnalysisFail, |
| 875 | 851 | }; |
| 876 | 852 | |
| 877 | /// May be called before or after updateDecl, but must be called after | |
| 878 | /// allocateDeclIndexes for any given Decl. | |
| 853 | /// May be called before or after updateDecl for any given Decl. | |
| 879 | 854 | pub fn updateDeclExports( |
| 880 | 855 | base: *File, |
| 881 | 856 | module: *Module, |
| ... | ... | @@ -911,6 +886,8 @@ pub const File = struct { |
| 911 | 886 | /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's |
| 912 | 887 | /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the |
| 913 | 888 | /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory. |
| 889 | /// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate | |
| 890 | /// the block/atom. | |
| 914 | 891 | pub fn getDeclVAddr(base: *File, decl_index: Module.Decl.Index, reloc_info: RelocInfo) !u64 { |
| 915 | 892 | if (build_options.only_c) unreachable; |
| 916 | 893 | switch (base.tag) { |
src/link/Coff.zig+79-73| ... | ... | @@ -480,16 +480,6 @@ fn growSectionVM(self: *Coff, sect_id: u32, needed_size: u32) !void { |
| 480 | 480 | header.virtual_size = increased_size; |
| 481 | 481 | } |
| 482 | 482 | |
| 483 | pub fn allocateDeclIndexes(self: *Coff, decl_index: Module.Decl.Index) !void { | |
| 484 | if (self.llvm_object) |_| return; | |
| 485 | const decl = self.base.options.module.?.declPtr(decl_index); | |
| 486 | if (decl.link.coff.sym_index != 0) return; | |
| 487 | decl.link.coff.sym_index = try self.allocateSymbol(); | |
| 488 | const gpa = self.base.allocator; | |
| 489 | try self.atom_by_index_table.putNoClobber(gpa, decl.link.coff.sym_index, &decl.link.coff); | |
| 490 | try self.decls.putNoClobber(gpa, decl_index, null); | |
| 491 | } | |
| 492 | ||
| 493 | 483 | fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u32 { |
| 494 | 484 | const tracy = trace(@src()); |
| 495 | 485 | defer tracy.end(); |
| ... | ... | @@ -615,7 +605,7 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u |
| 615 | 605 | return vaddr; |
| 616 | 606 | } |
| 617 | 607 | |
| 618 | fn allocateSymbol(self: *Coff) !u32 { | |
| 608 | pub fn allocateSymbol(self: *Coff) !u32 { | |
| 619 | 609 | const gpa = self.base.allocator; |
| 620 | 610 | try self.locals.ensureUnusedCapacity(gpa, 1); |
| 621 | 611 | |
| ... | ... | @@ -716,12 +706,11 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom { |
| 716 | 706 | const atom = try gpa.create(Atom); |
| 717 | 707 | errdefer gpa.destroy(atom); |
| 718 | 708 | atom.* = Atom.empty; |
| 719 | atom.sym_index = try self.allocateSymbol(); | |
| 709 | try atom.ensureInitialized(self); | |
| 720 | 710 | atom.size = @sizeOf(u64); |
| 721 | 711 | atom.alignment = @alignOf(u64); |
| 722 | 712 | |
| 723 | 713 | try self.managed_atoms.append(gpa, atom); |
| 724 | try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); | |
| 725 | 714 | |
| 726 | 715 | const sym = atom.getSymbolPtr(self); |
| 727 | 716 | sym.section_number = @intToEnum(coff.SectionNumber, self.got_section_index.? + 1); |
| ... | ... | @@ -754,12 +743,11 @@ fn createImportAtom(self: *Coff) !*Atom { |
| 754 | 743 | const atom = try gpa.create(Atom); |
| 755 | 744 | errdefer gpa.destroy(atom); |
| 756 | 745 | atom.* = Atom.empty; |
| 757 | atom.sym_index = try self.allocateSymbol(); | |
| 746 | try atom.ensureInitialized(self); | |
| 758 | 747 | atom.size = @sizeOf(u64); |
| 759 | 748 | atom.alignment = @alignOf(u64); |
| 760 | 749 | |
| 761 | 750 | try self.managed_atoms.append(gpa, atom); |
| 762 | try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); | |
| 763 | 751 | |
| 764 | 752 | const sym = atom.getSymbolPtr(self); |
| 765 | 753 | sym.section_number = @intToEnum(coff.SectionNumber, self.idata_section_index.? + 1); |
| ... | ... | @@ -790,7 +778,11 @@ fn writeAtom(self: *Coff, atom: *Atom, code: []const u8) !void { |
| 790 | 778 | const sym = atom.getSymbol(self); |
| 791 | 779 | const section = self.sections.get(@enumToInt(sym.section_number) - 1); |
| 792 | 780 | const file_offset = section.header.pointer_to_raw_data + sym.value - section.header.virtual_address; |
| 793 | log.debug("writing atom for symbol {s} at file offset 0x{x} to 0x{x}", .{ atom.getName(self), file_offset, file_offset + code.len }); | |
| 781 | log.debug("writing atom for symbol {s} at file offset 0x{x} to 0x{x}", .{ | |
| 782 | atom.getName(self), | |
| 783 | file_offset, | |
| 784 | file_offset + code.len, | |
| 785 | }); | |
| 794 | 786 | try self.base.file.?.pwriteAll(code, file_offset); |
| 795 | 787 | try self.resolveRelocs(atom); |
| 796 | 788 | } |
| ... | ... | @@ -848,6 +840,7 @@ fn freeAtom(self: *Coff, atom: *Atom) void { |
| 848 | 840 | // Remove any relocs and base relocs associated with this Atom |
| 849 | 841 | self.freeRelocationsForAtom(atom); |
| 850 | 842 | |
| 843 | const gpa = self.base.allocator; | |
| 851 | 844 | const sym = atom.getSymbol(self); |
| 852 | 845 | const sect_id = @enumToInt(sym.section_number) - 1; |
| 853 | 846 | const free_list = &self.sections.items(.free_list)[sect_id]; |
| ... | ... | @@ -885,7 +878,7 @@ fn freeAtom(self: *Coff, atom: *Atom) void { |
| 885 | 878 | if (!already_have_free_list_node and prev.freeListEligible(self)) { |
| 886 | 879 | // The free list is heuristics, it doesn't have to be perfect, so we can |
| 887 | 880 | // ignore the OOM here. |
| 888 | free_list.append(self.base.allocator, prev) catch {}; | |
| 881 | free_list.append(gpa, prev) catch {}; | |
| 889 | 882 | } |
| 890 | 883 | } else { |
| 891 | 884 | atom.prev = null; |
| ... | ... | @@ -896,6 +889,28 @@ fn freeAtom(self: *Coff, atom: *Atom) void { |
| 896 | 889 | } else { |
| 897 | 890 | atom.next = null; |
| 898 | 891 | } |
| 892 | ||
| 893 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | |
| 894 | const sym_index = atom.getSymbolIndex().?; | |
| 895 | self.locals_free_list.append(gpa, sym_index) catch {}; | |
| 896 | ||
| 897 | // Try freeing GOT atom if this decl had one | |
| 898 | const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 899 | if (self.got_entries_table.get(got_target)) |got_index| { | |
| 900 | self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {}; | |
| 901 | self.got_entries.items[got_index] = .{ | |
| 902 | .target = .{ .sym_index = 0, .file = null }, | |
| 903 | .sym_index = 0, | |
| 904 | }; | |
| 905 | _ = self.got_entries_table.remove(got_target); | |
| 906 | ||
| 907 | log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); | |
| 908 | } | |
| 909 | ||
| 910 | self.locals.items[sym_index].section_number = .UNDEFINED; | |
| 911 | _ = self.atom_by_index_table.remove(sym_index); | |
| 912 | log.debug(" adding local symbol index {d} to free list", .{sym_index}); | |
| 913 | atom.sym_index = 0; | |
| 899 | 914 | } |
| 900 | 915 | |
| 901 | 916 | pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { |
| ... | ... | @@ -912,8 +927,15 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live |
| 912 | 927 | |
| 913 | 928 | const decl_index = func.owner_decl; |
| 914 | 929 | const decl = module.declPtr(decl_index); |
| 915 | self.freeUnnamedConsts(decl_index); | |
| 916 | self.freeRelocationsForAtom(&decl.link.coff); | |
| 930 | const atom = &decl.link.coff; | |
| 931 | try atom.ensureInitialized(self); | |
| 932 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | |
| 933 | if (gop.found_existing) { | |
| 934 | self.freeUnnamedConsts(decl_index); | |
| 935 | self.freeRelocationsForAtom(&decl.link.coff); | |
| 936 | } else { | |
| 937 | gop.value_ptr.* = null; | |
| 938 | } | |
| 917 | 939 | |
| 918 | 940 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 919 | 941 | defer code_buffer.deinit(); |
| ... | ... | @@ -960,9 +982,9 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In |
| 960 | 982 | const atom = try gpa.create(Atom); |
| 961 | 983 | errdefer gpa.destroy(atom); |
| 962 | 984 | atom.* = Atom.empty; |
| 985 | try atom.ensureInitialized(self); | |
| 986 | try self.managed_atoms.append(gpa, atom); | |
| 963 | 987 | |
| 964 | atom.sym_index = try self.allocateSymbol(); | |
| 965 | const sym = atom.getSymbolPtr(self); | |
| 966 | 988 | const sym_name = blk: { |
| 967 | 989 | const decl_name = try decl.getFullyQualifiedName(mod); |
| 968 | 990 | defer gpa.free(decl_name); |
| ... | ... | @@ -971,14 +993,11 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In |
| 971 | 993 | break :blk try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| 972 | 994 | }; |
| 973 | 995 | defer gpa.free(sym_name); |
| 974 | try self.setSymbolName(sym, sym_name); | |
| 975 | sym.section_number = @intToEnum(coff.SectionNumber, self.rdata_section_index.? + 1); | |
| 976 | ||
| 977 | try self.managed_atoms.append(gpa, atom); | |
| 978 | try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); | |
| 996 | try self.setSymbolName(atom.getSymbolPtr(self), sym_name); | |
| 997 | atom.getSymbolPtr(self).section_number = @intToEnum(coff.SectionNumber, self.rdata_section_index.? + 1); | |
| 979 | 998 | |
| 980 | 999 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .none, .{ |
| 981 | .parent_atom_index = atom.sym_index, | |
| 1000 | .parent_atom_index = atom.getSymbolIndex().?, | |
| 982 | 1001 | }); |
| 983 | 1002 | const code = switch (res) { |
| 984 | 1003 | .ok => code_buffer.items, |
| ... | ... | @@ -993,17 +1012,17 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In |
| 993 | 1012 | const required_alignment = tv.ty.abiAlignment(self.base.options.target); |
| 994 | 1013 | atom.alignment = required_alignment; |
| 995 | 1014 | atom.size = @intCast(u32, code.len); |
| 996 | sym.value = try self.allocateAtom(atom, atom.size, atom.alignment); | |
| 1015 | atom.getSymbolPtr(self).value = try self.allocateAtom(atom, atom.size, atom.alignment); | |
| 997 | 1016 | errdefer self.freeAtom(atom); |
| 998 | 1017 | |
| 999 | 1018 | try unnamed_consts.append(gpa, atom); |
| 1000 | 1019 | |
| 1001 | log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, sym.value }); | |
| 1020 | log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, atom.getSymbol(self).value }); | |
| 1002 | 1021 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 1003 | 1022 | |
| 1004 | 1023 | try self.writeAtom(atom, code); |
| 1005 | 1024 | |
| 1006 | return atom.sym_index; | |
| 1025 | return atom.getSymbolIndex().?; | |
| 1007 | 1026 | } |
| 1008 | 1027 | |
| 1009 | 1028 | pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !void { |
| ... | ... | @@ -1028,7 +1047,14 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! |
| 1028 | 1047 | } |
| 1029 | 1048 | } |
| 1030 | 1049 | |
| 1031 | self.freeRelocationsForAtom(&decl.link.coff); | |
| 1050 | const atom = &decl.link.coff; | |
| 1051 | try atom.ensureInitialized(self); | |
| 1052 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | |
| 1053 | if (gop.found_existing) { | |
| 1054 | self.freeRelocationsForAtom(atom); | |
| 1055 | } else { | |
| 1056 | gop.value_ptr.* = null; | |
| 1057 | } | |
| 1032 | 1058 | |
| 1033 | 1059 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 1034 | 1060 | defer code_buffer.deinit(); |
| ... | ... | @@ -1038,7 +1064,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! |
| 1038 | 1064 | .ty = decl.ty, |
| 1039 | 1065 | .val = decl_val, |
| 1040 | 1066 | }, &code_buffer, .none, .{ |
| 1041 | .parent_atom_index = decl.link.coff.sym_index, | |
| 1067 | .parent_atom_index = decl.link.coff.getSymbolIndex().?, | |
| 1042 | 1068 | }); |
| 1043 | 1069 | const code = switch (res) { |
| 1044 | 1070 | .ok => code_buffer.items, |
| ... | ... | @@ -1099,7 +1125,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, |
| 1099 | 1125 | |
| 1100 | 1126 | const code_len = @intCast(u32, code.len); |
| 1101 | 1127 | const atom = &decl.link.coff; |
| 1102 | assert(atom.sym_index != 0); // Caller forgot to allocateDeclIndexes() | |
| 1128 | ||
| 1103 | 1129 | if (atom.size != 0) { |
| 1104 | 1130 | const sym = atom.getSymbolPtr(self); |
| 1105 | 1131 | try self.setSymbolName(sym, decl_name); |
| ... | ... | @@ -1116,7 +1142,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, |
| 1116 | 1142 | if (vaddr != sym.value) { |
| 1117 | 1143 | sym.value = vaddr; |
| 1118 | 1144 | log.debug(" (updating GOT entry)", .{}); |
| 1119 | const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null }; | |
| 1145 | const got_target = SymbolWithLoc{ .sym_index = atom.getSymbolIndex().?, .file = null }; | |
| 1120 | 1146 | const got_atom = self.getGotAtomForSymbol(got_target).?; |
| 1121 | 1147 | self.markRelocsDirtyByTarget(got_target); |
| 1122 | 1148 | try self.writePtrWidthAtom(got_atom); |
| ... | ... | @@ -1137,10 +1163,10 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, |
| 1137 | 1163 | atom.size = code_len; |
| 1138 | 1164 | sym.value = vaddr; |
| 1139 | 1165 | |
| 1140 | const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null }; | |
| 1166 | const got_target = SymbolWithLoc{ .sym_index = atom.getSymbolIndex().?, .file = null }; | |
| 1141 | 1167 | const got_index = try self.allocateGotEntry(got_target); |
| 1142 | 1168 | const got_atom = try self.createGotAtom(got_target); |
| 1143 | self.got_entries.items[got_index].sym_index = got_atom.sym_index; | |
| 1169 | self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?; | |
| 1144 | 1170 | try self.writePtrWidthAtom(got_atom); |
| 1145 | 1171 | } |
| 1146 | 1172 | |
| ... | ... | @@ -1160,11 +1186,6 @@ fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void { |
| 1160 | 1186 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; |
| 1161 | 1187 | for (unnamed_consts.items) |atom| { |
| 1162 | 1188 | self.freeAtom(atom); |
| 1163 | self.locals_free_list.append(gpa, atom.sym_index) catch {}; | |
| 1164 | self.locals.items[atom.sym_index].section_number = .UNDEFINED; | |
| 1165 | _ = self.atom_by_index_table.remove(atom.sym_index); | |
| 1166 | log.debug(" adding local symbol index {d} to free list", .{atom.sym_index}); | |
| 1167 | atom.sym_index = 0; | |
| 1168 | 1189 | } |
| 1169 | 1190 | unnamed_consts.clearAndFree(gpa); |
| 1170 | 1191 | } |
| ... | ... | @@ -1179,35 +1200,11 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { |
| 1179 | 1200 | |
| 1180 | 1201 | log.debug("freeDecl {*}", .{decl}); |
| 1181 | 1202 | |
| 1182 | const kv = self.decls.fetchRemove(decl_index); | |
| 1183 | if (kv.?.value) |_| { | |
| 1184 | self.freeAtom(&decl.link.coff); | |
| 1185 | self.freeUnnamedConsts(decl_index); | |
| 1186 | } | |
| 1187 | ||
| 1188 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | |
| 1189 | const gpa = self.base.allocator; | |
| 1190 | const sym_index = decl.link.coff.sym_index; | |
| 1191 | if (sym_index != 0) { | |
| 1192 | self.locals_free_list.append(gpa, sym_index) catch {}; | |
| 1193 | ||
| 1194 | // Try freeing GOT atom if this decl had one | |
| 1195 | const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 1196 | if (self.got_entries_table.get(got_target)) |got_index| { | |
| 1197 | self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {}; | |
| 1198 | self.got_entries.items[got_index] = .{ | |
| 1199 | .target = .{ .sym_index = 0, .file = null }, | |
| 1200 | .sym_index = 0, | |
| 1201 | }; | |
| 1202 | _ = self.got_entries_table.remove(got_target); | |
| 1203 | ||
| 1204 | log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); | |
| 1203 | if (self.decls.fetchRemove(decl_index)) |kv| { | |
| 1204 | if (kv.value) |_| { | |
| 1205 | self.freeAtom(&decl.link.coff); | |
| 1206 | self.freeUnnamedConsts(decl_index); | |
| 1205 | 1207 | } |
| 1206 | ||
| 1207 | self.locals.items[sym_index].section_number = .UNDEFINED; | |
| 1208 | _ = self.atom_by_index_table.remove(sym_index); | |
| 1209 | log.debug(" adding local symbol index {d} to free list", .{sym_index}); | |
| 1210 | decl.link.coff.sym_index = 0; | |
| 1211 | 1208 | } |
| 1212 | 1209 | } |
| 1213 | 1210 | |
| ... | ... | @@ -1261,7 +1258,14 @@ pub fn updateDeclExports( |
| 1261 | 1258 | |
| 1262 | 1259 | const decl = module.declPtr(decl_index); |
| 1263 | 1260 | const atom = &decl.link.coff; |
| 1264 | if (atom.sym_index == 0) return; | |
| 1261 | ||
| 1262 | if (atom.getSymbolIndex() == null) return; | |
| 1263 | ||
| 1264 | const gop = try self.decls.getOrPut(gpa, decl_index); | |
| 1265 | if (!gop.found_existing) { | |
| 1266 | gop.value_ptr.* = self.getDeclOutputSection(decl); | |
| 1267 | } | |
| 1268 | ||
| 1265 | 1269 | const decl_sym = atom.getSymbol(self); |
| 1266 | 1270 | |
| 1267 | 1271 | for (exports) |exp| { |
| ... | ... | @@ -1416,7 +1420,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1416 | 1420 | |
| 1417 | 1421 | const import_index = try self.allocateImportEntry(global); |
| 1418 | 1422 | const import_atom = try self.createImportAtom(); |
| 1419 | self.imports.items[import_index].sym_index = import_atom.sym_index; | |
| 1423 | self.imports.items[import_index].sym_index = import_atom.getSymbolIndex().?; | |
| 1420 | 1424 | try self.writePtrWidthAtom(import_atom); |
| 1421 | 1425 | } |
| 1422 | 1426 | |
| ... | ... | @@ -1460,10 +1464,12 @@ pub fn getDeclVAddr( |
| 1460 | 1464 | const decl = mod.declPtr(decl_index); |
| 1461 | 1465 | |
| 1462 | 1466 | assert(self.llvm_object == null); |
| 1463 | assert(decl.link.coff.sym_index != 0); | |
| 1467 | ||
| 1468 | try decl.link.coff.ensureInitialized(self); | |
| 1469 | const sym_index = decl.link.coff.getSymbolIndex().?; | |
| 1464 | 1470 | |
| 1465 | 1471 | const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?; |
| 1466 | const target = SymbolWithLoc{ .sym_index = decl.link.coff.sym_index, .file = null }; | |
| 1472 | const target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 1467 | 1473 | try atom.addRelocation(self, .{ |
| 1468 | 1474 | .type = .direct, |
| 1469 | 1475 | .target = target, |
src/link/Coff/Atom.zig+19-4| ... | ... | @@ -39,30 +39,45 @@ pub const empty = Atom{ |
| 39 | 39 | .next = null, |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | pub fn ensureInitialized(self: *Atom, coff_file: *Coff) !void { | |
| 43 | if (self.getSymbolIndex() != null) return; // Already initialized | |
| 44 | self.sym_index = try coff_file.allocateSymbol(); | |
| 45 | try coff_file.atom_by_index_table.putNoClobber(coff_file.base.allocator, self.sym_index, self); | |
| 46 | } | |
| 47 | ||
| 48 | pub fn getSymbolIndex(self: Atom) ?u32 { | |
| 49 | if (self.sym_index == 0) return null; | |
| 50 | return self.sym_index; | |
| 51 | } | |
| 52 | ||
| 42 | 53 | /// Returns symbol referencing this atom. |
| 43 | 54 | pub fn getSymbol(self: Atom, coff_file: *const Coff) *const coff.Symbol { |
| 55 | const sym_index = self.getSymbolIndex().?; | |
| 44 | 56 | return coff_file.getSymbol(.{ |
| 45 | .sym_index = self.sym_index, | |
| 57 | .sym_index = sym_index, | |
| 46 | 58 | .file = self.file, |
| 47 | 59 | }); |
| 48 | 60 | } |
| 49 | 61 | |
| 50 | 62 | /// Returns pointer-to-symbol referencing this atom. |
| 51 | 63 | pub fn getSymbolPtr(self: Atom, coff_file: *Coff) *coff.Symbol { |
| 64 | const sym_index = self.getSymbolIndex().?; | |
| 52 | 65 | return coff_file.getSymbolPtr(.{ |
| 53 | .sym_index = self.sym_index, | |
| 66 | .sym_index = sym_index, | |
| 54 | 67 | .file = self.file, |
| 55 | 68 | }); |
| 56 | 69 | } |
| 57 | 70 | |
| 58 | 71 | pub fn getSymbolWithLoc(self: Atom) SymbolWithLoc { |
| 59 | return .{ .sym_index = self.sym_index, .file = self.file }; | |
| 72 | const sym_index = self.getSymbolIndex().?; | |
| 73 | return .{ .sym_index = sym_index, .file = self.file }; | |
| 60 | 74 | } |
| 61 | 75 | |
| 62 | 76 | /// Returns the name of this atom. |
| 63 | 77 | pub fn getName(self: Atom, coff_file: *const Coff) []const u8 { |
| 78 | const sym_index = self.getSymbolIndex().?; | |
| 64 | 79 | return coff_file.getSymbolName(.{ |
| 65 | .sym_index = self.sym_index, | |
| 80 | .sym_index = sym_index, | |
| 66 | 81 | .file = self.file, |
| 67 | 82 | }); |
| 68 | 83 | } |
src/link/Elf.zig+99-131| ... | ... | @@ -10,6 +10,7 @@ const fs = std.fs; |
| 10 | 10 | const elf = std.elf; |
| 11 | 11 | const log = std.log.scoped(.link); |
| 12 | 12 | |
| 13 | const Atom = @import("Elf/Atom.zig"); | |
| 13 | 14 | const Module = @import("../Module.zig"); |
| 14 | 15 | const Compilation = @import("../Compilation.zig"); |
| 15 | 16 | const Dwarf = @import("Dwarf.zig"); |
| ... | ... | @@ -31,6 +32,8 @@ const Air = @import("../Air.zig"); |
| 31 | 32 | const Liveness = @import("../Liveness.zig"); |
| 32 | 33 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 33 | 34 | |
| 35 | pub const TextBlock = Atom; | |
| 36 | ||
| 34 | 37 | const default_entry_addr = 0x8000000; |
| 35 | 38 | |
| 36 | 39 | pub const base_tag: File.Tag = .elf; |
| ... | ... | @@ -188,62 +191,10 @@ const ideal_factor = 3; |
| 188 | 191 | /// it as a possible place to put new symbols, it must have enough room for this many bytes |
| 189 | 192 | /// (plus extra for reserved capacity). |
| 190 | 193 | const minimum_text_block_size = 64; |
| 191 | const min_text_capacity = padToIdeal(minimum_text_block_size); | |
| 194 | pub const min_text_capacity = padToIdeal(minimum_text_block_size); | |
| 192 | 195 | |
| 193 | 196 | pub const PtrWidth = enum { p32, p64 }; |
| 194 | 197 | |
| 195 | pub const TextBlock = struct { | |
| 196 | /// Each decl always gets a local symbol with the fully qualified name. | |
| 197 | /// The vaddr and size are found here directly. | |
| 198 | /// The file offset is found by computing the vaddr offset from the section vaddr | |
| 199 | /// the symbol references, and adding that to the file offset of the section. | |
| 200 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or | |
| 201 | /// offset table entry. | |
| 202 | local_sym_index: u32, | |
| 203 | /// This field is undefined for symbols with size = 0. | |
| 204 | offset_table_index: u32, | |
| 205 | /// Points to the previous and next neighbors, based on the `text_offset`. | |
| 206 | /// This can be used to find, for example, the capacity of this `TextBlock`. | |
| 207 | prev: ?*TextBlock, | |
| 208 | next: ?*TextBlock, | |
| 209 | ||
| 210 | dbg_info_atom: Dwarf.Atom, | |
| 211 | ||
| 212 | pub const empty = TextBlock{ | |
| 213 | .local_sym_index = 0, | |
| 214 | .offset_table_index = undefined, | |
| 215 | .prev = null, | |
| 216 | .next = null, | |
| 217 | .dbg_info_atom = undefined, | |
| 218 | }; | |
| 219 | ||
| 220 | /// Returns how much room there is to grow in virtual address space. | |
| 221 | /// File offset relocation happens transparently, so it is not included in | |
| 222 | /// this calculation. | |
| 223 | fn capacity(self: TextBlock, elf_file: Elf) u64 { | |
| 224 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; | |
| 225 | if (self.next) |next| { | |
| 226 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; | |
| 227 | return next_sym.st_value - self_sym.st_value; | |
| 228 | } else { | |
| 229 | // We are the last block. The capacity is limited only by virtual address space. | |
| 230 | return std.math.maxInt(u32) - self_sym.st_value; | |
| 231 | } | |
| 232 | } | |
| 233 | ||
| 234 | fn freeListEligible(self: TextBlock, elf_file: Elf) bool { | |
| 235 | // No need to keep a free list node for the last block. | |
| 236 | const next = self.next orelse return false; | |
| 237 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; | |
| 238 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; | |
| 239 | const cap = next_sym.st_value - self_sym.st_value; | |
| 240 | const ideal_cap = padToIdeal(self_sym.st_size); | |
| 241 | if (cap <= ideal_cap) return false; | |
| 242 | const surplus = cap - ideal_cap; | |
| 243 | return surplus >= min_text_capacity; | |
| 244 | } | |
| 245 | }; | |
| 246 | ||
| 247 | 198 | pub const Export = struct { |
| 248 | 199 | sym_index: ?u32 = null, |
| 249 | 200 | }; |
| ... | ... | @@ -393,9 +344,10 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: File. |
| 393 | 344 | const decl = mod.declPtr(decl_index); |
| 394 | 345 | |
| 395 | 346 | assert(self.llvm_object == null); |
| 396 | assert(decl.link.elf.local_sym_index != 0); | |
| 397 | 347 | |
| 398 | const target = decl.link.elf.local_sym_index; | |
| 348 | try decl.link.elf.ensureInitialized(self); | |
| 349 | const target = decl.link.elf.getSymbolIndex().?; | |
| 350 | ||
| 399 | 351 | const vaddr = self.local_symbols.items[target].st_value; |
| 400 | 352 | const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?; |
| 401 | 353 | const gop = try self.relocs.getOrPut(self.base.allocator, atom); |
| ... | ... | @@ -496,7 +448,7 @@ fn makeString(self: *Elf, bytes: []const u8) !u32 { |
| 496 | 448 | return @intCast(u32, result); |
| 497 | 449 | } |
| 498 | 450 | |
| 499 | fn getString(self: Elf, str_off: u32) []const u8 { | |
| 451 | pub fn getString(self: Elf, str_off: u32) []const u8 { | |
| 500 | 452 | assert(str_off < self.shstrtab.items.len); |
| 501 | 453 | return mem.sliceTo(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off), 0); |
| 502 | 454 | } |
| ... | ... | @@ -941,7 +893,7 @@ fn growAllocSection(self: *Elf, shdr_index: u16, phdr_index: u16, needed_size: u |
| 941 | 893 | // Must move the entire section. |
| 942 | 894 | const new_offset = self.findFreeSpace(needed_size, self.page_size); |
| 943 | 895 | const existing_size = if (self.atoms.get(phdr_index)) |last| blk: { |
| 944 | const sym = self.local_symbols.items[last.local_sym_index]; | |
| 896 | const sym = last.getSymbol(self); | |
| 945 | 897 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; |
| 946 | 898 | } else if (shdr_index == self.got_section_index.?) blk: { |
| 947 | 899 | break :blk shdr.sh_size; |
| ... | ... | @@ -1079,7 +1031,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1079 | 1031 | while (it.next()) |entry| { |
| 1080 | 1032 | const atom = entry.key_ptr.*; |
| 1081 | 1033 | const relocs = entry.value_ptr.*; |
| 1082 | const source_sym = self.local_symbols.items[atom.local_sym_index]; | |
| 1034 | const source_sym = atom.getSymbol(self); | |
| 1083 | 1035 | const source_shdr = self.sections.items[source_sym.st_shndx]; |
| 1084 | 1036 | |
| 1085 | 1037 | log.debug("relocating '{s}'", .{self.getString(source_sym.st_name)}); |
| ... | ... | @@ -2082,11 +2034,13 @@ fn writeElfHeader(self: *Elf) !void { |
| 2082 | 2034 | } |
| 2083 | 2035 | |
| 2084 | 2036 | fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { |
| 2085 | const local_sym = self.local_symbols.items[text_block.local_sym_index]; | |
| 2037 | const local_sym = text_block.getSymbol(self); | |
| 2086 | 2038 | const name_str_index = local_sym.st_name; |
| 2087 | 2039 | const name = self.getString(name_str_index); |
| 2088 | 2040 | log.debug("freeTextBlock {*} ({s})", .{ text_block, name }); |
| 2089 | 2041 | |
| 2042 | self.freeRelocationsForTextBlock(text_block); | |
| 2043 | ||
| 2090 | 2044 | const free_list = self.atom_free_lists.getPtr(phdr_index).?; |
| 2091 | 2045 | var already_have_free_list_node = false; |
| 2092 | 2046 | { |
| ... | ... | @@ -2118,7 +2072,7 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { |
| 2118 | 2072 | if (text_block.prev) |prev| { |
| 2119 | 2073 | prev.next = text_block.next; |
| 2120 | 2074 | |
| 2121 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { | |
| 2075 | if (!already_have_free_list_node and prev.freeListEligible(self)) { | |
| 2122 | 2076 | // The free list is heuristics, it doesn't have to be perfect, so we can |
| 2123 | 2077 | // ignore the OOM here. |
| 2124 | 2078 | free_list.append(self.base.allocator, prev) catch {}; |
| ... | ... | @@ -2133,6 +2087,15 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { |
| 2133 | 2087 | text_block.next = null; |
| 2134 | 2088 | } |
| 2135 | 2089 | |
| 2090 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | |
| 2091 | const local_sym_index = text_block.getSymbolIndex().?; | |
| 2092 | self.local_symbol_free_list.append(self.base.allocator, local_sym_index) catch {}; | |
| 2093 | self.local_symbols.items[local_sym_index].st_info = 0; | |
| 2094 | _ = self.atom_by_index_table.remove(local_sym_index); | |
| 2095 | text_block.local_sym_index = 0; | |
| 2096 | ||
| 2097 | self.offset_table_free_list.append(self.base.allocator, text_block.offset_table_index) catch {}; | |
| 2098 | ||
| 2136 | 2099 | if (self.dwarf) |*dw| { |
| 2137 | 2100 | dw.freeAtom(&text_block.dbg_info_atom); |
| 2138 | 2101 | } |
| ... | ... | @@ -2146,9 +2109,9 @@ fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, phdr |
| 2146 | 2109 | } |
| 2147 | 2110 | |
| 2148 | 2111 | fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64, phdr_index: u16) !u64 { |
| 2149 | const sym = self.local_symbols.items[text_block.local_sym_index]; | |
| 2112 | const sym = text_block.getSymbol(self); | |
| 2150 | 2113 | const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; |
| 2151 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*); | |
| 2114 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self); | |
| 2152 | 2115 | if (!need_realloc) return sym.st_value; |
| 2153 | 2116 | return self.allocateTextBlock(text_block, new_block_size, alignment, phdr_index); |
| 2154 | 2117 | } |
| ... | ... | @@ -2176,8 +2139,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2176 | 2139 | const big_block = free_list.items[i]; |
| 2177 | 2140 | // We now have a pointer to a live text block that has too much capacity. |
| 2178 | 2141 | // Is it enough that we could fit this new text block? |
| 2179 | const sym = self.local_symbols.items[big_block.local_sym_index]; | |
| 2180 | const capacity = big_block.capacity(self.*); | |
| 2142 | const sym = big_block.getSymbol(self); | |
| 2143 | const capacity = big_block.capacity(self); | |
| 2181 | 2144 | const ideal_capacity = padToIdeal(capacity); |
| 2182 | 2145 | const ideal_capacity_end_vaddr = std.math.add(u64, sym.st_value, ideal_capacity) catch ideal_capacity; |
| 2183 | 2146 | const capacity_end_vaddr = sym.st_value + capacity; |
| ... | ... | @@ -2187,7 +2150,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2187 | 2150 | // Additional bookkeeping here to notice if this free list node |
| 2188 | 2151 | // should be deleted because the block that it points to has grown to take up |
| 2189 | 2152 | // more of the extra capacity. |
| 2190 | if (!big_block.freeListEligible(self.*)) { | |
| 2153 | if (!big_block.freeListEligible(self)) { | |
| 2191 | 2154 | _ = free_list.swapRemove(i); |
| 2192 | 2155 | } else { |
| 2193 | 2156 | i += 1; |
| ... | ... | @@ -2207,7 +2170,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2207 | 2170 | } |
| 2208 | 2171 | break :blk new_start_vaddr; |
| 2209 | 2172 | } else if (self.atoms.get(phdr_index)) |last| { |
| 2210 | const sym = self.local_symbols.items[last.local_sym_index]; | |
| 2173 | const sym = last.getSymbol(self); | |
| 2211 | 2174 | const ideal_capacity = padToIdeal(sym.st_size); |
| 2212 | 2175 | const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity; |
| 2213 | 2176 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment); |
| ... | ... | @@ -2262,7 +2225,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2262 | 2225 | return vaddr; |
| 2263 | 2226 | } |
| 2264 | 2227 | |
| 2265 | fn allocateLocalSymbol(self: *Elf) !u32 { | |
| 2228 | pub fn allocateLocalSymbol(self: *Elf) !u32 { | |
| 2266 | 2229 | try self.local_symbols.ensureUnusedCapacity(self.base.allocator, 1); |
| 2267 | 2230 | |
| 2268 | 2231 | const index = blk: { |
| ... | ... | @@ -2289,40 +2252,35 @@ fn allocateLocalSymbol(self: *Elf) !u32 { |
| 2289 | 2252 | return index; |
| 2290 | 2253 | } |
| 2291 | 2254 | |
| 2292 | pub fn allocateDeclIndexes(self: *Elf, decl_index: Module.Decl.Index) !void { | |
| 2293 | if (self.llvm_object) |_| return; | |
| 2294 | ||
| 2295 | const mod = self.base.options.module.?; | |
| 2296 | const decl = mod.declPtr(decl_index); | |
| 2297 | if (decl.link.elf.local_sym_index != 0) return; | |
| 2298 | ||
| 2255 | pub fn allocateGotOffset(self: *Elf) !u32 { | |
| 2299 | 2256 | try self.offset_table.ensureUnusedCapacity(self.base.allocator, 1); |
| 2300 | try self.decls.putNoClobber(self.base.allocator, decl_index, null); | |
| 2301 | 2257 | |
| 2302 | const decl_name = try decl.getFullyQualifiedName(mod); | |
| 2303 | defer self.base.allocator.free(decl_name); | |
| 2258 | const index = blk: { | |
| 2259 | if (self.offset_table_free_list.popOrNull()) |index| { | |
| 2260 | log.debug(" (reusing GOT offset at index {d})", .{index}); | |
| 2261 | break :blk index; | |
| 2262 | } else { | |
| 2263 | log.debug(" (allocating GOT offset at index {d})", .{self.offset_table.items.len}); | |
| 2264 | const index = @intCast(u32, self.offset_table.items.len); | |
| 2265 | _ = self.offset_table.addOneAssumeCapacity(); | |
| 2266 | self.offset_table_count_dirty = true; | |
| 2267 | break :blk index; | |
| 2268 | } | |
| 2269 | }; | |
| 2304 | 2270 | |
| 2305 | log.debug("allocating symbol indexes for {s}", .{decl_name}); | |
| 2306 | decl.link.elf.local_sym_index = try self.allocateLocalSymbol(); | |
| 2307 | try self.atom_by_index_table.putNoClobber(self.base.allocator, decl.link.elf.local_sym_index, &decl.link.elf); | |
| 2271 | self.offset_table.items[index] = 0; | |
| 2272 | return index; | |
| 2273 | } | |
| 2308 | 2274 | |
| 2309 | if (self.offset_table_free_list.popOrNull()) |i| { | |
| 2310 | decl.link.elf.offset_table_index = i; | |
| 2311 | } else { | |
| 2312 | decl.link.elf.offset_table_index = @intCast(u32, self.offset_table.items.len); | |
| 2313 | _ = self.offset_table.addOneAssumeCapacity(); | |
| 2314 | self.offset_table_count_dirty = true; | |
| 2315 | } | |
| 2316 | self.offset_table.items[decl.link.elf.offset_table_index] = 0; | |
| 2275 | fn freeRelocationsForTextBlock(self: *Elf, text_block: *TextBlock) void { | |
| 2276 | var removed_relocs = self.relocs.fetchRemove(text_block); | |
| 2277 | if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator); | |
| 2317 | 2278 | } |
| 2318 | 2279 | |
| 2319 | 2280 | fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2320 | 2281 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; |
| 2321 | 2282 | for (unnamed_consts.items) |atom| { |
| 2322 | 2283 | self.freeTextBlock(atom, self.phdr_load_ro_index.?); |
| 2323 | self.local_symbol_free_list.append(self.base.allocator, atom.local_sym_index) catch {}; | |
| 2324 | self.local_symbols.items[atom.local_sym_index].st_info = 0; | |
| 2325 | _ = self.atom_by_index_table.remove(atom.local_sym_index); | |
| 2326 | 2284 | } |
| 2327 | 2285 | unnamed_consts.clearAndFree(self.base.allocator); |
| 2328 | 2286 | } |
| ... | ... | @@ -2335,20 +2293,13 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2335 | 2293 | const mod = self.base.options.module.?; |
| 2336 | 2294 | const decl = mod.declPtr(decl_index); |
| 2337 | 2295 | |
| 2338 | const kv = self.decls.fetchRemove(decl_index); | |
| 2339 | if (kv.?.value) |index| { | |
| 2340 | self.freeTextBlock(&decl.link.elf, index); | |
| 2341 | self.freeUnnamedConsts(decl_index); | |
| 2342 | } | |
| 2343 | ||
| 2344 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | |
| 2345 | if (decl.link.elf.local_sym_index != 0) { | |
| 2346 | self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {}; | |
| 2347 | self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0; | |
| 2348 | _ = self.atom_by_index_table.remove(decl.link.elf.local_sym_index); | |
| 2349 | decl.link.elf.local_sym_index = 0; | |
| 2296 | log.debug("freeDecl {*}", .{decl}); | |
| 2350 | 2297 | |
| 2351 | self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; | |
| 2298 | if (self.decls.fetchRemove(decl_index)) |kv| { | |
| 2299 | if (kv.value) |index| { | |
| 2300 | self.freeTextBlock(&decl.link.elf, index); | |
| 2301 | self.freeUnnamedConsts(decl_index); | |
| 2302 | } | |
| 2352 | 2303 | } |
| 2353 | 2304 | |
| 2354 | 2305 | if (self.dwarf) |*dw| { |
| ... | ... | @@ -2397,10 +2348,9 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s |
| 2397 | 2348 | const phdr_index = decl_ptr.*.?; |
| 2398 | 2349 | const shdr_index = self.phdr_shdr_table.get(phdr_index).?; |
| 2399 | 2350 | |
| 2400 | assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() | |
| 2401 | const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; | |
| 2351 | const local_sym = decl.link.elf.getSymbolPtr(self); | |
| 2402 | 2352 | if (local_sym.st_size != 0) { |
| 2403 | const capacity = decl.link.elf.capacity(self.*); | |
| 2353 | const capacity = decl.link.elf.capacity(self); | |
| 2404 | 2354 | const need_realloc = code.len > capacity or |
| 2405 | 2355 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); |
| 2406 | 2356 | if (need_realloc) { |
| ... | ... | @@ -2422,7 +2372,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s |
| 2422 | 2372 | local_sym.st_other = 0; |
| 2423 | 2373 | local_sym.st_shndx = shdr_index; |
| 2424 | 2374 | // TODO this write could be avoided if no fields of the symbol were changed. |
| 2425 | try self.writeSymbol(decl.link.elf.local_sym_index); | |
| 2375 | try self.writeSymbol(decl.link.elf.getSymbolIndex().?); | |
| 2426 | 2376 | } else { |
| 2427 | 2377 | const name_str_index = try self.makeString(decl_name); |
| 2428 | 2378 | const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment, phdr_index); |
| ... | ... | @@ -2439,7 +2389,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s |
| 2439 | 2389 | }; |
| 2440 | 2390 | self.offset_table.items[decl.link.elf.offset_table_index] = vaddr; |
| 2441 | 2391 | |
| 2442 | try self.writeSymbol(decl.link.elf.local_sym_index); | |
| 2392 | try self.writeSymbol(decl.link.elf.getSymbolIndex().?); | |
| 2443 | 2393 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); |
| 2444 | 2394 | } |
| 2445 | 2395 | |
| ... | ... | @@ -2461,12 +2411,20 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2461 | 2411 | const tracy = trace(@src()); |
| 2462 | 2412 | defer tracy.end(); |
| 2463 | 2413 | |
| 2464 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | |
| 2465 | defer code_buffer.deinit(); | |
| 2466 | ||
| 2467 | 2414 | const decl_index = func.owner_decl; |
| 2468 | 2415 | const decl = module.declPtr(decl_index); |
| 2469 | self.freeUnnamedConsts(decl_index); | |
| 2416 | const atom = &decl.link.elf; | |
| 2417 | try atom.ensureInitialized(self); | |
| 2418 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | |
| 2419 | if (gop.found_existing) { | |
| 2420 | self.freeUnnamedConsts(decl_index); | |
| 2421 | self.freeRelocationsForTextBlock(atom); | |
| 2422 | } else { | |
| 2423 | gop.value_ptr.* = null; | |
| 2424 | } | |
| 2425 | ||
| 2426 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | |
| 2427 | defer code_buffer.deinit(); | |
| 2470 | 2428 | |
| 2471 | 2429 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(module, decl_index) else null; |
| 2472 | 2430 | defer if (decl_state) |*ds| ds.deinit(); |
| ... | ... | @@ -2527,6 +2485,15 @@ pub fn updateDecl(self: *Elf, module: *Module, decl_index: Module.Decl.Index) !v |
| 2527 | 2485 | |
| 2528 | 2486 | assert(!self.unnamed_const_atoms.contains(decl_index)); |
| 2529 | 2487 | |
| 2488 | const atom = &decl.link.elf; | |
| 2489 | try atom.ensureInitialized(self); | |
| 2490 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | |
| 2491 | if (gop.found_existing) { | |
| 2492 | self.freeRelocationsForTextBlock(atom); | |
| 2493 | } else { | |
| 2494 | gop.value_ptr.* = null; | |
| 2495 | } | |
| 2496 | ||
| 2530 | 2497 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2531 | 2498 | defer code_buffer.deinit(); |
| 2532 | 2499 | |
| ... | ... | @@ -2542,14 +2509,14 @@ pub fn updateDecl(self: *Elf, module: *Module, decl_index: Module.Decl.Index) !v |
| 2542 | 2509 | }, &code_buffer, .{ |
| 2543 | 2510 | .dwarf = ds, |
| 2544 | 2511 | }, .{ |
| 2545 | .parent_atom_index = decl.link.elf.local_sym_index, | |
| 2512 | .parent_atom_index = decl.link.elf.getSymbolIndex().?, | |
| 2546 | 2513 | }) |
| 2547 | 2514 | else |
| 2548 | 2515 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 2549 | 2516 | .ty = decl.ty, |
| 2550 | 2517 | .val = decl_val, |
| 2551 | 2518 | }, &code_buffer, .none, .{ |
| 2552 | .parent_atom_index = decl.link.elf.local_sym_index, | |
| 2519 | .parent_atom_index = decl.link.elf.getSymbolIndex().?, | |
| 2553 | 2520 | }); |
| 2554 | 2521 | |
| 2555 | 2522 | const code = switch (res) { |
| ... | ... | @@ -2593,6 +2560,8 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2593 | 2560 | const atom = try self.base.allocator.create(TextBlock); |
| 2594 | 2561 | errdefer self.base.allocator.destroy(atom); |
| 2595 | 2562 | atom.* = TextBlock.empty; |
| 2563 | // TODO for unnamed consts we don't need GOT offset/entry allocated | |
| 2564 | try atom.ensureInitialized(self); | |
| 2596 | 2565 | try self.managed_atoms.append(self.base.allocator, atom); |
| 2597 | 2566 | |
| 2598 | 2567 | const name_str_index = blk: { |
| ... | ... | @@ -2607,14 +2576,10 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2607 | 2576 | }; |
| 2608 | 2577 | const name = self.getString(name_str_index); |
| 2609 | 2578 | |
| 2610 | log.debug("allocating symbol indexes for {s}", .{name}); | |
| 2611 | atom.local_sym_index = try self.allocateLocalSymbol(); | |
| 2612 | try self.atom_by_index_table.putNoClobber(self.base.allocator, atom.local_sym_index, atom); | |
| 2613 | ||
| 2614 | 2579 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{ |
| 2615 | 2580 | .none = {}, |
| 2616 | 2581 | }, .{ |
| 2617 | .parent_atom_index = atom.local_sym_index, | |
| 2582 | .parent_atom_index = atom.getSymbolIndex().?, | |
| 2618 | 2583 | }); |
| 2619 | 2584 | const code = switch (res) { |
| 2620 | 2585 | .ok => code_buffer.items, |
| ... | ... | @@ -2634,7 +2599,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2634 | 2599 | |
| 2635 | 2600 | log.debug("allocated text block for {s} at 0x{x}", .{ name, vaddr }); |
| 2636 | 2601 | |
| 2637 | const local_sym = &self.local_symbols.items[atom.local_sym_index]; | |
| 2602 | const local_sym = atom.getSymbolPtr(self); | |
| 2638 | 2603 | local_sym.* = .{ |
| 2639 | 2604 | .st_name = name_str_index, |
| 2640 | 2605 | .st_info = (elf.STB_LOCAL << 4) | elf.STT_OBJECT, |
| ... | ... | @@ -2644,14 +2609,14 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2644 | 2609 | .st_size = code.len, |
| 2645 | 2610 | }; |
| 2646 | 2611 | |
| 2647 | try self.writeSymbol(atom.local_sym_index); | |
| 2612 | try self.writeSymbol(atom.getSymbolIndex().?); | |
| 2648 | 2613 | try unnamed_consts.append(self.base.allocator, atom); |
| 2649 | 2614 | |
| 2650 | 2615 | const section_offset = local_sym.st_value - self.program_headers.items[phdr_index].p_vaddr; |
| 2651 | 2616 | const file_offset = self.sections.items[shdr_index].sh_offset + section_offset; |
| 2652 | 2617 | try self.base.file.?.pwriteAll(code, file_offset); |
| 2653 | 2618 | |
| 2654 | return atom.local_sym_index; | |
| 2619 | return atom.getSymbolIndex().?; | |
| 2655 | 2620 | } |
| 2656 | 2621 | |
| 2657 | 2622 | pub fn updateDeclExports( |
| ... | ... | @@ -2670,16 +2635,19 @@ pub fn updateDeclExports( |
| 2670 | 2635 | const tracy = trace(@src()); |
| 2671 | 2636 | defer tracy.end(); |
| 2672 | 2637 | |
| 2673 | try self.global_symbols.ensureUnusedCapacity(self.base.allocator, exports.len); | |
| 2674 | 2638 | const decl = module.declPtr(decl_index); |
| 2675 | if (decl.link.elf.local_sym_index == 0) return; | |
| 2676 | const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index]; | |
| 2639 | const atom = &decl.link.elf; | |
| 2677 | 2640 | |
| 2678 | const decl_ptr = self.decls.getPtr(decl_index).?; | |
| 2679 | if (decl_ptr.* == null) { | |
| 2680 | decl_ptr.* = try self.getDeclPhdrIndex(decl); | |
| 2641 | if (atom.getSymbolIndex() == null) return; | |
| 2642 | ||
| 2643 | const decl_sym = atom.getSymbol(self); | |
| 2644 | try self.global_symbols.ensureUnusedCapacity(self.base.allocator, exports.len); | |
| 2645 | ||
| 2646 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | |
| 2647 | if (!gop.found_existing) { | |
| 2648 | gop.value_ptr.* = try self.getDeclPhdrIndex(decl); | |
| 2681 | 2649 | } |
| 2682 | const phdr_index = decl_ptr.*.?; | |
| 2650 | const phdr_index = gop.value_ptr.*.?; | |
| 2683 | 2651 | const shdr_index = self.phdr_shdr_table.get(phdr_index).?; |
| 2684 | 2652 | |
| 2685 | 2653 | for (exports) |exp| { |
| ... | ... | @@ -3040,7 +3008,7 @@ fn getLDMOption(target: std.Target) ?[]const u8 { |
| 3040 | 3008 | } |
| 3041 | 3009 | } |
| 3042 | 3010 | |
| 3043 | fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | |
| 3011 | pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | |
| 3044 | 3012 | return actual_size +| (actual_size / ideal_factor); |
| 3045 | 3013 | } |
| 3046 | 3014 |
src/link/Elf/Atom.zig created+96| ... | ... | @@ -0,0 +1,96 @@ |
| 1 | const Atom = @This(); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | const assert = std.debug.assert; | |
| 5 | const elf = std.elf; | |
| 6 | ||
| 7 | const Dwarf = @import("../Dwarf.zig"); | |
| 8 | const Elf = @import("../Elf.zig"); | |
| 9 | ||
| 10 | /// Each decl always gets a local symbol with the fully qualified name. | |
| 11 | /// The vaddr and size are found here directly. | |
| 12 | /// The file offset is found by computing the vaddr offset from the section vaddr | |
| 13 | /// the symbol references, and adding that to the file offset of the section. | |
| 14 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or | |
| 15 | /// offset table entry. | |
| 16 | local_sym_index: u32, | |
| 17 | ||
| 18 | /// This field is undefined for symbols with size = 0. | |
| 19 | offset_table_index: u32, | |
| 20 | ||
| 21 | /// Points to the previous and next neighbors, based on the `text_offset`. | |
| 22 | /// This can be used to find, for example, the capacity of this `TextBlock`. | |
| 23 | prev: ?*Atom, | |
| 24 | next: ?*Atom, | |
| 25 | ||
| 26 | dbg_info_atom: Dwarf.Atom, | |
| 27 | ||
| 28 | pub const empty = Atom{ | |
| 29 | .local_sym_index = 0, | |
| 30 | .offset_table_index = undefined, | |
| 31 | .prev = null, | |
| 32 | .next = null, | |
| 33 | .dbg_info_atom = undefined, | |
| 34 | }; | |
| 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 | ||
| 72 | /// Returns how much room there is to grow in virtual address space. | |
| 73 | /// File offset relocation happens transparently, so it is not included in | |
| 74 | /// this calculation. | |
| 75 | pub fn capacity(self: Atom, elf_file: *Elf) u64 { | |
| 76 | const self_sym = self.getSymbol(elf_file); | |
| 77 | if (self.next) |next| { | |
| 78 | const next_sym = next.getSymbol(elf_file); | |
| 79 | return next_sym.st_value - self_sym.st_value; | |
| 80 | } else { | |
| 81 | // We are the last block. The capacity is limited only by virtual address space. | |
| 82 | return std.math.maxInt(u32) - self_sym.st_value; | |
| 83 | } | |
| 84 | } | |
| 85 | ||
| 86 | pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { | |
| 87 | // No need to keep a free list node for the last block. | |
| 88 | const next = self.next orelse return false; | |
| 89 | const self_sym = self.getSymbol(elf_file); | |
| 90 | const next_sym = next.getSymbol(elf_file); | |
| 91 | const cap = next_sym.st_value - self_sym.st_value; | |
| 92 | const ideal_cap = Elf.padToIdeal(self_sym.st_size); | |
| 93 | if (cap <= ideal_cap) return false; | |
| 94 | const surplus = cap - ideal_cap; | |
| 95 | return surplus >= Elf.min_text_capacity; | |
| 96 | } |
src/link/MachO.zig+125-148| ... | ... | @@ -1056,19 +1056,14 @@ pub fn allocateSpecialSymbols(self: *MachO) !void { |
| 1056 | 1056 | pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 1057 | 1057 | const gpa = self.base.allocator; |
| 1058 | 1058 | |
| 1059 | const sym_index = try self.allocateSymbol(); | |
| 1060 | const atom = blk: { | |
| 1061 | const atom = try gpa.create(Atom); | |
| 1062 | atom.* = Atom.empty; | |
| 1063 | atom.sym_index = sym_index; | |
| 1064 | atom.size = @sizeOf(u64); | |
| 1065 | atom.alignment = @alignOf(u64); | |
| 1066 | break :blk atom; | |
| 1067 | }; | |
| 1059 | const atom = try gpa.create(Atom); | |
| 1060 | atom.* = Atom.empty; | |
| 1061 | try atom.ensureInitialized(self); | |
| 1062 | atom.size = @sizeOf(u64); | |
| 1063 | atom.alignment = @alignOf(u64); | |
| 1068 | 1064 | errdefer gpa.destroy(atom); |
| 1069 | 1065 | |
| 1070 | 1066 | try self.managed_atoms.append(gpa, atom); |
| 1071 | try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); | |
| 1072 | 1067 | |
| 1073 | 1068 | const sym = atom.getSymbolPtr(self); |
| 1074 | 1069 | sym.n_type = macho.N_SECT; |
| ... | ... | @@ -1109,15 +1104,11 @@ pub fn createDyldPrivateAtom(self: *MachO) !void { |
| 1109 | 1104 | |
| 1110 | 1105 | const gpa = self.base.allocator; |
| 1111 | 1106 | |
| 1112 | const sym_index = try self.allocateSymbol(); | |
| 1113 | const atom = blk: { | |
| 1114 | const atom = try gpa.create(Atom); | |
| 1115 | atom.* = Atom.empty; | |
| 1116 | atom.sym_index = sym_index; | |
| 1117 | atom.size = @sizeOf(u64); | |
| 1118 | atom.alignment = @alignOf(u64); | |
| 1119 | break :blk atom; | |
| 1120 | }; | |
| 1107 | const atom = try gpa.create(Atom); | |
| 1108 | atom.* = Atom.empty; | |
| 1109 | try atom.ensureInitialized(self); | |
| 1110 | atom.size = @sizeOf(u64); | |
| 1111 | atom.alignment = @alignOf(u64); | |
| 1121 | 1112 | errdefer gpa.destroy(atom); |
| 1122 | 1113 | |
| 1123 | 1114 | const sym = atom.getSymbolPtr(self); |
| ... | ... | @@ -1126,7 +1117,6 @@ pub fn createDyldPrivateAtom(self: *MachO) !void { |
| 1126 | 1117 | self.dyld_private_atom = atom; |
| 1127 | 1118 | |
| 1128 | 1119 | try self.managed_atoms.append(gpa, atom); |
| 1129 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | |
| 1130 | 1120 | |
| 1131 | 1121 | sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64)); |
| 1132 | 1122 | log.debug("allocated dyld_private atom at 0x{x}", .{sym.n_value}); |
| ... | ... | @@ -1144,18 +1134,14 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 1144 | 1134 | .aarch64 => 6 * @sizeOf(u32), |
| 1145 | 1135 | else => unreachable, |
| 1146 | 1136 | }; |
| 1147 | const sym_index = try self.allocateSymbol(); | |
| 1148 | const atom = blk: { | |
| 1149 | const atom = try gpa.create(Atom); | |
| 1150 | atom.* = Atom.empty; | |
| 1151 | atom.sym_index = sym_index; | |
| 1152 | atom.size = size; | |
| 1153 | atom.alignment = switch (arch) { | |
| 1154 | .x86_64 => 1, | |
| 1155 | .aarch64 => @alignOf(u32), | |
| 1156 | else => unreachable, | |
| 1157 | }; | |
| 1158 | break :blk atom; | |
| 1137 | const atom = try gpa.create(Atom); | |
| 1138 | atom.* = Atom.empty; | |
| 1139 | try atom.ensureInitialized(self); | |
| 1140 | atom.size = size; | |
| 1141 | atom.alignment = switch (arch) { | |
| 1142 | .x86_64 => 1, | |
| 1143 | .aarch64 => @alignOf(u32), | |
| 1144 | else => unreachable, | |
| 1159 | 1145 | }; |
| 1160 | 1146 | errdefer gpa.destroy(atom); |
| 1161 | 1147 | |
| ... | ... | @@ -1163,7 +1149,7 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 1163 | 1149 | sym.n_type = macho.N_SECT; |
| 1164 | 1150 | sym.n_sect = self.stub_helper_section_index.? + 1; |
| 1165 | 1151 | |
| 1166 | const dyld_private_sym_index = self.dyld_private_atom.?.sym_index; | |
| 1152 | const dyld_private_sym_index = self.dyld_private_atom.?.getSymbolIndex().?; | |
| 1167 | 1153 | |
| 1168 | 1154 | const code = try gpa.alloc(u8, size); |
| 1169 | 1155 | defer gpa.free(code); |
| ... | ... | @@ -1258,7 +1244,6 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 1258 | 1244 | self.stub_helper_preamble_atom = atom; |
| 1259 | 1245 | |
| 1260 | 1246 | try self.managed_atoms.append(gpa, atom); |
| 1261 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | |
| 1262 | 1247 | |
| 1263 | 1248 | sym.n_value = try self.allocateAtom(atom, size, atom.alignment); |
| 1264 | 1249 | log.debug("allocated stub preamble atom at 0x{x}", .{sym.n_value}); |
| ... | ... | @@ -1273,18 +1258,14 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1273 | 1258 | .aarch64 => 3 * @sizeOf(u32), |
| 1274 | 1259 | else => unreachable, |
| 1275 | 1260 | }; |
| 1276 | const sym_index = try self.allocateSymbol(); | |
| 1277 | const atom = blk: { | |
| 1278 | const atom = try gpa.create(Atom); | |
| 1279 | atom.* = Atom.empty; | |
| 1280 | atom.sym_index = sym_index; | |
| 1281 | atom.size = size; | |
| 1282 | atom.alignment = switch (arch) { | |
| 1283 | .x86_64 => 1, | |
| 1284 | .aarch64 => @alignOf(u32), | |
| 1285 | else => unreachable, | |
| 1286 | }; | |
| 1287 | break :blk atom; | |
| 1261 | const atom = try gpa.create(Atom); | |
| 1262 | atom.* = Atom.empty; | |
| 1263 | try atom.ensureInitialized(self); | |
| 1264 | atom.size = size; | |
| 1265 | atom.alignment = switch (arch) { | |
| 1266 | .x86_64 => 1, | |
| 1267 | .aarch64 => @alignOf(u32), | |
| 1268 | else => unreachable, | |
| 1288 | 1269 | }; |
| 1289 | 1270 | errdefer gpa.destroy(atom); |
| 1290 | 1271 | |
| ... | ... | @@ -1306,7 +1287,7 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1306 | 1287 | |
| 1307 | 1288 | try atom.addRelocation(self, .{ |
| 1308 | 1289 | .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), |
| 1309 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, | |
| 1290 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.getSymbolIndex().?, .file = null }, | |
| 1310 | 1291 | .offset = 6, |
| 1311 | 1292 | .addend = 0, |
| 1312 | 1293 | .pcrel = true, |
| ... | ... | @@ -1329,7 +1310,7 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1329 | 1310 | |
| 1330 | 1311 | try atom.addRelocation(self, .{ |
| 1331 | 1312 | .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_BRANCH26), |
| 1332 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, | |
| 1313 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.getSymbolIndex().?, .file = null }, | |
| 1333 | 1314 | .offset = 4, |
| 1334 | 1315 | .addend = 0, |
| 1335 | 1316 | .pcrel = true, |
| ... | ... | @@ -1340,7 +1321,6 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1340 | 1321 | } |
| 1341 | 1322 | |
| 1342 | 1323 | try self.managed_atoms.append(gpa, atom); |
| 1343 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | |
| 1344 | 1324 | |
| 1345 | 1325 | sym.n_value = try self.allocateAtom(atom, size, atom.alignment); |
| 1346 | 1326 | log.debug("allocated stub helper atom at 0x{x}", .{sym.n_value}); |
| ... | ... | @@ -1351,15 +1331,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1351 | 1331 | |
| 1352 | 1332 | pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom { |
| 1353 | 1333 | const gpa = self.base.allocator; |
| 1354 | const sym_index = try self.allocateSymbol(); | |
| 1355 | const atom = blk: { | |
| 1356 | const atom = try gpa.create(Atom); | |
| 1357 | atom.* = Atom.empty; | |
| 1358 | atom.sym_index = sym_index; | |
| 1359 | atom.size = @sizeOf(u64); | |
| 1360 | atom.alignment = @alignOf(u64); | |
| 1361 | break :blk atom; | |
| 1362 | }; | |
| 1334 | const atom = try gpa.create(Atom); | |
| 1335 | atom.* = Atom.empty; | |
| 1336 | try atom.ensureInitialized(self); | |
| 1337 | atom.size = @sizeOf(u64); | |
| 1338 | atom.alignment = @alignOf(u64); | |
| 1363 | 1339 | errdefer gpa.destroy(atom); |
| 1364 | 1340 | |
| 1365 | 1341 | const sym = atom.getSymbolPtr(self); |
| ... | ... | @@ -1385,7 +1361,6 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi |
| 1385 | 1361 | }); |
| 1386 | 1362 | |
| 1387 | 1363 | try self.managed_atoms.append(gpa, atom); |
| 1388 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | |
| 1389 | 1364 | |
| 1390 | 1365 | sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64)); |
| 1391 | 1366 | log.debug("allocated lazy pointer atom at 0x{x} ({s})", .{ sym.n_value, self.getSymbolName(target) }); |
| ... | ... | @@ -1402,19 +1377,15 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 1402 | 1377 | .aarch64 => 3 * @sizeOf(u32), |
| 1403 | 1378 | else => unreachable, // unhandled architecture type |
| 1404 | 1379 | }; |
| 1405 | const sym_index = try self.allocateSymbol(); | |
| 1406 | const atom = blk: { | |
| 1407 | const atom = try gpa.create(Atom); | |
| 1408 | atom.* = Atom.empty; | |
| 1409 | atom.sym_index = sym_index; | |
| 1410 | atom.size = size; | |
| 1411 | atom.alignment = switch (arch) { | |
| 1412 | .x86_64 => 1, | |
| 1413 | .aarch64 => @alignOf(u32), | |
| 1414 | else => unreachable, // unhandled architecture type | |
| 1380 | const atom = try gpa.create(Atom); | |
| 1381 | atom.* = Atom.empty; | |
| 1382 | try atom.ensureInitialized(self); | |
| 1383 | atom.size = size; | |
| 1384 | atom.alignment = switch (arch) { | |
| 1385 | .x86_64 => 1, | |
| 1386 | .aarch64 => @alignOf(u32), | |
| 1387 | else => unreachable, // unhandled architecture type | |
| 1415 | 1388 | |
| 1416 | }; | |
| 1417 | break :blk atom; | |
| 1418 | 1389 | }; |
| 1419 | 1390 | errdefer gpa.destroy(atom); |
| 1420 | 1391 | |
| ... | ... | @@ -1476,7 +1447,6 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 1476 | 1447 | } |
| 1477 | 1448 | |
| 1478 | 1449 | try self.managed_atoms.append(gpa, atom); |
| 1479 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | |
| 1480 | 1450 | |
| 1481 | 1451 | sym.n_value = try self.allocateAtom(atom, size, atom.alignment); |
| 1482 | 1452 | log.debug("allocated stub atom at 0x{x}", .{sym.n_value}); |
| ... | ... | @@ -1617,9 +1587,9 @@ pub fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 1617 | 1587 | |
| 1618 | 1588 | const stub_index = try self.allocateStubEntry(global); |
| 1619 | 1589 | const stub_helper_atom = try self.createStubHelperAtom(); |
| 1620 | const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.sym_index, global); | |
| 1621 | const stub_atom = try self.createStubAtom(laptr_atom.sym_index); | |
| 1622 | self.stubs.items[stub_index].sym_index = stub_atom.sym_index; | |
| 1590 | const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.getSymbolIndex().?, global); | |
| 1591 | const stub_atom = try self.createStubAtom(laptr_atom.getSymbolIndex().?); | |
| 1592 | self.stubs.items[stub_index].sym_index = stub_atom.getSymbolIndex().?; | |
| 1623 | 1593 | self.markRelocsDirtyByTarget(global); |
| 1624 | 1594 | } |
| 1625 | 1595 | |
| ... | ... | @@ -1717,7 +1687,7 @@ pub fn resolveDyldStubBinder(self: *MachO) !void { |
| 1717 | 1687 | // Add dyld_stub_binder as the final GOT entry. |
| 1718 | 1688 | const got_index = try self.allocateGotEntry(global); |
| 1719 | 1689 | const got_atom = try self.createGotAtom(global); |
| 1720 | self.got_entries.items[got_index].sym_index = got_atom.sym_index; | |
| 1690 | self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?; | |
| 1721 | 1691 | |
| 1722 | 1692 | try self.writePtrWidthAtom(got_atom); |
| 1723 | 1693 | } |
| ... | ... | @@ -1811,6 +1781,8 @@ pub fn deinit(self: *MachO) void { |
| 1811 | 1781 | fn freeAtom(self: *MachO, atom: *Atom) void { |
| 1812 | 1782 | log.debug("freeAtom {*}", .{atom}); |
| 1813 | 1783 | |
| 1784 | const gpa = self.base.allocator; | |
| 1785 | ||
| 1814 | 1786 | // Remove any relocs and base relocs associated with this Atom |
| 1815 | 1787 | self.freeRelocationsForAtom(atom); |
| 1816 | 1788 | |
| ... | ... | @@ -1850,7 +1822,7 @@ fn freeAtom(self: *MachO, atom: *Atom) void { |
| 1850 | 1822 | if (!already_have_free_list_node and prev.freeListEligible(self)) { |
| 1851 | 1823 | // The free list is heuristics, it doesn't have to be perfect, so we can ignore |
| 1852 | 1824 | // the OOM here. |
| 1853 | free_list.append(self.base.allocator, prev) catch {}; | |
| 1825 | free_list.append(gpa, prev) catch {}; | |
| 1854 | 1826 | } |
| 1855 | 1827 | } else { |
| 1856 | 1828 | atom.prev = null; |
| ... | ... | @@ -1862,6 +1834,33 @@ fn freeAtom(self: *MachO, atom: *Atom) void { |
| 1862 | 1834 | atom.next = null; |
| 1863 | 1835 | } |
| 1864 | 1836 | |
| 1837 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | |
| 1838 | const sym_index = atom.getSymbolIndex().?; | |
| 1839 | ||
| 1840 | self.locals_free_list.append(gpa, sym_index) catch {}; | |
| 1841 | ||
| 1842 | // Try freeing GOT atom if this decl had one | |
| 1843 | const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 1844 | if (self.got_entries_table.get(got_target)) |got_index| { | |
| 1845 | self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {}; | |
| 1846 | self.got_entries.items[got_index] = .{ | |
| 1847 | .target = .{ .sym_index = 0, .file = null }, | |
| 1848 | .sym_index = 0, | |
| 1849 | }; | |
| 1850 | _ = self.got_entries_table.remove(got_target); | |
| 1851 | ||
| 1852 | if (self.d_sym) |*d_sym| { | |
| 1853 | d_sym.swapRemoveRelocs(sym_index); | |
| 1854 | } | |
| 1855 | ||
| 1856 | log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); | |
| 1857 | } | |
| 1858 | ||
| 1859 | self.locals.items[sym_index].n_type = 0; | |
| 1860 | _ = self.atom_by_index_table.remove(sym_index); | |
| 1861 | log.debug(" adding local symbol index {d} to free list", .{sym_index}); | |
| 1862 | atom.sym_index = 0; | |
| 1863 | ||
| 1865 | 1864 | if (self.d_sym) |*d_sym| { |
| 1866 | 1865 | d_sym.dwarf.freeAtom(&atom.dbg_info_atom); |
| 1867 | 1866 | } |
| ... | ... | @@ -1883,7 +1882,7 @@ fn growAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !u64 |
| 1883 | 1882 | return self.allocateAtom(atom, new_atom_size, alignment); |
| 1884 | 1883 | } |
| 1885 | 1884 | |
| 1886 | fn allocateSymbol(self: *MachO) !u32 { | |
| 1885 | pub fn allocateSymbol(self: *MachO) !u32 { | |
| 1887 | 1886 | try self.locals.ensureUnusedCapacity(self.base.allocator, 1); |
| 1888 | 1887 | |
| 1889 | 1888 | const index = blk: { |
| ... | ... | @@ -1975,16 +1974,6 @@ pub fn allocateStubEntry(self: *MachO, target: SymbolWithLoc) !u32 { |
| 1975 | 1974 | return index; |
| 1976 | 1975 | } |
| 1977 | 1976 | |
| 1978 | pub fn allocateDeclIndexes(self: *MachO, decl_index: Module.Decl.Index) !void { | |
| 1979 | if (self.llvm_object) |_| return; | |
| 1980 | const decl = self.base.options.module.?.declPtr(decl_index); | |
| 1981 | if (decl.link.macho.sym_index != 0) return; | |
| 1982 | ||
| 1983 | decl.link.macho.sym_index = try self.allocateSymbol(); | |
| 1984 | try self.atom_by_index_table.putNoClobber(self.base.allocator, decl.link.macho.sym_index, &decl.link.macho); | |
| 1985 | try self.decls.putNoClobber(self.base.allocator, decl_index, null); | |
| 1986 | } | |
| 1987 | ||
| 1988 | 1977 | pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { |
| 1989 | 1978 | if (build_options.skip_non_native and builtin.object_format != .macho) { |
| 1990 | 1979 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| ... | ... | @@ -1997,8 +1986,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 1997 | 1986 | |
| 1998 | 1987 | const decl_index = func.owner_decl; |
| 1999 | 1988 | const decl = module.declPtr(decl_index); |
| 2000 | self.freeUnnamedConsts(decl_index); | |
| 2001 | self.freeRelocationsForAtom(&decl.link.macho); | |
| 1989 | const atom = &decl.link.macho; | |
| 1990 | try atom.ensureInitialized(self); | |
| 1991 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | |
| 1992 | if (gop.found_existing) { | |
| 1993 | self.freeUnnamedConsts(decl_index); | |
| 1994 | self.freeRelocationsForAtom(atom); | |
| 1995 | } else { | |
| 1996 | gop.value_ptr.* = null; | |
| 1997 | } | |
| 2002 | 1998 | |
| 2003 | 1999 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2004 | 2000 | defer code_buffer.deinit(); |
| ... | ... | @@ -2072,14 +2068,11 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 2072 | 2068 | const atom = try gpa.create(Atom); |
| 2073 | 2069 | errdefer gpa.destroy(atom); |
| 2074 | 2070 | atom.* = Atom.empty; |
| 2075 | ||
| 2076 | atom.sym_index = try self.allocateSymbol(); | |
| 2077 | ||
| 2071 | try atom.ensureInitialized(self); | |
| 2078 | 2072 | try self.managed_atoms.append(gpa, atom); |
| 2079 | try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); | |
| 2080 | 2073 | |
| 2081 | 2074 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{ |
| 2082 | .parent_atom_index = atom.sym_index, | |
| 2075 | .parent_atom_index = atom.getSymbolIndex().?, | |
| 2083 | 2076 | }); |
| 2084 | 2077 | const code = switch (res) { |
| 2085 | 2078 | .ok => code_buffer.items, |
| ... | ... | @@ -2111,7 +2104,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 2111 | 2104 | |
| 2112 | 2105 | try self.writeAtom(atom, code); |
| 2113 | 2106 | |
| 2114 | return atom.sym_index; | |
| 2107 | return atom.getSymbolIndex().?; | |
| 2115 | 2108 | } |
| 2116 | 2109 | |
| 2117 | 2110 | pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void { |
| ... | ... | @@ -2136,7 +2129,14 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) |
| 2136 | 2129 | } |
| 2137 | 2130 | } |
| 2138 | 2131 | |
| 2139 | self.freeRelocationsForAtom(&decl.link.macho); | |
| 2132 | const atom = &decl.link.macho; | |
| 2133 | try atom.ensureInitialized(self); | |
| 2134 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); | |
| 2135 | if (gop.found_existing) { | |
| 2136 | self.freeRelocationsForAtom(atom); | |
| 2137 | } else { | |
| 2138 | gop.value_ptr.* = null; | |
| 2139 | } | |
| 2140 | 2140 | |
| 2141 | 2141 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2142 | 2142 | defer code_buffer.deinit(); |
| ... | ... | @@ -2155,14 +2155,14 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) |
| 2155 | 2155 | }, &code_buffer, .{ |
| 2156 | 2156 | .dwarf = ds, |
| 2157 | 2157 | }, .{ |
| 2158 | .parent_atom_index = decl.link.macho.sym_index, | |
| 2158 | .parent_atom_index = decl.link.macho.getSymbolIndex().?, | |
| 2159 | 2159 | }) |
| 2160 | 2160 | else |
| 2161 | 2161 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 2162 | 2162 | .ty = decl.ty, |
| 2163 | 2163 | .val = decl_val, |
| 2164 | 2164 | }, &code_buffer, .none, .{ |
| 2165 | .parent_atom_index = decl.link.macho.sym_index, | |
| 2165 | .parent_atom_index = decl.link.macho.getSymbolIndex().?, | |
| 2166 | 2166 | }); |
| 2167 | 2167 | |
| 2168 | 2168 | const code = switch (res) { |
| ... | ... | @@ -2337,12 +2337,12 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8) |
| 2337 | 2337 | const decl = mod.declPtr(decl_index); |
| 2338 | 2338 | |
| 2339 | 2339 | const required_alignment = decl.getAlignment(self.base.options.target); |
| 2340 | assert(decl.link.macho.sym_index != 0); // Caller forgot to call allocateDeclIndexes() | |
| 2341 | 2340 | |
| 2342 | 2341 | const sym_name = try decl.getFullyQualifiedName(mod); |
| 2343 | 2342 | defer self.base.allocator.free(sym_name); |
| 2344 | 2343 | |
| 2345 | 2344 | const atom = &decl.link.macho; |
| 2345 | const sym_index = atom.getSymbolIndex().?; // Atom was not initialized | |
| 2346 | 2346 | const decl_ptr = self.decls.getPtr(decl_index).?; |
| 2347 | 2347 | if (decl_ptr.* == null) { |
| 2348 | 2348 | decl_ptr.* = self.getDeclOutputSection(decl); |
| ... | ... | @@ -2368,7 +2368,7 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8) |
| 2368 | 2368 | if (vaddr != sym.n_value) { |
| 2369 | 2369 | sym.n_value = vaddr; |
| 2370 | 2370 | log.debug(" (updating GOT entry)", .{}); |
| 2371 | const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null }; | |
| 2371 | const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 2372 | 2372 | const got_atom = self.getGotAtomForSymbol(got_target).?; |
| 2373 | 2373 | self.markRelocsDirtyByTarget(got_target); |
| 2374 | 2374 | try self.writePtrWidthAtom(got_atom); |
| ... | ... | @@ -2399,10 +2399,10 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8) |
| 2399 | 2399 | atom.size = code_len; |
| 2400 | 2400 | sym.n_value = vaddr; |
| 2401 | 2401 | |
| 2402 | const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null }; | |
| 2402 | const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 2403 | 2403 | const got_index = try self.allocateGotEntry(got_target); |
| 2404 | 2404 | const got_atom = try self.createGotAtom(got_target); |
| 2405 | self.got_entries.items[got_index].sym_index = got_atom.sym_index; | |
| 2405 | self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?; | |
| 2406 | 2406 | try self.writePtrWidthAtom(got_atom); |
| 2407 | 2407 | } |
| 2408 | 2408 | |
| ... | ... | @@ -2438,8 +2438,16 @@ pub fn updateDeclExports( |
| 2438 | 2438 | const gpa = self.base.allocator; |
| 2439 | 2439 | |
| 2440 | 2440 | const decl = module.declPtr(decl_index); |
| 2441 | if (decl.link.macho.sym_index == 0) return; | |
| 2442 | const decl_sym = decl.link.macho.getSymbol(self); | |
| 2441 | const atom = &decl.link.macho; | |
| 2442 | ||
| 2443 | if (atom.getSymbolIndex() == null) return; | |
| 2444 | ||
| 2445 | const gop = try self.decls.getOrPut(gpa, decl_index); | |
| 2446 | if (!gop.found_existing) { | |
| 2447 | gop.value_ptr.* = self.getDeclOutputSection(decl); | |
| 2448 | } | |
| 2449 | ||
| 2450 | const decl_sym = atom.getSymbol(self); | |
| 2443 | 2451 | |
| 2444 | 2452 | for (exports) |exp| { |
| 2445 | 2453 | const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{exp.options.name}); |
| ... | ... | @@ -2573,11 +2581,6 @@ fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void { |
| 2573 | 2581 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; |
| 2574 | 2582 | for (unnamed_consts.items) |atom| { |
| 2575 | 2583 | self.freeAtom(atom); |
| 2576 | self.locals_free_list.append(gpa, atom.sym_index) catch {}; | |
| 2577 | self.locals.items[atom.sym_index].n_type = 0; | |
| 2578 | _ = self.atom_by_index_table.remove(atom.sym_index); | |
| 2579 | log.debug(" adding local symbol index {d} to free list", .{atom.sym_index}); | |
| 2580 | atom.sym_index = 0; | |
| 2581 | 2584 | } |
| 2582 | 2585 | unnamed_consts.clearAndFree(gpa); |
| 2583 | 2586 | } |
| ... | ... | @@ -2591,39 +2594,11 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void { |
| 2591 | 2594 | |
| 2592 | 2595 | log.debug("freeDecl {*}", .{decl}); |
| 2593 | 2596 | |
| 2594 | const kv = self.decls.fetchSwapRemove(decl_index); | |
| 2595 | if (kv.?.value) |_| { | |
| 2596 | self.freeAtom(&decl.link.macho); | |
| 2597 | self.freeUnnamedConsts(decl_index); | |
| 2598 | } | |
| 2599 | ||
| 2600 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | |
| 2601 | const gpa = self.base.allocator; | |
| 2602 | const sym_index = decl.link.macho.sym_index; | |
| 2603 | if (sym_index != 0) { | |
| 2604 | self.locals_free_list.append(gpa, sym_index) catch {}; | |
| 2605 | ||
| 2606 | // Try freeing GOT atom if this decl had one | |
| 2607 | const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | |
| 2608 | if (self.got_entries_table.get(got_target)) |got_index| { | |
| 2609 | self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {}; | |
| 2610 | self.got_entries.items[got_index] = .{ | |
| 2611 | .target = .{ .sym_index = 0, .file = null }, | |
| 2612 | .sym_index = 0, | |
| 2613 | }; | |
| 2614 | _ = self.got_entries_table.remove(got_target); | |
| 2615 | ||
| 2616 | if (self.d_sym) |*d_sym| { | |
| 2617 | d_sym.swapRemoveRelocs(sym_index); | |
| 2618 | } | |
| 2619 | ||
| 2620 | log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); | |
| 2597 | if (self.decls.fetchSwapRemove(decl_index)) |kv| { | |
| 2598 | if (kv.value) |_| { | |
| 2599 | self.freeAtom(&decl.link.macho); | |
| 2600 | self.freeUnnamedConsts(decl_index); | |
| 2621 | 2601 | } |
| 2622 | ||
| 2623 | self.locals.items[sym_index].n_type = 0; | |
| 2624 | _ = self.atom_by_index_table.remove(sym_index); | |
| 2625 | log.debug(" adding local symbol index {d} to free list", .{sym_index}); | |
| 2626 | decl.link.macho.sym_index = 0; | |
| 2627 | 2602 | } |
| 2628 | 2603 | |
| 2629 | 2604 | if (self.d_sym) |*d_sym| { |
| ... | ... | @@ -2636,7 +2611,9 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil |
| 2636 | 2611 | const decl = mod.declPtr(decl_index); |
| 2637 | 2612 | |
| 2638 | 2613 | assert(self.llvm_object == null); |
| 2639 | assert(decl.link.macho.sym_index != 0); | |
| 2614 | ||
| 2615 | try decl.link.macho.ensureInitialized(self); | |
| 2616 | const sym_index = decl.link.macho.getSymbolIndex().?; | |
| 2640 | 2617 | |
| 2641 | 2618 | const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?; |
| 2642 | 2619 | try atom.addRelocation(self, .{ |
| ... | ... | @@ -2645,7 +2622,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil |
| 2645 | 2622 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), |
| 2646 | 2623 | else => unreachable, |
| 2647 | 2624 | }, |
| 2648 | .target = .{ .sym_index = decl.link.macho.sym_index, .file = null }, | |
| 2625 | .target = .{ .sym_index = sym_index, .file = null }, | |
| 2649 | 2626 | .offset = @intCast(u32, reloc_info.offset), |
| 2650 | 2627 | .addend = reloc_info.addend, |
| 2651 | 2628 | .pcrel = false, |
| ... | ... | @@ -3179,7 +3156,7 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void { |
| 3179 | 3156 | const slice = self.sections.slice(); |
| 3180 | 3157 | |
| 3181 | 3158 | for (self.rebases.keys()) |atom, i| { |
| 3182 | log.debug(" ATOM(%{d}, '{s}')", .{ atom.sym_index, atom.getName(self) }); | |
| 3159 | log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) }); | |
| 3183 | 3160 | |
| 3184 | 3161 | const sym = atom.getSymbol(self); |
| 3185 | 3162 | const segment_index = slice.items(.segment_index)[sym.n_sect - 1]; |
| ... | ... | @@ -3208,7 +3185,7 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void { |
| 3208 | 3185 | const slice = self.sections.slice(); |
| 3209 | 3186 | |
| 3210 | 3187 | for (raw_bindings.keys()) |atom, i| { |
| 3211 | log.debug(" ATOM(%{d}, '{s}')", .{ atom.sym_index, atom.getName(self) }); | |
| 3188 | log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) }); | |
| 3212 | 3189 | |
| 3213 | 3190 | const sym = atom.getSymbol(self); |
| 3214 | 3191 | const segment_index = slice.items(.segment_index)[sym.n_sect - 1]; |
| ... | ... | @@ -4277,8 +4254,8 @@ pub fn logAtoms(self: *MachO) void { |
| 4277 | 4254 | pub fn logAtom(self: *MachO, atom: *const Atom) void { |
| 4278 | 4255 | const sym = atom.getSymbol(self); |
| 4279 | 4256 | const sym_name = atom.getName(self); |
| 4280 | log.debug(" ATOM(%{d}, '{s}') @ {x} (sizeof({x}), alignof({x})) in object({?d}) in sect({d})", .{ | |
| 4281 | atom.sym_index, | |
| 4257 | log.debug(" ATOM(%{?d}, '{s}') @ {x} (sizeof({x}), alignof({x})) in object({?d}) in sect({d})", .{ | |
| 4258 | atom.getSymbolIndex(), | |
| 4282 | 4259 | sym_name, |
| 4283 | 4260 | sym.n_value, |
| 4284 | 4261 | atom.size, |
src/link/MachO/Atom.zig+22-8| ... | ... | @@ -64,6 +64,17 @@ pub const empty = Atom{ |
| 64 | 64 | .dbg_info_atom = undefined, |
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | pub fn ensureInitialized(self: *Atom, macho_file: *MachO) !void { | |
| 68 | if (self.getSymbolIndex() != null) return; // Already initialized | |
| 69 | self.sym_index = try macho_file.allocateSymbol(); | |
| 70 | try macho_file.atom_by_index_table.putNoClobber(macho_file.base.allocator, self.sym_index, self); | |
| 71 | } | |
| 72 | ||
| 73 | pub fn getSymbolIndex(self: Atom) ?u32 { | |
| 74 | if (self.sym_index == 0) return null; | |
| 75 | return self.sym_index; | |
| 76 | } | |
| 77 | ||
| 67 | 78 | /// Returns symbol referencing this atom. |
| 68 | 79 | pub fn getSymbol(self: Atom, macho_file: *MachO) macho.nlist_64 { |
| 69 | 80 | return self.getSymbolPtr(macho_file).*; |
| ... | ... | @@ -71,20 +82,23 @@ pub fn getSymbol(self: Atom, macho_file: *MachO) macho.nlist_64 { |
| 71 | 82 | |
| 72 | 83 | /// Returns pointer-to-symbol referencing this atom. |
| 73 | 84 | pub fn getSymbolPtr(self: Atom, macho_file: *MachO) *macho.nlist_64 { |
| 85 | const sym_index = self.getSymbolIndex().?; | |
| 74 | 86 | return macho_file.getSymbolPtr(.{ |
| 75 | .sym_index = self.sym_index, | |
| 87 | .sym_index = sym_index, | |
| 76 | 88 | .file = self.file, |
| 77 | 89 | }); |
| 78 | 90 | } |
| 79 | 91 | |
| 80 | 92 | pub fn getSymbolWithLoc(self: Atom) SymbolWithLoc { |
| 81 | return .{ .sym_index = self.sym_index, .file = self.file }; | |
| 93 | const sym_index = self.getSymbolIndex().?; | |
| 94 | return .{ .sym_index = sym_index, .file = self.file }; | |
| 82 | 95 | } |
| 83 | 96 | |
| 84 | 97 | /// Returns the name of this atom. |
| 85 | 98 | pub fn getName(self: Atom, macho_file: *MachO) []const u8 { |
| 99 | const sym_index = self.getSymbolIndex().?; | |
| 86 | 100 | return macho_file.getSymbolName(.{ |
| 87 | .sym_index = self.sym_index, | |
| 101 | .sym_index = sym_index, | |
| 88 | 102 | .file = self.file, |
| 89 | 103 | }); |
| 90 | 104 | } |
| ... | ... | @@ -144,7 +158,7 @@ pub fn addRelocations( |
| 144 | 158 | |
| 145 | 159 | pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void { |
| 146 | 160 | const gpa = macho_file.base.allocator; |
| 147 | log.debug(" (adding rebase at offset 0x{x} in %{d})", .{ offset, self.sym_index }); | |
| 161 | log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, self.getSymbolIndex() }); | |
| 148 | 162 | const gop = try macho_file.rebases.getOrPut(gpa, self); |
| 149 | 163 | if (!gop.found_existing) { |
| 150 | 164 | gop.value_ptr.* = .{}; |
| ... | ... | @@ -154,10 +168,10 @@ pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void { |
| 154 | 168 | |
| 155 | 169 | pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void { |
| 156 | 170 | const gpa = macho_file.base.allocator; |
| 157 | log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{d})", .{ | |
| 171 | log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{?d})", .{ | |
| 158 | 172 | macho_file.getSymbolName(binding.target), |
| 159 | 173 | binding.offset, |
| 160 | self.sym_index, | |
| 174 | self.getSymbolIndex(), | |
| 161 | 175 | }); |
| 162 | 176 | const gop = try macho_file.bindings.getOrPut(gpa, self); |
| 163 | 177 | if (!gop.found_existing) { |
| ... | ... | @@ -168,10 +182,10 @@ pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void { |
| 168 | 182 | |
| 169 | 183 | pub fn addLazyBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void { |
| 170 | 184 | const gpa = macho_file.base.allocator; |
| 171 | log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{d})", .{ | |
| 185 | log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{?d})", .{ | |
| 172 | 186 | macho_file.getSymbolName(binding.target), |
| 173 | 187 | binding.offset, |
| 174 | self.sym_index, | |
| 188 | self.getSymbolIndex(), | |
| 175 | 189 | }); |
| 176 | 190 | const gop = try macho_file.lazy_bindings.getOrPut(gpa, self); |
| 177 | 191 | if (!gop.found_existing) { |
src/link/Plan9.zig+2-7| ... | ... | @@ -424,7 +424,7 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { |
| 424 | 424 | // write the internal linker metadata |
| 425 | 425 | decl.link.plan9.type = sym_t; |
| 426 | 426 | // write the symbol |
| 427 | // we already have the got index because that got allocated in allocateDeclIndexes | |
| 427 | // we already have the got index | |
| 428 | 428 | const sym: aout.Sym = .{ |
| 429 | 429 | .value = undefined, // the value of stuff gets filled in in flushModule |
| 430 | 430 | .type = decl.link.plan9.type, |
| ... | ... | @@ -737,7 +737,7 @@ fn addDeclExports( |
| 737 | 737 | |
| 738 | 738 | pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { |
| 739 | 739 | // TODO audit the lifetimes of decls table entries. It's possible to get |
| 740 | // allocateDeclIndexes and then freeDecl without any updateDecl in between. | |
| 740 | // freeDecl without any updateDecl in between. | |
| 741 | 741 | // However that is planned to change, see the TODO comment in Module.zig |
| 742 | 742 | // in the deleteUnusedDecl function. |
| 743 | 743 | const mod = self.base.options.module.?; |
| ... | ... | @@ -959,11 +959,6 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 959 | 959 | } |
| 960 | 960 | } |
| 961 | 961 | |
| 962 | /// this will be removed, moved to updateFinish | |
| 963 | pub fn allocateDeclIndexes(self: *Plan9, decl_index: Module.Decl.Index) !void { | |
| 964 | _ = self; | |
| 965 | _ = decl_index; | |
| 966 | } | |
| 967 | 962 | /// Must be called only after a successful call to `updateDecl`. |
| 968 | 963 | pub fn updateDeclLineNumber(self: *Plan9, mod: *Module, decl: *const Module.Decl) !void { |
| 969 | 964 | _ = self; |
src/link/Wasm.zig+30-40| ... | ... | @@ -986,31 +986,23 @@ pub fn deinit(wasm: *Wasm) void { |
| 986 | 986 | } |
| 987 | 987 | } |
| 988 | 988 | |
| 989 | pub fn allocateDeclIndexes(wasm: *Wasm, decl_index: Module.Decl.Index) !void { | |
| 990 | if (wasm.llvm_object) |_| return; | |
| 991 | const decl = wasm.base.options.module.?.declPtr(decl_index); | |
| 992 | if (decl.link.wasm.sym_index != 0) return; | |
| 993 | ||
| 989 | /// Allocates a new symbol and returns its index. | |
| 990 | /// Will re-use slots when a symbol was freed at an earlier stage. | |
| 991 | pub fn allocateSymbol(wasm: *Wasm) !u32 { | |
| 994 | 992 | try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1); |
| 995 | try wasm.decls.putNoClobber(wasm.base.allocator, decl_index, {}); | |
| 996 | ||
| 997 | const atom = &decl.link.wasm; | |
| 998 | ||
| 999 | 993 | var symbol: Symbol = .{ |
| 1000 | 994 | .name = undefined, // will be set after updateDecl |
| 1001 | 995 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), |
| 1002 | 996 | .tag = undefined, // will be set after updateDecl |
| 1003 | 997 | .index = undefined, // will be set after updateDecl |
| 1004 | 998 | }; |
| 1005 | ||
| 1006 | 999 | if (wasm.symbols_free_list.popOrNull()) |index| { |
| 1007 | atom.sym_index = index; | |
| 1008 | 1000 | wasm.symbols.items[index] = symbol; |
| 1009 | } else { | |
| 1010 | atom.sym_index = @intCast(u32, wasm.symbols.items.len); | |
| 1011 | wasm.symbols.appendAssumeCapacity(symbol); | |
| 1001 | return index; | |
| 1012 | 1002 | } |
| 1013 | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, atom.symbolLoc(), atom); | |
| 1003 | const index = @intCast(u32, wasm.symbols.items.len); | |
| 1004 | wasm.symbols.appendAssumeCapacity(symbol); | |
| 1005 | return index; | |
| 1014 | 1006 | } |
| 1015 | 1007 | |
| 1016 | 1008 | pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { |
| ... | ... | @@ -1026,9 +1018,12 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes |
| 1026 | 1018 | |
| 1027 | 1019 | const decl_index = func.owner_decl; |
| 1028 | 1020 | const decl = mod.declPtr(decl_index); |
| 1029 | assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes() | |
| 1030 | ||
| 1031 | decl.link.wasm.clear(); | |
| 1021 | const atom = &decl.link.wasm; | |
| 1022 | try atom.ensureInitialized(wasm); | |
| 1023 | const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index); | |
| 1024 | if (gop.found_existing) { | |
| 1025 | atom.clear(); | |
| 1026 | } else gop.value_ptr.* = {}; | |
| 1032 | 1027 | |
| 1033 | 1028 | var decl_state: ?Dwarf.DeclState = if (wasm.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl_index) else null; |
| 1034 | 1029 | defer if (decl_state) |*ds| ds.deinit(); |
| ... | ... | @@ -1083,16 +1078,19 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi |
| 1083 | 1078 | defer tracy.end(); |
| 1084 | 1079 | |
| 1085 | 1080 | const decl = mod.declPtr(decl_index); |
| 1086 | assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes() | |
| 1087 | ||
| 1088 | decl.link.wasm.clear(); | |
| 1089 | ||
| 1090 | 1081 | if (decl.val.castTag(.function)) |_| { |
| 1091 | 1082 | return; |
| 1092 | 1083 | } else if (decl.val.castTag(.extern_fn)) |_| { |
| 1093 | 1084 | return; |
| 1094 | 1085 | } |
| 1095 | 1086 | |
| 1087 | const atom = &decl.link.wasm; | |
| 1088 | try atom.ensureInitialized(wasm); | |
| 1089 | const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index); | |
| 1090 | if (gop.found_existing) { | |
| 1091 | atom.clear(); | |
| 1092 | } else gop.value_ptr.* = {}; | |
| 1093 | ||
| 1096 | 1094 | if (decl.isExtern()) { |
| 1097 | 1095 | const variable = decl.getVariable().?; |
| 1098 | 1096 | const name = mem.sliceTo(decl.name, 0); |
| ... | ... | @@ -1148,8 +1146,8 @@ fn finishUpdateDecl(wasm: *Wasm, decl: *Module.Decl, code: []const u8) !void { |
| 1148 | 1146 | try atom.code.appendSlice(wasm.base.allocator, code); |
| 1149 | 1147 | try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {}); |
| 1150 | 1148 | |
| 1151 | if (code.len == 0) return; | |
| 1152 | 1149 | atom.size = @intCast(u32, code.len); |
| 1150 | if (code.len == 0) return; | |
| 1153 | 1151 | atom.alignment = decl.ty.abiAlignment(wasm.base.options.target); |
| 1154 | 1152 | } |
| 1155 | 1153 | |
| ... | ... | @@ -1211,28 +1209,19 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In |
| 1211 | 1209 | defer wasm.base.allocator.free(fqdn); |
| 1212 | 1210 | const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index }); |
| 1213 | 1211 | defer wasm.base.allocator.free(name); |
| 1214 | var symbol: Symbol = .{ | |
| 1215 | .name = try wasm.string_table.put(wasm.base.allocator, name), | |
| 1216 | .flags = 0, | |
| 1217 | .tag = .data, | |
| 1218 | .index = undefined, | |
| 1219 | }; | |
| 1220 | symbol.setFlag(.WASM_SYM_BINDING_LOCAL); | |
| 1221 | 1212 | |
| 1222 | 1213 | const atom = try decl.link.wasm.locals.addOne(wasm.base.allocator); |
| 1223 | 1214 | atom.* = Atom.empty; |
| 1215 | try atom.ensureInitialized(wasm); | |
| 1224 | 1216 | atom.alignment = tv.ty.abiAlignment(wasm.base.options.target); |
| 1225 | try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1); | |
| 1217 | wasm.symbols.items[atom.sym_index] = .{ | |
| 1218 | .name = try wasm.string_table.put(wasm.base.allocator, name), | |
| 1219 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), | |
| 1220 | .tag = .data, | |
| 1221 | .index = undefined, | |
| 1222 | }; | |
| 1226 | 1223 | |
| 1227 | if (wasm.symbols_free_list.popOrNull()) |index| { | |
| 1228 | atom.sym_index = index; | |
| 1229 | wasm.symbols.items[index] = symbol; | |
| 1230 | } else { | |
| 1231 | atom.sym_index = @intCast(u32, wasm.symbols.items.len); | |
| 1232 | wasm.symbols.appendAssumeCapacity(symbol); | |
| 1233 | } | |
| 1234 | 1224 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {}); |
| 1235 | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, atom.symbolLoc(), atom); | |
| 1236 | 1225 | |
| 1237 | 1226 | var value_bytes = std.ArrayList(u8).init(wasm.base.allocator); |
| 1238 | 1227 | defer value_bytes.deinit(); |
| ... | ... | @@ -1304,8 +1293,8 @@ pub fn getDeclVAddr( |
| 1304 | 1293 | ) !u64 { |
| 1305 | 1294 | const mod = wasm.base.options.module.?; |
| 1306 | 1295 | const decl = mod.declPtr(decl_index); |
| 1296 | try decl.link.wasm.ensureInitialized(wasm); | |
| 1307 | 1297 | const target_symbol_index = decl.link.wasm.sym_index; |
| 1308 | assert(target_symbol_index != 0); | |
| 1309 | 1298 | assert(reloc_info.parent_atom_index != 0); |
| 1310 | 1299 | const atom = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; |
| 1311 | 1300 | const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32; |
| ... | ... | @@ -1363,6 +1352,7 @@ pub fn updateDeclExports( |
| 1363 | 1352 | } |
| 1364 | 1353 | |
| 1365 | 1354 | const decl = mod.declPtr(decl_index); |
| 1355 | if (decl.link.wasm.getSymbolIndex() == null) return; // unititialized | |
| 1366 | 1356 | |
| 1367 | 1357 | for (exports) |exp| { |
| 1368 | 1358 | if (exp.options.section) |section| { |
src/link/Wasm/Atom.zig+11| ... | ... | @@ -95,6 +95,17 @@ pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc { |
| 95 | 95 | return .{ .file = atom.file, .index = atom.sym_index }; |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | pub fn ensureInitialized(atom: *Atom, wasm_bin: *Wasm) !void { | |
| 99 | if (atom.getSymbolIndex() != null) return; // already initialized | |
| 100 | atom.sym_index = try wasm_bin.allocateSymbol(); | |
| 101 | try wasm_bin.symbol_atom.putNoClobber(wasm_bin.base.allocator, atom.symbolLoc(), atom); | |
| 102 | } | |
| 103 | ||
| 104 | pub fn getSymbolIndex(atom: Atom) ?u32 { | |
| 105 | if (atom.sym_index == 0) return null; | |
| 106 | return atom.sym_index; | |
| 107 | } | |
| 108 | ||
| 98 | 109 | /// Returns the virtual address of the `Atom`. This is the address starting |
| 99 | 110 | /// from the first entry within a section. |
| 100 | 111 | pub fn getVA(atom: Atom, wasm: *const Wasm, symbol: *const Symbol) u32 { |