@@ -3797,7 +3797,7 @@ pub const Function = struct {
instructions: std.MultiArrayList(Instruction) = .{},
names: [*]const String = &[0]String{},
value_indices: [*]const u32 = &[0]u32{},
debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, Metadata) = .{},
debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, DebugLocation) = .{},
debug_values: []const Instruction.Index = &.{},
extra: []const u32 = &.{},
@@ -4857,16 +4857,40 @@ pub const Function = struct {
}
};
pub const DebugLocation = union(enum) {
no_location: void,
location: Location,
pub const Location = struct {
line: u32,
column: u32,
scope: Builder.Metadata,
inlined_at: Builder.Metadata,
};
pub fn toMetadata(self: DebugLocation, builder: *Builder) Allocator.Error!Metadata {
return switch (self) {
.no_location => .none,
.location => |location| try builder.debugLocation(
location.line,
location.column,
location.scope,
location.inlined_at,
),
};
}
};
pub const WipFunction = struct {
builder: *Builder,
function: Function.Index,
last_debug_location: Metadata,
current_debug_location: Metadata,
prev_debug_location: DebugLocation,
debug_location: DebugLocation,
cursor: Cursor,
blocks: std.ArrayListUnmanaged(Block),
instructions: std.MultiArrayList(Instruction),
names: std.ArrayListUnmanaged(String),
debug_locations: std.AutoArrayHashMapUnmanaged(Instruction.Index, Metadata),
debug_locations: std.AutoArrayHashMapUnmanaged(Instruction.Index, DebugLocation),
debug_values: std.AutoArrayHashMapUnmanaged(Instruction.Index, void),
extra: std.ArrayListUnmanaged(u32),
@@ -4902,8 +4926,8 @@ pub const WipFunction = struct {
var self: WipFunction = .{
.builder = builder,
.function = function,
.last_debug_location = .none,
.current_debug_location = .none,
.prev_debug_location = .no_location,
.debug_location = .no_location,
.cursor = undefined,
.blocks = .{},
.instructions = .{},
@@ -5850,7 +5874,7 @@ pub const WipFunction = struct {
const value_indices = try gpa.alloc(u32, final_instructions_len);
errdefer gpa.free(value_indices);
var debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, Metadata) = .{};
var debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, DebugLocation) = .{};
errdefer debug_locations.deinit(gpa);
try debug_locations.ensureUnusedCapacity(gpa, @intCast(self.debug_locations.count()));
@@ -6494,10 +6518,10 @@ pub const WipFunction = struct {
if (!self.builder.strip) {
self.names.appendAssumeCapacity(final_name);
if (block_instructions.items.len == 0 or
self.current_debug_location != self.last_debug_location)
!std.meta.eql(self.debug_location, self.prev_debug_location))
{
self.debug_locations.putAssumeCapacity(index, self.current_debug_location);
self.last_debug_location = self.current_debug_location;
self.debug_locations.putAssumeCapacity(index, self.debug_location);
self.prev_debug_location = self.debug_location;
}
}
block_instructions.insertAssumeCapacity(self.cursor.instruction, index);
@@ -8002,7 +8026,10 @@ pub const Metadata = enum(u32) {
const Formatter = struct {
builder: *Builder,
need_comma: bool,
map: std.AutoArrayHashMapUnmanaged(Metadata, void) = .{},
map: std.AutoArrayHashMapUnmanaged(union(enum) {
metadata: Metadata,
debug_location: DebugLocation.Location,
}, void) = .{},
const FormatData = struct {
formatter: *Formatter,
@@ -8190,7 +8217,7 @@ pub const Metadata = enum(u32) {
.expression, .constant => return .{ .@"inline" = unwrapped_metadata },
else => {
assert(!tag.isInline());
const gop = try formatter.map.getOrPutValue(builder.gpa, unwrapped_metadata, {});
const gop = try formatter.map.getOrPut(builder.gpa, .{ .metadata = unwrapped_metadata });
return .{ .index = @intCast(gop.index) };
},
}
@@ -9409,12 +9436,19 @@ pub fn printUnbuffered(
if (function.instructions.len > 0) {
var block_incoming_len: u32 = undefined;
try writer.writeAll(" {\n");
var dbg: Metadata = .none;
var maybe_dbg_index: ?u32 = null;
for (params_len..function.instructions.len) |instruction_i| {
const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
const instruction = function.instructions.get(@intFromEnum(instruction_index));
if (function.debug_locations.get(instruction_index)) |debug_location|
dbg = debug_location;
if (function.debug_locations.get(instruction_index)) |debug_location| switch (debug_location) {
.no_location => maybe_dbg_index = null,
.location => |location| {
const gop = try metadata_formatter.map.getOrPut(self.gpa, .{
.debug_location = location,
});
maybe_dbg_index = @intCast(gop.index);
},
};
switch (instruction.tag) {
.add,
.@"add nsw",
@@ -9846,9 +9880,10 @@ pub fn printUnbuffered(
});
},
}
metadata_formatter.need_comma = true;
defer metadata_formatter.need_comma = undefined;
try writer.print("{}\n", .{try metadata_formatter.fmt("!dbg ", dbg)});
if (maybe_dbg_index) |dbg_index| {
try writer.print(", !dbg !{}\n", .{dbg_index});
} else try writer.writeByte('\n');
}
try writer.writeByte('}');
}
@@ -9884,11 +9919,25 @@ pub fn printUnbuffered(
var metadata_index: usize = 0;
while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {
@setEvalBranchQuota(10_000);
const metadata_item =
self.metadata_items.get(@intFromEnum(metadata_formatter.map.keys()[metadata_index]));
try writer.print("!{} = ", .{metadata_index});
metadata_formatter.need_comma = false;
defer metadata_formatter.need_comma = undefined;
const key = metadata_formatter.map.keys()[metadata_index];
const metadata_item = switch (key) {
.debug_location => |location| {
try metadata_formatter.specialized(.@"!", .DILocation, .{
.line = location.line,
.column = location.column,
.scope = location.scope,
.inlinedAt = location.inlined_at,
.isImplicitCode = false,
}, writer);
continue;
},
.metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),
};
switch (metadata_item.tag) {
.none, .expression, .constant => unreachable,
.file => {
@@ -14866,20 +14915,18 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
if (!self.strip) {
if (func.debug_locations.get(@enumFromInt(instr_index))) |debug_location| {
if (debug_location != .none) {
const location = self.metadata_items.get(@intFromEnum(debug_location));
assert(location.tag == .location);
const extra = self.metadataExtraData(Metadata.Location, location.data);
try function_block.writeAbbrev(FunctionBlock.DebugLoc{
.line = extra.line,
.column = extra.column,
.scope = @enumFromInt(metadata_adapter.getMetadataIndex(extra.scope)),
.inlined_at = @enumFromInt(metadata_adapter.getMetadataIndex(extra.inlined_at)),
.is_implicit = false,
});
has_location = true;
} else {
has_location = false;
switch (debug_location) {
.no_location => has_location = false,
.location => |location| {
try function_block.writeAbbrev(FunctionBlock.DebugLoc{
.line = location.line,
.column = location.column,
.scope = @enumFromInt(metadata_adapter.getMetadataIndex(location.scope)),
.inlined_at = @enumFromInt(metadata_adapter.getMetadataIndex(location.inlined_at)),
.is_implicit = false,
});
has_location = true;
},
}
} else if (has_location) {
try function_block.writeAbbrev(FunctionBlock.DebugLocAgain{});