authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-05-09 02:24:57-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:13-04:00
log338df862d147986c797902706967b3dae7c95cd6
tree74395d320108f6444f95a1c77d85256dd64a7675
parentf3f3c877e0da444e6e5208d7c7179776ddb8ecd8

- fix remember_state

- implement def_cfa_register

1 files changed, 38 insertions(+), 45 deletions(-)

lib/std/dwarf/call_frame.zig+38-45
...@@ -233,17 +233,10 @@ pub const Instruction = union(Opcode) {...@@ -233,17 +233,10 @@ pub const Instruction = union(Opcode) {
233 .register => {},233 .register => {},
234 .remember_state => {},234 .remember_state => {},
235 .restore_state => {},235 .restore_state => {},
236 .def_cfa => |i| {236 .def_cfa => |i| try writer.print("{} {d:<1}", .{ abi.fmtRegister(i.operands.register, arch), @intCast(i64, i.operands.offset)}),
237 try abi.writeRegisterName(writer, arch, i.operands.register);237 .def_cfa_register => |i| try abi.writeRegisterName(writer, arch, i.operands.register),
238 try writer.print(" {d:<1}", .{@intCast(i64, i.operands.offset)});238 .def_cfa_offset => |i| try writer.print("{d:<1}", .{@intCast(i64, i.operands.offset)}),
239 },239 .def_cfa_expression => |i| try writeExpression(writer, i.operands.block, arch, addr_size_bytes, endian),
240 .def_cfa_register => {},
241 .def_cfa_offset => |i| {
242 try writer.print("{d:<1}", .{@intCast(i64, i.operands.offset)});
243 },
244 .def_cfa_expression => |i| {
245 try writeExpression(writer, i.operands.block, arch, addr_size_bytes, endian);
246 },
247 .expression => {},240 .expression => {},
248 .offset_extended_sf => {},241 .offset_extended_sf => {},
249 .def_cfa_sf => {},242 .def_cfa_sf => {},
...@@ -318,16 +311,6 @@ fn writeExpression(...@@ -318,16 +311,6 @@ fn writeExpression(
318 }311 }
319}312}
320313
321// fn formatOffset(data: i64, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
322// _ = fmt;
323// if (data >= 0) try writer.writeByte('+');
324// return std.fmt.formatInt(data, 10, .lower, options, writer);
325// }
326
327// fn fmtOffset(offset: i64) std.fmt.Formatter(formatOffset) {
328// return .{ .data = offset };
329// }
330
331/// See section 6.4.1 of the DWARF5 specification314/// See section 6.4.1 of the DWARF5 specification
332pub const VirtualMachine = struct {315pub const VirtualMachine = struct {
333 const RegisterRule = union(enum) {316 const RegisterRule = union(enum) {
...@@ -387,7 +370,7 @@ pub const VirtualMachine = struct {...@@ -387,7 +370,7 @@ pub const VirtualMachine = struct {
387 }370 }
388 };371 };
389372
390 /// Each row contains unwinding rules for a set of registers at a specific location in the program.373 /// Each row contains unwinding rules for a set of registers at a specific location in the
391 pub const Row = struct {374 pub const Row = struct {
392 /// Offset from pc_begin375 /// Offset from pc_begin
393 offset: u64 = 0,376 offset: u64 = 0,
...@@ -395,31 +378,33 @@ pub const VirtualMachine = struct {...@@ -395,31 +378,33 @@ pub const VirtualMachine = struct {
395 /// The register field of this column defines the register that CFA is derived378 /// The register field of this column defines the register that CFA is derived
396 /// from, while other columns define registers in terms of the CFA.379 /// from, while other columns define registers in terms of the CFA.
397 cfa: Column = .{},380 cfa: Column = .{},
381 columns: ColumnRange = .{},
382 };
383
384 const ColumnRange = struct {
398 /// Index into `columns` of the first column in this row.385 /// Index into `columns` of the first column in this row.
399 columns_start: usize = undefined,386 start: usize = undefined,
400 columns_len: u8 = 0,387 len: u8 = 0,
401 };388 };
402389
403 columns: std.ArrayListUnmanaged(Column) = .{},390 columns: std.ArrayListUnmanaged(Column) = .{},
404 row_stack: std.ArrayListUnmanaged(Row) = .{},391 stack: std.ArrayListUnmanaged(ColumnRange) = .{},
405 current_row: Row = .{},392 current_row: Row = .{},
406393
407 // TODO: Add stack machine stack
408
409 pub fn reset(self: *VirtualMachine) void {394 pub fn reset(self: *VirtualMachine) void {
410 self.row_stack.clearRetainingCapacity();395 self.stack.clearRetainingCapacity();
411 self.columns.clearRetainingCapacity();396 self.columns.clearRetainingCapacity();
412 self.current_row = .{};397 self.current_row = .{};
413 }398 }
414399
415 pub fn deinit(self: *VirtualMachine, allocator: std.mem.Allocator) void {400 pub fn deinit(self: *VirtualMachine, allocator: std.mem.Allocator) void {
416 self.row_stack.deinit(allocator);401 self.stack.deinit(allocator);
417 self.columns.deinit(allocator);402 self.columns.deinit(allocator);
418 self.* = undefined;403 self.* = undefined;
419 }404 }
420405
421 pub fn getColumns(self: VirtualMachine, row: Row) []Column {406 pub fn getColumns(self: VirtualMachine, row: Row) []Column {
422 return self.columns.items[row.columns_start..][0..row.columns_len];407 return self.columns.items[row.columns.start..][0..row.columns.len];
423 }408 }
424409
425 fn getOrAddColumn(self: *VirtualMachine, allocator: std.mem.Allocator, register: u8) !*Column {410 fn getOrAddColumn(self: *VirtualMachine, allocator: std.mem.Allocator, register: u8) !*Column {
...@@ -427,10 +412,10 @@ pub const VirtualMachine = struct {...@@ -427,10 +412,10 @@ pub const VirtualMachine = struct {
427 if (c.register == register) return c;412 if (c.register == register) return c;
428 }413 }
429414
430 if (self.current_row.columns_len == 0) {415 if (self.current_row.columns.len == 0) {
431 self.current_row.columns_start = self.columns.items.len;416 self.current_row.columns.start = self.columns.items.len;
432 }417 }
433 self.current_row.columns_len += 1;418 self.current_row.columns.len += 1;
434419
435 const column = try self.columns.addOne(allocator);420 const column = try self.columns.addOne(allocator);
436 column.* = .{421 column.* = .{
...@@ -443,7 +428,7 @@ pub const VirtualMachine = struct {...@@ -443,7 +428,7 @@ pub const VirtualMachine = struct {
443 pub fn step(self: *VirtualMachine, allocator: std.mem.Allocator, cie: dwarf.CommonInformationEntry, instruction: Instruction) !void {428 pub fn step(self: *VirtualMachine, allocator: std.mem.Allocator, cie: dwarf.CommonInformationEntry, instruction: Instruction) !void {
444 switch (instruction) {429 switch (instruction) {
445 inline .advance_loc, .advance_loc1, .advance_loc2, .advance_loc4 => |i| {430 inline .advance_loc, .advance_loc1, .advance_loc2, .advance_loc4 => |i| {
446 self.current_row.offset += i.operands.delta;431 self.current_row.offset += i.operands.delta * cie.code_alignment_factor;
447 },432 },
448 .offset => |i| {433 .offset => |i| {
449 const column = try self.getOrAddColumn(allocator, i.operands.register);434 const column = try self.getOrAddColumn(allocator, i.operands.register);
...@@ -458,18 +443,22 @@ pub const VirtualMachine = struct {...@@ -458,18 +443,22 @@ pub const VirtualMachine = struct {
458 .same_value => {},443 .same_value => {},
459 .register => {},444 .register => {},
460 .remember_state => {445 .remember_state => {
461446 try self.stack.append(allocator, self.current_row.columns);
462 // TODO: The row stack only actually needs the column information447 errdefer _ = self.stack.pop();
463 // TODO: Also it needs to copy the columns because changes can edit the referenced columns448
464 // TODO: This function could push the column range onto the stack, the copy the columns and update current row449 const new_start = self.columns.items.len;
465450 if (self.current_row.columns.len > 0) {
466 try self.row_stack.append(allocator, self.current_row);451 // Since we're copying from the same backing array, ensure it won't be reallocated
452 try self.columns.ensureUnusedCapacity(allocator, self.current_row.columns.len);
453 self.columns.appendSliceAssumeCapacity(self.getColumns(self.current_row));
454 self.current_row.columns.start = new_start;
455 }
467 },456 },
468 .restore_state => {457 .restore_state => {
469 if (self.row_stack.items.len == 0) return error.InvalidOperation;458 // TODO: Is it possible to remove the duplicate from above? Other instructions may have added columns since then though
470 const row = self.row_stack.pop();459 const columns = self.stack.popOrNull() orelse return error.InvalidOperation;
471 self.current_row.columns_len = row.columns_len;460 self.current_row.columns.len = columns.len;
472 self.current_row.columns_start = row.columns_start;461 self.current_row.columns.start = columns.start;
473 },462 },
474 .def_cfa => |i| {463 .def_cfa => |i| {
475 self.current_row.cfa = .{464 self.current_row.cfa = .{
...@@ -477,8 +466,12 @@ pub const VirtualMachine = struct {...@@ -477,8 +466,12 @@ pub const VirtualMachine = struct {
477 .rule = .{ .offset = @intCast(i64, i.operands.offset) },466 .rule = .{ .offset = @intCast(i64, i.operands.offset) },
478 };467 };
479 },468 },
480 .def_cfa_register => {},469 .def_cfa_register => |i| {
470 // TODO: Verify the the current row is using a register and offset (validation)
471 self.current_row.cfa.register = i.operands.register;
472 },
481 .def_cfa_offset => |i| {473 .def_cfa_offset => |i| {
474 // TODO: Verify the the current row is using a register and offset (validation)
482 self.current_row.cfa.rule = .{ .offset = @intCast(i64, i.operands.offset) };475 self.current_row.cfa.rule = .{ .offset = @intCast(i64, i.operands.offset) };
483 },476 },
484 .def_cfa_expression => |i| {477 .def_cfa_expression => |i| {