| ... | @@ -146,11 +146,8 @@ const MCValue = union(enum) { | ... | @@ -146,11 +146,8 @@ const MCValue = union(enum) { |
| 146 | /// If the type is a pointer, it means the pointer address is at | 146 | /// If the type is a pointer, it means the pointer address is at |
| 147 | /// this memory location. | 147 | /// this memory location. |
| 148 | memory: u64, | 148 | memory: u64, |
| 149 | /// The value is in memory but requires a linker relocation fixup: | 149 | /// The value is in memory but requires a linker relocation fixup. |
| 150 | /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) | 150 | linker_load: codegen.LinkerLoad, |
| 151 | /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) | | |
| 152 | /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) | | |
| 153 | linker_load: struct { type: enum { got, direct, import }, sym_index: u32 }, | | |
| 154 | /// The value is one of the stack variables. | 151 | /// The value is one of the stack variables. |
| 155 | /// | 152 | /// |
| 156 | /// If the type is a pointer, it means the pointer address is in | 153 | /// If the type is a pointer, it means the pointer address is in |
| ... | @@ -217,33 +214,23 @@ const DbgInfoReloc = struct { | ... | @@ -217,33 +214,23 @@ const DbgInfoReloc = struct { |
| 217 | } | 214 | } |
| 218 | | 215 | |
| 219 | fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void { | 216 | fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void { |
| 220 | const name_with_null = reloc.name.ptr[0 .. reloc.name.len + 1]; | 217 | const is_ptr = switch (reloc.tag) { |
| 221 | const ty = switch (reloc.tag) { | 218 | .dbg_var_ptr => true, |
| 222 | .dbg_var_ptr => reloc.ty.childType(), | 219 | .dbg_var_val => false, |
| 223 | .dbg_var_val => reloc.ty, | | |
| 224 | else => unreachable, | 220 | else => unreachable, |
| 225 | }; | 221 | }; |
| 226 | // const atom= function.getDbgInfoAtomPtr(); | 222 | const atom = function.getDbgInfoAtomPtr(); |
| 227 | | 223 | |
| 228 | switch (function.debug_output) { | 224 | switch (function.debug_output) { |
| 229 | .dwarf => |dw| { | 225 | .dwarf => |dw| { |
| 230 | const dbg_info = &dw.dbg_info; | 226 | const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (reloc.mcv) { |
| 231 | try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); | 227 | .register => |reg| .{ |
| 232 | const endian = function.target.cpu.arch.endian(); | 228 | .register = reg.dwarfLocOp(), |
| 233 | | | |
| 234 | switch (reloc.mcv) { | | |
| 235 | .register => |reg| { | | |
| 236 | try dbg_info.ensureUnusedCapacity(2); | | |
| 237 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | | |
| 238 | 1, // ULEB128 dwarf expression length | | |
| 239 | reg.dwarfLocOp(), | | |
| 240 | }); | | |
| 241 | }, | 229 | }, |
| 242 | | | |
| 243 | .ptr_stack_offset, | 230 | .ptr_stack_offset, |
| 244 | .stack_offset, | 231 | .stack_offset, |
| 245 | .stack_argument_offset, | 232 | .stack_argument_offset, |
| 246 | => |offset| { | 233 | => |offset| blk: { |
| 247 | const adjusted_offset = switch (reloc.mcv) { | 234 | const adjusted_offset = switch (reloc.mcv) { |
| 248 | .ptr_stack_offset, | 235 | .ptr_stack_offset, |
| 249 | .stack_offset, | 236 | .stack_offset, |
| ... | @@ -251,110 +238,31 @@ const DbgInfoReloc = struct { | ... | @@ -251,110 +238,31 @@ const DbgInfoReloc = struct { |
| 251 | .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), | 238 | .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), |
| 252 | else => unreachable, | 239 | else => unreachable, |
| 253 | }; | 240 | }; |
| 254 | | 241 | break :blk .{ |
| 255 | try dbg_info.ensureUnusedCapacity(7); | 242 | .stack = .{ |
| 256 | const fixup = dbg_info.items.len; | 243 | .fp_register = Register.x29.dwarfLocOpDeref(), |
| 257 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | 244 | .offset = adjusted_offset, |
| 258 | 1, // we will backpatch it after we encode the displacement in LEB128 | | |
| 259 | Register.x29.dwarfLocOpDeref(), // frame pointer | | |
| 260 | }); | | |
| 261 | leb128.writeILEB128(dbg_info.writer(), adjusted_offset) catch unreachable; | | |
| 262 | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); | | |
| 263 | }, | | |
| 264 | | | |
| 265 | .memory, | | |
| 266 | .linker_load, | | |
| 267 | => { | | |
| 268 | const ptr_width = @intCast(u8, @divExact(function.target.cpu.arch.ptrBitWidth(), 8)); | | |
| 269 | const is_ptr = switch (reloc.tag) { | | |
| 270 | .dbg_var_ptr => true, | | |
| 271 | .dbg_var_val => false, | | |
| 272 | else => unreachable, | | |
| 273 | }; | | |
| 274 | try dbg_info.ensureUnusedCapacity(2 + ptr_width); | | |
| 275 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | | |
| 276 | 1 + ptr_width + @boolToInt(is_ptr), | | |
| 277 | DW.OP.addr, // literal address | | |
| 278 | }); | | |
| 279 | const offset = @intCast(u32, dbg_info.items.len); | | |
| 280 | const addr = switch (reloc.mcv) { | | |
| 281 | .memory => |addr| addr, | | |
| 282 | else => 0, | | |
| 283 | }; | | |
| 284 | switch (ptr_width) { | | |
| 285 | 0...4 => { | | |
| 286 | try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian); | | |
| 287 | }, | 245 | }, |
| 288 | 5...8 => { | 246 | }; |
| 289 | try dbg_info.writer().writeInt(u64, addr, endian); | | |
| 290 | }, | | |
| 291 | else => unreachable, | | |
| 292 | } | | |
| 293 | if (is_ptr) { | | |
| 294 | // We need deref the address as we point to the value via GOT entry. | | |
| 295 | try dbg_info.append(DW.OP.deref); | | |
| 296 | } | | |
| 297 | switch (reloc.mcv) { | | |
| 298 | .linker_load => |load_struct| try dw.addExprlocReloc( | | |
| 299 | load_struct.sym_index, | | |
| 300 | offset, | | |
| 301 | is_ptr, | | |
| 302 | ), | | |
| 303 | else => {}, | | |
| 304 | } | | |
| 305 | }, | | |
| 306 | | | |
| 307 | .immediate => |x| { | | |
| 308 | try dbg_info.ensureUnusedCapacity(2); | | |
| 309 | const fixup = dbg_info.items.len; | | |
| 310 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | | |
| 311 | 1, | | |
| 312 | if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu, | | |
| 313 | }); | | |
| 314 | if (ty.isSignedInt()) { | | |
| 315 | try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); | | |
| 316 | } else { | | |
| 317 | try leb128.writeULEB128(dbg_info.writer(), x); | | |
| 318 | } | | |
| 319 | try dbg_info.append(DW.OP.stack_value); | | |
| 320 | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); | | |
| 321 | }, | | |
| 322 | | | |
| 323 | .undef => { | | |
| 324 | // DW.AT.location, DW.FORM.exprloc | | |
| 325 | // uleb128(exprloc_len) | | |
| 326 | // DW.OP.implicit_value uleb128(len_of_bytes) bytes | | |
| 327 | const abi_size = @intCast(u32, ty.abiSize(function.target.*)); | | |
| 328 | var implicit_value_len = std.ArrayList(u8).init(function.gpa); | | |
| 329 | defer implicit_value_len.deinit(); | | |
| 330 | try leb128.writeULEB128(implicit_value_len.writer(), abi_size); | | |
| 331 | const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size; | | |
| 332 | try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len); | | |
| 333 | try dbg_info.ensureUnusedCapacity(total_exprloc_len); | | |
| 334 | dbg_info.appendAssumeCapacity(DW.OP.implicit_value); | | |
| 335 | dbg_info.appendSliceAssumeCapacity(implicit_value_len.items); | | |
| 336 | dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size); | | |
| 337 | }, | | |
| 338 | | | |
| 339 | .none => { | | |
| 340 | try dbg_info.ensureUnusedCapacity(3); | | |
| 341 | dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc | | |
| 342 | 2, DW.OP.lit0, DW.OP.stack_value, | | |
| 343 | }); | | |
| 344 | }, | 247 | }, |
| 345 | | 248 | .memory => |address| .{ .memory = .{ |
| 346 | else => { | 249 | .address = address, |
| 347 | try dbg_info.ensureUnusedCapacity(2); | 250 | .is_ptr = is_ptr, |
| 348 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | 251 | } }, |
| 349 | 1, DW.OP.nop, | 252 | .linker_load => |linker_load| .{ .memory = .{ |
| 350 | }); | 253 | .address = 0, |
| | 254 | .is_ptr = is_ptr, |
| | 255 | .linker_load = linker_load, |
| | 256 | } }, |
| | 257 | .immediate => |x| .{ .immediate = x }, |
| | 258 | .undef => .undef, |
| | 259 | .none => .none, |
| | 260 | else => blk: { |
| 351 | log.debug("TODO generate debug info for {}", .{reloc.mcv}); | 261 | log.debug("TODO generate debug info for {}", .{reloc.mcv}); |
| | 262 | break :blk .nop; |
| 352 | }, | 263 | }, |
| 353 | } | 264 | }; |
| 354 | | 265 | try dw.genVarDbgInfo(reloc.name, reloc.ty, atom, loc); |
| 355 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | | |
| 356 | try function.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | | |
| 357 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | | |
| 358 | }, | 266 | }, |
| 359 | .plan9 => {}, | 267 | .plan9 => {}, |
| 360 | .none => {}, | 268 | .none => {}, |
| ... | @@ -1071,28 +979,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { | ... | @@ -1071,28 +979,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 1071 | try table.ensureUnusedCapacity(self.gpa, additional_count); | 979 | try table.ensureUnusedCapacity(self.gpa, additional_count); |
| 1072 | } | 980 | } |
| 1073 | | 981 | |
| 1074 | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, | | |
| 1075 | /// after codegen for this symbol is done. | | |
| 1076 | fn addDbgInfoTypeReloc(self: Self, ty: Type) !void { | | |
| 1077 | switch (self.debug_output) { | | |
| 1078 | .dwarf => |dw| { | | |
| 1079 | const dbg_info = &dw.dbg_info; | | |
| 1080 | const index = dbg_info.items.len; | | |
| 1081 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | | |
| 1082 | const mod = self.bin_file.options.module.?; | | |
| 1083 | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); | | |
| 1084 | const atom = switch (self.bin_file.tag) { | | |
| 1085 | .elf => &fn_owner_decl.link.elf.dbg_info_atom, | | |
| 1086 | .macho => &fn_owner_decl.link.macho.dbg_info_atom, | | |
| 1087 | else => unreachable, | | |
| 1088 | }; | | |
| 1089 | try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); | | |
| 1090 | }, | | |
| 1091 | .plan9 => {}, | | |
| 1092 | .none => {}, | | |
| 1093 | } | | |
| 1094 | } | | |
| 1095 | | | |
| 1096 | fn allocMem( | 982 | fn allocMem( |
| 1097 | self: *Self, | 983 | self: *Self, |
| 1098 | abi_size: u32, | 984 | abi_size: u32, |