| ... | @@ -10,6 +10,7 @@ const fs = std.fs; | ... | @@ -10,6 +10,7 @@ const fs = std.fs; |
| 10 | const elf = std.elf; | 10 | const elf = std.elf; |
| 11 | const log = std.log.scoped(.link); | 11 | const log = std.log.scoped(.link); |
| 12 | | 12 | |
| | 13 | const Atom = @import("Elf/Atom.zig"); |
| 13 | const Module = @import("../Module.zig"); | 14 | const Module = @import("../Module.zig"); |
| 14 | const Compilation = @import("../Compilation.zig"); | 15 | const Compilation = @import("../Compilation.zig"); |
| 15 | const Dwarf = @import("Dwarf.zig"); | 16 | const Dwarf = @import("Dwarf.zig"); |
| ... | @@ -31,6 +32,8 @@ const Air = @import("../Air.zig"); | ... | @@ -31,6 +32,8 @@ const Air = @import("../Air.zig"); |
| 31 | const Liveness = @import("../Liveness.zig"); | 32 | const Liveness = @import("../Liveness.zig"); |
| 32 | const LlvmObject = @import("../codegen/llvm.zig").Object; | 33 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 33 | | 34 | |
| | 35 | pub const TextBlock = Atom; |
| | 36 | |
| 34 | const default_entry_addr = 0x8000000; | 37 | const default_entry_addr = 0x8000000; |
| 35 | | 38 | |
| 36 | pub const base_tag: File.Tag = .elf; | 39 | pub const base_tag: File.Tag = .elf; |
| ... | @@ -188,62 +191,10 @@ const ideal_factor = 3; | ... | @@ -188,62 +191,10 @@ const ideal_factor = 3; |
| 188 | /// it as a possible place to put new symbols, it must have enough room for this many bytes | 191 | /// it as a possible place to put new symbols, it must have enough room for this many bytes |
| 189 | /// (plus extra for reserved capacity). | 192 | /// (plus extra for reserved capacity). |
| 190 | const minimum_text_block_size = 64; | 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 | pub const PtrWidth = enum { p32, p64 }; | 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 | pub const Export = struct { | 198 | pub const Export = struct { |
| 248 | sym_index: ?u32 = null, | 199 | sym_index: ?u32 = null, |
| 249 | }; | 200 | }; |
| ... | @@ -3052,7 +3003,7 @@ fn getLDMOption(target: std.Target) ?[]const u8 { | ... | @@ -3052,7 +3003,7 @@ fn getLDMOption(target: std.Target) ?[]const u8 { |
| 3052 | } | 3003 | } |
| 3053 | } | 3004 | } |
| 3054 | | 3005 | |
| 3055 | fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | 3006 | pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 3056 | return actual_size +| (actual_size / ideal_factor); | 3007 | return actual_size +| (actual_size / ideal_factor); |
| 3057 | } | 3008 | } |
| 3058 | | 3009 | |