pub fn read(
reader: *std.Io.Reader,
addr_size_bytes: u8,
endian: std.builtin.Endian,
) !Instruction {
const inst: OpcodeByte = @bitCast(try reader.takeByte());
return switch (inst.opcode) {
.advance_loc => .{ .advance_loc = inst.low.operand },
.offset => .{ .register = .{
.index = inst.low.operand,
.rule = .{ .offset_uf = try reader.takeLeb128(u64) },
} },
.restore => .{ .register = .{
.index = inst.low.operand,
.rule = .restore,
} },
.extended => switch (inst.low.extended) {
.nop => .nop,
.remember_state => .remember_state,
.restore_state => .restore_state,
.advance_loc1 => .{ .advance_loc = try reader.takeByte() },
.advance_loc2 => .{ .advance_loc = try reader.takeInt(u16, endian) },
.advance_loc4 => .{ .advance_loc = try reader.takeInt(u32, endian) },
.set_loc => .{ .set_loc = switch (addr_size_bytes) {
2 => try reader.takeInt(u16, endian),
4 => try reader.takeInt(u32, endian),
8 => try reader.takeInt(u64, endian),
else => return error.UnsupportedAddrSize,
} },
.offset_extended => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .{ .offset_uf = try reader.takeLeb128(u64) },
} },
.offset_extended_sf => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .{ .offset_sf = try reader.takeLeb128(i64) },
} },
.restore_extended => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .restore,
} },
.undefined => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .undefined,
} },
.same_value => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .same_value,
} },
.register => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .{ .register = try reader.takeLeb128(u8) },
} },
.val_offset => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .{ .val_offset_uf = try reader.takeLeb128(u64) },
} },
.val_offset_sf => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .{ .val_offset_sf = try reader.takeLeb128(i64) },
} },
.expression => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .{ .expr = try reader.takeLeb128(usize) },
} },
.val_expression => .{ .register = .{
.index = try reader.takeLeb128(u8),
.rule = .{ .val_expr = try reader.takeLeb128(usize) },
} },
.def_cfa => .{ .def_cfa = .{
.register = try reader.takeLeb128(u8),
.offset = try reader.takeLeb128(u64),
} },
.def_cfa_sf => .{ .def_cfa_sf = .{
.register = try reader.takeLeb128(u8),
.offset_sf = try reader.takeLeb128(i64),
} },
.def_cfa_register => .{ .def_cfa_reg = try reader.takeLeb128(u8) },
.def_cfa_offset => .{ .def_cfa_offset = try reader.takeLeb128(u64) },
.def_cfa_offset_sf => .{ .def_cfa_offset_sf = try reader.takeLeb128(i64) },
.def_cfa_expression => .{ .def_cfa_expr = try reader.takeLeb128(usize) },
_ => switch (@backingInt(inst.low.extended)) {
0x1C...0x3F => return error.UnimplementedUserOpcode,
else => return error.InvalidOpcode,
},
},
};
}