| ... | ... | @@ -3935,6 +3935,8 @@ pub const Function = struct { |
| 3935 | 3935 | names: [*]const String = &[0]String{}, |
| 3936 | 3936 | value_indices: [*]const u32 = &[0]u32{}, |
| 3937 | 3937 | metadata: ?[*]const Metadata = null, |
| 3938 | debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, ?DebugLocation) = .{}, |
| 3939 | debug_values: []const Instruction.Index = &.{}, |
| 3938 | 3940 | extra: []const u32 = &.{}, |
| 3939 | 3941 | |
| 3940 | 3942 | pub const Index = enum(u32) { |
| ... | ... | @@ -5031,7 +5033,8 @@ pub const Function = struct { |
| 5031 | 5033 | |
| 5032 | 5034 | pub fn deinit(self: *Function, gpa: Allocator) void { |
| 5033 | 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 | 5038 | gpa.free(self.value_indices[0..self.instructions.len]); |
| 5036 | 5039 | gpa.free(self.names[0..self.instructions.len]); |
| 5037 | 5040 | self.instructions.deinit(gpa); |
| ... | ... | @@ -5103,6 +5106,13 @@ pub const Function = struct { |
| 5103 | 5106 | } |
| 5104 | 5107 | }; |
| 5105 | 5108 | |
| 5109 | pub const DebugLocation = struct { |
| 5110 | line: u32, |
| 5111 | column: u32, |
| 5112 | scope: Metadata, |
| 5113 | inlined_at: Metadata, |
| 5114 | }; |
| 5115 | |
| 5106 | 5116 | pub const WipFunction = struct { |
| 5107 | 5117 | builder: *Builder, |
| 5108 | 5118 | function: Function.Index, |
| ... | ... | @@ -5111,11 +5121,14 @@ pub const WipFunction = struct { |
| 5111 | 5121 | blocks: std.ArrayListUnmanaged(*llvm.BasicBlock), |
| 5112 | 5122 | instructions: std.ArrayListUnmanaged(*llvm.Value), |
| 5113 | 5123 | } else void, |
| 5124 | last_debug_location: ?DebugLocation, |
| 5125 | current_debug_location: ?DebugLocation, |
| 5114 | 5126 | cursor: Cursor, |
| 5115 | 5127 | blocks: std.ArrayListUnmanaged(Block), |
| 5116 | 5128 | instructions: std.MultiArrayList(Instruction), |
| 5117 | 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 | 5132 | extra: std.ArrayListUnmanaged(u32), |
| 5120 | 5133 | |
| 5121 | 5134 | pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 }; |
| ... | ... | @@ -5169,20 +5182,27 @@ pub const WipFunction = struct { |
| 5169 | 5182 | .blocks = .{}, |
| 5170 | 5183 | .instructions = .{}, |
| 5171 | 5184 | .names = .{}, |
| 5172 | | .metadata = .{}, |
| 5185 | .debug_locations = .{}, |
| 5186 | .debug_values = .{}, |
| 5173 | 5187 | .extra = .{}, |
| 5188 | .current_debug_location = null, |
| 5189 | .last_debug_location = null, |
| 5174 | 5190 | }; |
| 5175 | 5191 | errdefer self.deinit(); |
| 5176 | 5192 | |
| 5177 | 5193 | const params_len = function.typeOf(self.builder).functionParameters(self.builder).len; |
| 5178 | 5194 | try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0); |
| 5179 | 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 | 5199 | if (self.builder.useLibLlvm()) |
| 5182 | 5200 | try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, params_len); |
| 5183 | 5201 | for (0..params_len) |param_index| { |
| 5184 | 5202 | self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) }); |
| 5185 | | if (!self.builder.strip) self.names.appendAssumeCapacity(.empty); // TODO: param names |
| 5203 | if (!self.builder.strip) { |
| 5204 | self.names.appendAssumeCapacity(.empty); // TODO: param names |
| 5205 | } |
| 5186 | 5206 | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5187 | 5207 | function.toLlvm(self.builder).getParam(@intCast(param_index)), |
| 5188 | 5208 | ); |
| ... | ... | @@ -6395,6 +6415,22 @@ pub const WipFunction = struct { |
| 6395 | 6415 | return instruction.toValue(); |
| 6396 | 6416 | } |
| 6397 | 6417 | |
| 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 | 6434 | pub fn finish(self: *WipFunction) Allocator.Error!void { |
| 6399 | 6435 | const gpa = self.builder.gpa; |
| 6400 | 6436 | const function = self.function.ptr(self.builder); |
| ... | ... | @@ -6426,9 +6462,12 @@ pub const WipFunction = struct { |
| 6426 | 6462 | const value_indices = try gpa.alloc(u32, final_instructions_len); |
| 6427 | 6463 | errdefer gpa.free(value_indices); |
| 6428 | 6464 | |
| 6429 | | const metadata = |
| 6430 | | if (self.builder.strip) null else try gpa.alloc(Metadata, final_instructions_len); |
| 6431 | | errdefer if (metadata) |new_metadata| gpa.free(new_metadata); |
| 6465 | var debug_locations = std.AutoHashMapUnmanaged(Instruction.Index, ?DebugLocation){}; |
| 6466 | errdefer debug_locations.deinit(gpa); |
| 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); |
| 6432 | 6471 | |
| 6433 | 6472 | var wip_extra: struct { |
| 6434 | 6473 | index: Instruction.ExtraIndex = 0, |
| ... | ... | @@ -6482,8 +6521,10 @@ pub const WipFunction = struct { |
| 6482 | 6521 | gpa.free(function.blocks); |
| 6483 | 6522 | function.blocks = &.{}; |
| 6484 | 6523 | gpa.free(function.names[0..function.instructions.len]); |
| 6485 | | if (function.metadata) |old_metadata| gpa.free(old_metadata[0..function.instructions.len]); |
| 6486 | | function.metadata = null; |
| 6524 | function.debug_locations.deinit(gpa); |
| 6525 | function.debug_locations = .{}; |
| 6526 | gpa.free(function.debug_values); |
| 6527 | function.debug_values = &.{}; |
| 6487 | 6528 | gpa.free(function.extra); |
| 6488 | 6529 | function.extra = &.{}; |
| 6489 | 6530 | |
| ... | ... | @@ -6532,6 +6573,12 @@ pub const WipFunction = struct { |
| 6532 | 6573 | names[@intFromEnum(new_argument_index)] = wip_name.map( |
| 6533 | 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 | 6583 | for (self.blocks.items) |current_block| { |
| 6537 | 6584 | const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len); |
| ... | ... | @@ -6846,6 +6893,14 @@ pub const WipFunction = struct { |
| 6846 | 6893 | else |
| 6847 | 6894 | self.names.items[@intFromEnum(old_instruction_index)]); |
| 6848 | 6895 | |
| 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 | 6904 | value_indices[@intFromEnum(new_instruction_index)] = value_index; |
| 6850 | 6905 | if (old_instruction_index.hasResultWip(self)) value_index += 1; |
| 6851 | 6906 | } |
| ... | ... | @@ -6856,12 +6911,14 @@ pub const WipFunction = struct { |
| 6856 | 6911 | function.blocks = blocks; |
| 6857 | 6912 | function.names = names.ptr; |
| 6858 | 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 | } |
| 6861 | 6917 | |
| 6862 | 6918 | pub fn deinit(self: *WipFunction) void { |
| 6863 | 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 | 6922 | self.names.deinit(self.builder.gpa); |
| 6866 | 6923 | self.instructions.deinit(self.builder.gpa); |
| 6867 | 6924 | for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa); |
| ... | ... | @@ -7137,7 +7194,16 @@ pub const WipFunction = struct { |
| 7137 | 7194 | ) Allocator.Error!Instruction.Index { |
| 7138 | 7195 | const block_instructions = &self.cursor.block.ptr(self).instructions; |
| 7139 | 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 | 7207 | try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1); |
| 7142 | 7208 | if (self.builder.useLibLlvm()) |
| 7143 | 7209 | try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, 1); |
| ... | ... | @@ -7158,7 +7224,17 @@ pub const WipFunction = struct { |
| 7158 | 7224 | |
| 7159 | 7225 | const index: Instruction.Index = @enumFromInt(self.instructions.len); |
| 7160 | 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 | 7238 | block_instructions.insertAssumeCapacity(self.cursor.instruction, index); |
| 7163 | 7239 | self.cursor.instruction += 1; |
| 7164 | 7240 | return index; |