| ... | @@ -1132,6 +1132,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -1132,6 +1132,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1132 | | 1132 | |
| 1133 | const file = self.base.file.?; | 1133 | const file = self.base.file.?; |
| 1134 | const header_size = 5 + 1; | 1134 | const header_size = 5 + 1; |
| | 1135 | const is_obj = self.base.options.output_mode == .Obj; |
| 1135 | | 1136 | |
| 1136 | // No need to rewrite the magic/version header | 1137 | // No need to rewrite the magic/version header |
| 1137 | try file.setEndPos(@sizeOf(@TypeOf(wasm.magic ++ wasm.version))); | 1138 | try file.setEndPos(@sizeOf(@TypeOf(wasm.magic ++ wasm.version))); |
| ... | @@ -1443,7 +1444,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -1443,7 +1444,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1443 | } | 1444 | } |
| 1444 | | 1445 | |
| 1445 | // Custom section "name" which contains symbol names | 1446 | // Custom section "name" which contains symbol names |
| 1446 | { | 1447 | if (!is_obj) { |
| 1447 | const Name = struct { | 1448 | const Name = struct { |
| 1448 | index: u32, | 1449 | index: u32, |
| 1449 | name: []const u8, | 1450 | name: []const u8, |
| ... | @@ -1492,6 +1493,10 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -1492,6 +1493,10 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1492 | @intCast(u32, (try file.getPos()) - header_offset - header_size), | 1493 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| 1493 | ); | 1494 | ); |
| 1494 | } | 1495 | } |
| | 1496 | |
| | 1497 | if (is_obj) { |
| | 1498 | try self.emitLinkSection(file, arena); |
| | 1499 | } |
| 1495 | } | 1500 | } |
| 1496 | | 1501 | |
| 1497 | fn emitNameSubsection(self: *Wasm, section_id: std.wasm.NameSubsection, names: anytype, writer: anytype) !void { | 1502 | fn emitNameSubsection(self: *Wasm, section_id: std.wasm.NameSubsection, names: anytype, writer: anytype) !void { |
| ... | @@ -2030,6 +2035,87 @@ fn writeCustomSectionHeader(file: fs.File, offset: u64, size: u32) !void { | ... | @@ -2030,6 +2035,87 @@ fn writeCustomSectionHeader(file: fs.File, offset: u64, size: u32) !void { |
| 2030 | try file.pwriteAll(&buf, offset); | 2035 | try file.pwriteAll(&buf, offset); |
| 2031 | } | 2036 | } |
| 2032 | | 2037 | |
| | 2038 | fn emitLinkSection(self: *Wasm, file: fs.File, arena: Allocator) !void { |
| | 2039 | const offset = try reserveCustomSectionHeader(file); |
| | 2040 | const writer = file.writer(); |
| | 2041 | // emit "linking" custom section name |
| | 2042 | const section_name = "linking"; |
| | 2043 | try leb.writeULEB128(writer, section_name.len); |
| | 2044 | try writer.writeAll(section_name); |
| | 2045 | |
| | 2046 | // meta data version, which is currently '2' |
| | 2047 | try leb.writeULEB128(writer, @as(u32, 2)); |
| | 2048 | |
| | 2049 | // For each subsection type (found in types.Subsection) we can emit a section. |
| | 2050 | // Currently, we only support emitting segment info and the symbol table. |
| | 2051 | try self.emitSymbolTable(file, arena); |
| | 2052 | |
| | 2053 | const size = @intCast(u32, (try file.getPos()) - offset - 6); |
| | 2054 | try writeCustomSectionHeader(file, offset, size); |
| | 2055 | } |
| | 2056 | |
| | 2057 | fn emitSymbolTable(self: *Wasm, file: fs.File, arena: Allocator) !void { |
| | 2058 | // After emitting the subtype, we must emit the subsection's length |
| | 2059 | // so first write it to a temporary arraylist to calculate the length |
| | 2060 | // and then write all data at once. |
| | 2061 | var payload = std.ArrayList(u8).init(arena); |
| | 2062 | const writer = payload.writer(); |
| | 2063 | |
| | 2064 | try leb.writeULEB128(file.writer(), @enumToInt(types.SubsectionType.WASM_SYMBOL_TABLE)); |
| | 2065 | |
| | 2066 | var symbol_count: u32 = 0; |
| | 2067 | |
| | 2068 | var atom_it = self.atoms.valueIterator(); |
| | 2069 | while (atom_it.next()) |next_atom| { |
| | 2070 | var atom: ?*Atom = next_atom.*.getFirst(); |
| | 2071 | while (atom) |current_atom| { |
| | 2072 | const sym_loc: SymbolLoc = .{ .file = current_atom.file, .index = current_atom.sym_index }; |
| | 2073 | const symbol = sym_loc.getSymbol(self).*; |
| | 2074 | if (symbol.tag == .dead) continue; // Do not emit dead symbols |
| | 2075 | symbol_count += 1; |
| | 2076 | try leb.writeULEB128(writer, @enumToInt(symbol.tag)); |
| | 2077 | try leb.writeULEB128(writer, symbol.flags); |
| | 2078 | |
| | 2079 | switch (symbol.tag) { |
| | 2080 | .data => { |
| | 2081 | const name = mem.sliceTo(symbol.name, 0); |
| | 2082 | try leb.writeULEB128(writer, @intCast(u32, name.len)); |
| | 2083 | try writer.writeAll(name); |
| | 2084 | |
| | 2085 | if (symbol.isDefined()) { |
| | 2086 | try leb.writeULEB128(writer, symbol.index); |
| | 2087 | try leb.writeULEB128(writer, @as(u32, current_atom.offset)); |
| | 2088 | try leb.writeULEB128(writer, @as(u32, current_atom.size)); |
| | 2089 | } |
| | 2090 | }, |
| | 2091 | .section => { |
| | 2092 | try leb.writeULEB128(writer, symbol.index); |
| | 2093 | }, |
| | 2094 | else => { |
| | 2095 | try leb.writeULEB128(writer, symbol.index); |
| | 2096 | if (symbol.isDefined()) { |
| | 2097 | const name = mem.sliceTo(symbol.name, 0); |
| | 2098 | try leb.writeULEB128(writer, @intCast(u32, name.len)); |
| | 2099 | try writer.writeAll(name); |
| | 2100 | } |
| | 2101 | }, |
| | 2102 | } |
| | 2103 | atom = current_atom.next orelse break; |
| | 2104 | } |
| | 2105 | } |
| | 2106 | |
| | 2107 | var buf: [5]u8 = undefined; |
| | 2108 | leb.writeUnsignedFixed(5, &buf, symbol_count); |
| | 2109 | try payload.insertSlice(0, &buf); |
| | 2110 | try leb.writeULEB128(file.writer(), @intCast(u32, payload.items.len)); |
| | 2111 | |
| | 2112 | const iovec: std.os.iovec_const = .{ |
| | 2113 | .iov_base = payload.items.ptr, |
| | 2114 | .iov_len = payload.items.len, |
| | 2115 | }; |
| | 2116 | try file.writevAll(&.{iovec}); |
| | 2117 | } |
| | 2118 | |
| 2033 | /// Searches for an a matching function signature, when not found | 2119 | /// Searches for an a matching function signature, when not found |
| 2034 | /// a new entry will be made. The index of the existing/new signature will be returned. | 2120 | /// a new entry will be made. The index of the existing/new signature will be returned. |
| 2035 | pub fn putOrGetFuncType(self: *Wasm, func_type: wasm.Type) !u32 { | 2121 | pub fn putOrGetFuncType(self: *Wasm, func_type: wasm.Type) !u32 { |