| author | |
| committer | |
| log | e045b77d9981434af7e87512f94ecfe5b9dc376f |
| tree | 1e5f06f7b401e6fe6c148e4503a832eeb185e401 |
| parent | de5c25420b05aab47346a7cd4c8d9def85b9d0f9 |
15 files changed, 2177 insertions(+), 474 deletions(-)
src/Compilation.zig+4-4| ... | @@ -3675,11 +3675,11 @@ pub fn saveState(comp: *Compilation) !void { | ... | @@ -3675,11 +3675,11 @@ pub fn saveState(comp: *Compilation) !void { |
| 3675 | addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values())); | 3675 | addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values())); |
| 3676 | addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind))); | 3676 | addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind))); |
| 3677 | addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index))); | 3677 | addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index))); |
| 3678 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.tag))); | 3678 | addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.tag))); |
| 3679 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.offset))); | 3679 | addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.offset))); |
| 3680 | // TODO handle the union safety field | 3680 | // TODO handle the union safety field |
| 3681 | //addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.pointee))); | 3681 | //addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.pointee))); |
| 3682 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.addend))); | 3682 | addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.addend))); |
| 3683 | addBuf(&bufs, @ptrCast(wasm.uav_fixups.items)); | 3683 | addBuf(&bufs, @ptrCast(wasm.uav_fixups.items)); |
| 3684 | addBuf(&bufs, @ptrCast(wasm.nav_fixups.items)); | 3684 | addBuf(&bufs, @ptrCast(wasm.nav_fixups.items)); |
| 3685 | addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items)); | 3685 | addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items)); |
src/codegen.zig+1-30| ... | @@ -767,11 +767,9 @@ fn lowerNavRef( | ... | @@ -767,11 +767,9 @@ fn lowerNavRef( |
| 767 | offset: u64, | 767 | offset: u64, |
| 768 | ) (Error || std.Io.Writer.Error)!void { | 768 | ) (Error || std.Io.Writer.Error)!void { |
| 769 | const zcu = pt.zcu; | 769 | const zcu = pt.zcu; |
| 770 | const gpa = zcu.gpa; | ||
| 771 | const ip = &zcu.intern_pool; | 770 | const ip = &zcu.intern_pool; |
| 772 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; | 771 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; |
| 773 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); | 772 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 774 | const is_obj = lf.comp.config.output_mode == .Obj; | ||
| 775 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).resolved.?.type); | 773 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).resolved.?.type); |
| 776 | 774 | ||
| 777 | if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) { | 775 | if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) { |
| ... | @@ -786,34 +784,7 @@ fn lowerNavRef( | ... | @@ -786,34 +784,7 @@ fn lowerNavRef( |
| 786 | dev.check(link.File.Tag.wasm.devFeature()); | 784 | dev.check(link.File.Tag.wasm.devFeature()); |
| 787 | const wasm = lf.cast(.wasm).?; | 785 | const wasm = lf.cast(.wasm).?; |
| 788 | assert(reloc_parent == .none); | 786 | assert(reloc_parent == .none); |
| 789 | if (nav_ty.zigTypeTag(zcu) == .@"fn") { | 787 | try wasm.addNavReloc(w.end, nav_index, nav_ty, @intCast(offset)); |
| 790 | const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); | ||
| 791 | if (!gop.found_existing) gop.value_ptr.* = {}; | ||
| 792 | if (is_obj) { | ||
| 793 | @panic("TODO add out_reloc for this"); | ||
| 794 | } else { | ||
| 795 | try wasm.func_table_fixups.append(gpa, .{ | ||
| 796 | .table_index = @fromBackingInt(@intCast(gop.index)), | ||
| 797 | .offset = @intCast(w.end), | ||
| 798 | }); | ||
| 799 | } | ||
| 800 | } else { | ||
| 801 | if (is_obj) { | ||
| 802 | try wasm.out_relocs.append(gpa, .{ | ||
| 803 | .offset = @intCast(w.end), | ||
| 804 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, | ||
| 805 | .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64, | ||
| 806 | .addend = @intCast(offset), | ||
| 807 | }); | ||
| 808 | } else { | ||
| 809 | try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); | ||
| 810 | wasm.nav_fixups.appendAssumeCapacity(.{ | ||
| 811 | .navs_exe_index = try wasm.refNavExe(nav_index), | ||
| 812 | .offset = @intCast(w.end), | ||
| 813 | .addend = @intCast(offset), | ||
| 814 | }); | ||
| 815 | } | ||
| 816 | } | ||
| 817 | try w.splatByteAll(0, ptr_width_bytes); | 788 | try w.splatByteAll(0, ptr_width_bytes); |
| 818 | return; | 789 | return; |
| 819 | }, | 790 | }, |
src/codegen/wasm/CodeGen.zig+4-1| ... | @@ -4923,7 +4923,8 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro | ... | @@ -4923,7 +4923,8 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro |
| 4923 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; | 4923 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 4924 | const offset: u64 = prev_offset + ptr.byte_offset; | 4924 | const offset: u64 = prev_offset + ptr.byte_offset; |
| 4925 | return switch (ptr.base_addr) { | 4925 | return switch (ptr.base_addr) { |
| 4926 | .nav => |nav| return if (Type.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) | 4926 | .nav => |nav| return if (ip.getNav(nav).getExtern(ip) != null or |
| 4927 | Type.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) | ||
| 4927 | .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } } | 4928 | .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } } |
| 4928 | else | 4929 | else |
| 4929 | .{ .imm32 = @intCast(zcu.navAlignment(nav).forward(@as(u32, 0xaaaaaaaa))) }, | 4930 | .{ .imm32 = @intCast(zcu.navAlignment(nav).forward(@as(u32, 0xaaaaaaaa))) }, |
| ... | @@ -5607,6 +5608,8 @@ fn bitcastClass(cg: *CodeGen, ty: Type) BitcastClass { | ... | @@ -5607,6 +5608,8 @@ fn bitcastClass(cg: *CodeGen, ty: Type) BitcastClass { |
| 5607 | } | 5608 | } |
| 5608 | 5609 | ||
| 5609 | fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue { | 5610 | fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue { |
| 5611 | if (dest_ty.eql(src_ty)) return null; | ||
| 5612 | |||
| 5610 | const zcu = cg.pt.zcu; | 5613 | const zcu = cg.pt.zcu; |
| 5611 | const src_class = cg.bitcastClass(src_ty); | 5614 | const src_class = cg.bitcastClass(src_ty); |
| 5612 | const dest_class = cg.bitcastClass(dest_ty); | 5615 | const dest_class = cg.bitcastClass(dest_ty); |
src/codegen/wasm/Emit.zig+123-47| ... | @@ -21,7 +21,7 @@ pub const Error = error{ | ... | @@ -21,7 +21,7 @@ pub const Error = error{ |
| 21 | OutOfMemory, | 21 | OutOfMemory, |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | pub fn lowerToCode(emit: *Emit) Error!void { | 24 | pub fn lower(emit: *Emit) Error!void { |
| 25 | const mir = &emit.mir; | 25 | const mir = &emit.mir; |
| 26 | const code = emit.code; | 26 | const code = emit.code; |
| 27 | const wasm = emit.wasm; | 27 | const wasm = emit.wasm; |
| ... | @@ -31,6 +31,47 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -31,6 +31,47 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 31 | const target = &comp.root_mod.resolved_target.result; | 31 | const target = &comp.root_mod.resolved_target.result; |
| 32 | const is_wasm32 = target.cpu.arch == .wasm32; | 32 | const is_wasm32 = target.cpu.arch == .wasm32; |
| 33 | 33 | ||
| 34 | // Write the locals in the prologue of the function body. | ||
| 35 | try code.ensureUnusedCapacity(gpa, 5 + mir.locals.len * 6 + 38); | ||
| 36 | |||
| 37 | writeUleb128(code, @as(u32, @intCast(mir.locals.len))); | ||
| 38 | |||
| 39 | for (mir.locals) |local| { | ||
| 40 | writeUleb128(code, @as(u32, 1)); | ||
| 41 | code.appendAssumeCapacity(@backingInt(local)); | ||
| 42 | } | ||
| 43 | |||
| 44 | // Stack management section of function prologue. | ||
| 45 | const stack_alignment = mir.prologue.flags.stack_alignment; | ||
| 46 | if (stack_alignment.toByteUnits()) |align_bytes| { | ||
| 47 | // load stack pointer | ||
| 48 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_get)); | ||
| 49 | try appendStackPointerGlobalIndex(wasm, code, is_obj); | ||
| 50 | // store stack pointer so we can restore it when we return from the function | ||
| 51 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.local_tee)); | ||
| 52 | writeUleb128(code, mir.prologue.sp_local); | ||
| 53 | // get the total stack size | ||
| 54 | const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size)); | ||
| 55 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); | ||
| 56 | writeSleb128(code, aligned_stack); | ||
| 57 | // subtract it from the current stack pointer | ||
| 58 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_sub)); | ||
| 59 | // Get negative stack alignment | ||
| 60 | const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1; | ||
| 61 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); | ||
| 62 | writeSleb128(code, neg_stack_align); | ||
| 63 | // Bitwise-and the value to get the new stack pointer to ensure the | ||
| 64 | // pointers are aligned with the abi alignment. | ||
| 65 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_and)); | ||
| 66 | // The bottom will be used to calculate all stack pointer offsets. | ||
| 67 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.local_tee)); | ||
| 68 | writeUleb128(code, mir.prologue.bottom_stack_local); | ||
| 69 | // Store the current stack pointer value into the global stack pointer so other function calls will | ||
| 70 | // start from this value instead and not overwrite the current stack. | ||
| 71 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set)); | ||
| 72 | try appendStackPointerGlobalIndex(wasm, code, is_obj); | ||
| 73 | } | ||
| 74 | |||
| 34 | const tags = mir.instructions.items(.tag); | 75 | const tags = mir.instructions.items(.tag); |
| 35 | const datas = mir.instructions.items(.data); | 76 | const datas = mir.instructions.items(.data); |
| 36 | var inst: u32 = 0; | 77 | var inst: u32 = 0; |
| ... | @@ -78,14 +119,21 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -78,14 +119,21 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 78 | continue :loop tags[inst]; | 119 | continue :loop tags[inst]; |
| 79 | }, | 120 | }, |
| 80 | .func_ref => { | 121 | .func_ref => { |
| 81 | const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @fromBackingInt(@intCast( | 122 | try code.ensureUnusedCapacity(gpa, 11); |
| 82 | wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?, | 123 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| 83 | )); | 124 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 84 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); | ||
| 85 | if (is_obj) { | 125 | if (is_obj) { |
| 86 | @panic("TODO"); | 126 | try wasm.zcu_relocations.append(gpa, .{ |
| 127 | .offset = @intCast(code.items.len), | ||
| 128 | .pointee = .{ .function_nav = datas[inst].nav_index }, | ||
| 129 | .tag = if (is_wasm32) .table_index_sleb else .table_index_sleb64, | ||
| 130 | .addend = 0, | ||
| 131 | }); | ||
| 132 | appendSlebRelocPlaceholder(code, is_wasm32); | ||
| 87 | } else { | 133 | } else { |
| 88 | writeSleb128(code, 1 + @backingInt(indirect_func_idx)); | 134 | const function_index = Wasm.OutputFunctionIndex.fromIpNav(wasm, datas[inst].nav_index); |
| 135 | const table_index = wasm.flush_buffer.indirect_function_table.getIndex(function_index).? + 1; | ||
| 136 | writeSleb128(code, table_index); | ||
| 89 | } | 137 | } |
| 90 | inst += 1; | 138 | inst += 1; |
| 91 | continue :loop tags[inst]; | 139 | continue :loop tags[inst]; |
| ... | @@ -105,18 +153,17 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -105,18 +153,17 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 105 | continue :loop tags[inst]; | 153 | continue :loop tags[inst]; |
| 106 | }, | 154 | }, |
| 107 | .error_name_table_ref => { | 155 | .error_name_table_ref => { |
| 108 | wasm.error_name_table_ref_count += 1; | ||
| 109 | try code.ensureUnusedCapacity(gpa, 11); | 156 | try code.ensureUnusedCapacity(gpa, 11); |
| 110 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; | 157 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| 111 | code.appendAssumeCapacity(@backingInt(opcode)); | 158 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 112 | if (is_obj) { | 159 | if (is_obj) { |
| 113 | try wasm.out_relocs.append(gpa, .{ | 160 | try wasm.zcu_relocations.append(gpa, .{ |
| 114 | .offset = @intCast(code.items.len), | 161 | .offset = @intCast(code.items.len), |
| 115 | .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() }, | 162 | .pointee = .{ .data_resolution = .__zig_error_name_table }, |
| 116 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, | 163 | .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, |
| 117 | .addend = 0, | 164 | .addend = 0, |
| 118 | }); | 165 | }); |
| 119 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | 166 | appendSlebRelocPlaceholder(code, is_wasm32); |
| 120 | 167 | ||
| 121 | inst += 1; | 168 | inst += 1; |
| 122 | continue :loop tags[inst]; | 169 | continue :loop tags[inst]; |
| ... | @@ -164,13 +211,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -164,13 +211,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 164 | try code.ensureUnusedCapacity(gpa, 6); | 211 | try code.ensureUnusedCapacity(gpa, 6); |
| 165 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); | 212 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); |
| 166 | if (is_obj) { | 213 | if (is_obj) { |
| 167 | try wasm.out_relocs.append(gpa, .{ | 214 | try wasm.zcu_relocations.append(gpa, .{ |
| 168 | .offset = @intCast(code.items.len), | 215 | .offset = @intCast(code.items.len), |
| 169 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) }, | 216 | .pointee = .{ .function_nav = datas[inst].nav_index }, |
| 170 | .tag = .function_index_leb, | 217 | .tag = .function_index_leb, |
| 171 | .addend = 0, | 218 | .addend = 0, |
| 172 | }); | 219 | }); |
| 173 | code.appendNTimesAssumeCapacity(0, 5); | 220 | appendUlebRelocPlaceholder(code); |
| 174 | } else { | 221 | } else { |
| 175 | appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index)); | 222 | appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index)); |
| 176 | } | 223 | } |
| ... | @@ -191,13 +238,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -191,13 +238,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 191 | ).?; | 238 | ).?; |
| 192 | if (is_obj) { | 239 | if (is_obj) { |
| 193 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call_indirect)); | 240 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call_indirect)); |
| 194 | try wasm.out_relocs.append(gpa, .{ | 241 | try wasm.zcu_relocations.append(gpa, .{ |
| 195 | .offset = @intCast(code.items.len), | 242 | .offset = @intCast(code.items.len), |
| 196 | .pointee = .{ .type_index = func_ty_index }, | 243 | .pointee = .{ .type_index = func_ty_index }, |
| 197 | .tag = .type_index_leb, | 244 | .tag = .type_index_leb, |
| 198 | .addend = 0, | 245 | .addend = 0, |
| 199 | }); | 246 | }); |
| 200 | code.appendNTimesAssumeCapacity(0, 5); | 247 | appendUlebRelocPlaceholder(code); |
| 201 | } else { | 248 | } else { |
| 202 | const index: Wasm.Flush.FuncTypeIndex = @fromBackingInt(@intCast(wasm.flush_buffer.func_types.getIndex(func_ty_index) orelse { | 249 | const index: Wasm.Flush.FuncTypeIndex = @fromBackingInt(@intCast(wasm.flush_buffer.func_types.getIndex(func_ty_index) orelse { |
| 203 | // In this case we tried to call a function pointer for | 250 | // In this case we tried to call a function pointer for |
| ... | @@ -224,13 +271,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -224,13 +271,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 224 | try code.ensureUnusedCapacity(gpa, 6); | 271 | try code.ensureUnusedCapacity(gpa, 6); |
| 225 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); | 272 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); |
| 226 | if (is_obj) { | 273 | if (is_obj) { |
| 227 | try wasm.out_relocs.append(gpa, .{ | 274 | try wasm.zcu_relocations.append(gpa, .{ |
| 228 | .offset = @intCast(code.items.len), | 275 | .offset = @intCast(code.items.len), |
| 229 | .pointee = .{ .symbol_index = try wasm.tagTableIndexSymbolIndex(datas[inst].ip_index) }, | 276 | .pointee = .{ .tag_function = datas[inst].ip_index }, |
| 230 | .tag = .function_index_leb, | 277 | .tag = .function_index_leb, |
| 231 | .addend = 0, | 278 | .addend = 0, |
| 232 | }); | 279 | }); |
| 233 | code.appendNTimesAssumeCapacity(0, 5); | 280 | appendUlebRelocPlaceholder(code); |
| 234 | } else { | 281 | } else { |
| 235 | appendOutputFunctionIndex(code, .fromTagIndexType(wasm, datas[inst].ip_index)); | 282 | appendOutputFunctionIndex(code, .fromTagIndexType(wasm, datas[inst].ip_index)); |
| 236 | } | 283 | } |
| ... | @@ -244,14 +291,20 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -244,14 +291,20 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 244 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; | 291 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| 245 | code.appendAssumeCapacity(@backingInt(opcode)); | 292 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 246 | if (is_obj) { | 293 | if (is_obj) { |
| 247 | @panic("TODO"); | 294 | try wasm.zcu_relocations.append(gpa, .{ |
| 295 | .offset = @intCast(code.items.len), | ||
| 296 | .pointee = .{ .data_resolution = .__zig_tag_name_table }, | ||
| 297 | .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, | ||
| 298 | .addend = @intCast(wasm.tagIndexTableOffset(datas[inst].ip_index)), | ||
| 299 | }); | ||
| 300 | appendSlebRelocPlaceholder(code, is_wasm32); | ||
| 248 | } else { | 301 | } else { |
| 249 | const addr: u32 = wasm.tagIndexTableAddr(datas[inst].ip_index); | 302 | const addr: u32 = wasm.tagIndexTableAddr(datas[inst].ip_index); |
| 250 | writeSleb128(code, addr); | 303 | writeSleb128(code, addr); |
| 251 | |||
| 252 | inst += 1; | ||
| 253 | continue :loop tags[inst]; | ||
| 254 | } | 304 | } |
| 305 | |||
| 306 | inst += 1; | ||
| 307 | continue :loop tags[inst]; | ||
| 255 | }, | 308 | }, |
| 256 | 309 | ||
| 257 | .call_intrinsic => { | 310 | .call_intrinsic => { |
| ... | @@ -263,13 +316,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -263,13 +316,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 263 | try code.ensureUnusedCapacity(gpa, 6); | 316 | try code.ensureUnusedCapacity(gpa, 6); |
| 264 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); | 317 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); |
| 265 | if (is_obj) { | 318 | if (is_obj) { |
| 266 | try wasm.out_relocs.append(gpa, .{ | 319 | try wasm.zcu_relocations.append(gpa, .{ |
| 267 | .offset = @intCast(code.items.len), | 320 | .offset = @intCast(code.items.len), |
| 268 | .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) }, | 321 | .pointee = .{ .function_name = symbol_name }, |
| 269 | .tag = .function_index_leb, | 322 | .tag = .function_index_leb, |
| 270 | .addend = 0, | 323 | .addend = 0, |
| 271 | }); | 324 | }); |
| 272 | code.appendNTimesAssumeCapacity(0, 5); | 325 | appendUlebRelocPlaceholder(code); |
| 273 | } else { | 326 | } else { |
| 274 | appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name)); | 327 | appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name)); |
| 275 | } | 328 | } |
| ... | @@ -281,18 +334,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -281,18 +334,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 281 | .global_set_sp => { | 334 | .global_set_sp => { |
| 282 | try code.ensureUnusedCapacity(gpa, 6); | 335 | try code.ensureUnusedCapacity(gpa, 6); |
| 283 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set)); | 336 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set)); |
| 284 | if (is_obj) { | 337 | try appendStackPointerGlobalIndex(wasm, code, is_obj); |
| 285 | try wasm.out_relocs.append(gpa, .{ | ||
| 286 | .offset = @intCast(code.items.len), | ||
| 287 | .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() }, | ||
| 288 | .tag = .global_index_leb, | ||
| 289 | .addend = 0, | ||
| 290 | }); | ||
| 291 | code.appendNTimesAssumeCapacity(0, 5); | ||
| 292 | } else { | ||
| 293 | const sp_global: Wasm.GlobalIndex = .stack_pointer; | ||
| 294 | writeUleb128(code, @backingInt(sp_global)); | ||
| 295 | } | ||
| 296 | 338 | ||
| 297 | inst += 1; | 339 | inst += 1; |
| 298 | continue :loop tags[inst]; | 340 | continue :loop tags[inst]; |
| ... | @@ -960,13 +1002,13 @@ fn uavRefObj(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: | ... | @@ -960,13 +1002,13 @@ fn uavRefObj(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: |
| 960 | try code.ensureUnusedCapacity(gpa, 11); | 1002 | try code.ensureUnusedCapacity(gpa, 11); |
| 961 | code.appendAssumeCapacity(@backingInt(opcode)); | 1003 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 962 | 1004 | ||
| 963 | try wasm.out_relocs.append(gpa, .{ | 1005 | try wasm.zcu_relocations.append(gpa, .{ |
| 964 | .offset = @intCast(code.items.len), | 1006 | .offset = @intCast(code.items.len), |
| 965 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) }, | 1007 | .pointee = .{ .data_uav = value }, |
| 966 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, | 1008 | .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, |
| 967 | .addend = offset, | 1009 | .addend = offset, |
| 968 | }); | 1010 | }); |
| 969 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | 1011 | appendSlebRelocPlaceholder(code, is_wasm32); |
| 970 | } | 1012 | } |
| 971 | 1013 | ||
| 972 | fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void { | 1014 | fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void { |
| ... | @@ -995,13 +1037,13 @@ fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: | ... | @@ -995,13 +1037,13 @@ fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: |
| 995 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; | 1037 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| 996 | code.appendAssumeCapacity(@backingInt(opcode)); | 1038 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 997 | if (is_obj) { | 1039 | if (is_obj) { |
| 998 | try wasm.out_relocs.append(gpa, .{ | 1040 | try wasm.zcu_relocations.append(gpa, .{ |
| 999 | .offset = @intCast(code.items.len), | 1041 | .offset = @intCast(code.items.len), |
| 1000 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, | 1042 | .pointee = .{ .data_nav = data.nav_index }, |
| 1001 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, | 1043 | .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, |
| 1002 | .addend = data.offset, | 1044 | .addend = data.offset, |
| 1003 | }); | 1045 | }); |
| 1004 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | 1046 | appendSlebRelocPlaceholder(code, is_wasm32); |
| 1005 | } else { | 1047 | } else { |
| 1006 | const addr = wasm.navAddr(data.nav_index); | 1048 | const addr = wasm.navAddr(data.nav_index); |
| 1007 | writeSleb128(code, @as(u32, @intCast(@as(i64, addr) + data.offset))); | 1049 | writeSleb128(code, @as(u32, @intCast(@as(i64, addr) + data.offset))); |
| ... | @@ -1012,6 +1054,40 @@ fn appendOutputFunctionIndex(code: *ArrayList(u8), i: Wasm.OutputFunctionIndex) | ... | @@ -1012,6 +1054,40 @@ fn appendOutputFunctionIndex(code: *ArrayList(u8), i: Wasm.OutputFunctionIndex) |
| 1012 | writeUleb128(code, @backingInt(i)); | 1054 | writeUleb128(code, @backingInt(i)); |
| 1013 | } | 1055 | } |
| 1014 | 1056 | ||
| 1057 | fn appendStackPointerGlobalIndex( | ||
| 1058 | wasm: *Wasm, | ||
| 1059 | code: *ArrayList(u8), | ||
| 1060 | is_obj: bool, | ||
| 1061 | ) Error!void { | ||
| 1062 | if (is_obj) { | ||
| 1063 | try wasm.zcu_relocations.append(wasm.base.comp.gpa, .{ | ||
| 1064 | .offset = @intCast(code.items.len), | ||
| 1065 | .pointee = .stack_pointer, | ||
| 1066 | .tag = .global_index_leb, | ||
| 1067 | .addend = 0, | ||
| 1068 | }); | ||
| 1069 | appendUlebRelocPlaceholder(code); | ||
| 1070 | } else { | ||
| 1071 | const sp_global: Wasm.GlobalIndex = .stack_pointer; | ||
| 1072 | writeUleb128(code, @backingInt(sp_global)); | ||
| 1073 | } | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | fn appendUlebRelocPlaceholder(code: *ArrayList(u8)) void { | ||
| 1077 | code.appendSliceAssumeCapacity(&.{ 0x80, 0x80, 0x80, 0x80, 0x00 }); | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | fn appendSlebRelocPlaceholder(code: *ArrayList(u8), is_wasm32: bool) void { | ||
| 1081 | if (is_wasm32) { | ||
| 1082 | code.appendSliceAssumeCapacity(&.{ 0x80, 0x80, 0x80, 0x80, 0x00 }); | ||
| 1083 | } else { | ||
| 1084 | code.appendSliceAssumeCapacity(&.{ | ||
| 1085 | 0x80, 0x80, 0x80, 0x80, 0x80, | ||
| 1086 | 0x80, 0x80, 0x80, 0x80, 0x00, | ||
| 1087 | }); | ||
| 1088 | } | ||
| 1089 | } | ||
| 1090 | |||
| 1015 | fn writeUleb128(code: *ArrayList(u8), arg: anytype) void { | 1091 | fn writeUleb128(code: *ArrayList(u8), arg: anytype) void { |
| 1016 | var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); | 1092 | var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); |
| 1017 | w.writeUleb128(arg) catch unreachable; | 1093 | w.writeUleb128(arg) catch unreachable; |
src/codegen/wasm/Mir.zig+2-50| ... | @@ -114,7 +114,7 @@ pub const Inst = struct { | ... | @@ -114,7 +114,7 @@ pub const Inst = struct { |
| 114 | /// | 114 | /// |
| 115 | /// Uses `payload` pointing to a `NavRefOff`. | 115 | /// Uses `payload` pointing to a `NavRefOff`. |
| 116 | nav_ref_off, | 116 | nav_ref_off, |
| 117 | /// Lowers to an i32_const which is the index of the function in the | 117 | /// Lowers to an iNN_const which is the index of the function in the |
| 118 | /// table section. | 118 | /// table section. |
| 119 | /// | 119 | /// |
| 120 | /// Uses `nav_index`. | 120 | /// Uses `nav_index`. |
| ... | @@ -679,60 +679,12 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void { | ... | @@ -679,60 +679,12 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void { |
| 679 | } | 679 | } |
| 680 | 680 | ||
| 681 | pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayList(u8)) std.mem.Allocator.Error!void { | 681 | pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayList(u8)) std.mem.Allocator.Error!void { |
| 682 | const gpa = wasm.base.comp.gpa; | ||
| 683 | |||
| 684 | // Write the locals in the prologue of the function body. | ||
| 685 | try code.ensureUnusedCapacity(gpa, 5 + mir.locals.len * 6 + 38); | ||
| 686 | |||
| 687 | var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); | ||
| 688 | |||
| 689 | w.writeLeb128(@as(u32, @intCast(mir.locals.len))) catch unreachable; | ||
| 690 | |||
| 691 | for (mir.locals) |local| { | ||
| 692 | w.writeLeb128(@as(u32, 1)) catch unreachable; | ||
| 693 | w.writeByte(@backingInt(local)) catch unreachable; | ||
| 694 | } | ||
| 695 | |||
| 696 | // Stack management section of function prologue. | ||
| 697 | const stack_alignment = mir.prologue.flags.stack_alignment; | ||
| 698 | if (stack_alignment.toByteUnits()) |align_bytes| { | ||
| 699 | const sp_global: Wasm.GlobalIndex = .stack_pointer; | ||
| 700 | // load stack pointer | ||
| 701 | w.writeByte(@backingInt(std.wasm.Opcode.global_get)) catch unreachable; | ||
| 702 | w.writeUleb128(@backingInt(sp_global)) catch unreachable; | ||
| 703 | // store stack pointer so we can restore it when we return from the function | ||
| 704 | w.writeByte(@backingInt(std.wasm.Opcode.local_tee)) catch unreachable; | ||
| 705 | w.writeUleb128(mir.prologue.sp_local) catch unreachable; | ||
| 706 | // get the total stack size | ||
| 707 | const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size)); | ||
| 708 | w.writeByte(@backingInt(std.wasm.Opcode.i32_const)) catch unreachable; | ||
| 709 | w.writeSleb128(aligned_stack) catch unreachable; | ||
| 710 | // subtract it from the current stack pointer | ||
| 711 | w.writeByte(@backingInt(std.wasm.Opcode.i32_sub)) catch unreachable; | ||
| 712 | // Get negative stack alignment | ||
| 713 | const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1; | ||
| 714 | w.writeByte(@backingInt(std.wasm.Opcode.i32_const)) catch unreachable; | ||
| 715 | w.writeSleb128(neg_stack_align) catch unreachable; | ||
| 716 | // Bitwise-and the value to get the new stack pointer to ensure the | ||
| 717 | // pointers are aligned with the abi alignment. | ||
| 718 | w.writeByte(@backingInt(std.wasm.Opcode.i32_and)) catch unreachable; | ||
| 719 | // The bottom will be used to calculate all stack pointer offsets. | ||
| 720 | w.writeByte(@backingInt(std.wasm.Opcode.local_tee)) catch unreachable; | ||
| 721 | w.writeUleb128(mir.prologue.bottom_stack_local) catch unreachable; | ||
| 722 | // Store the current stack pointer value into the global stack pointer so other function calls will | ||
| 723 | // start from this value instead and not overwrite the current stack. | ||
| 724 | w.writeByte(@backingInt(std.wasm.Opcode.global_set)) catch unreachable; | ||
| 725 | w.writeUleb128(@backingInt(sp_global)) catch unreachable; | ||
| 726 | } | ||
| 727 | |||
| 728 | code.items.len += w.end; | ||
| 729 | |||
| 730 | var emit: Emit = .{ | 682 | var emit: Emit = .{ |
| 731 | .mir = mir.*, | 683 | .mir = mir.*, |
| 732 | .wasm = wasm, | 684 | .wasm = wasm, |
| 733 | .code = code, | 685 | .code = code, |
| 734 | }; | 686 | }; |
| 735 | try emit.lowerToCode(); | 687 | try emit.lower(); |
| 736 | } | 688 | } |
| 737 | 689 | ||
| 738 | pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data: T, end: usize } { | 690 | pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data: T, end: usize } { |
src/link/Wasm.zig+927-189| ... | @@ -133,25 +133,21 @@ object_total_sections: u32 = 0, | ... | @@ -133,25 +133,21 @@ object_total_sections: u32 = 0, |
| 133 | /// All comdat symbols from all objects concatenated. | 133 | /// All comdat symbols from all objects concatenated. |
| 134 | object_comdat_symbols: std.MultiArrayList(Comdat.Symbol) = .empty, | 134 | object_comdat_symbols: std.MultiArrayList(Comdat.Symbol) = .empty, |
| 135 | 135 | ||
| 136 | /// Relocations to be emitted into an object file. Remains empty when not | 136 | /// Relocations produced by Zig code and data lowering. These retain semantic |
| 137 | /// emitting an object file. | 137 | /// targets until `flush`, where final output indexes are known. |
| 138 | out_relocs: std.MultiArrayList(OutReloc) = .empty, | 138 | zcu_relocations: std.MultiArrayList(ZcuRelocation) = .empty, |
| 139 | /// List of locations within `string_bytes` that must be patched with the virtual | 139 | /// List of locations within `string_bytes` that must be patched with the virtual |
| 140 | /// memory address of a Uav during `flush`. | 140 | /// memory address of a Uav during `flush`. |
| 141 | /// When emitting an object file, `out_relocs` is used instead. | 141 | /// When emitting an object file, `zcu_relocations` is used instead. |
| 142 | uav_fixups: std.ArrayList(UavFixup) = .empty, | 142 | uav_fixups: std.ArrayList(UavFixup) = .empty, |
| 143 | /// List of locations within `string_bytes` that must be patched with the virtual | 143 | /// List of locations within `string_bytes` that must be patched with the virtual |
| 144 | /// memory address of a Nav during `flush`. | 144 | /// memory address of a Nav during `flush`. |
| 145 | /// When emitting an object file, `out_relocs` is used instead. | 145 | /// When emitting an object file, `zcu_relocations` is used instead. |
| 146 | /// No functions here only global variables. | 146 | /// No functions here only global variables. |
| 147 | nav_fixups: std.ArrayList(NavFixup) = .empty, | 147 | nav_fixups: std.ArrayList(NavFixup) = .empty, |
| 148 | /// When a nav reference is a function pointer, this tracks the required function | 148 | /// When a nav reference is a function pointer, this tracks the required function |
| 149 | /// table entry index that needs to overwrite the code in the final output. | 149 | /// table entry index that needs to overwrite the code in the final output. |
| 150 | func_table_fixups: std.ArrayList(FuncTableFixup) = .empty, | 150 | func_table_fixups: std.ArrayList(FuncTableFixup) = .empty, |
| 151 | /// Symbols to be emitted into an object file. Remains empty when not emitting | ||
| 152 | /// an object file. | ||
| 153 | symbol_table: std.array_hash_map.Auto(String, void) = .empty, | ||
| 154 | |||
| 155 | /// When importing objects from the host environment, a name must be supplied. | 151 | /// When importing objects from the host environment, a name must be supplied. |
| 156 | /// LLVM uses "env" by default when none is given. | 152 | /// LLVM uses "env" by default when none is given. |
| 157 | /// This value is passed to object files since wasm tooling conventions provides | 153 | /// This value is passed to object files since wasm tooling conventions provides |
| ... | @@ -244,7 +240,9 @@ function_imports: std.array_hash_map.Auto(String, FunctionImportId) = .empty, | ... | @@ -244,7 +240,9 @@ function_imports: std.array_hash_map.Auto(String, FunctionImportId) = .empty, |
| 244 | /// remove elements from the table, and the remainder are either undefined | 240 | /// remove elements from the table, and the remainder are either undefined |
| 245 | /// symbol errors, or symbol table entries depending on the output mode. | 241 | /// symbol errors, or symbol table entries depending on the output mode. |
| 246 | data_imports: std.array_hash_map.Auto(String, DataImportId) = .empty, | 242 | data_imports: std.array_hash_map.Auto(String, DataImportId) = .empty, |
| 247 | /// Set of data symbols that will appear in the final binary. Used to populate | 243 | /// Set of data symbols that will appear in the final binary when outputting an object file. |
| 244 | datas: std.array_hash_map.Auto(ObjectDataImport.Resolution, void) = .empty, | ||
| 245 | /// Set of data segment symbols that will appear in the final binary. Used to populate | ||
| 248 | /// `Flush.data_segments` before sorting. | 246 | /// `Flush.data_segments` before sorting. |
| 249 | data_segments: std.array_hash_map.Auto(DataSegmentId, void) = .empty, | 247 | data_segments: std.array_hash_map.Auto(DataSegmentId, void) = .empty, |
| 250 | 248 | ||
| ... | @@ -302,11 +300,6 @@ pub const TagNameOff = extern struct { | ... | @@ -302,11 +300,6 @@ pub const TagNameOff = extern struct { |
| 302 | len: u32, | 300 | len: u32, |
| 303 | }; | 301 | }; |
| 304 | 302 | ||
| 305 | /// Index into `Wasm.zcu_indirect_function_set`. | ||
| 306 | pub const ZcuIndirectFunctionSetIndex = enum(u32) { | ||
| 307 | _, | ||
| 308 | }; | ||
| 309 | |||
| 310 | pub const UavFixup = extern struct { | 303 | pub const UavFixup = extern struct { |
| 311 | uavs_exe_index: UavsExeIndex, | 304 | uavs_exe_index: UavsExeIndex, |
| 312 | /// Index into `string_bytes`. | 305 | /// Index into `string_bytes`. |
| ... | @@ -315,14 +308,14 @@ pub const UavFixup = extern struct { | ... | @@ -315,14 +308,14 @@ pub const UavFixup = extern struct { |
| 315 | }; | 308 | }; |
| 316 | 309 | ||
| 317 | pub const NavFixup = extern struct { | 310 | pub const NavFixup = extern struct { |
| 318 | navs_exe_index: NavsExeIndex, | 311 | nav_index: InternPool.Nav.Index, |
| 319 | /// Index into `string_bytes`. | 312 | /// Index into `string_bytes`. |
| 320 | offset: u32, | 313 | offset: u32, |
| 321 | addend: u32, | 314 | addend: u32, |
| 322 | }; | 315 | }; |
| 323 | 316 | ||
| 324 | pub const FuncTableFixup = extern struct { | 317 | pub const FuncTableFixup = extern struct { |
| 325 | table_index: ZcuIndirectFunctionSetIndex, | 318 | nav_index: InternPool.Nav.Index, |
| 326 | /// Index into `string_bytes`. | 319 | /// Index into `string_bytes`. |
| 327 | offset: u32, | 320 | offset: u32, |
| 328 | }; | 321 | }; |
| ... | @@ -355,7 +348,9 @@ pub const FunctionIndex = enum(u32) { | ... | @@ -355,7 +348,9 @@ pub const FunctionIndex = enum(u32) { |
| 355 | 348 | ||
| 356 | pub fn fromSymbolName(wasm: *const Wasm, name: String) ?FunctionIndex { | 349 | pub fn fromSymbolName(wasm: *const Wasm, name: String) ?FunctionIndex { |
| 357 | if (wasm.object_function_imports.getPtr(name)) |import| { | 350 | if (wasm.object_function_imports.getPtr(name)) |import| { |
| 358 | return fromResolution(wasm, import.resolution); | 351 | if (import.resolution != .unresolved) { |
| 352 | return fromResolution(wasm, import.resolution); | ||
| 353 | } | ||
| 359 | } | 354 | } |
| 360 | if (wasm.function_exports.get(name)) |index| return index; | 355 | if (wasm.function_exports.get(name)) |index| return index; |
| 361 | if (wasm.hidden_function_exports.get(name)) |index| return index; | 356 | if (wasm.hidden_function_exports.get(name)) |index| return index; |
| ... | @@ -374,7 +369,8 @@ pub const GlobalExport = extern struct { | ... | @@ -374,7 +369,8 @@ pub const GlobalExport = extern struct { |
| 374 | }; | 369 | }; |
| 375 | 370 | ||
| 376 | /// 0. Index into `Flush.function_imports` | 371 | /// 0. Index into `Flush.function_imports` |
| 377 | /// 1. Index into `functions`. | 372 | /// 1. Index into `Flush.intrinsic_function_imports` |
| 373 | /// 2. Index into `functions`. | ||
| 378 | /// | 374 | /// |
| 379 | /// Note that function_imports indexes are subject to swap removals during | 375 | /// Note that function_imports indexes are subject to swap removals during |
| 380 | /// `flush`. | 376 | /// `flush`. |
| ... | @@ -386,7 +382,11 @@ pub const OutputFunctionIndex = enum(u32) { | ... | @@ -386,7 +382,11 @@ pub const OutputFunctionIndex = enum(u32) { |
| 386 | } | 382 | } |
| 387 | 383 | ||
| 388 | pub fn fromFunctionIndex(wasm: *const Wasm, index: FunctionIndex) OutputFunctionIndex { | 384 | pub fn fromFunctionIndex(wasm: *const Wasm, index: FunctionIndex) OutputFunctionIndex { |
| 389 | return @fromBackingInt(@intCast(wasm.flush_buffer.function_imports.entries.len + @backingInt(index))); | 385 | return @fromBackingInt(@intCast( |
| 386 | wasm.flush_buffer.function_imports.entries.len + | ||
| 387 | wasm.flush_buffer.intrinsic_function_imports.entries.len + | ||
| 388 | @backingInt(index), | ||
| 389 | )); | ||
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | pub fn fromObjectFunction(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex { | 392 | pub fn fromObjectFunction(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex { |
| ... | @@ -429,6 +429,9 @@ pub const OutputFunctionIndex = enum(u32) { | ... | @@ -429,6 +429,9 @@ pub const OutputFunctionIndex = enum(u32) { |
| 429 | 429 | ||
| 430 | pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex { | 430 | pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex { |
| 431 | if (wasm.flush_buffer.function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); | 431 | if (wasm.flush_buffer.function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); |
| 432 | if (wasm.flush_buffer.intrinsic_function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast( | ||
| 433 | wasm.flush_buffer.function_imports.entries.len + i, | ||
| 434 | )); | ||
| 432 | return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name) orelse { | 435 | return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name) orelse { |
| 433 | if (std.debug.runtime_safety) { | 436 | if (std.debug.runtime_safety) { |
| 434 | std.debug.panic("function index for symbol not found: {s}", .{name.slice(wasm)}); | 437 | std.debug.panic("function index for symbol not found: {s}", .{name.slice(wasm)}); |
| ... | @@ -437,6 +440,56 @@ pub const OutputFunctionIndex = enum(u32) { | ... | @@ -437,6 +440,56 @@ pub const OutputFunctionIndex = enum(u32) { |
| 437 | } | 440 | } |
| 438 | }; | 441 | }; |
| 439 | 442 | ||
| 443 | // Order | ||
| 444 | // 0. Flush.data_imports | ||
| 445 | // 1. Wasm.datas | ||
| 446 | pub const OutputDataIndex = enum(u32) { | ||
| 447 | _, | ||
| 448 | |||
| 449 | pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputDataIndex { | ||
| 450 | if (wasm.flush_buffer.data_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); | ||
| 451 | if (wasm.object_data_imports.getPtr(name)) |import| { | ||
| 452 | if (import.resolution != .unresolved) return fromResolution(wasm, import.resolution).?; | ||
| 453 | } | ||
| 454 | if (wasm.flush_buffer.data_exports.get(name)) |symbol| return fromResolution(wasm, symbol.resolution).?; | ||
| 455 | if (std.debug.runtime_safety) { | ||
| 456 | std.debug.panic("data index for symbol not found: {s}", .{name.slice(wasm)}); | ||
| 457 | } else unreachable; | ||
| 458 | } | ||
| 459 | |||
| 460 | pub fn fromObjectData(wasm: *const Wasm, index: ObjectData.Index) OutputDataIndex { | ||
| 461 | return fromResolution(wasm, .fromObjectDataIndex(wasm, index)).?; | ||
| 462 | } | ||
| 463 | |||
| 464 | pub fn fromResolution(wasm: *const Wasm, resolution: ObjectDataImport.Resolution) ?OutputDataIndex { | ||
| 465 | const i = wasm.datas.getIndex(resolution) orelse return null; | ||
| 466 | return @fromBackingInt(@intCast(wasm.flush_buffer.data_imports.entries.len + i)); | ||
| 467 | } | ||
| 468 | |||
| 469 | pub fn fromUav(wasm: *const Wasm, ip_index: InternPool.Index) OutputDataIndex { | ||
| 470 | const comp = wasm.base.comp; | ||
| 471 | const resolution: ObjectDataImport.Resolution = if (comp.config.output_mode == .Obj) | ||
| 472 | .pack(wasm, .{ .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)) }) | ||
| 473 | else | ||
| 474 | .pack(wasm, .{ .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)) }); | ||
| 475 | return fromResolution(wasm, resolution).?; | ||
| 476 | } | ||
| 477 | |||
| 478 | pub fn fromNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) OutputDataIndex { | ||
| 479 | const zcu = wasm.base.comp.zcu.?; | ||
| 480 | const ip = &zcu.intern_pool; | ||
| 481 | const nav = ip.getNav(nav_index); | ||
| 482 | if (nav.getExtern(ip)) |ext| { | ||
| 483 | return fromSymbolName(wasm, wasm.getExistingString(ext.name.toSlice(ip)).?); | ||
| 484 | } | ||
| 485 | const resolution: ObjectDataImport.Resolution = if (wasm.base.comp.config.output_mode == .Obj) | ||
| 486 | .pack(wasm, .{ .nav_obj = @fromBackingInt(@intCast(wasm.navs_obj.getIndex(nav_index).?)) }) | ||
| 487 | else | ||
| 488 | .pack(wasm, .{ .nav_exe = @fromBackingInt(@intCast(wasm.navs_exe.getIndex(nav_index).?)) }); | ||
| 489 | return fromResolution(wasm, resolution).?; | ||
| 490 | } | ||
| 491 | }; | ||
| 492 | |||
| 440 | /// Index into `Wasm.globals`. | 493 | /// Index into `Wasm.globals`. |
| 441 | pub const GlobalIndex = enum(u32) { | 494 | pub const GlobalIndex = enum(u32) { |
| 442 | _, | 495 | _, |
| ... | @@ -452,17 +505,17 @@ pub const GlobalIndex = enum(u32) { | ... | @@ -452,17 +505,17 @@ pub const GlobalIndex = enum(u32) { |
| 452 | return .stack_pointer; | 505 | return .stack_pointer; |
| 453 | } | 506 | } |
| 454 | 507 | ||
| 455 | pub fn ptr(index: GlobalIndex, f: *const Flush) *Wasm.GlobalImport.Resolution { | 508 | pub fn fromResolution(wasm: *const Wasm, resolution: GlobalImport.Resolution) ?GlobalIndex { |
| 456 | return &f.globals.items[@backingInt(index)]; | 509 | const i = wasm.globals.getIndex(resolution) orelse return null; |
| 510 | return @fromBackingInt(@intCast(wasm.flush_buffer.global_imports.entries.len + i)); | ||
| 457 | } | 511 | } |
| 458 | 512 | ||
| 459 | pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) ?GlobalIndex { | 513 | pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) ?GlobalIndex { |
| 460 | const i = wasm.globals.getIndex(.fromIpNav(wasm, nav_index)) orelse return null; | 514 | return fromResolution(wasm, .fromIpNav(wasm, nav_index)); |
| 461 | return @fromBackingInt(@intCast(i)); | ||
| 462 | } | 515 | } |
| 463 | 516 | ||
| 464 | pub fn fromObjectGlobal(wasm: *const Wasm, i: ObjectGlobalIndex) GlobalIndex { | 517 | pub fn fromObjectGlobal(wasm: *const Wasm, i: ObjectGlobalIndex) GlobalIndex { |
| 465 | return @fromBackingInt(@intCast(wasm.globals.getIndex(.fromObjectGlobal(wasm, i)).?)); | 518 | return fromResolution(wasm, .fromObjectGlobal(wasm, i)).?; |
| 466 | } | 519 | } |
| 467 | 520 | ||
| 468 | pub fn fromObjectGlobalHandlingWeak(wasm: *const Wasm, index: ObjectGlobalIndex) GlobalIndex { | 521 | pub fn fromObjectGlobalHandlingWeak(wasm: *const Wasm, index: ObjectGlobalIndex) GlobalIndex { |
| ... | @@ -474,8 +527,9 @@ pub const GlobalIndex = enum(u32) { | ... | @@ -474,8 +527,9 @@ pub const GlobalIndex = enum(u32) { |
| 474 | } | 527 | } |
| 475 | 528 | ||
| 476 | pub fn fromSymbolName(wasm: *const Wasm, name: String) GlobalIndex { | 529 | pub fn fromSymbolName(wasm: *const Wasm, name: String) GlobalIndex { |
| 530 | if (wasm.flush_buffer.global_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); | ||
| 477 | const import = wasm.object_global_imports.getPtr(name).?; | 531 | const import = wasm.object_global_imports.getPtr(name).?; |
| 478 | return @fromBackingInt(@intCast(wasm.globals.getIndex(import.resolution).?)); | 532 | return fromResolution(wasm, import.resolution).?; |
| 479 | } | 533 | } |
| 480 | }; | 534 | }; |
| 481 | 535 | ||
| ... | @@ -483,10 +537,6 @@ pub const GlobalIndex = enum(u32) { | ... | @@ -483,10 +537,6 @@ pub const GlobalIndex = enum(u32) { |
| 483 | pub const TableIndex = enum(u32) { | 537 | pub const TableIndex = enum(u32) { |
| 484 | _, | 538 | _, |
| 485 | 539 | ||
| 486 | pub fn ptr(index: TableIndex, f: *const Flush) *Wasm.TableImport.Resolution { | ||
| 487 | return &f.tables.items[@backingInt(index)]; | ||
| 488 | } | ||
| 489 | |||
| 490 | pub fn fromObjectTable(wasm: *const Wasm, i: ObjectTableIndex) TableIndex { | 540 | pub fn fromObjectTable(wasm: *const Wasm, i: ObjectTableIndex) TableIndex { |
| 491 | return @fromBackingInt(@intCast(wasm.tables.getIndex(.fromObjectTable(i)).?)); | 541 | return @fromBackingInt(@intCast(wasm.tables.getIndex(.fromObjectTable(i)).?)); |
| 492 | } | 542 | } |
| ... | @@ -668,9 +718,10 @@ pub const SymbolFlags = packed struct(u32) { | ... | @@ -668,9 +718,10 @@ pub const SymbolFlags = packed struct(u32) { |
| 668 | flags.ref_type = .funcref; | 718 | flags.ref_type = .funcref; |
| 669 | } | 719 | } |
| 670 | 720 | ||
| 671 | pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool) bool { | 721 | pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool, is_obj: bool) bool { |
| 672 | return flags.exported or | 722 | return flags.exported or |
| 673 | (is_dynamic and !flags.visibility_hidden) or | 723 | (is_dynamic and !flags.visibility_hidden) or |
| 724 | (is_obj and flags.binding != .local) or | ||
| 674 | (flags.no_strip and flags.must_link); | 725 | (flags.no_strip and flags.must_link); |
| 675 | } | 726 | } |
| 676 | 727 | ||
| ... | @@ -696,8 +747,8 @@ pub const SymbolFlags = packed struct(u32) { | ... | @@ -696,8 +747,8 @@ pub const SymbolFlags = packed struct(u32) { |
| 696 | /// Masks off the Zig-specific stuff. | 747 | /// Masks off the Zig-specific stuff. |
| 697 | pub fn toAbiInteger(flags: SymbolFlags) u32 { | 748 | pub fn toAbiInteger(flags: SymbolFlags) u32 { |
| 698 | var copy = flags; | 749 | var copy = flags; |
| 699 | copy.initZigSpecific(false, false); | 750 | copy.initZigSpecific(false, flags.no_strip); |
| 700 | return @bitCast(copy); | 751 | return @backingInt(copy); |
| 701 | } | 752 | } |
| 702 | }; | 753 | }; |
| 703 | 754 | ||
| ... | @@ -812,7 +863,7 @@ pub const UavsExeIndex = enum(u32) { | ... | @@ -812,7 +863,7 @@ pub const UavsExeIndex = enum(u32) { |
| 812 | /// Used when emitting a relocatable object. | 863 | /// Used when emitting a relocatable object. |
| 813 | pub const ZcuDataObj = extern struct { | 864 | pub const ZcuDataObj = extern struct { |
| 814 | code: DataPayload, | 865 | code: DataPayload, |
| 815 | relocs: OutReloc.Slice, | 866 | relocs: ZcuRelocation.Slice, |
| 816 | }; | 867 | }; |
| 817 | 868 | ||
| 818 | /// Used when not emitting a relocatable object. | 869 | /// Used when not emitting a relocatable object. |
| ... | @@ -855,7 +906,9 @@ const ZcuDataStarts = struct { | ... | @@ -855,7 +906,9 @@ const ZcuDataStarts = struct { |
| 855 | var uavs_i = zds.uavs_i; | 906 | var uavs_i = zds.uavs_i; |
| 856 | while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) { | 907 | while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) { |
| 857 | // Call to `lowerZcuData` here possibly creates more entries in these tables. | 908 | // Call to `lowerZcuData` here possibly creates more entries in these tables. |
| 858 | wasm.uavs_obj.values()[uavs_i] = try lowerZcuData(wasm, pt, wasm.uavs_obj.keys()[uavs_i]); | 909 | const uav = wasm.uavs_obj.keys()[uavs_i]; |
| 910 | const zcu_data = try lowerZcuData(wasm, pt, uav); | ||
| 911 | wasm.uavs_obj.values()[uavs_i] = zcu_data; | ||
| 859 | } | 912 | } |
| 860 | } | 913 | } |
| 861 | 914 | ||
| ... | @@ -906,6 +959,51 @@ pub const ZcuFunc = union { | ... | @@ -906,6 +959,51 @@ pub const ZcuFunc = union { |
| 906 | return &wasm.zcu_funcs.values()[@backingInt(i)]; | 959 | return &wasm.zcu_funcs.values()[@backingInt(i)]; |
| 907 | } | 960 | } |
| 908 | 961 | ||
| 962 | pub fn flags(i: @This(), wasm: *const Wasm) SymbolFlags { | ||
| 963 | const zcu = wasm.base.comp.zcu.?; | ||
| 964 | const ip = &zcu.intern_pool; | ||
| 965 | const ip_index = i.key(wasm).*; | ||
| 966 | switch (ip.indexToKey(ip_index)) { | ||
| 967 | .func => |func| { | ||
| 968 | const nav = ip.getNav(func.owner_nav); | ||
| 969 | if (nav.getExtern(ip)) |ext| { | ||
| 970 | const name_slice = ext.name.toSlice(ip); | ||
| 971 | const name_string = wasm.getExistingString(name_slice).?; | ||
| 972 | return .{ | ||
| 973 | .binding = switch (ext.linkage) { | ||
| 974 | .internal => .local, | ||
| 975 | .strong => .strong, | ||
| 976 | .weak => .weak, | ||
| 977 | .link_once => @panic("TODO: COMDAT"), | ||
| 978 | }, | ||
| 979 | .visibility_hidden = switch (ext.visibility) { | ||
| 980 | .default => false, | ||
| 981 | .hidden => true, | ||
| 982 | .protected => false, | ||
| 983 | }, | ||
| 984 | .undefined = false, | ||
| 985 | .exported = wasm.missing_exports.contains(name_string), | ||
| 986 | .explicit_name = false, | ||
| 987 | .no_strip = false, | ||
| 988 | .tls = ext.is_threadlocal, | ||
| 989 | .absolute = false, | ||
| 990 | }; | ||
| 991 | } else { | ||
| 992 | return .{ | ||
| 993 | .binding = .local, | ||
| 994 | .tls = nav.resolved.?.@"threadlocal", | ||
| 995 | }; | ||
| 996 | } | ||
| 997 | }, | ||
| 998 | .enum_type => { | ||
| 999 | return .{ | ||
| 1000 | .binding = .local, | ||
| 1001 | }; | ||
| 1002 | }, | ||
| 1003 | else => unreachable, | ||
| 1004 | } | ||
| 1005 | } | ||
| 1006 | |||
| 909 | pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 { | 1007 | pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 { |
| 910 | const zcu = wasm.base.comp.zcu.?; | 1008 | const zcu = wasm.base.comp.zcu.?; |
| 911 | const ip = &zcu.intern_pool; | 1009 | const ip = &zcu.intern_pool; |
| ... | @@ -1034,6 +1132,15 @@ pub const FunctionImport = extern struct { | ... | @@ -1034,6 +1132,15 @@ pub const FunctionImport = extern struct { |
| 1034 | return pack(wasm, .{ .object_function = object_function }); | 1132 | return pack(wasm, .{ .object_function = object_function }); |
| 1035 | } | 1133 | } |
| 1036 | 1134 | ||
| 1135 | pub fn flags(r: Resolution, wasm: *Wasm) SymbolFlags { | ||
| 1136 | return switch (unpack(r, wasm)) { | ||
| 1137 | .unresolved => unreachable, | ||
| 1138 | .__wasm_apply_global_tls_relocs, .__wasm_call_ctors, .__wasm_init_memory, .__wasm_init_tls => unreachable, | ||
| 1139 | .object_function => |i| i.ptr(wasm).flags, | ||
| 1140 | .zcu_func => |i| i.flags(wasm), | ||
| 1141 | }; | ||
| 1142 | } | ||
| 1143 | |||
| 1037 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { | 1144 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { |
| 1038 | return switch (r.unpack(wasm)) { | 1145 | return switch (r.unpack(wasm)) { |
| 1039 | .unresolved, .zcu_func => true, | 1146 | .unresolved, .zcu_func => true, |
| ... | @@ -1136,6 +1243,7 @@ pub const GlobalImport = extern struct { | ... | @@ -1136,6 +1243,7 @@ pub const GlobalImport = extern struct { |
| 1136 | __tls_base, | 1243 | __tls_base, |
| 1137 | __tls_size, | 1244 | __tls_size, |
| 1138 | // Next, index into `object_globals`. | 1245 | // Next, index into `object_globals`. |
| 1246 | // Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. | ||
| 1139 | // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. | 1247 | // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. |
| 1140 | _, | 1248 | _, |
| 1141 | 1249 | ||
| ... | @@ -1150,6 +1258,8 @@ pub const GlobalImport = extern struct { | ... | @@ -1150,6 +1258,8 @@ pub const GlobalImport = extern struct { |
| 1150 | __tls_base, | 1258 | __tls_base, |
| 1151 | __tls_size, | 1259 | __tls_size, |
| 1152 | object_global: ObjectGlobalIndex, | 1260 | object_global: ObjectGlobalIndex, |
| 1261 | uav_exe: UavsExeIndex, | ||
| 1262 | uav_obj: UavsObjIndex, | ||
| 1153 | nav_exe: NavsExeIndex, | 1263 | nav_exe: NavsExeIndex, |
| 1154 | nav_obj: NavsObjIndex, | 1264 | nav_obj: NavsObjIndex, |
| 1155 | }; | 1265 | }; |
| ... | @@ -1170,12 +1280,22 @@ pub const GlobalImport = extern struct { | ... | @@ -1170,12 +1280,22 @@ pub const GlobalImport = extern struct { |
| 1170 | return .{ .object_global = @fromBackingInt(@intCast(object_global_index)) }; | 1280 | return .{ .object_global = @fromBackingInt(@intCast(object_global_index)) }; |
| 1171 | const comp = wasm.base.comp; | 1281 | const comp = wasm.base.comp; |
| 1172 | const is_obj = comp.config.output_mode == .Obj; | 1282 | const is_obj = comp.config.output_mode == .Obj; |
| 1173 | const nav_index = object_global_index - wasm.object_globals.items.len; | 1283 | const uav_index = object_global_index - wasm.object_globals.items.len; |
| 1174 | return if (is_obj) .{ | 1284 | if (is_obj) { |
| 1175 | .nav_obj = @fromBackingInt(@intCast(nav_index)), | 1285 | if (uav_index < wasm.uavs_obj.entries.len) { |
| 1176 | } else .{ | 1286 | return .{ .uav_obj = @fromBackingInt(@intCast(uav_index)) }; |
| 1177 | .nav_exe = @fromBackingInt(@intCast(nav_index)), | 1287 | } |
| 1178 | }; | 1288 | return .{ .nav_obj = @fromBackingInt( |
| 1289 | @intCast(uav_index - wasm.uavs_obj.entries.len), | ||
| 1290 | ) }; | ||
| 1291 | } else { | ||
| 1292 | if (uav_index < wasm.uavs_exe.entries.len) { | ||
| 1293 | return .{ .uav_exe = @fromBackingInt(@intCast(uav_index)) }; | ||
| 1294 | } | ||
| 1295 | return .{ .nav_exe = @fromBackingInt( | ||
| 1296 | @intCast(uav_index - wasm.uavs_exe.entries.len), | ||
| 1297 | ) }; | ||
| 1298 | } | ||
| 1179 | }, | 1299 | }, |
| 1180 | }; | 1300 | }; |
| 1181 | } | 1301 | } |
| ... | @@ -1190,11 +1310,29 @@ pub const GlobalImport = extern struct { | ... | @@ -1190,11 +1310,29 @@ pub const GlobalImport = extern struct { |
| 1190 | .__tls_base => .__tls_base, | 1310 | .__tls_base => .__tls_base, |
| 1191 | .__tls_size => .__tls_size, | 1311 | .__tls_size => .__tls_size, |
| 1192 | .object_global => |i| @fromBackingInt(@intCast(first_object_global + @backingInt(i))), | 1312 | .object_global => |i| @fromBackingInt(@intCast(first_object_global + @backingInt(i))), |
| 1193 | .nav_obj => |i| @fromBackingInt(@intCast(first_object_global + wasm.object_globals.items.len + @backingInt(i))), | 1313 | inline .uav_obj, .uav_exe => |i| @fromBackingInt(@intCast( |
| 1194 | .nav_exe => |i| @fromBackingInt(@intCast(first_object_global + wasm.object_globals.items.len + @backingInt(i))), | 1314 | first_object_global + wasm.object_globals.items.len + @backingInt(i), |
| 1315 | )), | ||
| 1316 | .nav_obj => |i| @fromBackingInt(@intCast( | ||
| 1317 | first_object_global + wasm.object_globals.items.len + | ||
| 1318 | wasm.uavs_obj.entries.len + @backingInt(i), | ||
| 1319 | )), | ||
| 1320 | .nav_exe => |i| @fromBackingInt(@intCast( | ||
| 1321 | first_object_global + wasm.object_globals.items.len + | ||
| 1322 | wasm.uavs_exe.entries.len + @backingInt(i), | ||
| 1323 | )), | ||
| 1195 | }; | 1324 | }; |
| 1196 | } | 1325 | } |
| 1197 | 1326 | ||
| 1327 | pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) Resolution { | ||
| 1328 | const is_obj = wasm.base.comp.config.output_mode == .Obj; | ||
| 1329 | return pack(wasm, if (is_obj) .{ | ||
| 1330 | .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)), | ||
| 1331 | } else .{ | ||
| 1332 | .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)), | ||
| 1333 | }); | ||
| 1334 | } | ||
| 1335 | |||
| 1198 | pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution { | 1336 | pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution { |
| 1199 | const comp = wasm.base.comp; | 1337 | const comp = wasm.base.comp; |
| 1200 | const is_obj = comp.config.output_mode == .Obj; | 1338 | const is_obj = comp.config.output_mode == .Obj; |
| ... | @@ -1209,7 +1347,22 @@ pub const GlobalImport = extern struct { | ... | @@ -1209,7 +1347,22 @@ pub const GlobalImport = extern struct { |
| 1209 | return pack(wasm, .{ .object_global = object_global }); | 1347 | return pack(wasm, .{ .object_global = object_global }); |
| 1210 | } | 1348 | } |
| 1211 | 1349 | ||
| 1212 | pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 { | 1350 | pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags { |
| 1351 | return switch (unpack(r, wasm)) { | ||
| 1352 | .unresolved, | ||
| 1353 | .__heap_base, | ||
| 1354 | .__heap_end, | ||
| 1355 | .__stack_pointer, | ||
| 1356 | .__tls_align, | ||
| 1357 | .__tls_base, | ||
| 1358 | .__tls_size, | ||
| 1359 | => unreachable, | ||
| 1360 | .object_global => |i| i.ptr(wasm).flags, | ||
| 1361 | .uav_obj, .uav_exe, .nav_obj, .nav_exe => unreachable, | ||
| 1362 | }; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | pub fn name(r: Resolution, wasm: *const Wasm, buf: []u8) ?[]const u8 { | ||
| 1213 | return switch (unpack(r, wasm)) { | 1366 | return switch (unpack(r, wasm)) { |
| 1214 | .unresolved => unreachable, | 1367 | .unresolved => unreachable, |
| 1215 | .__heap_base => @tagName(Unpacked.__heap_base), | 1368 | .__heap_base => @tagName(Unpacked.__heap_base), |
| ... | @@ -1219,6 +1372,11 @@ pub const GlobalImport = extern struct { | ... | @@ -1219,6 +1372,11 @@ pub const GlobalImport = extern struct { |
| 1219 | .__tls_base => @tagName(Unpacked.__tls_base), | 1372 | .__tls_base => @tagName(Unpacked.__tls_base), |
| 1220 | .__tls_size => @tagName(Unpacked.__tls_size), | 1373 | .__tls_size => @tagName(Unpacked.__tls_size), |
| 1221 | .object_global => |i| i.name(wasm).slice(wasm), | 1374 | .object_global => |i| i.name(wasm).slice(wasm), |
| 1375 | inline .uav_obj, .uav_exe => |i| std.fmt.bufPrint( | ||
| 1376 | buf, | ||
| 1377 | "__anon_{d}", | ||
| 1378 | .{@backingInt(i.key(wasm).*)}, | ||
| 1379 | ) catch unreachable, | ||
| 1222 | .nav_obj => |i| i.name(wasm), | 1380 | .nav_obj => |i| i.name(wasm), |
| 1223 | .nav_exe => |i| i.name(wasm), | 1381 | .nav_exe => |i| i.name(wasm), |
| 1224 | }; | 1382 | }; |
| ... | @@ -1349,6 +1507,22 @@ pub const TableImport = extern struct { | ... | @@ -1349,6 +1507,22 @@ pub const TableImport = extern struct { |
| 1349 | return pack(.{ .object_table = object_table }); | 1507 | return pack(.{ .object_table = object_table }); |
| 1350 | } | 1508 | } |
| 1351 | 1509 | ||
| 1510 | pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 { | ||
| 1511 | return switch (unpack(r)) { | ||
| 1512 | .unresolved => unreachable, | ||
| 1513 | .__indirect_function_table => @tagName(Unpacked.__indirect_function_table), | ||
| 1514 | .object_table => |i| i.ptr(wasm).name.slice(wasm), | ||
| 1515 | }; | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags { | ||
| 1519 | return switch (unpack(r)) { | ||
| 1520 | .unresolved => unreachable, | ||
| 1521 | .__indirect_function_table => unreachable, | ||
| 1522 | .object_table => |i| i.ptr(wasm).flags, | ||
| 1523 | }; | ||
| 1524 | } | ||
| 1525 | |||
| 1352 | pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType { | 1526 | pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType { |
| 1353 | return switch (unpack(r)) { | 1527 | return switch (unpack(r)) { |
| 1354 | .unresolved => unreachable, | 1528 | .unresolved => unreachable, |
| ... | @@ -1602,6 +1776,8 @@ pub const ObjectDataImport = extern struct { | ... | @@ -1602,6 +1776,8 @@ pub const ObjectDataImport = extern struct { |
| 1602 | unresolved, | 1776 | unresolved, |
| 1603 | __zig_error_names, | 1777 | __zig_error_names, |
| 1604 | __zig_error_name_table, | 1778 | __zig_error_name_table, |
| 1779 | __zig_tag_names, | ||
| 1780 | __zig_tag_name_table, | ||
| 1605 | __heap_base, | 1781 | __heap_base, |
| 1606 | __heap_end, | 1782 | __heap_end, |
| 1607 | /// Next, an `ObjectData.Index`. | 1783 | /// Next, an `ObjectData.Index`. |
| ... | @@ -1615,6 +1791,8 @@ pub const ObjectDataImport = extern struct { | ... | @@ -1615,6 +1791,8 @@ pub const ObjectDataImport = extern struct { |
| 1615 | unresolved, | 1791 | unresolved, |
| 1616 | __zig_error_names, | 1792 | __zig_error_names, |
| 1617 | __zig_error_name_table, | 1793 | __zig_error_name_table, |
| 1794 | __zig_tag_names, | ||
| 1795 | __zig_tag_name_table, | ||
| 1618 | __heap_base, | 1796 | __heap_base, |
| 1619 | __heap_end, | 1797 | __heap_end, |
| 1620 | object: ObjectData.Index, | 1798 | object: ObjectData.Index, |
| ... | @@ -1629,6 +1807,8 @@ pub const ObjectDataImport = extern struct { | ... | @@ -1629,6 +1807,8 @@ pub const ObjectDataImport = extern struct { |
| 1629 | .unresolved => .unresolved, | 1807 | .unresolved => .unresolved, |
| 1630 | .__zig_error_names => .__zig_error_names, | 1808 | .__zig_error_names => .__zig_error_names, |
| 1631 | .__zig_error_name_table => .__zig_error_name_table, | 1809 | .__zig_error_name_table => .__zig_error_name_table, |
| 1810 | .__zig_tag_names => .__zig_tag_names, | ||
| 1811 | .__zig_tag_name_table => .__zig_tag_name_table, | ||
| 1632 | .__heap_base => .__heap_base, | 1812 | .__heap_base => .__heap_base, |
| 1633 | .__heap_end => .__heap_end, | 1813 | .__heap_end => .__heap_end, |
| 1634 | _ => { | 1814 | _ => { |
| ... | @@ -1665,6 +1845,8 @@ pub const ObjectDataImport = extern struct { | ... | @@ -1665,6 +1845,8 @@ pub const ObjectDataImport = extern struct { |
| 1665 | .unresolved => .unresolved, | 1845 | .unresolved => .unresolved, |
| 1666 | .__zig_error_names => .__zig_error_names, | 1846 | .__zig_error_names => .__zig_error_names, |
| 1667 | .__zig_error_name_table => .__zig_error_name_table, | 1847 | .__zig_error_name_table => .__zig_error_name_table, |
| 1848 | .__zig_tag_names => .__zig_tag_names, | ||
| 1849 | .__zig_tag_name_table => .__zig_tag_name_table, | ||
| 1668 | .__heap_base => .__heap_base, | 1850 | .__heap_base => .__heap_base, |
| 1669 | .__heap_end => .__heap_end, | 1851 | .__heap_end => .__heap_end, |
| 1670 | .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))), | 1852 | .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))), |
| ... | @@ -1678,12 +1860,32 @@ pub const ObjectDataImport = extern struct { | ... | @@ -1678,12 +1860,32 @@ pub const ObjectDataImport = extern struct { |
| 1678 | return pack(wasm, .{ .object = object_data_index }); | 1860 | return pack(wasm, .{ .object = object_data_index }); |
| 1679 | } | 1861 | } |
| 1680 | 1862 | ||
| 1863 | pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) Resolution { | ||
| 1864 | const is_obj = wasm.base.comp.config.output_mode == .Obj; | ||
| 1865 | return pack(wasm, if (is_obj) .{ | ||
| 1866 | .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)), | ||
| 1867 | } else .{ | ||
| 1868 | .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)), | ||
| 1869 | }); | ||
| 1870 | } | ||
| 1871 | |||
| 1872 | pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution { | ||
| 1873 | const is_obj = wasm.base.comp.config.output_mode == .Obj; | ||
| 1874 | return pack(wasm, if (is_obj) .{ | ||
| 1875 | .nav_obj = @fromBackingInt(@intCast(wasm.navs_obj.getIndex(nav_index).?)), | ||
| 1876 | } else .{ | ||
| 1877 | .nav_exe = @fromBackingInt(@intCast(wasm.navs_exe.getIndex(nav_index).?)), | ||
| 1878 | }); | ||
| 1879 | } | ||
| 1880 | |||
| 1681 | pub fn objectDataSegment(r: Resolution, wasm: *const Wasm) ?ObjectDataSegment.Index { | 1881 | pub fn objectDataSegment(r: Resolution, wasm: *const Wasm) ?ObjectDataSegment.Index { |
| 1682 | return switch (unpack(r, wasm)) { | 1882 | return switch (unpack(r, wasm)) { |
| 1683 | .unresolved => unreachable, | 1883 | .unresolved => unreachable, |
| 1684 | .object => |i| i.ptr(wasm).segment, | 1884 | .object => |i| i.ptr(wasm).segment, |
| 1685 | .__zig_error_names, | 1885 | .__zig_error_names, |
| 1686 | .__zig_error_name_table, | 1886 | .__zig_error_name_table, |
| 1887 | .__zig_tag_names, | ||
| 1888 | .__zig_tag_name_table, | ||
| 1687 | .__heap_base, | 1889 | .__heap_base, |
| 1688 | .__heap_end, | 1890 | .__heap_end, |
| 1689 | .uav_exe, | 1891 | .uav_exe, |
| ... | @@ -1706,12 +1908,107 @@ pub const ObjectDataImport = extern struct { | ... | @@ -1706,12 +1908,107 @@ pub const ObjectDataImport = extern struct { |
| 1706 | }, | 1908 | }, |
| 1707 | .__zig_error_names => .{ .segment = .__zig_error_names, .offset = 0 }, | 1909 | .__zig_error_names => .{ .segment = .__zig_error_names, .offset = 0 }, |
| 1708 | .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 }, | 1910 | .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 }, |
| 1911 | .__zig_tag_names => .{ .segment = .__zig_tag_names, .offset = 0 }, | ||
| 1912 | .__zig_tag_name_table => .{ .segment = .__zig_tag_name_table, .offset = 0 }, | ||
| 1709 | .__heap_base => .{ .segment = .__heap_base, .offset = 0 }, | 1913 | .__heap_base => .{ .segment = .__heap_base, .offset = 0 }, |
| 1710 | .__heap_end => .{ .segment = .__heap_end, .offset = 0 }, | 1914 | .__heap_end => .{ .segment = .__heap_end, .offset = 0 }, |
| 1711 | .uav_exe => @panic("TODO"), | 1915 | .uav_exe => |i| .{ .segment = .pack(wasm, .{ .uav_exe = i }), .offset = 0 }, |
| 1712 | .uav_obj => @panic("TODO"), | 1916 | .uav_obj => |i| .{ .segment = .pack(wasm, .{ .uav_obj = i }), .offset = 0 }, |
| 1713 | .nav_exe => @panic("TODO"), | 1917 | .nav_exe => |i| .{ .segment = .pack(wasm, .{ .nav_exe = i }), .offset = 0 }, |
| 1714 | .nav_obj => @panic("TODO"), | 1918 | .nav_obj => |i| .{ .segment = .pack(wasm, .{ .nav_obj = i }), .offset = 0 }, |
| 1919 | }; | ||
| 1920 | } | ||
| 1921 | |||
| 1922 | pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags { | ||
| 1923 | return switch (unpack(r, wasm)) { | ||
| 1924 | .unresolved => unreachable, | ||
| 1925 | .__zig_error_names, | ||
| 1926 | .__zig_error_name_table, | ||
| 1927 | .__zig_tag_names, | ||
| 1928 | .__zig_tag_name_table, | ||
| 1929 | => .{ .binding = .local }, | ||
| 1930 | .__heap_base, | ||
| 1931 | .__heap_end, | ||
| 1932 | => unreachable, | ||
| 1933 | .object => |i| i.ptr(wasm).flags, | ||
| 1934 | inline .nav_exe, .nav_obj => |i| { | ||
| 1935 | const zcu = wasm.base.comp.zcu.?; | ||
| 1936 | const ip = &zcu.intern_pool; | ||
| 1937 | const nav = ip.getNav(i.key(wasm).*); | ||
| 1938 | if (nav.getExtern(ip)) |ext| { | ||
| 1939 | const name_slice = ext.name.toSlice(ip); | ||
| 1940 | const name_string = wasm.getExistingString(name_slice).?; | ||
| 1941 | return .{ | ||
| 1942 | .binding = switch (ext.linkage) { | ||
| 1943 | .internal => .local, | ||
| 1944 | .strong => .strong, | ||
| 1945 | .weak => .weak, | ||
| 1946 | .link_once => @panic("TODO: COMDAT"), | ||
| 1947 | }, | ||
| 1948 | .visibility_hidden = switch (ext.visibility) { | ||
| 1949 | .default => false, | ||
| 1950 | .hidden => true, | ||
| 1951 | .protected => false, | ||
| 1952 | }, | ||
| 1953 | .undefined = false, | ||
| 1954 | .exported = wasm.missing_exports.contains(name_string), | ||
| 1955 | .explicit_name = false, | ||
| 1956 | .no_strip = false, | ||
| 1957 | .tls = ext.is_threadlocal, | ||
| 1958 | .absolute = false, | ||
| 1959 | }; | ||
| 1960 | } else { | ||
| 1961 | return .{ | ||
| 1962 | .binding = .local, | ||
| 1963 | .tls = nav.resolved.?.@"threadlocal", | ||
| 1964 | }; | ||
| 1965 | } | ||
| 1966 | }, | ||
| 1967 | .uav_exe, .uav_obj => .{ .binding = .local }, | ||
| 1968 | }; | ||
| 1969 | } | ||
| 1970 | |||
| 1971 | pub fn name(r: Resolution, wasm: *const Wasm, buf: []u8) []const u8 { | ||
| 1972 | return switch (unpack(r, wasm)) { | ||
| 1973 | .unresolved => unreachable, | ||
| 1974 | .object => |i| i.ptr(wasm).name.slice(wasm), | ||
| 1975 | .__zig_error_names => @tagName(.__zig_error_names), | ||
| 1976 | .__zig_error_name_table => @tagName(.__zig_error_name_table), | ||
| 1977 | .__zig_tag_names => @tagName(.__zig_tag_names), | ||
| 1978 | .__zig_tag_name_table => @tagName(.__zig_tag_name_table), | ||
| 1979 | .__heap_base => @tagName(.__heap_base), | ||
| 1980 | .__heap_end => @tagName(.__heap_end), | ||
| 1981 | inline .uav_exe, .uav_obj => |i| std.fmt.bufPrint( | ||
| 1982 | buf, | ||
| 1983 | "__anon_{d}", | ||
| 1984 | .{@backingInt(i.key(wasm).*)}, | ||
| 1985 | ) catch unreachable, | ||
| 1986 | inline .nav_exe, .nav_obj => |i| i.name(wasm), | ||
| 1987 | }; | ||
| 1988 | } | ||
| 1989 | |||
| 1990 | pub fn size(r: Resolution, wasm: *const Wasm) u32 { | ||
| 1991 | return switch (unpack(r, wasm)) { | ||
| 1992 | .unresolved => unreachable, | ||
| 1993 | .__zig_error_names => @intCast(wasm.error_name_bytes.items.len), | ||
| 1994 | .__zig_error_name_table => { | ||
| 1995 | const comp = wasm.base.comp; | ||
| 1996 | const zcu = comp.zcu.?; | ||
| 1997 | const errors_len = wasm.error_name_offs.items.len; | ||
| 1998 | const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); | ||
| 1999 | return @intCast(errors_len * elem_size); | ||
| 2000 | }, | ||
| 2001 | .__zig_tag_names => @intCast(wasm.tag_name_bytes.items.len), | ||
| 2002 | .__zig_tag_name_table => { | ||
| 2003 | const comp = wasm.base.comp; | ||
| 2004 | const zcu = comp.zcu.?; | ||
| 2005 | const table_len = wasm.tag_name_offs.items.len; | ||
| 2006 | const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); | ||
| 2007 | return @intCast(table_len * elem_size); | ||
| 2008 | }, | ||
| 2009 | .__heap_base, .__heap_end => wasm.pointerSize(), | ||
| 2010 | .object => |i| i.ptr(wasm).size, | ||
| 2011 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, | ||
| 1715 | }; | 2012 | }; |
| 1716 | } | 2013 | } |
| 1717 | }; | 2014 | }; |
| ... | @@ -1910,6 +2207,38 @@ pub const DataSegmentId = enum(u32) { | ... | @@ -1910,6 +2207,38 @@ pub const DataSegmentId = enum(u32) { |
| 1910 | }; | 2207 | }; |
| 1911 | } | 2208 | } |
| 1912 | 2209 | ||
| 2210 | pub fn isStrings(id: DataSegmentId, wasm: *const Wasm) bool { | ||
| 2211 | return switch (unpack(id, wasm)) { | ||
| 2212 | .__zig_error_names, .__zig_tag_names => true, | ||
| 2213 | |||
| 2214 | .__zig_error_name_table, | ||
| 2215 | .__zig_tag_name_table, | ||
| 2216 | .__heap_base, | ||
| 2217 | .__heap_end, | ||
| 2218 | => false, | ||
| 2219 | |||
| 2220 | .object => |i| i.ptr(wasm).flags.strings, | ||
| 2221 | .uav_exe, .uav_obj => false, | ||
| 2222 | .nav_exe, .nav_obj => false, | ||
| 2223 | }; | ||
| 2224 | } | ||
| 2225 | |||
| 2226 | pub fn isRetain(id: DataSegmentId, wasm: *const Wasm) bool { | ||
| 2227 | return switch (unpack(id, wasm)) { | ||
| 2228 | .__zig_error_names, | ||
| 2229 | .__zig_error_name_table, | ||
| 2230 | .__zig_tag_names, | ||
| 2231 | .__zig_tag_name_table, | ||
| 2232 | .__heap_base, | ||
| 2233 | .__heap_end, | ||
| 2234 | => false, | ||
| 2235 | |||
| 2236 | .object => |i| i.ptr(wasm).flags.retain, | ||
| 2237 | .uav_exe, .uav_obj => false, | ||
| 2238 | .nav_exe, .nav_obj => false, | ||
| 2239 | }; | ||
| 2240 | } | ||
| 2241 | |||
| 1913 | pub fn isBss(id: DataSegmentId, wasm: *const Wasm) bool { | 2242 | pub fn isBss(id: DataSegmentId, wasm: *const Wasm) bool { |
| 1914 | return id.category(wasm) == .zero; | 2243 | return id.category(wasm) == .zero; |
| 1915 | } | 2244 | } |
| ... | @@ -2181,6 +2510,7 @@ const PreloadedStrings = struct { | ... | @@ -2181,6 +2510,7 @@ const PreloadedStrings = struct { |
| 2181 | _initialize: String, | 2510 | _initialize: String, |
| 2182 | _start: String, | 2511 | _start: String, |
| 2183 | memory: String, | 2512 | memory: String, |
| 2513 | env: String, | ||
| 2184 | }; | 2514 | }; |
| 2185 | 2515 | ||
| 2186 | /// Index into string_bytes | 2516 | /// Index into string_bytes |
| ... | @@ -2262,6 +2592,34 @@ pub const ZcuImportIndex = enum(u32) { | ... | @@ -2262,6 +2592,34 @@ pub const ZcuImportIndex = enum(u32) { |
| 2262 | return &wasm.imports.keys()[@backingInt(index)]; | 2592 | return &wasm.imports.keys()[@backingInt(index)]; |
| 2263 | } | 2593 | } |
| 2264 | 2594 | ||
| 2595 | pub fn flags(index: ZcuImportIndex, wasm: *const Wasm) SymbolFlags { | ||
| 2596 | const zcu = wasm.base.comp.zcu.?; | ||
| 2597 | const ip = &zcu.intern_pool; | ||
| 2598 | const nav_index = index.ptr(wasm).*; | ||
| 2599 | const ext = ip.indexToKey(ip.getNav(nav_index).resolved.?.value).@"extern"; | ||
| 2600 | const name_slice = ext.name.toSlice(ip); | ||
| 2601 | const name_string = wasm.getExistingString(name_slice).?; | ||
| 2602 | return .{ | ||
| 2603 | .binding = switch (ext.linkage) { | ||
| 2604 | .internal => .local, | ||
| 2605 | .strong => .strong, | ||
| 2606 | .weak => .weak, | ||
| 2607 | .link_once => @panic("TODO: COMDAT"), | ||
| 2608 | }, | ||
| 2609 | .visibility_hidden = switch (ext.visibility) { | ||
| 2610 | .default => false, | ||
| 2611 | .hidden => true, | ||
| 2612 | .protected => false, | ||
| 2613 | }, | ||
| 2614 | .undefined = true, | ||
| 2615 | .exported = wasm.missing_exports.contains(name_string), | ||
| 2616 | .explicit_name = false, | ||
| 2617 | .no_strip = false, | ||
| 2618 | .tls = ext.is_threadlocal, | ||
| 2619 | .absolute = false, | ||
| 2620 | }; | ||
| 2621 | } | ||
| 2622 | |||
| 2265 | pub fn importName(index: ZcuImportIndex, wasm: *const Wasm) String { | 2623 | pub fn importName(index: ZcuImportIndex, wasm: *const Wasm) String { |
| 2266 | const zcu = wasm.base.comp.zcu.?; | 2624 | const zcu = wasm.base.comp.zcu.?; |
| 2267 | const ip = &zcu.intern_pool; | 2625 | const ip = &zcu.intern_pool; |
| ... | @@ -2348,6 +2706,13 @@ pub const FunctionImportId = enum(u32) { | ... | @@ -2348,6 +2706,13 @@ pub const FunctionImportId = enum(u32) { |
| 2348 | } | 2706 | } |
| 2349 | } | 2707 | } |
| 2350 | 2708 | ||
| 2709 | pub fn flags(id: FunctionImportId, wasm: *const Wasm) SymbolFlags { | ||
| 2710 | return switch (id.unpack(wasm)) { | ||
| 2711 | .object_function_import => |i| i.value(wasm).flags, | ||
| 2712 | .zcu_import => |i| i.flags(wasm), | ||
| 2713 | }; | ||
| 2714 | } | ||
| 2715 | |||
| 2351 | pub fn importName(id: FunctionImportId, wasm: *const Wasm) String { | 2716 | pub fn importName(id: FunctionImportId, wasm: *const Wasm) String { |
| 2352 | return switch (unpack(id, wasm)) { | 2717 | return switch (unpack(id, wasm)) { |
| 2353 | inline .object_function_import, .zcu_import => |i| i.importName(wasm), | 2718 | inline .object_function_import, .zcu_import => |i| i.importName(wasm), |
| ... | @@ -2385,38 +2750,61 @@ pub const FunctionImportId = enum(u32) { | ... | @@ -2385,38 +2750,61 @@ pub const FunctionImportId = enum(u32) { |
| 2385 | } | 2750 | } |
| 2386 | }; | 2751 | }; |
| 2387 | 2752 | ||
| 2388 | /// 0. Index into `object_global_imports`. | 2753 | /// 0. `__stack_pointer`. |
| 2389 | /// 1. Index into `imports`. | 2754 | /// 1. Index into `object_global_imports`. |
| 2755 | /// 2. Index into `imports`. | ||
| 2390 | pub const GlobalImportId = enum(u32) { | 2756 | pub const GlobalImportId = enum(u32) { |
| 2757 | __stack_pointer, | ||
| 2391 | _, | 2758 | _, |
| 2392 | 2759 | ||
| 2393 | pub const Unpacked = union(enum) { | 2760 | pub const Unpacked = union(enum) { |
| 2761 | __stack_pointer, | ||
| 2394 | object_global_import: GlobalImport.Index, | 2762 | object_global_import: GlobalImport.Index, |
| 2395 | zcu_import: ZcuImportIndex, | 2763 | zcu_import: ZcuImportIndex, |
| 2396 | }; | 2764 | }; |
| 2397 | 2765 | ||
| 2398 | pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId { | 2766 | pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId { |
| 2399 | return switch (unpacked) { | 2767 | return switch (unpacked) { |
| 2400 | .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i))), | 2768 | .__stack_pointer => .__stack_pointer, |
| 2401 | .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len)), | 2769 | .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i) + 1)), |
| 2770 | .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len + 1)), | ||
| 2402 | }; | 2771 | }; |
| 2403 | } | 2772 | } |
| 2404 | 2773 | ||
| 2405 | pub fn unpack(id: GlobalImportId, wasm: *const Wasm) Unpacked { | 2774 | pub fn unpack(id: GlobalImportId, wasm: *const Wasm) Unpacked { |
| 2406 | const i = @backingInt(id); | 2775 | return switch (id) { |
| 2407 | if (i < wasm.object_global_imports.entries.len) return .{ .object_global_import = @fromBackingInt(@intCast(i)) }; | 2776 | .__stack_pointer => .__stack_pointer, |
| 2408 | const zcu_import_i = i - wasm.object_global_imports.entries.len; | 2777 | _ => { |
| 2409 | return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) }; | 2778 | const i = @backingInt(id) - 1; |
| 2779 | if (i < wasm.object_global_imports.entries.len) { | ||
| 2780 | return .{ .object_global_import = @fromBackingInt(@intCast(i)) }; | ||
| 2781 | } | ||
| 2782 | const zcu_import_i = i - wasm.object_global_imports.entries.len; | ||
| 2783 | return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) }; | ||
| 2784 | }, | ||
| 2785 | }; | ||
| 2410 | } | 2786 | } |
| 2411 | 2787 | ||
| 2412 | pub fn fromObject(object_global_import: GlobalImport.Index, wasm: *const Wasm) GlobalImportId { | 2788 | pub fn fromObject(object_global_import: GlobalImport.Index, wasm: *const Wasm) GlobalImportId { |
| 2413 | return pack(.{ .object_global_import = object_global_import }, wasm); | 2789 | return pack(.{ .object_global_import = object_global_import }, wasm); |
| 2414 | } | 2790 | } |
| 2415 | 2791 | ||
| 2792 | pub fn flags(id: GlobalImportId, wasm: *const Wasm) SymbolFlags { | ||
| 2793 | return switch (id.unpack(wasm)) { | ||
| 2794 | .__stack_pointer => .{ | ||
| 2795 | .binding = .strong, | ||
| 2796 | .undefined = true, | ||
| 2797 | }, | ||
| 2798 | .object_global_import => |i| i.value(wasm).flags, | ||
| 2799 | .zcu_import => |i| i.flags(wasm), | ||
| 2800 | }; | ||
| 2801 | } | ||
| 2802 | |||
| 2416 | /// This function is allowed O(N) lookup because it is only called during | 2803 | /// This function is allowed O(N) lookup because it is only called during |
| 2417 | /// diagnostic generation. | 2804 | /// diagnostic generation. |
| 2418 | pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation { | 2805 | pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation { |
| 2419 | switch (id.unpack(wasm)) { | 2806 | switch (id.unpack(wasm)) { |
| 2807 | .__stack_pointer => return .zig_object_nofile, | ||
| 2420 | .object_global_import => |obj_global_index| { | 2808 | .object_global_import => |obj_global_index| { |
| 2421 | // TODO binary search | 2809 | // TODO binary search |
| 2422 | for (wasm.objects.items, 0..) |o, i| { | 2810 | for (wasm.objects.items, 0..) |o, i| { |
| ... | @@ -2433,18 +2821,28 @@ pub const GlobalImportId = enum(u32) { | ... | @@ -2433,18 +2821,28 @@ pub const GlobalImportId = enum(u32) { |
| 2433 | 2821 | ||
| 2434 | pub fn importName(id: GlobalImportId, wasm: *const Wasm) String { | 2822 | pub fn importName(id: GlobalImportId, wasm: *const Wasm) String { |
| 2435 | return switch (unpack(id, wasm)) { | 2823 | return switch (unpack(id, wasm)) { |
| 2824 | .__stack_pointer => wasm.preloaded_strings.__stack_pointer, | ||
| 2436 | inline .object_global_import, .zcu_import => |i| i.importName(wasm), | 2825 | inline .object_global_import, .zcu_import => |i| i.importName(wasm), |
| 2437 | }; | 2826 | }; |
| 2438 | } | 2827 | } |
| 2439 | 2828 | ||
| 2440 | pub fn moduleName(id: GlobalImportId, wasm: *const Wasm) OptionalString { | 2829 | pub fn moduleName(id: GlobalImportId, wasm: *const Wasm) OptionalString { |
| 2441 | return switch (unpack(id, wasm)) { | 2830 | return switch (unpack(id, wasm)) { |
| 2831 | .__stack_pointer => wasm.preloaded_strings.env.toOptional(), | ||
| 2442 | inline .object_global_import, .zcu_import => |i| i.moduleName(wasm), | 2832 | inline .object_global_import, .zcu_import => |i| i.moduleName(wasm), |
| 2443 | }; | 2833 | }; |
| 2444 | } | 2834 | } |
| 2445 | 2835 | ||
| 2446 | pub fn globalType(id: GlobalImportId, wasm: *Wasm) ObjectGlobal.Type { | 2836 | pub fn globalType(id: GlobalImportId, wasm: *Wasm) ObjectGlobal.Type { |
| 2447 | return switch (unpack(id, wasm)) { | 2837 | return switch (unpack(id, wasm)) { |
| 2838 | .__stack_pointer => .{ | ||
| 2839 | .valtype = switch (wasm.pointerSize()) { | ||
| 2840 | 4 => .i32, | ||
| 2841 | 8 => .i64, | ||
| 2842 | else => unreachable, | ||
| 2843 | }, | ||
| 2844 | .mutable = true, | ||
| 2845 | }, | ||
| 2448 | inline .object_global_import, .zcu_import => |i| i.globalType(wasm), | 2846 | inline .object_global_import, .zcu_import => |i| i.globalType(wasm), |
| 2449 | }; | 2847 | }; |
| 2450 | } | 2848 | } |
| ... | @@ -2482,6 +2880,13 @@ pub const DataImportId = enum(u32) { | ... | @@ -2482,6 +2880,13 @@ pub const DataImportId = enum(u32) { |
| 2482 | return pack(.{ .object_data_import = object_data_import }, wasm); | 2880 | return pack(.{ .object_data_import = object_data_import }, wasm); |
| 2483 | } | 2881 | } |
| 2484 | 2882 | ||
| 2883 | pub fn flags(id: DataImportId, wasm: *const Wasm) SymbolFlags { | ||
| 2884 | return switch (id.unpack(wasm)) { | ||
| 2885 | .object_data_import => |i| i.value(wasm).flags, | ||
| 2886 | .zcu_import => |i| i.flags(wasm), | ||
| 2887 | }; | ||
| 2888 | } | ||
| 2889 | |||
| 2485 | pub fn sourceLocation(id: DataImportId, wasm: *const Wasm) SourceLocation { | 2890 | pub fn sourceLocation(id: DataImportId, wasm: *const Wasm) SourceLocation { |
| 2486 | switch (id.unpack(wasm)) { | 2891 | switch (id.unpack(wasm)) { |
| 2487 | .object_data_import => |obj_data_index| { | 2892 | .object_data_import => |obj_data_index| { |
| ... | @@ -2499,33 +2904,42 @@ pub const DataImportId = enum(u32) { | ... | @@ -2499,33 +2904,42 @@ pub const DataImportId = enum(u32) { |
| 2499 | } | 2904 | } |
| 2500 | }; | 2905 | }; |
| 2501 | 2906 | ||
| 2502 | /// Index into `Wasm.symbol_table`. | 2907 | pub const ZcuRelocation = struct { |
| 2503 | pub const SymbolTableIndex = enum(u32) { | ||
| 2504 | _, | ||
| 2505 | |||
| 2506 | pub fn key(i: @This(), wasm: *const Wasm) *String { | ||
| 2507 | return &wasm.symbol_table.keys()[@backingInt(i)]; | ||
| 2508 | } | ||
| 2509 | }; | ||
| 2510 | |||
| 2511 | pub const OutReloc = struct { | ||
| 2512 | tag: Object.RelocationType, | 2908 | tag: Object.RelocationType, |
| 2513 | offset: u32, | 2909 | offset: u32, |
| 2514 | pointee: Pointee, | 2910 | pointee: Pointee, |
| 2515 | addend: i32, | 2911 | addend: i32, |
| 2516 | 2912 | ||
| 2517 | pub const Pointee = union { | 2913 | pub const Pointee = union(enum) { |
| 2518 | symbol_index: SymbolTableIndex, | 2914 | function_nav: InternPool.Nav.Index, |
| 2915 | function_name: String, | ||
| 2916 | tag_function: InternPool.Index, | ||
| 2917 | data_uav: InternPool.Index, | ||
| 2918 | data_nav: InternPool.Nav.Index, | ||
| 2919 | data_resolution: ObjectDataImport.Resolution, | ||
| 2920 | stack_pointer, | ||
| 2519 | type_index: FunctionType.Index, | 2921 | type_index: FunctionType.Index, |
| 2520 | }; | 2922 | }; |
| 2521 | 2923 | ||
| 2522 | pub const Slice = extern struct { | 2924 | pub const Slice = extern struct { |
| 2523 | /// Index into `out_relocs`. | 2925 | /// Index into `zcu_relocations`. |
| 2524 | off: u32, | 2926 | off: u32, |
| 2525 | len: u32, | 2927 | len: u32, |
| 2526 | 2928 | ||
| 2527 | pub fn slice(s: Slice, wasm: *const Wasm) []OutReloc { | 2929 | pub fn tags(s: Slice, wasm: *const Wasm) []const Object.RelocationType { |
| 2528 | return wasm.relocations.items[s.off..][0..s.len]; | 2930 | return wasm.zcu_relocations.items(.tag)[s.off..][0..s.len]; |
| 2931 | } | ||
| 2932 | |||
| 2933 | pub fn offsets(s: Slice, wasm: *const Wasm) []const u32 { | ||
| 2934 | return wasm.zcu_relocations.items(.offset)[s.off..][0..s.len]; | ||
| 2935 | } | ||
| 2936 | |||
| 2937 | pub fn pointees(s: Slice, wasm: *const Wasm) []const Pointee { | ||
| 2938 | return wasm.zcu_relocations.items(.pointee)[s.off..][0..s.len]; | ||
| 2939 | } | ||
| 2940 | |||
| 2941 | pub fn addends(s: Slice, wasm: *const Wasm) []const i32 { | ||
| 2942 | return wasm.zcu_relocations.items(.addend)[s.off..][0..s.len]; | ||
| 2529 | } | 2943 | } |
| 2530 | }; | 2944 | }; |
| 2531 | }; | 2945 | }; |
| ... | @@ -3137,9 +3551,9 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -3137,9 +3551,9 @@ pub fn deinit(wasm: *Wasm) void { |
| 3137 | wasm.table_imports.deinit(gpa); | 3551 | wasm.table_imports.deinit(gpa); |
| 3138 | wasm.tables.deinit(gpa); | 3552 | wasm.tables.deinit(gpa); |
| 3139 | wasm.data_imports.deinit(gpa); | 3553 | wasm.data_imports.deinit(gpa); |
| 3554 | wasm.datas.deinit(gpa); | ||
| 3140 | wasm.data_segments.deinit(gpa); | 3555 | wasm.data_segments.deinit(gpa); |
| 3141 | wasm.symbol_table.deinit(gpa); | 3556 | wasm.zcu_relocations.deinit(gpa); |
| 3142 | wasm.out_relocs.deinit(gpa); | ||
| 3143 | wasm.uav_fixups.deinit(gpa); | 3557 | wasm.uav_fixups.deinit(gpa); |
| 3144 | wasm.nav_fixups.deinit(gpa); | 3558 | wasm.nav_fixups.deinit(gpa); |
| 3145 | wasm.func_table_fixups.deinit(gpa); | 3559 | wasm.func_table_fixups.deinit(gpa); |
| ... | @@ -3351,6 +3765,25 @@ pub fn updateExports( | ... | @@ -3351,6 +3765,25 @@ pub fn updateExports( |
| 3351 | const zcu = pt.zcu; | 3765 | const zcu = pt.zcu; |
| 3352 | const gpa = zcu.gpa; | 3766 | const gpa = zcu.gpa; |
| 3353 | const ip = &zcu.intern_pool; | 3767 | const ip = &zcu.intern_pool; |
| 3768 | const is_obj = wasm.base.comp.config.output_mode == .Obj; | ||
| 3769 | switch (exported) { | ||
| 3770 | .nav => {}, // handled in updateNav | ||
| 3771 | .uav => |uav_index| { // export may be the only reference | ||
| 3772 | const zds: ZcuDataStarts = .init(wasm); | ||
| 3773 | if (is_obj) { | ||
| 3774 | const gop = try wasm.uavs_obj.getOrPut(gpa, uav_index); | ||
| 3775 | if (!gop.found_existing) gop.value_ptr.* = undefined; | ||
| 3776 | } else { | ||
| 3777 | const gop = try wasm.uavs_exe.getOrPut(gpa, uav_index); | ||
| 3778 | if (!gop.found_existing) gop.value_ptr.* = .{ | ||
| 3779 | .code = undefined, | ||
| 3780 | .count = 0, | ||
| 3781 | }; | ||
| 3782 | gop.value_ptr.count += 1; | ||
| 3783 | } | ||
| 3784 | try zds.finish(wasm, pt); | ||
| 3785 | }, | ||
| 3786 | } | ||
| 3354 | for (export_indices) |export_idx| { | 3787 | for (export_indices) |export_idx| { |
| 3355 | const exp = export_idx.ptr(zcu); | 3788 | const exp = export_idx.ptr(zcu); |
| 3356 | const name_slice = exp.opts.name.toSlice(ip); | 3789 | const name_slice = exp.opts.name.toSlice(ip); |
| ... | @@ -3443,7 +3876,11 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { | ... | @@ -3443,7 +3876,11 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { |
| 3443 | // Zig always depends on a stack pointer global. | 3876 | // Zig always depends on a stack pointer global. |
| 3444 | // If emitting an object, it's an import. Otherwise, the linker synthesizes it. | 3877 | // If emitting an object, it's an import. Otherwise, the linker synthesizes it. |
| 3445 | if (is_obj) { | 3878 | if (is_obj) { |
| 3446 | @panic("TODO"); | 3879 | try wasm.global_imports.putNoClobber( |
| 3880 | gpa, | ||
| 3881 | wasm.preloaded_strings.__stack_pointer, | ||
| 3882 | .__stack_pointer, | ||
| 3883 | ); | ||
| 3447 | } else { | 3884 | } else { |
| 3448 | try wasm.globals.put(gpa, .__stack_pointer, {}); | 3885 | try wasm.globals.put(gpa, .__stack_pointer, {}); |
| 3449 | assert(wasm.globals.entries.len - 1 == @backingInt(GlobalIndex.stack_pointer)); | 3886 | assert(wasm.globals.entries.len - 1 == @backingInt(GlobalIndex.stack_pointer)); |
| ... | @@ -3453,7 +3890,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { | ... | @@ -3453,7 +3890,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { |
| 3453 | // These loops do both recursive marking of alive symbols well as checking for undefined symbols. | 3890 | // These loops do both recursive marking of alive symbols well as checking for undefined symbols. |
| 3454 | // At the end, output functions and globals will be populated. | 3891 | // At the end, output functions and globals will be populated. |
| 3455 | for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| { | 3892 | for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| { |
| 3456 | if (import.flags.isIncluded(rdynamic)) { | 3893 | if (import.flags.isIncluded(rdynamic, is_obj)) { |
| 3457 | try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i))); | 3894 | try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i))); |
| 3458 | } | 3895 | } |
| 3459 | } | 3896 | } |
| ... | @@ -3467,7 +3904,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { | ... | @@ -3467,7 +3904,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { |
| 3467 | wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); | 3904 | wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); |
| 3468 | 3905 | ||
| 3469 | for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { | 3906 | for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { |
| 3470 | if (import.flags.isIncluded(rdynamic)) { | 3907 | if (import.flags.isIncluded(rdynamic, is_obj)) { |
| 3471 | try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i))); | 3908 | try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i))); |
| 3472 | } | 3909 | } |
| 3473 | } | 3910 | } |
| ... | @@ -3475,13 +3912,13 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { | ... | @@ -3475,13 +3912,13 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { |
| 3475 | wasm.global_exports_len = @intCast(wasm.global_exports.items.len); | 3912 | wasm.global_exports_len = @intCast(wasm.global_exports.items.len); |
| 3476 | 3913 | ||
| 3477 | for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| { | 3914 | for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| { |
| 3478 | if (import.flags.isIncluded(rdynamic)) { | 3915 | if (import.flags.isIncluded(rdynamic, is_obj)) { |
| 3479 | try markTableImport(wasm, name, import, @fromBackingInt(@intCast(i))); | 3916 | try markTableImport(wasm, name, import, @fromBackingInt(@intCast(i))); |
| 3480 | } | 3917 | } |
| 3481 | } | 3918 | } |
| 3482 | 3919 | ||
| 3483 | for (wasm.object_data_imports.keys(), wasm.object_data_imports.values(), 0..) |name, *import, i| { | 3920 | for (wasm.object_data_imports.keys(), wasm.object_data_imports.values(), 0..) |name, *import, i| { |
| 3484 | if (import.flags.isIncluded(rdynamic)) { | 3921 | if (import.flags.isIncluded(rdynamic, is_obj)) { |
| 3485 | try markDataImport(wasm, name, import, @fromBackingInt(@intCast(i))); | 3922 | try markDataImport(wasm, name, import, @fromBackingInt(@intCast(i))); |
| 3486 | } | 3923 | } |
| 3487 | } | 3924 | } |
| ... | @@ -3512,18 +3949,23 @@ pub fn markFunctionImport( | ... | @@ -3512,18 +3949,23 @@ pub fn markFunctionImport( |
| 3512 | 3949 | ||
| 3513 | const comp = wasm.base.comp; | 3950 | const comp = wasm.base.comp; |
| 3514 | const gpa = comp.gpa; | 3951 | const gpa = comp.gpa; |
| 3952 | const is_obj = comp.config.output_mode == .Obj; | ||
| 3515 | 3953 | ||
| 3516 | try wasm.functions.ensureUnusedCapacity(gpa, 1); | 3954 | try wasm.functions.ensureUnusedCapacity(gpa, 1); |
| 3517 | 3955 | ||
| 3518 | if (import.resolution == .unresolved) { | 3956 | if (import.resolution == .unresolved) { |
| 3519 | if (name == wasm.preloaded_strings.__wasm_init_memory) { | 3957 | if (!is_obj) { |
| 3520 | try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{}); | 3958 | if (name == wasm.preloaded_strings.__wasm_init_memory) { |
| 3521 | } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) { | 3959 | try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{}); |
| 3522 | try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{}); | 3960 | } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) { |
| 3523 | } else if (name == wasm.preloaded_strings.__wasm_call_ctors) { | 3961 | try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{}); |
| 3524 | try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{}); | 3962 | } else if (name == wasm.preloaded_strings.__wasm_call_ctors) { |
| 3525 | } else if (name == wasm.preloaded_strings.__wasm_init_tls) { | 3963 | try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{}); |
| 3526 | try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{}); | 3964 | } else if (name == wasm.preloaded_strings.__wasm_init_tls) { |
| 3965 | try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{}); | ||
| 3966 | } else { | ||
| 3967 | try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); | ||
| 3968 | } | ||
| 3527 | } else { | 3969 | } else { |
| 3528 | try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); | 3970 | try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); |
| 3529 | } | 3971 | } |
| ... | @@ -3576,28 +4018,33 @@ fn markGlobalImport( | ... | @@ -3576,28 +4018,33 @@ fn markGlobalImport( |
| 3576 | 4018 | ||
| 3577 | const comp = wasm.base.comp; | 4019 | const comp = wasm.base.comp; |
| 3578 | const gpa = comp.gpa; | 4020 | const gpa = comp.gpa; |
| 4021 | const is_obj = comp.config.output_mode == .Obj; | ||
| 3579 | 4022 | ||
| 3580 | try wasm.globals.ensureUnusedCapacity(gpa, 1); | 4023 | try wasm.globals.ensureUnusedCapacity(gpa, 1); |
| 3581 | 4024 | ||
| 3582 | if (import.resolution == .unresolved) { | 4025 | if (import.resolution == .unresolved) { |
| 3583 | if (name == wasm.preloaded_strings.__heap_base) { | 4026 | if (!is_obj) { |
| 3584 | import.resolution = .__heap_base; | 4027 | if (name == wasm.preloaded_strings.__heap_base) { |
| 3585 | wasm.globals.putAssumeCapacity(.__heap_base, {}); | 4028 | import.resolution = .__heap_base; |
| 3586 | } else if (name == wasm.preloaded_strings.__heap_end) { | 4029 | wasm.globals.putAssumeCapacity(.__heap_base, {}); |
| 3587 | import.resolution = .__heap_end; | 4030 | } else if (name == wasm.preloaded_strings.__heap_end) { |
| 3588 | wasm.globals.putAssumeCapacity(.__heap_end, {}); | 4031 | import.resolution = .__heap_end; |
| 3589 | } else if (name == wasm.preloaded_strings.__stack_pointer) { | 4032 | wasm.globals.putAssumeCapacity(.__heap_end, {}); |
| 3590 | import.resolution = .__stack_pointer; | 4033 | } else if (name == wasm.preloaded_strings.__stack_pointer) { |
| 3591 | wasm.globals.putAssumeCapacity(.__stack_pointer, {}); | 4034 | import.resolution = .__stack_pointer; |
| 3592 | } else if (name == wasm.preloaded_strings.__tls_align) { | 4035 | wasm.globals.putAssumeCapacity(.__stack_pointer, {}); |
| 3593 | import.resolution = .__tls_align; | 4036 | } else if (name == wasm.preloaded_strings.__tls_align) { |
| 3594 | wasm.globals.putAssumeCapacity(.__tls_align, {}); | 4037 | import.resolution = .__tls_align; |
| 3595 | } else if (name == wasm.preloaded_strings.__tls_base) { | 4038 | wasm.globals.putAssumeCapacity(.__tls_align, {}); |
| 3596 | import.resolution = .__tls_base; | 4039 | } else if (name == wasm.preloaded_strings.__tls_base) { |
| 3597 | wasm.globals.putAssumeCapacity(.__tls_base, {}); | 4040 | import.resolution = .__tls_base; |
| 3598 | } else if (name == wasm.preloaded_strings.__tls_size) { | 4041 | wasm.globals.putAssumeCapacity(.__tls_base, {}); |
| 3599 | import.resolution = .__tls_size; | 4042 | } else if (name == wasm.preloaded_strings.__tls_size) { |
| 3600 | wasm.globals.putAssumeCapacity(.__tls_size, {}); | 4043 | import.resolution = .__tls_size; |
| 4044 | wasm.globals.putAssumeCapacity(.__tls_size, {}); | ||
| 4045 | } else { | ||
| 4046 | try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); | ||
| 4047 | } | ||
| 3601 | } else { | 4048 | } else { |
| 3602 | try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); | 4049 | try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); |
| 3603 | } | 4050 | } |
| ... | @@ -3625,7 +4072,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err | ... | @@ -3625,7 +4072,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err |
| 3625 | try wasm.markRelocations(global.relocations(wasm)); | 4072 | try wasm.markRelocations(global.relocations(wasm)); |
| 3626 | } | 4073 | } |
| 3627 | 4074 | ||
| 3628 | fn markTableImport( | 4075 | pub fn markTableImport( |
| 3629 | wasm: *Wasm, | 4076 | wasm: *Wasm, |
| 3630 | name: String, | 4077 | name: String, |
| 3631 | import: *TableImport, | 4078 | import: *TableImport, |
| ... | @@ -3636,13 +4083,18 @@ fn markTableImport( | ... | @@ -3636,13 +4083,18 @@ fn markTableImport( |
| 3636 | 4083 | ||
| 3637 | const comp = wasm.base.comp; | 4084 | const comp = wasm.base.comp; |
| 3638 | const gpa = comp.gpa; | 4085 | const gpa = comp.gpa; |
| 4086 | const is_obj = comp.config.output_mode == .Obj; | ||
| 3639 | 4087 | ||
| 3640 | try wasm.tables.ensureUnusedCapacity(gpa, 1); | 4088 | try wasm.tables.ensureUnusedCapacity(gpa, 1); |
| 3641 | 4089 | ||
| 3642 | if (import.resolution == .unresolved) { | 4090 | if (import.resolution == .unresolved) { |
| 3643 | if (name == wasm.preloaded_strings.__indirect_function_table) { | 4091 | if (!is_obj) { |
| 3644 | import.resolution = .__indirect_function_table; | 4092 | if (name == wasm.preloaded_strings.__indirect_function_table) { |
| 3645 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); | 4093 | import.resolution = .__indirect_function_table; |
| 4094 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); | ||
| 4095 | } else { | ||
| 4096 | try wasm.table_imports.put(gpa, name, table_index); | ||
| 4097 | } | ||
| 3646 | } else { | 4098 | } else { |
| 3647 | try wasm.table_imports.put(gpa, name, table_index); | 4099 | try wasm.table_imports.put(gpa, name, table_index); |
| 3648 | } | 4100 | } |
| ... | @@ -3676,22 +4128,38 @@ pub fn markDataImport( | ... | @@ -3676,22 +4128,38 @@ pub fn markDataImport( |
| 3676 | 4128 | ||
| 3677 | const comp = wasm.base.comp; | 4129 | const comp = wasm.base.comp; |
| 3678 | const gpa = comp.gpa; | 4130 | const gpa = comp.gpa; |
| 4131 | const is_obj = comp.config.output_mode == .Obj; | ||
| 4132 | |||
| 4133 | try wasm.data_segments.ensureUnusedCapacity(gpa, 1); | ||
| 3679 | 4134 | ||
| 3680 | if (import.resolution == .unresolved) { | 4135 | if (import.resolution == .unresolved) { |
| 3681 | if (name == wasm.preloaded_strings.__heap_base) { | 4136 | if (!is_obj) { |
| 3682 | import.resolution = .__heap_base; | 4137 | if (name == wasm.preloaded_strings.__heap_base) { |
| 3683 | wasm.data_segments.putAssumeCapacity(.__heap_base, {}); | 4138 | import.resolution = .__heap_base; |
| 3684 | } else if (name == wasm.preloaded_strings.__heap_end) { | 4139 | wasm.data_segments.putAssumeCapacity(.__heap_base, {}); |
| 3685 | import.resolution = .__heap_end; | 4140 | } else if (name == wasm.preloaded_strings.__heap_end) { |
| 3686 | wasm.data_segments.putAssumeCapacity(.__heap_end, {}); | 4141 | import.resolution = .__heap_end; |
| 4142 | wasm.data_segments.putAssumeCapacity(.__heap_end, {}); | ||
| 4143 | } else { | ||
| 4144 | try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); | ||
| 4145 | } | ||
| 3687 | } else { | 4146 | } else { |
| 3688 | try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); | 4147 | try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); |
| 3689 | } | 4148 | } |
| 3690 | } else if (import.resolution.objectDataSegment(wasm)) |segment_index| { | 4149 | } else switch (import.resolution.unpack(wasm)) { |
| 3691 | try markDataSegment(wasm, segment_index); | 4150 | .object => |object_data_index| try markData(wasm, object_data_index), |
| 4151 | else => {}, | ||
| 3692 | } | 4152 | } |
| 3693 | } | 4153 | } |
| 3694 | 4154 | ||
| 4155 | fn markData(wasm: *Wasm, i: ObjectData.Index) link.Error!void { | ||
| 4156 | const gpa = wasm.base.comp.gpa; | ||
| 4157 | const gop = try wasm.datas.getOrPut(gpa, .fromObjectDataIndex(wasm, i)); | ||
| 4158 | if (gop.found_existing) return; | ||
| 4159 | |||
| 4160 | try markDataSegment(wasm, i.ptr(wasm).segment); | ||
| 4161 | } | ||
| 4162 | |||
| 3695 | fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void { | 4163 | fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void { |
| 3696 | const gpa = wasm.base.comp.gpa; | 4164 | const gpa = wasm.base.comp.gpa; |
| 3697 | for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| { | 4165 | for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| { |
| ... | @@ -3782,7 +4250,7 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Err | ... | @@ -3782,7 +4250,7 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Err |
| 3782 | .memory_addr_tls_sleb, | 4250 | .memory_addr_tls_sleb, |
| 3783 | .memory_addr_locrel_i32, | 4251 | .memory_addr_locrel_i32, |
| 3784 | .memory_addr_tls_sleb64, | 4252 | .memory_addr_tls_sleb64, |
| 3785 | => try markDataSegment(wasm, pointee.data.ptr(wasm).segment), | 4253 | => try markData(wasm, pointee.data), |
| 3786 | 4254 | ||
| 3787 | .type_index_leb => continue, | 4255 | .type_index_leb => continue, |
| 3788 | } | 4256 | } |
| ... | @@ -3829,7 +4297,13 @@ pub fn flush( | ... | @@ -3829,7 +4297,13 @@ pub fn flush( |
| 3829 | const hidden_function_exports_end_zcu: u32 = @intCast(wasm.hidden_function_exports.entries.len); | 4297 | const hidden_function_exports_end_zcu: u32 = @intCast(wasm.hidden_function_exports.entries.len); |
| 3830 | defer wasm.hidden_function_exports.shrinkRetainingCapacity(hidden_function_exports_end_zcu); | 4298 | defer wasm.hidden_function_exports.shrinkRetainingCapacity(hidden_function_exports_end_zcu); |
| 3831 | 4299 | ||
| 4300 | const global_exports_end_zcu: u32 = @intCast(wasm.global_exports.items.len); | ||
| 4301 | defer wasm.global_exports.shrinkRetainingCapacity(global_exports_end_zcu); | ||
| 4302 | |||
| 3832 | wasm.flush_buffer.clear(); | 4303 | wasm.flush_buffer.clear(); |
| 4304 | wasm.tag_name_bytes.clearRetainingCapacity(); | ||
| 4305 | wasm.tag_name_offs.clearRetainingCapacity(); | ||
| 4306 | wasm.tag_name_table_ref_count = 0; | ||
| 3833 | try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{}); | 4307 | try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{}); |
| 3834 | try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values()); | 4308 | try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values()); |
| 3835 | try wasm.flush_buffer.global_imports.reinit(gpa, wasm.global_imports.keys(), wasm.global_imports.values()); | 4309 | try wasm.flush_buffer.global_imports.reinit(gpa, wasm.global_imports.keys(), wasm.global_imports.values()); |
| ... | @@ -3953,6 +4427,255 @@ pub fn getExistingFunctionType( | ... | @@ -3953,6 +4427,255 @@ pub fn getExistingFunctionType( |
| 3953 | }); | 4427 | }); |
| 3954 | } | 4428 | } |
| 3955 | 4429 | ||
| 4430 | fn internIntrinsicType( | ||
| 4431 | wasm: *Wasm, | ||
| 4432 | params: []const InternPool.Index, | ||
| 4433 | return_type: Zcu.Type, | ||
| 4434 | ) Allocator.Error!FunctionType.Index { | ||
| 4435 | const target = &wasm.base.comp.root_mod.resolved_target.result; | ||
| 4436 | return wasm.internFunctionType(.{ .wasm_mvp = .{} }, params, return_type, false, target); | ||
| 4437 | } | ||
| 4438 | |||
| 4439 | pub fn intrinsicFunctionType(wasm: *Wasm, intrinsic: Mir.Intrinsic) Allocator.Error!FunctionType.Index { | ||
| 4440 | return switch (intrinsic) { | ||
| 4441 | .__addhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), | ||
| 4442 | .__addtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), | ||
| 4443 | .__addxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), | ||
| 4444 | .__ashlti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128), | ||
| 4445 | .__ashrti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128), | ||
| 4446 | .__bitreversedi2 => internIntrinsicType(wasm, &.{.u64_type}, .u64), | ||
| 4447 | .__bitreversesi2 => internIntrinsicType(wasm, &.{.u32_type}, .u32), | ||
| 4448 | .__bswapdi2 => internIntrinsicType(wasm, &.{.u64_type}, .u64), | ||
| 4449 | .__bswapsi2 => internIntrinsicType(wasm, &.{.u32_type}, .u32), | ||
| 4450 | .__ceilh => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4451 | .__ceilx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4452 | .__cosh => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4453 | .__cosx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4454 | .__divei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), | ||
| 4455 | .__divhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), | ||
| 4456 | .__divtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), | ||
| 4457 | .__divti3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128), | ||
| 4458 | .__divxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), | ||
| 4459 | .__eqtf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), | ||
| 4460 | .__eqxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), | ||
| 4461 | .__exp2h => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4462 | .__exp2x => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4463 | .__exph => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4464 | .__expx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4465 | .__extenddftf2 => internIntrinsicType(wasm, &.{.f64_type}, .f128), | ||
| 4466 | .__extenddfxf2 => internIntrinsicType(wasm, &.{.f64_type}, .f80), | ||
| 4467 | .__extendhfsf2 => internIntrinsicType(wasm, &.{.f16_type}, .f32), | ||
| 4468 | .__extendhftf2 => internIntrinsicType(wasm, &.{.f16_type}, .f128), | ||
| 4469 | .__extendhfxf2 => internIntrinsicType(wasm, &.{.f16_type}, .f80), | ||
| 4470 | .__extendsftf2 => internIntrinsicType(wasm, &.{.f32_type}, .f128), | ||
| 4471 | .__extendsfxf2 => internIntrinsicType(wasm, &.{.f32_type}, .f80), | ||
| 4472 | .__extendxftf2 => internIntrinsicType(wasm, &.{.f80_type}, .f128), | ||
| 4473 | .__fabsh => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4474 | .__fabsx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4475 | .__fixdfdi => internIntrinsicType(wasm, &.{.f64_type}, .i64), | ||
| 4476 | .__fixdfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f64_type }, .void), | ||
| 4477 | .__fixdfsi => internIntrinsicType(wasm, &.{.f64_type}, .i32), | ||
| 4478 | .__fixdfti => internIntrinsicType(wasm, &.{.f64_type}, .i128), | ||
| 4479 | .__fixhfdi => internIntrinsicType(wasm, &.{.f16_type}, .i64), | ||
| 4480 | .__fixhfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f16_type }, .void), | ||
| 4481 | .__fixhfsi => internIntrinsicType(wasm, &.{.f16_type}, .i32), | ||
| 4482 | .__fixhfti => internIntrinsicType(wasm, &.{.f16_type}, .i128), | ||
| 4483 | .__fixsfdi => internIntrinsicType(wasm, &.{.f32_type}, .i64), | ||
| 4484 | .__fixsfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f32_type }, .void), | ||
| 4485 | .__fixsfsi => internIntrinsicType(wasm, &.{.f32_type}, .i32), | ||
| 4486 | .__fixsfti => internIntrinsicType(wasm, &.{.f32_type}, .i128), | ||
| 4487 | .__fixtfdi => internIntrinsicType(wasm, &.{.f128_type}, .i64), | ||
| 4488 | .__fixtfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f128_type }, .void), | ||
| 4489 | .__fixtfsi => internIntrinsicType(wasm, &.{.f128_type}, .i32), | ||
| 4490 | .__fixtfti => internIntrinsicType(wasm, &.{.f128_type}, .i128), | ||
| 4491 | .__fixunsdfdi => internIntrinsicType(wasm, &.{.f64_type}, .u64), | ||
| 4492 | .__fixunsdfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f64_type }, .void), | ||
| 4493 | .__fixunsdfsi => internIntrinsicType(wasm, &.{.f64_type}, .u32), | ||
| 4494 | .__fixunsdfti => internIntrinsicType(wasm, &.{.f64_type}, .u128), | ||
| 4495 | .__fixunshfdi => internIntrinsicType(wasm, &.{.f16_type}, .u64), | ||
| 4496 | .__fixunshfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f16_type }, .void), | ||
| 4497 | .__fixunshfsi => internIntrinsicType(wasm, &.{.f16_type}, .u32), | ||
| 4498 | .__fixunshfti => internIntrinsicType(wasm, &.{.f16_type}, .u128), | ||
| 4499 | .__fixunssfdi => internIntrinsicType(wasm, &.{.f32_type}, .u64), | ||
| 4500 | .__fixunssfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f32_type }, .void), | ||
| 4501 | .__fixunssfsi => internIntrinsicType(wasm, &.{.f32_type}, .u32), | ||
| 4502 | .__fixunssfti => internIntrinsicType(wasm, &.{.f32_type}, .u128), | ||
| 4503 | .__fixunstfdi => internIntrinsicType(wasm, &.{.f128_type}, .u64), | ||
| 4504 | .__fixunstfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f128_type }, .void), | ||
| 4505 | .__fixunstfsi => internIntrinsicType(wasm, &.{.f128_type}, .u32), | ||
| 4506 | .__fixunstfti => internIntrinsicType(wasm, &.{.f128_type}, .u128), | ||
| 4507 | .__fixunsxfdi => internIntrinsicType(wasm, &.{.f80_type}, .u64), | ||
| 4508 | .__fixunsxfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f80_type }, .void), | ||
| 4509 | .__fixunsxfsi => internIntrinsicType(wasm, &.{.f80_type}, .u32), | ||
| 4510 | .__fixunsxfti => internIntrinsicType(wasm, &.{.f80_type}, .u128), | ||
| 4511 | .__fixxfdi => internIntrinsicType(wasm, &.{.f80_type}, .i64), | ||
| 4512 | .__fixxfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f80_type }, .void), | ||
| 4513 | .__fixxfsi => internIntrinsicType(wasm, &.{.f80_type}, .i32), | ||
| 4514 | .__fixxfti => internIntrinsicType(wasm, &.{.f80_type}, .i128), | ||
| 4515 | .__floatdidf => internIntrinsicType(wasm, &.{.i64_type}, .f64), | ||
| 4516 | .__floatdihf => internIntrinsicType(wasm, &.{.i64_type}, .f16), | ||
| 4517 | .__floatdisf => internIntrinsicType(wasm, &.{.i64_type}, .f32), | ||
| 4518 | .__floatditf => internIntrinsicType(wasm, &.{.i64_type}, .f128), | ||
| 4519 | .__floatdixf => internIntrinsicType(wasm, &.{.i64_type}, .f80), | ||
| 4520 | .__floateidf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f64), | ||
| 4521 | .__floateihf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f16), | ||
| 4522 | .__floateisf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f32), | ||
| 4523 | .__floateitf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f128), | ||
| 4524 | .__floateixf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f80), | ||
| 4525 | .__floatsidf => internIntrinsicType(wasm, &.{.i32_type}, .f64), | ||
| 4526 | .__floatsihf => internIntrinsicType(wasm, &.{.i32_type}, .f16), | ||
| 4527 | .__floatsisf => internIntrinsicType(wasm, &.{.i32_type}, .f32), | ||
| 4528 | .__floatsitf => internIntrinsicType(wasm, &.{.i32_type}, .f128), | ||
| 4529 | .__floatsixf => internIntrinsicType(wasm, &.{.i32_type}, .f80), | ||
| 4530 | .__floattidf => internIntrinsicType(wasm, &.{.i128_type}, .f64), | ||
| 4531 | .__floattihf => internIntrinsicType(wasm, &.{.i128_type}, .f16), | ||
| 4532 | .__floattisf => internIntrinsicType(wasm, &.{.i128_type}, .f32), | ||
| 4533 | .__floattitf => internIntrinsicType(wasm, &.{.i128_type}, .f128), | ||
| 4534 | .__floattixf => internIntrinsicType(wasm, &.{.i128_type}, .f80), | ||
| 4535 | .__floatundidf => internIntrinsicType(wasm, &.{.u64_type}, .f64), | ||
| 4536 | .__floatundihf => internIntrinsicType(wasm, &.{.u64_type}, .f16), | ||
| 4537 | .__floatundisf => internIntrinsicType(wasm, &.{.u64_type}, .f32), | ||
| 4538 | .__floatunditf => internIntrinsicType(wasm, &.{.u64_type}, .f128), | ||
| 4539 | .__floatundixf => internIntrinsicType(wasm, &.{.u64_type}, .f80), | ||
| 4540 | .__floatuneidf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f64), | ||
| 4541 | .__floatuneihf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f16), | ||
| 4542 | .__floatuneisf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f32), | ||
| 4543 | .__floatuneitf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f128), | ||
| 4544 | .__floatuneixf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f80), | ||
| 4545 | .__floatunsidf => internIntrinsicType(wasm, &.{.u32_type}, .f64), | ||
| 4546 | .__floatunsihf => internIntrinsicType(wasm, &.{.u32_type}, .f16), | ||
| 4547 | .__floatunsisf => internIntrinsicType(wasm, &.{.u32_type}, .f32), | ||
| 4548 | .__floatunsitf => internIntrinsicType(wasm, &.{.u32_type}, .f128), | ||
| 4549 | .__floatunsixf => internIntrinsicType(wasm, &.{.u32_type}, .f80), | ||
| 4550 | .__floatuntidf => internIntrinsicType(wasm, &.{.u128_type}, .f64), | ||
| 4551 | .__floatuntihf => internIntrinsicType(wasm, &.{.u128_type}, .f16), | ||
| 4552 | .__floatuntisf => internIntrinsicType(wasm, &.{.u128_type}, .f32), | ||
| 4553 | .__floatuntitf => internIntrinsicType(wasm, &.{.u128_type}, .f128), | ||
| 4554 | .__floatuntixf => internIntrinsicType(wasm, &.{.u128_type}, .f80), | ||
| 4555 | .__floorh => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4556 | .__floorx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4557 | .__fmah => internIntrinsicType(wasm, &.{ .f16_type, .f16_type, .f16_type }, .f16), | ||
| 4558 | .__fmax => internIntrinsicType(wasm, &.{ .f80_type, .f80_type, .f80_type }, .f80), | ||
| 4559 | .__fmaxh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), | ||
| 4560 | .__fmaxx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), | ||
| 4561 | .__fminh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), | ||
| 4562 | .__fminx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), | ||
| 4563 | .__fmodh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), | ||
| 4564 | .__fmodx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), | ||
| 4565 | .__getf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), | ||
| 4566 | .__gexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), | ||
| 4567 | .__gttf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), | ||
| 4568 | .__gtxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), | ||
| 4569 | .__letf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), | ||
| 4570 | .__lexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), | ||
| 4571 | .__log10h => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4572 | .__log10x => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4573 | .__log2h => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4574 | .__log2x => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4575 | .__logh => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4576 | .__logx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4577 | .__lshrti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128), | ||
| 4578 | .__lttf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), | ||
| 4579 | .__ltxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), | ||
| 4580 | .__modei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), | ||
| 4581 | .__modti3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128), | ||
| 4582 | .__mulhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), | ||
| 4583 | .__mulodi4 => internIntrinsicType(wasm, &.{ .i64_type, .i64_type, .usize_type }, .i64), | ||
| 4584 | .__muloti4 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type, .usize_type }, .i128), | ||
| 4585 | .__multf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), | ||
| 4586 | .__multi3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128), | ||
| 4587 | .__mulxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), | ||
| 4588 | .__netf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), | ||
| 4589 | .__nexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), | ||
| 4590 | .__roundh => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4591 | .__roundx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4592 | .__sinh => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4593 | .__sinx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4594 | .__sqrth => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4595 | .__sqrtx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4596 | .__subhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), | ||
| 4597 | .__subtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), | ||
| 4598 | .__subxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), | ||
| 4599 | .__tanh => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4600 | .__tanx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4601 | .__trunch => internIntrinsicType(wasm, &.{.f16_type}, .f16), | ||
| 4602 | .__truncsfhf2 => internIntrinsicType(wasm, &.{.f32_type}, .f16), | ||
| 4603 | .__trunctfdf2 => internIntrinsicType(wasm, &.{.f128_type}, .f64), | ||
| 4604 | .__trunctfhf2 => internIntrinsicType(wasm, &.{.f128_type}, .f16), | ||
| 4605 | .__trunctfsf2 => internIntrinsicType(wasm, &.{.f128_type}, .f32), | ||
| 4606 | .__trunctfxf2 => internIntrinsicType(wasm, &.{.f128_type}, .f80), | ||
| 4607 | .__truncx => internIntrinsicType(wasm, &.{.f80_type}, .f80), | ||
| 4608 | .__truncxfdf2 => internIntrinsicType(wasm, &.{.f80_type}, .f64), | ||
| 4609 | .__truncxfhf2 => internIntrinsicType(wasm, &.{.f80_type}, .f16), | ||
| 4610 | .__truncxfsf2 => internIntrinsicType(wasm, &.{.f80_type}, .f32), | ||
| 4611 | .__udivei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), | ||
| 4612 | .__udivti3 => internIntrinsicType(wasm, &.{ .u128_type, .u128_type }, .u128), | ||
| 4613 | .__umodei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), | ||
| 4614 | .__umodti3 => internIntrinsicType(wasm, &.{ .u128_type, .u128_type }, .u128), | ||
| 4615 | .ceilq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4616 | .cos => internIntrinsicType(wasm, &.{.f64_type}, .f64), | ||
| 4617 | .cosf => internIntrinsicType(wasm, &.{.f32_type}, .f32), | ||
| 4618 | .cosq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4619 | .exp => internIntrinsicType(wasm, &.{.f64_type}, .f64), | ||
| 4620 | .exp2 => internIntrinsicType(wasm, &.{.f64_type}, .f64), | ||
| 4621 | .exp2f => internIntrinsicType(wasm, &.{.f32_type}, .f32), | ||
| 4622 | .exp2q => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4623 | .expf => internIntrinsicType(wasm, &.{.f32_type}, .f32), | ||
| 4624 | .expq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4625 | .fabsq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4626 | .floorq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4627 | .fma => internIntrinsicType(wasm, &.{ .f64_type, .f64_type, .f64_type }, .f64), | ||
| 4628 | .fmaf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type, .f32_type }, .f32), | ||
| 4629 | .fmaq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type, .f128_type }, .f128), | ||
| 4630 | .fmax => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), | ||
| 4631 | .fmaxf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), | ||
| 4632 | .fmaxq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), | ||
| 4633 | .fmin => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), | ||
| 4634 | .fminf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), | ||
| 4635 | .fminq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), | ||
| 4636 | .fmod => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), | ||
| 4637 | .fmodf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), | ||
| 4638 | .fmodq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), | ||
| 4639 | .log => internIntrinsicType(wasm, &.{.f64_type}, .f64), | ||
| 4640 | .log10 => internIntrinsicType(wasm, &.{.f64_type}, .f64), | ||
| 4641 | .log10f => internIntrinsicType(wasm, &.{.f32_type}, .f32), | ||
| 4642 | .log10q => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4643 | .log2 => internIntrinsicType(wasm, &.{.f64_type}, .f64), | ||
| 4644 | .log2f => internIntrinsicType(wasm, &.{.f32_type}, .f32), | ||
| 4645 | .log2q => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4646 | .logf => internIntrinsicType(wasm, &.{.f32_type}, .f32), | ||
| 4647 | .logq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4648 | .roundq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4649 | .sin => internIntrinsicType(wasm, &.{.f64_type}, .f64), | ||
| 4650 | .sinf => internIntrinsicType(wasm, &.{.f32_type}, .f32), | ||
| 4651 | .sinq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4652 | .sqrtq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4653 | .tan => internIntrinsicType(wasm, &.{.f64_type}, .f64), | ||
| 4654 | .tanf => internIntrinsicType(wasm, &.{.f32_type}, .f32), | ||
| 4655 | .tanq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4656 | .truncq => internIntrinsicType(wasm, &.{.f128_type}, .f128), | ||
| 4657 | .memcpy => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type }, .usize), | ||
| 4658 | .memmove => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type }, .usize), | ||
| 4659 | .memset => internIntrinsicType(wasm, &.{ .usize_type, .i32_type, .usize_type }, .usize), | ||
| 4660 | .__addo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool), | ||
| 4661 | .__subo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool), | ||
| 4662 | .__cmp_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .i8), | ||
| 4663 | .__and_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void), | ||
| 4664 | .__or_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void), | ||
| 4665 | .__xor_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void), | ||
| 4666 | .__not_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void), | ||
| 4667 | .__shlo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type, .bool_type, .u16_type }, .bool), | ||
| 4668 | .__shr_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type, .bool_type, .u16_type }, .void), | ||
| 4669 | .__clz_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16), | ||
| 4670 | .__ctz_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16), | ||
| 4671 | .__popcount_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16), | ||
| 4672 | .__bitreverse_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void), | ||
| 4673 | .__byteswap_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void), | ||
| 4674 | .__mulo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool), | ||
| 4675 | .__abs_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type }, .void), | ||
| 4676 | }; | ||
| 4677 | } | ||
| 4678 | |||
| 3956 | pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr { | 4679 | pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr { |
| 3957 | const gpa = wasm.base.comp.gpa; | 4680 | const gpa = wasm.base.comp.gpa; |
| 3958 | // We can't use string table deduplication here since these expressions can | 4681 | // We can't use string table deduplication here since these expressions can |
| ... | @@ -3972,64 +4695,63 @@ pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error | ... | @@ -3972,64 +4695,63 @@ pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error |
| 3972 | }; | 4695 | }; |
| 3973 | } | 4696 | } |
| 3974 | 4697 | ||
| 3975 | pub fn uavSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex { | 4698 | pub fn addNavReloc( |
| 3976 | const comp = wasm.base.comp; | 4699 | wasm: *Wasm, |
| 3977 | assert(comp.config.output_mode == .Obj); | 4700 | reloc_offset: usize, |
| 3978 | const gpa = comp.gpa; | 4701 | nav_index: InternPool.Nav.Index, |
| 3979 | const name = try wasm.internStringFmt("__anon_{d}", .{@backingInt(ip_index)}); | 4702 | nav_ty: Zcu.Type, |
| 3980 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | 4703 | addend: u32, |
| 3981 | gop.value_ptr.* = {}; | 4704 | ) !void { |
| 3982 | return @fromBackingInt(@intCast(gop.index)); | ||
| 3983 | } | ||
| 3984 | |||
| 3985 | pub fn navSymbolIndex(wasm: *Wasm, nav_index: InternPool.Nav.Index) Allocator.Error!SymbolTableIndex { | ||
| 3986 | const comp = wasm.base.comp; | 4705 | const comp = wasm.base.comp; |
| 3987 | assert(comp.config.output_mode == .Obj); | ||
| 3988 | const zcu = comp.zcu.?; | 4706 | const zcu = comp.zcu.?; |
| 3989 | const ip = &zcu.intern_pool; | 4707 | const ip = &zcu.intern_pool; |
| 3990 | const gpa = comp.gpa; | 4708 | const gpa = comp.gpa; |
| 3991 | const nav = ip.getNav(nav_index); | ||
| 3992 | const name = try wasm.internString(nav.fqn.toSlice(ip)); | ||
| 3993 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | ||
| 3994 | gop.value_ptr.* = {}; | ||
| 3995 | return @fromBackingInt(@intCast(gop.index)); | ||
| 3996 | } | ||
| 3997 | 4709 | ||
| 3998 | pub fn errorNameTableSymbolIndex(wasm: *Wasm) Allocator.Error!SymbolTableIndex { | 4710 | const is_obj = comp.config.output_mode == .Obj; |
| 3999 | const comp = wasm.base.comp; | ||
| 4000 | assert(comp.config.output_mode == .Obj); | ||
| 4001 | const gpa = comp.gpa; | ||
| 4002 | const gop = try wasm.symbol_table.getOrPut(gpa, wasm.preloaded_strings.__zig_error_name_table); | ||
| 4003 | gop.value_ptr.* = {}; | ||
| 4004 | return @fromBackingInt(@intCast(gop.index)); | ||
| 4005 | } | ||
| 4006 | |||
| 4007 | pub fn stackPointerSymbolIndex(wasm: *Wasm) Allocator.Error!SymbolTableIndex { | ||
| 4008 | const comp = wasm.base.comp; | ||
| 4009 | assert(comp.config.output_mode == .Obj); | ||
| 4010 | const gpa = comp.gpa; | ||
| 4011 | const gop = try wasm.symbol_table.getOrPut(gpa, wasm.preloaded_strings.__stack_pointer); | ||
| 4012 | gop.value_ptr.* = {}; | ||
| 4013 | return @fromBackingInt(@intCast(gop.index)); | ||
| 4014 | } | ||
| 4015 | |||
| 4016 | pub fn tagTableIndexSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex { | ||
| 4017 | const comp = wasm.base.comp; | ||
| 4018 | assert(comp.config.output_mode == .Obj); | ||
| 4019 | const gpa = comp.gpa; | ||
| 4020 | const name = try wasm.internStringFmt("__zig_tag_name_{d}", .{ip_index}); | ||
| 4021 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | ||
| 4022 | gop.value_ptr.* = {}; | ||
| 4023 | return @fromBackingInt(@intCast(gop.index)); | ||
| 4024 | } | ||
| 4025 | 4711 | ||
| 4026 | pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableIndex { | 4712 | if (nav_ty.zigTypeTag(zcu) == .@"fn") { |
| 4027 | const comp = wasm.base.comp; | 4713 | const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); |
| 4028 | assert(comp.config.output_mode == .Obj); | 4714 | if (!gop.found_existing) gop.value_ptr.* = {}; |
| 4029 | const gpa = comp.gpa; | 4715 | if (is_obj) { |
| 4030 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | 4716 | assert(addend == 0); |
| 4031 | gop.value_ptr.* = {}; | 4717 | try wasm.zcu_relocations.append(gpa, .{ |
| 4032 | return @fromBackingInt(@intCast(gop.index)); | 4718 | .offset = @intCast(reloc_offset), |
| 4719 | .pointee = .{ .function_nav = nav_index }, | ||
| 4720 | .tag = switch (wasm.pointerSize()) { | ||
| 4721 | 4 => .table_index_i32, | ||
| 4722 | 8 => .table_index_i64, | ||
| 4723 | else => unreachable, | ||
| 4724 | }, | ||
| 4725 | .addend = 0, | ||
| 4726 | }); | ||
| 4727 | } else { | ||
| 4728 | try wasm.func_table_fixups.append(gpa, .{ | ||
| 4729 | .nav_index = nav_index, | ||
| 4730 | .offset = @intCast(reloc_offset), | ||
| 4731 | }); | ||
| 4732 | } | ||
| 4733 | } else { | ||
| 4734 | if (is_obj) { | ||
| 4735 | if (ip.getNav(nav_index).getExtern(ip) == null) _ = try wasm.refNavObj(nav_index); | ||
| 4736 | try wasm.zcu_relocations.append(gpa, .{ | ||
| 4737 | .offset = @intCast(reloc_offset), | ||
| 4738 | .pointee = .{ .data_nav = nav_index }, | ||
| 4739 | .tag = switch (wasm.pointerSize()) { | ||
| 4740 | 4 => .memory_addr_i32, | ||
| 4741 | 8 => .memory_addr_i64, | ||
| 4742 | else => unreachable, | ||
| 4743 | }, | ||
| 4744 | .addend = @intCast(addend), | ||
| 4745 | }); | ||
| 4746 | } else { | ||
| 4747 | try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); | ||
| 4748 | wasm.nav_fixups.appendAssumeCapacity(.{ | ||
| 4749 | .nav_index = nav_index, | ||
| 4750 | .offset = @intCast(reloc_offset), | ||
| 4751 | .addend = addend, | ||
| 4752 | }); | ||
| 4753 | } | ||
| 4754 | } | ||
| 4033 | } | 4755 | } |
| 4034 | 4756 | ||
| 4035 | pub fn addUavReloc( | 4757 | pub fn addUavReloc( |
| ... | @@ -4057,12 +4779,12 @@ pub fn addUavReloc( | ... | @@ -4057,12 +4779,12 @@ pub fn addUavReloc( |
| 4057 | if (comp.config.output_mode == .Obj) { | 4779 | if (comp.config.output_mode == .Obj) { |
| 4058 | const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val); | 4780 | const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val); |
| 4059 | if (!gop.found_existing) gop.value_ptr.* = undefined; // to avoid recursion, `ZcuDataStarts` will lower the value later | 4781 | if (!gop.found_existing) gop.value_ptr.* = undefined; // to avoid recursion, `ZcuDataStarts` will lower the value later |
| 4060 | try wasm.out_relocs.append(gpa, .{ | 4782 | try wasm.zcu_relocations.append(gpa, .{ |
| 4061 | .offset = @intCast(reloc_offset), | 4783 | .offset = @intCast(reloc_offset), |
| 4062 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav_val) }, | 4784 | .pointee = .{ .data_uav = uav_val }, |
| 4063 | .tag = switch (wasm.pointerSize()) { | 4785 | .tag = switch (wasm.pointerSize()) { |
| 4064 | 32 => .memory_addr_i32, | 4786 | 4 => .memory_addr_i32, |
| 4065 | 64 => .memory_addr_i64, | 4787 | 8 => .memory_addr_i64, |
| 4066 | else => unreachable, | 4788 | else => unreachable, |
| 4067 | }, | 4789 | }, |
| 4068 | .addend = @intCast(addend), | 4790 | .addend = @intCast(addend), |
| ... | @@ -4085,7 +4807,7 @@ pub fn addUavReloc( | ... | @@ -4085,7 +4807,7 @@ pub fn addUavReloc( |
| 4085 | pub fn refNavObj(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsObjIndex { | 4807 | pub fn refNavObj(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsObjIndex { |
| 4086 | const comp = wasm.base.comp; | 4808 | const comp = wasm.base.comp; |
| 4087 | const gpa = comp.gpa; | 4809 | const gpa = comp.gpa; |
| 4088 | assert(comp.config.output_mode != .Obj); | 4810 | assert(comp.config.output_mode == .Obj); |
| 4089 | const gop = try wasm.navs_obj.getOrPut(gpa, nav_index); | 4811 | const gop = try wasm.navs_obj.getOrPut(gpa, nav_index); |
| 4090 | if (!gop.found_existing) gop.value_ptr.* = .{ | 4812 | if (!gop.found_existing) gop.value_ptr.* = .{ |
| 4091 | // Lowering the value is delayed to avoid recursion. | 4813 | // Lowering the value is delayed to avoid recursion. |
| ... | @@ -4113,7 +4835,7 @@ pub fn refNavExe(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsExeIndex { | ... | @@ -4113,7 +4835,7 @@ pub fn refNavExe(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsExeIndex { |
| 4113 | } | 4835 | } |
| 4114 | 4836 | ||
| 4115 | /// Asserts it is called after `Flush.data_segments` is fully populated and sorted. | 4837 | /// Asserts it is called after `Flush.data_segments` is fully populated and sorted. |
| 4116 | pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { | 4838 | pub fn uavAddr(wasm: *const Wasm, ip_index: InternPool.Index) u32 { |
| 4117 | assert(wasm.flush_buffer.memory_layout_finished); | 4839 | assert(wasm.flush_buffer.memory_layout_finished); |
| 4118 | const comp = wasm.base.comp; | 4840 | const comp = wasm.base.comp; |
| 4119 | assert(comp.config.output_mode != .Obj); | 4841 | assert(comp.config.output_mode != .Obj); |
| ... | @@ -4123,7 +4845,7 @@ pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { | ... | @@ -4123,7 +4845,7 @@ pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { |
| 4123 | } | 4845 | } |
| 4124 | 4846 | ||
| 4125 | /// Asserts it is called after `Flush.data_segments` is fully populated and sorted. | 4847 | /// Asserts it is called after `Flush.data_segments` is fully populated and sorted. |
| 4126 | pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { | 4848 | pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 { |
| 4127 | assert(wasm.flush_buffer.memory_layout_finished); | 4849 | assert(wasm.flush_buffer.memory_layout_finished); |
| 4128 | const comp = wasm.base.comp; | 4850 | const comp = wasm.base.comp; |
| 4129 | assert(comp.config.output_mode != .Obj); | 4851 | assert(comp.config.output_mode != .Obj); |
| ... | @@ -4139,23 +4861,34 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { | ... | @@ -4139,23 +4861,34 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { |
| 4139 | .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| { | 4861 | .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| { |
| 4140 | if (wasm.object_data_imports.getPtr(symbol_name)) |import| { | 4862 | if (wasm.object_data_imports.getPtr(symbol_name)) |import| { |
| 4141 | switch (import.resolution.unpack(wasm)) { | 4863 | switch (import.resolution.unpack(wasm)) { |
| 4142 | .unresolved => unreachable, | 4864 | .unresolved => {}, |
| 4143 | .object => |object_data_index| { | 4865 | .object => |object_data_index| { |
| 4144 | const object_data = object_data_index.ptr(wasm); | 4866 | const object_data = object_data_index.ptr(wasm); |
| 4145 | const ds_id: DataSegmentId = .fromObjectDataSegment(wasm, object_data.segment); | 4867 | const ds_id: DataSegmentId = .fromObjectDataSegment(wasm, object_data.segment); |
| 4146 | const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?; | 4868 | const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?; |
| 4147 | return segment_base_addr + object_data.offset; | 4869 | return segment_base_addr + object_data.offset; |
| 4148 | }, | 4870 | }, |
| 4149 | .__zig_error_names => @panic("TODO"), | 4871 | .__heap_base, |
| 4150 | .__zig_error_name_table => @panic("TODO"), | 4872 | .__heap_end, |
| 4151 | .__heap_base => @panic("TODO"), | 4873 | .uav_exe, |
| 4152 | .__heap_end => @panic("TODO"), | 4874 | .nav_exe, |
| 4153 | .uav_exe => @panic("TODO"), | 4875 | => { |
| 4154 | .uav_obj => @panic("TODO"), | 4876 | const data_loc = import.resolution.dataLoc(wasm); |
| 4155 | .nav_exe => @panic("TODO"), | 4877 | return wasm.flush_buffer.data_segments.get(data_loc.segment).? + data_loc.offset; |
| 4156 | .nav_obj => @panic("TODO"), | 4878 | }, |
| 4879 | .__zig_error_names, | ||
| 4880 | .__zig_error_name_table, | ||
| 4881 | .__zig_tag_names, | ||
| 4882 | .__zig_tag_name_table, | ||
| 4883 | .uav_obj, | ||
| 4884 | .nav_obj, | ||
| 4885 | => unreachable, | ||
| 4157 | } | 4886 | } |
| 4158 | } | 4887 | } |
| 4888 | if (wasm.flush_buffer.data_exports.get(symbol_name)) |symbol| { | ||
| 4889 | const data_loc = symbol.resolution.dataLoc(wasm); | ||
| 4890 | return wasm.flush_buffer.data_segments.get(data_loc.segment).? + data_loc.offset; | ||
| 4891 | } | ||
| 4159 | }, | 4892 | }, |
| 4160 | else => {}, | 4893 | else => {}, |
| 4161 | } | 4894 | } |
| ... | @@ -4177,8 +4910,12 @@ pub fn tagIndexTableAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { | ... | @@ -4177,8 +4910,12 @@ pub fn tagIndexTableAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { |
| 4177 | assert(comp.config.output_mode != .Obj); | 4910 | assert(comp.config.output_mode != .Obj); |
| 4178 | const f = &wasm.flush_buffer; | 4911 | const f = &wasm.flush_buffer; |
| 4179 | const table_base_addr = f.data_segments.get(.__zig_tag_name_table).?; | 4912 | const table_base_addr = f.data_segments.get(.__zig_tag_name_table).?; |
| 4180 | const table_index = f.enum_tag_name_table.get(ip_index).?; | 4913 | return table_base_addr + wasm.tagIndexTableOffset(ip_index); |
| 4181 | return table_base_addr + table_index * 8; | 4914 | } |
| 4915 | |||
| 4916 | pub fn tagIndexTableOffset(wasm: *const Wasm, ip_index: InternPool.Index) u32 { | ||
| 4917 | const table_index = wasm.flush_buffer.enum_tag_name_table.get(ip_index).?; | ||
| 4918 | return table_index * wasm.pointerSize() * 2; | ||
| 4182 | } | 4919 | } |
| 4183 | 4920 | ||
| 4184 | fn convertZcuFnType( | 4921 | fn convertZcuFnType( |
| ... | @@ -4255,7 +4992,7 @@ pub fn isBss(wasm: *const Wasm, optional_name: OptionalString) bool { | ... | @@ -4255,7 +4992,7 @@ pub fn isBss(wasm: *const Wasm, optional_name: OptionalString) bool { |
| 4255 | /// those entries. | 4992 | /// those entries. |
| 4256 | fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj { | 4993 | fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj { |
| 4257 | const code_start: u32 = @intCast(wasm.string_bytes.items.len); | 4994 | const code_start: u32 = @intCast(wasm.string_bytes.items.len); |
| 4258 | const relocs_start: u32 = @intCast(wasm.out_relocs.len); | 4995 | const relocs_start: u32 = @intCast(wasm.zcu_relocations.len); |
| 4259 | const uav_fixups_start: u32 = @intCast(wasm.uav_fixups.items.len); | 4996 | const uav_fixups_start: u32 = @intCast(wasm.uav_fixups.items.len); |
| 4260 | const nav_fixups_start: u32 = @intCast(wasm.nav_fixups.items.len); | 4997 | const nav_fixups_start: u32 = @intCast(wasm.nav_fixups.items.len); |
| 4261 | const func_table_fixups_start: u32 = @intCast(wasm.func_table_fixups.items.len); | 4998 | const func_table_fixups_start: u32 = @intCast(wasm.func_table_fixups.items.len); |
| ... | @@ -4271,8 +5008,9 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu | ... | @@ -4271,8 +5008,9 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu |
| 4271 | } | 5008 | } |
| 4272 | 5009 | ||
| 4273 | const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start); | 5010 | const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start); |
| 4274 | const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start); | 5011 | const relocs_len: u32 = @intCast(wasm.zcu_relocations.len - relocs_start); |
| 4275 | const any_fixups = | 5012 | const any_fixups = |
| 5013 | relocs_len != 0 or | ||
| 4276 | uav_fixups_start != wasm.uav_fixups.items.len or | 5014 | uav_fixups_start != wasm.uav_fixups.items.len or |
| 4277 | nav_fixups_start != wasm.nav_fixups.items.len or | 5015 | nav_fixups_start != wasm.nav_fixups.items.len or |
| 4278 | func_table_fixups_start != wasm.func_table_fixups.items.len; | 5016 | func_table_fixups_start != wasm.func_table_fixups.items.len; |
src/link/Wasm/Flush.zig+1114-131| ... | @@ -7,7 +7,6 @@ const Object = @import("Object.zig"); | ... | @@ -7,7 +7,6 @@ const Object = @import("Object.zig"); |
| 7 | const Zcu = @import("../../Zcu.zig"); | 7 | const Zcu = @import("../../Zcu.zig"); |
| 8 | const Alignment = Wasm.Alignment; | 8 | const Alignment = Wasm.Alignment; |
| 9 | const String = Wasm.String; | 9 | const String = Wasm.String; |
| 10 | const Relocation = Wasm.Relocation; | ||
| 11 | const InternPool = @import("../../InternPool.zig"); | 10 | const InternPool = @import("../../InternPool.zig"); |
| 12 | const Mir = @import("../../codegen/wasm/Mir.zig"); | 11 | const Mir = @import("../../codegen/wasm/Mir.zig"); |
| 13 | 12 | ||
| ... | @@ -33,8 +32,13 @@ data_segment_groups: ArrayList(DataSegmentGroup) = .empty, | ... | @@ -33,8 +32,13 @@ data_segment_groups: ArrayList(DataSegmentGroup) = .empty, |
| 33 | binary_bytes: ArrayList(u8) = .empty, | 32 | binary_bytes: ArrayList(u8) = .empty, |
| 34 | missing_exports: std.array_hash_map.Auto(String, void) = .empty, | 33 | missing_exports: std.array_hash_map.Auto(String, void) = .empty, |
| 35 | function_imports: std.array_hash_map.Auto(String, Wasm.FunctionImportId) = .empty, | 34 | function_imports: std.array_hash_map.Auto(String, Wasm.FunctionImportId) = .empty, |
| 35 | intrinsic_function_imports: std.array_hash_map.Auto(String, Wasm.FunctionType.Index) = .empty, | ||
| 36 | /// Function aliases emitted after function symbols. | ||
| 37 | function_export_symbols: std.array_hash_map.Auto(String, FunctionExportSymbol) = .empty, | ||
| 36 | global_imports: std.array_hash_map.Auto(String, Wasm.GlobalImportId) = .empty, | 38 | global_imports: std.array_hash_map.Auto(String, Wasm.GlobalImportId) = .empty, |
| 37 | data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty, | 39 | data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty, |
| 40 | /// Data aliases emitted after data symbols. | ||
| 41 | data_exports: std.array_hash_map.Auto(String, DataExportSymbol) = .empty, | ||
| 38 | 42 | ||
| 39 | indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty, | 43 | indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty, |
| 40 | 44 | ||
| ... | @@ -43,6 +47,9 @@ func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty, | ... | @@ -43,6 +47,9 @@ func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty, |
| 43 | 47 | ||
| 44 | enum_tag_name_table: std.array_hash_map.Auto(InternPool.Index, u32) = .empty, | 48 | enum_tag_name_table: std.array_hash_map.Auto(InternPool.Index, u32) = .empty, |
| 45 | 49 | ||
| 50 | code_relocs: std.ArrayList(Relocation) = .empty, | ||
| 51 | data_relocs: std.ArrayList(Relocation) = .empty, | ||
| 52 | |||
| 46 | /// For debug purposes only. | 53 | /// For debug purposes only. |
| 47 | memory_layout_finished: bool = false, | 54 | memory_layout_finished: bool = false, |
| 48 | 55 | ||
| ... | @@ -55,6 +62,74 @@ pub const FuncTypeIndex = enum(u32) { | ... | @@ -55,6 +62,74 @@ pub const FuncTypeIndex = enum(u32) { |
| 55 | } | 62 | } |
| 56 | }; | 63 | }; |
| 57 | 64 | ||
| 65 | /// Index into SYMTAB_FUNCTION. | ||
| 66 | const FunctionSymbolIndex = enum(u32) { | ||
| 67 | _, | ||
| 68 | |||
| 69 | fn fromOutputFunctionIndex(i: Wasm.OutputFunctionIndex) FunctionSymbolIndex { | ||
| 70 | return @fromBackingInt(@backingInt(i)); | ||
| 71 | } | ||
| 72 | |||
| 73 | fn fromObjectFunctionHandlingWeak(wasm: *const Wasm, index: Wasm.ObjectFunctionIndex) FunctionSymbolIndex { | ||
| 74 | return fromOutputFunctionIndex(.fromObjectFunctionHandlingWeak(wasm, index)); | ||
| 75 | } | ||
| 76 | |||
| 77 | fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) FunctionSymbolIndex { | ||
| 78 | return fromOutputFunctionIndex(.fromIpNav(wasm, nav_index)); | ||
| 79 | } | ||
| 80 | |||
| 81 | fn fromTagIndexType(wasm: *const Wasm, ip_index: InternPool.Index) FunctionSymbolIndex { | ||
| 82 | return fromOutputFunctionIndex(.fromTagIndexType(wasm, ip_index)); | ||
| 83 | } | ||
| 84 | |||
| 85 | fn fromSymbolName(wasm: *const Wasm, name: String) FunctionSymbolIndex { | ||
| 86 | const f = &wasm.flush_buffer; | ||
| 87 | if (f.function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); | ||
| 88 | if (f.intrinsic_function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast( | ||
| 89 | f.function_imports.entries.len + i, | ||
| 90 | )); | ||
| 91 | if (f.function_export_symbols.getIndex(name)) |i| return @fromBackingInt(@intCast( | ||
| 92 | f.function_imports.entries.len + f.intrinsic_function_imports.entries.len + | ||
| 93 | wasm.functions.entries.len + i, | ||
| 94 | )); | ||
| 95 | return fromOutputFunctionIndex(.fromSymbolName(wasm, name)); | ||
| 96 | } | ||
| 97 | }; | ||
| 98 | |||
| 99 | /// Index into SYMTAB_DATA. | ||
| 100 | const DataSymbolIndex = enum(u32) { | ||
| 101 | _, | ||
| 102 | |||
| 103 | fn fromOutputDataIndex(i: Wasm.OutputDataIndex) DataSymbolIndex { | ||
| 104 | return @fromBackingInt(@backingInt(i)); | ||
| 105 | } | ||
| 106 | |||
| 107 | fn fromResolution(wasm: *const Wasm, resolution: Wasm.ObjectDataImport.Resolution) DataSymbolIndex { | ||
| 108 | return fromOutputDataIndex(Wasm.OutputDataIndex.fromResolution(wasm, resolution).?); | ||
| 109 | } | ||
| 110 | |||
| 111 | fn fromObjectData(wasm: *const Wasm, index: Wasm.ObjectData.Index) DataSymbolIndex { | ||
| 112 | return fromOutputDataIndex(.fromObjectData(wasm, index)); | ||
| 113 | } | ||
| 114 | |||
| 115 | fn fromUav(wasm: *const Wasm, ip_index: InternPool.Index) DataSymbolIndex { | ||
| 116 | return fromOutputDataIndex(.fromUav(wasm, ip_index)); | ||
| 117 | } | ||
| 118 | |||
| 119 | fn fromNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) DataSymbolIndex { | ||
| 120 | return fromOutputDataIndex(.fromNav(wasm, nav_index)); | ||
| 121 | } | ||
| 122 | |||
| 123 | fn fromSymbolName(wasm: *const Wasm, name: String) DataSymbolIndex { | ||
| 124 | const f = &wasm.flush_buffer; | ||
| 125 | if (f.data_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); | ||
| 126 | if (f.data_exports.getIndex(name)) |i| return @fromBackingInt(@intCast( | ||
| 127 | f.data_imports.entries.len + wasm.datas.entries.len + i, | ||
| 128 | )); | ||
| 129 | return fromOutputDataIndex(.fromSymbolName(wasm, name)); | ||
| 130 | } | ||
| 131 | }; | ||
| 132 | |||
| 58 | /// Index into `indirect_function_table`. | 133 | /// Index into `indirect_function_table`. |
| 59 | const IndirectFunctionTableIndex = enum(u32) { | 134 | const IndirectFunctionTableIndex = enum(u32) { |
| 60 | _, | 135 | _, |
| ... | @@ -71,9 +146,8 @@ const IndirectFunctionTableIndex = enum(u32) { | ... | @@ -71,9 +146,8 @@ const IndirectFunctionTableIndex = enum(u32) { |
| 71 | return @fromBackingInt(@intCast(f.indirect_function_table.getIndex(i).?)); | 146 | return @fromBackingInt(@intCast(f.indirect_function_table.getIndex(i).?)); |
| 72 | } | 147 | } |
| 73 | 148 | ||
| 74 | fn fromZcuIndirectFunctionSetIndex(i: Wasm.ZcuIndirectFunctionSetIndex) IndirectFunctionTableIndex { | 149 | fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) IndirectFunctionTableIndex { |
| 75 | // These are the same since those are added to the table first. | 150 | return fromOutputFunctionIndex(&wasm.flush_buffer, .fromIpNav(wasm, nav_index)); |
| 76 | return @fromBackingInt(@intCast(@backingInt(i))); | ||
| 77 | } | 151 | } |
| 78 | 152 | ||
| 79 | fn toAbi(i: IndirectFunctionTableIndex) u32 { | 153 | fn toAbi(i: IndirectFunctionTableIndex) u32 { |
| ... | @@ -81,6 +155,39 @@ const IndirectFunctionTableIndex = enum(u32) { | ... | @@ -81,6 +155,39 @@ const IndirectFunctionTableIndex = enum(u32) { |
| 81 | } | 155 | } |
| 82 | }; | 156 | }; |
| 83 | 157 | ||
| 158 | const SymbolTableOffsets = struct { | ||
| 159 | function: u32, | ||
| 160 | data: u32, | ||
| 161 | global: u32, | ||
| 162 | table: u32, | ||
| 163 | }; | ||
| 164 | |||
| 165 | const FunctionExportSymbol = struct { | ||
| 166 | function_index: Wasm.FunctionIndex, | ||
| 167 | flags: Wasm.SymbolFlags, | ||
| 168 | }; | ||
| 169 | |||
| 170 | const DataExportSymbol = struct { | ||
| 171 | resolution: Wasm.ObjectDataImport.Resolution, | ||
| 172 | flags: Wasm.SymbolFlags, | ||
| 173 | }; | ||
| 174 | |||
| 175 | const Relocation = struct { | ||
| 176 | tag: Object.RelocationType, | ||
| 177 | offset: u32, | ||
| 178 | pointee: Pointee, | ||
| 179 | addend: i32, | ||
| 180 | |||
| 181 | const Pointee = union { | ||
| 182 | data: DataSymbolIndex, | ||
| 183 | type_index: FuncTypeIndex, | ||
| 184 | section: Wasm.ObjectSectionIndex, | ||
| 185 | function: FunctionSymbolIndex, | ||
| 186 | global: Wasm.GlobalIndex, | ||
| 187 | table: Wasm.TableIndex, | ||
| 188 | }; | ||
| 189 | }; | ||
| 190 | |||
| 84 | const DataSegmentGroup = struct { | 191 | const DataSegmentGroup = struct { |
| 85 | first_segment: Wasm.DataSegmentId, | 192 | first_segment: Wasm.DataSegmentId, |
| 86 | end_addr: u32, | 193 | end_addr: u32, |
| ... | @@ -90,9 +197,14 @@ pub fn clear(f: *Flush) void { | ... | @@ -90,9 +197,14 @@ pub fn clear(f: *Flush) void { |
| 90 | f.data_segments.clearRetainingCapacity(); | 197 | f.data_segments.clearRetainingCapacity(); |
| 91 | f.data_segment_groups.clearRetainingCapacity(); | 198 | f.data_segment_groups.clearRetainingCapacity(); |
| 92 | f.binary_bytes.clearRetainingCapacity(); | 199 | f.binary_bytes.clearRetainingCapacity(); |
| 200 | f.intrinsic_function_imports.clearRetainingCapacity(); | ||
| 201 | f.function_export_symbols.clearRetainingCapacity(); | ||
| 202 | f.data_exports.clearRetainingCapacity(); | ||
| 93 | f.indirect_function_table.clearRetainingCapacity(); | 203 | f.indirect_function_table.clearRetainingCapacity(); |
| 94 | f.func_types.clearRetainingCapacity(); | 204 | f.func_types.clearRetainingCapacity(); |
| 95 | f.enum_tag_name_table.clearRetainingCapacity(); | 205 | f.enum_tag_name_table.clearRetainingCapacity(); |
| 206 | f.code_relocs.clearRetainingCapacity(); | ||
| 207 | f.data_relocs.clearRetainingCapacity(); | ||
| 96 | f.memory_layout_finished = false; | 208 | f.memory_layout_finished = false; |
| 97 | } | 209 | } |
| 98 | 210 | ||
| ... | @@ -102,11 +214,16 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { | ... | @@ -102,11 +214,16 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { |
| 102 | f.binary_bytes.deinit(gpa); | 214 | f.binary_bytes.deinit(gpa); |
| 103 | f.missing_exports.deinit(gpa); | 215 | f.missing_exports.deinit(gpa); |
| 104 | f.function_imports.deinit(gpa); | 216 | f.function_imports.deinit(gpa); |
| 217 | f.intrinsic_function_imports.deinit(gpa); | ||
| 218 | f.function_export_symbols.deinit(gpa); | ||
| 105 | f.global_imports.deinit(gpa); | 219 | f.global_imports.deinit(gpa); |
| 106 | f.data_imports.deinit(gpa); | 220 | f.data_imports.deinit(gpa); |
| 221 | f.data_exports.deinit(gpa); | ||
| 107 | f.indirect_function_table.deinit(gpa); | 222 | f.indirect_function_table.deinit(gpa); |
| 108 | f.func_types.deinit(gpa); | 223 | f.func_types.deinit(gpa); |
| 109 | f.enum_tag_name_table.deinit(gpa); | 224 | f.enum_tag_name_table.deinit(gpa); |
| 225 | f.code_relocs.deinit(gpa); | ||
| 226 | f.data_relocs.deinit(gpa); | ||
| 110 | f.* = undefined; | 227 | f.* = undefined; |
| 111 | } | 228 | } |
| 112 | 229 | ||
| ... | @@ -134,48 +251,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -134,48 +251,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 134 | 251 | ||
| 135 | log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len}); | 252 | log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len}); |
| 136 | 253 | ||
| 137 | // Detect any intrinsics that were called; they need to have dependencies on the symbols marked. | ||
| 138 | // Likewise detect `@tagName` calls so those functions can be included in the output and synthesized. | ||
| 139 | for (wasm.mir_instructions.items(.tag), wasm.mir_instructions.items(.data)) |tag, *data| switch (tag) { | ||
| 140 | .call_intrinsic => { | ||
| 141 | const symbol_name = try wasm.internString(@tagName(data.intrinsic)); | ||
| 142 | const i: Wasm.FunctionImport.Index = @fromBackingInt(@intCast(wasm.object_function_imports.getIndex(symbol_name) orelse { | ||
| 143 | return diags.fail("missing compiler runtime intrinsic '{t}' (undefined linker symbol)", .{ | ||
| 144 | data.intrinsic, | ||
| 145 | }); | ||
| 146 | })); | ||
| 147 | try wasm.markFunctionImport(symbol_name, i.value(wasm), i); | ||
| 148 | log.debug("markFunctionImport intrinsic {d}={t}", .{ i, data.intrinsic }); | ||
| 149 | }, | ||
| 150 | .call_tag_index => { | ||
| 151 | assert(ip.indexToKey(data.ip_index) == .enum_type); | ||
| 152 | const gop = try wasm.zcu_funcs.getOrPut(gpa, data.ip_index); | ||
| 153 | if (!gop.found_existing) { | ||
| 154 | const int_tag_ty = Zcu.Type.fromInterned(data.ip_index).backingIntType(zcu); | ||
| 155 | gop.value_ptr.* = .{ .tag_name = .{ | ||
| 156 | .symbol_name = try wasm.internStringFmt("__zig_tag_index_{d}", .{data.ip_index}), | ||
| 157 | .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .u32, false, target), | ||
| 158 | } }; | ||
| 159 | } | ||
| 160 | try wasm.functions.put(gpa, .fromZcuFunc(wasm, @fromBackingInt(@intCast(gop.index))), {}); | ||
| 161 | }, | ||
| 162 | .enum_tag_name_table_ref => { | ||
| 163 | assert(ip.indexToKey(data.ip_index) == .enum_type); | ||
| 164 | const gop = try f.enum_tag_name_table.getOrPut(gpa, data.ip_index); | ||
| 165 | if (!gop.found_existing) { | ||
| 166 | wasm.tag_name_table_ref_count += 1; | ||
| 167 | gop.value_ptr.* = @intCast(wasm.tag_name_offs.items.len); | ||
| 168 | const tag_names = ip.loadEnumType(data.ip_index).field_names; | ||
| 169 | for (tag_names.get(ip)) |tag_name| { | ||
| 170 | const slice = tag_name.toSlice(ip); | ||
| 171 | try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len)); | ||
| 172 | try wasm.tag_name_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | }, | ||
| 176 | else => continue, | ||
| 177 | }; | ||
| 178 | |||
| 179 | { | 254 | { |
| 180 | var i = wasm.function_imports_len_prelink; | 255 | var i = wasm.function_imports_len_prelink; |
| 181 | while (i < f.function_imports.entries.len) { | 256 | while (i < f.function_imports.entries.len) { |
| ... | @@ -225,10 +300,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -225,10 +300,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 225 | log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index }); | 300 | log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index }); |
| 226 | const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?; | 301 | const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?; |
| 227 | const explicit = f.missing_exports.swapRemove(nav_export.name); | 302 | const explicit = f.missing_exports.swapRemove(nav_export.name); |
| 228 | const is_hidden = !explicit and switch (export_index.ptr(zcu).opts.visibility) { | 303 | const opts = export_index.ptr(zcu).opts; |
| 304 | const is_hidden = !explicit and switch (opts.visibility) { | ||
| 229 | .hidden => true, | 305 | .hidden => true, |
| 230 | .default, .protected => false, | 306 | .default, .protected => false, |
| 231 | }; | 307 | }; |
| 308 | if (is_obj) try f.function_export_symbols.put(gpa, nav_export.name, .{ | ||
| 309 | .function_index = function_index, | ||
| 310 | .flags = .{ | ||
| 311 | .binding = switch (opts.linkage) { | ||
| 312 | .internal => .local, | ||
| 313 | .strong => .strong, | ||
| 314 | .weak => .weak, | ||
| 315 | .link_once => @panic("TODO: COMDAT"), | ||
| 316 | }, | ||
| 317 | .visibility_hidden = is_hidden, | ||
| 318 | .exported = !is_hidden, | ||
| 319 | }, | ||
| 320 | }); | ||
| 232 | if (is_hidden) { | 321 | if (is_hidden) { |
| 233 | try wasm.hidden_function_exports.put(gpa, nav_export.name, function_index); | 322 | try wasm.hidden_function_exports.put(gpa, nav_export.name, function_index); |
| 234 | } else { | 323 | } else { |
| ... | @@ -239,17 +328,141 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -239,17 +328,141 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 239 | if (nav_export.name.toOptional() == entry_name) | 328 | if (nav_export.name.toOptional() == entry_name) |
| 240 | wasm.entry_resolution = .fromIpNav(wasm, nav_export.nav_index); | 329 | wasm.entry_resolution = .fromIpNav(wasm, nav_export.nav_index); |
| 241 | } else { | 330 | } else { |
| 242 | // This is a data export because Zcu currently has no way to | 331 | // data exports are linker symbols |
| 243 | // export wasm globals. | 332 | // explicit exports become address globals |
| 244 | _ = f.missing_exports.swapRemove(nav_export.name); | 333 | const explicit = f.missing_exports.swapRemove(nav_export.name); |
| 334 | const opts = export_index.ptr(zcu).opts; | ||
| 335 | try f.data_exports.put(gpa, nav_export.name, .{ | ||
| 336 | .resolution = .fromIpNav(wasm, nav_export.nav_index), | ||
| 337 | .flags = if (is_obj) .{ | ||
| 338 | .binding = switch (opts.linkage) { | ||
| 339 | .internal => .local, | ||
| 340 | .strong => .strong, | ||
| 341 | .weak => .weak, | ||
| 342 | .link_once => @panic("TODO: COMDAT"), | ||
| 343 | }, | ||
| 344 | .visibility_hidden = !explicit and switch (opts.visibility) { | ||
| 345 | .default => false, | ||
| 346 | .hidden => true, | ||
| 347 | .protected => false, | ||
| 348 | }, | ||
| 349 | .exported = explicit, | ||
| 350 | .tls = ip.getNav(nav_export.nav_index).resolved.?.@"threadlocal", | ||
| 351 | } else .{}, | ||
| 352 | }); | ||
| 245 | _ = f.data_imports.swapRemove(nav_export.name); | 353 | _ = f.data_imports.swapRemove(nav_export.name); |
| 246 | if (!is_obj) { | 354 | if (explicit and !is_obj) { |
| 247 | diags.addError("unable to export data symbol '{s}'; not emitting a relocatable", .{ | 355 | const global_resolution: Wasm.GlobalImport.Resolution = .fromIpNav( |
| 248 | nav_export.name.slice(wasm), | 356 | wasm, |
| 357 | nav_export.nav_index, | ||
| 358 | ); | ||
| 359 | try wasm.globals.put(gpa, global_resolution, {}); | ||
| 360 | try wasm.global_exports.append(gpa, .{ | ||
| 361 | .name = nav_export.name, | ||
| 362 | .global_index = Wasm.GlobalIndex.fromResolution(wasm, global_resolution).?, | ||
| 249 | }); | 363 | }); |
| 250 | } | 364 | } |
| 251 | } | 365 | } |
| 252 | } | 366 | } |
| 367 | // handle exported values without navs | ||
| 368 | for (wasm.uav_exports.keys(), wasm.uav_exports.values()) |uav_export, export_index| { | ||
| 369 | assert(!ip.isFunctionType(ip.typeOf(uav_export.uav_index))); | ||
| 370 | const explicit = f.missing_exports.swapRemove(uav_export.name); | ||
| 371 | const opts = export_index.ptr(zcu).opts; | ||
| 372 | try f.data_exports.put(gpa, uav_export.name, .{ | ||
| 373 | .resolution = .fromIpIndex(wasm, uav_export.uav_index), | ||
| 374 | .flags = if (is_obj) .{ | ||
| 375 | .binding = switch (opts.linkage) { | ||
| 376 | .internal => .local, | ||
| 377 | .strong => .strong, | ||
| 378 | .weak => .weak, | ||
| 379 | .link_once => @panic("TODO: COMDAT"), | ||
| 380 | }, | ||
| 381 | .visibility_hidden = !explicit and switch (opts.visibility) { | ||
| 382 | .default => false, | ||
| 383 | .hidden => true, | ||
| 384 | .protected => false, | ||
| 385 | }, | ||
| 386 | .exported = explicit, | ||
| 387 | } else .{}, | ||
| 388 | }); | ||
| 389 | _ = f.data_imports.swapRemove(uav_export.name); | ||
| 390 | if (explicit and !is_obj) { | ||
| 391 | const global_resolution: Wasm.GlobalImport.Resolution = .fromIpIndex( | ||
| 392 | wasm, | ||
| 393 | uav_export.uav_index, | ||
| 394 | ); | ||
| 395 | try wasm.globals.put(gpa, global_resolution, {}); | ||
| 396 | try wasm.global_exports.append(gpa, .{ | ||
| 397 | .name = uav_export.name, | ||
| 398 | .global_index = Wasm.GlobalIndex.fromResolution(wasm, global_resolution).?, | ||
| 399 | }); | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | // Detect any intrinsics that were called; they need to have dependencies on the symbols marked. | ||
| 404 | // Likewise detect `@tagName` calls so those functions can be included in the output and synthesized. | ||
| 405 | for (wasm.mir_instructions.items(.tag), wasm.mir_instructions.items(.data)) |tag, *data| switch (tag) { | ||
| 406 | .call_intrinsic => { | ||
| 407 | const symbol_name = try wasm.internString(@tagName(data.intrinsic)); | ||
| 408 | if (Wasm.FunctionIndex.fromSymbolName(wasm, symbol_name) == null and | ||
| 409 | !f.function_imports.contains(symbol_name)) | ||
| 410 | { | ||
| 411 | if (wasm.object_function_imports.getIndex(symbol_name)) |object_import_index| { | ||
| 412 | const i: Wasm.FunctionImport.Index = @fromBackingInt(@intCast(object_import_index)); | ||
| 413 | try wasm.markFunctionImport(symbol_name, i.value(wasm), i); | ||
| 414 | if (Wasm.FunctionIndex.fromSymbolName(wasm, symbol_name) == null) { | ||
| 415 | try f.function_imports.put(gpa, symbol_name, .fromObject(i, wasm)); | ||
| 416 | } | ||
| 417 | } else if (is_obj) { | ||
| 418 | const gop = try f.intrinsic_function_imports.getOrPut(gpa, symbol_name); | ||
| 419 | if (!gop.found_existing) gop.value_ptr.* = try wasm.intrinsicFunctionType(data.intrinsic); | ||
| 420 | } else { | ||
| 421 | return diags.fail("missing compiler runtime intrinsic '{t}' (undefined linker symbol)", .{ | ||
| 422 | data.intrinsic, | ||
| 423 | }); | ||
| 424 | } | ||
| 425 | } | ||
| 426 | }, | ||
| 427 | .call_indirect => { | ||
| 428 | const fn_info = zcu.typeToFunc(.fromInterned(data.ip_index)).?; | ||
| 429 | const type_index = wasm.getExistingFunctionType( | ||
| 430 | fn_info.cc, | ||
| 431 | fn_info.param_types.get(ip), | ||
| 432 | .fromInterned(fn_info.return_type), | ||
| 433 | fn_info.is_var_args, | ||
| 434 | target, | ||
| 435 | ).?; | ||
| 436 | try f.func_types.put(gpa, type_index, {}); | ||
| 437 | }, | ||
| 438 | .call_tag_index => { | ||
| 439 | assert(ip.indexToKey(data.ip_index) == .enum_type); | ||
| 440 | const gop = try wasm.zcu_funcs.getOrPut(gpa, data.ip_index); | ||
| 441 | if (!gop.found_existing) { | ||
| 442 | const int_tag_ty = Zcu.Type.fromInterned(data.ip_index).backingIntType(zcu); | ||
| 443 | gop.value_ptr.* = .{ .tag_name = .{ | ||
| 444 | .symbol_name = try wasm.internStringFmt("__zig_tag_index_{d}", .{data.ip_index}), | ||
| 445 | .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .u32, false, target), | ||
| 446 | } }; | ||
| 447 | } | ||
| 448 | try wasm.functions.put(gpa, .fromZcuFunc(wasm, @fromBackingInt(@intCast(gop.index))), {}); | ||
| 449 | }, | ||
| 450 | .enum_tag_name_table_ref => { | ||
| 451 | assert(ip.indexToKey(data.ip_index) == .enum_type); | ||
| 452 | const gop = try f.enum_tag_name_table.getOrPut(gpa, data.ip_index); | ||
| 453 | if (!gop.found_existing) { | ||
| 454 | wasm.tag_name_table_ref_count += 1; | ||
| 455 | gop.value_ptr.* = @intCast(wasm.tag_name_offs.items.len); | ||
| 456 | const tag_names = ip.loadEnumType(data.ip_index).field_names; | ||
| 457 | for (tag_names.get(ip)) |tag_name| { | ||
| 458 | const slice = tag_name.toSlice(ip); | ||
| 459 | try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len)); | ||
| 460 | try wasm.tag_name_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); | ||
| 461 | } | ||
| 462 | } | ||
| 463 | }, | ||
| 464 | else => continue, | ||
| 465 | }; | ||
| 253 | 466 | ||
| 254 | for (f.missing_exports.keys()) |exp_name| { | 467 | for (f.missing_exports.keys()) |exp_name| { |
| 255 | diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)}); | 468 | diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)}); |
| ... | @@ -300,7 +513,27 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -300,7 +513,27 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 300 | if (wasm.object_init_funcs.items.len > 0) { | 513 | if (wasm.object_init_funcs.items.len > 0) { |
| 301 | // Zig has no constructors so these are only for object file inputs. | 514 | // Zig has no constructors so these are only for object file inputs. |
| 302 | mem.sortUnstable(Wasm.InitFunc, wasm.object_init_funcs.items, {}, Wasm.InitFunc.lessThan); | 515 | mem.sortUnstable(Wasm.InitFunc, wasm.object_init_funcs.items, {}, Wasm.InitFunc.lessThan); |
| 303 | try wasm.functions.put(gpa, .__wasm_call_ctors, {}); | 516 | if (!is_obj) try wasm.functions.put(gpa, .__wasm_call_ctors, {}); |
| 517 | } | ||
| 518 | |||
| 519 | if (is_obj) { | ||
| 520 | try wasm.datas.ensureUnusedCapacity(gpa, wasm.uavs_obj.entries.len + wasm.navs_obj.entries.len + 4); | ||
| 521 | for (0..wasm.uavs_obj.entries.len) |i| wasm.datas.putAssumeCapacity( | ||
| 522 | .pack(wasm, .{ .uav_obj = @fromBackingInt(@intCast(i)) }), | ||
| 523 | {}, | ||
| 524 | ); | ||
| 525 | for (0..wasm.navs_obj.entries.len) |i| wasm.datas.putAssumeCapacity( | ||
| 526 | .pack(wasm, .{ .nav_obj = @fromBackingInt(@intCast(i)) }), | ||
| 527 | {}, | ||
| 528 | ); | ||
| 529 | if (wasm.error_name_table_ref_count > 0) { | ||
| 530 | wasm.datas.putAssumeCapacity(.__zig_error_names, {}); | ||
| 531 | wasm.datas.putAssumeCapacity(.__zig_error_name_table, {}); | ||
| 532 | } | ||
| 533 | if (wasm.tag_name_table_ref_count > 0) { | ||
| 534 | wasm.datas.putAssumeCapacity(.__zig_tag_names, {}); | ||
| 535 | wasm.datas.putAssumeCapacity(.__zig_tag_name_table, {}); | ||
| 536 | } | ||
| 304 | } | 537 | } |
| 305 | 538 | ||
| 306 | // Merge and order the data segments. Depends on garbage collection so that | 539 | // Merge and order the data segments. Depends on garbage collection so that |
| ... | @@ -341,14 +574,33 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -341,14 +574,33 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 341 | // dropped in __wasm_init_memory, which is registered as the start function | 574 | // dropped in __wasm_init_memory, which is registered as the start function |
| 342 | // We also initialize bss segments (using memory.fill) as part of this | 575 | // We also initialize bss segments (using memory.fill) as part of this |
| 343 | // function. | 576 | // function. |
| 344 | if (wasm.any_passive_inits) { | 577 | if (!is_obj and wasm.any_passive_inits) { |
| 345 | try wasm.addFunction(.__wasm_init_memory, &.{}, &.{}); | 578 | try wasm.addFunction(.__wasm_init_memory, &.{}, &.{}); |
| 346 | } | 579 | } |
| 347 | 580 | ||
| 348 | try wasm.tables.ensureUnusedCapacity(gpa, 1); | 581 | try wasm.tables.ensureUnusedCapacity(gpa, 1); |
| 349 | 582 | ||
| 350 | if (f.indirect_function_table.entries.len > 0) { | 583 | if (f.indirect_function_table.entries.len > 0) { |
| 351 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); | 584 | if (is_obj) { |
| 585 | const name = wasm.preloaded_strings.__indirect_function_table; | ||
| 586 | const gop = try wasm.object_table_imports.getOrPut(gpa, name); | ||
| 587 | if (!gop.found_existing) gop.value_ptr.* = .{ | ||
| 588 | .flags = .{ | ||
| 589 | .undefined = true, | ||
| 590 | .no_strip = true, | ||
| 591 | }, | ||
| 592 | .module_name = wasm.preloaded_strings.env, | ||
| 593 | .name = name, | ||
| 594 | .source_location = .zig_object_nofile, | ||
| 595 | .resolution = .unresolved, | ||
| 596 | .limits_min = 1, | ||
| 597 | .limits_max = 0, | ||
| 598 | }; | ||
| 599 | const import_index: Wasm.TableImport.Index = @fromBackingInt(@intCast(gop.index)); | ||
| 600 | try wasm.markTableImport(name, gop.value_ptr, import_index); | ||
| 601 | } else { | ||
| 602 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); | ||
| 603 | } | ||
| 352 | } | 604 | } |
| 353 | 605 | ||
| 354 | // Sort order: | 606 | // Sort order: |
| ... | @@ -449,7 +701,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -449,7 +701,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 449 | const start_addr = alignment.forward(memory_ptr); | 701 | const start_addr = alignment.forward(memory_ptr); |
| 450 | 702 | ||
| 451 | const want_new_segment = b: { | 703 | const want_new_segment = b: { |
| 452 | if (is_obj) break :b false; | 704 | if (is_obj) break :b i != 0; |
| 453 | switch (seen_tls) { | 705 | switch (seen_tls) { |
| 454 | .before => switch (category) { | 706 | .before => switch (category) { |
| 455 | .tls => { | 707 | .tls => { |
| ... | @@ -489,7 +741,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -489,7 +741,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 489 | log.debug("0x{x} {d} {s}", .{ start_addr, @backingInt(segment_id), segment_id.name(wasm) }); | 741 | log.debug("0x{x} {d} {s}", .{ start_addr, @backingInt(segment_id), segment_id.name(wasm) }); |
| 490 | memory_ptr = start_addr + size; | 742 | memory_ptr = start_addr + size; |
| 491 | } | 743 | } |
| 492 | if (category != .zero) try f.data_segment_groups.append(gpa, .{ | 744 | if (is_obj or category != .zero) try f.data_segment_groups.append(gpa, .{ |
| 493 | .first_segment = first_segment, | 745 | .first_segment = first_segment, |
| 494 | .end_addr = @intCast(memory_ptr), | 746 | .end_addr = @intCast(memory_ptr), |
| 495 | }); | 747 | }); |
| ... | @@ -555,7 +807,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -555,7 +807,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 555 | 807 | ||
| 556 | // When we have TLS GOT entries and shared memory is enabled, we must | 808 | // When we have TLS GOT entries and shared memory is enabled, we must |
| 557 | // perform runtime relocations or else we don't create the function. | 809 | // perform runtime relocations or else we don't create the function. |
| 558 | if (shared_memory and virtual_addrs.tls_base != null) { | 810 | if (!is_obj and shared_memory and virtual_addrs.tls_base != null) { |
| 559 | // This logic that checks `any_tls_relocs` is missing the part where it | 811 | // This logic that checks `any_tls_relocs` is missing the part where it |
| 560 | // also notices threadlocal globals from Zcu code. | 812 | // also notices threadlocal globals from Zcu code. |
| 561 | if (wasm.any_tls_relocs) try wasm.addFunction(.__wasm_apply_global_tls_relocs, &.{}, &.{}); | 813 | if (wasm.any_tls_relocs) try wasm.addFunction(.__wasm_apply_global_tls_relocs, &.{}, &.{}); |
| ... | @@ -582,6 +834,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -582,6 +834,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 582 | for (f.function_imports.values()) |id| { | 834 | for (f.function_imports.values()) |id| { |
| 583 | try f.func_types.put(gpa, id.functionType(wasm), {}); | 835 | try f.func_types.put(gpa, id.functionType(wasm), {}); |
| 584 | } | 836 | } |
| 837 | for (f.intrinsic_function_imports.values()) |type_index| { | ||
| 838 | try f.func_types.put(gpa, type_index, {}); | ||
| 839 | } | ||
| 585 | for (wasm.functions.keys()) |function| { | 840 | for (wasm.functions.keys()) |function| { |
| 586 | try f.func_types.put(gpa, function.typeIndex(wasm), {}); | 841 | try f.func_types.put(gpa, function.typeIndex(wasm), {}); |
| 587 | } | 842 | } |
| ... | @@ -617,7 +872,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -617,7 +872,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 617 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 872 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 618 | 873 | ||
| 619 | for (f.function_imports.values()) |id| { | 874 | for (f.function_imports.values()) |id| { |
| 620 | const module_name = id.moduleName(wasm).slice(wasm).?; | 875 | const module_name = (id.moduleName(wasm).unwrap() orelse wasm.preloaded_strings.env).slice(wasm); |
| 621 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); | 876 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); |
| 622 | try binary_bytes.appendSlice(gpa, module_name); | 877 | try binary_bytes.appendSlice(gpa, module_name); |
| 623 | 878 | ||
| ... | @@ -631,6 +886,20 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -631,6 +886,20 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 631 | } | 886 | } |
| 632 | total_imports += f.function_imports.entries.len; | 887 | total_imports += f.function_imports.entries.len; |
| 633 | 888 | ||
| 889 | for (f.intrinsic_function_imports.keys(), f.intrinsic_function_imports.values()) |name_string, type_index| { | ||
| 890 | const module_name = wasm.preloaded_strings.env.slice(wasm); | ||
| 891 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); | ||
| 892 | try binary_bytes.appendSlice(gpa, module_name); | ||
| 893 | |||
| 894 | const name = name_string.slice(wasm); | ||
| 895 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 896 | try binary_bytes.appendSlice(gpa, name); | ||
| 897 | |||
| 898 | try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.function)); | ||
| 899 | try appendLeb128(gpa, binary_bytes, @backingInt(FuncTypeIndex.fromTypeIndex(type_index, f))); | ||
| 900 | } | ||
| 901 | total_imports += f.intrinsic_function_imports.entries.len; | ||
| 902 | |||
| 634 | for (wasm.table_imports.values()) |id| { | 903 | for (wasm.table_imports.values()) |id| { |
| 635 | const table_import = id.value(wasm); | 904 | const table_import = id.value(wasm); |
| 636 | const module_name = table_import.module_name.slice(wasm); | 905 | const module_name = table_import.module_name.slice(wasm); |
| ... | @@ -662,7 +931,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -662,7 +931,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 662 | } | 931 | } |
| 663 | 932 | ||
| 664 | for (f.global_imports.values()) |id| { | 933 | for (f.global_imports.values()) |id| { |
| 665 | const module_name = id.moduleName(wasm).slice(wasm).?; | 934 | const module_name = (id.moduleName(wasm).unwrap() orelse wasm.preloaded_strings.env).slice(wasm); |
| 666 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); | 935 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); |
| 667 | try binary_bytes.appendSlice(gpa, module_name); | 936 | try binary_bytes.appendSlice(gpa, module_name); |
| 668 | 937 | ||
| ... | @@ -726,12 +995,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -726,12 +995,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 726 | for (wasm.globals.keys()) |global_resolution| { | 995 | for (wasm.globals.keys()) |global_resolution| { |
| 727 | switch (global_resolution.unpack(wasm)) { | 996 | switch (global_resolution.unpack(wasm)) { |
| 728 | .unresolved => unreachable, | 997 | .unresolved => unreachable, |
| 729 | .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base), | 998 | .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base, is64), |
| 730 | .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end), | 999 | .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end, is64), |
| 731 | .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer), | 1000 | .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer, is64), |
| 732 | .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?)), | 1001 | .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?), is64), |
| 733 | .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?), | 1002 | .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?, is64), |
| 734 | .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?), | 1003 | .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?, is64), |
| 735 | .object_global => |i| { | 1004 | .object_global => |i| { |
| 736 | const global = i.ptr(wasm); | 1005 | const global = i.ptr(wasm); |
| 737 | try binary_bytes.appendSlice(gpa, &.{ | 1006 | try binary_bytes.appendSlice(gpa, &.{ |
| ... | @@ -740,8 +1009,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -740,8 +1009,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 740 | }); | 1009 | }); |
| 741 | try emitExpr(wasm, binary_bytes, global.expr); | 1010 | try emitExpr(wasm, binary_bytes, global.expr); |
| 742 | }, | 1011 | }, |
| 743 | .nav_exe => unreachable, // Zig source code currently cannot represent this. | 1012 | .uav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.uavAddr(i.key(wasm).*), is64), |
| 744 | .nav_obj => unreachable, // Zig source code currently cannot represent this. | 1013 | .nav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.navAddr(i.key(wasm).*), is64), |
| 1014 | .uav_obj, .nav_obj => unreachable, | ||
| 745 | } | 1015 | } |
| 746 | } | 1016 | } |
| 747 | 1017 | ||
| ... | @@ -766,7 +1036,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -766,7 +1036,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 766 | 1036 | ||
| 767 | if (wasm.export_table and f.indirect_function_table.entries.len > 0) { | 1037 | if (wasm.export_table and f.indirect_function_table.entries.len > 0) { |
| 768 | const name = "__indirect_function_table"; | 1038 | const name = "__indirect_function_table"; |
| 769 | const index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?); | 1039 | const index: u32 = @intCast(wasm.table_imports.entries.len + |
| 1040 | wasm.tables.getIndex(.__indirect_function_table).?); | ||
| 770 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | 1041 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); |
| 771 | try binary_bytes.appendSlice(gpa, name); | 1042 | try binary_bytes.appendSlice(gpa, name); |
| 772 | try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.table)); | 1043 | try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.table)); |
| ... | @@ -803,8 +1074,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -803,8 +1074,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 803 | // start section | 1074 | // start section |
| 804 | if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| { | 1075 | if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| { |
| 805 | try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index)))); | 1076 | try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index)))); |
| 1077 | section_index += 1; | ||
| 806 | } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| { | 1078 | } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| { |
| 807 | try emitStartSection(gpa, binary_bytes, func_index); | 1079 | try emitStartSection(gpa, binary_bytes, func_index); |
| 1080 | section_index += 1; | ||
| 808 | } | 1081 | } |
| 809 | 1082 | ||
| 810 | // element section | 1083 | // element section |
| ... | @@ -812,7 +1085,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -812,7 +1085,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 812 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 1085 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 813 | 1086 | ||
| 814 | // indirect function table elements | 1087 | // indirect function table elements |
| 815 | const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?); | 1088 | const table_index: u32 = @intCast( |
| 1089 | wasm.table_imports.getIndex(wasm.preloaded_strings.__indirect_function_table) orelse | ||
| 1090 | wasm.table_imports.entries.len + wasm.tables.getIndex(.__indirect_function_table).?, | ||
| 1091 | ); | ||
| 816 | // passive with implicit 0-index table or set table index manually | 1092 | // passive with implicit 0-index table or set table index manually |
| 817 | const flags: u32 = if (table_index == 0) 0x0 else 0x02; | 1093 | const flags: u32 = if (table_index == 0) 0x0 else 0x02; |
| 818 | try appendLeb128(gpa, binary_bytes, flags); | 1094 | try appendLeb128(gpa, binary_bytes, flags); |
| ... | @@ -841,11 +1117,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -841,11 +1117,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 841 | if (f.data_segment_groups.items.len > 0) { | 1117 | if (f.data_segment_groups.items.len > 0) { |
| 842 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 1118 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 843 | replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len)); | 1119 | replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len)); |
| 1120 | section_index += 1; | ||
| 844 | } | 1121 | } |
| 845 | 1122 | ||
| 846 | // Code section. | 1123 | // Code section. |
| 847 | if (wasm.functions.count() != 0) { | 1124 | if (wasm.functions.count() != 0) { |
| 848 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 1125 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 1126 | const section_offset = binary_bytes.items.len - uleb128size(@intCast(wasm.functions.count())); | ||
| 849 | 1127 | ||
| 850 | for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) { | 1128 | for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) { |
| 851 | .unresolved => unreachable, | 1129 | .unresolved => unreachable, |
| ... | @@ -870,10 +1148,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -870,10 +1148,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 870 | const code = ptr.code.slice(wasm); | 1148 | const code = ptr.code.slice(wasm); |
| 871 | try appendLeb128(gpa, binary_bytes, code.len); | 1149 | try appendLeb128(gpa, binary_bytes, code.len); |
| 872 | const code_start = binary_bytes.items.len; | 1150 | const code_start = binary_bytes.items.len; |
| 1151 | const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset); | ||
| 873 | try binary_bytes.appendSlice(gpa, code); | 1152 | try binary_bytes.appendSlice(gpa, code); |
| 874 | if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); | 1153 | if (is_obj) { |
| 1154 | try processRelocs( | ||
| 1155 | wasm, | ||
| 1156 | &f.code_relocs, | ||
| 1157 | output_offset, | ||
| 1158 | ptr.offset, | ||
| 1159 | ptr.relocations(wasm), | ||
| 1160 | ); | ||
| 1161 | } else { | ||
| 1162 | applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); | ||
| 1163 | } | ||
| 875 | }, | 1164 | }, |
| 876 | .zcu_func => |i| { | 1165 | .zcu_func => |i| { |
| 1166 | const function_offset: u32 = @intCast(binary_bytes.items.len - section_offset); | ||
| 877 | const code_start = try reserveSize(gpa, binary_bytes); | 1167 | const code_start = try reserveSize(gpa, binary_bytes); |
| 878 | defer replaceSize(binary_bytes, code_start); | 1168 | defer replaceSize(binary_bytes, code_start); |
| 879 | 1169 | ||
| ... | @@ -899,7 +1189,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -899,7 +1189,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 899 | .func_tys = undefined, | 1189 | .func_tys = undefined, |
| 900 | .error_name_table_ref_count = undefined, | 1190 | .error_name_table_ref_count = undefined, |
| 901 | }; | 1191 | }; |
| 1192 | const body_start: u32 = @intCast(binary_bytes.items.len); | ||
| 1193 | const relocs_start: u32 = @intCast(wasm.zcu_relocations.len); | ||
| 1194 | defer wasm.zcu_relocations.shrinkRetainingCapacity(relocs_start); | ||
| 902 | try mir.lower(wasm, binary_bytes); | 1195 | try mir.lower(wasm, binary_bytes); |
| 1196 | const relocs_len: u32 = @intCast(wasm.zcu_relocations.len - relocs_start); | ||
| 1197 | if (is_obj) { | ||
| 1198 | const body_len: u32 = @intCast(binary_bytes.items.len - @as(usize, body_start)); | ||
| 1199 | const output_offset = function_offset + uleb128size(body_len); | ||
| 1200 | try processZcuRelocs( | ||
| 1201 | wasm, | ||
| 1202 | &f.code_relocs, | ||
| 1203 | output_offset, | ||
| 1204 | body_start, | ||
| 1205 | .{ .off = relocs_start, .len = relocs_len }, | ||
| 1206 | ); | ||
| 1207 | } | ||
| 903 | }, | 1208 | }, |
| 904 | } | 1209 | } |
| 905 | }, | 1210 | }, |
| ... | @@ -921,8 +1226,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -921,8 +1226,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 921 | } | 1226 | } |
| 922 | } | 1227 | } |
| 923 | for (wasm.nav_fixups.items) |nav_fixup| { | 1228 | for (wasm.nav_fixups.items) |nav_fixup| { |
| 924 | const ds_id: Wasm.DataSegmentId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index }); | 1229 | const vaddr = wasm.navAddr(nav_fixup.nav_index) + nav_fixup.addend; |
| 925 | const vaddr = f.data_segments.get(ds_id).? + nav_fixup.addend; | ||
| 926 | if (!is64) { | 1230 | if (!is64) { |
| 927 | mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little); | 1231 | mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little); |
| 928 | } else { | 1232 | } else { |
| ... | @@ -930,7 +1234,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -930,7 +1234,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 930 | } | 1234 | } |
| 931 | } | 1235 | } |
| 932 | for (wasm.func_table_fixups.items) |fixup| { | 1236 | for (wasm.func_table_fixups.items) |fixup| { |
| 933 | const table_index: IndirectFunctionTableIndex = .fromZcuIndirectFunctionSetIndex(fixup.table_index); | 1237 | const table_index: IndirectFunctionTableIndex = .fromIpNav(wasm, fixup.nav_index); |
| 934 | if (!is64) { | 1238 | if (!is64) { |
| 935 | mem.writeInt(u32, wasm.string_bytes.items[fixup.offset..][0..4], table_index.toAbi(), .little); | 1239 | mem.writeInt(u32, wasm.string_bytes.items[fixup.offset..][0..4], table_index.toAbi(), .little); |
| 936 | } else { | 1240 | } else { |
| ... | @@ -942,6 +1246,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -942,6 +1246,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 942 | // Data section. | 1246 | // Data section. |
| 943 | if (f.data_segment_groups.items.len != 0) { | 1247 | if (f.data_segment_groups.items.len != 0) { |
| 944 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 1248 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 1249 | const section_offset = binary_bytes.items.len - uleb128size(@intCast(f.data_segment_groups.items.len)); | ||
| 945 | 1250 | ||
| 946 | var group_index: u32 = 0; | 1251 | var group_index: u32 = 0; |
| 947 | var segment_offset: u32 = 0; | 1252 | var segment_offset: u32 = 0; |
| ... | @@ -976,7 +1281,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -976,7 +1281,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 976 | try appendLeb128(gpa, binary_bytes, group_size); | 1281 | try appendLeb128(gpa, binary_bytes, group_size); |
| 977 | } | 1282 | } |
| 978 | if (segment_id.isEmpty(wasm)) { | 1283 | if (segment_id.isEmpty(wasm)) { |
| 979 | // It counted for virtual memory but it does not go into the binary. | 1284 | if (is_obj) { |
| 1285 | const group_size = group_end_addr - group_start_addr; | ||
| 1286 | try binary_bytes.appendNTimes(gpa, 0, group_size - segment_offset); | ||
| 1287 | segment_offset = group_size; | ||
| 1288 | } | ||
| 980 | continue; | 1289 | continue; |
| 981 | } | 1290 | } |
| 982 | 1291 | ||
| ... | @@ -986,6 +1295,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -986,6 +1295,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 986 | segment_offset = needed_offset; | 1295 | segment_offset = needed_offset; |
| 987 | 1296 | ||
| 988 | const code_start = binary_bytes.items.len; | 1297 | const code_start = binary_bytes.items.len; |
| 1298 | const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset); | ||
| 989 | append: { | 1299 | append: { |
| 990 | const code = switch (segment_id.unpack(wasm)) { | 1300 | const code = switch (segment_id.unpack(wasm)) { |
| 991 | .__heap_base => { | 1301 | .__heap_base => { |
| ... | @@ -1001,12 +1311,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -1001,12 +1311,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 1001 | break :append; | 1311 | break :append; |
| 1002 | }, | 1312 | }, |
| 1003 | .__zig_error_name_table => { | 1313 | .__zig_error_name_table => { |
| 1004 | if (is_obj) @panic("TODO error name table reloc"); | 1314 | if (is_obj) { |
| 1005 | const base = f.data_segments.get(.__zig_error_names).?; | 1315 | try emitRelocatableNameTable( |
| 1006 | if (!is64) { | 1316 | wasm, |
| 1007 | try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32); | 1317 | binary_bytes, |
| 1318 | &f.data_relocs, | ||
| 1319 | output_offset, | ||
| 1320 | wasm.error_name_offs.items, | ||
| 1321 | wasm.error_name_bytes.items, | ||
| 1322 | .__zig_error_names, | ||
| 1323 | ); | ||
| 1008 | } else { | 1324 | } else { |
| 1009 | try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u64); | 1325 | const base = f.data_segments.get(.__zig_error_names).?; |
| 1326 | try emitTagNameTable(wasm, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, is64); | ||
| 1010 | } | 1327 | } |
| 1011 | break :append; | 1328 | break :append; |
| 1012 | }, | 1329 | }, |
| ... | @@ -1015,22 +1332,51 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -1015,22 +1332,51 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 1015 | break :append; | 1332 | break :append; |
| 1016 | }, | 1333 | }, |
| 1017 | .__zig_tag_name_table => { | 1334 | .__zig_tag_name_table => { |
| 1018 | if (is_obj) @panic("TODO tag name table reloc"); | 1335 | if (is_obj) { |
| 1019 | const base = f.data_segments.get(.__zig_tag_names).?; | 1336 | try emitRelocatableNameTable( |
| 1020 | if (!is64) { | 1337 | wasm, |
| 1021 | try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32); | 1338 | binary_bytes, |
| 1339 | &f.data_relocs, | ||
| 1340 | output_offset, | ||
| 1341 | wasm.tag_name_offs.items, | ||
| 1342 | wasm.tag_name_bytes.items, | ||
| 1343 | .__zig_tag_names, | ||
| 1344 | ); | ||
| 1022 | } else { | 1345 | } else { |
| 1023 | try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u64); | 1346 | const base = f.data_segments.get(.__zig_tag_names).?; |
| 1347 | try emitTagNameTable(wasm, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, is64); | ||
| 1024 | } | 1348 | } |
| 1025 | break :append; | 1349 | break :append; |
| 1026 | }, | 1350 | }, |
| 1027 | .object => |i| { | 1351 | .object => |i| { |
| 1028 | const ptr = i.ptr(wasm); | 1352 | const ptr = i.ptr(wasm); |
| 1029 | try binary_bytes.appendSlice(gpa, ptr.payload.slice(wasm)); | 1353 | try binary_bytes.appendSlice(gpa, ptr.payload.slice(wasm)); |
| 1030 | if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); | 1354 | if (is_obj) { |
| 1355 | try processRelocs( | ||
| 1356 | wasm, | ||
| 1357 | &f.data_relocs, | ||
| 1358 | output_offset, | ||
| 1359 | ptr.offset, | ||
| 1360 | ptr.relocations(wasm), | ||
| 1361 | ); | ||
| 1362 | } else { | ||
| 1363 | applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); | ||
| 1364 | } | ||
| 1031 | break :append; | 1365 | break :append; |
| 1032 | }, | 1366 | }, |
| 1033 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code, | 1367 | inline .uav_obj, .nav_obj => |i| { |
| 1368 | const zcu_data = i.value(wasm); | ||
| 1369 | try binary_bytes.appendSlice(gpa, zcu_data.code.slice(wasm)); | ||
| 1370 | try processZcuRelocs( | ||
| 1371 | wasm, | ||
| 1372 | &f.data_relocs, | ||
| 1373 | output_offset, | ||
| 1374 | zcu_data.code.off.unwrap().?, | ||
| 1375 | zcu_data.relocs, | ||
| 1376 | ); | ||
| 1377 | break :append; | ||
| 1378 | }, | ||
| 1379 | inline .uav_exe, .nav_exe => |i| i.value(wasm).code, | ||
| 1034 | }; | 1380 | }; |
| 1035 | try binary_bytes.appendSlice(gpa, code.slice(wasm)); | 1381 | try binary_bytes.appendSlice(gpa, code.slice(wasm)); |
| 1036 | } | 1382 | } |
| ... | @@ -1043,7 +1389,274 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -1043,7 +1389,274 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 1043 | } | 1389 | } |
| 1044 | 1390 | ||
| 1045 | if (is_obj) { | 1391 | if (is_obj) { |
| 1046 | @panic("TODO emit link section for object file and emit modified relocations"); | 1392 | var symbol_table_offsets: SymbolTableOffsets = undefined; |
| 1393 | { | ||
| 1394 | const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes); | ||
| 1395 | defer writeCustomSectionHeader(binary_bytes, header_offset); | ||
| 1396 | |||
| 1397 | const linking_name = "linking"; | ||
| 1398 | try appendLeb128(gpa, binary_bytes, @as(u32, linking_name.len)); | ||
| 1399 | try binary_bytes.appendSlice(gpa, linking_name); | ||
| 1400 | |||
| 1401 | try appendLeb128(gpa, binary_bytes, @as(u32, 2)); | ||
| 1402 | |||
| 1403 | // WASM_SEGMENT_INFO | ||
| 1404 | { | ||
| 1405 | const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); | ||
| 1406 | defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.segment_info)); | ||
| 1407 | |||
| 1408 | const total_data_segments: u32 = @intCast(f.data_segment_groups.items.len); | ||
| 1409 | try appendLeb128(gpa, binary_bytes, total_data_segments); | ||
| 1410 | |||
| 1411 | for (f.data_segment_groups.items) |group| { | ||
| 1412 | const segment = group.first_segment; | ||
| 1413 | const name, _ = splitSegmentName(segment.name(wasm)); | ||
| 1414 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1415 | try binary_bytes.appendSlice(gpa, name); | ||
| 1416 | |||
| 1417 | try appendLeb128(gpa, binary_bytes, @as(u32, segment.alignment(wasm).toLog2Units())); | ||
| 1418 | |||
| 1419 | var flags: u32 = 0; | ||
| 1420 | if (segment.isStrings(wasm)) flags |= 1; | ||
| 1421 | if (segment.isTls(wasm)) flags |= 2; | ||
| 1422 | if (segment.isRetain(wasm)) flags |= 4; | ||
| 1423 | try appendLeb128(gpa, binary_bytes, flags); | ||
| 1424 | } | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | // WASM_SYMBOL_TABLE | ||
| 1428 | { | ||
| 1429 | const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); | ||
| 1430 | defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.symbol_table)); | ||
| 1431 | |||
| 1432 | const total_symbols: u32 = @intCast( | ||
| 1433 | f.function_imports.entries.len + f.intrinsic_function_imports.entries.len + | ||
| 1434 | wasm.functions.entries.len + | ||
| 1435 | f.function_export_symbols.entries.len + | ||
| 1436 | f.data_imports.entries.len + wasm.datas.entries.len + f.data_exports.entries.len + | ||
| 1437 | f.global_imports.entries.len + wasm.globals.entries.len + | ||
| 1438 | wasm.table_imports.entries.len + wasm.tables.entries.len, | ||
| 1439 | ); | ||
| 1440 | try appendLeb128(gpa, binary_bytes, total_symbols); | ||
| 1441 | var symbol_count: u32 = 0; | ||
| 1442 | |||
| 1443 | // SYMTAB_FUNCTION | ||
| 1444 | { | ||
| 1445 | symbol_table_offsets.function = symbol_count; | ||
| 1446 | for (f.function_imports.values(), 0..) |i, function_index| { | ||
| 1447 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function)); | ||
| 1448 | const flags = i.flags(wasm); | ||
| 1449 | assert(flags.undefined); | ||
| 1450 | try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); | ||
| 1451 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); | ||
| 1452 | if (flags.explicit_name) { | ||
| 1453 | unreachable; // never set | ||
| 1454 | } | ||
| 1455 | symbol_count += 1; | ||
| 1456 | } | ||
| 1457 | const intrinsic_flags: Wasm.SymbolFlags = .{ .undefined = true }; | ||
| 1458 | for (f.intrinsic_function_imports.keys(), f.function_imports.entries.len..) |_, function_index| { | ||
| 1459 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function)); | ||
| 1460 | try appendLeb128(gpa, binary_bytes, intrinsic_flags.toAbiInteger()); | ||
| 1461 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); | ||
| 1462 | symbol_count += 1; | ||
| 1463 | } | ||
| 1464 | for ( | ||
| 1465 | wasm.functions.keys(), | ||
| 1466 | f.function_imports.entries.len + f.intrinsic_function_imports.entries.len.., | ||
| 1467 | ) |resolution, function_index| { | ||
| 1468 | const name = resolution.name(wasm).?; | ||
| 1469 | const flags = resolution.flags(wasm); | ||
| 1470 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function)); | ||
| 1471 | assert(!flags.undefined); | ||
| 1472 | try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); | ||
| 1473 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); | ||
| 1474 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1475 | try binary_bytes.appendSlice(gpa, name); | ||
| 1476 | symbol_count += 1; | ||
| 1477 | } | ||
| 1478 | for ( | ||
| 1479 | f.function_export_symbols.keys(), | ||
| 1480 | f.function_export_symbols.values(), | ||
| 1481 | ) |name_string, symbol| { | ||
| 1482 | const name = name_string.slice(wasm); | ||
| 1483 | const function_index: Wasm.OutputFunctionIndex = .fromFunctionIndex( | ||
| 1484 | wasm, | ||
| 1485 | symbol.function_index, | ||
| 1486 | ); | ||
| 1487 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function)); | ||
| 1488 | try appendLeb128(gpa, binary_bytes, symbol.flags.toAbiInteger()); | ||
| 1489 | try appendLeb128(gpa, binary_bytes, @backingInt(function_index)); | ||
| 1490 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1491 | try binary_bytes.appendSlice(gpa, name); | ||
| 1492 | symbol_count += 1; | ||
| 1493 | } | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | // SYMTAB_DATA | ||
| 1497 | { | ||
| 1498 | symbol_table_offsets.data = symbol_count; | ||
| 1499 | for (f.data_imports.keys(), f.data_imports.values()) |name_string, data_index| { | ||
| 1500 | const name = name_string.slice(wasm); | ||
| 1501 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data)); | ||
| 1502 | const flags = data_index.flags(wasm); | ||
| 1503 | assert(flags.undefined); | ||
| 1504 | try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); | ||
| 1505 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1506 | try binary_bytes.appendSlice(gpa, name); | ||
| 1507 | symbol_count += 1; | ||
| 1508 | } | ||
| 1509 | for (wasm.datas.keys()) |resolution| { | ||
| 1510 | var buf: [32]u8 = undefined; | ||
| 1511 | const name = resolution.name(wasm, &buf); | ||
| 1512 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data)); | ||
| 1513 | const flags = resolution.flags(wasm); | ||
| 1514 | assert(!flags.undefined); | ||
| 1515 | try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); | ||
| 1516 | |||
| 1517 | const data_loc = resolution.dataLoc(wasm); | ||
| 1518 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1519 | try binary_bytes.appendSlice(gpa, name); | ||
| 1520 | |||
| 1521 | const segment_index = f.data_segments.getIndex(data_loc.segment).?; | ||
| 1522 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_index))); | ||
| 1523 | try appendLeb128(gpa, binary_bytes, data_loc.offset); | ||
| 1524 | try appendLeb128(gpa, binary_bytes, resolution.size(wasm)); | ||
| 1525 | symbol_count += 1; | ||
| 1526 | } | ||
| 1527 | for (f.data_exports.keys(), f.data_exports.values()) |name_string, symbol| { | ||
| 1528 | const name = name_string.slice(wasm); | ||
| 1529 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data)); | ||
| 1530 | try appendLeb128(gpa, binary_bytes, symbol.flags.toAbiInteger()); | ||
| 1531 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1532 | try binary_bytes.appendSlice(gpa, name); | ||
| 1533 | |||
| 1534 | const data_loc = symbol.resolution.dataLoc(wasm); | ||
| 1535 | const segment_index = f.data_segments.getIndex(data_loc.segment).?; | ||
| 1536 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_index))); | ||
| 1537 | try appendLeb128(gpa, binary_bytes, data_loc.offset); | ||
| 1538 | try appendLeb128(gpa, binary_bytes, symbol.resolution.size(wasm)); | ||
| 1539 | symbol_count += 1; | ||
| 1540 | } | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | // SYMTAB_GLOBAL | ||
| 1544 | { | ||
| 1545 | symbol_table_offsets.global = symbol_count; | ||
| 1546 | for (f.global_imports.values(), 0..) |i, global_index| { | ||
| 1547 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.global)); | ||
| 1548 | const flags = i.flags(wasm); | ||
| 1549 | assert(flags.undefined); | ||
| 1550 | try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); | ||
| 1551 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); | ||
| 1552 | if (flags.explicit_name) { | ||
| 1553 | unreachable; // never set | ||
| 1554 | } | ||
| 1555 | symbol_count += 1; | ||
| 1556 | } | ||
| 1557 | for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| { | ||
| 1558 | var buf: [32]u8 = undefined; | ||
| 1559 | const name = resolution.name(wasm, &buf).?; | ||
| 1560 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.global)); | ||
| 1561 | const flags = resolution.flags(wasm); | ||
| 1562 | assert(!flags.undefined); | ||
| 1563 | try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); | ||
| 1564 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); | ||
| 1565 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1566 | try binary_bytes.appendSlice(gpa, name); | ||
| 1567 | symbol_count += 1; | ||
| 1568 | } | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | // SYMTAB_EVENT | ||
| 1572 | { | ||
| 1573 | // TODO not parsed yet | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | // SYMTAB_SECTION | ||
| 1577 | { | ||
| 1578 | // TODO not parsed correctly yet | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | // SYMTAB_TABLE | ||
| 1582 | { | ||
| 1583 | symbol_table_offsets.table = symbol_count; | ||
| 1584 | for (wasm.table_imports.values(), 0..) |i, table_index| { | ||
| 1585 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.table)); | ||
| 1586 | const flags = i.value(wasm).flags; | ||
| 1587 | assert(flags.undefined); | ||
| 1588 | try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); | ||
| 1589 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(table_index))); | ||
| 1590 | if (flags.explicit_name) { | ||
| 1591 | unreachable; // never set | ||
| 1592 | } | ||
| 1593 | symbol_count += 1; | ||
| 1594 | } | ||
| 1595 | for (wasm.tables.keys(), wasm.table_imports.entries.len..) |resolution, table_index| { | ||
| 1596 | const name = resolution.name(wasm).?; | ||
| 1597 | try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.table)); | ||
| 1598 | const flags = resolution.flags(wasm); | ||
| 1599 | assert(!flags.undefined); | ||
| 1600 | try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); | ||
| 1601 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(table_index))); | ||
| 1602 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1603 | try binary_bytes.appendSlice(gpa, name); | ||
| 1604 | symbol_count += 1; | ||
| 1605 | } | ||
| 1606 | } | ||
| 1607 | assert(symbol_count == total_symbols); | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | // WASM_INIT_FUNCS | ||
| 1611 | { | ||
| 1612 | const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); | ||
| 1613 | defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.init_funcs)); | ||
| 1614 | |||
| 1615 | const init_funcs = wasm.object_init_funcs.items; | ||
| 1616 | const total_functions: u32 = b: { | ||
| 1617 | var cnt: u32 = 0; | ||
| 1618 | for (init_funcs) |init_func| { | ||
| 1619 | const func = init_func.function_index.ptr(wasm); | ||
| 1620 | if (!func.object_index.ptr(wasm).is_included) continue; | ||
| 1621 | cnt += 1; | ||
| 1622 | } | ||
| 1623 | break :b cnt; | ||
| 1624 | }; | ||
| 1625 | try appendLeb128(gpa, binary_bytes, total_functions); | ||
| 1626 | |||
| 1627 | for (init_funcs) |init_func| { | ||
| 1628 | const func = init_func.function_index.ptr(wasm); | ||
| 1629 | if (!func.object_index.ptr(wasm).is_included) continue; | ||
| 1630 | |||
| 1631 | try appendLeb128(gpa, binary_bytes, init_func.priority); | ||
| 1632 | const out_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index); | ||
| 1633 | const symbol_index: u32 = symbol_table_offsets.function + @backingInt(out_index); | ||
| 1634 | try appendLeb128(gpa, binary_bytes, symbol_index); | ||
| 1635 | } | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | // WASM_COMDAT_INFO | ||
| 1639 | { | ||
| 1640 | // TODO | ||
| 1641 | } | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | if (f.code_relocs.items.len != 0) try emitRelocSection( | ||
| 1645 | wasm, | ||
| 1646 | binary_bytes, | ||
| 1647 | code_section_index.?, | ||
| 1648 | "reloc.CODE", | ||
| 1649 | f.code_relocs.items, | ||
| 1650 | symbol_table_offsets, | ||
| 1651 | ); | ||
| 1652 | if (f.data_relocs.items.len != 0) try emitRelocSection( | ||
| 1653 | wasm, | ||
| 1654 | binary_bytes, | ||
| 1655 | data_section_index.?, | ||
| 1656 | "reloc.DATA", | ||
| 1657 | f.data_relocs.items, | ||
| 1658 | symbol_table_offsets, | ||
| 1659 | ); | ||
| 1047 | } else if (comp.config.debug_format != .strip) { | 1660 | } else if (comp.config.debug_format != .strip) { |
| 1048 | try emitNameSection(wasm, f.data_segment_groups.items, binary_bytes); | 1661 | try emitNameSection(wasm, f.data_segment_groups.items, binary_bytes); |
| 1049 | } | 1662 | } |
| ... | @@ -1121,7 +1734,10 @@ fn emitNameSection( | ... | @@ -1121,7 +1734,10 @@ fn emitNameSection( |
| 1121 | const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); | 1734 | const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); |
| 1122 | defer replaceHeader(binary_bytes, sub_offset, @backingInt(std.wasm.NameSubsection.function)); | 1735 | defer replaceHeader(binary_bytes, sub_offset, @backingInt(std.wasm.NameSubsection.function)); |
| 1123 | 1736 | ||
| 1124 | const total_functions: u32 = @intCast(f.function_imports.entries.len + wasm.functions.entries.len); | 1737 | const total_functions: u32 = @intCast( |
| 1738 | f.function_imports.entries.len + f.intrinsic_function_imports.entries.len + | ||
| 1739 | wasm.functions.entries.len, | ||
| 1740 | ); | ||
| 1125 | try appendLeb128(gpa, binary_bytes, total_functions); | 1741 | try appendLeb128(gpa, binary_bytes, total_functions); |
| 1126 | 1742 | ||
| 1127 | for (f.function_imports.keys(), 0..) |name_index, function_index| { | 1743 | for (f.function_imports.keys(), 0..) |name_index, function_index| { |
| ... | @@ -1130,7 +1746,16 @@ fn emitNameSection( | ... | @@ -1130,7 +1746,16 @@ fn emitNameSection( |
| 1130 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | 1746 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); |
| 1131 | try binary_bytes.appendSlice(gpa, name); | 1747 | try binary_bytes.appendSlice(gpa, name); |
| 1132 | } | 1748 | } |
| 1133 | for (wasm.functions.keys(), f.function_imports.entries.len..) |resolution, function_index| { | 1749 | for (f.intrinsic_function_imports.keys(), f.function_imports.entries.len..) |name_index, function_index| { |
| 1750 | const name = name_index.slice(wasm); | ||
| 1751 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); | ||
| 1752 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | ||
| 1753 | try binary_bytes.appendSlice(gpa, name); | ||
| 1754 | } | ||
| 1755 | for ( | ||
| 1756 | wasm.functions.keys(), | ||
| 1757 | f.function_imports.entries.len + f.intrinsic_function_imports.entries.len.., | ||
| 1758 | ) |resolution, function_index| { | ||
| 1134 | const name = resolution.name(wasm).?; | 1759 | const name = resolution.name(wasm).?; |
| 1135 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); | 1760 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); |
| 1136 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | 1761 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); |
| ... | @@ -1152,7 +1777,8 @@ fn emitNameSection( | ... | @@ -1152,7 +1777,8 @@ fn emitNameSection( |
| 1152 | try binary_bytes.appendSlice(gpa, name); | 1777 | try binary_bytes.appendSlice(gpa, name); |
| 1153 | } | 1778 | } |
| 1154 | for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| { | 1779 | for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| { |
| 1155 | const name = resolution.name(wasm).?; | 1780 | var buf: [32]u8 = undefined; |
| 1781 | const name = resolution.name(wasm, &buf).?; | ||
| 1156 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); | 1782 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); |
| 1157 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | 1783 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); |
| 1158 | try binary_bytes.appendSlice(gpa, name); | 1784 | try binary_bytes.appendSlice(gpa, name); |
| ... | @@ -1418,29 +2044,6 @@ pub fn emitExpr(wasm: *const Wasm, binary_bytes: *ArrayList(u8), expr: Wasm.Expr | ... | @@ -1418,29 +2044,6 @@ pub fn emitExpr(wasm: *const Wasm, binary_bytes: *ArrayList(u8), expr: Wasm.Expr |
| 1418 | try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode | 2044 | try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode |
| 1419 | } | 2045 | } |
| 1420 | 2046 | ||
| 1421 | fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.array_list.Managed(u8)) !void { | ||
| 1422 | const gpa = wasm.base.comp.gpa; | ||
| 1423 | try appendLeb128(gpa, binary_bytes, @backingInt(Wasm.SubsectionType.segment_info)); | ||
| 1424 | const segment_offset = binary_bytes.items.len; | ||
| 1425 | |||
| 1426 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(wasm.segment_info.count()))); | ||
| 1427 | for (wasm.segment_info.values()) |segment_info| { | ||
| 1428 | log.debug("Emit segment: {s} align({d}) flags({b})", .{ | ||
| 1429 | segment_info.name, | ||
| 1430 | segment_info.alignment, | ||
| 1431 | segment_info.flags, | ||
| 1432 | }); | ||
| 1433 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_info.name.len))); | ||
| 1434 | try binary_bytes.appendSlice(gpa, segment_info.name); | ||
| 1435 | try appendLeb128(gpa, binary_bytes, segment_info.alignment.toLog2Units()); | ||
| 1436 | try appendLeb128(gpa, binary_bytes, segment_info.flags); | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | var buf: [5]u8 = undefined; | ||
| 1440 | leb.writeUnsignedFixed(5, &buf, @as(u32, @intCast(binary_bytes.items.len - segment_offset))); | ||
| 1441 | try binary_bytes.insertSlice(segment_offset, &buf); | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | fn uleb128size(x: u32) u32 { | 2047 | fn uleb128size(x: u32) u32 { |
| 1445 | var value = x; | 2048 | var value = x; |
| 1446 | var size: u32 = 0; | 2049 | var size: u32 = 0; |
| ... | @@ -1449,22 +2052,395 @@ fn uleb128size(x: u32) u32 { | ... | @@ -1449,22 +2052,395 @@ fn uleb128size(x: u32) u32 { |
| 1449 | } | 2052 | } |
| 1450 | 2053 | ||
| 1451 | fn emitTagNameTable( | 2054 | fn emitTagNameTable( |
| 1452 | gpa: Allocator, | 2055 | wasm: *const Wasm, |
| 1453 | code: *ArrayList(u8), | 2056 | code: *ArrayList(u8), |
| 1454 | tag_name_offs: []const u32, | 2057 | tag_name_offs: []const u32, |
| 1455 | tag_name_bytes: []const u8, | 2058 | tag_name_bytes: []const u8, |
| 1456 | base: u32, | 2059 | base: u32, |
| 1457 | comptime Int: type, | 2060 | is64: bool, |
| 1458 | ) error{OutOfMemory}!void { | 2061 | ) error{OutOfMemory}!void { |
| 1459 | const ptr_size_bytes = @divExact(@bitSizeOf(Int), 8); | 2062 | const gpa = wasm.base.comp.gpa; |
| 2063 | const ptr_size_bytes: usize = if (is64) 8 else 4; | ||
| 1460 | try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len); | 2064 | try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len); |
| 1461 | for (tag_name_offs) |off| { | 2065 | for (tag_name_offs) |off| { |
| 1462 | const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?); | 2066 | const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?); |
| 1463 | mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), base + off, .little); | 2067 | if (is64) { |
| 1464 | mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), name_len, .little); | 2068 | mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), base + off, .little); |
| 2069 | mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), name_len, .little); | ||
| 2070 | } else { | ||
| 2071 | mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), base + off, .little); | ||
| 2072 | mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), name_len, .little); | ||
| 2073 | } | ||
| 2074 | } | ||
| 2075 | } | ||
| 2076 | |||
| 2077 | fn emitRelocatableNameTable( | ||
| 2078 | wasm: *const Wasm, | ||
| 2079 | code: *ArrayList(u8), | ||
| 2080 | relocs: *ArrayList(Relocation), | ||
| 2081 | output_offset: u32, | ||
| 2082 | name_offs: []const u32, | ||
| 2083 | name_bytes: []const u8, | ||
| 2084 | names_resolution: Wasm.ObjectDataImport.Resolution, | ||
| 2085 | ) error{OutOfMemory}!void { | ||
| 2086 | const gpa = wasm.base.comp.gpa; | ||
| 2087 | const ptr_size = @divExact(wasm.base.comp.root_mod.resolved_target.result.ptrBitWidth(), 8); | ||
| 2088 | const table_start = code.items.len; | ||
| 2089 | const data_index: DataSymbolIndex = .fromResolution(wasm, names_resolution); | ||
| 2090 | try code.ensureUnusedCapacity(gpa, @as(usize, ptr_size) * 2 * name_offs.len); | ||
| 2091 | try relocs.ensureUnusedCapacity(gpa, name_offs.len); | ||
| 2092 | for (name_offs) |off| { | ||
| 2093 | const name_len: u32 = @intCast(mem.indexOfScalar(u8, name_bytes[off..], 0).?); | ||
| 2094 | const reloc_offset = output_offset + @as(u32, @intCast(code.items.len - table_start)); | ||
| 2095 | switch (ptr_size) { | ||
| 2096 | 4 => { | ||
| 2097 | @memset(code.addManyAsArrayAssumeCapacity(4), 0); | ||
| 2098 | mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), name_len, .little); | ||
| 2099 | }, | ||
| 2100 | 8 => { | ||
| 2101 | @memset(code.addManyAsArrayAssumeCapacity(8), 0); | ||
| 2102 | mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), @intCast(name_len), .little); | ||
| 2103 | }, | ||
| 2104 | else => unreachable, | ||
| 2105 | } | ||
| 2106 | relocs.appendAssumeCapacity(.{ | ||
| 2107 | .tag = if (ptr_size == 4) .memory_addr_i32 else .memory_addr_i64, | ||
| 2108 | .offset = reloc_offset, | ||
| 2109 | .pointee = .{ .data = data_index }, | ||
| 2110 | .addend = @intCast(off), | ||
| 2111 | }); | ||
| 1465 | } | 2112 | } |
| 1466 | } | 2113 | } |
| 1467 | 2114 | ||
| 2115 | fn emitRelocSection( | ||
| 2116 | wasm: *const Wasm, | ||
| 2117 | binary_bytes: *ArrayList(u8), | ||
| 2118 | section_index: u32, | ||
| 2119 | reloc_name: []const u8, | ||
| 2120 | relocs: []const Relocation, | ||
| 2121 | symbol_table_offsets: SymbolTableOffsets, | ||
| 2122 | ) !void { | ||
| 2123 | const comp = wasm.base.comp; | ||
| 2124 | const gpa = comp.gpa; | ||
| 2125 | |||
| 2126 | const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes); | ||
| 2127 | defer writeCustomSectionHeader(binary_bytes, header_offset); | ||
| 2128 | |||
| 2129 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(reloc_name.len))); | ||
| 2130 | try binary_bytes.appendSlice(gpa, reloc_name); | ||
| 2131 | |||
| 2132 | try appendLeb128(gpa, binary_bytes, section_index); | ||
| 2133 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(relocs.len))); | ||
| 2134 | |||
| 2135 | for (relocs) |r| { | ||
| 2136 | try binary_bytes.append(gpa, @backingInt(r.tag)); | ||
| 2137 | try appendLeb128(gpa, binary_bytes, r.offset); | ||
| 2138 | switch (r.tag) { | ||
| 2139 | .memory_addr_leb, | ||
| 2140 | .memory_addr_sleb, | ||
| 2141 | .memory_addr_i32, | ||
| 2142 | .memory_addr_rel_sleb, | ||
| 2143 | .memory_addr_leb64, | ||
| 2144 | .memory_addr_sleb64, | ||
| 2145 | .memory_addr_i64, | ||
| 2146 | .memory_addr_rel_sleb64, | ||
| 2147 | .memory_addr_tls_sleb, | ||
| 2148 | .memory_addr_locrel_i32, | ||
| 2149 | .memory_addr_tls_sleb64, | ||
| 2150 | => { | ||
| 2151 | const symbol_index: u32 = symbol_table_offsets.data + @backingInt(r.pointee.data); | ||
| 2152 | try appendLeb128(gpa, binary_bytes, symbol_index); | ||
| 2153 | }, | ||
| 2154 | .section_offset_i32 => { | ||
| 2155 | @panic("TODO"); | ||
| 2156 | }, | ||
| 2157 | .type_index_leb => { | ||
| 2158 | try appendLeb128(gpa, binary_bytes, @backingInt(r.pointee.type_index)); | ||
| 2159 | }, | ||
| 2160 | .function_offset_i32, | ||
| 2161 | .function_offset_i64, | ||
| 2162 | .function_index_leb, | ||
| 2163 | .function_index_i32, | ||
| 2164 | .table_index_sleb, | ||
| 2165 | .table_index_i32, | ||
| 2166 | .table_index_sleb64, | ||
| 2167 | .table_index_i64, | ||
| 2168 | .table_index_rel_sleb, | ||
| 2169 | .table_index_rel_sleb64, | ||
| 2170 | => { | ||
| 2171 | const symbol_index: u32 = symbol_table_offsets.function + @backingInt(r.pointee.function); | ||
| 2172 | try appendLeb128(gpa, binary_bytes, symbol_index); | ||
| 2173 | }, | ||
| 2174 | .global_index_leb, .global_index_i32 => { | ||
| 2175 | const symbol_index: u32 = symbol_table_offsets.global + @backingInt(r.pointee.global); | ||
| 2176 | try appendLeb128(gpa, binary_bytes, symbol_index); | ||
| 2177 | }, | ||
| 2178 | .table_number_leb => { | ||
| 2179 | const symbol_index: u32 = symbol_table_offsets.table + @backingInt(r.pointee.table); | ||
| 2180 | try appendLeb128(gpa, binary_bytes, symbol_index); | ||
| 2181 | }, | ||
| 2182 | .event_index_leb => @panic("TODO"), | ||
| 2183 | } | ||
| 2184 | switch (r.tag) { | ||
| 2185 | .memory_addr_leb, | ||
| 2186 | .memory_addr_sleb, | ||
| 2187 | .memory_addr_i32, | ||
| 2188 | .memory_addr_rel_sleb, | ||
| 2189 | .memory_addr_leb64, | ||
| 2190 | .memory_addr_sleb64, | ||
| 2191 | .memory_addr_i64, | ||
| 2192 | .memory_addr_rel_sleb64, | ||
| 2193 | .memory_addr_tls_sleb, | ||
| 2194 | .memory_addr_locrel_i32, | ||
| 2195 | .memory_addr_tls_sleb64, | ||
| 2196 | .function_offset_i32, | ||
| 2197 | .function_offset_i64, | ||
| 2198 | .section_offset_i32, | ||
| 2199 | => { | ||
| 2200 | try appendLeb128(gpa, binary_bytes, r.addend); | ||
| 2201 | }, | ||
| 2202 | else => {}, | ||
| 2203 | } | ||
| 2204 | } | ||
| 2205 | } | ||
| 2206 | |||
| 2207 | fn processZcuRelocs( | ||
| 2208 | wasm: *const Wasm, | ||
| 2209 | out: *ArrayList(Relocation), | ||
| 2210 | output_offset: u32, | ||
| 2211 | input_offset: u32, | ||
| 2212 | relocs: Wasm.ZcuRelocation.Slice, | ||
| 2213 | ) !void { | ||
| 2214 | const gpa = wasm.base.comp.gpa; | ||
| 2215 | for ( | ||
| 2216 | relocs.tags(wasm), | ||
| 2217 | relocs.pointees(wasm), | ||
| 2218 | relocs.offsets(wasm), | ||
| 2219 | relocs.addends(wasm), | ||
| 2220 | ) |tag, pointee, offset, addend| { | ||
| 2221 | const output_pointee: Relocation.Pointee = switch (pointee) { | ||
| 2222 | .function_nav => |nav_index| .{ .function = .fromIpNav(wasm, nav_index) }, | ||
| 2223 | .function_name => |name| .{ .function = .fromSymbolName(wasm, name) }, | ||
| 2224 | .tag_function => |ip_index| .{ .function = .fromTagIndexType(wasm, ip_index) }, | ||
| 2225 | .data_uav => |ip_index| .{ .data = .fromUav(wasm, ip_index) }, | ||
| 2226 | .data_nav => |nav_index| .{ .data = .fromNav(wasm, nav_index) }, | ||
| 2227 | .data_resolution => |resolution| .{ .data = .fromResolution(wasm, resolution) }, | ||
| 2228 | .stack_pointer => .{ .global = .fromSymbolName(wasm, wasm.preloaded_strings.__stack_pointer) }, | ||
| 2229 | .type_index => |type_index| .{ .type_index = .fromTypeIndex(type_index, &wasm.flush_buffer) }, | ||
| 2230 | }; | ||
| 2231 | try out.append(gpa, .{ | ||
| 2232 | .tag = tag, | ||
| 2233 | .offset = output_offset + (offset - input_offset), | ||
| 2234 | .pointee = output_pointee, | ||
| 2235 | .addend = addend, | ||
| 2236 | }); | ||
| 2237 | } | ||
| 2238 | } | ||
| 2239 | |||
| 2240 | fn processRelocs( | ||
| 2241 | wasm: *const Wasm, | ||
| 2242 | out: *ArrayList(Relocation), | ||
| 2243 | output_offset: u32, | ||
| 2244 | input_offset: u32, | ||
| 2245 | relocs: Wasm.ObjectRelocation.IterableSlice, | ||
| 2246 | ) !void { | ||
| 2247 | const gpa = wasm.base.comp.gpa; | ||
| 2248 | for ( | ||
| 2249 | relocs.slice.tags(wasm), | ||
| 2250 | relocs.slice.pointees(wasm), | ||
| 2251 | relocs.slice.offsets(wasm), | ||
| 2252 | relocs.slice.addends(wasm), | ||
| 2253 | ) |tag, pointee, offset, addend| { | ||
| 2254 | if (offset >= relocs.end) break; | ||
| 2255 | const rebased_offset = output_offset + (offset - input_offset); | ||
| 2256 | try out.ensureUnusedCapacity(gpa, 1); | ||
| 2257 | switch (tag) { | ||
| 2258 | .function_index_i32 => out.appendAssumeCapacity(.{ | ||
| 2259 | .tag = .function_index_i32, | ||
| 2260 | .offset = rebased_offset, | ||
| 2261 | .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, | ||
| 2262 | .addend = addend, | ||
| 2263 | }), | ||
| 2264 | .function_index_leb => out.appendAssumeCapacity(.{ | ||
| 2265 | .tag = .function_index_leb, | ||
| 2266 | .offset = rebased_offset, | ||
| 2267 | .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, | ||
| 2268 | .addend = addend, | ||
| 2269 | }), | ||
| 2270 | .function_offset_i32 => @panic("TODO this value is not known yet"), | ||
| 2271 | .function_offset_i64 => @panic("TODO this value is not known yet"), | ||
| 2272 | .table_index_i32 => out.appendAssumeCapacity(.{ | ||
| 2273 | .tag = .table_index_i32, | ||
| 2274 | .offset = rebased_offset, | ||
| 2275 | .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, | ||
| 2276 | .addend = addend, | ||
| 2277 | }), | ||
| 2278 | .table_index_i64 => out.appendAssumeCapacity(.{ | ||
| 2279 | .tag = .table_index_i64, | ||
| 2280 | .offset = rebased_offset, | ||
| 2281 | .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, | ||
| 2282 | .addend = addend, | ||
| 2283 | }), | ||
| 2284 | .table_index_rel_sleb => @panic("TODO what does this reloc tag mean?"), | ||
| 2285 | .table_index_rel_sleb64 => @panic("TODO what does this reloc tag mean?"), | ||
| 2286 | .table_index_sleb => out.appendAssumeCapacity(.{ | ||
| 2287 | .tag = .table_index_sleb, | ||
| 2288 | .offset = rebased_offset, | ||
| 2289 | .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, | ||
| 2290 | .addend = addend, | ||
| 2291 | }), | ||
| 2292 | .table_index_sleb64 => out.appendAssumeCapacity(.{ | ||
| 2293 | .tag = .table_index_sleb64, | ||
| 2294 | .offset = rebased_offset, | ||
| 2295 | .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, | ||
| 2296 | .addend = addend, | ||
| 2297 | }), | ||
| 2298 | |||
| 2299 | .function_import_index_i32 => out.appendAssumeCapacity(.{ | ||
| 2300 | .tag = .function_index_i32, | ||
| 2301 | .offset = rebased_offset, | ||
| 2302 | .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2303 | .addend = addend, | ||
| 2304 | }), | ||
| 2305 | .function_import_index_leb => out.appendAssumeCapacity(.{ | ||
| 2306 | .tag = .function_index_leb, | ||
| 2307 | .offset = rebased_offset, | ||
| 2308 | .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2309 | .addend = addend, | ||
| 2310 | }), | ||
| 2311 | .function_import_offset_i32 => @panic("TODO this value is not known yet"), | ||
| 2312 | .function_import_offset_i64 => @panic("TODO this value is not known yet"), | ||
| 2313 | .table_import_index_i32 => out.appendAssumeCapacity(.{ | ||
| 2314 | .tag = .table_index_i32, | ||
| 2315 | .offset = rebased_offset, | ||
| 2316 | .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2317 | .addend = addend, | ||
| 2318 | }), | ||
| 2319 | .table_import_index_i64 => out.appendAssumeCapacity(.{ | ||
| 2320 | .tag = .table_index_i64, | ||
| 2321 | .offset = rebased_offset, | ||
| 2322 | .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2323 | .addend = addend, | ||
| 2324 | }), | ||
| 2325 | .table_import_index_rel_sleb => @panic("TODO what does this reloc tag mean?"), | ||
| 2326 | .table_import_index_rel_sleb64 => @panic("TODO what does this reloc tag mean?"), | ||
| 2327 | .table_import_index_sleb => out.appendAssumeCapacity(.{ | ||
| 2328 | .tag = .table_index_sleb, | ||
| 2329 | .offset = rebased_offset, | ||
| 2330 | .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2331 | .addend = addend, | ||
| 2332 | }), | ||
| 2333 | .table_import_index_sleb64 => out.appendAssumeCapacity(.{ | ||
| 2334 | .tag = .table_index_sleb64, | ||
| 2335 | .offset = rebased_offset, | ||
| 2336 | .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2337 | .addend = addend, | ||
| 2338 | }), | ||
| 2339 | |||
| 2340 | .global_index_i32 => out.appendAssumeCapacity(.{ | ||
| 2341 | .tag = .global_index_i32, | ||
| 2342 | .offset = rebased_offset, | ||
| 2343 | .pointee = .{ .global = .fromObjectGlobalHandlingWeak(wasm, pointee.global) }, | ||
| 2344 | .addend = addend, | ||
| 2345 | }), | ||
| 2346 | .global_index_leb => out.appendAssumeCapacity(.{ | ||
| 2347 | .tag = .global_index_leb, | ||
| 2348 | .offset = rebased_offset, | ||
| 2349 | .pointee = .{ .global = .fromObjectGlobalHandlingWeak(wasm, pointee.global) }, | ||
| 2350 | .addend = addend, | ||
| 2351 | }), | ||
| 2352 | |||
| 2353 | .global_import_index_i32 => out.appendAssumeCapacity(.{ | ||
| 2354 | .tag = .global_index_i32, | ||
| 2355 | .offset = rebased_offset, | ||
| 2356 | .pointee = .{ .global = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2357 | .addend = addend, | ||
| 2358 | }), | ||
| 2359 | .global_import_index_leb => out.appendAssumeCapacity(.{ | ||
| 2360 | .tag = .global_index_leb, | ||
| 2361 | .offset = rebased_offset, | ||
| 2362 | .pointee = .{ .global = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2363 | .addend = addend, | ||
| 2364 | }), | ||
| 2365 | |||
| 2366 | .memory_addr_i32, | ||
| 2367 | .memory_addr_i64, | ||
| 2368 | .memory_addr_leb, | ||
| 2369 | .memory_addr_leb64, | ||
| 2370 | .memory_addr_sleb, | ||
| 2371 | .memory_addr_sleb64, | ||
| 2372 | .memory_addr_tls_sleb, | ||
| 2373 | .memory_addr_tls_sleb64, | ||
| 2374 | => out.appendAssumeCapacity(.{ | ||
| 2375 | .tag = memoryRelocationType(tag), | ||
| 2376 | .offset = rebased_offset, | ||
| 2377 | .pointee = .{ .data = .fromObjectData(wasm, pointee.data) }, | ||
| 2378 | .addend = addend, | ||
| 2379 | }), | ||
| 2380 | .memory_addr_locrel_i32 => @panic("TODO implement relocation memory_addr_locrel_i32"), | ||
| 2381 | .memory_addr_rel_sleb => @panic("TODO implement relocation memory_addr_rel_sleb"), | ||
| 2382 | .memory_addr_rel_sleb64 => @panic("TODO implement relocation memory_addr_rel_sleb64"), | ||
| 2383 | |||
| 2384 | .memory_addr_import_i32, | ||
| 2385 | .memory_addr_import_i64, | ||
| 2386 | .memory_addr_import_leb, | ||
| 2387 | .memory_addr_import_leb64, | ||
| 2388 | .memory_addr_import_sleb, | ||
| 2389 | .memory_addr_import_sleb64, | ||
| 2390 | => out.appendAssumeCapacity(.{ | ||
| 2391 | .tag = memoryRelocationType(tag), | ||
| 2392 | .offset = rebased_offset, | ||
| 2393 | .pointee = .{ .data = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2394 | .addend = addend, | ||
| 2395 | }), | ||
| 2396 | .memory_addr_import_locrel_i32 => @panic("TODO implement relocation memory_addr_import_locrel_i32"), | ||
| 2397 | .memory_addr_import_rel_sleb => @panic("TODO implement relocation memory_addr_import_rel_sleb"), | ||
| 2398 | .memory_addr_import_rel_sleb64 => @panic("TODO implement memory_addr_import_rel_sleb64"), | ||
| 2399 | .memory_addr_import_tls_sleb => @panic("TODO"), | ||
| 2400 | .memory_addr_import_tls_sleb64 => @panic("TODO"), | ||
| 2401 | |||
| 2402 | .section_offset_i32 => @panic("TODO this value is not known yet"), | ||
| 2403 | |||
| 2404 | .table_number_leb => out.appendAssumeCapacity(.{ | ||
| 2405 | .tag = .table_number_leb, | ||
| 2406 | .offset = rebased_offset, | ||
| 2407 | .pointee = .{ .table = .fromObjectTable(wasm, pointee.table) }, | ||
| 2408 | .addend = addend, | ||
| 2409 | }), | ||
| 2410 | .table_import_number_leb => out.appendAssumeCapacity(.{ | ||
| 2411 | .tag = .table_number_leb, | ||
| 2412 | .offset = rebased_offset, | ||
| 2413 | .pointee = .{ .table = .fromSymbolName(wasm, pointee.symbol_name) }, | ||
| 2414 | .addend = addend, | ||
| 2415 | }), | ||
| 2416 | |||
| 2417 | .type_index_leb => out.appendAssumeCapacity(.{ | ||
| 2418 | .tag = .type_index_leb, | ||
| 2419 | .offset = rebased_offset, | ||
| 2420 | .pointee = .{ .type_index = .fromTypeIndex(pointee.type_index, &wasm.flush_buffer) }, | ||
| 2421 | .addend = addend, | ||
| 2422 | }), | ||
| 2423 | } | ||
| 2424 | } | ||
| 2425 | } | ||
| 2426 | |||
| 2427 | fn memoryRelocationType(tag: Wasm.ObjectRelocation.Tag) Object.RelocationType { | ||
| 2428 | return switch (tag) { | ||
| 2429 | .memory_addr_i32, .memory_addr_import_i32 => .memory_addr_i32, | ||
| 2430 | .memory_addr_i64, .memory_addr_import_i64 => .memory_addr_i64, | ||
| 2431 | .memory_addr_leb, .memory_addr_import_leb => .memory_addr_leb, | ||
| 2432 | .memory_addr_leb64, .memory_addr_import_leb64 => .memory_addr_leb64, | ||
| 2433 | .memory_addr_locrel_i32, .memory_addr_import_locrel_i32 => .memory_addr_locrel_i32, | ||
| 2434 | .memory_addr_rel_sleb, .memory_addr_import_rel_sleb => .memory_addr_rel_sleb, | ||
| 2435 | .memory_addr_rel_sleb64, .memory_addr_import_rel_sleb64 => .memory_addr_rel_sleb64, | ||
| 2436 | .memory_addr_sleb, .memory_addr_import_sleb => .memory_addr_sleb, | ||
| 2437 | .memory_addr_sleb64, .memory_addr_import_sleb64 => .memory_addr_sleb64, | ||
| 2438 | .memory_addr_tls_sleb, .memory_addr_import_tls_sleb => .memory_addr_tls_sleb, | ||
| 2439 | .memory_addr_tls_sleb64, .memory_addr_import_tls_sleb64 => .memory_addr_tls_sleb64, | ||
| 2440 | else => unreachable, | ||
| 2441 | }; | ||
| 2442 | } | ||
| 2443 | |||
| 1468 | fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.IterableSlice, wasm: *const Wasm) void { | 2444 | fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.IterableSlice, wasm: *const Wasm) void { |
| 1469 | for ( | 2445 | for ( |
| 1470 | relocs.slice.tags(wasm), | 2446 | relocs.slice.tags(wasm), |
| ... | @@ -1579,12 +2555,17 @@ const RelocAddr = struct { | ... | @@ -1579,12 +2555,17 @@ const RelocAddr = struct { |
| 1579 | fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr { | 2555 | fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr { |
| 1580 | const flush = &wasm.flush_buffer; | 2556 | const flush = &wasm.flush_buffer; |
| 1581 | if (wasm.object_data_imports.getPtr(name)) |import| { | 2557 | if (wasm.object_data_imports.getPtr(name)) |import| { |
| 1582 | return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend); | 2558 | if (import.resolution != .unresolved) { |
| 1583 | } else if (wasm.data_imports.get(name)) |id| { | 2559 | return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend); |
| 2560 | } | ||
| 2561 | } | ||
| 2562 | if (flush.data_exports.get(name)) |symbol| { | ||
| 2563 | return fromDataLoc(flush, symbol.resolution.dataLoc(wasm), addend); | ||
| 2564 | } | ||
| 2565 | if (wasm.data_imports.get(name)) |id| { | ||
| 1584 | return fromDataLoc(flush, .fromDataImportId(wasm, id), addend); | 2566 | return fromDataLoc(flush, .fromDataImportId(wasm, id), addend); |
| 1585 | } else { | ||
| 1586 | unreachable; | ||
| 1587 | } | 2567 | } |
| 2568 | unreachable; | ||
| 1588 | } | 2569 | } |
| 1589 | 2570 | ||
| 1590 | fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr { | 2571 | fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr { |
| ... | @@ -1702,13 +2683,11 @@ fn emitInitMemoryFunction( | ... | @@ -1702,13 +2683,11 @@ fn emitInitMemoryFunction( |
| 1702 | } | 2683 | } |
| 1703 | 2684 | ||
| 1704 | const segment_groups = wasm.flush_buffer.data_segment_groups.items; | 2685 | const segment_groups = wasm.flush_buffer.data_segment_groups.items; |
| 1705 | var prev_end: u32 = 0; | ||
| 1706 | for (segment_groups, 0..) |group, segment_index| { | 2686 | for (segment_groups, 0..) |group, segment_index| { |
| 1707 | defer prev_end = group.end_addr; | ||
| 1708 | const segment = group.first_segment; | 2687 | const segment = group.first_segment; |
| 1709 | if (!segment.isPassive(wasm)) continue; | 2688 | if (!segment.isPassive(wasm)) continue; |
| 1710 | 2689 | ||
| 1711 | const start_addr: u32 = @intCast(segment.alignment(wasm).forward(prev_end)); | 2690 | const start_addr = wasm.flush_buffer.data_segments.get(segment).?; |
| 1712 | const segment_size: u32 = group.end_addr - start_addr; | 2691 | const segment_size: u32 = group.end_addr - start_addr; |
| 1713 | 2692 | ||
| 1714 | try binary_bytes.ensureUnusedCapacity(gpa, 6 + 6 + 1 + 5 + 6 + 6 + 1 + 6 * 2 + 1 + 1); | 2693 | try binary_bytes.ensureUnusedCapacity(gpa, 6 + 6 + 1 + 5 + 6 + 6 + 1 + 6 * 2 + 1 + 1); |
| ... | @@ -2028,11 +3007,15 @@ fn appendReservedUleb32(bytes: *ArrayList(u8), val: u32) void { | ... | @@ -2028,11 +3007,15 @@ fn appendReservedUleb32(bytes: *ArrayList(u8), val: u32) void { |
| 2028 | }; | 3007 | }; |
| 2029 | } | 3008 | } |
| 2030 | 3009 | ||
| 2031 | fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u32) Allocator.Error!void { | 3010 | fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u64, is64: bool) Allocator.Error!void { |
| 2032 | try bytes.ensureUnusedCapacity(gpa, 9); | 3011 | try bytes.ensureUnusedCapacity(gpa, if (is64) 14 else 9); |
| 2033 | bytes.appendAssumeCapacity(@backingInt(std.wasm.Valtype.i32)); | 3012 | bytes.appendAssumeCapacity(@backingInt(@as(std.wasm.Valtype, if (is64) .i64 else .i32))); |
| 2034 | bytes.appendAssumeCapacity(mutable); | 3013 | bytes.appendAssumeCapacity(mutable); |
| 2035 | appendReservedI32Const(bytes, val); | 3014 | if (is64) { |
| 3015 | appendReservedI64Const(bytes, val); | ||
| 3016 | } else { | ||
| 3017 | appendReservedI32Const(bytes, @intCast(val)); | ||
| 3018 | } | ||
| 2036 | bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end)); | 3019 | bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end)); |
| 2037 | } | 3020 | } |
| 2038 | 3021 |
src/link/Wasm/Object.zig+1-1| ... | @@ -146,7 +146,7 @@ pub const Symbol = struct { | ... | @@ -146,7 +146,7 @@ pub const Symbol = struct { |
| 146 | pointee: Pointee, | 146 | pointee: Pointee, |
| 147 | 147 | ||
| 148 | /// https://github.com/WebAssembly/tool-conventions/blob/df8d737539eb8a8f446ba5eab9dc670c40dfb81e/Linking.md#symbol-table-subsection | 148 | /// https://github.com/WebAssembly/tool-conventions/blob/df8d737539eb8a8f446ba5eab9dc670c40dfb81e/Linking.md#symbol-table-subsection |
| 149 | const Tag = enum(u8) { | 149 | pub const Tag = enum(u8) { |
| 150 | function, | 150 | function, |
| 151 | data, | 151 | data, |
| 152 | global, | 152 | global, |
src/target.zig+1-1| ... | @@ -437,7 +437,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target) enum { no, yes, llvm_onl | ... | @@ -437,7 +437,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target) enum { no, yes, llvm_onl |
| 437 | else => {}, | 437 | else => {}, |
| 438 | } | 438 | } |
| 439 | return switch (zigBackend(target, false)) { | 439 | return switch (zigBackend(target, false)) { |
| 440 | .stage2_aarch64, .stage2_x86_64 => .yes, | 440 | .stage2_aarch64, .stage2_wasm, .stage2_x86_64 => .yes, |
| 441 | else => .llvm_only, | 441 | else => .llvm_only, |
| 442 | }; | 442 | }; |
| 443 | } | 443 | } |
test/behavior/basic.zig-1| ... | @@ -797,7 +797,6 @@ test "auto created variables have correct alignment" { | ... | @@ -797,7 +797,6 @@ test "auto created variables have correct alignment" { |
| 797 | } | 797 | } |
| 798 | 798 | ||
| 799 | test "extern variable with non-pointer opaque type" { | 799 | test "extern variable with non-pointer opaque type" { |
| 800 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 801 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 800 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 802 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 801 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 803 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO | 802 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO |
test/behavior/builtin_functions_returning_void_or_noreturn.zig-1| ... | @@ -6,7 +6,6 @@ var x: u8 = 1; | ... | @@ -6,7 +6,6 @@ var x: u8 = 1; |
| 6 | 6 | ||
| 7 | // This excludes builtin functions that return void or noreturn that cannot be tested. | 7 | // This excludes builtin functions that return void or noreturn that cannot be tested. |
| 8 | test { | 8 | test { |
| 9 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 11 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 12 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 11 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/behavior/call.zig-1| ... | @@ -21,7 +21,6 @@ test "super basic invocations" { | ... | @@ -21,7 +21,6 @@ test "super basic invocations" { |
| 21 | 21 | ||
| 22 | test "basic invocations" { | 22 | test "basic invocations" { |
| 23 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 23 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 24 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 25 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 24 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 26 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 25 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 27 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 26 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/behavior/export_builtin.zig-15| ... | @@ -5,11 +5,6 @@ const expect = std.testing.expect; | ... | @@ -5,11 +5,6 @@ const expect = std.testing.expect; |
| 5 | test "exporting enum value" { | 5 | test "exporting enum value" { |
| 6 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 6 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 7 | 7 | ||
| 8 | if (builtin.cpu.arch.isWasm()) { | ||
| 9 | // https://github.com/ziglang/zig/issues/4866 | ||
| 10 | return error.SkipZigTest; | ||
| 11 | } | ||
| 12 | |||
| 13 | const S = struct { | 8 | const S = struct { |
| 14 | const E = enum(c_int) { one, two }; | 9 | const E = enum(c_int) { one, two }; |
| 15 | const e: E = .two; | 10 | const e: E = .two; |
| ... | @@ -35,11 +30,6 @@ test "exporting with internal linkage" { | ... | @@ -35,11 +30,6 @@ test "exporting with internal linkage" { |
| 35 | test "exporting using namespace access" { | 30 | test "exporting using namespace access" { |
| 36 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 31 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 37 | 32 | ||
| 38 | if (builtin.cpu.arch.isWasm()) { | ||
| 39 | // https://github.com/ziglang/zig/issues/4866 | ||
| 40 | return error.SkipZigTest; | ||
| 41 | } | ||
| 42 | |||
| 43 | const S = struct { | 33 | const S = struct { |
| 44 | const Inner = struct { | 34 | const Inner = struct { |
| 45 | const x: u32 = 5; | 35 | const x: u32 = 5; |
| ... | @@ -57,11 +47,6 @@ test "exporting comptime-known value" { | ... | @@ -57,11 +47,6 @@ test "exporting comptime-known value" { |
| 57 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 47 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 58 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 48 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 59 | 49 | ||
| 60 | if (builtin.cpu.arch.isWasm()) { | ||
| 61 | // https://github.com/ziglang/zig/issues/4866 | ||
| 62 | return error.SkipZigTest; | ||
| 63 | } | ||
| 64 | |||
| 65 | const x: u32 = 10; | 50 | const x: u32 = 10; |
| 66 | @export(&x, .{ .name = "exporting_comptime_known_value_foo" }); | 51 | @export(&x, .{ .name = "exporting_comptime_known_value_foo" }); |
| 67 | const S = struct { | 52 | const S = struct { |
test/behavior/fn.zig-1| ... | @@ -418,7 +418,6 @@ test "import passed byref to function in return type" { | ... | @@ -418,7 +418,6 @@ test "import passed byref to function in return type" { |
| 418 | 418 | ||
| 419 | test "implicit cast function to function ptr" { | 419 | test "implicit cast function to function ptr" { |
| 420 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 420 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 421 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 422 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 421 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 423 | 422 | ||
| 424 | const S1 = struct { | 423 | const S1 = struct { |
test/tests.zig-1| ... | @@ -1568,7 +1568,6 @@ const module_test_targets = blk: { | ... | @@ -1568,7 +1568,6 @@ const module_test_targets = blk: { |
| 1568 | .os_tag = .wasi, | 1568 | .os_tag = .wasi, |
| 1569 | .abi = .none, | 1569 | .abi = .none, |
| 1570 | }, | 1570 | }, |
| 1571 | .skip_modules = &.{"compiler-rt"}, | ||
| 1572 | .use_llvm = false, | 1571 | .use_llvm = false, |
| 1573 | .use_lld = false, | 1572 | .use_lld = false, |
| 1574 | }, | 1573 | }, |