authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-08-20 18:41:26-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-20 18:41:26-04:00
log16d74809d44d6bb8db1a32923ef8db43d956e24d
tree78344089f8c4cc2bdc07ea74f0a47b8f500d2fcb
parent0a70455095a19a4c18497e6786ca6139c1cc2892
parent55864e98e08c9d44ee2ea6fc1f3a3c2a98042310
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21140 from jacobly0/self-dwarf

Dwarf: inline calls progress

30 files changed, 1236 insertions(+), 698 deletions(-)

src/Air.zig+14-11
...@@ -456,6 +456,8 @@ pub const Inst = struct {...@@ -456,6 +456,8 @@ pub const Inst = struct {
456 /// Same as `dbg_var_ptr` except the local is a const, not a var, and the456 /// Same as `dbg_var_ptr` except the local is a const, not a var, and the
457 /// operand is the local's value.457 /// operand is the local's value.
458 dbg_var_val,458 dbg_var_val,
459 /// Same as `dbg_var_val` except the local is an inline function argument.
460 dbg_arg_inline,
459 /// ?T => bool461 /// ?T => bool
460 /// Result type is always bool.462 /// Result type is always bool.
461 /// Uses the `un_op` field.463 /// Uses the `un_op` field.
...@@ -1022,10 +1024,7 @@ pub const Inst = struct {...@@ -1022,10 +1024,7 @@ pub const Inst = struct {
1022 ty: Ref,1024 ty: Ref,
1023 /// Index into `extra` of a null-terminated string representing the parameter name.1025 /// Index into `extra` of a null-terminated string representing the parameter name.
1024 /// This is `.none` if debug info is stripped.1026 /// This is `.none` if debug info is stripped.
1025 name: enum(u32) {1027 name: NullTerminatedString,
1026 none = std.math.maxInt(u32),
1027 _,
1028 },
1029 },1028 },
1030 ty_op: struct {1029 ty_op: struct {
1031 ty: Ref,1030 ty: Ref,
...@@ -1440,6 +1439,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1440,6 +1439,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1440 .dbg_stmt,1439 .dbg_stmt,
1441 .dbg_var_ptr,1440 .dbg_var_ptr,
1442 .dbg_var_val,1441 .dbg_var_val,
1442 .dbg_arg_inline,
1443 .store,1443 .store,
1444 .store_safe,1444 .store_safe,
1445 .fence,1445 .fence,
...@@ -1562,14 +1562,16 @@ pub fn value(air: Air, inst: Inst.Ref, pt: Zcu.PerThread) !?Value {...@@ -1562,14 +1562,16 @@ pub fn value(air: Air, inst: Inst.Ref, pt: Zcu.PerThread) !?Value {
1562 return air.typeOfIndex(index, &pt.zcu.intern_pool).onePossibleValue(pt);1562 return air.typeOfIndex(index, &pt.zcu.intern_pool).onePossibleValue(pt);
1563}1563}
15641564
1565pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {1565pub const NullTerminatedString = enum(u32) {
1566 const bytes = std.mem.sliceAsBytes(air.extra[index..]);1566 none = std.math.maxInt(u32),
1567 var end: usize = 0;1567 _,
1568 while (bytes[end] != 0) {1568
1569 end += 1;1569 pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 {
1570 if (nts == .none) return "";
1571 const bytes = std.mem.sliceAsBytes(air.extra[@intFromEnum(nts)..]);
1572 return bytes[0..std.mem.indexOfScalar(u8, bytes, 0).? :0];
1570 }1573 }
1571 return bytes[0..end :0];1574};
1572}
15731575
1574/// Returns whether the given instruction must always be lowered, for instance1576/// Returns whether the given instruction must always be lowered, for instance
1575/// because it can cause side effects. If an instruction does not need to be1577/// because it can cause side effects. If an instruction does not need to be
...@@ -1596,6 +1598,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {...@@ -1596,6 +1598,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1596 .dbg_inline_block,1598 .dbg_inline_block,
1597 .dbg_var_ptr,1599 .dbg_var_ptr,
1598 .dbg_var_val,1600 .dbg_var_val,
1601 .dbg_arg_inline,
1599 .ret,1602 .ret,
1600 .ret_safe,1603 .ret_safe,
1601 .ret_load,1604 .ret_load,
src/Air/types_resolved.zig+1
...@@ -339,6 +339,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {...@@ -339,6 +339,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
339339
340 .dbg_var_ptr,340 .dbg_var_ptr,
341 .dbg_var_val,341 .dbg_var_val,
342 .dbg_arg_inline,
342 => {343 => {
343 if (!checkRef(data.pl_op.operand, zcu)) return false;344 if (!checkRef(data.pl_op.operand, zcu)) return false;
344 },345 },
src/Compilation.zig+20-8
...@@ -2997,14 +2997,26 @@ pub fn saveState(comp: *Compilation) !void {...@@ -2997,14 +2997,26 @@ pub fn saveState(comp: *Compilation) !void {
2997 addBuf(&bufs, mem.sliceAsBytes(ip.free_dep_entries.items));2997 addBuf(&bufs, mem.sliceAsBytes(ip.free_dep_entries.items));
29982998
2999 for (ip.locals, pt_headers.items) |*local, pt_header| {2999 for (ip.locals, pt_headers.items) |*local, pt_header| {
3000 addBuf(&bufs, mem.sliceAsBytes(local.shared.limbs.view().items(.@"0")[0..pt_header.intern_pool.limbs_len]));3000 if (pt_header.intern_pool.limbs_len > 0) {
3001 addBuf(&bufs, mem.sliceAsBytes(local.shared.extra.view().items(.@"0")[0..pt_header.intern_pool.extra_len]));3001 addBuf(&bufs, mem.sliceAsBytes(local.shared.limbs.view().items(.@"0")[0..pt_header.intern_pool.limbs_len]));
3002 addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.data)[0..pt_header.intern_pool.items_len]));3002 }
3003 addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len]));3003 if (pt_header.intern_pool.extra_len > 0) {
3004 addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]);3004 addBuf(&bufs, mem.sliceAsBytes(local.shared.extra.view().items(.@"0")[0..pt_header.intern_pool.extra_len]));
3005 addBuf(&bufs, mem.sliceAsBytes(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len]));3005 }
3006 addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len]));3006 if (pt_header.intern_pool.items_len > 0) {
3007 addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len]));3007 addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.data)[0..pt_header.intern_pool.items_len]));
3008 addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len]));
3009 }
3010 if (pt_header.intern_pool.string_bytes_len > 0) {
3011 addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]);
3012 }
3013 if (pt_header.intern_pool.tracked_insts_len > 0) {
3014 addBuf(&bufs, mem.sliceAsBytes(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len]));
3015 }
3016 if (pt_header.intern_pool.files_len > 0) {
3017 addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len]));
3018 addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len]));
3019 }
3008 }3020 }
30093021
3010 //// TODO: compilation errors3022 //// TODO: compilation errors
src/Liveness.zig+2
...@@ -464,6 +464,7 @@ pub fn categorizeOperand(...@@ -464,6 +464,7 @@ pub fn categorizeOperand(
464464
465 .dbg_var_ptr,465 .dbg_var_ptr,
466 .dbg_var_val,466 .dbg_var_val,
467 .dbg_arg_inline,
467 => {468 => {
468 const o = air_datas[@intFromEnum(inst)].pl_op.operand;469 const o = air_datas[@intFromEnum(inst)].pl_op.operand;
469 if (o == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);470 if (o == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
...@@ -1097,6 +1098,7 @@ fn analyzeInst(...@@ -1097,6 +1098,7 @@ fn analyzeInst(
10971098
1098 .dbg_var_ptr,1099 .dbg_var_ptr,
1099 .dbg_var_val,1100 .dbg_var_val,
1101 .dbg_arg_inline,
1100 => {1102 => {
1101 const operand = inst_datas[@intFromEnum(inst)].pl_op.operand;1103 const operand = inst_datas[@intFromEnum(inst)].pl_op.operand;
1102 return analyzeOperands(a, pass, data, inst, .{ operand, .none, .none });1104 return analyzeOperands(a, pass, data, inst, .{ operand, .none, .none });
src/Liveness/Verify.zig+1
...@@ -157,6 +157,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -157,6 +157,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
157 },157 },
158 .dbg_var_ptr,158 .dbg_var_ptr,
159 .dbg_var_val,159 .dbg_var_val,
160 .dbg_arg_inline,
160 .wasm_memory_grow,161 .wasm_memory_grow,
161 => {162 => {
162 const pl_op = data[@intFromEnum(inst)].pl_op;163 const pl_op = data[@intFromEnum(inst)].pl_op;
src/Sema.zig+11-10
...@@ -376,7 +376,7 @@ pub const Block = struct {...@@ -376,7 +376,7 @@ pub const Block = struct {
376376
377 c_import_buf: ?*std.ArrayList(u8) = null,377 c_import_buf: ?*std.ArrayList(u8) = null,
378378
379 /// If not `null`, this boolean is set when a `dbg_var_ptr` or `dbg_var_val`379 /// If not `null`, this boolean is set when a `dbg_var_ptr`, `dbg_var_val`, or `dbg_arg_inline`.
380 /// instruction is emitted. It signals that the innermost lexically380 /// instruction is emitted. It signals that the innermost lexically
381 /// enclosing `block`/`block_inline` should be translated into a real AIR381 /// enclosing `block`/`block_inline` should be translated into a real AIR
382 /// `block` in order for codegen to match lexical scoping for debug vars.382 /// `block` in order for codegen to match lexical scoping for debug vars.
...@@ -6567,7 +6567,7 @@ fn addDbgVar(...@@ -6567,7 +6567,7 @@ fn addDbgVar(
6567 const operand_ty = sema.typeOf(operand);6567 const operand_ty = sema.typeOf(operand);
6568 const val_ty = switch (air_tag) {6568 const val_ty = switch (air_tag) {
6569 .dbg_var_ptr => operand_ty.childType(mod),6569 .dbg_var_ptr => operand_ty.childType(mod),
6570 .dbg_var_val => operand_ty,6570 .dbg_var_val, .dbg_arg_inline => operand_ty,
6571 else => unreachable,6571 else => unreachable,
6572 };6572 };
6573 if (try sema.typeRequiresComptime(val_ty)) return;6573 if (try sema.typeRequiresComptime(val_ty)) return;
...@@ -6586,25 +6586,26 @@ fn addDbgVar(...@@ -6586,25 +6586,26 @@ fn addDbgVar(
6586 if (block.need_debug_scope) |ptr| ptr.* = true;6586 if (block.need_debug_scope) |ptr| ptr.* = true;
65876587
6588 // Add the name to the AIR.6588 // Add the name to the AIR.
6589 const name_extra_index = try sema.appendAirString(name);6589 const name_nts = try sema.appendAirString(name);
65906590
6591 _ = try block.addInst(.{6591 _ = try block.addInst(.{
6592 .tag = air_tag,6592 .tag = air_tag,
6593 .data = .{ .pl_op = .{6593 .data = .{ .pl_op = .{
6594 .payload = name_extra_index,6594 .payload = @intFromEnum(name_nts),
6595 .operand = operand,6595 .operand = operand,
6596 } },6596 } },
6597 });6597 });
6598}6598}
65996599
6600pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!u32 {6600pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!Air.NullTerminatedString {
6601 const str_extra_index: u32 = @intCast(sema.air_extra.items.len);6601 if (str.len == 0) return .none;
6602 const nts: Air.NullTerminatedString = @enumFromInt(sema.air_extra.items.len);
6602 const elements_used = str.len / 4 + 1;6603 const elements_used = str.len / 4 + 1;
6603 const elements = try sema.air_extra.addManyAsSlice(sema.gpa, elements_used);6604 const elements = try sema.air_extra.addManyAsSlice(sema.gpa, elements_used);
6604 const buffer = mem.sliceAsBytes(elements);6605 const buffer = mem.sliceAsBytes(elements);
6605 @memcpy(buffer[0..str.len], str);6606 @memcpy(buffer[0..str.len], str);
6606 buffer[str.len] = 0;6607 buffer[str.len] = 0;
6607 return str_extra_index;6608 return nts;
6608}6609}
66096610
6610fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6611fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -7748,14 +7749,14 @@ fn analyzeCall(...@@ -7748,14 +7749,14 @@ fn analyzeCall(
7748 const param_name = sema.code.nullTerminatedString(extra.data.name);7749 const param_name = sema.code.nullTerminatedString(extra.data.name);
7749 const inst = sema.inst_map.get(param).?;7750 const inst = sema.inst_map.get(param).?;
77507751
7751 try sema.addDbgVar(&child_block, inst, .dbg_var_val, param_name);7752 try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name);
7752 },7753 },
7753 .param_anytype, .param_anytype_comptime => {7754 .param_anytype, .param_anytype_comptime => {
7754 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok;7755 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok;
7755 const param_name = inst_data.get(sema.code);7756 const param_name = inst_data.get(sema.code);
7756 const inst = sema.inst_map.get(param).?;7757 const inst = sema.inst_map.get(param).?;
77577758
7758 try sema.addDbgVar(&child_block, inst, .dbg_var_val, param_name);7759 try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name);
7759 },7760 },
7760 else => continue,7761 else => continue,
7761 };7762 };
...@@ -8266,7 +8267,7 @@ fn instantiateGenericCall(...@@ -8266,7 +8267,7 @@ fn instantiateGenericCall(
8266 .name = if (child_block.ownerModule().strip)8267 .name = if (child_block.ownerModule().strip)
8267 .none8268 .none
8268 else8269 else
8269 @enumFromInt(try sema.appendAirString(fn_zir.nullTerminatedString(param_name))),8270 try sema.appendAirString(fn_zir.nullTerminatedString(param_name)),
8270 } },8271 } },
8271 }));8272 }));
8272 try child_block.params.append(sema.arena, .{8273 try child_block.params.append(sema.arena, .{
src/Zcu/PerThread.zig+15-13
...@@ -1240,11 +1240,11 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1240,11 +1240,11 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1240 };1240 };
1241 }1241 }
12421242
1243 const nav_already_populated, const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) {1243 const nav_already_populated, const queue_linker_work, const resolve_type = switch (ip.indexToKey(decl_val.toIntern())) {
1244 .func => |f| .{ f.owner_nav == nav_index, false },1244 .func => |f| .{ f.owner_nav == nav_index, true, false },
1245 .variable => |v| .{ false, v.owner_nav == nav_index },1245 .variable => |v| .{ false, v.owner_nav == nav_index, true },
1246 .@"extern" => .{ false, false },1246 .@"extern" => .{ false, false, false },
1247 else => .{ false, true },1247 else => .{ false, true, true },
1248 };1248 };
12491249
1250 if (nav_already_populated) {1250 if (nav_already_populated) {
...@@ -1317,14 +1317,16 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1317,14 +1317,16 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1317 queue_codegen: {1317 queue_codegen: {
1318 if (!queue_linker_work) break :queue_codegen;1318 if (!queue_linker_work) break :queue_codegen;
13191319
1320 // Needed for codegen_nav which will call updateDecl and then the1320 if (resolve_type) {
1321 // codegen backend wants full access to the Decl Type.1321 // Needed for codegen_nav which will call updateDecl and then the
1322 // We also need this for the `isFnOrHasRuntimeBits` check below.1322 // codegen backend wants full access to the Decl Type.
1323 // TODO: we could make the language more lenient by deferring this work1323 // We also need this for the `isFnOrHasRuntimeBits` check below.
1324 // to the `codegen_nav` job.1324 // TODO: we could make the language more lenient by deferring this work
1325 try decl_ty.resolveFully(pt);1325 // to the `codegen_nav` job.
1326 try decl_ty.resolveFully(pt);
1327 }
13261328
1327 if (!decl_ty.isFnOrHasRuntimeBits(pt)) {1329 if (!resolve_type or !decl_ty.hasRuntimeBits(pt)) {
1328 if (zcu.comp.config.use_llvm) break :queue_codegen;1330 if (zcu.comp.config.use_llvm) break :queue_codegen;
1329 if (file.mod.strip) break :queue_codegen;1331 if (file.mod.strip) break :queue_codegen;
1330 }1332 }
...@@ -2158,7 +2160,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!...@@ -2158,7 +2160,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
2158 .name = if (inner_block.ownerModule().strip)2160 .name = if (inner_block.ownerModule().strip)
2159 .none2161 .none
2160 else2162 else
2161 @enumFromInt(try sema.appendAirString(sema.code.nullTerminatedString(param_name))),2163 try sema.appendAirString(sema.code.nullTerminatedString(param_name)),
2162 } },2164 } },
2163 });2165 });
2164 }2166 }
src/arch/aarch64/CodeGen.zig+15-16
...@@ -170,7 +170,9 @@ const DbgInfoReloc = struct {...@@ -170,7 +170,9 @@ const DbgInfoReloc = struct {
170170
171 fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {171 fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
172 switch (reloc.tag) {172 switch (reloc.tag) {
173 .arg => try reloc.genArgDbgInfo(function),173 .arg,
174 .dbg_arg_inline,
175 => try reloc.genArgDbgInfo(function),
174176
175 .dbg_var_ptr,177 .dbg_var_ptr,
176 .dbg_var_val,178 .dbg_var_val,
...@@ -201,7 +203,7 @@ const DbgInfoReloc = struct {...@@ -201,7 +203,7 @@ const DbgInfoReloc = struct {
201 else => unreachable, // not a possible argument203 else => unreachable, // not a possible argument
202204
203 };205 };
204 try dw.genVarDebugInfo(.local_arg, reloc.name, reloc.ty, loc);206 try dw.genLocalDebugInfo(.local_arg, reloc.name, reloc.ty, loc);
205 },207 },
206 .plan9 => {},208 .plan9 => {},
207 .none => {},209 .none => {},
...@@ -237,7 +239,7 @@ const DbgInfoReloc = struct {...@@ -237,7 +239,7 @@ const DbgInfoReloc = struct {
237 break :blk .empty;239 break :blk .empty;
238 },240 },
239 };241 };
240 try dwarf.genVarDebugInfo(.local_var, reloc.name, reloc.ty, loc);242 try dwarf.genLocalDebugInfo(.local_var, reloc.name, reloc.ty, loc);
241 },243 },
242 .plan9 => {},244 .plan9 => {},
243 .none => {},245 .none => {},
...@@ -799,6 +801,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -799,6 +801,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
799 .dbg_inline_block => try self.airDbgInlineBlock(inst),801 .dbg_inline_block => try self.airDbgInlineBlock(inst),
800 .dbg_var_ptr,802 .dbg_var_ptr,
801 .dbg_var_val,803 .dbg_var_val,
804 .dbg_arg_inline,
802 => try self.airDbgVar(inst),805 => try self.airDbgVar(inst),
803806
804 .call => try self.airCall(inst, .auto),807 .call => try self.airCall(inst, .auto),
...@@ -4220,17 +4223,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4220,17 +4223,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
42204223
4221 const ty = self.typeOfIndex(inst);4224 const ty = self.typeOfIndex(inst);
4222 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4225 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
42234226 const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
4224 const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;4227 if (name != .none) try self.dbg_info_relocs.append(self.gpa, .{
4225 if (name_nts != .none) {4228 .tag = tag,
4226 const name = self.air.nullTerminatedString(@intFromEnum(name_nts));4229 .ty = ty,
4227 try self.dbg_info_relocs.append(self.gpa, .{4230 .name = name.toSlice(self.air),
4228 .tag = tag,4231 .mcv = self.args[arg_index],
4229 .ty = ty,4232 });
4230 .name = name,
4231 .mcv = self.args[arg_index],
4232 });
4233 }
42344233
4235 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];4234 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
4236 return self.finishAir(inst, result, .{ .none, .none, .none });4235 return self.finishAir(inst, result, .{ .none, .none, .none });
...@@ -4644,14 +4643,14 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {...@@ -4644,14 +4643,14 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
4644 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4643 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
4645 const ty = self.typeOf(operand);4644 const ty = self.typeOf(operand);
4646 const mcv = try self.resolveInst(operand);4645 const mcv = try self.resolveInst(operand);
4647 const name = self.air.nullTerminatedString(pl_op.payload);4646 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
46484647
4649 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });4648 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });
46504649
4651 try self.dbg_info_relocs.append(self.gpa, .{4650 try self.dbg_info_relocs.append(self.gpa, .{
4652 .tag = tag,4651 .tag = tag,
4653 .ty = ty,4652 .ty = ty,
4654 .name = name,4653 .name = name.toSlice(self.air),
4655 .mcv = mcv,4654 .mcv = mcv,
4656 });4655 });
46574656
src/arch/arm/CodeGen.zig+15-15
...@@ -248,7 +248,9 @@ const DbgInfoReloc = struct {...@@ -248,7 +248,9 @@ const DbgInfoReloc = struct {
248248
249 fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {249 fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
250 switch (reloc.tag) {250 switch (reloc.tag) {
251 .arg => try reloc.genArgDbgInfo(function),251 .arg,
252 .dbg_arg_inline,
253 => try reloc.genArgDbgInfo(function),
252254
253 .dbg_var_ptr,255 .dbg_var_ptr,
254 .dbg_var_val,256 .dbg_var_val,
...@@ -279,7 +281,7 @@ const DbgInfoReloc = struct {...@@ -279,7 +281,7 @@ const DbgInfoReloc = struct {
279 else => unreachable, // not a possible argument281 else => unreachable, // not a possible argument
280 };282 };
281283
282 try dw.genVarDebugInfo(.local_arg, reloc.name, reloc.ty, loc);284 try dw.genLocalDebugInfo(.local_arg, reloc.name, reloc.ty, loc);
283 },285 },
284 .plan9 => {},286 .plan9 => {},
285 .none => {},287 .none => {},
...@@ -315,7 +317,7 @@ const DbgInfoReloc = struct {...@@ -315,7 +317,7 @@ const DbgInfoReloc = struct {
315 break :blk .empty;317 break :blk .empty;
316 },318 },
317 };319 };
318 try dw.genVarDebugInfo(.local_var, reloc.name, reloc.ty, loc);320 try dw.genLocalDebugInfo(.local_var, reloc.name, reloc.ty, loc);
319 },321 },
320 .plan9 => {},322 .plan9 => {},
321 .none => {},323 .none => {},
...@@ -786,6 +788,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -786,6 +788,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
786 .dbg_inline_block => try self.airDbgInlineBlock(inst),788 .dbg_inline_block => try self.airDbgInlineBlock(inst),
787 .dbg_var_ptr,789 .dbg_var_ptr,
788 .dbg_var_val,790 .dbg_var_val,
791 .dbg_arg_inline,
789 => try self.airDbgVar(inst),792 => try self.airDbgVar(inst),
790793
791 .call => try self.airCall(inst, .auto),794 .call => try self.airCall(inst, .auto),
...@@ -4199,16 +4202,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4199,16 +4202,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4199 const ty = self.typeOfIndex(inst);4202 const ty = self.typeOfIndex(inst);
4200 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4203 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
42014204
4202 const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;4205 const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
4203 if (name_nts != .none) {4206 if (name != .none) try self.dbg_info_relocs.append(self.gpa, .{
4204 const name = self.air.nullTerminatedString(@intFromEnum(name_nts));4207 .tag = tag,
4205 try self.dbg_info_relocs.append(self.gpa, .{4208 .ty = ty,
4206 .tag = tag,4209 .name = name.toSlice(self.air),
4207 .ty = ty,4210 .mcv = self.args[arg_index],
4208 .name = name,4211 });
4209 .mcv = self.args[arg_index],
4210 });
4211 }
42124212
4213 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];4213 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
4214 return self.finishAir(inst, result, .{ .none, .none, .none });4214 return self.finishAir(inst, result, .{ .none, .none, .none });
...@@ -4612,14 +4612,14 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {...@@ -4612,14 +4612,14 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
4612 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4612 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
4613 const ty = self.typeOf(operand);4613 const ty = self.typeOf(operand);
4614 const mcv = try self.resolveInst(operand);4614 const mcv = try self.resolveInst(operand);
4615 const name = self.air.nullTerminatedString(pl_op.payload);4615 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
46164616
4617 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });4617 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });
46184618
4619 try self.dbg_info_relocs.append(self.gpa, .{4619 try self.dbg_info_relocs.append(self.gpa, .{
4620 .tag = tag,4620 .tag = tag,
4621 .ty = ty,4621 .ty = ty,
4622 .name = name,4622 .name = name.toSlice(self.air),
4623 .mcv = mcv,4623 .mcv = mcv,
4624 });4624 });
46254625
src/arch/riscv64/CodeGen.zig+16-6
...@@ -1644,6 +1644,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1644,6 +1644,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
16441644
1645 .dbg_var_ptr,1645 .dbg_var_ptr,
1646 .dbg_var_val,1646 .dbg_var_val,
1647 .dbg_arg_inline,
1647 => try func.airDbgVar(inst),1648 => try func.airDbgVar(inst),
16481649
1649 .dbg_inline_block => try func.airDbgInlineBlock(inst),1650 .dbg_inline_block => try func.airDbgInlineBlock(inst),
...@@ -4673,11 +4674,15 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {...@@ -4673,11 +4674,15 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {
4673 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;4674 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
4674 const ty = arg.ty.toType();4675 const ty = arg.ty.toType();
4675 if (arg.name == .none) return;4676 if (arg.name == .none) return;
4676 const name = func.air.nullTerminatedString(@intFromEnum(arg.name));
46774677
4678 switch (func.debug_output) {4678 switch (func.debug_output) {
4679 .dwarf => |dw| switch (mcv) {4679 .dwarf => |dw| switch (mcv) {
4680 .register => |reg| try dw.genVarDebugInfo(.local_arg, name, ty, .{ .reg = reg.dwarfNum() }),4680 .register => |reg| try dw.genLocalDebugInfo(
4681 .local_arg,
4682 arg.name.toSlice(func.air),
4683 ty,
4684 .{ .reg = reg.dwarfNum() },
4685 ),
4681 .load_frame => {},4686 .load_frame => {},
4682 else => {},4687 else => {},
4683 },4688 },
...@@ -5179,16 +5184,17 @@ fn airDbgVar(func: *Func, inst: Air.Inst.Index) !void {...@@ -5179,16 +5184,17 @@ fn airDbgVar(func: *Func, inst: Air.Inst.Index) !void {
5179 const operand = pl_op.operand;5184 const operand = pl_op.operand;
5180 const ty = func.typeOf(operand);5185 const ty = func.typeOf(operand);
5181 const mcv = try func.resolveInst(operand);5186 const mcv = try func.resolveInst(operand);
5187 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
51825188
5183 const name = func.air.nullTerminatedString(pl_op.payload);5189 const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
51845190 try func.genVarDbgInfo(tag, ty, mcv, name.toSlice(func.air));
5185 try func.genVarDbgInfo(ty, mcv, name);
51865191
5187 return func.finishAir(inst, .unreach, .{ operand, .none, .none });5192 return func.finishAir(inst, .unreach, .{ operand, .none, .none });
5188}5193}
51895194
5190fn genVarDbgInfo(5195fn genVarDbgInfo(
5191 func: Func,5196 func: Func,
5197 tag: Air.Inst.Tag,
5192 ty: Type,5198 ty: Type,
5193 mcv: MCValue,5199 mcv: MCValue,
5194 name: []const u8,5200 name: []const u8,
...@@ -5205,7 +5211,11 @@ fn genVarDbgInfo(...@@ -5205,7 +5211,11 @@ fn genVarDbgInfo(
5205 break :blk .empty;5211 break :blk .empty;
5206 },5212 },
5207 };5213 };
5208 try dwarf.genVarDebugInfo(.local_var, name, ty, loc);5214 try dwarf.genLocalDebugInfo(switch (tag) {
5215 else => unreachable,
5216 .dbg_var_ptr, .dbg_var_val => .local_var,
5217 .dbg_arg_inline => .local_arg,
5218 }, name, ty, loc);
5209 },5219 },
5210 .plan9 => {},5220 .plan9 => {},
5211 .none => {},5221 .none => {},
src/arch/sparc64/CodeGen.zig+8-5
...@@ -643,6 +643,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -643,6 +643,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
643 .dbg_inline_block => try self.airDbgInlineBlock(inst),643 .dbg_inline_block => try self.airDbgInlineBlock(inst),
644 .dbg_var_ptr,644 .dbg_var_ptr,
645 .dbg_var_val,645 .dbg_var_val,
646 .dbg_arg_inline,
646 => try self.airDbgVar(inst),647 => try self.airDbgVar(inst),
647648
648 .call => try self.airCall(inst, .auto),649 .call => try self.airCall(inst, .auto),
...@@ -1662,7 +1663,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -1662,7 +1663,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
16621663
1663fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {1664fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
1664 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;1665 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
1665 const name = self.air.nullTerminatedString(pl_op.payload);1666 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
1666 const operand = pl_op.operand;1667 const operand = pl_op.operand;
1667 // TODO emit debug info for this variable1668 // TODO emit debug info for this variable
1668 _ = name;1669 _ = name;
...@@ -3582,13 +3583,15 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {...@@ -3582,13 +3583,15 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3582 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;3583 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
3583 const ty = arg.ty.toType();3584 const ty = arg.ty.toType();
3584 if (arg.name == .none) return;3585 if (arg.name == .none) return;
3585 const name = self.air.nullTerminatedString(@intFromEnum(arg.name));
35863586
3587 switch (self.debug_output) {3587 switch (self.debug_output) {
3588 .dwarf => |dw| switch (mcv) {3588 .dwarf => |dw| switch (mcv) {
3589 .register => |reg| try dw.genVarDebugInfo(.local_arg, name, ty, .{3589 .register => |reg| try dw.genLocalDebugInfo(
3590 .reg = reg.dwarfNum(),3590 .local_arg,
3591 }),3591 arg.name.toSlice(self.air),
3592 ty,
3593 .{ .reg = reg.dwarfNum() },
3594 ),
3592 else => {},3595 else => {},
3593 },3596 },
3594 else => {},3597 else => {},
src/arch/wasm/CodeGen.zig+19-13
...@@ -1917,8 +1917,9 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1917,8 +1917,9 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
19171917
1918 .dbg_stmt => func.airDbgStmt(inst),1918 .dbg_stmt => func.airDbgStmt(inst),
1919 .dbg_inline_block => func.airDbgInlineBlock(inst),1919 .dbg_inline_block => func.airDbgInlineBlock(inst),
1920 .dbg_var_ptr => func.airDbgVar(inst, true),1920 .dbg_var_ptr => func.airDbgVar(inst, .local_var, true),
1921 .dbg_var_val => func.airDbgVar(inst, false),1921 .dbg_var_val => func.airDbgVar(inst, .local_var, false),
1922 .dbg_arg_inline => func.airDbgVar(inst, .local_arg, false),
19221923
1923 .call => func.airCall(inst, .auto),1924 .call => func.airCall(inst, .auto),
1924 .call_always_tail => func.airCall(inst, .always_tail),1925 .call_always_tail => func.airCall(inst, .always_tail),
...@@ -2585,13 +2586,13 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2585,13 +2586,13 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25852586
2586 switch (func.debug_output) {2587 switch (func.debug_output) {
2587 .dwarf => |dwarf| {2588 .dwarf => |dwarf| {
2588 const name_nts = func.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;2589 const name = func.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
2589 if (name_nts != .none) {2590 if (name != .none) try dwarf.genLocalDebugInfo(
2590 const name = func.air.nullTerminatedString(@intFromEnum(name_nts));2591 .local_arg,
2591 try dwarf.genVarDebugInfo(.local_arg, name, arg_ty, .{2592 name.toSlice(func.air),
2592 .wasm_ext = .{ .local = arg.local.value },2593 arg_ty,
2593 });2594 .{ .wasm_ext = .{ .local = arg.local.value } },
2594 }2595 );
2595 },2596 },
2596 else => {},2597 else => {},
2597 }2598 }
...@@ -6454,7 +6455,12 @@ fn airDbgInlineBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6454,7 +6455,12 @@ fn airDbgInlineBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6454 try func.lowerBlock(inst, ty_pl.ty.toType(), @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]));6455 try func.lowerBlock(inst, ty_pl.ty.toType(), @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]));
6455}6456}
64566457
6457fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void {6458fn airDbgVar(
6459 func: *CodeGen,
6460 inst: Air.Inst.Index,
6461 local_tag: link.File.Dwarf.WipNav.LocalTag,
6462 is_ptr: bool,
6463) InnerError!void {
6458 _ = is_ptr;6464 _ = is_ptr;
6459 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});6465 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
64606466
...@@ -6464,8 +6470,8 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void...@@ -6464,8 +6470,8 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void
64646470
6465 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), operand });6471 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), operand });
64666472
6467 const name = func.air.nullTerminatedString(pl_op.payload);6473 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
6468 log.debug(" var name = ({s})", .{name});6474 log.debug(" var name = ({s})", .{name.toSlice(func.air)});
64696475
6470 const loc: link.File.Dwarf.Loc = switch (operand) {6476 const loc: link.File.Dwarf.Loc = switch (operand) {
6471 .local => |local| .{ .wasm_ext = .{ .local = local.value } },6477 .local => |local| .{ .wasm_ext = .{ .local = local.value } },
...@@ -6474,7 +6480,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void...@@ -6474,7 +6480,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void
6474 break :blk .empty;6480 break :blk .empty;
6475 },6481 },
6476 };6482 };
6477 try func.debug_output.dwarf.genVarDebugInfo(.local_var, name, ty, loc);6483 try func.debug_output.dwarf.genLocalDebugInfo(local_tag, name.toSlice(func.air), ty, loc);
64786484
6479 return func.finishAir(inst, .none, &.{});6485 return func.finishAir(inst, .none, &.{});
6480}6486}
src/arch/x86_64/CodeGen.zig+268-238
...@@ -64,8 +64,8 @@ va_info: union {...@@ -64,8 +64,8 @@ va_info: union {
64 sysv: struct {64 sysv: struct {
65 gp_count: u32,65 gp_count: u32,
66 fp_count: u32,66 fp_count: u32,
67 overflow_arg_area: FrameAddr,67 overflow_arg_area: bits.FrameAddr,
68 reg_save_area: FrameAddr,68 reg_save_area: bits.FrameAddr,
69 },69 },
70 win64: struct {},70 win64: struct {},
71},71},
...@@ -81,9 +81,6 @@ mir_instructions: std.MultiArrayList(Mir.Inst) = .{},...@@ -81,9 +81,6 @@ mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
81/// MIR extra data81/// MIR extra data
82mir_extra: std.ArrayListUnmanaged(u32) = .{},82mir_extra: std.ArrayListUnmanaged(u32) = .{},
8383
84stack_args: std.ArrayListUnmanaged(StackVar) = .{},
85stack_vars: std.ArrayListUnmanaged(StackVar) = .{},
86
87/// Byte offset within the source file of the ending curly.84/// Byte offset within the source file of the ending curly.
88end_di_line: u32,85end_di_line: u32,
89end_di_column: u32,86end_di_column: u32,
...@@ -113,10 +110,6 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,...@@ -113,10 +110,6 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,
113110
114const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};111const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
115112
116const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
117const RegisterOffset = struct { reg: Register, off: i32 = 0 };
118const SymbolOffset = struct { sym: u32, off: i32 = 0 };
119
120const Owner = union(enum) {113const Owner = union(enum) {
121 nav_index: InternPool.Nav.Index,114 nav_index: InternPool.Nav.Index,
122 lazy_sym: link.File.LazySymbol,115 lazy_sym: link.File.LazySymbol,
...@@ -174,7 +167,7 @@ pub const MCValue = union(enum) {...@@ -174,7 +167,7 @@ pub const MCValue = union(enum) {
174 /// The value is split across two registers.167 /// The value is split across two registers.
175 register_pair: [2]Register,168 register_pair: [2]Register,
176 /// The value is a constant offset from the value in a register.169 /// The value is a constant offset from the value in a register.
177 register_offset: RegisterOffset,170 register_offset: bits.RegisterOffset,
178 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.171 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
179 register_overflow: struct { reg: Register, eflags: Condition },172 register_overflow: struct { reg: Register, eflags: Condition },
180 /// The value is in memory at a hard-coded address.173 /// The value is in memory at a hard-coded address.
...@@ -182,11 +175,11 @@ pub const MCValue = union(enum) {...@@ -182,11 +175,11 @@ pub const MCValue = union(enum) {
182 memory: u64,175 memory: u64,
183 /// The value is in memory at an address not-yet-allocated by the linker.176 /// The value is in memory at an address not-yet-allocated by the linker.
184 /// This traditionally corresponds to a relocation emitted in a relocatable object file.177 /// This traditionally corresponds to a relocation emitted in a relocatable object file.
185 load_symbol: SymbolOffset,178 load_symbol: bits.SymbolOffset,
186 /// The address of the memory location not-yet-allocated by the linker.179 /// The address of the memory location not-yet-allocated by the linker.
187 lea_symbol: SymbolOffset,180 lea_symbol: bits.SymbolOffset,
188 /// The value is in memory at a constant offset from the address in a register.181 /// The value is in memory at a constant offset from the address in a register.
189 indirect: RegisterOffset,182 indirect: bits.RegisterOffset,
190 /// The value is in memory.183 /// The value is in memory.
191 /// Payload is a symbol index.184 /// Payload is a symbol index.
192 load_direct: u32,185 load_direct: u32,
...@@ -207,10 +200,10 @@ pub const MCValue = union(enum) {...@@ -207,10 +200,10 @@ pub const MCValue = union(enum) {
207 lea_tlv: u32,200 lea_tlv: u32,
208 /// The value stored at an offset from a frame index201 /// The value stored at an offset from a frame index
209 /// Payload is a frame address.202 /// Payload is a frame address.
210 load_frame: FrameAddr,203 load_frame: bits.FrameAddr,
211 /// The address of an offset from a frame index204 /// The address of an offset from a frame index
212 /// Payload is a frame address.205 /// Payload is a frame address.
213 lea_frame: FrameAddr,206 lea_frame: bits.FrameAddr,
214 /// Supports integer_per_element abi207 /// Supports integer_per_element abi
215 elementwise_regs_then_frame: packed struct { regs: u3 = 0, frame_off: i29 = 0, frame_index: FrameIndex },208 elementwise_regs_then_frame: packed struct { regs: u3 = 0, frame_off: i29 = 0, frame_index: FrameIndex },
216 /// This indicates that we have already allocated a frame index for this instruction,209 /// This indicates that we have already allocated a frame index for this instruction,
...@@ -426,10 +419,7 @@ pub const MCValue = union(enum) {...@@ -426,10 +419,7 @@ pub const MCValue = union(enum) {
426 .load_symbol => |sym_off| {419 .load_symbol => |sym_off| {
427 assert(sym_off.off == 0);420 assert(sym_off.off == 0);
428 return .{421 return .{
429 .base = .{ .reloc = .{422 .base = .{ .reloc = sym_off.sym_index },
430 .atom_index = try function.owner.getSymbolIndex(function),
431 .sym_index = sym_off.sym,
432 } },
433 .mod = .{ .rm = .{423 .mod = .{ .rm = .{
434 .size = size,424 .size = size,
435 .disp = sym_off.off,425 .disp = sym_off.off,
...@@ -456,8 +446,8 @@ pub const MCValue = union(enum) {...@@ -456,8 +446,8 @@ pub const MCValue = union(enum) {
456 .register_overflow => |pl| try writer.print("{s}:{s}", .{446 .register_overflow => |pl| try writer.print("{s}:{s}", .{
457 @tagName(pl.eflags), @tagName(pl.reg),447 @tagName(pl.eflags), @tagName(pl.reg),
458 }),448 }),
459 .load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym, pl.off }),449 .load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym_index, pl.off }),
460 .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym, pl.off }),450 .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym_index, pl.off }),
461 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),451 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
462 .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),452 .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
463 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),453 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
...@@ -728,12 +718,6 @@ const InstTracking = struct {...@@ -728,12 +718,6 @@ const InstTracking = struct {
728 }718 }
729};719};
730720
731const StackVar = struct {
732 name: []const u8,
733 type: Type,
734 frame_addr: FrameAddr,
735};
736
737const FrameAlloc = struct {721const FrameAlloc = struct {
738 abi_size: u31,722 abi_size: u31,
739 spill_pad: u3,723 spill_pad: u3,
...@@ -839,8 +823,6 @@ pub fn generate(...@@ -839,8 +823,6 @@ pub fn generate(
839 function.exitlude_jump_relocs.deinit(gpa);823 function.exitlude_jump_relocs.deinit(gpa);
840 function.mir_instructions.deinit(gpa);824 function.mir_instructions.deinit(gpa);
841 function.mir_extra.deinit(gpa);825 function.mir_extra.deinit(gpa);
842 function.stack_args.deinit(gpa);
843 function.stack_vars.deinit(gpa);
844 }826 }
845827
846 wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});828 wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});
...@@ -913,9 +895,6 @@ pub fn generate(...@@ -913,9 +895,6 @@ pub fn generate(
913 else => |e| return e,895 else => |e| return e,
914 };896 };
915897
916 try function.genStackVarDebugInfo(.local_arg, function.stack_args.items);
917 try function.genStackVarDebugInfo(.local_var, function.stack_vars.items);
918
919 var mir: Mir = .{898 var mir: Mir = .{
920 .instructions = function.mir_instructions.toOwnedSlice(),899 .instructions = function.mir_instructions.toOwnedSlice(),
921 .extra = try function.mir_extra.toOwnedSlice(gpa),900 .extra = try function.mir_extra.toOwnedSlice(gpa),
...@@ -924,6 +903,7 @@ pub fn generate(...@@ -924,6 +903,7 @@ pub fn generate(
924 defer mir.deinit(gpa);903 defer mir.deinit(gpa);
925904
926 var emit: Emit = .{905 var emit: Emit = .{
906 .air = function.air,
927 .lower = .{907 .lower = .{
928 .bin_file = bin_file,908 .bin_file = bin_file,
929 .allocator = gpa,909 .allocator = gpa,
...@@ -934,6 +914,13 @@ pub fn generate(...@@ -934,6 +914,13 @@ pub fn generate(
934 .link_mode = comp.config.link_mode,914 .link_mode = comp.config.link_mode,
935 .pic = mod.pic,915 .pic = mod.pic,
936 },916 },
917 .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
918 error.CodegenFail => return Result{ .fail = function.err_msg.? },
919 error.OutOfRegisters => return Result{
920 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
921 },
922 else => |e| return e,
923 },
937 .debug_output = debug_output,924 .debug_output = debug_output,
938 .code = code,925 .code = code,
939 .prev_di_pc = 0,926 .prev_di_pc = 0,
...@@ -1013,14 +1000,15 @@ pub fn generateLazy(...@@ -1013,14 +1000,15 @@ pub fn generateLazy(
1013 else => |e| return e,1000 else => |e| return e,
1014 };1001 };
10151002
1016 var mir = Mir{1003 var mir: Mir = .{
1017 .instructions = function.mir_instructions.toOwnedSlice(),1004 .instructions = function.mir_instructions.toOwnedSlice(),
1018 .extra = try function.mir_extra.toOwnedSlice(gpa),1005 .extra = try function.mir_extra.toOwnedSlice(gpa),
1019 .frame_locs = function.frame_locs.toOwnedSlice(),1006 .frame_locs = function.frame_locs.toOwnedSlice(),
1020 };1007 };
1021 defer mir.deinit(gpa);1008 defer mir.deinit(gpa);
10221009
1023 var emit = Emit{1010 var emit: Emit = .{
1011 .air = function.air,
1024 .lower = .{1012 .lower = .{
1025 .bin_file = bin_file,1013 .bin_file = bin_file,
1026 .allocator = gpa,1014 .allocator = gpa,
...@@ -1031,6 +1019,13 @@ pub fn generateLazy(...@@ -1031,6 +1019,13 @@ pub fn generateLazy(
1031 .link_mode = comp.config.link_mode,1019 .link_mode = comp.config.link_mode,
1032 .pic = mod.pic,1020 .pic = mod.pic,
1033 },1021 },
1022 .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
1023 error.CodegenFail => return Result{ .fail = function.err_msg.? },
1024 error.OutOfRegisters => return Result{
1025 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
1026 },
1027 else => |e| return e,
1028 },
1034 .debug_output = debug_output,1029 .debug_output = debug_output,
1035 .code = code,1030 .code = code,
1036 .prev_di_pc = undefined, // no debug info yet1031 .prev_di_pc = undefined, // no debug info yet
...@@ -1116,7 +1111,7 @@ fn formatWipMir(...@@ -1116,7 +1111,7 @@ fn formatWipMir(
1116) @TypeOf(writer).Error!void {1111) @TypeOf(writer).Error!void {
1117 const comp = data.self.bin_file.comp;1112 const comp = data.self.bin_file.comp;
1118 const mod = comp.root_mod;1113 const mod = comp.root_mod;
1119 var lower = Lower{1114 var lower: Lower = .{
1120 .bin_file = data.self.bin_file,1115 .bin_file = data.self.bin_file,
1121 .allocator = data.self.gpa,1116 .allocator = data.self.gpa,
1122 .mir = .{1117 .mir = .{
...@@ -1204,6 +1199,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {...@@ -1204,6 +1199,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
1204 self.mir_extra.appendAssumeCapacity(switch (field.type) {1199 self.mir_extra.appendAssumeCapacity(switch (field.type) {
1205 u32 => @field(extra, field.name),1200 u32 => @field(extra, field.name),
1206 i32, Mir.Memory.Info => @bitCast(@field(extra, field.name)),1201 i32, Mir.Memory.Info => @bitCast(@field(extra, field.name)),
1202 bits.FrameIndex => @intFromEnum(@field(extra, field.name)),
1207 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),1203 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
1208 });1204 });
1209 }1205 }
...@@ -1357,6 +1353,124 @@ fn asmPlaceholder(self: *Self) !Mir.Inst.Index {...@@ -1357,6 +1353,124 @@ fn asmPlaceholder(self: *Self) !Mir.Inst.Index {
1357 });1353 });
1358}1354}
13591355
1356const MirTagAir = enum { dbg_local };
1357
1358fn asmAir(self: *Self, tag: MirTagAir, inst: Air.Inst.Index) !void {
1359 _ = try self.addInst(.{
1360 .tag = .pseudo,
1361 .ops = switch (tag) {
1362 .dbg_local => .pseudo_dbg_local_a,
1363 },
1364 .data = .{ .a = .{ .air_inst = inst } },
1365 });
1366}
1367
1368fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void {
1369 switch (imm) {
1370 .signed => |s| _ = try self.addInst(.{
1371 .tag = .pseudo,
1372 .ops = switch (tag) {
1373 .dbg_local => .pseudo_dbg_local_ai_s,
1374 },
1375 .data = .{ .ai = .{
1376 .air_inst = inst,
1377 .i = @bitCast(s),
1378 } },
1379 }),
1380 .unsigned => |u| _ = if (math.cast(u32, u)) |small| try self.addInst(.{
1381 .tag = .pseudo,
1382 .ops = switch (tag) {
1383 .dbg_local => .pseudo_dbg_local_ai_u,
1384 },
1385 .data = .{ .ai = .{
1386 .air_inst = inst,
1387 .i = small,
1388 } },
1389 }) else try self.addInst(.{
1390 .tag = .pseudo,
1391 .ops = switch (tag) {
1392 .dbg_local => .pseudo_dbg_local_ai_64,
1393 },
1394 .data = .{ .ai = .{
1395 .air_inst = inst,
1396 .i = try self.addExtra(Mir.Imm64.encode(u)),
1397 } },
1398 }),
1399 .reloc => |sym_off| _ = if (sym_off.off == 0) try self.addInst(.{
1400 .tag = .pseudo,
1401 .ops = switch (tag) {
1402 .dbg_local => .pseudo_dbg_local_as,
1403 },
1404 .data = .{ .as = .{
1405 .air_inst = inst,
1406 .sym_index = sym_off.sym_index,
1407 } },
1408 }) else try self.addInst(.{
1409 .tag = .pseudo,
1410 .ops = switch (tag) {
1411 .dbg_local => .pseudo_dbg_local_aso,
1412 },
1413 .data = .{ .ax = .{
1414 .air_inst = inst,
1415 .payload = try self.addExtra(sym_off),
1416 } },
1417 }),
1418 }
1419}
1420
1421fn asmAirRegisterImmediate(
1422 self: *Self,
1423 tag: MirTagAir,
1424 inst: Air.Inst.Index,
1425 reg: Register,
1426 imm: Immediate,
1427) !void {
1428 _ = try self.addInst(.{
1429 .tag = .pseudo,
1430 .ops = switch (tag) {
1431 .dbg_local => .pseudo_dbg_local_aro,
1432 },
1433 .data = .{ .rx = .{
1434 .r1 = reg,
1435 .payload = try self.addExtra(Mir.AirOffset{
1436 .air_inst = inst,
1437 .off = imm.signed,
1438 }),
1439 } },
1440 });
1441}
1442
1443fn asmAirFrameAddress(
1444 self: *Self,
1445 tag: MirTagAir,
1446 inst: Air.Inst.Index,
1447 frame_addr: bits.FrameAddr,
1448) !void {
1449 _ = try self.addInst(.{
1450 .tag = .pseudo,
1451 .ops = switch (tag) {
1452 .dbg_local => .pseudo_dbg_local_af,
1453 },
1454 .data = .{ .ax = .{
1455 .air_inst = inst,
1456 .payload = try self.addExtra(frame_addr),
1457 } },
1458 });
1459}
1460
1461fn asmAirMemory(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, m: Memory) !void {
1462 _ = try self.addInst(.{
1463 .tag = .pseudo,
1464 .ops = switch (tag) {
1465 .dbg_local => .pseudo_dbg_local_am,
1466 },
1467 .data = .{ .ax = .{
1468 .air_inst = inst,
1469 .payload = try self.addExtra(Mir.Memory.encode(m)),
1470 } },
1471 });
1472}
1473
1360fn asmOpOnly(self: *Self, tag: Mir.Inst.FixedTag) !void {1474fn asmOpOnly(self: *Self, tag: Mir.Inst.FixedTag) !void {
1361 _ = try self.addInst(.{1475 _ = try self.addInst(.{
1362 .tag = tag[1],1476 .tag = tag[1],
...@@ -1395,9 +1509,9 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {...@@ -1395,9 +1509,9 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
1395 .reloc => .rel,1509 .reloc => .rel,
1396 },1510 },
1397 .data = switch (imm) {1511 .data = switch (imm) {
1398 .reloc => |x| reloc: {1512 .reloc => |sym_off| reloc: {
1399 assert(tag[0] == ._);1513 assert(tag[0] == ._);
1400 break :reloc .{ .reloc = x };1514 break :reloc .{ .reloc = sym_off };
1401 },1515 },
1402 .signed, .unsigned => .{ .i = .{1516 .signed, .unsigned => .{ .i = .{
1403 .fixes = tag[0],1517 .fixes = tag[0],
...@@ -1424,31 +1538,22 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.FixedTag, reg1: Register, reg2...@@ -1424,31 +1538,22 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.FixedTag, reg1: Register, reg2
1424}1538}
14251539
1426fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void {1540fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void {
1427 const ops: Mir.Inst.Ops = switch (imm) {1541 const ops: Mir.Inst.Ops, const i: u32 = switch (imm) {
1428 .signed => .ri_s,1542 .signed => |s| .{ .ri_s, @bitCast(s) },
1429 .unsigned => |u| if (math.cast(u32, u)) |_| .ri_u else .ri64,1543 .unsigned => |u| if (math.cast(u32, u)) |small|
1544 .{ .ri_u, small }
1545 else
1546 .{ .ri_64, try self.addExtra(Mir.Imm64.encode(imm.unsigned)) },
1430 .reloc => unreachable,1547 .reloc => unreachable,
1431 };1548 };
1432 _ = try self.addInst(.{1549 _ = try self.addInst(.{
1433 .tag = tag[1],1550 .tag = tag[1],
1434 .ops = ops,1551 .ops = ops,
1435 .data = switch (ops) {1552 .data = .{ .ri = .{
1436 .ri_s, .ri_u => .{ .ri = .{1553 .fixes = tag[0],
1437 .fixes = tag[0],1554 .r1 = reg,
1438 .r1 = reg,1555 .i = i,
1439 .i = switch (imm) {1556 } },
1440 .signed => |s| @bitCast(s),
1441 .unsigned => |u| @intCast(u),
1442 .reloc => unreachable,
1443 },
1444 } },
1445 .ri64 => .{ .rx = .{
1446 .fixes = tag[0],
1447 .r1 = reg,
1448 .payload = try self.addExtra(Mir.Imm64.encode(imm.unsigned)),
1449 } },
1450 else => unreachable,
1451 },
1452 });1557 });
1453}1558}
14541559
...@@ -2158,6 +2263,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -2158,6 +2263,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
2158 .dbg_inline_block => try self.airDbgInlineBlock(inst),2263 .dbg_inline_block => try self.airDbgInlineBlock(inst),
2159 .dbg_var_ptr,2264 .dbg_var_ptr,
2160 .dbg_var_val,2265 .dbg_var_val,
2266 .dbg_arg_inline,
2161 => try self.airDbgVar(inst),2267 => try self.airDbgVar(inst),
21622268
2163 .call => try self.airCall(inst, .auto),2269 .call => try self.airCall(inst, .auto),
...@@ -2485,12 +2591,12 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo...@@ -2485,12 +2591,12 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
2485 };2591 };
2486}2592}
24872593
2488fn getFrameAddrAlignment(self: *Self, frame_addr: FrameAddr) Alignment {2594fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) Alignment {
2489 const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;2595 const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;
2490 return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));2596 return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));
2491}2597}
24922598
2493fn getFrameAddrSize(self: *Self, frame_addr: FrameAddr) u32 {2599fn getFrameAddrSize(self: *Self, frame_addr: bits.FrameAddr) u32 {
2494 return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off));2600 return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off));
2495}2601}
24962602
...@@ -11951,87 +12057,65 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -11951,87 +12057,65 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
11951fn airDbgArg(self: *Self, inst: Air.Inst.Index) !void {12057fn airDbgArg(self: *Self, inst: Air.Inst.Index) !void {
11952 defer self.finishAirBookkeeping();12058 defer self.finishAirBookkeeping();
11953 if (self.debug_output == .none) return;12059 if (self.debug_output == .none) return;
11954 const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;12060 const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
11955 const name = self.air.nullTerminatedString(@intFromEnum(name_nts));12061 if (name != .none) try self.genLocalDebugInfo(inst, self.getResolvedInstValue(inst).short);
11956 if (name.len > 0) {
11957 const arg_ty = self.typeOfIndex(inst);
11958 const arg_mcv = self.getResolvedInstValue(inst).short;
11959 try self.genVarDebugInfo(.local_arg, .dbg_var_val, name, arg_ty, arg_mcv);
11960 }
11961 if (self.liveness.isUnused(inst)) try self.processDeath(inst);12062 if (self.liveness.isUnused(inst)) try self.processDeath(inst);
11962}12063}
1196312064
11964fn genVarDebugInfo(12065fn genLocalDebugInfo(
11965 self: *Self,12066 self: *Self,
11966 var_tag: link.File.Dwarf.WipNav.VarTag,12067 inst: Air.Inst.Index,
11967 tag: Air.Inst.Tag,
11968 name: []const u8,
11969 ty: Type,
11970 mcv: MCValue,12068 mcv: MCValue,
11971) !void {12069) !void {
11972 const stack_vars = switch (var_tag) {12070 if (self.debug_output == .none) return;
11973 .local_arg => &self.stack_args,12071 switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
11974 .local_var => &self.stack_vars,12072 else => unreachable,
11975 };12073 .arg, .dbg_arg_inline, .dbg_var_val => |tag| {
11976 switch (self.debug_output) {12074 switch (mcv) {
11977 .dwarf => |dwarf| switch (tag) {12075 .none => try self.asmAir(.dbg_local, inst),
11978 else => unreachable,
11979 .dbg_var_ptr => {
11980 const var_ty = ty.childType(self.pt.zcu);
11981 switch (mcv) {
11982 else => {
11983 log.info("dbg_var_ptr({s}({}))", .{ @tagName(mcv), mcv });
11984 unreachable;
11985 },
11986 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
11987 .lea_frame => |frame_addr| try stack_vars.append(self.gpa, .{
11988 .name = name,
11989 .type = var_ty,
11990 .frame_addr = frame_addr,
11991 }),
11992 .lea_symbol => |sym_off| try dwarf.genVarDebugInfo(var_tag, name, var_ty, .{ .plus = .{
11993 &.{ .addr = .{ .sym = sym_off.sym } },
11994 &.{ .consts = sym_off.off },
11995 } }),
11996 }
11997 },
11998 .dbg_var_val => switch (mcv) {
11999 .none => try dwarf.genVarDebugInfo(var_tag, name, ty, .empty),
12000 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,12076 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
12001 .immediate => |immediate| try dwarf.genVarDebugInfo(var_tag, name, ty, .{ .stack_value = &.{12077 .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, Immediate.u(imm)),
12002 .constu = immediate,12078 .lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
12003 } }),12079 .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, Immediate.rel(sym_off)),
12004 else => {12080 else => {
12081 const ty = switch (tag) {
12082 else => unreachable,
12083 .arg => self.typeOfIndex(inst),
12084 .dbg_arg_inline, .dbg_var_val => self.typeOf(
12085 self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op.operand,
12086 ),
12087 };
12005 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ty, self.pt));12088 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ty, self.pt));
12006 try self.genSetMem(.{ .frame = frame_index }, 0, ty, mcv, .{});12089 try self.genSetMem(.{ .frame = frame_index }, 0, ty, mcv, .{});
12007 try stack_vars.append(self.gpa, .{12090 try self.asmAirMemory(.dbg_local, inst, .{
12008 .name = name,12091 .base = .{ .frame = frame_index },
12009 .type = ty,12092 .mod = .{ .rm = .{ .size = .qword } },
12010 .frame_addr = .{ .index = frame_index },
12011 });12093 });
12012 },12094 },
12013 },12095 }
12014 },12096 },
12015 .plan9 => {},12097 .dbg_var_ptr => switch (mcv) {
12016 .none => {},12098 else => unreachable,
12017 }12099 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
12018}12100 .lea_frame => |frame_addr| try self.asmAirMemory(.dbg_local, inst, .{
1201912101 .base = .{ .frame = frame_addr.index },
12020fn genStackVarDebugInfo(12102 .mod = .{ .rm = .{
12021 self: Self,12103 .size = .qword,
12022 var_tag: link.File.Dwarf.WipNav.VarTag,12104 .disp = frame_addr.off,
12023 stack_vars: []const StackVar,12105 } },
12024) !void {12106 }),
12025 switch (self.debug_output) {12107 .lea_symbol => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{
12026 .dwarf => |dwarf| for (stack_vars) |stack_var| {12108 .base = .{ .reloc = sym_off.sym_index },
12027 const frame_loc = self.frame_locs.get(@intFromEnum(stack_var.frame_addr.index));12109 .mod = .{ .rm = .{
12028 try dwarf.genVarDebugInfo(var_tag, stack_var.name, stack_var.type, .{ .plus = .{12110 .size = .qword,
12029 &.{ .breg = frame_loc.base.dwarfNum() },12111 .disp = sym_off.off,
12030 &.{ .consts = @as(i33, frame_loc.disp) + stack_var.frame_addr.off },12112 } },
12031 } });12113 }),
12114 .lea_direct, .lea_got, .lea_tlv => |sym_index| try self.asmAirMemory(.dbg_local, inst, .{
12115 .base = .{ .reloc = sym_index },
12116 .mod = .{ .rm = .{ .size = .qword } },
12117 }),
12032 },12118 },
12033 .plan9 => {},
12034 .none => {},
12035 }12119 }
12036}12120}
1203712121
...@@ -12351,10 +12435,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12351,10 +12435,7 @@ fn genCall(self: *Self, info: union(enum) {
12351 if (self.bin_file.cast(.elf)) |elf_file| {12435 if (self.bin_file.cast(.elf)) |elf_file| {
12352 const zo = elf_file.zigObjectPtr().?;12436 const zo = elf_file.zigObjectPtr().?;
12353 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);12437 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
12354 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12438 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index }));
12355 .atom_index = try self.owner.getSymbolIndex(self),
12356 .sym_index = sym_index,
12357 }));
12358 } else if (self.bin_file.cast(.coff)) |coff_file| {12439 } else if (self.bin_file.cast(.coff)) |coff_file| {
12359 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);12440 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
12360 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;12441 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
...@@ -12364,10 +12445,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12364,10 +12445,7 @@ fn genCall(self: *Self, info: union(enum) {
12364 const zo = macho_file.getZigObject().?;12445 const zo = macho_file.getZigObject().?;
12365 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);12446 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
12366 const sym = zo.symbols.items[sym_index];12447 const sym = zo.symbols.items[sym_index];
12367 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12448 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym.nlist_idx }));
12368 .atom_index = try self.owner.getSymbolIndex(self),
12369 .sym_index = sym.nlist_idx,
12370 }));
12371 } else if (self.bin_file.cast(.plan9)) |p9| {12449 } else if (self.bin_file.cast(.plan9)) |p9| {
12372 const atom_index = try p9.seeNav(pt, func.owner_nav);12450 const atom_index = try p9.seeNav(pt, func.owner_nav);
12373 const atom = p9.getAtom(atom_index);12451 const atom = p9.getAtom(atom_index);
...@@ -12385,19 +12463,13 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12385,19 +12463,13 @@ fn genCall(self: *Self, info: union(enum) {
12385 @"extern".name.toSlice(ip),12463 @"extern".name.toSlice(ip),
12386 @"extern".lib_name.toSlice(ip),12464 @"extern".lib_name.toSlice(ip),
12387 );12465 );
12388 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12466 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12389 .atom_index = try self.owner.getSymbolIndex(self),
12390 .sym_index = target_sym_index,
12391 }));
12392 } else if (self.bin_file.cast(.macho)) |macho_file| {12467 } else if (self.bin_file.cast(.macho)) |macho_file| {
12393 const target_sym_index = try macho_file.getGlobalSymbol(12468 const target_sym_index = try macho_file.getGlobalSymbol(
12394 @"extern".name.toSlice(ip),12469 @"extern".name.toSlice(ip),
12395 @"extern".lib_name.toSlice(ip),12470 @"extern".lib_name.toSlice(ip),
12396 );12471 );
12397 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12472 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12398 .atom_index = try self.owner.getSymbolIndex(self),
12399 .sym_index = target_sym_index,
12400 }));
12401 } else try self.genExternSymbolRef(12473 } else try self.genExternSymbolRef(
12402 .call,12474 .call,
12403 @"extern".lib_name.toSlice(ip),12475 @"extern".lib_name.toSlice(ip),
...@@ -12412,16 +12484,10 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12412,16 +12484,10 @@ fn genCall(self: *Self, info: union(enum) {
12412 },12484 },
12413 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {12485 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
12414 const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);12486 const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
12415 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12487 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12416 .atom_index = try self.owner.getSymbolIndex(self),
12417 .sym_index = target_sym_index,
12418 }));
12419 } else if (self.bin_file.cast(.macho)) |macho_file| {12488 } else if (self.bin_file.cast(.macho)) |macho_file| {
12420 const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);12489 const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
12421 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12490 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12422 .atom_index = try self.owner.getSymbolIndex(self),
12423 .sym_index = target_sym_index,
12424 }));
12425 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),12491 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
12426 }12492 }
12427 return call_info.return_value.short;12493 return call_info.return_value.short;
...@@ -13060,29 +13126,21 @@ fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -13060,29 +13126,21 @@ fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
13060 self.inline_func = extra.data.func;13126 self.inline_func = extra.data.func;
13061 _ = try self.addInst(.{13127 _ = try self.addInst(.{
13062 .tag = .pseudo,13128 .tag = .pseudo,
13063 .ops = .pseudo_dbg_inline_func,13129 .ops = .pseudo_dbg_enter_inline_func,
13064 .data = .{ .func = extra.data.func },13130 .data = .{ .func = extra.data.func },
13065 });13131 });
13066 try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));13132 try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
13067 _ = try self.addInst(.{13133 _ = try self.addInst(.{
13068 .tag = .pseudo,13134 .tag = .pseudo,
13069 .ops = .pseudo_dbg_inline_func,13135 .ops = .pseudo_dbg_leave_inline_func,
13070 .data = .{ .func = old_inline_func },13136 .data = .{ .func = old_inline_func },
13071 });13137 });
13072}13138}
1307313139
13074fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {13140fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
13075 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;13141 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
13076 const operand = pl_op.operand;13142 try self.genLocalDebugInfo(inst, try self.resolveInst(pl_op.operand));
13077 const ty = self.typeOf(operand);13143 return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
13078 const mcv = try self.resolveInst(operand);
13079
13080 const name = self.air.nullTerminatedString(pl_op.payload);
13081
13082 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
13083 try self.genVarDebugInfo(.local_var, tag, name, ty, mcv);
13084
13085 return self.finishAir(inst, .unreach, .{ operand, .none, .none });
13086}13144}
1308713145
13088fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {13146fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
...@@ -14970,10 +15028,7 @@ fn genSetReg(...@@ -14970,10 +15028,7 @@ fn genSetReg(
14970 .general_purpose => {15028 .general_purpose => {
14971 assert(sym_off.off == 0);15029 assert(sym_off.off == 0);
14972 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{15030 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{
14973 .base = .{ .reloc = .{15031 .base = .{ .reloc = sym_off.sym_index },
14974 .atom_index = try self.owner.getSymbolIndex(self),
14975 .sym_index = sym_off.sym,
14976 } },
14977 .mod = .{ .rm = .{15032 .mod = .{ .rm = .{
14978 .size = self.memSize(ty),15033 .size = self.memSize(ty),
14979 .disp = sym_off.off,15034 .disp = sym_off.off,
...@@ -14991,10 +15046,7 @@ fn genSetReg(...@@ -14991,10 +15046,7 @@ fn genSetReg(
14991 .ops = .direct_reloc,15046 .ops = .direct_reloc,
14992 .data = .{ .rx = .{15047 .data = .{ .rx = .{
14993 .r1 = registerAlias(dst_reg, abi_size),15048 .r1 = registerAlias(dst_reg, abi_size),
14994 .payload = try self.addExtra(bits.Symbol{15049 .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
14995 .atom_index = try self.owner.getSymbolIndex(self),
14996 .sym_index = sym_index,
14997 }),
14998 } },15050 } },
14999 });15051 });
15000 return;15052 return;
...@@ -15019,52 +15071,38 @@ fn genSetReg(...@@ -15019,52 +15071,38 @@ fn genSetReg(
15019 },15071 },
15020 );15072 );
15021 },15073 },
15022 .lea_symbol => |sym_index| {15074 .lea_symbol => |sym_off| switch (self.bin_file.tag) {
15023 const atom_index = try self.owner.getSymbolIndex(self);15075 .elf, .macho => try self.asmRegisterMemory(
15024 switch (self.bin_file.tag) {15076 .{ ._, .lea },
15025 .elf, .macho => {15077 dst_reg.to64(),
15026 try self.asmRegisterMemory(15078 .{
15027 .{ ._, .lea },15079 .base = .{ .reloc = sym_off.sym_index },
15028 dst_reg.to64(),15080 .mod = .{ .rm = .{
15029 .{15081 .size = .qword,
15030 .base = .{ .reloc = .{15082 .disp = sym_off.off,
15031 .atom_index = atom_index,15083 } },
15032 .sym_index = sym_index.sym,
15033 } },
15034 .mod = .{ .rm = .{
15035 .size = .qword,
15036 .disp = sym_index.off,
15037 } },
15038 },
15039 );
15040 },
15041 else => return self.fail("TODO emit symbol sequence on {s}", .{
15042 @tagName(self.bin_file.tag),
15043 }),
15044 }
15045 },
15046 .lea_direct, .lea_got => |sym_index| {
15047 const atom_index = try self.owner.getSymbolIndex(self);
15048 _ = try self.addInst(.{
15049 .tag = switch (src_mcv) {
15050 .lea_direct => .lea,
15051 .lea_got => .mov,
15052 else => unreachable,
15053 },
15054 .ops = switch (src_mcv) {
15055 .lea_direct => .direct_reloc,
15056 .lea_got => .got_reloc,
15057 else => unreachable,
15058 },15084 },
15059 .data = .{ .rx = .{15085 ),
15060 .r1 = dst_reg.to64(),15086 else => return self.fail("TODO emit symbol sequence on {s}", .{
15061 .payload = try self.addExtra(bits.Symbol{15087 @tagName(self.bin_file.tag),
15062 .atom_index = atom_index,15088 }),
15063 .sym_index = sym_index,
15064 }),
15065 } },
15066 });
15067 },15089 },
15090 .lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{
15091 .tag = switch (src_mcv) {
15092 .lea_direct => .lea,
15093 .lea_got => .mov,
15094 else => unreachable,
15095 },
15096 .ops = switch (src_mcv) {
15097 .lea_direct => .direct_reloc,
15098 .lea_got => .got_reloc,
15099 else => unreachable,
15100 },
15101 .data = .{ .rx = .{
15102 .r1 = dst_reg.to64(),
15103 .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
15104 } },
15105 }),
15068 .lea_tlv => unreachable, // TODO: remove this15106 .lea_tlv => unreachable, // TODO: remove this
15069 .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),15107 .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
15070 }15108 }
...@@ -15085,7 +15123,7 @@ fn genSetMem(...@@ -15085,7 +15123,7 @@ fn genSetMem(
15085 .none => .{ .immediate = @bitCast(@as(i64, disp)) },15123 .none => .{ .immediate = @bitCast(@as(i64, disp)) },
15086 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },15124 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
15087 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },15125 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
15088 .reloc => |base_symbol| .{ .lea_symbol = .{ .sym = base_symbol.sym_index, .off = disp } },15126 .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },
15089 };15127 };
15090 switch (src_mcv) {15128 switch (src_mcv) {
15091 .none,15129 .none,
...@@ -15328,7 +15366,6 @@ fn genExternSymbolRef(...@@ -15328,7 +15366,6 @@ fn genExternSymbolRef(
15328 lib: ?[]const u8,15366 lib: ?[]const u8,
15329 callee: []const u8,15367 callee: []const u8,
15330) InnerError!void {15368) InnerError!void {
15331 const atom_index = try self.owner.getSymbolIndex(self);
15332 if (self.bin_file.cast(.coff)) |coff_file| {15369 if (self.bin_file.cast(.coff)) |coff_file| {
15333 const global_index = try coff_file.getGlobalSymbol(callee, lib);15370 const global_index = try coff_file.getGlobalSymbol(callee, lib);
15334 _ = try self.addInst(.{15371 _ = try self.addInst(.{
...@@ -15336,8 +15373,7 @@ fn genExternSymbolRef(...@@ -15336,8 +15373,7 @@ fn genExternSymbolRef(
15336 .ops = .import_reloc,15373 .ops = .import_reloc,
15337 .data = .{ .rx = .{15374 .data = .{ .rx = .{
15338 .r1 = .rax,15375 .r1 = .rax,
15339 .payload = try self.addExtra(bits.Symbol{15376 .payload = try self.addExtra(bits.SymbolOffset{
15340 .atom_index = atom_index,
15341 .sym_index = link.File.Coff.global_symbol_bit | global_index,15377 .sym_index = link.File.Coff.global_symbol_bit | global_index,
15342 }),15378 }),
15343 } },15379 } },
...@@ -15364,10 +15400,10 @@ fn genLazySymbolRef(...@@ -15364,10 +15400,10 @@ fn genLazySymbolRef(
15364 if (self.mod.pic) {15400 if (self.mod.pic) {
15365 switch (tag) {15401 switch (tag) {
15366 .lea, .call => try self.genSetReg(reg, Type.usize, .{15402 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15367 .lea_symbol = .{ .sym = sym_index },15403 .lea_symbol = .{ .sym_index = sym_index },
15368 }, .{}),15404 }, .{}),
15369 .mov => try self.genSetReg(reg, Type.usize, .{15405 .mov => try self.genSetReg(reg, Type.usize, .{
15370 .load_symbol = .{ .sym = sym_index },15406 .load_symbol = .{ .sym_index = sym_index },
15371 }, .{}),15407 }, .{}),
15372 else => unreachable,15408 else => unreachable,
15373 }15409 }
...@@ -15376,19 +15412,13 @@ fn genLazySymbolRef(...@@ -15376,19 +15412,13 @@ fn genLazySymbolRef(
15376 .call => try self.asmRegister(.{ ._, .call }, reg),15412 .call => try self.asmRegister(.{ ._, .call }, reg),
15377 else => unreachable,15413 else => unreachable,
15378 }15414 }
15379 } else {15415 } else switch (tag) {
15380 const reloc = bits.Symbol{15416 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
15381 .atom_index = try self.owner.getSymbolIndex(self),15417 .base = .{ .reloc = sym_index },
15382 .sym_index = sym_index,15418 .mod = .{ .rm = .{ .size = .qword } },
15383 };15419 }),
15384 switch (tag) {15420 .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index })),
15385 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{15421 else => unreachable,
15386 .base = .{ .reloc = reloc },
15387 .mod = .{ .rm = .{ .size = .qword } },
15388 }),
15389 .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(reloc)),
15390 else => unreachable,
15391 }
15392 }15422 }
15393 } else if (self.bin_file.cast(.plan9)) |p9_file| {15423 } else if (self.bin_file.cast(.plan9)) |p9_file| {
15394 const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|15424 const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
...@@ -15438,10 +15468,10 @@ fn genLazySymbolRef(...@@ -15438,10 +15468,10 @@ fn genLazySymbolRef(
15438 const sym = zo.symbols.items[sym_index];15468 const sym = zo.symbols.items[sym_index];
15439 switch (tag) {15469 switch (tag) {
15440 .lea, .call => try self.genSetReg(reg, Type.usize, .{15470 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15441 .lea_symbol = .{ .sym = sym.nlist_idx },15471 .lea_symbol = .{ .sym_index = sym.nlist_idx },
15442 }, .{}),15472 }, .{}),
15443 .mov => try self.genSetReg(reg, Type.usize, .{15473 .mov => try self.genSetReg(reg, Type.usize, .{
15444 .load_symbol = .{ .sym = sym.nlist_idx },15474 .load_symbol = .{ .sym_index = sym.nlist_idx },
15445 }, .{}),15475 }, .{}),
15446 else => unreachable,15476 else => unreachable,
15447 }15477 }
...@@ -18786,7 +18816,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -18786,7 +18816,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
18786 .{ .frame = frame_index },18816 .{ .frame = frame_index },
18787 0,18817 0,
18788 Type.usize,18818 Type.usize,
18789 .{ .lea_symbol = .{ .sym = tlv_sym } },18819 .{ .lea_symbol = .{ .sym_index = tlv_sym } },
18790 .{},18820 .{},
18791 );18821 );
18792 break :init .{ .load_frame = .{ .index = frame_index } };18822 break :init .{ .load_frame = .{ .index = frame_index } };
...@@ -18842,8 +18872,8 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {...@@ -18842,8 +18872,8 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
18842 .undef => .undef,18872 .undef => .undef,
18843 .immediate => |imm| .{ .immediate = imm },18873 .immediate => |imm| .{ .immediate = imm },
18844 .memory => |addr| .{ .memory = addr },18874 .memory => |addr| .{ .memory = addr },
18845 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },18875 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym_index = sym_index } },
18846 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },18876 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index } },
18847 .load_direct => |sym_index| .{ .load_direct = sym_index },18877 .load_direct => |sym_index| .{ .load_direct = sym_index },
18848 .lea_direct => |sym_index| .{ .lea_direct = sym_index },18878 .lea_direct => |sym_index| .{ .lea_direct = sym_index },
18849 .load_got => |sym_index| .{ .lea_got = sym_index },18879 .load_got => |sym_index| .{ .lea_got = sym_index },
src/arch/x86_64/Emit.zig+195-52
...@@ -1,6 +1,8 @@...@@ -1,6 +1,8 @@
1//! This file contains the functionality for emitting x86_64 MIR as machine code1//! This file contains the functionality for emitting x86_64 MIR as machine code
22
3air: Air,
3lower: Lower,4lower: Lower,
5atom_index: u32,
4debug_output: DebugInfoOutput,6debug_output: DebugInfoOutput,
5code: *std.ArrayList(u8),7code: *std.ArrayList(u8),
68
...@@ -36,83 +38,84 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -36,83 +38,84 @@ pub fn emitMir(emit: *Emit) Error!void {
36 }) switch (lowered_relocs[0].target) {38 }) switch (lowered_relocs[0].target) {
37 .inst => |target| try emit.relocs.append(emit.lower.allocator, .{39 .inst => |target| try emit.relocs.append(emit.lower.allocator, .{
38 .source = start_offset,40 .source = start_offset,
41 .source_offset = end_offset - 4,
39 .target = target,42 .target = target,
40 .offset = end_offset - 4,43 .target_offset = lowered_relocs[0].off,
41 .length = @intCast(end_offset - start_offset),44 .length = @intCast(end_offset - start_offset),
42 }),45 }),
43 .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(.elf)) |elf_file| {46 .linker_extern_fn => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
44 // Add relocation to the decl.47 // Add relocation to the decl.
45 const zo = elf_file.zigObjectPtr().?;48 const zo = elf_file.zigObjectPtr().?;
46 const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;49 const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;
47 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);50 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
48 try atom_ptr.addReloc(elf_file, .{51 try atom_ptr.addReloc(elf_file, .{
49 .r_offset = end_offset - 4,52 .r_offset = end_offset - 4,
50 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,53 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
51 .r_addend = -4,54 .r_addend = lowered_relocs[0].off - 4,
52 });55 });
53 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {56 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
54 // Add relocation to the decl.57 // Add relocation to the decl.
55 const zo = macho_file.getZigObject().?;58 const zo = macho_file.getZigObject().?;
56 const atom = zo.symbols.items[symbol.atom_index].getAtom(macho_file).?;59 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
57 try atom.addReloc(macho_file, .{60 try atom.addReloc(macho_file, .{
58 .tag = .@"extern",61 .tag = .@"extern",
59 .offset = end_offset - 4,62 .offset = end_offset - 4,
60 .target = symbol.sym_index,63 .target = sym_index,
61 .addend = 0,64 .addend = lowered_relocs[0].off,
62 .type = .branch,65 .type = .branch,
63 .meta = .{66 .meta = .{
64 .pcrel = true,67 .pcrel = true,
65 .has_subtractor = false,68 .has_subtractor = false,
66 .length = 2,69 .length = 2,
67 .symbolnum = @intCast(symbol.sym_index),70 .symbolnum = @intCast(sym_index),
68 },71 },
69 });72 });
70 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {73 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
71 // Add relocation to the decl.74 // Add relocation to the decl.
72 const atom_index = coff_file.getAtomIndexForSymbol(75 const atom_index = coff_file.getAtomIndexForSymbol(
73 .{ .sym_index = symbol.atom_index, .file = null },76 .{ .sym_index = emit.atom_index, .file = null },
74 ).?;77 ).?;
75 const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)78 const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
76 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)79 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
77 else80 else
78 link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };81 link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
79 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{82 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
80 .type = .direct,83 .type = .direct,
81 .target = target,84 .target = target,
82 .offset = end_offset - 4,85 .offset = end_offset - 4,
83 .addend = 0,86 .addend = @intCast(lowered_relocs[0].off),
84 .pcrel = true,87 .pcrel = true,
85 .length = 2,88 .length = 2,
86 });89 });
87 } else return emit.fail("TODO implement extern reloc for {s}", .{90 } else return emit.fail("TODO implement extern reloc for {s}", .{
88 @tagName(emit.lower.bin_file.tag),91 @tagName(emit.lower.bin_file.tag),
89 }),92 }),
90 .linker_tlsld => |data| {93 .linker_tlsld => |sym_index| {
91 const elf_file = emit.lower.bin_file.cast(.elf).?;94 const elf_file = emit.lower.bin_file.cast(.elf).?;
92 const zo = elf_file.zigObjectPtr().?;95 const zo = elf_file.zigObjectPtr().?;
93 const atom = zo.symbol(data.atom_index).atom(elf_file).?;96 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
94 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);97 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
95 try atom.addReloc(elf_file, .{98 try atom.addReloc(elf_file, .{
96 .r_offset = end_offset - 4,99 .r_offset = end_offset - 4,
97 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,100 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
98 .r_addend = -4,101 .r_addend = lowered_relocs[0].off - 4,
99 });102 });
100 },103 },
101 .linker_dtpoff => |data| {104 .linker_dtpoff => |sym_index| {
102 const elf_file = emit.lower.bin_file.cast(.elf).?;105 const elf_file = emit.lower.bin_file.cast(.elf).?;
103 const zo = elf_file.zigObjectPtr().?;106 const zo = elf_file.zigObjectPtr().?;
104 const atom = zo.symbol(data.atom_index).atom(elf_file).?;107 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
105 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);108 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
106 try atom.addReloc(elf_file, .{109 try atom.addReloc(elf_file, .{
107 .r_offset = end_offset - 4,110 .r_offset = end_offset - 4,
108 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,111 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
109 .r_addend = 0,112 .r_addend = lowered_relocs[0].off,
110 });113 });
111 },114 },
112 .linker_reloc => |data| if (emit.lower.bin_file.cast(.elf)) |elf_file| {115 .linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
113 const zo = elf_file.zigObjectPtr().?;116 const zo = elf_file.zigObjectPtr().?;
114 const atom = zo.symbol(data.atom_index).atom(elf_file).?;117 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
115 const sym = zo.symbol(data.sym_index);118 const sym = zo.symbol(sym_index);
116 if (emit.lower.pic) {119 if (emit.lower.pic) {
117 const r_type: u32 = if (sym.flags.is_extern_ptr)120 const r_type: u32 = if (sym.flags.is_extern_ptr)
118 @intFromEnum(std.elf.R_X86_64.GOTPCREL)121 @intFromEnum(std.elf.R_X86_64.GOTPCREL)
...@@ -120,8 +123,8 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -120,8 +123,8 @@ pub fn emitMir(emit: *Emit) Error!void {
120 @intFromEnum(std.elf.R_X86_64.PC32);123 @intFromEnum(std.elf.R_X86_64.PC32);
121 try atom.addReloc(elf_file, .{124 try atom.addReloc(elf_file, .{
122 .r_offset = end_offset - 4,125 .r_offset = end_offset - 4,
123 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,126 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
124 .r_addend = -4,127 .r_addend = lowered_relocs[0].off - 4,
125 });128 });
126 } else {129 } else {
127 const r_type: u32 = if (sym.flags.is_tls)130 const r_type: u32 = if (sym.flags.is_tls)
...@@ -130,14 +133,14 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -130,14 +133,14 @@ pub fn emitMir(emit: *Emit) Error!void {
130 @intFromEnum(std.elf.R_X86_64.@"32");133 @intFromEnum(std.elf.R_X86_64.@"32");
131 try atom.addReloc(elf_file, .{134 try atom.addReloc(elf_file, .{
132 .r_offset = end_offset - 4,135 .r_offset = end_offset - 4,
133 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,136 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
134 .r_addend = 0,137 .r_addend = lowered_relocs[0].off,
135 });138 });
136 }139 }
137 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {140 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
138 const zo = macho_file.getZigObject().?;141 const zo = macho_file.getZigObject().?;
139 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;142 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
140 const sym = &zo.symbols.items[data.sym_index];143 const sym = &zo.symbols.items[sym_index];
141 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)144 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)
142 .got_load145 .got_load
143 else if (sym.flags.tlv)146 else if (sym.flags.tlv)
...@@ -147,33 +150,33 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -147,33 +150,33 @@ pub fn emitMir(emit: *Emit) Error!void {
147 try atom.addReloc(macho_file, .{150 try atom.addReloc(macho_file, .{
148 .tag = .@"extern",151 .tag = .@"extern",
149 .offset = @intCast(end_offset - 4),152 .offset = @intCast(end_offset - 4),
150 .target = data.sym_index,153 .target = sym_index,
151 .addend = 0,154 .addend = lowered_relocs[0].off,
152 .type = @"type",155 .type = @"type",
153 .meta = .{156 .meta = .{
154 .pcrel = true,157 .pcrel = true,
155 .has_subtractor = false,158 .has_subtractor = false,
156 .length = 2,159 .length = 2,
157 .symbolnum = @intCast(data.sym_index),160 .symbolnum = @intCast(sym_index),
158 },161 },
159 });162 });
160 } else unreachable,163 } else unreachable,
161 .linker_got,164 .linker_got,
162 .linker_direct,165 .linker_direct,
163 .linker_import,166 .linker_import,
164 => |symbol| if (emit.lower.bin_file.cast(.elf)) |_| {167 => |sym_index| if (emit.lower.bin_file.cast(.elf)) |_| {
165 unreachable;168 unreachable;
166 } else if (emit.lower.bin_file.cast(.macho)) |_| {169 } else if (emit.lower.bin_file.cast(.macho)) |_| {
167 unreachable;170 unreachable;
168 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {171 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
169 const atom_index = coff_file.getAtomIndexForSymbol(.{172 const atom_index = coff_file.getAtomIndexForSymbol(.{
170 .sym_index = symbol.atom_index,173 .sym_index = emit.atom_index,
171 .file = null,174 .file = null,
172 }).?;175 }).?;
173 const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)176 const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
174 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)177 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
175 else178 else
176 link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };179 link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
177 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{180 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
178 .type = switch (lowered_relocs[0].target) {181 .type = switch (lowered_relocs[0].target) {
179 .linker_got => .got,182 .linker_got => .got,
...@@ -183,16 +186,15 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -183,16 +186,15 @@ pub fn emitMir(emit: *Emit) Error!void {
183 },186 },
184 .target = target,187 .target = target,
185 .offset = @intCast(end_offset - 4),188 .offset = @intCast(end_offset - 4),
186 .addend = 0,189 .addend = @intCast(lowered_relocs[0].off),
187 .pcrel = true,190 .pcrel = true,
188 .length = 2,191 .length = 2,
189 });192 });
190 } else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {193 } else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {
191 const atom_index = symbol.atom_index;194 try p9_file.addReloc(emit.atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct
192 try p9_file.addReloc(atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct195 .target = sym_index, // we set sym_index to just be the atom index
193 .target = symbol.sym_index, // we set sym_index to just be the atom index
194 .offset = @intCast(end_offset - 4),196 .offset = @intCast(end_offset - 4),
195 .addend = 0,197 .addend = @intCast(lowered_relocs[0].off),
196 .type = .pcrel,198 .type = .pcrel,
197 });199 });
198 } else return emit.fail("TODO implement linker reloc for {s}", .{200 } else return emit.fail("TODO implement linker reloc for {s}", .{
...@@ -232,13 +234,151 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -232,13 +234,151 @@ pub fn emitMir(emit: *Emit) Error!void {
232 .none => {},234 .none => {},
233 }235 }
234 },236 },
235 .pseudo_dbg_inline_func => {237 .pseudo_dbg_enter_inline_func => {
236 switch (emit.debug_output) {238 switch (emit.debug_output) {
237 .dwarf => |dw| {239 .dwarf => |dw| {
238 log.debug("mirDbgInline (line={d}, col={d})", .{240 log.debug("mirDbgEnterInline (line={d}, col={d})", .{
239 emit.prev_di_line, emit.prev_di_column,241 emit.prev_di_line, emit.prev_di_column,
240 });242 });
241 try dw.setInlineFunc(mir_inst.data.func);243 try dw.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_line, emit.prev_di_column);
244 },
245 .plan9 => {},
246 .none => {},
247 }
248 },
249 .pseudo_dbg_leave_inline_func => {
250 switch (emit.debug_output) {
251 .dwarf => |dw| {
252 log.debug("mirDbgLeaveInline (line={d}, col={d})", .{
253 emit.prev_di_line, emit.prev_di_column,
254 });
255 try dw.leaveInlineFunc(mir_inst.data.func, emit.code.items.len);
256 },
257 .plan9 => {},
258 .none => {},
259 }
260 },
261 .pseudo_dbg_local_a,
262 .pseudo_dbg_local_ai_s,
263 .pseudo_dbg_local_ai_u,
264 .pseudo_dbg_local_ai_64,
265 .pseudo_dbg_local_as,
266 .pseudo_dbg_local_aso,
267 .pseudo_dbg_local_aro,
268 .pseudo_dbg_local_af,
269 .pseudo_dbg_local_am,
270 => {
271 switch (emit.debug_output) {
272 .dwarf => |dw| {
273 var loc_buf: [2]link.File.Dwarf.Loc = undefined;
274 const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) {
275 else => unreachable,
276 .pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty },
277 .pseudo_dbg_local_ai_s,
278 .pseudo_dbg_local_ai_u,
279 .pseudo_dbg_local_ai_64,
280 => .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: {
281 loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) {
282 .signed => |s| .{ .consts = s },
283 .unsigned => |u| .{ .constu = u },
284 };
285 break :stack_value &loc_buf[0];
286 } } },
287 .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
288 .sym = mir_inst.data.as.sym_index,
289 } } },
290 .pseudo_dbg_local_aso => loc: {
291 const sym_off = emit.lower.mir.extraData(
292 bits.SymbolOffset,
293 mir_inst.data.ax.payload,
294 ).data;
295 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
296 sym: {
297 loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
298 break :sym &loc_buf[0];
299 },
300 off: {
301 loc_buf[1] = .{ .consts = sym_off.off };
302 break :off &loc_buf[1];
303 },
304 } } };
305 },
306 .pseudo_dbg_local_aro => loc: {
307 const air_off = emit.lower.mir.extraData(
308 Mir.AirOffset,
309 mir_inst.data.rx.payload,
310 ).data;
311 break :loc .{ air_off.air_inst, .{ .plus = .{
312 reg: {
313 loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
314 break :reg &loc_buf[0];
315 },
316 off: {
317 loc_buf[1] = .{ .consts = air_off.off };
318 break :off &loc_buf[1];
319 },
320 } } };
321 },
322 .pseudo_dbg_local_af => loc: {
323 const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
324 bits.FrameAddr,
325 mir_inst.data.ax.payload,
326 ).data);
327 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
328 reg: {
329 loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
330 break :reg &loc_buf[0];
331 },
332 off: {
333 loc_buf[1] = .{ .consts = reg_off.off };
334 break :off &loc_buf[1];
335 },
336 } } };
337 },
338 .pseudo_dbg_local_am => loc: {
339 const mem = emit.lower.mem(mir_inst.data.ax.payload);
340 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
341 base: {
342 loc_buf[0] = switch (mem.base()) {
343 .none => .{ .constu = 0 },
344 .reg => |reg| .{ .breg = reg.dwarfNum() },
345 .frame => unreachable,
346 .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
347 };
348 break :base &loc_buf[0];
349 },
350 disp: {
351 loc_buf[1] = switch (mem.disp()) {
352 .signed => |s| .{ .consts = s },
353 .unsigned => |u| .{ .constu = u },
354 };
355 break :disp &loc_buf[1];
356 },
357 } } };
358 },
359 };
360 const ip = &emit.lower.bin_file.comp.module.?.intern_pool;
361 const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index));
362 const name: Air.NullTerminatedString = switch (air_inst.tag) {
363 else => unreachable,
364 .arg => air_inst.data.arg.name,
365 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload),
366 };
367 try dw.genLocalDebugInfo(
368 switch (air_inst.tag) {
369 else => unreachable,
370 .arg, .dbg_arg_inline => .local_arg,
371 .dbg_var_ptr, .dbg_var_val => .local_var,
372 },
373 name.toSlice(emit.air),
374 switch (air_inst.tag) {
375 else => unreachable,
376 .arg => emit.air.typeOfIndex(air_inst_index, ip),
377 .dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip),
378 .dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip),
379 },
380 loc,
381 );
242 },382 },
243 .plan9 => {},383 .plan9 => {},
244 .none => {},384 .none => {},
...@@ -268,10 +408,12 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {...@@ -268,10 +408,12 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
268const Reloc = struct {408const Reloc = struct {
269 /// Offset of the instruction.409 /// Offset of the instruction.
270 source: usize,410 source: usize,
411 /// Offset of the relocation within the instruction.
412 source_offset: u32,
271 /// Target of the relocation.413 /// Target of the relocation.
272 target: Mir.Inst.Index,414 target: Mir.Inst.Index,
273 /// Offset of the relocation within the instruction.415 /// Offset from the target instruction.
274 offset: u32,416 target_offset: i32,
275 /// Length of the instruction.417 /// Length of the instruction.
276 length: u5,418 length: u5,
277};419};
...@@ -284,8 +426,8 @@ fn fixupRelocs(emit: *Emit) Error!void {...@@ -284,8 +426,8 @@ fn fixupRelocs(emit: *Emit) Error!void {
284 for (emit.relocs.items) |reloc| {426 for (emit.relocs.items) |reloc| {
285 const target = emit.code_offset_mapping.get(reloc.target) orelse427 const target = emit.code_offset_mapping.get(reloc.target) orelse
286 return emit.fail("JMP/CALL relocation target not found!", .{});428 return emit.fail("JMP/CALL relocation target not found!", .{});
287 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length));429 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length)) + reloc.target_offset;
288 mem.writeInt(i32, emit.code.items[reloc.offset..][0..4], @intCast(disp), .little);430 std.mem.writeInt(i32, emit.code.items[reloc.source_offset..][0..4], @intCast(disp), .little);
289 }431 }
290}432}
291433
...@@ -338,11 +480,12 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {...@@ -338,11 +480,12 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
338 }480 }
339}481}
340482
483const bits = @import("bits.zig");
341const link = @import("../../link.zig");484const link = @import("../../link.zig");
342const log = std.log.scoped(.emit);485const log = std.log.scoped(.emit);
343const mem = std.mem;
344const std = @import("std");486const std = @import("std");
345487
488const Air = @import("../../Air.zig");
346const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;489const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
347const Emit = @This();490const Emit = @This();
348const Lower = @import("Lower.zig");491const Lower = @import("Lower.zig");
src/arch/x86_64/Lower.zig+60-52
...@@ -4,10 +4,10 @@ bin_file: *link.File,...@@ -4,10 +4,10 @@ bin_file: *link.File,
4output_mode: std.builtin.OutputMode,4output_mode: std.builtin.OutputMode,
5link_mode: std.builtin.LinkMode,5link_mode: std.builtin.LinkMode,
6pic: bool,6pic: bool,
7allocator: Allocator,7allocator: std.mem.Allocator,
8mir: Mir,8mir: Mir,
9cc: std.builtin.CallingConvention,9cc: std.builtin.CallingConvention,
10err_msg: ?*ErrorMsg = null,10err_msg: ?*Zcu.ErrorMsg = null,
11src_loc: Zcu.LazySrcLoc,11src_loc: Zcu.LazySrcLoc,
12result_insts_len: u8 = undefined,12result_insts_len: u8 = undefined,
13result_relocs_len: u8 = undefined,13result_relocs_len: u8 = undefined,
...@@ -52,16 +52,17 @@ pub const Error = error{...@@ -52,16 +52,17 @@ pub const Error = error{
52pub const Reloc = struct {52pub const Reloc = struct {
53 lowered_inst_index: u8,53 lowered_inst_index: u8,
54 target: Target,54 target: Target,
55 off: i32,
5556
56 const Target = union(enum) {57 const Target = union(enum) {
57 inst: Mir.Inst.Index,58 inst: Mir.Inst.Index,
58 linker_reloc: bits.Symbol,59 linker_reloc: u32,
59 linker_tlsld: bits.Symbol,60 linker_tlsld: u32,
60 linker_dtpoff: bits.Symbol,61 linker_dtpoff: u32,
61 linker_extern_fn: bits.Symbol,62 linker_extern_fn: u32,
62 linker_got: bits.Symbol,63 linker_got: u32,
63 linker_direct: bits.Symbol,64 linker_direct: u32,
64 linker_import: bits.Symbol,65 linker_import: u32,
65 };66 };
66};67};
6768
...@@ -173,19 +174,19 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -173,19 +174,19 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
173 .pseudo_j_z_and_np_inst => {174 .pseudo_j_z_and_np_inst => {
174 assert(inst.data.inst.fixes == ._);175 assert(inst.data.inst.fixes == ._);
175 try lower.emit(.none, .jnz, &.{176 try lower.emit(.none, .jnz, &.{
176 .{ .imm = lower.reloc(.{ .inst = index + 1 }) },177 .{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
177 });178 });
178 try lower.emit(.none, .jnp, &.{179 try lower.emit(.none, .jnp, &.{
179 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },180 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
180 });181 });
181 },182 },
182 .pseudo_j_nz_or_p_inst => {183 .pseudo_j_nz_or_p_inst => {
183 assert(inst.data.inst.fixes == ._);184 assert(inst.data.inst.fixes == ._);
184 try lower.emit(.none, .jnz, &.{185 try lower.emit(.none, .jnz, &.{
185 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },186 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
186 });187 });
187 try lower.emit(.none, .jp, &.{188 try lower.emit(.none, .jp, &.{
188 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },189 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
189 });190 });
190 },191 },
191192
...@@ -195,7 +196,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -195,7 +196,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
195 .{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },196 .{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },
196 });197 });
197 try lower.emit(.none, .jz, &.{198 try lower.emit(.none, .jz, &.{
198 .{ .imm = lower.reloc(.{ .inst = index + 1 }) },199 .{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
199 });200 });
200 try lower.emit(.none, .lea, &.{201 try lower.emit(.none, .lea, &.{
201 .{ .reg = inst.data.ri.r1 },202 .{ .reg = inst.data.ri.r1 },
...@@ -211,7 +212,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -211,7 +212,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
211 .{ .reg = inst.data.ri.r1.to32() },212 .{ .reg = inst.data.ri.r1.to32() },
212 });213 });
213 try lower.emit(.none, .jmp, &.{214 try lower.emit(.none, .jmp, &.{
214 .{ .imm = lower.reloc(.{ .inst = index }) },215 .{ .imm = lower.reloc(.{ .inst = index }, 0) },
215 });216 });
216 assert(lower.result_insts_len == pseudo_probe_align_insts);217 assert(lower.result_insts_len == pseudo_probe_align_insts);
217 },218 },
...@@ -257,7 +258,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -257,7 +258,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
257 .{ .imm = Immediate.s(page_size) },258 .{ .imm = Immediate.s(page_size) },
258 });259 });
259 try lower.emit(.none, .jae, &.{260 try lower.emit(.none, .jae, &.{
260 .{ .imm = lower.reloc(.{ .inst = index }) },261 .{ .imm = lower.reloc(.{ .inst = index }, 0) },
261 });262 });
262 assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);263 assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
263 },264 },
...@@ -267,7 +268,17 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -267,7 +268,17 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
267 .pseudo_dbg_prologue_end_none,268 .pseudo_dbg_prologue_end_none,
268 .pseudo_dbg_line_line_column,269 .pseudo_dbg_line_line_column,
269 .pseudo_dbg_epilogue_begin_none,270 .pseudo_dbg_epilogue_begin_none,
270 .pseudo_dbg_inline_func,271 .pseudo_dbg_enter_inline_func,
272 .pseudo_dbg_leave_inline_func,
273 .pseudo_dbg_local_a,
274 .pseudo_dbg_local_ai_s,
275 .pseudo_dbg_local_ai_u,
276 .pseudo_dbg_local_ai_64,
277 .pseudo_dbg_local_as,
278 .pseudo_dbg_local_aso,
279 .pseudo_dbg_local_aro,
280 .pseudo_dbg_local_af,
281 .pseudo_dbg_local_am,
271 .pseudo_dead_none,282 .pseudo_dead_none,
272 => {},283 => {},
273 else => unreachable,284 else => unreachable,
...@@ -283,17 +294,18 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -283,17 +294,18 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
283pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {294pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
284 @setCold(true);295 @setCold(true);
285 assert(lower.err_msg == null);296 assert(lower.err_msg == null);
286 lower.err_msg = try ErrorMsg.create(lower.allocator, lower.src_loc, format, args);297 lower.err_msg = try Zcu.ErrorMsg.create(lower.allocator, lower.src_loc, format, args);
287 return error.LowerFail;298 return error.LowerFail;
288}299}
289300
290fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {301pub fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
291 return switch (ops) {302 return switch (ops) {
292 .rri_s,303 .rri_s,
293 .ri_s,304 .ri_s,
294 .i_s,305 .i_s,
295 .mi_s,306 .mi_s,
296 .rmi_s,307 .rmi_s,
308 .pseudo_dbg_local_ai_s,
297 => Immediate.s(@bitCast(i)),309 => Immediate.s(@bitCast(i)),
298310
299 .rrri,311 .rrri,
...@@ -306,22 +318,26 @@ fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {...@@ -306,22 +318,26 @@ fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
306 .mri,318 .mri,
307 .rrm,319 .rrm,
308 .rrmi,320 .rrmi,
321 .pseudo_dbg_local_ai_u,
309 => Immediate.u(i),322 => Immediate.u(i),
310323
311 .ri64 => Immediate.u(lower.mir.extraData(Mir.Imm64, i).data.decode()),324 .ri_64,
325 .pseudo_dbg_local_ai_64,
326 => Immediate.u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
312327
313 else => unreachable,328 else => unreachable,
314 };329 };
315}330}
316331
317fn mem(lower: Lower, payload: u32) Memory {332pub fn mem(lower: Lower, payload: u32) Memory {
318 return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();333 return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
319}334}
320335
321fn reloc(lower: *Lower, target: Reloc.Target) Immediate {336fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {
322 lower.result_relocs[lower.result_relocs_len] = .{337 lower.result_relocs[lower.result_relocs_len] = .{
323 .lowered_inst_index = lower.result_insts_len,338 .lowered_inst_index = lower.result_insts_len,
324 .target = target,339 .target = target,
340 .off = off,
325 };341 };
326 lower.result_relocs_len += 1;342 lower.result_relocs_len += 1;
327 return Immediate.s(0);343 return Immediate.s(0);
...@@ -337,37 +353,36 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -337,37 +353,36 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
337 else => op,353 else => op,
338 .mem => |mem_op| switch (mem_op.base()) {354 .mem => |mem_op| switch (mem_op.base()) {
339 else => op,355 else => op,
340 .reloc => |sym| op: {356 .reloc => |sym_index| op: {
341 assert(prefix == .none);357 assert(prefix == .none);
342 assert(mem_op.sib.disp == 0);358 assert(mem_op.sib.disp == 0);
343 assert(mem_op.sib.scale_index.scale == 0);359 assert(mem_op.sib.scale_index.scale == 0);
344360
345 if (lower.bin_file.cast(.elf)) |elf_file| {361 if (lower.bin_file.cast(.elf)) |elf_file| {
346 const zo = elf_file.zigObjectPtr().?;362 const zo = elf_file.zigObjectPtr().?;
347 const elf_sym = zo.symbol(sym.sym_index);363 const elf_sym = zo.symbol(sym_index);
348364
349 if (elf_sym.flags.is_tls) {365 if (elf_sym.flags.is_tls) {
350 // TODO handle extern TLS vars, i.e., emit GD model366 // TODO handle extern TLS vars, i.e., emit GD model
351 if (lower.pic) {367 if (lower.pic) {
352 // Here, we currently assume local dynamic TLS vars, and so368 // Here, we currently assume local dynamic TLS vars, and so
353 // we emit LD model.369 // we emit LD model.
354 _ = lower.reloc(.{ .linker_tlsld = sym });370 _ = lower.reloc(.{ .linker_tlsld = sym_index }, 0);
355 lower.result_insts[lower.result_insts_len] =371 lower.result_insts[lower.result_insts_len] =
356 try Instruction.new(.none, .lea, &[_]Operand{372 try Instruction.new(.none, .lea, &[_]Operand{
357 .{ .reg = .rdi },373 .{ .reg = .rdi },
358 .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },374 .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
359 });375 });
360 lower.result_insts_len += 1;376 lower.result_insts_len += 1;
361 _ = lower.reloc(.{ .linker_extern_fn = .{377 _ = lower.reloc(.{
362 .atom_index = sym.atom_index,378 .linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
363 .sym_index = try elf_file.getGlobalSymbol("__tls_get_addr", null),379 }, 0);
364 } });
365 lower.result_insts[lower.result_insts_len] =380 lower.result_insts[lower.result_insts_len] =
366 try Instruction.new(.none, .call, &[_]Operand{381 try Instruction.new(.none, .call, &[_]Operand{
367 .{ .imm = Immediate.s(0) },382 .{ .imm = Immediate.s(0) },
368 });383 });
369 lower.result_insts_len += 1;384 lower.result_insts_len += 1;
370 _ = lower.reloc(.{ .linker_dtpoff = sym });385 _ = lower.reloc(.{ .linker_dtpoff = sym_index }, 0);
371 emit_mnemonic = .lea;386 emit_mnemonic = .lea;
372 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{387 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
373 .base = .{ .reg = .rax },388 .base = .{ .reg = .rax },
...@@ -381,7 +396,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -381,7 +396,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
381 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },396 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
382 });397 });
383 lower.result_insts_len += 1;398 lower.result_insts_len += 1;
384 _ = lower.reloc(.{ .linker_reloc = sym });399 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
385 emit_mnemonic = .lea;400 emit_mnemonic = .lea;
386 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{401 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
387 .base = .{ .reg = .rax },402 .base = .{ .reg = .rax },
...@@ -390,7 +405,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -390,7 +405,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
390 }405 }
391 }406 }
392407
393 _ = lower.reloc(.{ .linker_reloc = sym });408 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
394 if (lower.pic) switch (mnemonic) {409 if (lower.pic) switch (mnemonic) {
395 .lea => {410 .lea => {
396 if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;411 if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
...@@ -427,10 +442,10 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -427,10 +442,10 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
427 }442 }
428 } else if (lower.bin_file.cast(.macho)) |macho_file| {443 } else if (lower.bin_file.cast(.macho)) |macho_file| {
429 const zo = macho_file.getZigObject().?;444 const zo = macho_file.getZigObject().?;
430 const macho_sym = zo.symbols.items[sym.sym_index];445 const macho_sym = zo.symbols.items[sym_index];
431446
432 if (macho_sym.flags.tlv) {447 if (macho_sym.flags.tlv) {
433 _ = lower.reloc(.{ .linker_reloc = sym });448 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
434 lower.result_insts[lower.result_insts_len] =449 lower.result_insts[lower.result_insts_len] =
435 try Instruction.new(.none, .mov, &[_]Operand{450 try Instruction.new(.none, .mov, &[_]Operand{
436 .{ .reg = .rdi },451 .{ .reg = .rdi },
...@@ -446,7 +461,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -446,7 +461,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
446 break :op .{ .reg = .rax };461 break :op .{ .reg = .rax };
447 }462 }
448463
449 _ = lower.reloc(.{ .linker_reloc = sym });464 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
450 break :op switch (mnemonic) {465 break :op switch (mnemonic) {
451 .lea => {466 .lea => {
452 if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;467 if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
...@@ -490,8 +505,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -490,8 +505,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
490 .rrrr => inst.data.rrrr.fixes,505 .rrrr => inst.data.rrrr.fixes,
491 .rrri => inst.data.rrri.fixes,506 .rrri => inst.data.rrri.fixes,
492 .rri_s, .rri_u => inst.data.rri.fixes,507 .rri_s, .rri_u => inst.data.rri.fixes,
493 .ri_s, .ri_u => inst.data.ri.fixes,508 .ri_s, .ri_u, .ri_64 => inst.data.ri.fixes,
494 .ri64, .rm, .rmi_s, .mr => inst.data.rx.fixes,509 .rm, .rmi_s, .mr => inst.data.rx.fixes,
495 .mrr, .rrm, .rmr => inst.data.rrx.fixes,510 .mrr, .rrm, .rmr => inst.data.rrx.fixes,
496 .rmi, .mri => inst.data.rix.fixes,511 .rmi, .mri => inst.data.rix.fixes,
497 .rrmr => inst.data.rrrx.fixes,512 .rrmr => inst.data.rrrx.fixes,
...@@ -525,7 +540,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -525,7 +540,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
525 }, switch (inst.ops) {540 }, switch (inst.ops) {
526 .none => &.{},541 .none => &.{},
527 .inst => &.{542 .inst => &.{
528 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },543 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
529 },544 },
530 .i_s, .i_u => &.{545 .i_s, .i_u => &.{
531 .{ .imm = lower.imm(inst.ops, inst.data.i.i) },546 .{ .imm = lower.imm(inst.ops, inst.data.i.i) },
...@@ -554,14 +569,10 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -554,14 +569,10 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
554 .{ .reg = inst.data.rrri.r3 },569 .{ .reg = inst.data.rrri.r3 },
555 .{ .imm = lower.imm(inst.ops, inst.data.rrri.i) },570 .{ .imm = lower.imm(inst.ops, inst.data.rrri.i) },
556 },571 },
557 .ri_s, .ri_u => &.{572 .ri_s, .ri_u, .ri_64 => &.{
558 .{ .reg = inst.data.ri.r1 },573 .{ .reg = inst.data.ri.r1 },
559 .{ .imm = lower.imm(inst.ops, inst.data.ri.i) },574 .{ .imm = lower.imm(inst.ops, inst.data.ri.i) },
560 },575 },
561 .ri64 => &.{
562 .{ .reg = inst.data.rx.r1 },
563 .{ .imm = lower.imm(inst.ops, inst.data.rx.payload) },
564 },
565 .rri_s, .rri_u => &.{576 .rri_s, .rri_u => &.{
566 .{ .reg = inst.data.rri.r1 },577 .{ .reg = inst.data.rri.r1 },
567 .{ .reg = inst.data.rri.r2 },578 .{ .reg = inst.data.rri.r2 },
...@@ -631,17 +642,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -631,17 +642,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
631 .{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },642 .{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
632 },643 },
633 .extern_fn_reloc, .rel => &.{644 .extern_fn_reloc, .rel => &.{
634 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },645 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc.sym_index }, inst.data.reloc.off) },
635 },646 },
636 .got_reloc, .direct_reloc, .import_reloc => ops: {647 .got_reloc, .direct_reloc, .import_reloc => ops: {
637 const reg = inst.data.rx.r1;648 const reg = inst.data.rx.r1;
638 const extra = lower.mir.extraData(bits.Symbol, inst.data.rx.payload).data;649 const extra = lower.mir.extraData(bits.SymbolOffset, inst.data.rx.payload).data;
639 _ = lower.reloc(switch (inst.ops) {650 _ = lower.reloc(switch (inst.ops) {
640 .got_reloc => .{ .linker_got = extra },651 .got_reloc => .{ .linker_got = extra.sym_index },
641 .direct_reloc => .{ .linker_direct = extra },652 .direct_reloc => .{ .linker_direct = extra.sym_index },
642 .import_reloc => .{ .linker_import = extra },653 .import_reloc => .{ .linker_import = extra.sym_index },
643 else => unreachable,654 else => unreachable,
644 });655 }, extra.off);
645 break :ops &.{656 break :ops &.{
646 .{ .reg = reg },657 .{ .reg = reg },
647 .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },658 .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
...@@ -670,9 +681,6 @@ const encoder = @import("encoder.zig");...@@ -670,9 +681,6 @@ const encoder = @import("encoder.zig");
670const link = @import("../../link.zig");681const link = @import("../../link.zig");
671const std = @import("std");682const std = @import("std");
672683
673const Air = @import("../../Air.zig");
674const Allocator = std.mem.Allocator;
675const ErrorMsg = Zcu.ErrorMsg;
676const Immediate = Instruction.Immediate;684const Immediate = Instruction.Immediate;
677const Instruction = encoder.Instruction;685const Instruction = encoder.Instruction;
678const Lower = @This();686const Lower = @This();
src/arch/x86_64/Mir.zig+74-20
...@@ -760,8 +760,8 @@ pub const Inst = struct {...@@ -760,8 +760,8 @@ pub const Inst = struct {
760 /// Uses `ri` payload.760 /// Uses `ri` payload.
761 ri_u,761 ri_u,
762 /// Register, 64-bit unsigned immediate operands.762 /// Register, 64-bit unsigned immediate operands.
763 /// Uses `rx` payload with payload type `Imm64`.763 /// Uses `ri` payload with `i` index of extra data of type `Imm64`.
764 ri64,764 ri_64,
765 /// Immediate (sign-extended) operand.765 /// Immediate (sign-extended) operand.
766 /// Uses `imm` payload.766 /// Uses `imm` payload.
767 i_s,767 i_s,
...@@ -796,7 +796,7 @@ pub const Inst = struct {...@@ -796,7 +796,7 @@ pub const Inst = struct {
796 /// Uses `rrix` payload with extra data of type `Memory`.796 /// Uses `rrix` payload with extra data of type `Memory`.
797 rrmi,797 rrmi,
798 /// Single memory operand.798 /// Single memory operand.
799 /// Uses `x` with extra data of type `Memory`.799 /// Uses `x` payload with extra data of type `Memory`.
800 m,800 m,
801 /// Memory, immediate (sign-extend) operands.801 /// Memory, immediate (sign-extend) operands.
802 /// Uses `x` payload with extra data of type `Imm32` followed by `Memory`.802 /// Uses `x` payload with extra data of type `Imm32` followed by `Memory`.
...@@ -820,16 +820,16 @@ pub const Inst = struct {...@@ -820,16 +820,16 @@ pub const Inst = struct {
820 /// Uses `reloc` payload.820 /// Uses `reloc` payload.
821 extern_fn_reloc,821 extern_fn_reloc,
822 /// Linker relocation - GOT indirection.822 /// Linker relocation - GOT indirection.
823 /// Uses `rx` payload with extra data of type `bits.Symbol`.823 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
824 got_reloc,824 got_reloc,
825 /// Linker relocation - direct reference.825 /// Linker relocation - direct reference.
826 /// Uses `rx` payload with extra data of type `bits.Symbol`.826 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
827 direct_reloc,827 direct_reloc,
828 /// Linker relocation - imports table indirection (binding).828 /// Linker relocation - imports table indirection (binding).
829 /// Uses `rx` payload with extra data of type `bits.Symbol`.829 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
830 import_reloc,830 import_reloc,
831 /// Linker relocation - threadlocal variable via GOT indirection.831 /// Linker relocation - threadlocal variable via GOT indirection.
832 /// Uses `rx` payload with extra data of type `bits.Symbol`.832 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
833 tlv_reloc,833 tlv_reloc,
834834
835 // Pseudo instructions:835 // Pseudo instructions:
...@@ -868,16 +868,16 @@ pub const Inst = struct {...@@ -868,16 +868,16 @@ pub const Inst = struct {
868 pseudo_j_nz_or_p_inst,868 pseudo_j_nz_or_p_inst,
869869
870 /// Probe alignment870 /// Probe alignment
871 /// Uses `ri` payload871 /// Uses `ri` payload.
872 pseudo_probe_align_ri_s,872 pseudo_probe_align_ri_s,
873 /// Probe adjust unrolled873 /// Probe adjust unrolled
874 /// Uses `ri` payload874 /// Uses `ri` payload.
875 pseudo_probe_adjust_unrolled_ri_s,875 pseudo_probe_adjust_unrolled_ri_s,
876 /// Probe adjust setup876 /// Probe adjust setup
877 /// Uses `rri` payload877 /// Uses `rri` payload.
878 pseudo_probe_adjust_setup_rri_s,878 pseudo_probe_adjust_setup_rri_s,
879 /// Probe adjust loop879 /// Probe adjust loop
880 /// Uses `rr` payload880 /// Uses `rr` payload.
881 pseudo_probe_adjust_loop_rr,881 pseudo_probe_adjust_loop_rr,
882 /// Push registers882 /// Push registers
883 /// Uses `reg_list` payload.883 /// Uses `reg_list` payload.
...@@ -893,8 +893,37 @@ pub const Inst = struct {...@@ -893,8 +893,37 @@ pub const Inst = struct {
893 pseudo_dbg_line_line_column,893 pseudo_dbg_line_line_column,
894 /// Start of epilogue894 /// Start of epilogue
895 pseudo_dbg_epilogue_begin_none,895 pseudo_dbg_epilogue_begin_none,
896 /// Start or end of inline function896 /// Start of inline function
897 pseudo_dbg_inline_func,897 pseudo_dbg_enter_inline_func,
898 /// End of inline function
899 pseudo_dbg_leave_inline_func,
900 /// Local argument or variable.
901 /// Uses `a` payload.
902 pseudo_dbg_local_a,
903 /// Local argument or variable.
904 /// Uses `ai` payload.
905 pseudo_dbg_local_ai_s,
906 /// Local argument or variable.
907 /// Uses `ai` payload.
908 pseudo_dbg_local_ai_u,
909 /// Local argument or variable.
910 /// Uses `ai` payload with extra data of type `Imm64`.
911 pseudo_dbg_local_ai_64,
912 /// Local argument or variable.
913 /// Uses `as` payload.
914 pseudo_dbg_local_as,
915 /// Local argument or variable.
916 /// Uses `ax` payload with extra data of type `bits.SymbolOffset`.
917 pseudo_dbg_local_aso,
918 /// Local argument or variable.
919 /// Uses `rx` payload with extra data of type `AirOffset`.
920 pseudo_dbg_local_aro,
921 /// Local argument or variable.
922 /// Uses `ax` payload with extra data of type `bits.FrameAddr`.
923 pseudo_dbg_local_af,
924 /// Local argument or variable.
925 /// Uses `ax` payload with extra data of type `Memory`.
926 pseudo_dbg_local_am,
898927
899 /// Tombstone928 /// Tombstone
900 /// Emitter should skip this instruction.929 /// Emitter should skip this instruction.
...@@ -997,10 +1026,28 @@ pub const Inst = struct {...@@ -997,10 +1026,28 @@ pub const Inst = struct {
997 fixes: Fixes = ._,1026 fixes: Fixes = ._,
998 payload: u32,1027 payload: u32,
999 },1028 },
1029 ix: struct {
1030 payload: u32,
1031 },
1032 a: struct {
1033 air_inst: Air.Inst.Index,
1034 },
1035 ai: struct {
1036 air_inst: Air.Inst.Index,
1037 i: u32,
1038 },
1039 as: struct {
1040 air_inst: Air.Inst.Index,
1041 sym_index: u32,
1042 },
1043 ax: struct {
1044 air_inst: Air.Inst.Index,
1045 payload: u32,
1046 },
1000 /// Relocation for the linker where:1047 /// Relocation for the linker where:
1001 /// * `atom_index` is the index of the source
1002 /// * `sym_index` is the index of the target1048 /// * `sym_index` is the index of the target
1003 reloc: bits.Symbol,1049 /// * `off` is the offset from the target
1050 reloc: bits.SymbolOffset,
1004 /// Debug line and column position1051 /// Debug line and column position
1005 line_column: struct {1052 line_column: struct {
1006 line: u32,1053 line: u32,
...@@ -1020,6 +1067,8 @@ pub const Inst = struct {...@@ -1020,6 +1067,8 @@ pub const Inst = struct {
1020 }1067 }
1021};1068};
10221069
1070pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
1071
1023/// Used in conjunction with payload to transfer a list of used registers in a compact manner.1072/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
1024pub const RegisterList = struct {1073pub const RegisterList = struct {
1025 bitset: BitSet = BitSet.initEmpty(),1074 bitset: BitSet = BitSet.initEmpty(),
...@@ -1118,15 +1167,13 @@ pub const Memory = struct {...@@ -1118,15 +1167,13 @@ pub const Memory = struct {
1118 .none => undefined,1167 .none => undefined,
1119 .reg => |reg| @intFromEnum(reg),1168 .reg => |reg| @intFromEnum(reg),
1120 .frame => |frame_index| @intFromEnum(frame_index),1169 .frame => |frame_index| @intFromEnum(frame_index),
1121 .reloc => |symbol| symbol.sym_index,1170 .reloc => |sym_index| sym_index,
1122 },1171 },
1123 .off = switch (mem.mod) {1172 .off = switch (mem.mod) {
1124 .rm => |rm| @bitCast(rm.disp),1173 .rm => |rm| @bitCast(rm.disp),
1125 .off => |off| @truncate(off),1174 .off => |off| @truncate(off),
1126 },1175 },
1127 .extra = if (mem.base == .reloc)1176 .extra = if (mem.mod == .off)
1128 mem.base.reloc.atom_index
1129 else if (mem.mod == .off)
1130 @intCast(mem.mod.off >> 32)1177 @intCast(mem.mod.off >> 32)
1131 else1178 else
1132 undefined,1179 undefined,
...@@ -1146,7 +1193,7 @@ pub const Memory = struct {...@@ -1146,7 +1193,7 @@ pub const Memory = struct {
1146 .none => .none,1193 .none => .none,
1147 .reg => .{ .reg = @enumFromInt(mem.base) },1194 .reg => .{ .reg = @enumFromInt(mem.base) },
1148 .frame => .{ .frame = @enumFromInt(mem.base) },1195 .frame => .{ .frame = @enumFromInt(mem.base) },
1149 .reloc => .{ .reloc = .{ .atom_index = mem.extra, .sym_index = mem.base } },1196 .reloc => .{ .reloc = mem.base },
1150 },1197 },
1151 .scale_index = switch (mem.info.index) {1198 .scale_index = switch (mem.info.index) {
1152 .none => null,1199 .none => null,
...@@ -1186,6 +1233,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:...@@ -1186,6 +1233,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:
1186 @field(result, field.name) = switch (field.type) {1233 @field(result, field.name) = switch (field.type) {
1187 u32 => mir.extra[i],1234 u32 => mir.extra[i],
1188 i32, Memory.Info => @bitCast(mir.extra[i]),1235 i32, Memory.Info => @bitCast(mir.extra[i]),
1236 bits.FrameIndex, Air.Inst.Index => @enumFromInt(mir.extra[i]),
1189 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),1237 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
1190 };1238 };
1191 i += 1;1239 i += 1;
...@@ -1201,6 +1249,11 @@ pub const FrameLoc = struct {...@@ -1201,6 +1249,11 @@ pub const FrameLoc = struct {
1201 disp: i32,1249 disp: i32,
1202};1250};
12031251
1252pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffset {
1253 const frame_loc = mir.frame_locs.get(@intFromEnum(frame_addr.index));
1254 return .{ .reg = frame_loc.base, .off = frame_loc.disp + frame_addr.off };
1255}
1256
1204pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {1257pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
1205 return switch (mem.info.base) {1258 return switch (mem.info.base) {
1206 .none, .reg, .reloc => mem,1259 .none, .reg, .reloc => mem,
...@@ -1225,6 +1278,7 @@ const builtin = @import("builtin");...@@ -1225,6 +1278,7 @@ const builtin = @import("builtin");
1225const encoder = @import("encoder.zig");1278const encoder = @import("encoder.zig");
1226const std = @import("std");1279const std = @import("std");
12271280
1281const Air = @import("../../Air.zig");
1228const IntegerBitSet = std.bit_set.IntegerBitSet;1282const IntegerBitSet = std.bit_set.IntegerBitSet;
1229const InternPool = @import("../../InternPool.zig");1283const InternPool = @import("../../InternPool.zig");
1230const Mir = @This();1284const Mir = @This();
src/arch/x86_64/bits.zig+12-27
...@@ -447,26 +447,11 @@ pub const FrameIndex = enum(u32) {...@@ -447,26 +447,11 @@ pub const FrameIndex = enum(u32) {
447 }447 }
448};448};
449449
450/// A linker symbol not yet allocated in VM.450pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
451pub const Symbol = struct {
452 /// Index of the containing atom.
453 atom_index: u32,
454 /// Index into the linker's symbol table.
455 sym_index: u32,
456451
457 pub fn format(452pub const RegisterOffset = struct { reg: Register, off: i32 = 0 };
458 sym: Symbol,453
459 comptime fmt: []const u8,454pub const SymbolOffset = struct { sym_index: u32, off: i32 = 0 };
460 options: std.fmt.FormatOptions,
461 writer: anytype,
462 ) @TypeOf(writer).Error!void {
463 try writer.writeAll("Symbol(");
464 try std.fmt.formatType(sym.atom_index, fmt, options, writer, 0);
465 try writer.writeAll(", ");
466 try std.fmt.formatType(sym.sym_index, fmt, options, writer, 0);
467 try writer.writeByte(')');
468 }
469};
470455
471pub const Memory = struct {456pub const Memory = struct {
472 base: Base,457 base: Base,
...@@ -476,7 +461,7 @@ pub const Memory = struct {...@@ -476,7 +461,7 @@ pub const Memory = struct {
476 none,461 none,
477 reg: Register,462 reg: Register,
478 frame: FrameIndex,463 frame: FrameIndex,
479 reloc: Symbol,464 reloc: u32,
480465
481 pub const Tag = @typeInfo(Base).Union.tag_type.?;466 pub const Tag = @typeInfo(Base).Union.tag_type.?;
482467
...@@ -568,7 +553,7 @@ pub const Memory = struct {...@@ -568,7 +553,7 @@ pub const Memory = struct {
568pub const Immediate = union(enum) {553pub const Immediate = union(enum) {
569 signed: i32,554 signed: i32,
570 unsigned: u64,555 unsigned: u64,
571 reloc: Symbol,556 reloc: SymbolOffset,
572557
573 pub fn u(x: u64) Immediate {558 pub fn u(x: u64) Immediate {
574 return .{ .unsigned = x };559 return .{ .unsigned = x };
...@@ -578,19 +563,19 @@ pub const Immediate = union(enum) {...@@ -578,19 +563,19 @@ pub const Immediate = union(enum) {
578 return .{ .signed = x };563 return .{ .signed = x };
579 }564 }
580565
581 pub fn rel(symbol: Symbol) Immediate {566 pub fn rel(sym_off: SymbolOffset) Immediate {
582 return .{ .reloc = symbol };567 return .{ .reloc = sym_off };
583 }568 }
584569
585 pub fn format(570 pub fn format(
586 imm: Immediate,571 imm: Immediate,
587 comptime fmt: []const u8,572 comptime _: []const u8,
588 options: std.fmt.FormatOptions,573 _: std.fmt.FormatOptions,
589 writer: anytype,574 writer: anytype,
590 ) @TypeOf(writer).Error!void {575 ) @TypeOf(writer).Error!void {
591 switch (imm) {576 switch (imm) {
592 .reloc => |x| try std.fmt.formatType(x, fmt, options, writer, 0),577 inline else => |int| try writer.print("{d}", .{int}),
593 inline else => |x| try writer.print("{d}", .{x}),578 .reloc => |sym_off| try writer.print("Symbol({[sym_index]d}) + {[off]d}", sym_off),
594 }579 }
595 }580 }
596};581};
src/arch/x86_64/encoder.zig+15-12
...@@ -128,8 +128,8 @@ pub const Instruction = struct {...@@ -128,8 +128,8 @@ pub const Instruction = struct {
128 } };128 } };
129 }129 }
130130
131 pub fn rip(ptr_size: PtrSize, disp: i32) Memory {131 pub fn rip(ptr_size: PtrSize, displacement: i32) Memory {
132 return .{ .rip = .{ .ptr_size = ptr_size, .disp = disp } };132 return .{ .rip = .{ .ptr_size = ptr_size, .disp = displacement } };
133 }133 }
134134
135 pub fn isSegmentRegister(mem: Memory) bool {135 pub fn isSegmentRegister(mem: Memory) bool {
...@@ -158,6 +158,14 @@ pub const Instruction = struct {...@@ -158,6 +158,14 @@ pub const Instruction = struct {
158 };158 };
159 }159 }
160160
161 pub fn disp(mem: Memory) Immediate {
162 return switch (mem) {
163 .sib => |s| Immediate.s(s.disp),
164 .rip => |r| Immediate.s(r.disp),
165 .moffs => |m| Immediate.u(m.offset),
166 };
167 }
168
161 pub fn bitSize(mem: Memory) u64 {169 pub fn bitSize(mem: Memory) u64 {
162 return switch (mem) {170 return switch (mem) {
163 .rip => |r| r.ptr_size.bitSize(),171 .rip => |r| r.ptr_size.bitSize(),
...@@ -258,17 +266,12 @@ pub const Instruction = struct {...@@ -258,17 +266,12 @@ pub const Instruction = struct {
258266
259 try writer.writeByte('[');267 try writer.writeByte('[');
260268
261 var any = false;269 var any = true;
262 switch (sib.base) {270 switch (sib.base) {
263 .none => {},271 .none => any = false,
264 .reg => |reg| {272 .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),
265 try writer.print("{s}", .{@tagName(reg)});273 .frame => |frame_index| try writer.print("{}", .{frame_index}),
266 any = true;274 .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),
267 },
268 inline .frame, .reloc => |payload| {
269 try writer.print("{}", .{payload});
270 any = true;
271 },
272 }275 }
273 if (mem.scaleIndex()) |si| {276 if (mem.scaleIndex()) |si| {
274 if (any) try writer.writeAll(" + ");277 if (any) try writer.writeAll(" + ");
src/codegen/c.zig+4-3
...@@ -3293,7 +3293,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3293,7 +3293,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
32933293
3294 .dbg_stmt => try airDbgStmt(f, inst),3294 .dbg_stmt => try airDbgStmt(f, inst),
3295 .dbg_inline_block => try airDbgInlineBlock(f, inst),3295 .dbg_inline_block => try airDbgInlineBlock(f, inst),
3296 .dbg_var_ptr, .dbg_var_val => try airDbgVar(f, inst),3296 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => try airDbgVar(f, inst),
32973297
3298 .call => try airCall(f, inst, .auto),3298 .call => try airCall(f, inst, .auto),
3299 .call_always_tail => .none,3299 .call_always_tail => .none,
...@@ -4590,14 +4590,15 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4590,14 +4590,15 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4590fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {4590fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
4591 const pt = f.object.dg.pt;4591 const pt = f.object.dg.pt;
4592 const zcu = pt.zcu;4592 const zcu = pt.zcu;
4593 const tag = f.air.instructions.items(.tag)[@intFromEnum(inst)];
4593 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4594 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4594 const name = f.air.nullTerminatedString(pl_op.payload);4595 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
4595 const operand_is_undef = if (try f.air.value(pl_op.operand, pt)) |v| v.isUndefDeep(zcu) else false;4596 const operand_is_undef = if (try f.air.value(pl_op.operand, pt)) |v| v.isUndefDeep(zcu) else false;
4596 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);4597 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
45974598
4598 try reap(f, inst, &.{pl_op.operand});4599 try reap(f, inst, &.{pl_op.operand});
4599 const writer = f.object.writer();4600 const writer = f.object.writer();
4600 try writer.print("/* var:{s} */\n", .{name});4601 try writer.print("/* {s}:{s} */\n", .{ @tagName(tag), name.toSlice(f.air) });
4601 return .none;4602 return .none;
4602}4603}
46034604
src/codegen/llvm.zig+24-10
...@@ -1665,6 +1665,7 @@ pub const Object = struct {...@@ -1665,6 +1665,7 @@ pub const Object = struct {
1665 .ret_ptr = ret_ptr,1665 .ret_ptr = ret_ptr,
1666 .args = args.items,1666 .args = args.items,
1667 .arg_index = 0,1667 .arg_index = 0,
1668 .arg_inline_index = 0,
1668 .func_inst_table = .{},1669 .func_inst_table = .{},
1669 .blocks = .{},1670 .blocks = .{},
1670 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,1671 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
...@@ -4769,7 +4770,8 @@ pub const FuncGen = struct {...@@ -4769,7 +4770,8 @@ pub const FuncGen = struct {
4769 /// it omits 0-bit types. If the function uses sret as the first parameter,4770 /// it omits 0-bit types. If the function uses sret as the first parameter,
4770 /// this slice does not include it.4771 /// this slice does not include it.
4771 args: []const Builder.Value,4772 args: []const Builder.Value,
4772 arg_index: usize,4773 arg_index: u32,
4774 arg_inline_index: u32,
47734775
4774 err_ret_trace: Builder.Value = .none,4776 err_ret_trace: Builder.Value = .none,
47754777
...@@ -5082,7 +5084,8 @@ pub const FuncGen = struct {...@@ -5082,7 +5084,8 @@ pub const FuncGen = struct {
5082 .dbg_stmt => try self.airDbgStmt(inst),5084 .dbg_stmt => try self.airDbgStmt(inst),
5083 .dbg_inline_block => try self.airDbgInlineBlock(inst),5085 .dbg_inline_block => try self.airDbgInlineBlock(inst),
5084 .dbg_var_ptr => try self.airDbgVarPtr(inst),5086 .dbg_var_ptr => try self.airDbgVarPtr(inst),
5085 .dbg_var_val => try self.airDbgVarVal(inst),5087 .dbg_var_val => try self.airDbgVarVal(inst, false),
5088 .dbg_arg_inline => try self.airDbgVarVal(inst, true),
50865089
5087 .c_va_arg => try self.airCVaArg(inst),5090 .c_va_arg => try self.airCVaArg(inst),
5088 .c_va_copy => try self.airCVaCopy(inst),5091 .c_va_copy => try self.airCVaCopy(inst),
...@@ -6677,6 +6680,7 @@ pub const FuncGen = struct {...@@ -6677,6 +6680,7 @@ pub const FuncGen = struct {
6677 fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6680 fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6678 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;6681 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
6679 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);6682 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
6683 self.arg_inline_index = 0;
6680 return self.lowerBlock(inst, extra.data.func, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));6684 return self.lowerBlock(inst, extra.data.func, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
6681 }6685 }
66826686
...@@ -6685,11 +6689,11 @@ pub const FuncGen = struct {...@@ -6685,11 +6689,11 @@ pub const FuncGen = struct {
6685 const mod = o.pt.zcu;6689 const mod = o.pt.zcu;
6686 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6690 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6687 const operand = try self.resolveInst(pl_op.operand);6691 const operand = try self.resolveInst(pl_op.operand);
6688 const name = self.air.nullTerminatedString(pl_op.payload);6692 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
6689 const ptr_ty = self.typeOf(pl_op.operand);6693 const ptr_ty = self.typeOf(pl_op.operand);
66906694
6691 const debug_local_var = try o.builder.debugLocalVar(6695 const debug_local_var = try o.builder.debugLocalVar(
6692 try o.builder.metadataString(name),6696 try o.builder.metadataString(name.toSlice(self.air)),
6693 self.file,6697 self.file,
6694 self.scope,6698 self.scope,
6695 self.prev_dbg_line,6699 self.prev_dbg_line,
...@@ -6712,15 +6716,25 @@ pub const FuncGen = struct {...@@ -6712,15 +6716,25 @@ pub const FuncGen = struct {
6712 return .none;6716 return .none;
6713 }6717 }
67146718
6715 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6719 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) !Builder.Value {
6716 const o = self.ng.object;6720 const o = self.ng.object;
6717 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6721 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6718 const operand = try self.resolveInst(pl_op.operand);6722 const operand = try self.resolveInst(pl_op.operand);
6719 const operand_ty = self.typeOf(pl_op.operand);6723 const operand_ty = self.typeOf(pl_op.operand);
6720 const name = self.air.nullTerminatedString(pl_op.payload);6724 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
67216725
6722 const debug_local_var = try o.builder.debugLocalVar(6726 const debug_local_var = if (is_arg) try o.builder.debugParameter(
6723 try o.builder.metadataString(name),6727 try o.builder.metadataString(name.toSlice(self.air)),
6728 self.file,
6729 self.scope,
6730 self.prev_dbg_line,
6731 try o.lowerDebugType(operand_ty),
6732 arg_no: {
6733 self.arg_inline_index += 1;
6734 break :arg_no self.arg_inline_index;
6735 },
6736 ) else try o.builder.debugLocalVar(
6737 try o.builder.metadataString(name.toSlice(self.air)),
6724 self.file,6738 self.file,
6725 self.scope,6739 self.scope,
6726 self.prev_dbg_line,6740 self.prev_dbg_line,
...@@ -8835,12 +8849,12 @@ pub const FuncGen = struct {...@@ -8835,12 +8849,12 @@ pub const FuncGen = struct {
8835 const lbrace_col = func.lbrace_column + 1;8849 const lbrace_col = func.lbrace_column + 1;
88368850
8837 const debug_parameter = try o.builder.debugParameter(8851 const debug_parameter = try o.builder.debugParameter(
8838 try o.builder.metadataString(self.air.nullTerminatedString(@intFromEnum(name))),8852 try o.builder.metadataString(name.toSlice(self.air)),
8839 self.file,8853 self.file,
8840 self.scope,8854 self.scope,
8841 lbrace_line,8855 lbrace_line,
8842 try o.lowerDebugType(inst_ty),8856 try o.lowerDebugType(inst_ty),
8843 @intCast(self.arg_index),8857 self.arg_index,
8844 );8858 );
88458859
8846 const old_location = self.wip.debug_location;8860 const old_location = self.wip.debug_location;
src/codegen/spirv.zig+2-2
...@@ -6366,8 +6366,8 @@ const NavGen = struct {...@@ -6366,8 +6366,8 @@ const NavGen = struct {
6366 fn airDbgVar(self: *NavGen, inst: Air.Inst.Index) !void {6366 fn airDbgVar(self: *NavGen, inst: Air.Inst.Index) !void {
6367 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6367 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6368 const target_id = try self.resolve(pl_op.operand);6368 const target_id = try self.resolve(pl_op.operand);
6369 const name = self.air.nullTerminatedString(pl_op.payload);6369 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
6370 try self.spv.debugName(target_id, name);6370 try self.spv.debugName(target_id, name.toSlice(self.air));
6371 }6371 }
63726372
6373 fn airAssembly(self: *NavGen, inst: Air.Inst.Index) !?IdRef {6373 fn airAssembly(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
src/link/C.zig+11-1
...@@ -317,8 +317,18 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !...@@ -317,8 +317,18 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !
317 defer tracy.end();317 defer tracy.end();
318318
319 const gpa = self.base.comp.gpa;319 const gpa = self.base.comp.gpa;
320
321 const zcu = pt.zcu;320 const zcu = pt.zcu;
321 const ip = &zcu.intern_pool;
322
323 const nav = ip.getNav(nav_index);
324 const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
325 .func => return,
326 .@"extern" => .none,
327 .variable => |variable| variable.init,
328 else => nav.status.resolved.val,
329 };
330 if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) return;
331
322 const gop = try self.navs.getOrPut(gpa, nav_index);332 const gop = try self.navs.getOrPut(gpa, nav_index);
323 errdefer _ = self.navs.pop();333 errdefer _ = self.navs.pop();
324 if (!gop.found_existing) gop.value_ptr.* = .{};334 if (!gop.found_existing) gop.value_ptr.* = .{};
src/link/Coff.zig+2-1
...@@ -1207,6 +1207,7 @@ pub fn updateNav(...@@ -1207,6 +1207,7 @@ pub fn updateNav(
12071207
1208 const nav_val = zcu.navValue(nav_index);1208 const nav_val = zcu.navValue(nav_index);
1209 const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {1209 const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
1210 .func => return,
1210 .variable => |variable| Value.fromInterned(variable.init),1211 .variable => |variable| Value.fromInterned(variable.init),
1211 .@"extern" => |@"extern"| {1212 .@"extern" => |@"extern"| {
1212 if (ip.isFunctionType(@"extern".ty)) return;1213 if (ip.isFunctionType(@"extern".ty)) return;
...@@ -1220,7 +1221,7 @@ pub fn updateNav(...@@ -1220,7 +1221,7 @@ pub fn updateNav(
1220 else => nav_val,1221 else => nav_val,
1221 };1222 };
12221223
1223 if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {1224 if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
1224 const atom_index = try self.getOrCreateAtomForNav(nav_index);1225 const atom_index = try self.getOrCreateAtomForNav(nav_index);
1225 Atom.freeRelocations(self, atom_index);1226 Atom.freeRelocations(self, atom_index);
1226 const atom = self.getAtom(atom_index);1227 const atom = self.getAtom(atom_index);
src/link/Dwarf.zig+339-150
...@@ -21,8 +21,9 @@ pub const UpdateError =...@@ -21,8 +21,9 @@ pub const UpdateError =
21 std.fs.File.OpenError ||21 std.fs.File.OpenError ||
22 std.fs.File.SetEndPosError ||22 std.fs.File.SetEndPosError ||
23 std.fs.File.CopyRangeError ||23 std.fs.File.CopyRangeError ||
24 std.fs.File.PReadError ||
24 std.fs.File.PWriteError ||25 std.fs.File.PWriteError ||
25 error{ Overflow, Underflow, UnexpectedEndOfFile };26 error{ EndOfStream, Overflow, Underflow, UnexpectedEndOfFile };
2627
27pub const FlushError =28pub const FlushError =
28 UpdateError ||29 UpdateError ||
...@@ -253,10 +254,8 @@ const Section = struct {...@@ -253,10 +254,8 @@ const Section = struct {
253 .trailer_len = trailer_len,254 .trailer_len = trailer_len,
254 .len = header_len + trailer_len,255 .len = header_len + trailer_len,
255 .entries = .{},256 .entries = .{},
256 .cross_entry_relocs = .{},
257 .cross_unit_relocs = .{},257 .cross_unit_relocs = .{},
258 .cross_section_relocs = .{},258 .cross_section_relocs = .{},
259 .external_relocs = .{},
260 };259 };
261 if (sec.last.unwrap()) |last_unit| {260 if (sec.last.unwrap()) |last_unit| {
262 const last_unit_ptr = sec.getUnit(last_unit);261 const last_unit_ptr = sec.getUnit(last_unit);
...@@ -358,10 +357,8 @@ const Unit = struct {...@@ -358,10 +357,8 @@ const Unit = struct {
358 /// data length in bytes357 /// data length in bytes
359 len: u32,358 len: u32,
360 entries: std.ArrayListUnmanaged(Entry),359 entries: std.ArrayListUnmanaged(Entry),
361 cross_entry_relocs: std.ArrayListUnmanaged(CrossEntryReloc),
362 cross_unit_relocs: std.ArrayListUnmanaged(CrossUnitReloc),360 cross_unit_relocs: std.ArrayListUnmanaged(CrossUnitReloc),
363 cross_section_relocs: std.ArrayListUnmanaged(CrossSectionReloc),361 cross_section_relocs: std.ArrayListUnmanaged(CrossSectionReloc),
364 external_relocs: std.ArrayListUnmanaged(ExternalReloc),
365362
366 const Index = enum(u32) {363 const Index = enum(u32) {
367 main,364 main,
...@@ -381,12 +378,16 @@ const Unit = struct {...@@ -381,12 +378,16 @@ const Unit = struct {
381 }378 }
382 };379 };
383380
381 fn clear(unit: *Unit) void {
382 unit.cross_unit_relocs.clearRetainingCapacity();
383 unit.cross_section_relocs.clearRetainingCapacity();
384 }
385
384 fn deinit(unit: *Unit, gpa: std.mem.Allocator) void {386 fn deinit(unit: *Unit, gpa: std.mem.Allocator) void {
387 for (unit.entries.items) |*entry| entry.deinit(gpa);
385 unit.entries.deinit(gpa);388 unit.entries.deinit(gpa);
386 unit.cross_entry_relocs.deinit(gpa);
387 unit.cross_unit_relocs.deinit(gpa);389 unit.cross_unit_relocs.deinit(gpa);
388 unit.cross_section_relocs.deinit(gpa);390 unit.cross_section_relocs.deinit(gpa);
389 unit.external_relocs.deinit(gpa);
390 unit.* = undefined;391 unit.* = undefined;
391 }392 }
392393
...@@ -398,6 +399,10 @@ const Unit = struct {...@@ -398,6 +399,10 @@ const Unit = struct {
398 .next = .none,399 .next = .none,
399 .off = 0,400 .off = 0,
400 .len = 0,401 .len = 0,
402 .cross_entry_relocs = .{},
403 .cross_unit_relocs = .{},
404 .cross_section_relocs = .{},
405 .external_relocs = .{},
401 };406 };
402 if (unit.last.unwrap()) |last_entry| {407 if (unit.last.unwrap()) |last_entry| {
403 const last_entry_ptr = unit.getEntry(last_entry);408 const last_entry_ptr = unit.getEntry(last_entry);
...@@ -451,6 +456,14 @@ const Unit = struct {...@@ -451,6 +456,14 @@ const Unit = struct {
451 unit_ptr.len = len;456 unit_ptr.len = len;
452 }457 }
453458
459 fn trim(unit: *Unit) void {
460 const len = unit.getEntry(unit.first.unwrap() orelse return).off;
461 if (len == 0) return;
462 for (unit.entries.items) |*entry| entry.off -= len;
463 unit.off += len;
464 unit.len -= len;
465 }
466
454 fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void {467 fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void {
455 if (unit.off == new_off) return;468 if (unit.off == new_off) return;
456 if (try dwarf.getFile().?.copyRangeAll(469 if (try dwarf.getFile().?.copyRangeAll(
...@@ -463,6 +476,7 @@ const Unit = struct {...@@ -463,6 +476,7 @@ const Unit = struct {
463 }476 }
464477
465 fn resizeHeader(unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void {478 fn resizeHeader(unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void {
479 unit.trim();
466 if (unit.header_len == len) return;480 if (unit.header_len == len) return;
467 const available_len = if (unit.prev.unwrap()) |prev_unit| prev_excess: {481 const available_len = if (unit.prev.unwrap()) |prev_unit| prev_excess: {
468 const prev_unit_ptr = sec.getUnit(prev_unit);482 const prev_unit_ptr = sec.getUnit(prev_unit);
...@@ -535,23 +549,11 @@ const Unit = struct {...@@ -535,23 +549,11 @@ const Unit = struct {
535 }549 }
536550
537 fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {551 fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {
538 for (unit.cross_entry_relocs.items) |reloc| {552 const unit_off = sec.off + unit.off;
539 try dwarf.resolveReloc(
540 sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|
541 unit.header_len + unit.getEntry(source_entry).off
542 else
543 0) + reloc.source_off,
544 unit.off + unit.header_len + unit.getEntry(reloc.target_entry).assertNonEmpty(unit, sec, dwarf).off + reloc.target_off,
545 dwarf.sectionOffsetBytes(),
546 );
547 }
548 for (unit.cross_unit_relocs.items) |reloc| {553 for (unit.cross_unit_relocs.items) |reloc| {
549 const target_unit = sec.getUnit(reloc.target_unit);554 const target_unit = sec.getUnit(reloc.target_unit);
550 try dwarf.resolveReloc(555 try dwarf.resolveReloc(
551 sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|556 unit_off + reloc.source_off,
552 unit.header_len + unit.getEntry(source_entry).off
553 else
554 0) + reloc.source_off,
555 target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|557 target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
556 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off558 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
557 else559 else
...@@ -565,10 +567,7 @@ const Unit = struct {...@@ -565,10 +567,7 @@ const Unit = struct {
565 };567 };
566 const target_unit = target_sec.getUnit(reloc.target_unit);568 const target_unit = target_sec.getUnit(reloc.target_unit);
567 try dwarf.resolveReloc(569 try dwarf.resolveReloc(
568 sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|570 unit_off + reloc.source_off,
569 unit.header_len + unit.getEntry(source_entry).off
570 else
571 0) + reloc.source_off,
572 target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|571 target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
573 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off572 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
574 else573 else
...@@ -576,57 +575,8 @@ const Unit = struct {...@@ -576,57 +575,8 @@ const Unit = struct {
576 dwarf.sectionOffsetBytes(),575 dwarf.sectionOffsetBytes(),
577 );576 );
578 }577 }
579 if (dwarf.bin_file.cast(.elf)) |elf_file| {578 for (unit.entries.items) |*entry| try entry.resolveRelocs(unit, sec, dwarf);
580 const zo = elf_file.zigObjectPtr().?;
581 for (unit.external_relocs.items) |reloc| {
582 const symbol = zo.symbol(reloc.target_sym);
583 try dwarf.resolveReloc(
584 sec.off + unit.off + unit.header_len + unit.getEntry(reloc.source_entry).off + reloc.source_off,
585 @bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off)) -
586 if (symbol.flags.is_tls) elf_file.dtpAddress() else 0),
587 @intFromEnum(dwarf.address_size),
588 );
589 }
590 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
591 const zo = macho_file.getZigObject().?;
592 for (unit.external_relocs.items) |reloc| {
593 const ref = zo.getSymbolRef(reloc.target_sym, macho_file);
594 try dwarf.resolveReloc(
595 sec.off + unit.off + unit.header_len + unit.getEntry(reloc.source_entry).off + reloc.source_off,
596 ref.getSymbol(macho_file).?.getAddress(.{}, macho_file),
597 @intFromEnum(dwarf.address_size),
598 );
599 }
600 }
601 }579 }
602
603 const CrossEntryReloc = struct {
604 source_entry: Entry.Index.Optional = .none,
605 source_off: u32 = 0,
606 target_entry: Entry.Index,
607 target_off: u32 = 0,
608 };
609 const CrossUnitReloc = struct {
610 source_entry: Entry.Index.Optional = .none,
611 source_off: u32 = 0,
612 target_unit: Unit.Index,
613 target_entry: Entry.Index.Optional = .none,
614 target_off: u32 = 0,
615 };
616 const CrossSectionReloc = struct {
617 source_entry: Entry.Index.Optional = .none,
618 source_off: u32 = 0,
619 target_sec: Section.Index,
620 target_unit: Unit.Index,
621 target_entry: Entry.Index.Optional = .none,
622 target_off: u32 = 0,
623 };
624 const ExternalReloc = struct {
625 source_entry: Entry.Index,
626 source_off: u32 = 0,
627 target_sym: u32,
628 target_off: u64 = 0,
629 };
630};580};
631581
632/// An indivisible entry within a `Unit` containing section-specific data.582/// An indivisible entry within a `Unit` containing section-specific data.
...@@ -637,6 +587,25 @@ const Entry = struct {...@@ -637,6 +587,25 @@ const Entry = struct {
637 off: u32,587 off: u32,
638 /// data length in bytes588 /// data length in bytes
639 len: u32,589 len: u32,
590 cross_entry_relocs: std.ArrayListUnmanaged(CrossEntryReloc),
591 cross_unit_relocs: std.ArrayListUnmanaged(CrossUnitReloc),
592 cross_section_relocs: std.ArrayListUnmanaged(CrossSectionReloc),
593 external_relocs: std.ArrayListUnmanaged(ExternalReloc),
594
595 fn clear(entry: *Entry) void {
596 entry.cross_entry_relocs.clearRetainingCapacity();
597 entry.cross_unit_relocs.clearRetainingCapacity();
598 entry.cross_section_relocs.clearRetainingCapacity();
599 entry.external_relocs.clearRetainingCapacity();
600 }
601
602 fn deinit(entry: *Entry, gpa: std.mem.Allocator) void {
603 entry.cross_entry_relocs.deinit(gpa);
604 entry.cross_unit_relocs.deinit(gpa);
605 entry.cross_section_relocs.deinit(gpa);
606 entry.external_relocs.deinit(gpa);
607 entry.* = undefined;
608 }
640609
641 const Index = enum(u32) {610 const Index = enum(u32) {
642 _,611 _,
...@@ -803,6 +772,88 @@ const Entry = struct {...@@ -803,6 +772,88 @@ const Entry = struct {
803 }772 }
804 @panic("missing dwarf relocation target");773 @panic("missing dwarf relocation target");
805 }774 }
775
776 fn resolveRelocs(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {
777 const entry_off = sec.off + unit.off + unit.header_len + entry.off;
778 for (entry.cross_entry_relocs.items) |reloc| {
779 try dwarf.resolveReloc(
780 entry_off + reloc.source_off,
781 unit.off + unit.header_len + unit.getEntry(reloc.target_entry).assertNonEmpty(unit, sec, dwarf).off + reloc.target_off,
782 dwarf.sectionOffsetBytes(),
783 );
784 }
785 for (entry.cross_unit_relocs.items) |reloc| {
786 const target_unit = sec.getUnit(reloc.target_unit);
787 try dwarf.resolveReloc(
788 entry_off + reloc.source_off,
789 target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
790 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
791 else
792 0) + reloc.target_off,
793 dwarf.sectionOffsetBytes(),
794 );
795 }
796 for (entry.cross_section_relocs.items) |reloc| {
797 const target_sec = switch (reloc.target_sec) {
798 inline else => |target_sec| &@field(dwarf, @tagName(target_sec)).section,
799 };
800 const target_unit = target_sec.getUnit(reloc.target_unit);
801 try dwarf.resolveReloc(
802 entry_off + reloc.source_off,
803 target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
804 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
805 else
806 0) + reloc.target_off,
807 dwarf.sectionOffsetBytes(),
808 );
809 }
810 if (dwarf.bin_file.cast(.elf)) |elf_file| {
811 const zo = elf_file.zigObjectPtr().?;
812 for (entry.external_relocs.items) |reloc| {
813 const symbol = zo.symbol(reloc.target_sym);
814 try dwarf.resolveReloc(
815 entry_off + reloc.source_off,
816 @bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off)) -
817 if (symbol.flags.is_tls) elf_file.dtpAddress() else 0),
818 @intFromEnum(dwarf.address_size),
819 );
820 }
821 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
822 const zo = macho_file.getZigObject().?;
823 for (entry.external_relocs.items) |reloc| {
824 const ref = zo.getSymbolRef(reloc.target_sym, macho_file);
825 try dwarf.resolveReloc(
826 entry_off + reloc.source_off,
827 ref.getSymbol(macho_file).?.getAddress(.{}, macho_file),
828 @intFromEnum(dwarf.address_size),
829 );
830 }
831 }
832 }
833};
834
835const CrossEntryReloc = struct {
836 source_off: u32 = 0,
837 target_entry: Entry.Index,
838 target_off: u32 = 0,
839};
840const CrossUnitReloc = struct {
841 source_off: u32 = 0,
842 target_unit: Unit.Index,
843 target_entry: Entry.Index.Optional = .none,
844 target_off: u32 = 0,
845};
846const CrossSectionReloc = struct {
847 source_off: u32 = 0,
848 target_sec: Section.Index,
849 target_unit: Unit.Index,
850 target_entry: Entry.Index.Optional = .none,
851 target_off: u32 = 0,
852};
853const ExternalReloc = struct {
854 source_off: u32 = 0,
855 target_sym: u32,
856 target_off: u64 = 0,
806};857};
807858
808pub const Loc = union(enum) {859pub const Loc = union(enum) {
...@@ -986,7 +1037,9 @@ pub const WipNav = struct {...@@ -986,7 +1037,9 @@ pub const WipNav = struct {
986 entry: Entry.Index,1037 entry: Entry.Index,
987 any_children: bool,1038 any_children: bool,
988 func: InternPool.Index,1039 func: InternPool.Index,
1040 func_sym_index: u32,
989 func_high_reloc: u32,1041 func_high_reloc: u32,
1042 inlined_funcs_high_reloc: std.ArrayListUnmanaged(u32),
990 debug_info: std.ArrayListUnmanaged(u8),1043 debug_info: std.ArrayListUnmanaged(u8),
991 debug_line: std.ArrayListUnmanaged(u8),1044 debug_line: std.ArrayListUnmanaged(u8),
992 debug_loclists: std.ArrayListUnmanaged(u8),1045 debug_loclists: std.ArrayListUnmanaged(u8),
...@@ -994,6 +1047,7 @@ pub const WipNav = struct {...@@ -994,6 +1047,7 @@ pub const WipNav = struct {
9941047
995 pub fn deinit(wip_nav: *WipNav) void {1048 pub fn deinit(wip_nav: *WipNav) void {
996 const gpa = wip_nav.dwarf.gpa;1049 const gpa = wip_nav.dwarf.gpa;
1050 if (wip_nav.func != .none) wip_nav.inlined_funcs_high_reloc.deinit(gpa);
997 wip_nav.debug_info.deinit(gpa);1051 wip_nav.debug_info.deinit(gpa);
998 wip_nav.debug_line.deinit(gpa);1052 wip_nav.debug_line.deinit(gpa);
999 wip_nav.debug_loclists.deinit(gpa);1053 wip_nav.debug_loclists.deinit(gpa);
...@@ -1004,10 +1058,10 @@ pub const WipNav = struct {...@@ -1004,10 +1058,10 @@ pub const WipNav = struct {
1004 return wip_nav.debug_info.writer(wip_nav.dwarf.gpa);1058 return wip_nav.debug_info.writer(wip_nav.dwarf.gpa);
1005 }1059 }
10061060
1007 pub const VarTag = enum { local_arg, local_var };1061 pub const LocalTag = enum { local_arg, local_var };
1008 pub fn genVarDebugInfo(1062 pub fn genLocalDebugInfo(
1009 wip_nav: *WipNav,1063 wip_nav: *WipNav,
1010 tag: VarTag,1064 tag: LocalTag,
1011 name: []const u8,1065 name: []const u8,
1012 ty: Type,1066 ty: Type,
1013 loc: Loc,1067 loc: Loc,
...@@ -1078,7 +1132,43 @@ pub const WipNav = struct {...@@ -1078,7 +1132,43 @@ pub const WipNav = struct {
1078 try dlw.writeByte(DW.LNS.set_epilogue_begin);1132 try dlw.writeByte(DW.LNS.set_epilogue_begin);
1079 }1133 }
10801134
1135 pub fn enterInlineFunc(wip_nav: *WipNav, func: InternPool.Index, code_off: u64, line: u32, column: u32) UpdateError!void {
1136 const dwarf = wip_nav.dwarf;
1137 const zcu = wip_nav.pt.zcu;
1138 const diw = wip_nav.debug_info.writer(dwarf.gpa);
1139 try wip_nav.inlined_funcs_high_reloc.ensureUnusedCapacity(dwarf.gpa, 1);
1140
1141 try uleb128(diw, @intFromEnum(AbbrevCode.inlined_func));
1142 try wip_nav.refNav(zcu.funcInfo(func).owner_nav);
1143 try uleb128(diw, zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1);
1144 try uleb128(diw, column + 1);
1145 const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
1146 try external_relocs.ensureUnusedCapacity(dwarf.gpa, 2);
1147 external_relocs.appendAssumeCapacity(.{
1148 .source_off = @intCast(wip_nav.debug_info.items.len),
1149 .target_sym = wip_nav.func_sym_index,
1150 .target_off = code_off,
1151 });
1152 try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
1153 wip_nav.inlined_funcs_high_reloc.appendAssumeCapacity(@intCast(external_relocs.items.len));
1154 external_relocs.appendAssumeCapacity(.{
1155 .source_off = @intCast(wip_nav.debug_info.items.len),
1156 .target_sym = wip_nav.func_sym_index,
1157 .target_off = undefined,
1158 });
1159 try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
1160 try wip_nav.setInlineFunc(func);
1161 }
1162
1163 pub fn leaveInlineFunc(wip_nav: *WipNav, func: InternPool.Index, code_off: u64) UpdateError!void {
1164 const external_relocs = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
1165 external_relocs.items[wip_nav.inlined_funcs_high_reloc.pop()].target_off = code_off;
1166 try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null));
1167 try wip_nav.setInlineFunc(func);
1168 }
1169
1081 pub fn setInlineFunc(wip_nav: *WipNav, func: InternPool.Index) UpdateError!void {1170 pub fn setInlineFunc(wip_nav: *WipNav, func: InternPool.Index) UpdateError!void {
1171 wip_nav.any_children = true;
1082 const zcu = wip_nav.pt.zcu;1172 const zcu = wip_nav.pt.zcu;
1083 const dwarf = wip_nav.dwarf;1173 const dwarf = wip_nav.dwarf;
1084 if (wip_nav.func == func) return;1174 if (wip_nav.func == func) return;
...@@ -1096,8 +1186,7 @@ pub const WipNav = struct {...@@ -1096,8 +1186,7 @@ pub const WipNav = struct {
1096 try dlw.writeByte(DW.LNS.extended_op);1186 try dlw.writeByte(DW.LNS.extended_op);
1097 try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());1187 try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());
1098 try dlw.writeByte(DW.LNE.ZIG_set_decl);1188 try dlw.writeByte(DW.LNE.ZIG_set_decl);
1099 try dwarf.debug_line.section.getUnit(wip_nav.unit).cross_section_relocs.append(dwarf.gpa, .{1189 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
1100 .source_entry = wip_nav.entry.toOptional(),
1101 .source_off = @intCast(wip_nav.debug_line.items.len),1190 .source_off = @intCast(wip_nav.debug_line.items.len),
1102 .target_sec = .debug_info,1191 .target_sec = .debug_info,
1103 .target_unit = new_unit,1192 .target_unit = new_unit,
...@@ -1133,9 +1222,9 @@ pub const WipNav = struct {...@@ -1133,9 +1222,9 @@ pub const WipNav = struct {
1133 fn infoSectionOffset(wip_nav: *WipNav, sec: Section.Index, unit: Unit.Index, entry: Entry.Index, off: u32) UpdateError!void {1222 fn infoSectionOffset(wip_nav: *WipNav, sec: Section.Index, unit: Unit.Index, entry: Entry.Index, off: u32) UpdateError!void {
1134 const dwarf = wip_nav.dwarf;1223 const dwarf = wip_nav.dwarf;
1135 const gpa = dwarf.gpa;1224 const gpa = dwarf.gpa;
1225 const entry_ptr = dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry);
1136 if (sec != .debug_info) {1226 if (sec != .debug_info) {
1137 try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_section_relocs.append(gpa, .{1227 try entry_ptr.cross_section_relocs.append(gpa, .{
1138 .source_entry = wip_nav.entry.toOptional(),
1139 .source_off = @intCast(wip_nav.debug_info.items.len),1228 .source_off = @intCast(wip_nav.debug_info.items.len),
1140 .target_sec = sec,1229 .target_sec = sec,
1141 .target_unit = unit,1230 .target_unit = unit,
...@@ -1143,16 +1232,14 @@ pub const WipNav = struct {...@@ -1143,16 +1232,14 @@ pub const WipNav = struct {
1143 .target_off = off,1232 .target_off = off,
1144 });1233 });
1145 } else if (unit != wip_nav.unit) {1234 } else if (unit != wip_nav.unit) {
1146 try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_unit_relocs.append(gpa, .{1235 try entry_ptr.cross_unit_relocs.append(gpa, .{
1147 .source_entry = wip_nav.entry.toOptional(),
1148 .source_off = @intCast(wip_nav.debug_info.items.len),1236 .source_off = @intCast(wip_nav.debug_info.items.len),
1149 .target_unit = unit,1237 .target_unit = unit,
1150 .target_entry = entry.toOptional(),1238 .target_entry = entry.toOptional(),
1151 .target_off = off,1239 .target_off = off,
1152 });1240 });
1153 } else {1241 } else {
1154 try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs.append(gpa, .{1242 try entry_ptr.cross_entry_relocs.append(gpa, .{
1155 .source_entry = wip_nav.entry.toOptional(),
1156 .source_off = @intCast(wip_nav.debug_info.items.len),1243 .source_off = @intCast(wip_nav.debug_info.items.len),
1157 .target_entry = entry,1244 .target_entry = entry,
1158 .target_off = off,1245 .target_off = off,
...@@ -1167,8 +1254,7 @@ pub const WipNav = struct {...@@ -1167,8 +1254,7 @@ pub const WipNav = struct {
11671254
1168 fn addrSym(wip_nav: *WipNav, sym_index: u32) UpdateError!void {1255 fn addrSym(wip_nav: *WipNav, sym_index: u32) UpdateError!void {
1169 const dwarf = wip_nav.dwarf;1256 const dwarf = wip_nav.dwarf;
1170 try dwarf.debug_info.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{1257 try dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
1171 .source_entry = wip_nav.entry,
1172 .source_off = @intCast(wip_nav.debug_info.items.len),1258 .source_off = @intCast(wip_nav.debug_info.items.len),
1173 .target_sym = sym_index,1259 .target_sym = sym_index,
1174 });1260 });
...@@ -1217,12 +1303,20 @@ pub const WipNav = struct {...@@ -1217,12 +1303,20 @@ pub const WipNav = struct {
1217 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);1303 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
1218 }1304 }
12191305
1306 fn refNav(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!void {
1307 const zcu = wip_nav.pt.zcu;
1308 const ip = &zcu.intern_pool;
1309 const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav_index).srcInst(ip).resolveFile(ip)).mod);
1310 const nav_gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index);
1311 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try wip_nav.dwarf.addCommonEntry(unit);
1312 try wip_nav.infoSectionOffset(.debug_info, unit, nav_gop.value_ptr.*, 0);
1313 }
1314
1220 fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 {1315 fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 {
1221 const dwarf = wip_nav.dwarf;1316 const dwarf = wip_nav.dwarf;
1222 const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs;1317 const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs;
1223 const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);1318 const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);
1224 try cross_entry_relocs.append(dwarf.gpa, .{1319 try cross_entry_relocs.append(dwarf.gpa, .{
1225 .source_entry = wip_nav.entry.toOptional(),
1226 .source_off = @intCast(wip_nav.debug_info.items.len),1320 .source_off = @intCast(wip_nav.debug_info.items.len),
1227 .target_entry = undefined,1321 .target_entry = undefined,
1228 .target_off = undefined,1322 .target_off = undefined,
...@@ -1232,7 +1326,7 @@ pub const WipNav = struct {...@@ -1232,7 +1326,7 @@ pub const WipNav = struct {
1232 }1326 }
12331327
1234 fn finishForward(wip_nav: *WipNav, reloc_index: u32) void {1328 fn finishForward(wip_nav: *WipNav, reloc_index: u32) void {
1235 const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs.items[reloc_index];1329 const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index];
1236 reloc.target_entry = wip_nav.entry;1330 reloc.target_entry = wip_nav.entry;
1237 reloc.target_off = @intCast(wip_nav.debug_info.items.len);1331 reloc.target_off = @intCast(wip_nav.debug_info.items.len);
1238 }1332 }
...@@ -1545,7 +1639,15 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -1545,7 +1639,15 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
1545 const unit = try dwarf.getUnit(file.mod);1639 const unit = try dwarf.getUnit(file.mod);
1546 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);1640 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
1547 errdefer _ = dwarf.navs.pop();1641 errdefer _ = dwarf.navs.pop();
1548 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);1642 if (nav_gop.found_existing) {
1643 for ([_]*Section{
1644 &dwarf.debug_aranges.section,
1645 &dwarf.debug_info.section,
1646 &dwarf.debug_line.section,
1647 &dwarf.debug_loclists.section,
1648 &dwarf.debug_rnglists.section,
1649 }) |sec| sec.getUnit(unit).getEntry(nav_gop.value_ptr.*).clear();
1650 } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
1549 const nav_val = zcu.navValue(nav_index);1651 const nav_val = zcu.navValue(nav_index);
1550 var wip_nav: WipNav = .{1652 var wip_nav: WipNav = .{
1551 .dwarf = dwarf,1653 .dwarf = dwarf,
...@@ -1554,7 +1656,9 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -1554,7 +1656,9 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
1554 .entry = nav_gop.value_ptr.*,1656 .entry = nav_gop.value_ptr.*,
1555 .any_children = false,1657 .any_children = false,
1556 .func = .none,1658 .func = .none,
1659 .func_sym_index = undefined,
1557 .func_high_reloc = undefined,1660 .func_high_reloc = undefined,
1661 .inlined_funcs_high_reloc = undefined,
1558 .debug_info = .{},1662 .debug_info = .{},
1559 .debug_line = .{},1663 .debug_line = .{},
1560 .debug_loclists = .{},1664 .debug_loclists = .{},
...@@ -1608,16 +1712,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -1608,16 +1712,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
1608 try wip_nav.exprloc(.{ .addr = .{ .sym = sym_index } });1712 try wip_nav.exprloc(.{ .addr = .{ .sym = sym_index } });
1609 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse1713 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
1610 ty.abiAlignment(pt).toByteUnits().?);1714 ty.abiAlignment(pt).toByteUnits().?);
1611 const func_unit = InternPool.AnalUnit.wrap(.{ .func = nav_val.toIntern() });1715 try diw.writeByte(@intFromBool(false));
1612 try diw.writeByte(@intFromBool(for (if (zcu.single_exports.get(func_unit)) |export_index|
1613 zcu.all_exports.items[export_index..][0..1]
1614 else if (zcu.multi_exports.get(func_unit)) |export_range|
1615 zcu.all_exports.items[export_range.index..][0..export_range.len]
1616 else
1617 &.{}) |@"export"|
1618 {
1619 if (@"export".exported == .nav and @"export".exported.nav == nav_index) break true;
1620 } else false));
1621 wip_nav.finishForward(ty_reloc_index);1716 wip_nav.finishForward(ty_reloc_index);
1622 try uleb128(diw, @intFromEnum(AbbrevCode.is_const));1717 try uleb128(diw, @intFromEnum(AbbrevCode.is_const));
1623 try wip_nav.refType(ty);1718 try wip_nav.refType(ty);
...@@ -1668,16 +1763,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -1668,16 +1763,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
1668 try wip_nav.exprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr);1763 try wip_nav.exprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr);
1669 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse1764 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
1670 ty.abiAlignment(pt).toByteUnits().?);1765 ty.abiAlignment(pt).toByteUnits().?);
1671 const func_unit = InternPool.AnalUnit.wrap(.{ .func = nav_val.toIntern() });1766 try diw.writeByte(@intFromBool(false));
1672 try diw.writeByte(@intFromBool(for (if (zcu.single_exports.get(func_unit)) |export_index|
1673 zcu.all_exports.items[export_index..][0..1]
1674 else if (zcu.multi_exports.get(func_unit)) |export_range|
1675 zcu.all_exports.items[export_range.index..][0..export_range.len]
1676 else
1677 &.{}) |@"export"|
1678 {
1679 if (@"export".exported == .nav and @"export".exported.nav == nav_index) break true;
1680 } else false));
1681 },1767 },
1682 .func => |func| {1768 .func => |func| {
1683 assert(file.zir_loaded);1769 assert(file.zir_loaded);
...@@ -1712,6 +1798,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -1712,6 +1798,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
17121798
1713 const func_type = ip.indexToKey(func.ty).func_type;1799 const func_type = ip.indexToKey(func.ty).func_type;
1714 wip_nav.func = nav_val.toIntern();1800 wip_nav.func = nav_val.toIntern();
1801 wip_nav.func_sym_index = sym_index;
1802 wip_nav.inlined_funcs_high_reloc = .{};
17151803
1716 const diw = wip_nav.debug_info.writer(dwarf.gpa);1804 const diw = wip_nav.debug_info.writer(dwarf.gpa);
1717 try uleb128(diw, @intFromEnum(AbbrevCode.decl_func));1805 try uleb128(diw, @intFromEnum(AbbrevCode.decl_func));
...@@ -1723,32 +1811,23 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -1723,32 +1811,23 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
1723 try wip_nav.strp(nav.name.toSlice(ip));1811 try wip_nav.strp(nav.name.toSlice(ip));
1724 try wip_nav.strp(nav.fqn.toSlice(ip));1812 try wip_nav.strp(nav.fqn.toSlice(ip));
1725 try wip_nav.refType(Type.fromInterned(func_type.return_type));1813 try wip_nav.refType(Type.fromInterned(func_type.return_type));
1726 const external_relocs = &dwarf.debug_info.section.getUnit(unit).external_relocs;1814 const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
1727 try external_relocs.append(dwarf.gpa, .{1815 try external_relocs.ensureUnusedCapacity(dwarf.gpa, 2);
1728 .source_entry = wip_nav.entry,1816 external_relocs.appendAssumeCapacity(.{
1729 .source_off = @intCast(wip_nav.debug_info.items.len),1817 .source_off = @intCast(wip_nav.debug_info.items.len),
1730 .target_sym = sym_index,1818 .target_sym = sym_index,
1731 });1819 });
1732 try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));1820 try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
1733 wip_nav.func_high_reloc = @intCast(external_relocs.items.len);1821 wip_nav.func_high_reloc = @intCast(external_relocs.items.len);
1734 try external_relocs.append(dwarf.gpa, .{1822 external_relocs.appendAssumeCapacity(.{
1735 .source_entry = wip_nav.entry,
1736 .source_off = @intCast(wip_nav.debug_info.items.len),1823 .source_off = @intCast(wip_nav.debug_info.items.len),
1737 .target_sym = sym_index,1824 .target_sym = sym_index,
1825 .target_off = undefined,
1738 });1826 });
1739 try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));1827 try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
1740 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse1828 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
1741 target_info.defaultFunctionAlignment(file.mod.resolved_target.result).toByteUnits().?);1829 target_info.defaultFunctionAlignment(file.mod.resolved_target.result).toByteUnits().?);
1742 const func_unit = InternPool.AnalUnit.wrap(.{ .func = nav_val.toIntern() });1830 try diw.writeByte(@intFromBool(false));
1743 try diw.writeByte(@intFromBool(for (if (zcu.single_exports.get(func_unit)) |export_index|
1744 zcu.all_exports.items[export_index..][0..1]
1745 else if (zcu.multi_exports.get(func_unit)) |export_range|
1746 zcu.all_exports.items[export_range.index..][0..export_range.len]
1747 else
1748 &.{}) |@"export"|
1749 {
1750 if (@"export".exported == .nav and @"export".exported.nav == nav_index) break true;
1751 } else false));
1752 try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));1831 try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));
17531832
1754 const dlw = wip_nav.debug_line.writer(dwarf.gpa);1833 const dlw = wip_nav.debug_line.writer(dwarf.gpa);
...@@ -1756,8 +1835,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -1756,8 +1835,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
1756 if (dwarf.incremental()) {1835 if (dwarf.incremental()) {
1757 try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());1836 try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());
1758 try dlw.writeByte(DW.LNE.ZIG_set_decl);1837 try dlw.writeByte(DW.LNE.ZIG_set_decl);
1759 try dwarf.debug_line.section.getUnit(wip_nav.unit).cross_section_relocs.append(dwarf.gpa, .{1838 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
1760 .source_entry = wip_nav.entry.toOptional(),
1761 .source_off = @intCast(wip_nav.debug_line.items.len),1839 .source_off = @intCast(wip_nav.debug_line.items.len),
1762 .target_sec = .debug_info,1840 .target_sec = .debug_info,
1763 .target_unit = wip_nav.unit,1841 .target_unit = wip_nav.unit,
...@@ -1772,8 +1850,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -1772,8 +1850,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
1772 } else {1850 } else {
1773 try uleb128(dlw, 1 + @intFromEnum(dwarf.address_size));1851 try uleb128(dlw, 1 + @intFromEnum(dwarf.address_size));
1774 try dlw.writeByte(DW.LNE.set_address);1852 try dlw.writeByte(DW.LNE.set_address);
1775 try dwarf.debug_line.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{1853 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
1776 .source_entry = wip_nav.entry,
1777 .source_off = @intCast(wip_nav.debug_line.items.len),1854 .source_off = @intCast(wip_nav.debug_line.items.len),
1778 .target_sym = sym_index,1855 .target_sym = sym_index,
1779 });1856 });
...@@ -1806,7 +1883,8 @@ pub fn finishWipNav(...@@ -1806,7 +1883,8 @@ pub fn finishWipNav(
1806 log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)});1883 log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)});
18071884
1808 if (wip_nav.func != .none) {1885 if (wip_nav.func != .none) {
1809 dwarf.debug_info.section.getUnit(wip_nav.unit).external_relocs.items[wip_nav.func_high_reloc].target_off = sym.size;1886 const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
1887 external_relocs.items[wip_nav.func_high_reloc].target_off = sym.size;
1810 if (wip_nav.any_children) {1888 if (wip_nav.any_children) {
1811 const diw = wip_nav.debug_info.writer(dwarf.gpa);1889 const diw = wip_nav.debug_info.writer(dwarf.gpa);
1812 try uleb128(diw, @intFromEnum(AbbrevCode.null));1890 try uleb128(diw, @intFromEnum(AbbrevCode.null));
...@@ -1817,8 +1895,7 @@ pub fn finishWipNav(...@@ -1817,8 +1895,7 @@ pub fn finishWipNav(
1817 );1895 );
18181896
1819 var aranges_entry = [1]u8{0} ** (8 + 8);1897 var aranges_entry = [1]u8{0} ** (8 + 8);
1820 try dwarf.debug_aranges.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{1898 try dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
1821 .source_entry = wip_nav.entry,
1822 .target_sym = sym.index,1899 .target_sym = sym.index,
1823 });1900 });
1824 dwarf.writeInt(aranges_entry[0..@intFromEnum(dwarf.address_size)], 0);1901 dwarf.writeInt(aranges_entry[0..@intFromEnum(dwarf.address_size)], 0);
...@@ -1832,14 +1909,12 @@ pub fn finishWipNav(...@@ -1832,14 +1909,12 @@ pub fn finishWipNav(
1832 aranges_entry[0 .. @intFromEnum(dwarf.address_size) * 2],1909 aranges_entry[0 .. @intFromEnum(dwarf.address_size) * 2],
1833 );1910 );
18341911
1835 try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).external_relocs.appendSlice(dwarf.gpa, &.{1912 try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.appendSlice(dwarf.gpa, &.{
1836 .{1913 .{
1837 .source_entry = wip_nav.entry,
1838 .source_off = 1,1914 .source_off = 1,
1839 .target_sym = sym.index,1915 .target_sym = sym.index,
1840 },1916 },
1841 .{1917 .{
1842 .source_entry = wip_nav.entry,
1843 .source_off = 1 + @intFromEnum(dwarf.address_size),1918 .source_off = 1 + @intFromEnum(dwarf.address_size),
1844 .target_sym = sym.index,1919 .target_sym = sym.index,
1845 .target_off = sym.size,1920 .target_off = sym.size,
...@@ -1891,7 +1966,9 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -1891,7 +1966,9 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
1891 .entry = undefined,1966 .entry = undefined,
1892 .any_children = false,1967 .any_children = false,
1893 .func = .none,1968 .func = .none,
1969 .func_sym_index = undefined,
1894 .func_high_reloc = undefined,1970 .func_high_reloc = undefined,
1971 .inlined_funcs_high_reloc = undefined,
1895 .debug_info = .{},1972 .debug_info = .{},
1896 .debug_line = .{},1973 .debug_line = .{},
1897 .debug_loclists = .{},1974 .debug_loclists = .{},
...@@ -1902,6 +1979,62 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -1902,6 +1979,62 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
1902 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);1979 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
1903 errdefer _ = dwarf.navs.pop();1980 errdefer _ = dwarf.navs.pop();
1904 switch (ip.indexToKey(nav_val.toIntern())) {1981 switch (ip.indexToKey(nav_val.toIntern())) {
1982 .func => |func| {
1983 if (nav_gop.found_existing) {
1984 const unit_ptr = dwarf.debug_info.section.getUnit(unit);
1985 const entry_ptr = unit_ptr.getEntry(nav_gop.value_ptr.*);
1986 if (entry_ptr.len >= AbbrevCode.decl_bytes) {
1987 var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined;
1988 if (try dwarf.getFile().?.preadAll(
1989 &abbrev_code_buf,
1990 dwarf.debug_info.section.off + unit_ptr.off + unit_ptr.header_len + entry_ptr.off,
1991 ) != abbrev_code_buf.len) return error.InputOutput;
1992 var abbrev_code_fbs = std.io.fixedBufferStream(&abbrev_code_buf);
1993 const abbrev_code: AbbrevCode = @enumFromInt(
1994 try std.leb.readUleb128(@typeInfo(AbbrevCode).Enum.tag_type, abbrev_code_fbs.reader()),
1995 );
1996 switch (abbrev_code) {
1997 else => unreachable,
1998 .decl_func, .decl_func_empty => return,
1999 .decl_func_generic, .decl_func_generic_empty => {},
2000 }
2001 }
2002 entry_ptr.clear();
2003 } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2004 wip_nav.entry = nav_gop.value_ptr.*;
2005
2006 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
2007 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
2008 break :parent .{
2009 parent_namespace_ptr.owner_type,
2010 if (parent_namespace_ptr.pub_decls.containsContext(nav_index, .{ .zcu = zcu }))
2011 DW.ACCESS.public
2012 else if (parent_namespace_ptr.priv_decls.containsContext(nav_index, .{ .zcu = zcu }))
2013 DW.ACCESS.private
2014 else
2015 unreachable,
2016 };
2017 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
2018
2019 const func_type = ip.indexToKey(func.ty).func_type;
2020 const diw = wip_nav.debug_info.writer(dwarf.gpa);
2021 try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (func_type.param_types.len > 0 or func_type.is_var_args) .decl_func_generic else .decl_func_generic_empty)));
2022 try wip_nav.refType(Type.fromInterned(parent_type));
2023 assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
2024 try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
2025 try uleb128(diw, loc.column + 1);
2026 try diw.writeByte(accessibility);
2027 try wip_nav.strp(nav.name.toSlice(ip));
2028 try wip_nav.refType(Type.fromInterned(func_type.return_type));
2029 if (func_type.param_types.len > 0 or func_type.is_var_args) {
2030 for (0..func_type.param_types.len) |param_index| {
2031 try uleb128(diw, @intFromEnum(AbbrevCode.func_type_param));
2032 try wip_nav.refType(Type.fromInterned(func_type.param_types.get(ip)[param_index]));
2033 }
2034 if (func_type.is_var_args) try uleb128(diw, @intFromEnum(AbbrevCode.is_var_args));
2035 try uleb128(diw, @intFromEnum(AbbrevCode.null));
2036 }
2037 },
1905 .struct_type => done: {2038 .struct_type => done: {
1906 const loaded_struct = ip.loadStructType(nav_val.toIntern());2039 const loaded_struct = ip.loadStructType(nav_val.toIntern());
19072040
...@@ -2304,7 +2437,9 @@ fn updateType(...@@ -2304,7 +2437,9 @@ fn updateType(
2304 .entry = dwarf.types.get(type_index).?,2437 .entry = dwarf.types.get(type_index).?,
2305 .any_children = false,2438 .any_children = false,
2306 .func = .none,2439 .func = .none,
2440 .func_sym_index = undefined,
2307 .func_high_reloc = undefined,2441 .func_high_reloc = undefined,
2442 .inlined_funcs_high_reloc = undefined,
2308 .debug_info = .{},2443 .debug_info = .{},
2309 .debug_line = .{},2444 .debug_line = .{},
2310 .debug_loclists = .{},2445 .debug_loclists = .{},
...@@ -2467,13 +2602,25 @@ fn updateType(...@@ -2467,13 +2602,25 @@ fn updateType(
2467 .error_union_type => |error_union_type| {2602 .error_union_type => |error_union_type| {
2468 const error_union_error_set_type = Type.fromInterned(error_union_type.error_set_type);2603 const error_union_error_set_type = Type.fromInterned(error_union_type.error_set_type);
2469 const error_union_payload_type = Type.fromInterned(error_union_type.payload_type);2604 const error_union_payload_type = Type.fromInterned(error_union_type.payload_type);
2470 const error_union_error_set_offset = codegen.errUnionErrorOffset(error_union_payload_type, pt);2605 const error_union_error_set_offset, const error_union_payload_offset = switch (error_union_type.payload_type) {
2471 const error_union_payload_offset = codegen.errUnionPayloadOffset(error_union_payload_type, pt);2606 .generic_poison_type => .{ 0, 0 },
2607 else => .{
2608 codegen.errUnionErrorOffset(error_union_payload_type, pt),
2609 codegen.errUnionPayloadOffset(error_union_payload_type, pt),
2610 },
2611 };
24722612
2473 try uleb128(diw, @intFromEnum(AbbrevCode.union_type));2613 try uleb128(diw, @intFromEnum(AbbrevCode.union_type));
2474 try wip_nav.strp(name);2614 try wip_nav.strp(name);
2475 try uleb128(diw, ty.abiSize(pt));2615 if (error_union_type.error_set_type != .generic_poison_type and
2476 try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);2616 error_union_type.payload_type != .generic_poison_type)
2617 {
2618 try uleb128(diw, ty.abiSize(pt));
2619 try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
2620 } else {
2621 try uleb128(diw, 0);
2622 try uleb128(diw, 1);
2623 }
2477 {2624 {
2478 try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));2625 try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));
2479 try wip_nav.infoSectionOffset(2626 try wip_nav.infoSectionOffset(
...@@ -2655,10 +2802,16 @@ fn updateType(...@@ -2655,10 +2802,16 @@ fn updateType(
2655 }2802 }
2656 if (error_set_type.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));2803 if (error_set_type.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));
2657 },2804 },
2658 .inferred_error_set_type => |func| {2805 .inferred_error_set_type => |func| switch (ip.funcIesResolvedUnordered(func)) {
2659 try uleb128(diw, @intFromEnum(AbbrevCode.inferred_error_set_type));2806 .none => {
2660 try wip_nav.strp(name);2807 try uleb128(diw, @intFromEnum(AbbrevCode.void_type));
2661 try wip_nav.refType(Type.fromInterned(ip.funcIesResolvedUnordered(func)));2808 try wip_nav.strp(name);
2809 },
2810 else => |ies| {
2811 try uleb128(diw, @intFromEnum(AbbrevCode.inferred_error_set_type));
2812 try wip_nav.strp(name);
2813 try wip_nav.refType(Type.fromInterned(ies));
2814 },
2662 },2815 },
26632816
2664 // values, not types2817 // values, not types
...@@ -2705,7 +2858,9 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP...@@ -2705,7 +2858,9 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
2705 .entry = type_gop.value_ptr.*,2858 .entry = type_gop.value_ptr.*,
2706 .any_children = false,2859 .any_children = false,
2707 .func = .none,2860 .func = .none,
2861 .func_sym_index = undefined,
2708 .func_high_reloc = undefined,2862 .func_high_reloc = undefined,
2863 .inlined_funcs_high_reloc = undefined,
2709 .debug_info = .{},2864 .debug_info = .{},
2710 .debug_line = .{},2865 .debug_line = .{},
2711 .debug_loclists = .{},2866 .debug_loclists = .{},
...@@ -2766,7 +2921,9 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP...@@ -2766,7 +2921,9 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
2766 .entry = type_gop.value_ptr.*,2921 .entry = type_gop.value_ptr.*,
2767 .any_children = false,2922 .any_children = false,
2768 .func = .none,2923 .func = .none,
2924 .func_sym_index = undefined,
2769 .func_high_reloc = undefined,2925 .func_high_reloc = undefined,
2926 .inlined_funcs_high_reloc = undefined,
2770 .debug_info = .{},2927 .debug_info = .{},
2771 .debug_line = .{},2928 .debug_line = .{},
2772 .debug_loclists = .{},2929 .debug_loclists = .{},
...@@ -2940,7 +3097,9 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -2940,7 +3097,9 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
2940 .entry = entry,3097 .entry = entry,
2941 .any_children = false,3098 .any_children = false,
2942 .func = .none,3099 .func = .none,
3100 .func_sym_index = undefined,
2943 .func_high_reloc = undefined,3101 .func_high_reloc = undefined,
3102 .inlined_funcs_high_reloc = undefined,
2944 .debug_info = .{},3103 .debug_info = .{},
2945 .debug_line = .{},3104 .debug_line = .{},
2946 .debug_loclists = .{},3105 .debug_loclists = .{},
...@@ -2998,7 +3157,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -2998,7 +3157,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
2998 if (dwarf.debug_aranges.section.dirty) {3157 if (dwarf.debug_aranges.section.dirty) {
2999 for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {3158 for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {
3000 const unit: Unit.Index = @enumFromInt(unit_index);3159 const unit: Unit.Index = @enumFromInt(unit_index);
3001 try unit_ptr.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 1);3160 unit_ptr.clear();
3161 try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 1);
3002 header.clearRetainingCapacity();3162 header.clearRetainingCapacity();
3003 try header.ensureTotalCapacity(unit_ptr.header_len);3163 try header.ensureTotalCapacity(unit_ptr.header_len);
3004 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|3164 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
...@@ -3029,8 +3189,9 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -3029,8 +3189,9 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
3029 if (dwarf.debug_info.section.dirty) {3189 if (dwarf.debug_info.section.dirty) {
3030 for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| {3190 for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| {
3031 const unit: Unit.Index = @enumFromInt(unit_index);3191 const unit: Unit.Index = @enumFromInt(unit_index);
3032 try unit_ptr.cross_unit_relocs.ensureUnusedCapacity(dwarf.gpa, 1);3192 unit_ptr.clear();
3033 try unit_ptr.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 7);3193 try unit_ptr.cross_unit_relocs.ensureTotalCapacity(dwarf.gpa, 1);
3194 try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 7);
3034 header.clearRetainingCapacity();3195 header.clearRetainingCapacity();
3035 try header.ensureTotalCapacity(unit_ptr.header_len);3196 try header.ensureTotalCapacity(unit_ptr.header_len);
3036 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|3197 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
...@@ -3121,7 +3282,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -3121,7 +3282,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
3121 for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit|3282 for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit|
3122 try unit.resizeHeader(&dwarf.debug_line.section, dwarf, DebugLine.headerBytes(dwarf, @intCast(mod_info.dirs.count()), @intCast(mod_info.files.count())));3283 try unit.resizeHeader(&dwarf.debug_line.section, dwarf, DebugLine.headerBytes(dwarf, @intCast(mod_info.dirs.count()), @intCast(mod_info.files.count())));
3123 for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| {3284 for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| {
3124 try unit.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 2 * (1 + mod_info.files.count()));3285 unit.clear();
3286 try unit.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 2 * (1 + mod_info.files.count()));
3125 header.clearRetainingCapacity();3287 header.clearRetainingCapacity();
3126 try header.ensureTotalCapacity(unit.header_len);3288 try header.ensureTotalCapacity(unit.header_len);
3127 const unit_len = (if (unit.next.unwrap()) |next_unit|3289 const unit_len = (if (unit.next.unwrap()) |next_unit|
...@@ -3310,6 +3472,8 @@ const AbbrevCode = enum(u8) {...@@ -3310,6 +3472,8 @@ const AbbrevCode = enum(u8) {
3310 decl_var,3472 decl_var,
3311 decl_func,3473 decl_func,
3312 decl_func_empty,3474 decl_func_empty,
3475 decl_func_generic,
3476 decl_func_generic_empty,
3313 // the rest are unrestricted3477 // the rest are unrestricted
3314 compile_unit,3478 compile_unit,
3315 module,3479 module,
...@@ -3344,10 +3508,11 @@ const AbbrevCode = enum(u8) {...@@ -3344,10 +3508,11 @@ const AbbrevCode = enum(u8) {
3344 struct_type,3508 struct_type,
3345 packed_struct_type,3509 packed_struct_type,
3346 union_type,3510 union_type,
3511 inlined_func,
3347 local_arg,3512 local_arg,
3348 local_var,3513 local_var,
33493514
3350 const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_func_empty));3515 const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_func_generic_empty));
33513516
3352 const Attr = struct {3517 const Attr = struct {
3353 DeclValEnum(DW.AT),3518 DeclValEnum(DW.AT),
...@@ -3451,6 +3616,19 @@ const AbbrevCode = enum(u8) {...@@ -3451,6 +3616,19 @@ const AbbrevCode = enum(u8) {
3451 .{ .noreturn, .flag },3616 .{ .noreturn, .flag },
3452 },3617 },
3453 },3618 },
3619 .decl_func_generic = .{
3620 .tag = .subprogram,
3621 .children = true,
3622 .attrs = decl_abbrev_common_attrs ++ .{
3623 .{ .type, .ref_addr },
3624 },
3625 },
3626 .decl_func_generic_empty = .{
3627 .tag = .subprogram,
3628 .attrs = decl_abbrev_common_attrs ++ .{
3629 .{ .type, .ref_addr },
3630 },
3631 },
3454 .compile_unit = .{3632 .compile_unit = .{
3455 .tag = .compile_unit,3633 .tag = .compile_unit,
3456 .children = true,3634 .children = true,
...@@ -3706,6 +3884,17 @@ const AbbrevCode = enum(u8) {...@@ -3706,6 +3884,17 @@ const AbbrevCode = enum(u8) {
3706 .{ .alignment, .udata },3884 .{ .alignment, .udata },
3707 },3885 },
3708 },3886 },
3887 .inlined_func = .{
3888 .tag = .inlined_subroutine,
3889 .children = true,
3890 .attrs = &.{
3891 .{ .abstract_origin, .ref_addr },
3892 .{ .call_line, .udata },
3893 .{ .call_column, .udata },
3894 .{ .low_pc, .addr },
3895 .{ .high_pc, .addr },
3896 },
3897 },
3709 .local_arg = .{3898 .local_arg = .{
3710 .tag = .formal_parameter,3899 .tag = .formal_parameter,
3711 .attrs = &.{3900 .attrs = &.{
src/link/Elf/ZigObject.zig+6-6
...@@ -1122,9 +1122,9 @@ pub fn updateNav(...@@ -1122,9 +1122,9 @@ pub fn updateNav(
11221122
1123 log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });1123 log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });
11241124
1125 const nav_val = zcu.navValue(nav_index);1125 const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
1126 const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {1126 .func => .none,
1127 .variable => |variable| Value.fromInterned(variable.init),1127 .variable => |variable| variable.init,
1128 .@"extern" => |@"extern"| {1128 .@"extern" => |@"extern"| {
1129 if (ip.isFunctionType(@"extern".ty)) return;1129 if (ip.isFunctionType(@"extern".ty)) return;
1130 const sym_index = try self.getGlobalSymbol(1130 const sym_index = try self.getGlobalSymbol(
...@@ -1135,10 +1135,10 @@ pub fn updateNav(...@@ -1135,10 +1135,10 @@ pub fn updateNav(
1135 self.symbol(sym_index).flags.is_extern_ptr = true;1135 self.symbol(sym_index).flags.is_extern_ptr = true;
1136 return;1136 return;
1137 },1137 },
1138 else => nav_val,1138 else => nav.status.resolved.val,
1139 };1139 };
11401140
1141 if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {1141 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {
1142 const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index);1142 const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index);
1143 self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);1143 self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
11441144
...@@ -1153,7 +1153,7 @@ pub fn updateNav(...@@ -1153,7 +1153,7 @@ pub fn updateNav(
1153 &elf_file.base,1153 &elf_file.base,
1154 pt,1154 pt,
1155 zcu.navSrcLoc(nav_index),1155 zcu.navSrcLoc(nav_index),
1156 nav_init,1156 Value.fromInterned(nav_init),
1157 &code_buffer,1157 &code_buffer,
1158 if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,1158 if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
1159 .{ .parent_atom_index = sym_index },1159 .{ .parent_atom_index = sym_index },
src/link/MachO/ZigObject.zig+7-6
...@@ -869,10 +869,11 @@ pub fn updateNav(...@@ -869,10 +869,11 @@ pub fn updateNav(
869869
870 const zcu = pt.zcu;870 const zcu = pt.zcu;
871 const ip = &zcu.intern_pool;871 const ip = &zcu.intern_pool;
872 const nav = ip.getNav(nav_index);
872873
873 const nav_val = zcu.navValue(nav_index);874 const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
874 const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {875 .func => .none,
875 .variable => |variable| Value.fromInterned(variable.init),876 .variable => |variable| variable.init,
876 .@"extern" => |@"extern"| {877 .@"extern" => |@"extern"| {
877 if (ip.isFunctionType(@"extern".ty)) return;878 if (ip.isFunctionType(@"extern".ty)) return;
878 // Extern variable gets a __got entry only879 // Extern variable gets a __got entry only
...@@ -883,10 +884,10 @@ pub fn updateNav(...@@ -883,10 +884,10 @@ pub fn updateNav(
883 sym.flags.is_extern_ptr = true;884 sym.flags.is_extern_ptr = true;
884 return;885 return;
885 },886 },
886 else => nav_val,887 else => nav.status.resolved.val,
887 };888 };
888889
889 if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {890 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {
890 const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index);891 const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index);
891 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);892 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
892893
...@@ -900,7 +901,7 @@ pub fn updateNav(...@@ -900,7 +901,7 @@ pub fn updateNav(
900 &macho_file.base,901 &macho_file.base,
901 pt,902 pt,
902 zcu.navSrcLoc(nav_index),903 zcu.navSrcLoc(nav_index),
903 nav_init,904 Value.fromInterned(nav_init),
904 &code_buffer,905 &code_buffer,
905 if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,906 if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
906 .{ .parent_atom_index = sym_index },907 .{ .parent_atom_index = sym_index },
src/link/Plan9.zig+2-1
...@@ -448,6 +448,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -448,6 +448,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
448 const nav = ip.getNav(nav_index);448 const nav = ip.getNav(nav_index);
449 const nav_val = zcu.navValue(nav_index);449 const nav_val = zcu.navValue(nav_index);
450 const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {450 const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
451 .func => return,
451 .variable => |variable| Value.fromInterned(variable.init),452 .variable => |variable| Value.fromInterned(variable.init),
452 .@"extern" => {453 .@"extern" => {
453 log.debug("found extern decl: {}", .{nav.name.fmt(ip)});454 log.debug("found extern decl: {}", .{nav.name.fmt(ip)});
...@@ -456,7 +457,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -456,7 +457,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
456 else => nav_val,457 else => nav_val,
457 };458 };
458459
459 if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {460 if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
460 const atom_idx = try self.seeNav(pt, nav_index);461 const atom_idx = try self.seeNav(pt, nav_index);
461462
462 var code_buffer = std.ArrayList(u8).init(gpa);463 var code_buffer = std.ArrayList(u8).init(gpa);
src/link/Wasm/ZigObject.zig+1-1
...@@ -259,7 +259,7 @@ pub fn updateNav(...@@ -259,7 +259,7 @@ pub fn updateNav(
259 else => .{ false, .none, nav_val },259 else => .{ false, .none, nav_val },
260 };260 };
261261
262 if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {262 if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
263 const gpa = wasm_file.base.comp.gpa;263 const gpa = wasm_file.base.comp.gpa;
264 const atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, nav_index);264 const atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, nav_index);
265 const atom = wasm_file.getAtomPtr(atom_index);265 const atom = wasm_file.getAtomPtr(atom_index);
src/print_air.zig+4-6
...@@ -283,6 +283,7 @@ const Writer = struct {...@@ -283,6 +283,7 @@ const Writer = struct {
283283
284 .dbg_var_ptr,284 .dbg_var_ptr,
285 .dbg_var_val,285 .dbg_var_val,
286 .dbg_arg_inline,
286 => try w.writeDbgVar(s, inst),287 => try w.writeDbgVar(s, inst),
287288
288 .struct_field_ptr => try w.writeStructField(s, inst),289 .struct_field_ptr => try w.writeStructField(s, inst),
...@@ -358,10 +359,7 @@ const Writer = struct {...@@ -358,10 +359,7 @@ const Writer = struct {
358 try w.writeType(s, arg.ty.toType());359 try w.writeType(s, arg.ty.toType());
359 switch (arg.name) {360 switch (arg.name) {
360 .none => {},361 .none => {},
361 _ => {362 _ => try s.print(", \"{}\"", .{std.zig.fmtEscapes(arg.name.toSlice(w.air))}),
362 const name = w.air.nullTerminatedString(@intFromEnum(arg.name));
363 try s.print(", \"{}\"", .{std.zig.fmtEscapes(name)});
364 },
365 }363 }
366 }364 }
367365
...@@ -686,8 +684,8 @@ const Writer = struct {...@@ -686,8 +684,8 @@ const Writer = struct {
686 fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {684 fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
687 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;685 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
688 try w.writeOperand(s, inst, 0, pl_op.operand);686 try w.writeOperand(s, inst, 0, pl_op.operand);
689 const name = w.air.nullTerminatedString(pl_op.payload);687 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
690 try s.print(", \"{}\"", .{std.zig.fmtEscapes(name)});688 try s.print(", \"{}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))});
691 }689 }
692690
693 fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {691 fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
test/src/Debugger.zig+73-13
...@@ -587,7 +587,7 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {...@@ -587,7 +587,7 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
587 },587 },
588 );588 );
589 db.addLldbTest(589 db.addLldbTest(
590 "cross_module_call",590 "inline_call",
591 target,591 target,
592 &.{592 &.{
593 .{593 .{
...@@ -595,8 +595,18 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {...@@ -595,8 +595,18 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
595 .source =595 .source =
596 \\const module = @import("module");596 \\const module = @import("module");
597 \\pub fn main() void {597 \\pub fn main() void {
598 \\ module.foo(123);598 \\ fa(12);
599 \\ module.bar(456);599 \\ fb(34);
600 \\ module.fc(56);
601 \\ module.fd(78);
602 \\}
603 \\fn fa(pa: u32) void {
604 \\ const la = ~pa;
605 \\ _ = la;
606 \\}
607 \\inline fn fb(pb: u32) void {
608 \\ const lb = ~pb;
609 \\ _ = lb;
600 \\}610 \\}
601 \\611 \\
602 ,612 ,
...@@ -605,34 +615,84 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {...@@ -605,34 +615,84 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
605 .import = "module",615 .import = "module",
606 .path = "module.zig",616 .path = "module.zig",
607 .source =617 .source =
608 \\pub fn foo(x: u32) void {618 \\pub fn fc(pc: u32) void {
609 \\ _ = x;619 \\ const lc = ~pc;
620 \\ _ = lc;
610 \\}621 \\}
611 \\pub inline fn bar(y: u32) void {622 \\pub inline fn fd(pd: u32) void {
612 \\ _ = y;623 \\ const ld = ~pd;
624 \\ _ = ld;
613 \\}625 \\}
614 \\626 \\
615 ,627 ,
616 },628 },
617 },629 },
618 \\breakpoint set --file module.zig --source-pattern-regexp '_ = x;'630 \\settings set frame-format 'frame #${frame.index}:{ ${module.file.basename}{\`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${line.file.basename}:${line.number}{:${line.column}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\n'
631 \\
632 \\breakpoint set --file main.zig --source-pattern-regexp '_ = la;'
619 \\process launch633 \\process launch
620 \\source info634 \\frame variable pa la
635 \\thread backtrace --count 2
621 \\breakpoint delete --force 1636 \\breakpoint delete --force 1
622 \\637 \\
623 \\breakpoint set --file module.zig --line 5638 \\breakpoint set --file main.zig --source-pattern-regexp '_ = lb;'
624 \\process continue639 \\process continue
625 \\source info640 \\frame variable pb lb
641 \\thread backtrace --count 2
626 \\breakpoint delete --force 2642 \\breakpoint delete --force 2
643 \\
644 \\breakpoint set --file module.zig --source-pattern-regexp '_ = lc;'
645 \\process continue
646 \\frame variable pc lc
647 \\thread backtrace --count 2
648 \\breakpoint delete --force 3
649 \\
650 \\breakpoint set --file module.zig --line 7
651 \\process continue
652 \\frame variable pd ld
653 \\thread backtrace --count 2
654 \\breakpoint delete --force 4
627 ,655 ,
628 &.{656 &.{
629 \\/module.zig:2:5657 \\(lldb) frame variable pa la
658 \\(u32) pa = 12
659 \\(u32) la = 4294967283
660 \\(lldb) thread backtrace --count 2
661 \\* thread #1, name = 'inline_call', stop reason = breakpoint 1.1
662 \\ * frame #0: inline_call`main.fa(pa=12) at main.zig:10:5
663 \\ frame #1: inline_call`main.main at main.zig:3:7
630 \\(lldb) breakpoint delete --force 1664 \\(lldb) breakpoint delete --force 1
631 \\1 breakpoints deleted; 0 breakpoint locations disabled.665 \\1 breakpoints deleted; 0 breakpoint locations disabled.
632 ,666 ,
633 \\/module.zig:5:5667 \\(lldb) frame variable pb lb
668 \\(u32) pb = 34
669 \\(u32) lb = 4294967261
670 \\(lldb) thread backtrace --count 2
671 \\* thread #1, name = 'inline_call', stop reason = breakpoint 2.1
672 \\ * frame #0: inline_call`main.main [inlined] fb(pb=34) at main.zig:14:5
673 \\ frame #1: inline_call`main.main at main.zig:4:7
634 \\(lldb) breakpoint delete --force 2674 \\(lldb) breakpoint delete --force 2
635 \\1 breakpoints deleted; 0 breakpoint locations disabled.675 \\1 breakpoints deleted; 0 breakpoint locations disabled.
676 ,
677 \\(lldb) frame variable pc lc
678 \\(u32) pc = 56
679 \\(u32) lc = 4294967239
680 \\(lldb) thread backtrace --count 2
681 \\* thread #1, name = 'inline_call', stop reason = breakpoint 3.1
682 \\ * frame #0: inline_call`module.fc(pc=56) at module.zig:3:5
683 \\ frame #1: inline_call`main.main at main.zig:5:14
684 \\(lldb) breakpoint delete --force 3
685 \\1 breakpoints deleted; 0 breakpoint locations disabled.
686 ,
687 \\(lldb) frame variable pd ld
688 \\(u32) pd = 78
689 \\(u32) ld = 4294967217
690 \\(lldb) thread backtrace --count 2
691 \\* thread #1, name = 'inline_call', stop reason = breakpoint 4.1
692 \\ * frame #0: inline_call`main.main [inlined] fd(pd=78) at module.zig:7:5
693 \\ frame #1: inline_call`main.main at main.zig:6:14
694 \\(lldb) breakpoint delete --force 4
695 \\1 breakpoints deleted; 0 breakpoint locations disabled.
636 },696 },
637 );697 );
638}698}