| ... | ... | @@ -3818,13 +3818,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3818 | 3818 | } |
| 3819 | 3819 | |
| 3820 | 3820 | fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { |
| 3821 | | const mod = self.bin_file.options.module.?; |
| 3822 | | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 3823 | | const atom = switch (self.bin_file.tag) { |
| 3824 | | .elf => &fn_owner_decl.link.elf.dbg_info_atom, |
| 3825 | | .macho => &fn_owner_decl.link.macho.dbg_info_atom, |
| 3826 | | else => unreachable, |
| 3827 | | }; |
| 3821 | const atom = self.getDbgInfoAtomPtr(); |
| 3828 | 3822 | |
| 3829 | 3823 | switch (self.debug_output) { |
| 3830 | 3824 | .dwarf => |dw| switch (mcv) { |
| ... | ... | @@ -3845,6 +3839,64 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { |
| 3845 | 3839 | } |
| 3846 | 3840 | } |
| 3847 | 3841 | |
| 3842 | fn genVarDbgInfo( |
| 3843 | self: Self, |
| 3844 | tag: Air.Inst.Tag, |
| 3845 | ty: Type, |
| 3846 | mcv: MCValue, |
| 3847 | name: [:0]const u8, |
| 3848 | ) !void { |
| 3849 | const is_ptr = switch (tag) { |
| 3850 | .dbg_var_ptr => true, |
| 3851 | .dbg_var_val => false, |
| 3852 | else => unreachable, |
| 3853 | }; |
| 3854 | const atom = self.getDbgInfoAtomPtr(); |
| 3855 | |
| 3856 | switch (self.debug_output) { |
| 3857 | .dwarf => |dw| { |
| 3858 | const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (mcv) { |
| 3859 | .register => |reg| .{ |
| 3860 | .register = reg.dwarfLocOp(), |
| 3861 | }, |
| 3862 | .ptr_stack_offset, |
| 3863 | .stack_offset, |
| 3864 | => |off| .{ .stack = .{ |
| 3865 | .fp_register = Register.rbp.dwarfLocOpDeref(), |
| 3866 | .offset = -off, |
| 3867 | } }, |
| 3868 | .memory => |address| .{ |
| 3869 | .memory = .{ |
| 3870 | .address = address, |
| 3871 | .is_ptr = is_ptr, |
| 3872 | }, |
| 3873 | }, |
| 3874 | .immediate => |x| .{ .immediate = x }, |
| 3875 | .undef => .undef, |
| 3876 | .none => .none, |
| 3877 | else => blk: { |
| 3878 | log.debug("TODO generate debug info for {}", .{mcv}); |
| 3879 | break :blk .nop; |
| 3880 | }, |
| 3881 | }; |
| 3882 | try dw.genVarDbgInfo(name, ty, atom, loc); |
| 3883 | }, |
| 3884 | .plan9 => {}, |
| 3885 | .none => {}, |
| 3886 | } |
| 3887 | } |
| 3888 | |
| 3889 | fn getDbgInfoAtomPtr(self: Self) *link.File.Dwarf.Atom { |
| 3890 | const mod = self.bin_file.options.module.?; |
| 3891 | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 3892 | const atom = switch (self.bin_file.tag) { |
| 3893 | .elf => &fn_owner_decl.link.elf.dbg_info_atom, |
| 3894 | .macho => &fn_owner_decl.link.macho.dbg_info_atom, |
| 3895 | else => unreachable, |
| 3896 | }; |
| 3897 | return atom; |
| 3898 | } |
| 3899 | |
| 3848 | 3900 | fn airBreakpoint(self: *Self) !void { |
| 3849 | 3901 | _ = try self.addInst(.{ |
| 3850 | 3902 | .tag = .interrupt, |
| ... | ... | @@ -4413,163 +4465,6 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 4413 | 4465 | return self.finishAir(inst, .dead, .{ operand, .none, .none }); |
| 4414 | 4466 | } |
| 4415 | 4467 | |
| 4416 | | fn genVarDbgInfo( |
| 4417 | | self: Self, |
| 4418 | | tag: Air.Inst.Tag, |
| 4419 | | ty: Type, |
| 4420 | | mcv: MCValue, |
| 4421 | | name: [:0]const u8, |
| 4422 | | ) !void { |
| 4423 | | const name_with_null = name.ptr[0 .. name.len + 1]; |
| 4424 | | switch (self.debug_output) { |
| 4425 | | .dwarf => |dw| { |
| 4426 | | const dbg_info = &dw.dbg_info; |
| 4427 | | try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); |
| 4428 | | const endian = self.target.cpu.arch.endian(); |
| 4429 | | |
| 4430 | | switch (mcv) { |
| 4431 | | .register => |reg| { |
| 4432 | | try dbg_info.ensureUnusedCapacity(2); |
| 4433 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 4434 | | 1, // ULEB128 dwarf expression length |
| 4435 | | reg.dwarfLocOp(), |
| 4436 | | }); |
| 4437 | | }, |
| 4438 | | |
| 4439 | | .ptr_stack_offset, |
| 4440 | | .stack_offset, |
| 4441 | | => |off| { |
| 4442 | | try dbg_info.ensureUnusedCapacity(7); |
| 4443 | | const fixup = dbg_info.items.len; |
| 4444 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 4445 | | 1, // we will backpatch it after we encode the displacement in LEB128 |
| 4446 | | Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer |
| 4447 | | }); |
| 4448 | | leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable; |
| 4449 | | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); |
| 4450 | | }, |
| 4451 | | |
| 4452 | | .memory, |
| 4453 | | .linker_load, |
| 4454 | | => { |
| 4455 | | const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8)); |
| 4456 | | const is_ptr = switch (tag) { |
| 4457 | | .dbg_var_ptr => true, |
| 4458 | | .dbg_var_val => false, |
| 4459 | | else => unreachable, |
| 4460 | | }; |
| 4461 | | try dbg_info.ensureUnusedCapacity(2 + ptr_width); |
| 4462 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 4463 | | 1 + ptr_width + @boolToInt(is_ptr), |
| 4464 | | DW.OP.addr, // literal address |
| 4465 | | }); |
| 4466 | | const offset = @intCast(u32, dbg_info.items.len); |
| 4467 | | const addr = switch (mcv) { |
| 4468 | | .memory => |addr| addr, |
| 4469 | | else => 0, |
| 4470 | | }; |
| 4471 | | switch (ptr_width) { |
| 4472 | | 0...4 => { |
| 4473 | | try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian); |
| 4474 | | }, |
| 4475 | | 5...8 => { |
| 4476 | | try dbg_info.writer().writeInt(u64, addr, endian); |
| 4477 | | }, |
| 4478 | | else => unreachable, |
| 4479 | | } |
| 4480 | | if (is_ptr) { |
| 4481 | | // We need deref the address as we point to the value via GOT entry. |
| 4482 | | try dbg_info.append(DW.OP.deref); |
| 4483 | | } |
| 4484 | | switch (mcv) { |
| 4485 | | .linker_load => |load_struct| try dw.addExprlocReloc( |
| 4486 | | load_struct.sym_index, |
| 4487 | | offset, |
| 4488 | | is_ptr, |
| 4489 | | ), |
| 4490 | | else => {}, |
| 4491 | | } |
| 4492 | | }, |
| 4493 | | |
| 4494 | | .immediate => |x| { |
| 4495 | | try dbg_info.ensureUnusedCapacity(2); |
| 4496 | | const fixup = dbg_info.items.len; |
| 4497 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 4498 | | 1, |
| 4499 | | if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu, |
| 4500 | | }); |
| 4501 | | if (ty.isSignedInt()) { |
| 4502 | | try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); |
| 4503 | | } else { |
| 4504 | | try leb128.writeULEB128(dbg_info.writer(), x); |
| 4505 | | } |
| 4506 | | try dbg_info.append(DW.OP.stack_value); |
| 4507 | | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); |
| 4508 | | }, |
| 4509 | | |
| 4510 | | .undef => { |
| 4511 | | // DW.AT.location, DW.FORM.exprloc |
| 4512 | | // uleb128(exprloc_len) |
| 4513 | | // DW.OP.implicit_value uleb128(len_of_bytes) bytes |
| 4514 | | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 4515 | | var implicit_value_len = std.ArrayList(u8).init(self.gpa); |
| 4516 | | defer implicit_value_len.deinit(); |
| 4517 | | try leb128.writeULEB128(implicit_value_len.writer(), abi_size); |
| 4518 | | const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size; |
| 4519 | | try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len); |
| 4520 | | try dbg_info.ensureUnusedCapacity(total_exprloc_len); |
| 4521 | | dbg_info.appendAssumeCapacity(DW.OP.implicit_value); |
| 4522 | | dbg_info.appendSliceAssumeCapacity(implicit_value_len.items); |
| 4523 | | dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size); |
| 4524 | | }, |
| 4525 | | |
| 4526 | | .none => { |
| 4527 | | try dbg_info.ensureUnusedCapacity(3); |
| 4528 | | dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc |
| 4529 | | 2, DW.OP.lit0, DW.OP.stack_value, |
| 4530 | | }); |
| 4531 | | }, |
| 4532 | | |
| 4533 | | else => { |
| 4534 | | try dbg_info.ensureUnusedCapacity(2); |
| 4535 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 4536 | | 1, DW.OP.nop, |
| 4537 | | }); |
| 4538 | | log.debug("TODO generate debug info for {}", .{mcv}); |
| 4539 | | }, |
| 4540 | | } |
| 4541 | | |
| 4542 | | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); |
| 4543 | | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 |
| 4544 | | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string |
| 4545 | | }, |
| 4546 | | .plan9 => {}, |
| 4547 | | .none => {}, |
| 4548 | | } |
| 4549 | | } |
| 4550 | | |
| 4551 | | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, |
| 4552 | | /// after codegen for this symbol is done. |
| 4553 | | fn addDbgInfoTypeReloc(self: Self, ty: Type) !void { |
| 4554 | | switch (self.debug_output) { |
| 4555 | | .dwarf => |dw| { |
| 4556 | | const dbg_info = &dw.dbg_info; |
| 4557 | | const index = dbg_info.items.len; |
| 4558 | | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 |
| 4559 | | const mod = self.bin_file.options.module.?; |
| 4560 | | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 4561 | | const atom = switch (self.bin_file.tag) { |
| 4562 | | .elf => &fn_owner_decl.link.elf.dbg_info_atom, |
| 4563 | | .macho => &fn_owner_decl.link.macho.dbg_info_atom, |
| 4564 | | else => unreachable, |
| 4565 | | }; |
| 4566 | | try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); |
| 4567 | | }, |
| 4568 | | .plan9 => {}, |
| 4569 | | .none => {}, |
| 4570 | | } |
| 4571 | | } |
| 4572 | | |
| 4573 | 4468 | fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { |
| 4574 | 4469 | const abi_size = ty.abiSize(self.target.*); |
| 4575 | 4470 | switch (mcv) { |