| ... | @@ -3818,13 +3818,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3818,13 +3818,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3818 | } | 3818 | } |
| 3819 | | 3819 | |
| 3820 | fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { | 3820 | fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { |
| 3821 | const mod = self.bin_file.options.module.?; | 3821 | const atom = self.getDbgInfoAtomPtr(); |
| 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 | }; | | |
| 3828 | | 3822 | |
| 3829 | switch (self.debug_output) { | 3823 | switch (self.debug_output) { |
| 3830 | .dwarf => |dw| switch (mcv) { | 3824 | .dwarf => |dw| switch (mcv) { |
| ... | @@ -3845,6 +3839,64 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { | ... | @@ -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 | fn airBreakpoint(self: *Self) !void { | 3900 | fn airBreakpoint(self: *Self) !void { |
| 3849 | _ = try self.addInst(.{ | 3901 | _ = try self.addInst(.{ |
| 3850 | .tag = .interrupt, | 3902 | .tag = .interrupt, |
| ... | @@ -4413,163 +4465,6 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4413,163 +4465,6 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 4413 | return self.finishAir(inst, .dead, .{ operand, .none, .none }); | 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 | fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { | 4468 | fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { |
| 4574 | const abi_size = ty.abiSize(self.target.*); | 4469 | const abi_size = ty.abiSize(self.target.*); |
| 4575 | switch (mcv) { | 4470 | switch (mcv) { |