authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2020-08-16 02:21:20+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2020-08-18 01:01:13+02:00
log60fb50ee5a4a06687bf2f7b8774cc46f73a5b07e
treed09a9107f1a91eec76e91f7d0ca737a32881e399
parent97300896ed137f411c1eef04f8cde86abf4d32df
signaturelock-open Commit is signed but in an unrecognized format.

stage2/wasm: write exports on flush, cleanup

Exports now have a dirty flag and are rewritten on flush if this flag has been set. A couple other minor changes have been made based on Andrew's review.

5 files changed, 43 insertions(+), 36 deletions(-)

src-self-hosted/Module.zig+1-1
...@@ -974,7 +974,7 @@ pub fn update(self: *Module) !void {...@@ -974,7 +974,7 @@ pub fn update(self: *Module) !void {
974 }974 }
975975
976 // This is needed before reading the error flags.976 // This is needed before reading the error flags.
977 try self.bin_file.flush();977 try self.bin_file.flush(self);
978978
979 self.link_error_flags = self.bin_file.errorFlags();979 self.link_error_flags = self.bin_file.errorFlags();
980980
src-self-hosted/codegen/wasm.zig+1-1
...@@ -52,7 +52,7 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void {...@@ -52,7 +52,7 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void {
52 const writer = buf.writer();52 const writer = buf.writer();
5353
54 // Reserve space to write the size after generating the code54 // Reserve space to write the size after generating the code
55 try writer.writeAll(&([1]u8{undefined} ** 5));55 try buf.resize(5);
5656
57 // Write the size of the locals vec57 // Write the size of the locals vec
58 // TODO: implement locals58 // TODO: implement locals
src-self-hosted/link.zig+8-8
...@@ -168,16 +168,15 @@ pub const File = struct {...@@ -168,16 +168,15 @@ pub const File = struct {
168 }168 }
169 }169 }
170170
171 /// Commit pending changes and write headers.171 pub fn flush(base: *File, module: *Module) !void {
172 pub fn flush(base: *File) !void {
173 const tracy = trace(@src());172 const tracy = trace(@src());
174 defer tracy.end();173 defer tracy.end();
175174
176 try switch (base.tag) {175 try switch (base.tag) {
177 .elf => @fieldParentPtr(Elf, "base", base).flush(),176 .elf => @fieldParentPtr(Elf, "base", base).flush(module),
178 .macho => @fieldParentPtr(MachO, "base", base).flush(),177 .macho => @fieldParentPtr(MachO, "base", base).flush(module),
179 .c => @fieldParentPtr(C, "base", base).flush(),178 .c => @fieldParentPtr(C, "base", base).flush(module),
180 .wasm => @fieldParentPtr(Wasm, "base", base).flush(),179 .wasm => @fieldParentPtr(Wasm, "base", base).flush(module),
181 };180 };
182 }181 }
183182
...@@ -285,7 +284,7 @@ pub const File = struct {...@@ -285,7 +284,7 @@ pub const File = struct {
285 };284 };
286 }285 }
287286
288 pub fn flush(self: *File.C) !void {287 pub fn flush(self: *File.C, module: *Module) !void {
289 const writer = self.base.file.?.writer();288 const writer = self.base.file.?.writer();
290 try writer.writeAll(@embedFile("cbe.h"));289 try writer.writeAll(@embedFile("cbe.h"));
291 var includes = false;290 var includes = false;
...@@ -1038,7 +1037,8 @@ pub const File = struct {...@@ -1038,7 +1037,8 @@ pub const File = struct {
1038 pub const abbrev_pad1 = 5;1037 pub const abbrev_pad1 = 5;
1039 pub const abbrev_parameter = 6;1038 pub const abbrev_parameter = 6;
10401039
1041 pub fn flush(self: *Elf) !void {1040 /// Commit pending changes and write headers.
1041 pub fn flush(self: *Elf, module: *Module) !void {
1042 const target_endian = self.base.options.target.cpu.arch.endian();1042 const target_endian = self.base.options.target.cpu.arch.endian();
1043 const foreign_endian = target_endian != std.Target.current.cpu.arch.endian();1043 const foreign_endian = target_endian != std.Target.current.cpu.arch.endian();
1044 const ptr_width_bytes: u8 = self.ptrWidthBytes();1044 const ptr_width_bytes: u8 = self.ptrWidthBytes();
src-self-hosted/link/MachO.zig+1-1
...@@ -73,7 +73,7 @@ fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Mach...@@ -73,7 +73,7 @@ fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Mach
73 }73 }
74}74}
7575
76pub fn flush(self: *MachO) !void {}76pub fn flush(self: *MachO, module: *Module) !void {}
7777
78pub fn deinit(self: *MachO) void {}78pub fn deinit(self: *MachO) void {}
7979
src-self-hosted/link/Wasm.zig+32-25
...@@ -59,34 +59,37 @@ pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, option...@@ -59,34 +59,37 @@ pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, option
5959
60 try file.writeAll(&(spec.magic ++ spec.version));60 try file.writeAll(&(spec.magic ++ spec.version));
6161
62 wasm.base = .{
63 .tag = .wasm,
64 .options = options,
65 .file = file,
66 .allocator = allocator,
67 };
68
69 // TODO: this should vary depending on the section and be less arbitrary62 // TODO: this should vary depending on the section and be less arbitrary
70 const size = 1024;63 const size = 1024;
71 const offset = @sizeOf(@TypeOf(spec.magic ++ spec.version));64 const offset = @sizeOf(@TypeOf(spec.magic ++ spec.version));
7265
73 wasm.types = try Types.init(file, offset, size);66 wasm.* = .{
74 wasm.funcs = try Funcs.init(file, offset + size, size, offset + 3 * size, size);67 .base = .{
75 wasm.exports = try Exports.init(file, offset + 2 * size, size);68 .tag = .wasm,
76 try file.setEndPos(offset + 4 * size);69 .options = options,
7770 .file = file,
78 wasm.sections = [_]*Section{71 .allocator = allocator,
79 &wasm.types.typesec.section,72 },
80 &wasm.funcs.funcsec,73
81 &wasm.exports.exportsec,74 .types = try Types.init(file, offset, size),
82 &wasm.funcs.codesec.section,75 .funcs = try Funcs.init(file, offset + size, size, offset + 3 * size, size),
76 .exports = try Exports.init(file, offset + 2 * size, size),
77
78 // These must be ordered as they will appear in the output file
79 .sections = [_]*Section{
80 &wasm.types.typesec.section,
81 &wasm.funcs.funcsec,
82 &wasm.exports.exportsec,
83 &wasm.funcs.codesec.section,
84 },
83 };85 };
8486
87 try file.setEndPos(offset + 4 * size);
88
85 return &wasm.base;89 return &wasm.base;
86}90}
8791
88pub fn deinit(self: *Wasm) void {92pub fn deinit(self: *Wasm) void {
89 if (self.base.file) |f| f.close();
90 self.types.deinit();93 self.types.deinit();
91 self.funcs.deinit();94 self.funcs.deinit();
92}95}
...@@ -112,7 +115,8 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {...@@ -112,7 +115,8 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
112115
113 decl.fn_link.wasm = .{ .typeidx = typeidx, .funcidx = funcidx };116 decl.fn_link.wasm = .{ .typeidx = typeidx, .funcidx = funcidx };
114117
115 try self.exports.writeAll(module);118 // TODO: we should be more smart and set this only when needed
119 self.exports.dirty = true;
116}120}
117121
118pub fn updateDeclExports(122pub fn updateDeclExports(
...@@ -121,11 +125,7 @@ pub fn updateDeclExports(...@@ -121,11 +125,7 @@ pub fn updateDeclExports(
121 decl: *const Module.Decl,125 decl: *const Module.Decl,
122 exports: []const *Module.Export,126 exports: []const *Module.Export,
123) !void {127) !void {
124 // TODO: updateDeclExports() may currently be called before updateDecl,128 self.exports.dirty = true;
125 // presumably due to a bug. For now just rely on the following call
126 // being made in updateDecl().
127
128 //try self.exports.writeAll(module);
129}129}
130130
131pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {131pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
...@@ -138,7 +138,9 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {...@@ -138,7 +138,9 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
138 }138 }
139}139}
140140
141pub fn flush(self: *Wasm) !void {}141pub fn flush(self: *Wasm, module: *Module) !void {
142 if (self.exports.dirty) try self.exports.writeAll(module);
143}
142144
143/// This struct describes the location of a named section + custom section145/// This struct describes the location of a named section + custom section
144/// padding in the output file. This is all the data we need to allow for146/// padding in the output file. This is all the data we need to allow for
...@@ -373,11 +375,14 @@ const Exports = struct {...@@ -373,11 +375,14 @@ const Exports = struct {
373 /// Size in bytes of the contents of the section. Does not include375 /// Size in bytes of the contents of the section. Does not include
374 /// the "header" containing the section id and this value.376 /// the "header" containing the section id and this value.
375 contents_size: u32,377 contents_size: u32,
378 /// If this is true, then exports will be rewritten on flush()
379 dirty: bool,
376380
377 fn init(file: fs.File, offset: u64, initial_size: u64) !Exports {381 fn init(file: fs.File, offset: u64, initial_size: u64) !Exports {
378 return Exports{382 return Exports{
379 .exportsec = (try VecSection.init(spec.exports_id, file, offset, initial_size)).section,383 .exportsec = (try VecSection.init(spec.exports_id, file, offset, initial_size)).section,
380 .contents_size = 5,384 .contents_size = 5,
385 .dirty = false,
381 };386 };
382 }387 }
383388
...@@ -410,6 +415,8 @@ const Exports = struct {...@@ -410,6 +415,8 @@ const Exports = struct {
410415
411 for (module.decl_exports.entries.items) |entry|416 for (module.decl_exports.entries.items) |entry|
412 for (entry.value) |e| try writeExport(writer, e);417 for (entry.value) |e| try writeExport(writer, e);
418
419 self.dirty = false;
413 }420 }
414421
415 /// Return the total number of bytes an export will take.422 /// Return the total number of bytes an export will take.