Source
pub fn read(
stream: *std.io.FixedBufferStream([]const u8),
addr_size_bytes: u8,
endian: std.builtin.Endian,
) !Instruction {
const reader = stream.reader();
switch (try reader.readByte()) {
Opcode.lo_inline...Opcode.hi_inline => |opcode| {
const e: Opcode = @enumFromInt(opcode & 0b11000000);
const value: u6 = @intCast(opcode & 0b111111);
return switch (e) {
.advance_loc => .{
.advance_loc = .{ .delta = value },
},
.offset => .{
.offset = .{
.register = value,
.offset = try leb.readUleb128(u64, reader),
},
},
.restore => .{
.restore = .{ .register = value },
},
else => unreachable,
};
},
Opcode.lo_reserved...Opcode.hi_reserved => |opcode| {
const e: Opcode = @enumFromInt(opcode);
return switch (e) {
.advance_loc,
.offset,
.restore,
=> unreachable,
.nop => .{ .nop = {} },
.set_loc => .{
.set_loc = .{
.address = switch (addr_size_bytes) {
2 => try reader.readInt(u16, endian),
4 => try reader.readInt(u32, endian),
8 => try reader.readInt(u64, endian),
else => return error.InvalidAddrSize,
},
},
},
.advance_loc1 => .{
.advance_loc1 = .{ .delta = try reader.readByte() },
},
.advance_loc2 => .{
.advance_loc2 = .{ .delta = try reader.readInt(u16, endian) },
},
.advance_loc4 => .{
.advance_loc4 = .{ .delta = try reader.readInt(u32, endian) },
},
.offset_extended => .{
.offset_extended = .{
.register = try leb.readUleb128(u8, reader),
.offset = try leb.readUleb128(u64, reader),
},
},
.restore_extended => .{
.restore_extended = .{
.register = try leb.readUleb128(u8, reader),
},
},
.undefined => .{
.undefined = .{
.register = try leb.readUleb128(u8, reader),
},
},
.same_value => .{
.same_value = .{
.register = try leb.readUleb128(u8, reader),
},
},
.register => .{
.register = .{
.register = try leb.readUleb128(u8, reader),
.target_register = try leb.readUleb128(u8, reader),
},
},
.remember_state => .{ .remember_state = {} },
.restore_state => .{ .restore_state = {} },
.def_cfa => .{
.def_cfa = .{
.register = try leb.readUleb128(u8, reader),
.offset = try leb.readUleb128(u64, reader),
},
},
.def_cfa_register => .{
.def_cfa_register = .{
.register = try leb.readUleb128(u8, reader),
},
},
.def_cfa_offset => .{
.def_cfa_offset = .{
.offset = try leb.readUleb128(u64, reader),
},
},
.def_cfa_expression => .{
.def_cfa_expression = .{
.block = try readBlock(stream),
},
},
.expression => .{
.expression = .{
.register = try leb.readUleb128(u8, reader),
.block = try readBlock(stream),
},
},
.offset_extended_sf => .{
.offset_extended_sf = .{
.register = try leb.readUleb128(u8, reader),
.offset = try leb.readIleb128(i64, reader),
},
},
.def_cfa_sf => .{
.def_cfa_sf = .{
.register = try leb.readUleb128(u8, reader),
.offset = try leb.readIleb128(i64, reader),
},
},
.def_cfa_offset_sf => .{
.def_cfa_offset_sf = .{
.offset = try leb.readIleb128(i64, reader),
},
},
.val_offset => .{
.val_offset = .{
.register = try leb.readUleb128(u8, reader),
.offset = try leb.readUleb128(u64, reader),
},
},
.val_offset_sf => .{
.val_offset_sf = .{
.register = try leb.readUleb128(u8, reader),
.offset = try leb.readIleb128(i64, reader),
},
},
.val_expression => .{
.val_expression = .{
.register = try leb.readUleb128(u8, reader),
.block = try readBlock(stream),
},
},
};
},
Opcode.lo_user...Opcode.hi_user => return error.UnimplementedUserOpcode,
else => return error.InvalidOpcode,
}
}