| ... | ... | @@ -180,6 +180,16 @@ pub const Segment = struct { |
| 180 | 180 | alignment: u32, |
| 181 | 181 | size: u32, |
| 182 | 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 | 195 | pub const Export = struct { |
| ... | ... | @@ -1673,6 +1683,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { |
| 1673 | 1683 | .alignment = atom.alignment, |
| 1674 | 1684 | .size = atom.size, |
| 1675 | 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 | 1722 | break :result index; |
| 1712 | 1723 | } else { |
| 1713 | 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 | 1729 | try wasm.segments.append(wasm.base.allocator, .{ |
| 1715 | 1730 | .alignment = atom.alignment, |
| 1716 | 1731 | .size = 0, |
| 1717 | 1732 | .offset = 0, |
| 1733 | .flags = flags, |
| 1718 | 1734 | }); |
| 1719 | 1735 | gop.value_ptr.* = index; |
| 1720 | 1736 | |
| ... | ... | @@ -2365,7 +2381,16 @@ pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, relocatable_index: u32 |
| 2365 | 2381 | const result = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(merge_segment)); |
| 2366 | 2382 | if (!result.found_existing) { |
| 2367 | 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 | 2394 | return index; |
| 2370 | 2395 | } else return result.value_ptr.*; |
| 2371 | 2396 | }, |
| ... | ... | @@ -2439,6 +2464,7 @@ fn appendDummySegment(wasm: *Wasm) !void { |
| 2439 | 2464 | .alignment = 1, |
| 2440 | 2465 | .size = 0, |
| 2441 | 2466 | .offset = 0, |
| 2467 | .flags = 0, |
| 2442 | 2468 | }); |
| 2443 | 2469 | } |
| 2444 | 2470 | |
| ... | ... | @@ -3147,6 +3173,19 @@ fn writeToFile( |
| 3147 | 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 | 3189 | // Code section |
| 3151 | 3190 | var code_section_size: u32 = 0; |
| 3152 | 3191 | if (wasm.code_section_index) |code_index| { |
| ... | ... | @@ -3197,7 +3236,7 @@ fn writeToFile( |
| 3197 | 3236 | } |
| 3198 | 3237 | |
| 3199 | 3238 | // Data section |
| 3200 | | if (wasm.data_segments.count() != 0) { |
| 3239 | if (data_segments_count != 0) { |
| 3201 | 3240 | const header_offset = try reserveVecSectionHeader(&binary_bytes); |
| 3202 | 3241 | |
| 3203 | 3242 | var it = wasm.data_segments.iterator(); |
| ... | ... | @@ -3212,10 +3251,15 @@ fn writeToFile( |
| 3212 | 3251 | segment_count += 1; |
| 3213 | 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) |
| 3216 | | try leb.writeULEB128(binary_writer, @as(u32, 0)); |
| 3254 | try leb.writeULEB128(binary_writer, segment.flags); |
| 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 | 3262 | // offset into data section |
| 3218 | | try emitInit(binary_writer, .{ .i32_const = @bitCast(i32, segment.offset) }); |
| 3219 | 3263 | try leb.writeULEB128(binary_writer, segment.size); |
| 3220 | 3264 | |
| 3221 | 3265 | // fill in the offset table and the data segments |