diff --git a/src/Air.zig b/src/Air.zig index 7ccb6ebc9659..45cae07f6af5 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -7,7 +7,6 @@ const std = @import("std"); const builtin = @import("builtin"); const Value = @import("value.zig").Value; const Type = @import("type.zig").Type; -const Module = @import("Module.zig"); const assert = std.debug.assert; const Air = @This(); @@ -327,6 +326,12 @@ pub const Inst = struct { /// Result type is always void. /// Uses the `dbg_stmt` field. dbg_stmt, + /// Marks the start of an inline call. + /// Uses `ty_pl` with the payload being the index of a Value.Function in air.values. + dbg_inline_begin, + /// Marks the end of an inline call. + /// Uses `ty_pl` with the payload being the index of a Value.Function in air.values. + dbg_inline_end, /// Marks the beginning of a local variable. The operand is a pointer pointing /// to the storage for the variable. The local may be a const or a var. /// Result type is always void. @@ -971,6 +976,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { .breakpoint, .dbg_stmt, + .dbg_inline_begin, + .dbg_inline_end, .dbg_var_ptr, .dbg_var_val, .store, diff --git a/src/AstGen.zig b/src/AstGen.zig index 84c6934acd70..c714b695725c 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -5148,6 +5148,7 @@ fn ifExpr( else false; + try emitDbgNode(parent_gz, if_full.ast.cond_expr); const cond: struct { inst: Zir.Inst.Ref, bool_bit: Zir.Inst.Ref, @@ -5458,6 +5459,7 @@ fn whileExpr( else false; + try emitDbgNode(parent_gz, while_full.ast.cond_expr); const cond: struct { inst: Zir.Inst.Ref, bool_bit: Zir.Inst.Ref, @@ -5678,6 +5680,8 @@ fn forExpr( else false; + try emitDbgNode(parent_gz, for_full.ast.cond_expr); + const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; const array_ptr = try expr(parent_gz, scope, cond_rl, for_full.ast.cond_expr); const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr); @@ -7810,6 +7814,19 @@ fn callExpr( break :blk .auto; }; + { + astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]); + const line = astgen.source_line - gz.decl_line; + const column = astgen.source_column; + + _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{ + .dbg_stmt = .{ + .line = line, + .column = column, + }, + } }); + } + assert(callee != .none); assert(node != 0); diff --git a/src/Liveness.zig b/src/Liveness.zig index 849b2c52c312..45558c681108 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -314,6 +314,8 @@ fn analyzeInst( .const_ty, .breakpoint, .dbg_stmt, + .dbg_inline_begin, + .dbg_inline_end, .unreach, .fence, .ret_addr, diff --git a/src/Sema.zig b/src/Sema.zig index c8a1f6e3436d..ca341bfeac0e 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4639,6 +4639,10 @@ fn analyzeCall( // comptime state. var should_memoize = true; + var new_fn_info = module_fn.owner_decl.ty.fnInfo(); + new_fn_info.param_types = try sema.arena.alloc(Type, new_fn_info.param_types.len); + new_fn_info.comptime_params = (try sema.arena.alloc(bool, new_fn_info.param_types.len)).ptr; + // This will have return instructions analyzed as break instructions to // the block_inst above. Here we are performing "comptime/inline semantic analysis" // for a function body, which means we must map the parameter ZIR instructions to @@ -4658,6 +4662,7 @@ fn analyzeCall( const param_body = sema.code.extra[extra.end..][0..extra.data.body_len]; const param_ty_inst = try sema.resolveBody(&child_block, param_body, inst); const param_ty = try sema.analyzeAsType(&child_block, param_src, param_ty_inst); + new_fn_info.param_types[arg_i] = param_ty; const arg_src = call_src; // TODO: better source location const casted_arg = try sema.coerce(&child_block, param_ty, uncasted_args[arg_i], arg_src); try sema.inst_map.putNoClobber(gpa, inst, casted_arg); @@ -4685,6 +4690,7 @@ fn analyzeCall( .param_anytype, .param_anytype_comptime => { // No coercion needed. const uncasted_arg = uncasted_args[arg_i]; + new_fn_info.param_types[arg_i] = sema.typeOf(uncasted_arg); try sema.inst_map.putNoClobber(gpa, inst, uncasted_arg); if (is_comptime_call) { @@ -4735,6 +4741,7 @@ fn analyzeCall( } break :blk bare_return_type; }; + new_fn_info.return_type = fn_ret_ty; const parent_fn_ret_ty = sema.fn_ret_ty; sema.fn_ret_ty = fn_ret_ty; defer sema.fn_ret_ty = parent_fn_ret_ty; @@ -4757,6 +4764,11 @@ fn analyzeCall( } } + const new_func_resolved_ty = try Type.Tag.function.create(sema.arena, new_fn_info); + if (!is_comptime_call) { + try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin); + } + const result = result: { sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { error.ComptimeReturn => break :result inlining.comptime_result, @@ -4771,6 +4783,10 @@ fn analyzeCall( break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); }; + if (!is_comptime_call) { + try sema.emitDbgInline(block, module_fn, parent_func.?, parent_func.?.owner_decl.ty, .dbg_inline_end); + } + if (should_memoize and is_comptime_call) { const result_val = try sema.resolveConstMaybeUndefVal(block, call_src, result); @@ -5175,6 +5191,27 @@ fn instantiateGenericCall( return func_inst; } +fn emitDbgInline( + sema: *Sema, + block: *Block, + old_func: *Module.Fn, + new_func: *Module.Fn, + new_func_ty: Type, + tag: Air.Inst.Tag, +) CompileError!void { + // No change of file; no dbg_inline needed. + if (old_func == new_func) return; + + try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func)); + _ = try block.addInst(.{ + .tag = tag, + .data = .{ .ty_pl = .{ + .ty = try sema.addType(new_func_ty), + .payload = @intCast(u32, sema.air_values.items.len - 1), + } }, + }); +} + fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const tracy = trace(@src()); diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 9534e31a0199..dddd4a27a156 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -649,6 +649,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .dbg_var_val, => try self.airDbgVar(inst), + .dbg_inline_begin, + .dbg_inline_end, + => try self.airDbgInline(inst), + .call => try self.airCall(inst, .auto), .call_always_tail => try self.airCall(inst, .always_tail), .call_never_tail => try self.airCall(inst, .never_tail), @@ -2715,6 +2719,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { return self.finishAirBookkeeping(); } +fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const function = self.air.values[ty_pl.payload].castTag(.function).?.data; + // TODO emit debug info for function change + _ = function; + return self.finishAir(inst, .dead, .{ .none, .none, .none }); +} + fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const name = self.air.nullTerminatedString(pl_op.payload); diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 5dda14a07dea..0ccec1be8823 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -646,6 +646,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .dbg_var_val, => try self.airDbgVar(inst), + .dbg_inline_begin, + .dbg_inline_end, + => try self.airDbgInline(inst), + .call => try self.airCall(inst, .auto), .call_always_tail => try self.airCall(inst, .always_tail), .call_never_tail => try self.airCall(inst, .never_tail), @@ -2835,6 +2839,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { return self.finishAirBookkeeping(); } +fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const function = self.air.values[ty_pl.payload].castTag(.function).?.data; + // TODO emit debug info for function change + _ = function; + return self.finishAir(inst, .dead, .{ .none, .none, .none }); +} + fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const name = self.air.nullTerminatedString(pl_op.payload); diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index e25848cd8578..0b8cbc2d628a 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -613,6 +613,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .dbg_var_val, => try self.airDbgVar(inst), + .dbg_inline_begin, + .dbg_inline_end, + => try self.airDbgInline(inst), + .call => try self.airCall(inst, .auto), .call_always_tail => try self.airCall(inst, .always_tail), .call_never_tail => try self.airCall(inst, .never_tail), @@ -1640,6 +1644,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { return self.finishAirBookkeeping(); } +fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const function = self.air.values[ty_pl.payload].castTag(.function).?.data; + // TODO emit debug info for function change + _ = function; + return self.finishAir(inst, .dead, .{ .none, .none, .none }); +} + fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const name = self.air.nullTerminatedString(pl_op.payload); diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 74af207a0a6c..33fb35163a36 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1227,6 +1227,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { // TODO .dbg_stmt, + .dbg_inline_begin, + .dbg_inline_end, .dbg_var_ptr, .dbg_var_val, => WValue.none, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 34facf4773f5..63c85a5a9e6f 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -730,6 +730,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .dbg_var_val, => try self.airDbgVar(inst), + .dbg_inline_begin, + .dbg_inline_end, + => try self.airDbgInline(inst), + .call => try self.airCall(inst, .auto), .call_always_tail => try self.airCall(inst, .always_tail), .call_never_tail => try self.airCall(inst, .never_tail), @@ -3670,6 +3674,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { return self.finishAirBookkeeping(); } +fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const function = self.air.values[ty_pl.payload].castTag(.function).?.data; + // TODO emit debug info for function change + _ = function; + return self.finishAir(inst, .dead, .{ .none, .none, .none }); +} + fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const name = self.air.nullTerminatedString(pl_op.payload); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 05ceb3037914..358e7354ddf1 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1726,6 +1726,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .dbg_var_val, => try airDbgVar(f, inst), + .dbg_inline_begin, + .dbg_inline_end, + => try airDbgInline(f, inst), + .call => try airCall(f, inst, .auto), .call_always_tail => try airCall(f, inst, .always_tail), .call_never_tail => try airCall(f, inst, .never_tail), @@ -2660,6 +2664,14 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { return CValue.none; } +fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue { + const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; + const writer = f.object.writer(); + const function = f.air.values[ty_pl.payload].castTag(.function).?.data; + try writer.print("/* dbg func:{s} */\n", .{function.owner_decl.name}); + return CValue.none; +} + fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { const pl_op = f.air.instructions.items(.data)[inst].pl_op; const name = f.air.nullTerminatedString(pl_op.payload); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index c4b381f6d695..9321b26e157a 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -620,7 +620,8 @@ pub const Object = struct { llvm_func.fnSetSubprogram(subprogram); - di_scope = subprogram.toScope(); + const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file.?, line_number, 1); + di_scope = lexical_block.toScope(); } var fg: FuncGen = .{ @@ -639,6 +640,7 @@ pub const Object = struct { .single_threaded = module.comp.bin_file.options.single_threaded, .di_scope = di_scope, .di_file = di_file, + .base_line = dg.decl.src_line, .prev_dbg_line = 0, .prev_dbg_column = 0, }; @@ -1754,11 +1756,14 @@ pub const DeclGen = struct { /// Note that this can be called before the function's semantic analysis has /// completed, so if any attributes rely on that, they must be done in updateFunc, not here. fn resolveLlvmFunction(dg: *DeclGen, decl: *Module.Decl) !*const llvm.Value { + return dg.resolveLlvmFunctionExtra(decl, decl.ty); + } + + fn resolveLlvmFunctionExtra(dg: *DeclGen, decl: *Module.Decl, zig_fn_type: Type) !*const llvm.Value { const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl); if (gop.found_existing) return gop.value_ptr.*; assert(decl.has_tv); - const zig_fn_type = decl.ty; const fn_info = zig_fn_type.fnInfo(); const target = dg.module.getTarget(); const sret = firstParamSRet(fn_info, target); @@ -3207,9 +3212,13 @@ pub const FuncGen = struct { builder: *const llvm.Builder, di_scope: ?*llvm.DIScope, di_file: ?*llvm.DIFile, + base_line: u32, prev_dbg_line: c_uint, prev_dbg_column: c_uint, + /// Stack of locations where a call was inlined. + dbg_inlined: std.ArrayListUnmanaged(DbgState) = .{}, + /// This stores the LLVM values used in a function, such that they can be referred to /// in other instructions. This table is cleared before every function is generated. func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, *const llvm.Value), @@ -3237,11 +3246,13 @@ pub const FuncGen = struct { single_threaded: bool, + const DbgState = struct { loc: *llvm.DILocation, scope: *llvm.DIScope, base_line: u32 }; const BreakBasicBlocks = std.ArrayListUnmanaged(*const llvm.BasicBlock); const BreakValues = std.ArrayListUnmanaged(*const llvm.Value); fn deinit(self: *FuncGen) void { self.builder.dispose(); + self.dbg_inlined.deinit(self.gpa); self.func_inst_table.deinit(self.gpa); self.blocks.deinit(self.gpa); } @@ -3460,6 +3471,8 @@ pub const FuncGen = struct { .const_ty => unreachable, .unreach => self.airUnreach(inst), .dbg_stmt => self.airDbgStmt(inst), + .dbg_inline_begin => try self.airDbgInline(inst, true), + .dbg_inline_end => try self.airDbgInline(inst, false), .dbg_var_ptr => try self.airDbgVarPtr(inst), .dbg_var_val => try self.airDbgVarVal(inst), // zig fmt: on @@ -4175,9 +4188,69 @@ pub const FuncGen = struct { fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) ?*const llvm.Value { const di_scope = self.di_scope orelse return null; const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt; - self.prev_dbg_line = @intCast(c_uint, self.dg.decl.src_line + dbg_stmt.line + 1); + self.prev_dbg_line = @intCast(c_uint, self.base_line + dbg_stmt.line + 1); self.prev_dbg_column = @intCast(c_uint, dbg_stmt.column + 1); - self.builder.setCurrentDebugLocation(self.prev_dbg_line, self.prev_dbg_column, di_scope); + const inlined_at = if (self.dbg_inlined.items.len > 0) + self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc + else + null; + self.builder.setCurrentDebugLocation(self.prev_dbg_line, self.prev_dbg_column, di_scope, inlined_at); + return null; + } + + fn airDbgInline(self: *FuncGen, inst: Air.Inst.Index, start: bool) !?*const llvm.Value { + const dib = self.dg.object.di_builder orelse return null; + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + + const func = self.air.values[ty_pl.payload].castTag(.function).?.data; + const decl = func.owner_decl; + const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope); + self.di_file = di_file; + const line_number = decl.src_line + 1; + const cur_debug_location = self.builder.getCurrentDebugLocation2(); + if (start) { + try self.dbg_inlined.append(self.gpa, .{ + .loc = @ptrCast(*llvm.DILocation, cur_debug_location), + .scope = self.di_scope.?, + .base_line = self.base_line, + }); + } else { + const old = self.dbg_inlined.pop(); + self.di_scope = old.scope; + self.base_line = old.base_line; + return null; + } + + const fn_ty = try self.air.getRefType(ty_pl.ty).copy(self.dg.object.type_map_arena.allocator()); + const fqn = try decl.getFullyQualifiedName(self.gpa); + defer self.gpa.free(fqn); + const fn_info = fn_ty.fnInfo(); + + const is_internal_linkage = !self.dg.module.decl_exports.contains(decl); + const noret_bit: c_uint = if (fn_info.return_type.isNoReturn()) + llvm.DIFlags.NoReturn + else + 0; + const subprogram = dib.createFunction( + di_file.toScope(), + decl.name, + fqn, + di_file, + line_number, + try self.dg.object.lowerDebugType(fn_ty, .full), + is_internal_linkage, + true, // is definition + line_number + func.lbrace_line, // scope line + llvm.DIFlags.StaticMember | noret_bit, + self.dg.module.comp.bin_file.options.optimize_mode != .Debug, + null, // decl_subprogram + ); + + try self.dg.object.di_map.put(self.gpa, decl, subprogram.toNode()); + + const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file, line_number, 1); + self.di_scope = lexical_block.toScope(); + self.base_line = decl.src_line; return null; } @@ -4197,7 +4270,11 @@ pub const FuncGen = struct { true, // always preserve 0, // flags ); - const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?); + const inlined_at = if (self.dbg_inlined.items.len > 0) + self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc + else + null; + const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); const insert_block = self.builder.getInsertBlock(); _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); return null; @@ -4219,7 +4296,11 @@ pub const FuncGen = struct { true, // always preserve 0, // flags ); - const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?); + const inlined_at = if (self.dbg_inlined.items.len > 0) + self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc + else + null; + const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); const insert_block = self.builder.getInsertBlock(); if (isByRef(operand_ty)) { _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); @@ -5481,7 +5562,7 @@ pub const FuncGen = struct { self.arg_index, // includes +1 because 0 is return type ); - const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?); + const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null); const insert_block = self.builder.getInsertBlock(); if (isByRef(inst_ty)) { _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block); diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index c54d226f6689..a6c53fddce88 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -839,8 +839,8 @@ pub const Builder = opaque { pub const buildExactSDiv = LLVMBuildExactSDiv; extern fn LLVMBuildExactSDiv(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; - pub const setCurrentDebugLocation = ZigLLVMSetCurrentDebugLocation; - extern fn ZigLLVMSetCurrentDebugLocation(builder: *const Builder, line: c_uint, column: c_uint, scope: *DIScope) void; + pub const setCurrentDebugLocation = ZigLLVMSetCurrentDebugLocation2; + extern fn ZigLLVMSetCurrentDebugLocation2(builder: *const Builder, line: c_uint, column: c_uint, scope: *DIScope, inlined_at: ?*DILocation) void; pub const clearCurrentDebugLocation = ZigLLVMClearCurrentDebugLocation; extern fn ZigLLVMClearCurrentDebugLocation(builder: *const Builder) void; @@ -1479,8 +1479,8 @@ pub const DISubprogram = opaque { extern fn ZigLLVMSubprogramReplaceLinkageName(subprogram: *DISubprogram, linkage_name: *MDString) void; }; -pub const getDebugLoc = ZigLLVMGetDebugLoc; -extern fn ZigLLVMGetDebugLoc(line: c_uint, col: c_uint, scope: *DIScope) *DILocation; +pub const getDebugLoc = ZigLLVMGetDebugLoc2; +extern fn ZigLLVMGetDebugLoc2(line: c_uint, col: c_uint, scope: *DIScope, inlined_at: ?*DILocation) *DILocation; pub const DIBuilder = opaque { pub const dispose = ZigLLVMDisposeDIBuilder; diff --git a/src/print_air.zig b/src/print_air.zig index d70fdf5c24be..7442d276c383 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -242,6 +242,8 @@ const Writer = struct { .constant => try w.writeConstant(s, inst), .assembly => try w.writeAssembly(s, inst), .dbg_stmt => try w.writeDbgStmt(s, inst), + + .dbg_inline_begin, .dbg_inline_end => try w.writeDbgInline(s, inst), .aggregate_init => try w.writeAggregateInit(s, inst), .union_init => try w.writeUnionInit(s, inst), .br => try w.writeBr(s, inst), @@ -552,6 +554,12 @@ const Writer = struct { try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); } + fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { + const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; + const function = w.air.values[ty_pl.payload].castTag(.function).?.data; + try s.print("{s}", .{function.owner_decl.name}); + } + fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { const pl_op = w.air.instructions.items(.data)[inst].pl_op; try w.writeOperand(s, inst, 0, pl_op.operand); diff --git a/src/type.zig b/src/type.zig index ffa43d32c0aa..7b45b89816cb 100644 --- a/src/type.zig +++ b/src/type.zig @@ -486,6 +486,36 @@ pub const Type = extern union { .pointer => return self.castTag(.pointer).?.*, + .optional_single_mut_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = true, + .@"volatile" = false, + .size = .One, + } }, + .optional_single_const_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .One, + } }, + .optional => { + var buf: Payload.ElemType = undefined; + const child_type = self.optionalChild(&buf); + return child_type.ptrInfo(); + }, + else => unreachable, } } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 6e3cccafeb2b..0b0b33b8d9db 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -799,6 +799,15 @@ void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, unwrap(builder)->SetCurrentDebugLocation(debug_loc); } +void ZigLLVMSetCurrentDebugLocation2(LLVMBuilderRef builder, unsigned int line, + unsigned int column, ZigLLVMDIScope *scope, ZigLLVMDILocation *inlined_at) +{ + DIScope* di_scope = reinterpret_cast(scope); + DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, column, di_scope, + reinterpret_cast(inlined_at), false); + unwrap(builder)->SetCurrentDebugLocation(debug_loc); +} + void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder) { unwrap(builder)->SetCurrentDebugLocation(DebugLoc()); } @@ -1025,6 +1034,14 @@ ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, ZigLLVMDIScop return reinterpret_cast(debug_loc.get()); } +ZigLLVMDILocation *ZigLLVMGetDebugLoc2(unsigned line, unsigned col, ZigLLVMDIScope *scope, + ZigLLVMDILocation *inlined_at) { + DIScope* di_scope = reinterpret_cast(scope); + DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, col, di_scope, + reinterpret_cast(inlined_at), false); + return reinterpret_cast(debug_loc.get()); +} + void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) { if (on_state) { FastMathFlags fmf; diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 5fe0142e7672..761fca86bee9 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -232,6 +232,8 @@ ZIG_EXTERN_C void ZigLLVMSetModuleCodeModel(LLVMModuleRef module, LLVMCodeModel ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, unsigned int line, unsigned int column, struct ZigLLVMDIScope *scope); +ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation2(LLVMBuilderRef builder, unsigned int line, + unsigned int column, ZigLLVMDIScope *scope, ZigLLVMDILocation *inlined_at); ZIG_EXTERN_C void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder); ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMLexicalBlockToScope(struct ZigLLVMDILexicalBlock *lexical_block); @@ -290,6 +292,8 @@ ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder); ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, struct ZigLLVMDIScope *scope); +ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc2(unsigned line, unsigned col, + ZigLLVMDIScope *scope, ZigLLVMDILocation *inlined_at); ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclareAtEnd(struct ZigLLVMDIBuilder *dib, LLVMValueRef storage, struct ZigLLVMDILocalVariable *var_info,