| ... | @@ -85,8 +85,6 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { | ... | @@ -85,8 +85,6 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { |
| 85 | const typed_value = decl.typed_value.most_recent.typed_value; | 85 | const typed_value = decl.typed_value.most_recent.typed_value; |
| 86 | if (typed_value.ty.zigTypeTag() != .Fn) | 86 | if (typed_value.ty.zigTypeTag() != .Fn) |
| 87 | return error.TODOImplementNonFnDeclsForWasm; | 87 | return error.TODOImplementNonFnDeclsForWasm; |
| 88 | if (typed_value.val.tag() == .extern_fn) | | |
| 89 | return error.TODOImplementExternFnDeclsForWasm; | | |
| 90 | | 88 | |
| 91 | if (decl.fn_link.wasm) |*fn_data| { | 89 | if (decl.fn_link.wasm) |*fn_data| { |
| 92 | fn_data.functype.items.len = 0; | 90 | fn_data.functype.items.len = 0; |
| ... | @@ -184,17 +182,63 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -184,17 +182,63 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 184 | ); | 182 | ); |
| 185 | } | 183 | } |
| 186 | | 184 | |
| | 185 | // Import section |
| | 186 | { |
| | 187 | // TODO: implement non-functions imports |
| | 188 | const header_offset = try reserveVecSectionHeader(file); |
| | 189 | const writer = file.writer(); |
| | 190 | var count: u32 = 0; |
| | 191 | for (self.funcs.items) |decl, typeidx| { |
| | 192 | if (decl.typed_value.most_recent.typed_value.val.tag() != .extern_fn) { |
| | 193 | continue; |
| | 194 | } |
| | 195 | |
| | 196 | // TODO: can we set/save the module name somewhere? |
| | 197 | // For now, emit "env" like LLVM does |
| | 198 | const module_name = "env"; |
| | 199 | try leb.writeULEB128(writer, @intCast(u32, module_name.len)); |
| | 200 | try writer.writeAll(module_name); |
| | 201 | |
| | 202 | // wasm requires the length of the import name and doesn't require a null-termination |
| | 203 | const decl_len = mem.len(decl.name); |
| | 204 | try leb.writeULEB128(writer, @intCast(u32, decl_len)); |
| | 205 | try writer.writeAll(decl.name[0..decl_len]); |
| | 206 | |
| | 207 | // emit kind and the function type |
| | 208 | try writer.writeByte(wasm.kind(.function)); |
| | 209 | try leb.writeULEB128(writer, @intCast(u32, typeidx)); |
| | 210 | |
| | 211 | count += 1; |
| | 212 | } |
| | 213 | |
| | 214 | try writeVecSectionHeader( |
| | 215 | file, |
| | 216 | header_offset, |
| | 217 | .import, |
| | 218 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| | 219 | count, |
| | 220 | ); |
| | 221 | } |
| | 222 | |
| 187 | // Function section | 223 | // Function section |
| 188 | { | 224 | { |
| 189 | const header_offset = try reserveVecSectionHeader(file); | 225 | const header_offset = try reserveVecSectionHeader(file); |
| 190 | const writer = file.writer(); | 226 | const writer = file.writer(); |
| 191 | for (self.funcs.items) |_, typeidx| try leb.writeULEB128(writer, @intCast(u32, typeidx)); | 227 | var count: u32 = 0; |
| | 228 | for (self.funcs.items) |decl, typeidx| { |
| | 229 | // Extern functions only have a type, so skip the function signature section |
| | 230 | if (decl.typed_value.most_recent.typed_value.val.tag() != .function) { |
| | 231 | continue; |
| | 232 | } |
| | 233 | try leb.writeULEB128(writer, @intCast(u32, typeidx)); |
| | 234 | count += 1; |
| | 235 | } |
| 192 | try writeVecSectionHeader( | 236 | try writeVecSectionHeader( |
| 193 | file, | 237 | file, |
| 194 | header_offset, | 238 | header_offset, |
| 195 | .function, | 239 | .function, |
| 196 | @intCast(u32, (try file.getPos()) - header_offset - header_size), | 240 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| 197 | @intCast(u32, self.funcs.items.len), | 241 | count, |
| 198 | ); | 242 | ); |
| 199 | } | 243 | } |
| 200 | | 244 | |
| ... | @@ -214,7 +258,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -214,7 +258,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 214 | // Type of the export | 258 | // Type of the export |
| 215 | try writer.writeByte(0x00); | 259 | try writer.writeByte(0x00); |
| 216 | // Exported function index | 260 | // Exported function index |
| 217 | try leb.writeULEB128(writer, self.getFuncidx(exprt.exported_decl).?); | 261 | try leb.writeULEB128(writer, self.getFuncidx(exprt.exported_decl).? + 1); |
| 218 | }, | 262 | }, |
| 219 | else => return error.TODOImplementNonFnDeclsForWasm, | 263 | else => return error.TODOImplementNonFnDeclsForWasm, |
| 220 | } | 264 | } |
| ... | @@ -235,7 +279,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -235,7 +279,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 235 | { | 279 | { |
| 236 | const header_offset = try reserveVecSectionHeader(file); | 280 | const header_offset = try reserveVecSectionHeader(file); |
| 237 | const writer = file.writer(); | 281 | const writer = file.writer(); |
| | 282 | var count: u32 = 0; |
| 238 | for (self.funcs.items) |decl| { | 283 | for (self.funcs.items) |decl| { |
| | 284 | // Do not emit any code for extern functions |
| | 285 | if (decl.typed_value.most_recent.typed_value.val.tag() != .function) { |
| | 286 | std.debug.print("Skipping decl: {s}\n", .{decl.name}); |
| | 287 | continue; |
| | 288 | } |
| 239 | const fn_data = &decl.fn_link.wasm.?; | 289 | const fn_data = &decl.fn_link.wasm.?; |
| 240 | | 290 | |
| 241 | // Write the already generated code to the file, inserting | 291 | // Write the already generated code to the file, inserting |
| ... | @@ -247,18 +297,20 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -247,18 +297,20 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 247 | // Use a fixed width here to make calculating the code size | 297 | // Use a fixed width here to make calculating the code size |
| 248 | // in codegen.wasm.gen() simpler. | 298 | // in codegen.wasm.gen() simpler. |
| 249 | var buf: [5]u8 = undefined; | 299 | var buf: [5]u8 = undefined; |
| 250 | leb.writeUnsignedFixed(5, &buf, self.getFuncidx(idx_ref.decl).?); | 300 | std.debug.print("idx_ref: {s} - {d}\n", .{ idx_ref.decl.name, self.getFuncidx(idx_ref.decl).? }); |
| | 301 | leb.writeUnsignedFixed(5, &buf, self.getFuncidx(idx_ref.decl).? - 1); |
| 251 | try writer.writeAll(&buf); | 302 | try writer.writeAll(&buf); |
| 252 | } | 303 | } |
| 253 | | 304 | |
| 254 | try writer.writeAll(fn_data.code.items[current..]); | 305 | try writer.writeAll(fn_data.code.items[current..]); |
| | 306 | count += 1; |
| 255 | } | 307 | } |
| 256 | try writeVecSectionHeader( | 308 | try writeVecSectionHeader( |
| 257 | file, | 309 | file, |
| 258 | header_offset, | 310 | header_offset, |
| 259 | .code, | 311 | .code, |
| 260 | @intCast(u32, (try file.getPos()) - header_offset - header_size), | 312 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| 261 | @intCast(u32, self.funcs.items.len), | 313 | count, |
| 262 | ); | 314 | ); |
| 263 | } | 315 | } |
| 264 | } | 316 | } |