mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 08:33:06 +00:00
LLVM Builder: Add debug locations to instructions
This commit is contained in:
parent
a456631e29
commit
049cad4411
@ -3935,6 +3935,8 @@ pub const Function = struct {
|
||||
names: [*]const String = &[0]String{},
|
||||
value_indices: [*]const u32 = &[0]u32{},
|
||||
metadata: ?[*]const Metadata = null,
|
||||
debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, ?DebugLocation) = .{},
|
||||
debug_values: []const Instruction.Index = &.{},
|
||||
extra: []const u32 = &.{},
|
||||
|
||||
pub const Index = enum(u32) {
|
||||
@ -5031,7 +5033,8 @@ pub const Function = struct {
|
||||
|
||||
pub fn deinit(self: *Function, gpa: Allocator) void {
|
||||
gpa.free(self.extra);
|
||||
if (self.metadata) |metadata| gpa.free(metadata[0..self.instructions.len]);
|
||||
gpa.free(self.debug_values);
|
||||
self.debug_locations.deinit(gpa);
|
||||
gpa.free(self.value_indices[0..self.instructions.len]);
|
||||
gpa.free(self.names[0..self.instructions.len]);
|
||||
self.instructions.deinit(gpa);
|
||||
@ -5103,6 +5106,13 @@ pub const Function = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const DebugLocation = struct {
|
||||
line: u32,
|
||||
column: u32,
|
||||
scope: Metadata,
|
||||
inlined_at: Metadata,
|
||||
};
|
||||
|
||||
pub const WipFunction = struct {
|
||||
builder: *Builder,
|
||||
function: Function.Index,
|
||||
@ -5111,11 +5121,14 @@ pub const WipFunction = struct {
|
||||
blocks: std.ArrayListUnmanaged(*llvm.BasicBlock),
|
||||
instructions: std.ArrayListUnmanaged(*llvm.Value),
|
||||
} else void,
|
||||
last_debug_location: ?DebugLocation,
|
||||
current_debug_location: ?DebugLocation,
|
||||
cursor: Cursor,
|
||||
blocks: std.ArrayListUnmanaged(Block),
|
||||
instructions: std.MultiArrayList(Instruction),
|
||||
names: std.ArrayListUnmanaged(String),
|
||||
metadata: std.ArrayListUnmanaged(Metadata),
|
||||
debug_locations: std.AutoArrayHashMapUnmanaged(Instruction.Index, ?DebugLocation),
|
||||
debug_values: std.AutoArrayHashMapUnmanaged(Instruction.Index, void),
|
||||
extra: std.ArrayListUnmanaged(u32),
|
||||
|
||||
pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 };
|
||||
@ -5169,20 +5182,27 @@ pub const WipFunction = struct {
|
||||
.blocks = .{},
|
||||
.instructions = .{},
|
||||
.names = .{},
|
||||
.metadata = .{},
|
||||
.debug_locations = .{},
|
||||
.debug_values = .{},
|
||||
.extra = .{},
|
||||
.current_debug_location = null,
|
||||
.last_debug_location = null,
|
||||
};
|
||||
errdefer self.deinit();
|
||||
|
||||
const params_len = function.typeOf(self.builder).functionParameters(self.builder).len;
|
||||
try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0);
|
||||
try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);
|
||||
if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, params_len);
|
||||
if (!self.builder.strip) {
|
||||
try self.names.ensureUnusedCapacity(self.builder.gpa, params_len);
|
||||
}
|
||||
if (self.builder.useLibLlvm())
|
||||
try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);
|
||||
for (0..params_len) |param_index| {
|
||||
self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) });
|
||||
if (!self.builder.strip) self.names.appendAssumeCapacity(.empty); // TODO: param names
|
||||
if (!self.builder.strip) {
|
||||
self.names.appendAssumeCapacity(.empty); // TODO: param names
|
||||
}
|
||||
if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
|
||||
function.toLlvm(self.builder).getParam(@intCast(param_index)),
|
||||
);
|
||||
@ -6395,6 +6415,22 @@ pub const WipFunction = struct {
|
||||
return instruction.toValue();
|
||||
}
|
||||
|
||||
pub fn debugValue(self: *WipFunction, value: Value) Allocator.Error!Metadata {
|
||||
if (self.builder.strip) return .none;
|
||||
return switch (value.unwrap()) {
|
||||
.instruction => |instr_index| blk: {
|
||||
const gop = try self.debug_values.getOrPut(self.builder.gpa, instr_index);
|
||||
|
||||
const metadata: Metadata = @enumFromInt(Metadata.first_local_metadata + gop.index);
|
||||
if (!gop.found_existing) gop.key_ptr.* = instr_index;
|
||||
|
||||
break :blk metadata;
|
||||
},
|
||||
.constant => |constant| try self.builder.debugConstant(constant),
|
||||
.metadata => |metadata| metadata,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn finish(self: *WipFunction) Allocator.Error!void {
|
||||
const gpa = self.builder.gpa;
|
||||
const function = self.function.ptr(self.builder);
|
||||
@ -6426,9 +6462,12 @@ pub const WipFunction = struct {
|
||||
const value_indices = try gpa.alloc(u32, final_instructions_len);
|
||||
errdefer gpa.free(value_indices);
|
||||
|
||||
const metadata =
|
||||
if (self.builder.strip) null else try gpa.alloc(Metadata, final_instructions_len);
|
||||
errdefer if (metadata) |new_metadata| gpa.free(new_metadata);
|
||||
var debug_locations = std.AutoHashMapUnmanaged(Instruction.Index, ?DebugLocation){};
|
||||
errdefer debug_locations.deinit(gpa);
|
||||
try debug_locations.ensureUnusedCapacity(gpa, @intCast(self.debug_locations.count()));
|
||||
|
||||
const debug_values = try gpa.alloc(Instruction.Index, self.debug_values.count());
|
||||
errdefer gpa.free(debug_values);
|
||||
|
||||
var wip_extra: struct {
|
||||
index: Instruction.ExtraIndex = 0,
|
||||
@ -6482,8 +6521,10 @@ pub const WipFunction = struct {
|
||||
gpa.free(function.blocks);
|
||||
function.blocks = &.{};
|
||||
gpa.free(function.names[0..function.instructions.len]);
|
||||
if (function.metadata) |old_metadata| gpa.free(old_metadata[0..function.instructions.len]);
|
||||
function.metadata = null;
|
||||
function.debug_locations.deinit(gpa);
|
||||
function.debug_locations = .{};
|
||||
gpa.free(function.debug_values);
|
||||
function.debug_values = &.{};
|
||||
gpa.free(function.extra);
|
||||
function.extra = &.{};
|
||||
|
||||
@ -6532,6 +6573,12 @@ pub const WipFunction = struct {
|
||||
names[@intFromEnum(new_argument_index)] = wip_name.map(
|
||||
if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)],
|
||||
);
|
||||
if (self.debug_locations.get(old_argument_index)) |location| {
|
||||
debug_locations.putAssumeCapacity(new_argument_index, location);
|
||||
}
|
||||
if (self.debug_values.getIndex(old_argument_index)) |index| {
|
||||
debug_values[index] = new_argument_index;
|
||||
}
|
||||
}
|
||||
for (self.blocks.items) |current_block| {
|
||||
const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len);
|
||||
@ -6846,6 +6893,14 @@ pub const WipFunction = struct {
|
||||
else
|
||||
self.names.items[@intFromEnum(old_instruction_index)]);
|
||||
|
||||
if (self.debug_locations.get(old_instruction_index)) |location| {
|
||||
debug_locations.putAssumeCapacity(new_instruction_index, location);
|
||||
}
|
||||
|
||||
if (self.debug_values.getIndex(old_instruction_index)) |index| {
|
||||
debug_values[index] = new_instruction_index;
|
||||
}
|
||||
|
||||
value_indices[@intFromEnum(new_instruction_index)] = value_index;
|
||||
if (old_instruction_index.hasResultWip(self)) value_index += 1;
|
||||
}
|
||||
@ -6856,12 +6911,14 @@ pub const WipFunction = struct {
|
||||
function.blocks = blocks;
|
||||
function.names = names.ptr;
|
||||
function.value_indices = value_indices.ptr;
|
||||
function.metadata = if (metadata) |new_metadata| new_metadata.ptr else null;
|
||||
function.debug_locations = debug_locations;
|
||||
function.debug_values = debug_values;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *WipFunction) void {
|
||||
self.extra.deinit(self.builder.gpa);
|
||||
self.metadata.deinit(self.builder.gpa);
|
||||
self.debug_values.deinit(self.builder.gpa);
|
||||
self.debug_locations.deinit(self.builder.gpa);
|
||||
self.names.deinit(self.builder.gpa);
|
||||
self.instructions.deinit(self.builder.gpa);
|
||||
for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa);
|
||||
@ -7137,7 +7194,16 @@ pub const WipFunction = struct {
|
||||
) Allocator.Error!Instruction.Index {
|
||||
const block_instructions = &self.cursor.block.ptr(self).instructions;
|
||||
try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
|
||||
if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, 1);
|
||||
if (!self.builder.strip) {
|
||||
try self.names.ensureUnusedCapacity(self.builder.gpa, 1);
|
||||
if (!std.mem.eql(
|
||||
u8,
|
||||
std.mem.asBytes(&self.current_debug_location),
|
||||
std.mem.asBytes(&self.last_debug_location),
|
||||
)) {
|
||||
try self.debug_locations.ensureUnusedCapacity(self.builder.gpa, 1);
|
||||
}
|
||||
}
|
||||
try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1);
|
||||
if (self.builder.useLibLlvm())
|
||||
try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
|
||||
@ -7158,7 +7224,17 @@ pub const WipFunction = struct {
|
||||
|
||||
const index: Instruction.Index = @enumFromInt(self.instructions.len);
|
||||
self.instructions.appendAssumeCapacity(instruction);
|
||||
if (!self.builder.strip) self.names.appendAssumeCapacity(final_name);
|
||||
if (!self.builder.strip) {
|
||||
self.names.appendAssumeCapacity(final_name);
|
||||
if (!std.mem.eql(
|
||||
u8,
|
||||
std.mem.asBytes(&self.current_debug_location),
|
||||
std.mem.asBytes(&self.last_debug_location),
|
||||
)) {
|
||||
self.debug_locations.putAssumeCapacity(index, self.current_debug_location);
|
||||
self.last_debug_location = self.current_debug_location;
|
||||
}
|
||||
}
|
||||
block_instructions.insertAssumeCapacity(self.cursor.instruction, index);
|
||||
self.cursor.instruction += 1;
|
||||
return index;
|
||||
|
Loading…
Reference in New Issue
Block a user