| ... | @@ -180,6 +180,16 @@ pub const Segment = struct { | ... | @@ -180,6 +180,16 @@ pub const Segment = struct { |
| 180 | alignment: u32, | 180 | alignment: u32, |
| 181 | size: u32, | 181 | size: u32, |
| 182 | offset: u32, | 182 | offset: u32, |
| | 183 | flags: u32, |
| | 184 | |
| | 185 | pub const Flag = enum(u32) { |
| | 186 | WASM_DATA_SEGMENT_IS_PASSIVE = 0x01, |
| | 187 | WASM_DATA_SEGMENT_HAS_MEMINDEX = 0x02, |
| | 188 | }; |
| | 189 | |
| | 190 | pub fn isPassive(segment: Segment) bool { |
| | 191 | return segment.flags & @enumToInt(Flag.WASM_DATA_SEGMENT_IS_PASSIVE) != 0; |
| | 192 | } |
| 183 | }; | 193 | }; |
| 184 | | 194 | |
| 185 | pub const Export = struct { | 195 | pub const Export = struct { |
| ... | @@ -1673,6 +1683,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { | ... | @@ -1673,6 +1683,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { |
| 1673 | .alignment = atom.alignment, | 1683 | .alignment = atom.alignment, |
| 1674 | .size = atom.size, | 1684 | .size = atom.size, |
| 1675 | .offset = 0, | 1685 | .offset = 0, |
| | 1686 | .flags = 0, |
| 1676 | }); | 1687 | }); |
| 1677 | } | 1688 | } |
| 1678 | | 1689 | |
| ... | @@ -1711,10 +1722,15 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { | ... | @@ -1711,10 +1722,15 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { |
| 1711 | break :result index; | 1722 | break :result index; |
| 1712 | } else { | 1723 | } else { |
| 1713 | const index = @intCast(u32, wasm.segments.items.len); | 1724 | const index = @intCast(u32, wasm.segments.items.len); |
| | 1725 | var flags: u32 = 0; |
| | 1726 | if (wasm.base.options.shared_memory) { |
| | 1727 | flags |= @enumToInt(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE); |
| | 1728 | } |
| 1714 | try wasm.segments.append(wasm.base.allocator, .{ | 1729 | try wasm.segments.append(wasm.base.allocator, .{ |
| 1715 | .alignment = atom.alignment, | 1730 | .alignment = atom.alignment, |
| 1716 | .size = 0, | 1731 | .size = 0, |
| 1717 | .offset = 0, | 1732 | .offset = 0, |
| | 1733 | .flags = flags, |
| 1718 | }); | 1734 | }); |
| 1719 | gop.value_ptr.* = index; | 1735 | gop.value_ptr.* = index; |
| 1720 | | 1736 | |
| ... | @@ -2365,7 +2381,16 @@ pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, relocatable_index: u32 | ... | @@ -2365,7 +2381,16 @@ pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, relocatable_index: u32 |
| 2365 | const result = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(merge_segment)); | 2381 | const result = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(merge_segment)); |
| 2366 | if (!result.found_existing) { | 2382 | if (!result.found_existing) { |
| 2367 | result.value_ptr.* = index; | 2383 | result.value_ptr.* = index; |
| 2368 | try wasm.appendDummySegment(); | 2384 | var flags: u32 = 0; |
| | 2385 | if (wasm.base.options.shared_memory) { |
| | 2386 | flags |= @enumToInt(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE); |
| | 2387 | } |
| | 2388 | try wasm.segments.append(wasm.base.allocator, .{ |
| | 2389 | .alignment = 1, |
| | 2390 | .size = 0, |
| | 2391 | .offset = 0, |
| | 2392 | .flags = flags, |
| | 2393 | }); |
| 2369 | return index; | 2394 | return index; |
| 2370 | } else return result.value_ptr.*; | 2395 | } else return result.value_ptr.*; |
| 2371 | }, | 2396 | }, |
| ... | @@ -2439,6 +2464,7 @@ fn appendDummySegment(wasm: *Wasm) !void { | ... | @@ -2439,6 +2464,7 @@ fn appendDummySegment(wasm: *Wasm) !void { |
| 2439 | .alignment = 1, | 2464 | .alignment = 1, |
| 2440 | .size = 0, | 2465 | .size = 0, |
| 2441 | .offset = 0, | 2466 | .offset = 0, |
| | 2467 | .flags = 0, |
| 2442 | }); | 2468 | }); |
| 2443 | } | 2469 | } |
| 2444 | | 2470 | |
| ... | @@ -3147,6 +3173,19 @@ fn writeToFile( | ... | @@ -3147,6 +3173,19 @@ fn writeToFile( |
| 3147 | section_count += 1; | 3173 | section_count += 1; |
| 3148 | } | 3174 | } |
| 3149 | | 3175 | |
| | 3176 | // When the shared-memory option is enabled, we *must* emit the 'data count' section. |
| | 3177 | const data_segments_count = wasm.data_segments.count() - @boolToInt(wasm.data_segments.contains(".bss") and import_memory); |
| | 3178 | if (data_segments_count != 0 and wasm.base.options.shared_memory) { |
| | 3179 | const header_offset = try reserveVecSectionHeader(&binary_bytes); |
| | 3180 | try writeVecSectionHeader( |
| | 3181 | binary_bytes.items, |
| | 3182 | header_offset, |
| | 3183 | .data_count, |
| | 3184 | @intCast(u32, binary_bytes.items.len - header_offset - header_size), |
| | 3185 | @intCast(u32, data_segments_count), |
| | 3186 | ); |
| | 3187 | } |
| | 3188 | |
| 3150 | // Code section | 3189 | // Code section |
| 3151 | var code_section_size: u32 = 0; | 3190 | var code_section_size: u32 = 0; |
| 3152 | if (wasm.code_section_index) |code_index| { | 3191 | if (wasm.code_section_index) |code_index| { |
| ... | @@ -3197,7 +3236,7 @@ fn writeToFile( | ... | @@ -3197,7 +3236,7 @@ fn writeToFile( |
| 3197 | } | 3236 | } |
| 3198 | | 3237 | |
| 3199 | // Data section | 3238 | // Data section |
| 3200 | if (wasm.data_segments.count() != 0) { | 3239 | if (data_segments_count != 0) { |
| 3201 | const header_offset = try reserveVecSectionHeader(&binary_bytes); | 3240 | const header_offset = try reserveVecSectionHeader(&binary_bytes); |
| 3202 | | 3241 | |
| 3203 | var it = wasm.data_segments.iterator(); | 3242 | var it = wasm.data_segments.iterator(); |
| ... | @@ -3212,10 +3251,15 @@ fn writeToFile( | ... | @@ -3212,10 +3251,15 @@ fn writeToFile( |
| 3212 | segment_count += 1; | 3251 | segment_count += 1; |
| 3213 | var atom_index = wasm.atoms.get(segment_index).?; | 3252 | var atom_index = wasm.atoms.get(segment_index).?; |
| 3214 | | 3253 | |
| 3215 | // flag and index to memory section (currently, there can only be 1 memory section in wasm) | 3254 | try leb.writeULEB128(binary_writer, segment.flags); |
| 3216 | try leb.writeULEB128(binary_writer, @as(u32, 0)); | 3255 | if (segment.flags & @enumToInt(Wasm.Segment.Flag.WASM_DATA_SEGMENT_HAS_MEMINDEX) != 0) { |
| | 3256 | try leb.writeULEB128(binary_writer, @as(u32, 0)); // memory is always index 0 as we only have 1 memory entry |
| | 3257 | } |
| | 3258 | // when a segment is passive, it's initialized during runtime. |
| | 3259 | if (!segment.isPassive()) { |
| | 3260 | try emitInit(binary_writer, .{ .i32_const = @bitCast(i32, segment.offset) }); |
| | 3261 | } |
| 3217 | // offset into data section | 3262 | // offset into data section |
| 3218 | try emitInit(binary_writer, .{ .i32_const = @bitCast(i32, segment.offset) }); | | |
| 3219 | try leb.writeULEB128(binary_writer, segment.size); | 3263 | try leb.writeULEB128(binary_writer, segment.size); |
| 3220 | | 3264 | |
| 3221 | // fill in the offset table and the data segments | 3265 | // fill in the offset table and the data segments |