aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig9
-rw-r--r--src/AstGen.zig17
-rw-r--r--src/Liveness.zig2
-rw-r--r--src/Sema.zig37
-rw-r--r--src/arch/aarch64/CodeGen.zig12
-rw-r--r--src/arch/arm/CodeGen.zig12
-rw-r--r--src/arch/riscv64/CodeGen.zig12
-rw-r--r--src/arch/wasm/CodeGen.zig2
-rw-r--r--src/arch/x86_64/CodeGen.zig12
-rw-r--r--src/codegen/c.zig12
-rw-r--r--src/codegen/llvm.zig95
-rw-r--r--src/codegen/llvm/bindings.zig8
-rw-r--r--src/print_air.zig8
-rw-r--r--src/type.zig30
-rw-r--r--src/zig_llvm.cpp17
-rw-r--r--src/zig_llvm.h4
16 files changed, 277 insertions, 12 deletions
diff --git a/src/Air.zig b/src/Air.zig
index 7ccb6ebc96..45cae07f6a 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 84c6934acd..c714b69572 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 849b2c52c3..45558c6811 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 c8a1f6e343..ca341bfeac 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 9534e31a01..dddd4a27a1 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 5dda14a07d..0ccec1be88 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 e25848cd85..0b8cbc2d62 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 74af207a0a..33fb35163a 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 34facf4773..63c85a5a9e 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 05ceb30379..358e7354dd 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 c4b381f6d6..9321b26e15 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 c54d226f66..a6c53fddce 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 d70fdf5c24..7442d276c3 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 f7aae88df5..b3edc87585 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 6e3cccafeb..0b0b33b8d9 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<DIScope*>(scope);
+ DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, column, di_scope,
+ reinterpret_cast<DILocation *>(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<ZigLLVMDILocation*>(debug_loc.get());
}
+ZigLLVMDILocation *ZigLLVMGetDebugLoc2(unsigned line, unsigned col, ZigLLVMDIScope *scope,
+ ZigLLVMDILocation *inlined_at) {
+ DIScope* di_scope = reinterpret_cast<DIScope*>(scope);
+ DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, col, di_scope,
+ reinterpret_cast<DILocation *>(inlined_at), false);
+ return reinterpret_cast<ZigLLVMDILocation*>(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 5fe0142e76..761fca86be 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,