| ... | ... | @@ -33,7 +33,6 @@ pub const base_tag = link.File.Tag.wasm; |
| 33 | 33 | |
| 34 | 34 | pub const FnData = struct { |
| 35 | 35 | funcidx: u32, |
| 36 | | typeidx: u32, |
| 37 | 36 | }; |
| 38 | 37 | |
| 39 | 38 | base: link.File, |
| ... | ... | @@ -99,7 +98,6 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { |
| 99 | 98 | return error.TODOImplementNonFnDeclsForWasm; |
| 100 | 99 | |
| 101 | 100 | if (decl.fn_link.wasm) |fn_data| { |
| 102 | | self.types.free(fn_data.typeidx); |
| 103 | 101 | self.funcs.free(fn_data.funcidx); |
| 104 | 102 | } |
| 105 | 103 | |
| ... | ... | @@ -113,7 +111,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { |
| 113 | 111 | try codegen.genCode(&buf, decl); |
| 114 | 112 | const funcidx = try self.funcs.new(typeidx, buf.items); |
| 115 | 113 | |
| 116 | | decl.fn_link.wasm = .{ .typeidx = typeidx, .funcidx = funcidx }; |
| 114 | decl.fn_link.wasm = .{ .funcidx = funcidx }; |
| 117 | 115 | |
| 118 | 116 | // TODO: we should be more smart and set this only when needed |
| 119 | 117 | self.exports.dirty = true; |
| ... | ... | @@ -132,7 +130,6 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { |
| 132 | 130 | // TODO: remove this assert when non-function Decls are implemented |
| 133 | 131 | assert(decl.typed_value.most_recent.typed_value.ty.zigTypeTag() == .Fn); |
| 134 | 132 | if (decl.fn_link.wasm) |fn_data| { |
| 135 | | self.types.free(fn_data.typeidx); |
| 136 | 133 | self.funcs.free(fn_data.funcidx); |
| 137 | 134 | decl.fn_link.wasm = null; |
| 138 | 135 | } |
| ... | ... | @@ -307,21 +304,20 @@ const Funcs = struct { |
| 307 | 304 | /// This section needs special handling to keep the indexes matching with |
| 308 | 305 | /// the codesec, so we cant just use a VecSection. |
| 309 | 306 | funcsec: Section, |
| 310 | | /// Number of functions listed in the funcsec. Must be kept in sync with |
| 311 | | /// codesec.entries.items.len. |
| 312 | | funcs_count: u32, |
| 307 | /// The typeidx stored for each function, indexed by funcidx. |
| 308 | func_types: std.ArrayListUnmanaged(u32) = std.ArrayListUnmanaged(u32){}, |
| 313 | 309 | codesec: VecSection, |
| 314 | 310 | |
| 315 | 311 | fn init(file: fs.File, funcs_offset: u64, funcs_size: u64, code_offset: u64, code_size: u64) !Funcs { |
| 316 | 312 | return Funcs{ |
| 317 | 313 | .funcsec = (try VecSection.init(spec.funcs_id, file, funcs_offset, funcs_size)).section, |
| 318 | | .funcs_count = 0, |
| 319 | 314 | .codesec = try VecSection.init(spec.code_id, file, code_offset, code_size), |
| 320 | 315 | }; |
| 321 | 316 | } |
| 322 | 317 | |
| 323 | 318 | fn deinit(self: *Funcs) void { |
| 324 | 319 | const wasm = @fieldParentPtr(Wasm, "funcs", self); |
| 320 | self.func_types.deinit(wasm.base.allocator); |
| 325 | 321 | self.codesec.deinit(wasm.base.allocator); |
| 326 | 322 | } |
| 327 | 323 | |
| ... | ... | @@ -333,25 +329,30 @@ const Funcs = struct { |
| 333 | 329 | const file = wasm.base.file.?; |
| 334 | 330 | const allocator = wasm.base.allocator; |
| 335 | 331 | |
| 336 | | assert(self.funcs_count == self.codesec.entries.items.len); |
| 332 | assert(self.func_types.items.len == self.codesec.entries.items.len); |
| 337 | 333 | |
| 338 | 334 | // TODO: consider nop-padding the code if there is a close but not perfect fit |
| 339 | 335 | const funcidx = try self.codesec.addEntry(file, allocator, code); |
| 340 | 336 | |
| 341 | | if (self.funcs_count < self.codesec.entries.items.len) { |
| 337 | if (self.func_types.items.len < self.codesec.entries.items.len) { |
| 342 | 338 | // u32 vector length + funcs_count u32s in the vector |
| 343 | | const current = 5 + self.funcs_count * 5; |
| 339 | const current = 5 + @intCast(u32, self.func_types.items.len) * 5; |
| 344 | 340 | try self.funcsec.resize(file, current, current + 5); |
| 345 | | self.funcs_count += 1; |
| 341 | try self.func_types.append(allocator, typeidx); |
| 346 | 342 | |
| 347 | 343 | // Update the size in the section header and the item count of |
| 348 | 344 | // the contents vector. |
| 345 | const count = @intCast(u32, self.func_types.items.len); |
| 349 | 346 | var size_and_count: [10]u8 = undefined; |
| 350 | | leb.writeUnsignedFixed(5, size_and_count[0..5], 5 + self.funcs_count * 5); |
| 351 | | leb.writeUnsignedFixed(5, size_and_count[5..], self.funcs_count); |
| 347 | leb.writeUnsignedFixed(5, size_and_count[0..5], 5 + count * 5); |
| 348 | leb.writeUnsignedFixed(5, size_and_count[5..], count); |
| 352 | 349 | try file.pwriteAll(&size_and_count, self.funcsec.offset + 1); |
| 350 | } else { |
| 351 | // We are overwriting a dead function and may now free the type |
| 352 | wasm.types.free(self.func_types.items[funcidx]); |
| 353 | 353 | } |
| 354 | | assert(self.funcs_count == self.codesec.entries.items.len); |
| 354 | |
| 355 | assert(self.func_types.items.len == self.codesec.entries.items.len); |
| 355 | 356 | |
| 356 | 357 | var typeidx_leb: [5]u8 = undefined; |
| 357 | 358 | leb.writeUnsignedFixed(5, &typeidx_leb, typeidx); |