diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index cb2578bee9..947174aaed 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1362,7 +1362,6 @@ fn isByRef(ty: Type, target: std.Target) bool { .NoReturn, .Void, .Bool, - .Float, .ErrorSet, .Fn, .Enum, @@ -1375,7 +1374,8 @@ fn isByRef(ty: Type, target: std.Target) bool { .Frame, .Union, => return ty.hasRuntimeBitsIgnoreComptime(), - .Int => return if (ty.intInfo(target).bits > 64) true else false, + .Int => return ty.intInfo(target).bits > 64, + .Float => return ty.floatBits(target) > 64, .ErrorUnion => { const has_tag = ty.errorUnionSet().hasRuntimeBitsIgnoreComptime(); const has_pl = ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime(); @@ -4326,7 +4326,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index, is_ptr: bool) !WValue { try self.addDbgInfoTypeReloc(op_ty); dbg_info.appendSliceAssumeCapacity(name); dbg_info.appendAssumeCapacity(0); - try return WValue{ .none = {} }; + return WValue{ .none = {} }; } fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index a7d2744491..a204dd91ae 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -851,6 +851,10 @@ pub fn commitDeclState( const file_pos = debug_line_sect.offset + src_fn.off; try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len); }, + .wasm => { + const wasm_file = file.cast(File.Wasm).?; + writeDbgLineNopsBuffered(wasm_file.debug_line.items, src_fn.off, 0, &.{}, src_fn.len); + }, else => unreachable, } // TODO Look at the free list before appending at the end. @@ -972,9 +976,16 @@ pub fn commitDeclState( mem.set(u8, debug_line.items[segment.size..], 0); } segment.size = needed_size; + debug_line.items.len = needed_size; } const offset = segment.offset + src_fn.off; - mem.copy(u8, debug_line.items[offset..], dbg_line_buffer.items); + writeDbgLineNopsBuffered( + debug_line.items, + offset, + prev_padding_size, + dbg_line_buffer.items, + next_padding_size, + ); }, else => unreachable, } @@ -1114,7 +1125,8 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false); }, .wasm => { - log.debug(" todo: updateDeclDebugInfoAllocation for Wasm: {d}", .{atom.len}); + const wasm_file = file.cast(File.Wasm).?; + writeDbgInfoNopsBuffered(wasm_file.debug_info.items, atom.off, 0, &.{0}, atom.len, false); }, else => unreachable, } @@ -1253,9 +1265,17 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co mem.set(u8, debug_info.items[segment.size..], 0); } segment.size = needed_size; + debug_info.items.len = needed_size; } const offset = segment.offset + atom.off; - mem.copy(u8, debug_info.items[offset..], dbg_info_buf); + writeDbgInfoNopsBuffered( + debug_info.items, + offset, + prev_padding_size, + dbg_info_buf, + next_padding_size, + trailing_zero, + ); }, else => unreachable, } @@ -1643,7 +1663,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6 }, .wasm => { const wasm_file = file.cast(File.Wasm).?; - mem.copy(u8, wasm_file.debug_info.items, di_buf.items); + writeDbgInfoNopsBuffered(wasm_file.debug_info.items, 0, 0, di_buf.items, jmp_amt, false); }, else => unreachable, } @@ -1738,6 +1758,45 @@ fn pwriteDbgLineNops( try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); } +fn writeDbgLineNopsBuffered( + buf: []u8, + offset: u32, + prev_padding_size: usize, + content: []const u8, + next_padding_size: usize, +) void { + assert(buf.len >= content.len + prev_padding_size + next_padding_size); + const tracy = trace(@src()); + defer tracy.end(); + + const three_byte_nop = [3]u8{ DW.LNS.advance_pc, 0b1000_0000, 0 }; + { + var padding_left = prev_padding_size; + if (padding_left % 2 != 0) { + buf[offset - padding_left ..][0..3].* = three_byte_nop; + padding_left -= 3; + } + + while (padding_left > 0) : (padding_left -= 1) { + buf[offset - padding_left] = DW.LNS.negate_stmt; + } + } + + mem.copy(u8, buf[offset..], content); + + { + var padding_left = next_padding_size; + if (padding_left % 2 != 0) { + buf[offset + content.len + padding_left ..][0..3].* = three_byte_nop; + padding_left -= 3; + } + + while (padding_left > 0) : (padding_left -= 1) { + buf[offset + content.len + padding_left] = DW.LNS.negate_stmt; + } + } +} + /// Writes to the file a buffer, prefixed and suffixed by the specified number of /// bytes of padding. fn pwriteDbgInfoNops( @@ -1810,6 +1869,38 @@ fn pwriteDbgInfoNops( try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); } +fn writeDbgInfoNopsBuffered( + buf: []u8, + offset: u32, + prev_padding_size: usize, + content: []const u8, + next_padding_size: usize, + trailing_zero: bool, +) void { + assert(buf.len >= content.len + prev_padding_size + next_padding_size + @boolToInt(trailing_zero)); + const tracy = trace(@src()); + defer tracy.end(); + + { + var padding_left = prev_padding_size; + while (padding_left > 0) : (padding_left -= 1) { + buf[offset - padding_left] = @enumToInt(AbbrevKind.pad1); + } + } + + mem.copy(u8, buf[offset..], content); + { + var padding_left = next_padding_size; + while (padding_left > 0) : (padding_left -= 1) { + buf[offset + content.len + padding_left] = @enumToInt(AbbrevKind.pad1); + } + } + + if (trailing_zero) { + buf[offset + content.len + next_padding_size] = 0; + } +} + pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void { const target_endian = self.target.cpu.arch.endian(); const init_len_size: usize = if (self.tag == .macho) @@ -1909,6 +2000,11 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void { const file_pos = debug_aranges_sect.offset; try d_sym.file.pwriteAll(di_buf.items, file_pos); }, + .wasm => { + const wasm_file = file.cast(File.Wasm).?; + try wasm_file.debug_aranges.resize(wasm_file.base.allocator, needed_size); + mem.copy(u8, wasm_file.debug_aranges.items, di_buf.items); + }, else => unreachable, } } @@ -2030,7 +2126,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void { }, .wasm => { const wasm_file = file.cast(File.Wasm).?; - mem.copy(u8, wasm_file.debug_line.items, di_buf.items); + writeDbgLineNopsBuffered(wasm_file.debug_line.items, 0, 0, di_buf.items, jmp_amt); }, else => unreachable, } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 4cc21260c3..d8c87703a6 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -97,6 +97,8 @@ debug_info: std.ArrayListUnmanaged(u8) = .{}, debug_line: std.ArrayListUnmanaged(u8) = .{}, /// Contains all bytes for the '.debug_abbrev' section debug_abbrev: std.ArrayListUnmanaged(u8) = .{}, +/// Contains all bytes for the '.debug_ranges' section +debug_aranges: std.ArrayListUnmanaged(u8) = .{}, // Output sections /// Output type section @@ -513,6 +515,7 @@ pub fn deinit(self: *Wasm) void { self.debug_info.deinit(gpa); self.debug_line.deinit(gpa); self.debug_abbrev.deinit(gpa); + self.debug_aranges.deinit(gpa); } pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void { @@ -1928,6 +1931,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod } // Code section + var code_section_size: u32 = 0; if (self.code_section_index) |code_index| { const header_offset = try reserveVecSectionHeader(file); const writer = file.writer(); @@ -1940,11 +1944,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod try writer.writeAll(atom.code.items); atom = atom.next orelse break; } + + code_section_size = @intCast(u32, (try file.getPos()) - header_offset - header_size); try writeVecSectionHeader( file, header_offset, .code, - @intCast(u32, (try file.getPos()) - header_offset - header_size), + code_section_size, @intCast(u32, self.functions.items.len), ); code_section_index = section_count; @@ -2032,13 +2038,16 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod } else if (!self.base.options.strip) { if (self.dwarf) |*dwarf| { if (self.debug_info_index != null) { - _ = dwarf; try dwarf.writeDbgAbbrev(&self.base); - try dwarf.writeDbgInfoHeader(&self.base, mod, 0, 0); + // for debug info and ranges, the address is always 0, + // as locations are always offsets relative to 'code' section. + try dwarf.writeDbgInfoHeader(&self.base, mod, 0, code_section_size); + try dwarf.writeDbgAranges(&self.base, 0, code_section_size); try dwarf.writeDbgLineHeader(&self.base, mod); try emitDebugSection(file, self.debug_info.items, ".debug_info"); - try emitDebugSection(file, self.debug_abbrev.items, ".debug_abbrev"); // TODO + try emitDebugSection(file, self.debug_aranges.items, ".debug_ranges"); + try emitDebugSection(file, self.debug_abbrev.items, ".debug_abbrev"); try emitDebugSection(file, self.debug_line.items, ".debug_line"); try emitDebugSection(file, dwarf.strtab.items, ".debug_str"); } diff --git a/test/behavior/ptrcast.zig b/test/behavior/ptrcast.zig index 10138cff01..c827cb6ef7 100644 --- a/test/behavior/ptrcast.zig +++ b/test/behavior/ptrcast.zig @@ -134,6 +134,7 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: CBE does not yet support under-aligned fields // Test lowering a field ptr @@ -158,6 +159,7 @@ test "lower reinterpreted comptime field ptr" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO // Test lowering a field ptr comptime var bytes align(4) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };