authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-26 16:52:01-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-07-26 16:52:01-07:00
log1aacfa7186187ed467a5e3189a877493d5c620a1
tree62a0292ef77b331055d619c8e05a9de6b6a4bac3
parentf9717f87f55cac0d986b6e3a47eba899a63912fb
parent8e4cc0ce5a21d743bc59def79efa75584d06fee4
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16538 from kcbanner/fixup_unwind_perf_regression

Reducing compile time regression introduced by the new DWARF unwinder

3 files changed, 278 insertions(+), 205 deletions(-)

lib/std/dwarf.zig+8-8
...@@ -741,7 +741,7 @@ pub const DwarfInfo = struct {...@@ -741,7 +741,7 @@ pub const DwarfInfo = struct {
741 fn scanAllFunctions(di: *DwarfInfo, allocator: mem.Allocator) !void {741 fn scanAllFunctions(di: *DwarfInfo, allocator: mem.Allocator) !void {
742 var stream = io.fixedBufferStream(di.section(.debug_info).?);742 var stream = io.fixedBufferStream(di.section(.debug_info).?);
743 const in = stream.reader();743 const in = stream.reader();
744 const seekable = &stream.seekableStream();744 const seekable = stream.seekableStream();
745 var this_unit_offset: u64 = 0;745 var this_unit_offset: u64 = 0;
746746
747 var tmp_arena = std.heap.ArenaAllocator.init(allocator);747 var tmp_arena = std.heap.ArenaAllocator.init(allocator);
...@@ -909,8 +909,8 @@ pub const DwarfInfo = struct {...@@ -909,8 +909,8 @@ pub const DwarfInfo = struct {
909909
910 fn scanAllCompileUnits(di: *DwarfInfo, allocator: mem.Allocator) !void {910 fn scanAllCompileUnits(di: *DwarfInfo, allocator: mem.Allocator) !void {
911 var stream = io.fixedBufferStream(di.section(.debug_info).?);911 var stream = io.fixedBufferStream(di.section(.debug_info).?);
912 const in = &stream.reader();912 const in = stream.reader();
913 const seekable = &stream.seekableStream();913 const seekable = stream.seekableStream();
914 var this_unit_offset: u64 = 0;914 var this_unit_offset: u64 = 0;
915915
916 while (this_unit_offset < try seekable.getEndPos()) {916 while (this_unit_offset < try seekable.getEndPos()) {
...@@ -1175,8 +1175,8 @@ pub const DwarfInfo = struct {...@@ -1175,8 +1175,8 @@ pub const DwarfInfo = struct {
11751175
1176 fn parseAbbrevTable(di: *DwarfInfo, allocator: mem.Allocator, offset: u64) !AbbrevTable {1176 fn parseAbbrevTable(di: *DwarfInfo, allocator: mem.Allocator, offset: u64) !AbbrevTable {
1177 var stream = io.fixedBufferStream(di.section(.debug_abbrev).?);1177 var stream = io.fixedBufferStream(di.section(.debug_abbrev).?);
1178 const in = &stream.reader();1178 const in = stream.reader();
1179 const seekable = &stream.seekableStream();1179 const seekable = stream.seekableStream();
11801180
1181 try seekable.seekTo(offset);1181 try seekable.seekTo(offset);
1182 var result = AbbrevTable.init(allocator);1182 var result = AbbrevTable.init(allocator);
...@@ -1256,8 +1256,8 @@ pub const DwarfInfo = struct {...@@ -1256,8 +1256,8 @@ pub const DwarfInfo = struct {
1256 target_address: u64,1256 target_address: u64,
1257 ) !debug.LineInfo {1257 ) !debug.LineInfo {
1258 var stream = io.fixedBufferStream(di.section(.debug_line).?);1258 var stream = io.fixedBufferStream(di.section(.debug_line).?);
1259 const in = &stream.reader();1259 const in = stream.reader();
1260 const seekable = &stream.seekableStream();1260 const seekable = stream.seekableStream();
12611261
1262 const compile_unit_cwd = try compile_unit.die.getAttrString(di, AT.comp_dir, di.section(.debug_line_str), compile_unit);1262 const compile_unit_cwd = try compile_unit.die.getAttrString(di, AT.comp_dir, di.section(.debug_line_str), compile_unit);
1263 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);1263 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);
...@@ -1638,7 +1638,7 @@ pub const DwarfInfo = struct {...@@ -1638,7 +1638,7 @@ pub const DwarfInfo = struct {
1638 }1638 }
1639 }1639 }
16401640
1641 std.mem.sort(FrameDescriptionEntry, di.fde_list.items, {}, struct {1641 std.mem.sortUnstable(FrameDescriptionEntry, di.fde_list.items, {}, struct {
1642 fn lessThan(ctx: void, a: FrameDescriptionEntry, b: FrameDescriptionEntry) bool {1642 fn lessThan(ctx: void, a: FrameDescriptionEntry, b: FrameDescriptionEntry) bool {
1643 _ = ctx;1643 _ = ctx;
1644 return a.pc_begin < b.pc_begin;1644 return a.pc_begin < b.pc_begin;
lib/std/dwarf/call_frame.zig+256-182
...@@ -50,176 +50,250 @@ const Opcode = enum(u8) {...@@ -50,176 +50,250 @@ const Opcode = enum(u8) {
50 pub const hi_user = 0x3f;50 pub const hi_user = 0x3f;
51};51};
5252
53const Operand = enum {53fn readBlock(stream: *std.io.FixedBufferStream([]const u8)) ![]const u8 {
54 opcode_delta,54 const reader = stream.reader();
55 opcode_register,55 const block_len = try leb.readULEB128(usize, reader);
56 uleb128_register,56 if (stream.pos + block_len > stream.buffer.len) return error.InvalidOperand;
57 uleb128_offset,
58 sleb128_offset,
59 address,
60 u8_delta,
61 u16_delta,
62 u32_delta,
63 block,
64
65 fn Storage(comptime self: Operand) type {
66 return switch (self) {
67 .opcode_delta, .opcode_register => u8,
68 .uleb128_register => u8,
69 .uleb128_offset => u64,
70 .sleb128_offset => i64,
71 .address => u64,
72 .u8_delta => u8,
73 .u16_delta => u16,
74 .u32_delta => u32,
75 .block => []const u8,
76 };
77 }
7857
79 fn read(58 const block = stream.buffer[stream.pos..][0..block_len];
80 comptime self: Operand,59 reader.context.pos += block_len;
81 stream: *std.io.FixedBufferStream([]const u8),
82 opcode_value: ?u6,
83 addr_size_bytes: u8,
84 endian: std.builtin.Endian,
85 ) !Storage(self) {
86 const reader = stream.reader();
87 return switch (self) {
88 .opcode_delta, .opcode_register => opcode_value orelse return error.InvalidOperand,
89 .uleb128_register => try leb.readULEB128(u8, reader),
90 .uleb128_offset => try leb.readULEB128(u64, reader),
91 .sleb128_offset => try leb.readILEB128(i64, reader),
92 .address => switch (addr_size_bytes) {
93 2 => try reader.readInt(u16, endian),
94 4 => try reader.readInt(u32, endian),
95 8 => try reader.readInt(u64, endian),
96 else => return error.InvalidAddrSize,
97 },
98 .u8_delta => try reader.readByte(),
99 .u16_delta => try reader.readInt(u16, endian),
100 .u32_delta => try reader.readInt(u32, endian),
101 .block => {
102 const block_len = try leb.readULEB128(usize, reader);
103 if (stream.pos + block_len > stream.buffer.len) return error.InvalidOperand;
104
105 const block = stream.buffer[stream.pos..][0..block_len];
106 reader.context.pos += block_len;
107
108 return block;
109 },
110 };
111 }
112};
11360
114fn InstructionType(comptime definition: anytype) type {61 return block;
115 const definition_type = @typeInfo(@TypeOf(definition));
116 assert(definition_type == .Struct);
117
118 const definition_len = definition_type.Struct.fields.len;
119 comptime var fields: [definition_len]std.builtin.Type.StructField = undefined;
120 inline for (definition_type.Struct.fields, &fields) |definition_field, *operands_field| {
121 const opcode = std.enums.nameCast(Operand, @field(definition, definition_field.name));
122 const storage_type = opcode.Storage();
123 operands_field.* = .{
124 .name = definition_field.name,
125 .type = storage_type,
126 .default_value = null,
127 .is_comptime = false,
128 .alignment = @alignOf(storage_type),
129 };
130 }
131
132 const InstructionOperands = @Type(.{
133 .Struct = .{
134 .layout = .Auto,
135 .fields = &fields,
136 .decls = &.{},
137 .is_tuple = false,
138 },
139 });
140
141 return struct {
142 const Self = @This();
143 operands: InstructionOperands,
144
145 pub fn read(
146 stream: *std.io.FixedBufferStream([]const u8),
147 opcode_value: ?u6,
148 addr_size_bytes: u8,
149 endian: std.builtin.Endian,
150 ) !Self {
151 var operands: InstructionOperands = undefined;
152 inline for (definition_type.Struct.fields) |definition_field| {
153 const operand = comptime std.enums.nameCast(Operand, @field(definition, definition_field.name));
154 @field(operands, definition_field.name) = try operand.read(stream, opcode_value, addr_size_bytes, endian);
155 }
156
157 return .{ .operands = operands };
158 }
159 };
160}62}
16163
162pub const Instruction = union(Opcode) {64pub const Instruction = union(Opcode) {
163 advance_loc: InstructionType(.{ .delta = .opcode_delta }),65 advance_loc: struct {
164 offset: InstructionType(.{ .register = .opcode_register, .offset = .uleb128_offset }),66 delta: u8,
165 offset_extended: InstructionType(.{ .register = .uleb128_register, .offset = .uleb128_offset }),67 },
166 restore: InstructionType(.{ .register = .opcode_register }),68 offset: struct {
167 restore_extended: InstructionType(.{ .register = .uleb128_register }),69 register: u8,
168 nop: InstructionType(.{}),70 offset: u64,
169 set_loc: InstructionType(.{ .address = .address }),71 },
170 advance_loc1: InstructionType(.{ .delta = .u8_delta }),72 offset_extended: struct {
171 advance_loc2: InstructionType(.{ .delta = .u16_delta }),73 register: u8,
172 advance_loc4: InstructionType(.{ .delta = .u32_delta }),74 offset: u64,
173 undefined: InstructionType(.{ .register = .uleb128_register }),75 },
174 same_value: InstructionType(.{ .register = .uleb128_register }),76 restore: struct {
175 register: InstructionType(.{ .register = .uleb128_register, .target_register = .uleb128_register }),77 register: u8,
176 remember_state: InstructionType(.{}),78 },
177 restore_state: InstructionType(.{}),79 restore_extended: struct {
178 def_cfa: InstructionType(.{ .register = .uleb128_register, .offset = .uleb128_offset }),80 register: u8,
179 def_cfa_register: InstructionType(.{ .register = .uleb128_register }),81 },
180 def_cfa_offset: InstructionType(.{ .offset = .uleb128_offset }),82 nop: void,
181 def_cfa_expression: InstructionType(.{ .block = .block }),83 set_loc: struct {
182 expression: InstructionType(.{ .register = .uleb128_register, .block = .block }),84 address: u64,
183 offset_extended_sf: InstructionType(.{ .register = .uleb128_register, .offset = .sleb128_offset }),85 },
184 def_cfa_sf: InstructionType(.{ .register = .uleb128_register, .offset = .sleb128_offset }),86 advance_loc1: struct {
185 def_cfa_offset_sf: InstructionType(.{ .offset = .sleb128_offset }),87 delta: u8,
186 val_offset: InstructionType(.{ .register = .uleb128_register, .offset = .uleb128_offset }),88 },
187 val_offset_sf: InstructionType(.{ .register = .uleb128_register, .offset = .sleb128_offset }),89 advance_loc2: struct {
188 val_expression: InstructionType(.{ .register = .uleb128_register, .block = .block }),90 delta: u16,
18991 },
190 fn readOperands(92 advance_loc4: struct {
191 self: *Instruction,93 delta: u32,
192 stream: *std.io.FixedBufferStream([]const u8),94 },
193 opcode_value: ?u6,95 undefined: struct {
194 addr_size_bytes: u8,96 register: u8,
195 endian: std.builtin.Endian,97 },
196 ) !void {98 same_value: struct {
197 switch (self.*) {99 register: u8,
198 inline else => |*inst| inst.* = try @TypeOf(inst.*).read(stream, opcode_value, addr_size_bytes, endian),100 },
199 }101 register: struct {
200 }102 register: u8,
103 target_register: u8,
104 },
105 remember_state: void,
106 restore_state: void,
107 def_cfa: struct {
108 register: u8,
109 offset: u64,
110 },
111 def_cfa_register: struct {
112 register: u8,
113 },
114 def_cfa_offset: struct {
115 offset: u64,
116 },
117 def_cfa_expression: struct {
118 block: []const u8,
119 },
120 expression: struct {
121 register: u8,
122 block: []const u8,
123 },
124 offset_extended_sf: struct {
125 register: u8,
126 offset: i64,
127 },
128 def_cfa_sf: struct {
129 register: u8,
130 offset: i64,
131 },
132 def_cfa_offset_sf: struct {
133 offset: i64,
134 },
135 val_offset: struct {
136 register: u8,
137 offset: u64,
138 },
139 val_offset_sf: struct {
140 register: u8,
141 offset: i64,
142 },
143 val_expression: struct {
144 register: u8,
145 block: []const u8,
146 },
201147
202 pub fn read(148 pub fn read(
203 stream: *std.io.FixedBufferStream([]const u8),149 stream: *std.io.FixedBufferStream([]const u8),
204 addr_size_bytes: u8,150 addr_size_bytes: u8,
205 endian: std.builtin.Endian,151 endian: std.builtin.Endian,
206 ) !Instruction {152 ) !Instruction {
207 return switch (try stream.reader().readByte()) {153 const reader = stream.reader();
208 inline Opcode.lo_inline...Opcode.hi_inline => |opcode| blk: {154 switch (try reader.readByte()) {
155 Opcode.lo_inline...Opcode.hi_inline => |opcode| {
209 const e: Opcode = @enumFromInt(opcode & 0b11000000);156 const e: Opcode = @enumFromInt(opcode & 0b11000000);
210 var result = @unionInit(Instruction, @tagName(e), undefined);157 const value: u6 = @intCast(opcode & 0b111111);
211 try result.readOperands(stream, @as(u6, @intCast(opcode & 0b111111)), addr_size_bytes, endian);158 return switch (e) {
212 break :blk result;159 .advance_loc => .{
160 .advance_loc = .{ .delta = value },
161 },
162 .offset => .{
163 .offset = .{
164 .register = value,
165 .offset = try leb.readULEB128(u64, reader),
166 },
167 },
168 .restore => .{
169 .restore = .{ .register = value },
170 },
171 else => unreachable,
172 };
213 },173 },
214 inline Opcode.lo_reserved...Opcode.hi_reserved => |opcode| blk: {174 Opcode.lo_reserved...Opcode.hi_reserved => |opcode| {
215 const e: Opcode = @enumFromInt(opcode);175 const e: Opcode = @enumFromInt(opcode);
216 var result = @unionInit(Instruction, @tagName(e), undefined);176 return switch (e) {
217 try result.readOperands(stream, null, addr_size_bytes, endian);177 .advance_loc,
218 break :blk result;178 .offset,
179 .restore,
180 => unreachable,
181 .nop => .{ .nop = {} },
182 .set_loc => .{
183 .set_loc = .{
184 .address = switch (addr_size_bytes) {
185 2 => try reader.readInt(u16, endian),
186 4 => try reader.readInt(u32, endian),
187 8 => try reader.readInt(u64, endian),
188 else => return error.InvalidAddrSize,
189 },
190 },
191 },
192 .advance_loc1 => .{
193 .advance_loc1 = .{ .delta = try reader.readByte() },
194 },
195 .advance_loc2 => .{
196 .advance_loc2 = .{ .delta = try reader.readInt(u16, endian) },
197 },
198 .advance_loc4 => .{
199 .advance_loc4 = .{ .delta = try reader.readInt(u32, endian) },
200 },
201 .offset_extended => .{
202 .offset_extended = .{
203 .register = try leb.readULEB128(u8, reader),
204 .offset = try leb.readULEB128(u64, reader),
205 },
206 },
207 .restore_extended => .{
208 .restore_extended = .{
209 .register = try leb.readULEB128(u8, reader),
210 },
211 },
212 .undefined => .{
213 .undefined = .{
214 .register = try leb.readULEB128(u8, reader),
215 },
216 },
217 .same_value => .{
218 .same_value = .{
219 .register = try leb.readULEB128(u8, reader),
220 },
221 },
222 .register => .{
223 .register = .{
224 .register = try leb.readULEB128(u8, reader),
225 .target_register = try leb.readULEB128(u8, reader),
226 },
227 },
228 .remember_state => .{ .remember_state = {} },
229 .restore_state => .{ .restore_state = {} },
230 .def_cfa => .{
231 .def_cfa = .{
232 .register = try leb.readULEB128(u8, reader),
233 .offset = try leb.readULEB128(u64, reader),
234 },
235 },
236 .def_cfa_register => .{
237 .def_cfa_register = .{
238 .register = try leb.readULEB128(u8, reader),
239 },
240 },
241 .def_cfa_offset => .{
242 .def_cfa_offset = .{
243 .offset = try leb.readULEB128(u64, reader),
244 },
245 },
246 .def_cfa_expression => .{
247 .def_cfa_expression = .{
248 .block = try readBlock(stream),
249 },
250 },
251 .expression => .{
252 .expression = .{
253 .register = try leb.readULEB128(u8, reader),
254 .block = try readBlock(stream),
255 },
256 },
257 .offset_extended_sf => .{
258 .offset_extended_sf = .{
259 .register = try leb.readULEB128(u8, reader),
260 .offset = try leb.readILEB128(i64, reader),
261 },
262 },
263 .def_cfa_sf => .{
264 .def_cfa_sf = .{
265 .register = try leb.readULEB128(u8, reader),
266 .offset = try leb.readILEB128(i64, reader),
267 },
268 },
269 .def_cfa_offset_sf => .{
270 .def_cfa_offset_sf = .{
271 .offset = try leb.readILEB128(i64, reader),
272 },
273 },
274 .val_offset => .{
275 .val_offset = .{
276 .register = try leb.readULEB128(u8, reader),
277 .offset = try leb.readULEB128(u64, reader),
278 },
279 },
280 .val_offset_sf => .{
281 .val_offset_sf = .{
282 .register = try leb.readULEB128(u8, reader),
283 .offset = try leb.readILEB128(i64, reader),
284 },
285 },
286 .val_expression => .{
287 .val_expression = .{
288 .register = try leb.readULEB128(u8, reader),
289 .block = try readBlock(stream),
290 },
291 },
292 };
219 },293 },
220 Opcode.lo_user...Opcode.hi_user => error.UnimplementedUserOpcode,294 Opcode.lo_user...Opcode.hi_user => return error.UnimplementedUserOpcode,
221 else => error.InvalidOpcode,295 else => return error.InvalidOpcode,
222 };296 }
223 }297 }
224};298};
225299
...@@ -475,16 +549,16 @@ pub const VirtualMachine = struct {...@@ -475,16 +549,16 @@ pub const VirtualMachine = struct {
475 const prev_row = self.current_row;549 const prev_row = self.current_row;
476 switch (instruction) {550 switch (instruction) {
477 .set_loc => |i| {551 .set_loc => |i| {
478 if (i.operands.address <= self.current_row.offset) return error.InvalidOperation;552 if (i.address <= self.current_row.offset) return error.InvalidOperation;
479 // TODO: Check cie.segment_selector_size != 0 for DWARFV4553 // TODO: Check cie.segment_selector_size != 0 for DWARFV4
480 self.current_row.offset = i.operands.address;554 self.current_row.offset = i.address;
481 },555 },
482 inline .advance_loc,556 inline .advance_loc,
483 .advance_loc1,557 .advance_loc1,
484 .advance_loc2,558 .advance_loc2,
485 .advance_loc4,559 .advance_loc4,
486 => |i| {560 => |i| {
487 self.current_row.offset += i.operands.delta * cie.code_alignment_factor;561 self.current_row.offset += i.delta * cie.code_alignment_factor;
488 self.current_row.copy_on_write = true;562 self.current_row.copy_on_write = true;
489 },563 },
490 inline .offset,564 inline .offset,
...@@ -492,35 +566,35 @@ pub const VirtualMachine = struct {...@@ -492,35 +566,35 @@ pub const VirtualMachine = struct {
492 .offset_extended_sf,566 .offset_extended_sf,
493 => |i| {567 => |i| {
494 try self.resolveCopyOnWrite(allocator);568 try self.resolveCopyOnWrite(allocator);
495 const column = try self.getOrAddColumn(allocator, i.operands.register);569 const column = try self.getOrAddColumn(allocator, i.register);
496 column.rule = .{ .offset = @as(i64, @intCast(i.operands.offset)) * cie.data_alignment_factor };570 column.rule = .{ .offset = @as(i64, @intCast(i.offset)) * cie.data_alignment_factor };
497 },571 },
498 inline .restore,572 inline .restore,
499 .restore_extended,573 .restore_extended,
500 => |i| {574 => |i| {
501 try self.resolveCopyOnWrite(allocator);575 try self.resolveCopyOnWrite(allocator);
502 if (self.cie_row) |cie_row| {576 if (self.cie_row) |cie_row| {
503 const column = try self.getOrAddColumn(allocator, i.operands.register);577 const column = try self.getOrAddColumn(allocator, i.register);
504 column.rule = for (self.rowColumns(cie_row)) |cie_column| {578 column.rule = for (self.rowColumns(cie_row)) |cie_column| {
505 if (cie_column.register == i.operands.register) break cie_column.rule;579 if (cie_column.register == i.register) break cie_column.rule;
506 } else .{ .default = {} };580 } else .{ .default = {} };
507 } else return error.InvalidOperation;581 } else return error.InvalidOperation;
508 },582 },
509 .nop => {},583 .nop => {},
510 .undefined => |i| {584 .undefined => |i| {
511 try self.resolveCopyOnWrite(allocator);585 try self.resolveCopyOnWrite(allocator);
512 const column = try self.getOrAddColumn(allocator, i.operands.register);586 const column = try self.getOrAddColumn(allocator, i.register);
513 column.rule = .{ .undefined = {} };587 column.rule = .{ .undefined = {} };
514 },588 },
515 .same_value => |i| {589 .same_value => |i| {
516 try self.resolveCopyOnWrite(allocator);590 try self.resolveCopyOnWrite(allocator);
517 const column = try self.getOrAddColumn(allocator, i.operands.register);591 const column = try self.getOrAddColumn(allocator, i.register);
518 column.rule = .{ .same_value = {} };592 column.rule = .{ .same_value = {} };
519 },593 },
520 .register => |i| {594 .register => |i| {
521 try self.resolveCopyOnWrite(allocator);595 try self.resolveCopyOnWrite(allocator);
522 const column = try self.getOrAddColumn(allocator, i.operands.register);596 const column = try self.getOrAddColumn(allocator, i.register);
523 column.rule = .{ .register = i.operands.target_register };597 column.rule = .{ .register = i.target_register };
524 },598 },
525 .remember_state => {599 .remember_state => {
526 try self.stack.append(allocator, self.current_row.columns);600 try self.stack.append(allocator, self.current_row.columns);
...@@ -538,69 +612,69 @@ pub const VirtualMachine = struct {...@@ -538,69 +612,69 @@ pub const VirtualMachine = struct {
538 .def_cfa => |i| {612 .def_cfa => |i| {
539 try self.resolveCopyOnWrite(allocator);613 try self.resolveCopyOnWrite(allocator);
540 self.current_row.cfa = .{614 self.current_row.cfa = .{
541 .register = i.operands.register,615 .register = i.register,
542 .rule = .{ .val_offset = @intCast(i.operands.offset) },616 .rule = .{ .val_offset = @intCast(i.offset) },
543 };617 };
544 },618 },
545 .def_cfa_sf => |i| {619 .def_cfa_sf => |i| {
546 try self.resolveCopyOnWrite(allocator);620 try self.resolveCopyOnWrite(allocator);
547 self.current_row.cfa = .{621 self.current_row.cfa = .{
548 .register = i.operands.register,622 .register = i.register,
549 .rule = .{ .val_offset = i.operands.offset * cie.data_alignment_factor },623 .rule = .{ .val_offset = i.offset * cie.data_alignment_factor },
550 };624 };
551 },625 },
552 .def_cfa_register => |i| {626 .def_cfa_register => |i| {
553 try self.resolveCopyOnWrite(allocator);627 try self.resolveCopyOnWrite(allocator);
554 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation;628 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation;
555 self.current_row.cfa.register = i.operands.register;629 self.current_row.cfa.register = i.register;
556 },630 },
557 .def_cfa_offset => |i| {631 .def_cfa_offset => |i| {
558 try self.resolveCopyOnWrite(allocator);632 try self.resolveCopyOnWrite(allocator);
559 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation;633 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation;
560 self.current_row.cfa.rule = .{634 self.current_row.cfa.rule = .{
561 .val_offset = @intCast(i.operands.offset),635 .val_offset = @intCast(i.offset),
562 };636 };
563 },637 },
564 .def_cfa_offset_sf => |i| {638 .def_cfa_offset_sf => |i| {
565 try self.resolveCopyOnWrite(allocator);639 try self.resolveCopyOnWrite(allocator);
566 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation;640 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation;
567 self.current_row.cfa.rule = .{641 self.current_row.cfa.rule = .{
568 .val_offset = i.operands.offset * cie.data_alignment_factor,642 .val_offset = i.offset * cie.data_alignment_factor,
569 };643 };
570 },644 },
571 .def_cfa_expression => |i| {645 .def_cfa_expression => |i| {
572 try self.resolveCopyOnWrite(allocator);646 try self.resolveCopyOnWrite(allocator);
573 self.current_row.cfa.register = undefined;647 self.current_row.cfa.register = undefined;
574 self.current_row.cfa.rule = .{648 self.current_row.cfa.rule = .{
575 .expression = i.operands.block,649 .expression = i.block,
576 };650 };
577 },651 },
578 .expression => |i| {652 .expression => |i| {
579 try self.resolveCopyOnWrite(allocator);653 try self.resolveCopyOnWrite(allocator);
580 const column = try self.getOrAddColumn(allocator, i.operands.register);654 const column = try self.getOrAddColumn(allocator, i.register);
581 column.rule = .{655 column.rule = .{
582 .expression = i.operands.block,656 .expression = i.block,
583 };657 };
584 },658 },
585 .val_offset => |i| {659 .val_offset => |i| {
586 try self.resolveCopyOnWrite(allocator);660 try self.resolveCopyOnWrite(allocator);
587 const column = try self.getOrAddColumn(allocator, i.operands.register);661 const column = try self.getOrAddColumn(allocator, i.register);
588 column.rule = .{662 column.rule = .{
589 .val_offset = @as(i64, @intCast(i.operands.offset)) * cie.data_alignment_factor,663 .val_offset = @as(i64, @intCast(i.offset)) * cie.data_alignment_factor,
590 };664 };
591 },665 },
592 .val_offset_sf => |i| {666 .val_offset_sf => |i| {
593 try self.resolveCopyOnWrite(allocator);667 try self.resolveCopyOnWrite(allocator);
594 const column = try self.getOrAddColumn(allocator, i.operands.register);668 const column = try self.getOrAddColumn(allocator, i.register);
595 column.rule = .{669 column.rule = .{
596 .val_offset = i.operands.offset * cie.data_alignment_factor,670 .val_offset = i.offset * cie.data_alignment_factor,
597 };671 };
598 },672 },
599 .val_expression => |i| {673 .val_expression => |i| {
600 try self.resolveCopyOnWrite(allocator);674 try self.resolveCopyOnWrite(allocator);
601 const column = try self.getOrAddColumn(allocator, i.operands.register);675 const column = try self.getOrAddColumn(allocator, i.register);
602 column.rule = .{676 column.rule = .{
603 .val_expression = i.operands.block,677 .val_expression = i.block,
604 };678 };
605 },679 },
606 }680 }
lib/std/dwarf/expressions.zig+14-15
...@@ -318,6 +318,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -318,6 +318,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
318318
319 const opcode = try stream.reader().readByte();319 const opcode = try stream.reader().readByte();
320 if (options.call_frame_context and !isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode;320 if (options.call_frame_context and !isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode;
321 const operand = try readOperand(stream, opcode, context);
321 switch (opcode) {322 switch (opcode) {
322323
323 // 2.5.1.1: Literal Encodings324 // 2.5.1.1: Literal Encodings
...@@ -333,10 +334,10 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -333,10 +334,10 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
333 OP.const8s,334 OP.const8s,
334 OP.constu,335 OP.constu,
335 OP.consts,336 OP.consts,
336 => try self.stack.append(allocator, .{ .generic = (try readOperand(stream, opcode, context)).?.generic }),337 => try self.stack.append(allocator, .{ .generic = operand.?.generic }),
337338
338 OP.const_type => {339 OP.const_type => {
339 const const_type = (try readOperand(stream, opcode, context)).?.const_type;340 const const_type = operand.?.const_type;
340 try self.stack.append(allocator, .{ .const_type = .{341 try self.stack.append(allocator, .{ .const_type = .{
341 .type_offset = const_type.type_offset,342 .type_offset = const_type.type_offset,
342 .value_bytes = const_type.value_bytes,343 .value_bytes = const_type.value_bytes,
...@@ -348,7 +349,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -348,7 +349,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
348 => {349 => {
349 if (context.compile_unit == null) return error.IncompleteExpressionContext;350 if (context.compile_unit == null) return error.IncompleteExpressionContext;
350 if (context.debug_addr == null) return error.IncompleteExpressionContext;351 if (context.debug_addr == null) return error.IncompleteExpressionContext;
351 const debug_addr_index = (try readOperand(stream, opcode, context)).?.generic;352 const debug_addr_index = operand.?.generic;
352 const offset = context.compile_unit.?.addr_base + debug_addr_index;353 const offset = context.compile_unit.?.addr_base + debug_addr_index;
353 if (offset >= context.debug_addr.?.len) return error.InvalidExpression;354 if (offset >= context.debug_addr.?.len) return error.InvalidExpression;
354 const value = mem.readIntSliceNative(usize, context.debug_addr.?[offset..][0..@sizeOf(usize)]);355 const value = mem.readIntSliceNative(usize, context.debug_addr.?[offset..][0..@sizeOf(usize)]);
...@@ -360,7 +361,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -360,7 +361,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
360 if (context.compile_unit == null) return error.IncompleteExpressionContext;361 if (context.compile_unit == null) return error.IncompleteExpressionContext;
361 if (context.compile_unit.?.frame_base == null) return error.IncompleteExpressionContext;362 if (context.compile_unit.?.frame_base == null) return error.IncompleteExpressionContext;
362363
363 const offset: i64 = @intCast((try readOperand(stream, opcode, context)).?.generic);364 const offset: i64 = @intCast(operand.?.generic);
364 _ = offset;365 _ = offset;
365366
366 switch (context.compile_unit.?.frame_base.?.*) {367 switch (context.compile_unit.?.frame_base.?.*) {
...@@ -384,7 +385,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -384,7 +385,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
384 => {385 => {
385 if (context.thread_context == null) return error.IncompleteExpressionContext;386 if (context.thread_context == null) return error.IncompleteExpressionContext;
386387
387 const base_register = (try readOperand(stream, opcode, context)).?.base_register;388 const base_register = operand.?.base_register;
388 var value: i64 = @intCast(mem.readIntSliceNative(usize, try abi.regBytes(389 var value: i64 = @intCast(mem.readIntSliceNative(usize, try abi.regBytes(
389 context.thread_context.?,390 context.thread_context.?,
390 base_register.base_register,391 base_register.base_register,
...@@ -394,7 +395,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -394,7 +395,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
394 try self.stack.append(allocator, .{ .generic = @intCast(value) });395 try self.stack.append(allocator, .{ .generic = @intCast(value) });
395 },396 },
396 OP.regval_type => {397 OP.regval_type => {
397 const register_type = (try readOperand(stream, opcode, context)).?.register_type;398 const register_type = operand.?.register_type;
398 const value = mem.readIntSliceNative(usize, try abi.regBytes(399 const value = mem.readIntSliceNative(usize, try abi.regBytes(
399 context.thread_context.?,400 context.thread_context.?,
400 register_type.register,401 register_type.register,
...@@ -418,7 +419,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -418,7 +419,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
418 _ = self.stack.pop();419 _ = self.stack.pop();
419 },420 },
420 OP.pick, OP.over => {421 OP.pick, OP.over => {
421 const stack_index = if (opcode == OP.over) 1 else (try readOperand(stream, opcode, context)).?.generic;422 const stack_index = if (opcode == OP.over) 1 else operand.?.generic;
422 if (stack_index >= self.stack.items.len) return error.InvalidExpression;423 if (stack_index >= self.stack.items.len) return error.InvalidExpression;
423 try self.stack.append(allocator, self.stack.items[self.stack.items.len - 1 - stack_index]);424 try self.stack.append(allocator, self.stack.items[self.stack.items.len - 1 - stack_index]);
424 },425 },
...@@ -459,8 +460,6 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -459,8 +460,6 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
459 _ = addr_space_identifier;460 _ = addr_space_identifier;
460461
461 if (context.isValidMemory) |isValidMemory| if (!isValidMemory(addr)) return error.InvalidExpression;462 if (context.isValidMemory) |isValidMemory| if (!isValidMemory(addr)) return error.InvalidExpression;
462
463 const operand = try readOperand(stream, opcode, context);
464 const size = switch (opcode) {463 const size = switch (opcode) {
465 OP.deref,464 OP.deref,
466 OP.xderef,465 OP.xderef,
...@@ -594,7 +593,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -594,7 +593,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
594 },593 },
595 OP.plus_uconst => {594 OP.plus_uconst => {
596 if (self.stack.items.len == 0) return error.InvalidExpression;595 if (self.stack.items.len == 0) return error.InvalidExpression;
597 const constant = (try readOperand(stream, opcode, context)).?.generic;596 const constant = operand.?.generic;
598 self.stack.items[self.stack.items.len - 1] = .{597 self.stack.items[self.stack.items.len - 1] = .{
599 .generic = try std.math.add(addr_type, try self.stack.items[self.stack.items.len - 1].asIntegral(), constant),598 .generic = try std.math.add(addr_type, try self.stack.items[self.stack.items.len - 1].asIntegral(), constant),
600 };599 };
...@@ -663,7 +662,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -663,7 +662,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
663 }662 }
664 },663 },
665 OP.skip, OP.bra => {664 OP.skip, OP.bra => {
666 const branch_offset = (try readOperand(stream, opcode, context)).?.branch_offset;665 const branch_offset = operand.?.branch_offset;
667 const condition = if (opcode == OP.bra) blk: {666 const condition = if (opcode == OP.bra) blk: {
668 if (self.stack.items.len == 0) return error.InvalidExpression;667 if (self.stack.items.len == 0) return error.InvalidExpression;
669 break :blk try self.stack.pop().asIntegral() != 0;668 break :blk try self.stack.pop().asIntegral() != 0;
...@@ -683,7 +682,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -683,7 +682,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
683 OP.call4,682 OP.call4,
684 OP.call_ref,683 OP.call_ref,
685 => {684 => {
686 const debug_info_offset = (try readOperand(stream, opcode, context)).?.generic;685 const debug_info_offset = operand.?.generic;
687 _ = debug_info_offset;686 _ = debug_info_offset;
688687
689 // TODO: Load a DIE entry at debug_info_offset in a .debug_info section (the spec says that it688 // TODO: Load a DIE entry at debug_info_offset in a .debug_info section (the spec says that it
...@@ -696,7 +695,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -696,7 +695,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
696 // 2.5.1.6: Type Conversions695 // 2.5.1.6: Type Conversions
697 OP.convert => {696 OP.convert => {
698 if (self.stack.items.len == 0) return error.InvalidExpression;697 if (self.stack.items.len == 0) return error.InvalidExpression;
699 const type_offset = (try readOperand(stream, opcode, context)).?.generic;698 const type_offset = operand.?.generic;
700699
701 // TODO: Load the DW_TAG_base_type entries in context.compile_unit and verify both types are the same size700 // TODO: Load the DW_TAG_base_type entries in context.compile_unit and verify both types are the same size
702 const value = self.stack.items[self.stack.items.len - 1];701 const value = self.stack.items[self.stack.items.len - 1];
...@@ -710,7 +709,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -710,7 +709,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
710 },709 },
711 OP.reinterpret => {710 OP.reinterpret => {
712 if (self.stack.items.len == 0) return error.InvalidExpression;711 if (self.stack.items.len == 0) return error.InvalidExpression;
713 const type_offset = (try readOperand(stream, opcode, context)).?.generic;712 const type_offset = operand.?.generic;
714713
715 // TODO: Load the DW_TAG_base_type entries in context.compile_unit and verify both types are the same size714 // TODO: Load the DW_TAG_base_type entries in context.compile_unit and verify both types are the same size
716 const value = self.stack.items[self.stack.items.len - 1];715 const value = self.stack.items[self.stack.items.len - 1];
...@@ -745,7 +744,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -745,7 +744,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
745 // 2.5.1.7: Special Operations744 // 2.5.1.7: Special Operations
746 OP.nop => {},745 OP.nop => {},
747 OP.entry_value => {746 OP.entry_value => {
748 const block = (try readOperand(stream, opcode, context)).?.block;747 const block = operand.?.block;
749 if (block.len == 0) return error.InvalidSubExpression;748 if (block.len == 0) return error.InvalidSubExpression;
750749
751 // TODO: The spec states that this sub-expression needs to observe the state (ie. registers)750 // TODO: The spec states that this sub-expression needs to observe the state (ie. registers)