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