| ... | ... | @@ -85,8 +85,6 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { |
| 85 | 85 | const typed_value = decl.typed_value.most_recent.typed_value; |
| 86 | 86 | if (typed_value.ty.zigTypeTag() != .Fn) |
| 87 | 87 | return error.TODOImplementNonFnDeclsForWasm; |
| 88 | | if (typed_value.val.tag() == .extern_fn) |
| 89 | | return error.TODOImplementExternFnDeclsForWasm; |
| 90 | 88 | |
| 91 | 89 | if (decl.fn_link.wasm) |*fn_data| { |
| 92 | 90 | fn_data.functype.items.len = 0; |
| ... | ... | @@ -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 | 223 | // Function section |
| 188 | 224 | { |
| 189 | 225 | const header_offset = try reserveVecSectionHeader(file); |
| 190 | 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 | 236 | try writeVecSectionHeader( |
| 193 | 237 | file, |
| 194 | 238 | header_offset, |
| 195 | 239 | .function, |
| 196 | 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 | 258 | // Type of the export |
| 215 | 259 | try writer.writeByte(0x00); |
| 216 | 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 | 263 | else => return error.TODOImplementNonFnDeclsForWasm, |
| 220 | 264 | } |
| ... | ... | @@ -235,7 +279,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 235 | 279 | { |
| 236 | 280 | const header_offset = try reserveVecSectionHeader(file); |
| 237 | 281 | const writer = file.writer(); |
| 282 | var count: u32 = 0; |
| 238 | 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 | 289 | const fn_data = &decl.fn_link.wasm.?; |
| 240 | 290 | |
| 241 | 291 | // Write the already generated code to the file, inserting |
| ... | ... | @@ -247,18 +297,20 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 247 | 297 | // Use a fixed width here to make calculating the code size |
| 248 | 298 | // in codegen.wasm.gen() simpler. |
| 249 | 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 | 302 | try writer.writeAll(&buf); |
| 252 | 303 | } |
| 253 | 304 | |
| 254 | 305 | try writer.writeAll(fn_data.code.items[current..]); |
| 306 | count += 1; |
| 255 | 307 | } |
| 256 | 308 | try writeVecSectionHeader( |
| 257 | 309 | file, |
| 258 | 310 | header_offset, |
| 259 | 311 | .code, |
| 260 | 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 | } |