pub fn readOperand(reader: *std.Io.Reader, opcode: u8, context: Context) !?Operand {
return switch (opcode) {
OP.addr => generic(try reader.takeInt(addr_type, options.endian)),
OP.call_ref => switch (context.format) {
.@"32" => generic(try reader.takeInt(u32, options.endian)),
.@"64" => generic(try reader.takeInt(u64, options.endian)),
},
OP.const1u,
OP.pick,
=> generic(try reader.takeByte()),
OP.deref_size,
OP.xderef_size,
=> .{ .type_size = try reader.takeByte() },
OP.const1s => generic(try reader.takeByteSigned()),
OP.const2u,
OP.call2,
=> generic(try reader.takeInt(u16, options.endian)),
OP.call4 => generic(try reader.takeInt(u32, options.endian)),
OP.const2s => generic(try reader.takeInt(i16, options.endian)),
OP.bra,
OP.skip,
=> .{ .branch_offset = try reader.takeInt(i16, options.endian) },
OP.const4u => generic(try reader.takeInt(u32, options.endian)),
OP.const4s => generic(try reader.takeInt(i32, options.endian)),
OP.const8u => generic(try reader.takeInt(u64, options.endian)),
OP.const8s => generic(try reader.takeInt(i64, options.endian)),
OP.constu,
OP.plus_uconst,
OP.addrx,
OP.constx,
OP.convert,
OP.reinterpret,
=> generic(try reader.takeLeb128(u64)),
OP.consts,
OP.fbreg,
=> generic(try reader.takeLeb128(i64)),
OP.lit0...OP.lit31 => |n| generic(n - OP.lit0),
OP.reg0...OP.reg31 => |n| .{ .register = n - OP.reg0 },
OP.breg0...OP.breg31 => |n| .{ .base_register = .{
.base_register = n - OP.breg0,
.offset = try reader.takeLeb128(i64),
} },
OP.regx => .{ .register = try reader.takeLeb128(u8) },
OP.bregx => blk: {
const base_register = try reader.takeLeb128(u8);
const offset = try reader.takeLeb128(i64);
break :blk .{ .base_register = .{
.base_register = base_register,
.offset = offset,
} };
},
OP.regval_type => blk: {
const register = try reader.takeLeb128(u8);
const type_offset = try reader.takeLeb128(addr_type);
break :blk .{ .register_type = .{
.register = register,
.type_offset = type_offset,
} };
},
OP.piece => .{
.composite_location = .{
.size = try reader.takeLeb128(u8),
.offset = 0,
},
},
OP.bit_piece => blk: {
const size = try reader.takeLeb128(u8);
const offset = try reader.takeLeb128(i64);
break :blk .{ .composite_location = .{
.size = size,
.offset = offset,
} };
},
OP.implicit_value, OP.entry_value => blk: {
const size = try reader.takeLeb128(u8);
const block = try reader.take(size);
break :blk .{ .block = block };
},
OP.const_type => blk: {
const type_offset = try reader.takeLeb128(addr_type);
const size = try reader.takeByte();
const value_bytes = try reader.take(size);
break :blk .{ .const_type = .{
.type_offset = type_offset,
.value_bytes = value_bytes,
} };
},
OP.deref_type,
OP.xderef_type,
=> .{
.deref_type = .{
.size = try reader.takeByte(),
.type_offset = try reader.takeLeb128(addr_type),
},
},
OP.lo_user...OP.hi_user => return error.UnimplementedUserOpcode,
else => null,
};
}