Commit 4e64373fc0

Veikka Tuominen <git@vexu.eu>
2022-12-30 13:28:04
fix generic function arg debug info referencing wrong parameter
Closes #14123
1 parent 4b5fc52
src/arch/aarch64/CodeGen.zig
@@ -4158,7 +4158,8 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
 
     const ty = self.air.typeOfIndex(inst);
     const result = self.args[arg_index];
-    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);
+    const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
+    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
 
     const mcv = switch (result) {
         // Copy registers to the stack
src/arch/arm/CodeGen.zig
@@ -4037,8 +4037,9 @@ fn genInlineMemsetCode(
 
 fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void {
     const mcv = self.args[arg_index];
-    const ty = self.air.instructions.items(.data)[inst].ty;
-    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);
+    const arg = self.air.instructions.items(.data)[inst].arg;
+    const ty = self.air.getRefType(arg.ty);
+    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
 
     switch (self.debug_output) {
         .dwarf => |dw| {
src/arch/riscv64/CodeGen.zig
@@ -1608,9 +1608,10 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
     return self.fail("TODO implement codegen airFieldParentPtr", .{});
 }
 
-fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void {
-    const ty = self.air.instructions.items(.data)[inst].ty;
-    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);
+fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
+    const arg = self.air.instructions.items(.data)[inst].arg;
+    const ty = self.air.getRefType(arg.ty);
+    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
 
     switch (self.debug_output) {
         .dwarf => |dw| switch (mcv) {
@@ -1640,7 +1641,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
     // TODO support stack-only arguments
     // TODO Copy registers to the stack
     const mcv = result;
-    try self.genArgDbgInfo(inst, mcv, @intCast(u32, arg_index));
+    try self.genArgDbgInfo(inst, mcv);
 
     if (self.liveness.isUnused(inst))
         return self.finishAirBookkeeping();
src/arch/sparc64/CodeGen.zig
@@ -1016,7 +1016,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
         }
     };
 
-    try self.genArgDbgInfo(inst, mcv, @intCast(u32, arg_index));
+    try self.genArgDbgInfo(inst, mcv);
 
     if (self.liveness.isUnused(inst))
         return self.finishAirBookkeeping();
@@ -3407,9 +3407,10 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
     self.finishAirBookkeeping();
 }
 
-fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void {
-    const ty = self.air.instructions.items(.data)[inst].ty;
-    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);
+fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
+    const arg = self.air.instructions.items(.data)[inst].arg;
+    const ty = self.air.getRefType(arg.ty);
+    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
 
     switch (self.debug_output) {
         .dwarf => |dw| switch (mcv) {
src/arch/wasm/CodeGen.zig
@@ -2474,8 +2474,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
 
     switch (func.debug_output) {
         .dwarf => |dwarf| {
-            // TODO: Get the original arg index rather than wasm arg index
-            const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, arg_index);
+            const src_index = func.air.instructions.items(.data)[inst].arg.src_index;
+            const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, src_index);
             try dwarf.genArgDbgInfo(name, arg_ty, .wasm, func.mod_fn.owner_decl, .{
                 .wasm_local = arg.local.value,
             });
src/arch/x86_64/CodeGen.zig
@@ -3799,7 +3799,8 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
 
     const ty = self.air.typeOfIndex(inst);
     const mcv = self.args[arg_index];
-    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);
+    const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
+    const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
 
     if (self.liveness.isUnused(inst))
         return self.finishAirBookkeeping();
src/codegen/llvm.zig
@@ -8062,7 +8062,7 @@ pub const FuncGen = struct {
                 return arg_val;
             }
 
-            const src_index = self.getSrcArgIndex(self.arg_index - 1);
+            const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
             const func = self.dg.decl.getFunction().?;
             const lbrace_line = self.dg.module.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
             const lbrace_col = func.lbrace_column + 1;
@@ -8095,16 +8095,6 @@ pub const FuncGen = struct {
         return arg_val;
     }
 
-    fn getSrcArgIndex(self: *FuncGen, runtime_index: u32) u32 {
-        const fn_info = self.dg.decl.ty.fnInfo();
-        var i: u32 = 0;
-        for (fn_info.param_types) |param_ty, src_index| {
-            if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
-            if (i == runtime_index) return @intCast(u32, src_index);
-            i += 1;
-        } else unreachable;
-    }
-
     fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
         if (self.liveness.isUnused(inst)) return null;
         const ptr_ty = self.air.typeOfIndex(inst);
src/link/SpirV.zig
@@ -314,7 +314,7 @@ fn cloneAir(air: Air, gpa: Allocator, air_arena: Allocator) !Air {
 
     for (air_tags) |tag, i| {
         switch (tag) {
-            .arg, .alloc, .ret_ptr, .const_ty => air_datas[i].ty = try air_datas[i].ty.copy(air_arena),
+            .alloc, .ret_ptr, .const_ty => air_datas[i].ty = try air_datas[i].ty.copy(air_arena),
             else => {},
         }
     }
src/Air.zig
@@ -31,7 +31,7 @@ pub const Inst = struct {
         /// The first N instructions in the main block must be one arg instruction per
         /// function parameter. This makes function parameters participate in
         /// liveness analysis without any special handling.
-        /// Uses the `ty` field.
+        /// Uses the `arg` field.
         arg,
         /// Float or integer addition. For integers, wrapping is undefined behavior.
         /// Both operands are guaranteed to be the same type, and the result type
@@ -795,6 +795,10 @@ pub const Inst = struct {
             rhs: Ref,
         },
         ty: Type,
+        arg: struct {
+            ty: Ref,
+            src_index: u32,
+        },
         ty_op: struct {
             ty: Ref,
             operand: Ref,
@@ -1103,11 +1107,12 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
 
         .alloc,
         .ret_ptr,
-        .arg,
         .err_return_trace,
         .c_va_start,
         => return datas[inst].ty,
 
+        .arg => return air.getRefType(datas[inst].arg.ty),
+
         .assembly,
         .block,
         .constant,
src/Module.zig
@@ -5672,11 +5672,15 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
             runtime_param_index += 1;
             continue;
         }
+        const air_ty = try sema.addType(param_ty);
         const arg_index = @intCast(u32, sema.air_instructions.len);
         inner_block.instructions.appendAssumeCapacity(arg_index);
         sema.air_instructions.appendAssumeCapacity(.{
             .tag = .arg,
-            .data = .{ .ty = param_ty },
+            .data = .{ .arg = .{
+                .ty = air_ty,
+                .src_index = @intCast(u32, total_param_index),
+            } },
         });
         sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
         total_param_index += 1;
src/print_air.zig
@@ -204,11 +204,12 @@ const Writer = struct {
             .const_ty,
             .alloc,
             .ret_ptr,
-            .arg,
             .err_return_trace,
             .c_va_start,
             => try w.writeTy(s, inst),
 
+            .arg => try w.writeArg(s, inst),
+
             .not,
             .bitcast,
             .load,
@@ -351,6 +352,12 @@ const Writer = struct {
         try w.writeType(s, ty);
     }
 
+    fn writeArg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
+        const arg = w.air.instructions.items(.data)[inst].arg;
+        try w.writeType(s, w.air.getRefType(arg.ty));
+        try s.print(", {d}", .{arg.src_index});
+    }
+
     fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
         const ty_op = w.air.instructions.items(.data)[inst].ty_op;
         try w.writeType(s, w.air.getRefType(ty_op.ty));
src/Sema.zig
@@ -476,13 +476,6 @@ pub const Block = struct {
         });
     }
 
-    fn addArg(block: *Block, ty: Type) error{OutOfMemory}!Air.Inst.Ref {
-        return block.addInst(.{
-            .tag = .arg,
-            .data = .{ .ty = ty },
-        });
-    }
-
     fn addStructFieldPtr(
         block: *Block,
         struct_ptr: Air.Inst.Ref,
@@ -7258,7 +7251,13 @@ fn instantiateGenericCall(
                 } else {
                     // We insert into the map an instruction which is runtime-known
                     // but has the type of the argument.
-                    const child_arg = try child_block.addArg(arg_ty);
+                    const child_arg = try child_block.addInst(.{
+                        .tag = .arg,
+                        .data = .{ .arg = .{
+                            .ty = try child_sema.addType(arg_ty),
+                            .src_index = @intCast(u32, arg_i),
+                        } },
+                    });
                     child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
                 }
             }