| ... | @@ -25,20 +25,22 @@ sixtyfour_bit: bool, | ... | @@ -25,20 +25,22 @@ sixtyfour_bit: bool, |
| 25 | error_flags: File.ErrorFlags = File.ErrorFlags{}, | 25 | error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 26 | bases: Bases, | 26 | bases: Bases, |
| 27 | | 27 | |
| 28 | decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{}, | 28 | /// A symbol's value is just casted down when compiling |
| 29 | /// is just casted down when 32 bit | 29 | /// for a 32 bit target. |
| 30 | syms: std.ArrayListUnmanaged(aout.Sym) = .{}, | 30 | syms: std.ArrayListUnmanaged(aout.Sym) = .{}, |
| 31 | text_buf: std.ArrayListUnmanaged(u8) = .{}, | 31 | |
| 32 | data_buf: std.ArrayListUnmanaged(u8) = .{}, | 32 | fn_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{}, |
| | 33 | data_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{}, |
| 33 | | 34 | |
| 34 | hdr: aout.ExecHdr = undefined, | 35 | hdr: aout.ExecHdr = undefined, |
| 35 | | 36 | |
| 36 | entry_decl: ?*Module.Decl = null, | 37 | entry_decl: ?*Module.Decl = null, |
| 37 | | 38 | |
| 38 | got: std.ArrayListUnmanaged(u64) = .{}, | 39 | got_len: u64 = 0, |
| | 40 | |
| 39 | const Bases = struct { | 41 | const Bases = struct { |
| 40 | text: u64, | 42 | text: u64, |
| 41 | /// the addr of the got | 43 | /// the Global Offset Table starts at the beginning of the data section |
| 42 | data: u64, | 44 | data: u64, |
| 43 | }; | 45 | }; |
| 44 | | 46 | |
| ... | @@ -49,14 +51,6 @@ fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { | ... | @@ -49,14 +51,6 @@ fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { |
| 49 | else => unreachable, | 51 | else => unreachable, |
| 50 | }; | 52 | }; |
| 51 | } | 53 | } |
| 52 | /// opposite of getAddr | | |
| 53 | fn takeAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { | | |
| 54 | return addr - switch (t) { | | |
| 55 | .T, .t, .l, .L => self.bases.text, | | |
| 56 | .D, .d, .B, .b => self.bases.data, | | |
| 57 | else => unreachable, | | |
| 58 | }; | | |
| 59 | } | | |
| 60 | | 54 | |
| 61 | fn getSymAddr(self: Plan9, s: aout.Sym) u64 { | 55 | fn getSymAddr(self: Plan9, s: aout.Sym) u64 { |
| 62 | return self.getAddr(s.value, s.type); | 56 | return self.getAddr(s.value, s.type); |
| ... | @@ -127,18 +121,80 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv | ... | @@ -127,18 +121,80 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv |
| 127 | if (build_options.skip_non_native and builtin.object_format != .plan9) { | 121 | if (build_options.skip_non_native and builtin.object_format != .plan9) { |
| 128 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 122 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 129 | } | 123 | } |
| 130 | _ = module; | | |
| 131 | // Keep track of all decls so we can iterate over them on flush(). | | |
| 132 | _ = try self.decl_table.getOrPut(self.base.allocator, func.owner_decl); | | |
| 133 | | 124 | |
| 134 | _ = air; | 125 | const decl = func.owner_decl; |
| 135 | _ = liveness; | 126 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); |
| 136 | @panic("TODO Plan9 needs to keep track of Air and Liveness so it can use them later"); | 127 | |
| | 128 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| | 129 | defer code_buffer.deinit(); |
| | 130 | const res = try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ .none = .{} }); |
| | 131 | const code = switch (res) { |
| | 132 | .appended => code_buffer.toOwnedSlice(), |
| | 133 | .fail => |em| { |
| | 134 | decl.analysis = .codegen_failure; |
| | 135 | try module.failed_decls.put(module.gpa, decl, em); |
| | 136 | return; |
| | 137 | }, |
| | 138 | }; |
| | 139 | try self.fn_decl_table.put(self.base.allocator, decl, code); |
| | 140 | return self.updateFinish(decl); |
| 137 | } | 141 | } |
| 138 | | 142 | |
| 139 | pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void { | 143 | pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void { |
| 140 | _ = module; | 144 | if (decl.val.tag() == .extern_fn) { |
| 141 | _ = try self.decl_table.getOrPut(self.base.allocator, decl); | 145 | return; // TODO Should we do more when front-end analyzed extern decl? |
| | 146 | } |
| | 147 | if (decl.val.castTag(.variable)) |payload| { |
| | 148 | const variable = payload.data; |
| | 149 | if (variable.is_extern) { |
| | 150 | return; // TODO Should we do more when front-end analyzed extern decl? |
| | 151 | } |
| | 152 | } |
| | 153 | |
| | 154 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); |
| | 155 | |
| | 156 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| | 157 | defer code_buffer.deinit(); |
| | 158 | const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; |
| | 159 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| | 160 | .ty = decl.ty, |
| | 161 | .val = decl_val, |
| | 162 | }, &code_buffer, .{ .none = .{} }); |
| | 163 | const code = switch (res) { |
| | 164 | .externally_managed => |x| x, |
| | 165 | .appended => code_buffer.items, |
| | 166 | .fail => |em| { |
| | 167 | decl.analysis = .codegen_failure; |
| | 168 | try module.failed_decls.put(module.gpa, decl, em); |
| | 169 | return; |
| | 170 | }, |
| | 171 | }; |
| | 172 | var duped_code = try std.mem.dupe(self.base.allocator, u8, code); |
| | 173 | errdefer self.base.allocator.free(duped_code); |
| | 174 | try self.data_decl_table.put(self.base.allocator, decl, duped_code); |
| | 175 | return self.updateFinish(decl); |
| | 176 | } |
| | 177 | /// called at the end of update{Decl,Func} |
| | 178 | fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { |
| | 179 | const is_fn = (decl.ty.zigTypeTag() == .Fn); |
| | 180 | log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name }); |
| | 181 | const sym_t: aout.Sym.Type = if (is_fn) .t else .d; |
| | 182 | // write the internal linker metadata |
| | 183 | decl.link.plan9.type = sym_t; |
| | 184 | // write the symbol |
| | 185 | // we already have the got index because that got allocated in allocateDeclIndexes |
| | 186 | const sym: aout.Sym = .{ |
| | 187 | .value = undefined, // the value of stuff gets filled in in flushModule |
| | 188 | .type = decl.link.plan9.type, |
| | 189 | .name = mem.span(decl.name), |
| | 190 | }; |
| | 191 | |
| | 192 | if (decl.link.plan9.sym_index) |s| { |
| | 193 | self.syms.items[s] = sym; |
| | 194 | } else { |
| | 195 | try self.syms.append(self.base.allocator, sym); |
| | 196 | decl.link.plan9.sym_index = self.syms.items.len - 1; |
| | 197 | } |
| 142 | } | 198 | } |
| 143 | | 199 | |
| 144 | pub fn flush(self: *Plan9, comp: *Compilation) !void { | 200 | pub fn flush(self: *Plan9, comp: *Compilation) !void { |
| ... | @@ -165,160 +221,107 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -165,160 +221,107 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 165 | | 221 | |
| 166 | defer assert(self.hdr.entry != 0x0); | 222 | defer assert(self.hdr.entry != 0x0); |
| 167 | | 223 | |
| 168 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 224 | _ = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 169 | | 225 | |
| 170 | self.text_buf.items.len = 0; | 226 | assert(self.got_len == self.fn_decl_table.count() + self.data_decl_table.count()); |
| 171 | self.data_buf.items.len = 0; | 227 | const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; |
| 172 | // ensure space to write the got later | 228 | var got_table = try self.base.allocator.alloc(u8, got_size); |
| 173 | assert(self.got.items.len == self.decl_table.count()); | 229 | defer self.base.allocator.free(got_table); |
| 174 | try self.data_buf.appendNTimes(self.base.allocator, 0x69, self.got.items.len * if (!self.sixtyfour_bit) @as(u32, 4) else 8); | | |
| 175 | // temporary buffer | | |
| 176 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | | |
| 177 | defer code_buffer.deinit(); | | |
| 178 | { | | |
| 179 | for (self.decl_table.keys()) |decl| { | | |
| 180 | if (!decl.has_tv) continue; | | |
| 181 | const is_fn = (decl.ty.zigTypeTag() == .Fn); | | |
| 182 | | | |
| 183 | log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name }); | | |
| 184 | decl.link.plan9 = if (is_fn) .{ | | |
| 185 | .offset = self.getAddr(self.text_buf.items.len, .t), | | |
| 186 | .type = .t, | | |
| 187 | .sym_index = decl.link.plan9.sym_index, | | |
| 188 | .got_index = decl.link.plan9.got_index, | | |
| 189 | } else .{ | | |
| 190 | .offset = self.getAddr(self.data_buf.items.len, .d), | | |
| 191 | .type = .d, | | |
| 192 | .sym_index = decl.link.plan9.sym_index, | | |
| 193 | .got_index = decl.link.plan9.got_index, | | |
| 194 | }; | | |
| 195 | self.got.items[decl.link.plan9.got_index.?] = decl.link.plan9.offset.?; | | |
| 196 | if (decl.link.plan9.sym_index) |s| { | | |
| 197 | self.syms.items[s] = .{ | | |
| 198 | .value = decl.link.plan9.offset.?, | | |
| 199 | .type = decl.link.plan9.type, | | |
| 200 | .name = mem.span(decl.name), | | |
| 201 | }; | | |
| 202 | } else { | | |
| 203 | try self.syms.append(self.base.allocator, .{ | | |
| 204 | .value = decl.link.plan9.offset.?, | | |
| 205 | .type = decl.link.plan9.type, | | |
| 206 | .name = mem.span(decl.name), | | |
| 207 | }); | | |
| 208 | decl.link.plan9.sym_index = self.syms.items.len - 1; | | |
| 209 | } | | |
| 210 | | 230 | |
| 211 | if (module.decl_exports.get(decl)) |exports| { | 231 | // + 2 for header, got, symbols |
| 212 | for (exports) |exp| { | 232 | var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.fn_decl_table.count() + self.data_decl_table.count() + 3); |
| 213 | // plan9 does not support custom sections | 233 | |
| 214 | if (exp.options.section) |section_name| { | 234 | const file = self.base.file.?; |
| 215 | if (!mem.eql(u8, section_name, ".text") or !mem.eql(u8, section_name, ".data")) { | | |
| 216 | try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "plan9 does not support extra sections", .{})); | | |
| 217 | break; | | |
| 218 | } | | |
| 219 | } | | |
| 220 | if (std.mem.eql(u8, exp.options.name, "_start")) { | | |
| 221 | assert(decl.link.plan9.type == .t); // we tried to link a non-function as the entry | | |
| 222 | self.entry_decl = decl; | | |
| 223 | } | | |
| 224 | if (exp.link.plan9) |i| { | | |
| 225 | self.syms.items[i] = .{ | | |
| 226 | .value = decl.link.plan9.offset.?, | | |
| 227 | .type = decl.link.plan9.type.toGlobal(), | | |
| 228 | .name = exp.options.name, | | |
| 229 | }; | | |
| 230 | } else { | | |
| 231 | try self.syms.append(self.base.allocator, .{ | | |
| 232 | .value = decl.link.plan9.offset.?, | | |
| 233 | .type = decl.link.plan9.type.toGlobal(), | | |
| 234 | .name = exp.options.name, | | |
| 235 | }); | | |
| 236 | exp.link.plan9 = self.syms.items.len - 1; | | |
| 237 | } | | |
| 238 | } | | |
| 239 | } | | |
| 240 | | 235 | |
| 241 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); | 236 | var hdr_buf: [40]u8 = undefined; |
| 242 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ | 237 | // account for the fat header |
| 243 | .ty = decl.ty, | 238 | const hdr_size = if (self.sixtyfour_bit) @as(usize, 40) else 32; |
| 244 | .val = decl.val, | 239 | const hdr_slice: []u8 = hdr_buf[0..hdr_size]; |
| 245 | }, &code_buffer, .{ .none = {} }); | 240 | var foff = hdr_size; |
| 246 | const code = switch (res) { | 241 | iovecs[0] = .{ .iov_base = hdr_slice.ptr, .iov_len = hdr_slice.len }; |
| 247 | .externally_managed => |x| x, | 242 | var iovecs_i: u64 = 1; |
| 248 | .appended => code_buffer.items, | 243 | var text_i: u64 = 0; |
| 249 | .fail => |em| { | 244 | // text |
| 250 | decl.analysis = .codegen_failure; | 245 | { |
| 251 | try module.failed_decls.put(module.gpa, decl, em); | 246 | var it = self.fn_decl_table.iterator(); |
| 252 | // TODO try to do more decls | 247 | while (it.next()) |entry| { |
| 253 | return; | 248 | const decl = entry.key_ptr.*; |
| 254 | }, | 249 | const code = entry.value_ptr.*; |
| 255 | }; | 250 | foff += code.len; |
| 256 | if (is_fn) { | 251 | text_i += code.len; |
| 257 | try self.text_buf.appendSlice(self.base.allocator, code); | 252 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; |
| 258 | code_buffer.items.len = 0; | 253 | iovecs_i += 1; |
| | 254 | const off = self.getAddr(text_i, .t); |
| | 255 | decl.link.plan9.offset = off; |
| | 256 | if (!self.sixtyfour_bit) { |
| | 257 | mem.writeIntNative(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off)); |
| | 258 | mem.writeInt(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); |
| 259 | } else { | 259 | } else { |
| 260 | try self.data_buf.appendSlice(self.base.allocator, code); | 260 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| 261 | code_buffer.items.len = 0; | | |
| 262 | } | 261 | } |
| | 262 | self.syms.items[decl.link.plan9.sym_index.?].value = off; |
| 263 | } | 263 | } |
| | 264 | // etext symbol |
| | 265 | self.syms.items[2].value = self.getAddr(text_i, .t); |
| 264 | } | 266 | } |
| 265 | | 267 | // data |
| 266 | // write the got | 268 | var data_i: u64 = got_size; |
| 267 | if (!self.sixtyfour_bit) { | 269 | { |
| 268 | for (self.got.items) |p, i| { | 270 | var it = self.data_decl_table.iterator(); |
| 269 | mem.writeInt(u32, self.data_buf.items[i * 4 ..][0..4], @intCast(u32, p), self.base.options.target.cpu.arch.endian()); | 271 | while (it.next()) |entry| { |
| 270 | } | 272 | const decl = entry.key_ptr.*; |
| 271 | } else { | 273 | const code = entry.value_ptr.*; |
| 272 | for (self.got.items) |p, i| { | 274 | foff += code.len; |
| 273 | mem.writeInt(u64, self.data_buf.items[i * 8 ..][0..8], p, self.base.options.target.cpu.arch.endian()); | 275 | data_i += code.len; |
| | 276 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; |
| | 277 | iovecs_i += 1; |
| | 278 | const off = self.getAddr(data_i, .d); |
| | 279 | decl.link.plan9.offset = off; |
| | 280 | if (!self.sixtyfour_bit) { |
| | 281 | mem.writeInt(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); |
| | 282 | } else { |
| | 283 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| | 284 | } |
| | 285 | self.syms.items[decl.link.plan9.sym_index.?].value = off; |
| 274 | } | 286 | } |
| | 287 | // edata symbol |
| | 288 | self.syms.items[0].value = self.getAddr(data_i, .b); |
| 275 | } | 289 | } |
| 276 | | 290 | // edata |
| 277 | self.hdr.entry = @truncate(u32, self.entry_decl.?.link.plan9.offset.?); | | |
| 278 | | | |
| 279 | // edata, end, etext | | |
| 280 | self.syms.items[0].value = self.getAddr(0x0, .b); | | |
| 281 | self.syms.items[1].value = self.getAddr(0x0, .b); | 291 | self.syms.items[1].value = self.getAddr(0x0, .b); |
| 282 | self.syms.items[2].value = self.getAddr(self.text_buf.items.len, .t); | | |
| 283 | | | |
| 284 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); | 292 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); |
| 285 | defer sym_buf.deinit(); | 293 | defer sym_buf.deinit(); |
| 286 | try self.writeSyms(&sym_buf); | 294 | try self.writeSyms(&sym_buf); |
| 287 | | 295 | iovecs[iovecs_i] = .{ .iov_base = got_table.ptr, .iov_len = got_table.len }; |
| | 296 | iovecs_i += 1; |
| | 297 | assert(2 + self.fn_decl_table.count() + self.data_decl_table.count() == iovecs_i); // we didn't write all the decls |
| | 298 | iovecs[iovecs_i] = .{ .iov_base = sym_buf.items.ptr, .iov_len = sym_buf.items.len }; |
| | 299 | iovecs_i += 1; |
| 288 | // generate the header | 300 | // generate the header |
| 289 | self.hdr = .{ | 301 | self.hdr = .{ |
| 290 | .magic = try aout.magicFromArch(self.base.options.target.cpu.arch), | 302 | .magic = try aout.magicFromArch(self.base.options.target.cpu.arch), |
| 291 | .text = @intCast(u32, self.text_buf.items.len), | 303 | .text = @intCast(u32, text_i), |
| 292 | .data = @intCast(u32, self.data_buf.items.len), | 304 | .data = @intCast(u32, data_i), |
| 293 | .syms = @intCast(u32, sym_buf.items.len), | 305 | .syms = @intCast(u32, sym_buf.items.len), |
| 294 | .bss = 0, | 306 | .bss = 0, |
| 295 | .pcsz = 0, | 307 | .pcsz = 0, |
| 296 | .spsz = 0, | 308 | .spsz = 0, |
| 297 | .entry = self.hdr.entry, | 309 | .entry = @intCast(u32, self.entry_decl.?.link.plan9.offset.?), |
| 298 | }; | 310 | }; |
| 299 | | 311 | std.mem.copy(u8, hdr_slice, self.hdr.toU8s()[0..hdr_size]); |
| 300 | const file = self.base.file.?; | | |
| 301 | | | |
| 302 | var hdr_buf = self.hdr.toU8s(); | | |
| 303 | const hdr_slice: []const u8 = &hdr_buf; | | |
| 304 | // account for the fat header | | |
| 305 | const hdr_size: u8 = if (!self.sixtyfour_bit) 32 else 40; | | |
| 306 | // write the fat header for 64 bit entry points | 312 | // write the fat header for 64 bit entry points |
| 307 | if (self.sixtyfour_bit) { | 313 | if (self.sixtyfour_bit) { |
| 308 | mem.writeIntSliceBig(u64, hdr_buf[32..40], self.hdr.entry); | 314 | mem.writeIntSliceBig(u64, hdr_buf[32..40], self.entry_decl.?.link.plan9.offset.?); |
| 309 | } | 315 | } |
| 310 | // write it all! | 316 | // write it all! |
| 311 | var vectors: [4]std.os.iovec_const = .{ | 317 | try file.pwritevAll(iovecs, 0); |
| 312 | .{ .iov_base = hdr_slice.ptr, .iov_len = hdr_size }, | | |
| 313 | .{ .iov_base = self.text_buf.items.ptr, .iov_len = self.text_buf.items.len }, | | |
| 314 | .{ .iov_base = self.data_buf.items.ptr, .iov_len = self.data_buf.items.len }, | | |
| 315 | .{ .iov_base = sym_buf.items.ptr, .iov_len = sym_buf.items.len }, | | |
| 316 | // TODO spsz, pcsz | | |
| 317 | }; | | |
| 318 | try file.pwritevAll(&vectors, 0); | | |
| 319 | } | 318 | } |
| 320 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { | 319 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { |
| 321 | assert(self.decl_table.swapRemove(decl)); | 320 | const is_fn = (decl.ty.zigTypeTag() == .Fn); |
| | 321 | if (is_fn) |
| | 322 | assert(self.fn_decl_table.swapRemove(decl)) |
| | 323 | else |
| | 324 | assert(self.data_decl_table.swapRemove(decl)); |
| 322 | } | 325 | } |
| 323 | | 326 | |
| 324 | pub fn updateDeclExports( | 327 | pub fn updateDeclExports( |
| ... | @@ -334,11 +337,17 @@ pub fn updateDeclExports( | ... | @@ -334,11 +337,17 @@ pub fn updateDeclExports( |
| 334 | _ = exports; | 337 | _ = exports; |
| 335 | } | 338 | } |
| 336 | pub fn deinit(self: *Plan9) void { | 339 | pub fn deinit(self: *Plan9) void { |
| 337 | self.decl_table.deinit(self.base.allocator); | 340 | var itf = self.fn_decl_table.iterator(); |
| | 341 | while (itf.next()) |entry| { |
| | 342 | self.base.allocator.free(entry.value_ptr.*); |
| | 343 | } |
| | 344 | self.fn_decl_table.deinit(self.base.allocator); |
| | 345 | var itd = self.data_decl_table.iterator(); |
| | 346 | while (itd.next()) |entry| { |
| | 347 | self.base.allocator.free(entry.value_ptr.*); |
| | 348 | } |
| | 349 | self.data_decl_table.deinit(self.base.allocator); |
| 338 | self.syms.deinit(self.base.allocator); | 350 | self.syms.deinit(self.base.allocator); |
| 339 | self.text_buf.deinit(self.base.allocator); | | |
| 340 | self.data_buf.deinit(self.base.allocator); | | |
| 341 | self.got.deinit(self.base.allocator); | | |
| 342 | } | 351 | } |
| 343 | | 352 | |
| 344 | pub const Export = ?usize; | 353 | pub const Export = ?usize; |
| ... | @@ -397,6 +406,8 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | ... | @@ -397,6 +406,8 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 397 | } | 406 | } |
| 398 | | 407 | |
| 399 | pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { | 408 | pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { |
| 400 | try self.got.append(self.base.allocator, 0xdeadbeef); | 409 | if (decl.link.plan9.got_index != null) { |
| 401 | decl.link.plan9.got_index = self.got.items.len - 1; | 410 | self.got_len += 1; |
| | 411 | decl.link.plan9.got_index = self.got_len - 1; |
| | 412 | } |
| 402 | } | 413 | } |