authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2024-02-19 23:04:13+01:00
committergravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2024-02-21 16:24:59+01:00
log049cad44113ad8851be95f691188402456551e3a
treefaea327b743ae0566cf1acb245e98e1af4036d77
parenta456631e2940ba53dc0e450bc4748cad9071f019

LLVM Builder: Add debug locations to instructions


1 files changed, 90 insertions(+), 14 deletions(-)

src/codegen/llvm/Builder.zig+90-14
...@@ -3935,6 +3935,8 @@ pub const Function = struct {...@@ -3935,6 +3935,8 @@ pub const Function = struct {
3935 names: [*]const String = &[0]String{},3935 names: [*]const String = &[0]String{},
3936 value_indices: [*]const u32 = &[0]u32{},3936 value_indices: [*]const u32 = &[0]u32{},
3937 metadata: ?[*]const Metadata = null,3937 metadata: ?[*]const Metadata = null,
3938 debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, ?DebugLocation) = .{},
3939 debug_values: []const Instruction.Index = &.{},
3938 extra: []const u32 = &.{},3940 extra: []const u32 = &.{},
39393941
3940 pub const Index = enum(u32) {3942 pub const Index = enum(u32) {
...@@ -5031,7 +5033,8 @@ pub const Function = struct {...@@ -5031,7 +5033,8 @@ pub const Function = struct {
50315033
5032 pub fn deinit(self: *Function, gpa: Allocator) void {5034 pub fn deinit(self: *Function, gpa: Allocator) void {
5033 gpa.free(self.extra);5035 gpa.free(self.extra);
5034 if (self.metadata) |metadata| gpa.free(metadata[0..self.instructions.len]);5036 gpa.free(self.debug_values);
5037 self.debug_locations.deinit(gpa);
5035 gpa.free(self.value_indices[0..self.instructions.len]);5038 gpa.free(self.value_indices[0..self.instructions.len]);
5036 gpa.free(self.names[0..self.instructions.len]);5039 gpa.free(self.names[0..self.instructions.len]);
5037 self.instructions.deinit(gpa);5040 self.instructions.deinit(gpa);
...@@ -5103,6 +5106,13 @@ pub const Function = struct {...@@ -5103,6 +5106,13 @@ pub const Function = struct {
5103 }5106 }
5104};5107};
51055108
5109pub const DebugLocation = struct {
5110 line: u32,
5111 column: u32,
5112 scope: Metadata,
5113 inlined_at: Metadata,
5114};
5115
5106pub const WipFunction = struct {5116pub const WipFunction = struct {
5107 builder: *Builder,5117 builder: *Builder,
5108 function: Function.Index,5118 function: Function.Index,
...@@ -5111,11 +5121,14 @@ pub const WipFunction = struct {...@@ -5111,11 +5121,14 @@ pub const WipFunction = struct {
5111 blocks: std.ArrayListUnmanaged(*llvm.BasicBlock),5121 blocks: std.ArrayListUnmanaged(*llvm.BasicBlock),
5112 instructions: std.ArrayListUnmanaged(*llvm.Value),5122 instructions: std.ArrayListUnmanaged(*llvm.Value),
5113 } else void,5123 } else void,
5124 last_debug_location: ?DebugLocation,
5125 current_debug_location: ?DebugLocation,
5114 cursor: Cursor,5126 cursor: Cursor,
5115 blocks: std.ArrayListUnmanaged(Block),5127 blocks: std.ArrayListUnmanaged(Block),
5116 instructions: std.MultiArrayList(Instruction),5128 instructions: std.MultiArrayList(Instruction),
5117 names: std.ArrayListUnmanaged(String),5129 names: std.ArrayListUnmanaged(String),
5118 metadata: std.ArrayListUnmanaged(Metadata),5130 debug_locations: std.AutoArrayHashMapUnmanaged(Instruction.Index, ?DebugLocation),
5131 debug_values: std.AutoArrayHashMapUnmanaged(Instruction.Index, void),
5119 extra: std.ArrayListUnmanaged(u32),5132 extra: std.ArrayListUnmanaged(u32),
51205133
5121 pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 };5134 pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 };
...@@ -5169,20 +5182,27 @@ pub const WipFunction = struct {...@@ -5169,20 +5182,27 @@ pub const WipFunction = struct {
5169 .blocks = .{},5182 .blocks = .{},
5170 .instructions = .{},5183 .instructions = .{},
5171 .names = .{},5184 .names = .{},
5172 .metadata = .{},5185 .debug_locations = .{},
5186 .debug_values = .{},
5173 .extra = .{},5187 .extra = .{},
5188 .current_debug_location = null,
5189 .last_debug_location = null,
5174 };5190 };
5175 errdefer self.deinit();5191 errdefer self.deinit();
51765192
5177 const params_len = function.typeOf(self.builder).functionParameters(self.builder).len;5193 const params_len = function.typeOf(self.builder).functionParameters(self.builder).len;
5178 try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0);5194 try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0);
5179 try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);5195 try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);
5180 if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, params_len);5196 if (!self.builder.strip) {
5197 try self.names.ensureUnusedCapacity(self.builder.gpa, params_len);
5198 }
5181 if (self.builder.useLibLlvm())5199 if (self.builder.useLibLlvm())
5182 try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);5200 try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);
5183 for (0..params_len) |param_index| {5201 for (0..params_len) |param_index| {
5184 self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) });5202 self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) });
5185 if (!self.builder.strip) self.names.appendAssumeCapacity(.empty); // TODO: param names5203 if (!self.builder.strip) {
5204 self.names.appendAssumeCapacity(.empty); // TODO: param names
5205 }
5186 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(5206 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5187 function.toLlvm(self.builder).getParam(@intCast(param_index)),5207 function.toLlvm(self.builder).getParam(@intCast(param_index)),
5188 );5208 );
...@@ -6395,6 +6415,22 @@ pub const WipFunction = struct {...@@ -6395,6 +6415,22 @@ pub const WipFunction = struct {
6395 return instruction.toValue();6415 return instruction.toValue();
6396 }6416 }
63976417
6418 pub fn debugValue(self: *WipFunction, value: Value) Allocator.Error!Metadata {
6419 if (self.builder.strip) return .none;
6420 return switch (value.unwrap()) {
6421 .instruction => |instr_index| blk: {
6422 const gop = try self.debug_values.getOrPut(self.builder.gpa, instr_index);
6423
6424 const metadata: Metadata = @enumFromInt(Metadata.first_local_metadata + gop.index);
6425 if (!gop.found_existing) gop.key_ptr.* = instr_index;
6426
6427 break :blk metadata;
6428 },
6429 .constant => |constant| try self.builder.debugConstant(constant),
6430 .metadata => |metadata| metadata,
6431 };
6432 }
6433
6398 pub fn finish(self: *WipFunction) Allocator.Error!void {6434 pub fn finish(self: *WipFunction) Allocator.Error!void {
6399 const gpa = self.builder.gpa;6435 const gpa = self.builder.gpa;
6400 const function = self.function.ptr(self.builder);6436 const function = self.function.ptr(self.builder);
...@@ -6426,9 +6462,12 @@ pub const WipFunction = struct {...@@ -6426,9 +6462,12 @@ pub const WipFunction = struct {
6426 const value_indices = try gpa.alloc(u32, final_instructions_len);6462 const value_indices = try gpa.alloc(u32, final_instructions_len);
6427 errdefer gpa.free(value_indices);6463 errdefer gpa.free(value_indices);
64286464
6429 const metadata =6465 var debug_locations = std.AutoHashMapUnmanaged(Instruction.Index, ?DebugLocation){};
6430 if (self.builder.strip) null else try gpa.alloc(Metadata, final_instructions_len);6466 errdefer debug_locations.deinit(gpa);
6431 errdefer if (metadata) |new_metadata| gpa.free(new_metadata);6467 try debug_locations.ensureUnusedCapacity(gpa, @intCast(self.debug_locations.count()));
6468
6469 const debug_values = try gpa.alloc(Instruction.Index, self.debug_values.count());
6470 errdefer gpa.free(debug_values);
64326471
6433 var wip_extra: struct {6472 var wip_extra: struct {
6434 index: Instruction.ExtraIndex = 0,6473 index: Instruction.ExtraIndex = 0,
...@@ -6482,8 +6521,10 @@ pub const WipFunction = struct {...@@ -6482,8 +6521,10 @@ pub const WipFunction = struct {
6482 gpa.free(function.blocks);6521 gpa.free(function.blocks);
6483 function.blocks = &.{};6522 function.blocks = &.{};
6484 gpa.free(function.names[0..function.instructions.len]);6523 gpa.free(function.names[0..function.instructions.len]);
6485 if (function.metadata) |old_metadata| gpa.free(old_metadata[0..function.instructions.len]);6524 function.debug_locations.deinit(gpa);
6486 function.metadata = null;6525 function.debug_locations = .{};
6526 gpa.free(function.debug_values);
6527 function.debug_values = &.{};
6487 gpa.free(function.extra);6528 gpa.free(function.extra);
6488 function.extra = &.{};6529 function.extra = &.{};
64896530
...@@ -6532,6 +6573,12 @@ pub const WipFunction = struct {...@@ -6532,6 +6573,12 @@ pub const WipFunction = struct {
6532 names[@intFromEnum(new_argument_index)] = wip_name.map(6573 names[@intFromEnum(new_argument_index)] = wip_name.map(
6533 if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)],6574 if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)],
6534 );6575 );
6576 if (self.debug_locations.get(old_argument_index)) |location| {
6577 debug_locations.putAssumeCapacity(new_argument_index, location);
6578 }
6579 if (self.debug_values.getIndex(old_argument_index)) |index| {
6580 debug_values[index] = new_argument_index;
6581 }
6535 }6582 }
6536 for (self.blocks.items) |current_block| {6583 for (self.blocks.items) |current_block| {
6537 const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len);6584 const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len);
...@@ -6846,6 +6893,14 @@ pub const WipFunction = struct {...@@ -6846,6 +6893,14 @@ pub const WipFunction = struct {
6846 else6893 else
6847 self.names.items[@intFromEnum(old_instruction_index)]);6894 self.names.items[@intFromEnum(old_instruction_index)]);
68486895
6896 if (self.debug_locations.get(old_instruction_index)) |location| {
6897 debug_locations.putAssumeCapacity(new_instruction_index, location);
6898 }
6899
6900 if (self.debug_values.getIndex(old_instruction_index)) |index| {
6901 debug_values[index] = new_instruction_index;
6902 }
6903
6849 value_indices[@intFromEnum(new_instruction_index)] = value_index;6904 value_indices[@intFromEnum(new_instruction_index)] = value_index;
6850 if (old_instruction_index.hasResultWip(self)) value_index += 1;6905 if (old_instruction_index.hasResultWip(self)) value_index += 1;
6851 }6906 }
...@@ -6856,12 +6911,14 @@ pub const WipFunction = struct {...@@ -6856,12 +6911,14 @@ pub const WipFunction = struct {
6856 function.blocks = blocks;6911 function.blocks = blocks;
6857 function.names = names.ptr;6912 function.names = names.ptr;
6858 function.value_indices = value_indices.ptr;6913 function.value_indices = value_indices.ptr;
6859 function.metadata = if (metadata) |new_metadata| new_metadata.ptr else null;6914 function.debug_locations = debug_locations;
6915 function.debug_values = debug_values;
6860 }6916 }
68616917
6862 pub fn deinit(self: *WipFunction) void {6918 pub fn deinit(self: *WipFunction) void {
6863 self.extra.deinit(self.builder.gpa);6919 self.extra.deinit(self.builder.gpa);
6864 self.metadata.deinit(self.builder.gpa);6920 self.debug_values.deinit(self.builder.gpa);
6921 self.debug_locations.deinit(self.builder.gpa);
6865 self.names.deinit(self.builder.gpa);6922 self.names.deinit(self.builder.gpa);
6866 self.instructions.deinit(self.builder.gpa);6923 self.instructions.deinit(self.builder.gpa);
6867 for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa);6924 for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa);
...@@ -7137,7 +7194,16 @@ pub const WipFunction = struct {...@@ -7137,7 +7194,16 @@ pub const WipFunction = struct {
7137 ) Allocator.Error!Instruction.Index {7194 ) Allocator.Error!Instruction.Index {
7138 const block_instructions = &self.cursor.block.ptr(self).instructions;7195 const block_instructions = &self.cursor.block.ptr(self).instructions;
7139 try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1);7196 try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
7140 if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, 1);7197 if (!self.builder.strip) {
7198 try self.names.ensureUnusedCapacity(self.builder.gpa, 1);
7199 if (!std.mem.eql(
7200 u8,
7201 std.mem.asBytes(&self.current_debug_location),
7202 std.mem.asBytes(&self.last_debug_location),
7203 )) {
7204 try self.debug_locations.ensureUnusedCapacity(self.builder.gpa, 1);
7205 }
7206 }
7141 try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1);7207 try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1);
7142 if (self.builder.useLibLlvm())7208 if (self.builder.useLibLlvm())
7143 try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, 1);7209 try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
...@@ -7158,7 +7224,17 @@ pub const WipFunction = struct {...@@ -7158,7 +7224,17 @@ pub const WipFunction = struct {
71587224
7159 const index: Instruction.Index = @enumFromInt(self.instructions.len);7225 const index: Instruction.Index = @enumFromInt(self.instructions.len);
7160 self.instructions.appendAssumeCapacity(instruction);7226 self.instructions.appendAssumeCapacity(instruction);
7161 if (!self.builder.strip) self.names.appendAssumeCapacity(final_name);7227 if (!self.builder.strip) {
7228 self.names.appendAssumeCapacity(final_name);
7229 if (!std.mem.eql(
7230 u8,
7231 std.mem.asBytes(&self.current_debug_location),
7232 std.mem.asBytes(&self.last_debug_location),
7233 )) {
7234 self.debug_locations.putAssumeCapacity(index, self.current_debug_location);
7235 self.last_debug_location = self.current_debug_location;
7236 }
7237 }
7162 block_instructions.insertAssumeCapacity(self.cursor.instruction, index);7238 block_instructions.insertAssumeCapacity(self.cursor.instruction, index);
7163 self.cursor.instruction += 1;7239 self.cursor.instruction += 1;
7164 return index;7240 return index;