9#include <unordered_map>
31 return OPERAND_TYPE_SIZE_BYTES;
205 return WireOpCode_WIRE_FORMAT;
213 return get_wire_opcode_wire_format();
218 return get_operand_type_size_bytes();
225bool is_wire_opcode_valid(uint8_t w_opcode)
234 const auto bytecode_length =
bytecode.size();
236 if (pos >= bytecode_length) {
237 std::string error_msg =
format(
"Invalid program counter ", pos,
", max is ", bytecode_length - 1);
242 const uint8_t opcode_byte =
bytecode[pos];
244 if (!is_wire_opcode_valid(opcode_byte)) {
245 std::string error_msg =
format(
"Opcode ",
246 static_cast<uint32_t
>(opcode_byte),
249 ") value is not in the range of valid opcodes (at PC ",
256 const auto opcode =
static_cast<WireOpCode>(opcode_byte);
257 const auto iter = get_wire_opcode_wire_format().find(opcode);
258 assert(iter != get_wire_opcode_wire_format().end());
259 const auto& inst_format = iter->second;
265 if (pos + instruction_size > bytecode_length) {
266 std::string error_msg =
format(
"Instruction at PC ",
268 " does not fit in bytecode (instruction size: ",
271 bytecode_length - pos,
279 uint16_t indirect = 0;
282 const auto operand_size = get_operand_type_size_bytes().at(op_type);
283 assert(pos + operand_size <= bytecode_length);
289 operands.emplace_back(Operand::from<uint8_t>(
bytecode[pos]));
297 uint16_t operand_u16 = 0;
298 uint8_t
const* pos_ptr = &
bytecode[pos];
300 indirect = operand_u16;
304 uint16_t operand_u16 = 0;
305 uint8_t
const* pos_ptr = &
bytecode[pos];
307 operands.emplace_back(Operand::from<uint16_t>(operand_u16));
311 uint32_t operand_u32 = 0;
312 uint8_t
const* pos_ptr = &
bytecode[pos];
314 operands.emplace_back(Operand::from<uint32_t>(operand_u32));
318 uint64_t operand_u64 = 0;
319 uint8_t
const* pos_ptr = &
bytecode[pos];
321 operands.emplace_back(Operand::from<uint64_t>(operand_u64));
326 uint8_t
const* pos_ptr = &
bytecode[pos];
328 operands.emplace_back(Operand::from<uint128_t>(operand_u128));
333 uint8_t
const* pos_ptr = &
bytecode[pos];
334 read(pos_ptr, operand_ff);
335 operands.emplace_back(Operand::from<FF>(operand_ff));
343 .indirect = indirect,
350 std::ostringstream oss;
352 for (
size_t operand_pos = 0; operand_pos <
operands.size(); ++operand_pos) {
353 const auto& operand =
operands[operand_pos];
380 std::vector<uint8_t> output;
382 output.emplace_back(
static_cast<uint8_t
>(
opcode));
383 size_t operand_pos = 0;
385 for (
const auto& operand_type : get_wire_opcode_wire_format().at(
opcode)) {
386 switch (operand_type) {
388 output.emplace_back(
static_cast<uint8_t
>(
indirect));
392 output.insert(output.end(),
398 output.emplace_back(
operands.at(operand_pos++).as<uint8_t>());
433 vinfo(
"Instruction does not contain a valid wire opcode.");
441 for (
size_t i = 0; i < wire_format.size(); i++) {
448 vinfo(
"Instruction operands size is too small. Tag position: ",
461 vinfo(
"Instruction tag operand at position: ",
471 }
catch (
const std::runtime_error&) {
472 vinfo(
"Instruction operand at position: ",
474 " is longer than a byte.",
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
std::string format(Args... args)
const std::unordered_map< OperandType, uint32_t > & get_operand_type_sizes()
const std::unordered_map< WireOpCode, std::vector< OperandType > > & get_instruction_wire_formats()
const std::vector< OperandType > external_call_format
bool check_tag(const Instruction &instruction)
Check whether the instruction must have a tag operand and whether the operand value is in the value t...
@ INSTRUCTION_OUT_OF_RANGE
const std::vector< OperandType > three_operand_format16
Instruction deserialize_instruction(std::span< const uint8_t > bytecode, size_t pos)
Parsing of an instruction in the supplied bytecode at byte position pos. This checks that the WireOpC...
const std::vector< OperandType > kernel_input_operand_format
const std::vector< OperandType > three_operand_format8
std::string to_hex(T value)
bool is_operand_relative(uint16_t indirect_flag, size_t operand_index)
const std::unordered_map< WireOpCode, WireInstructionSpec > & get_wire_instruction_spec()
bool is_operand_indirect(uint16_t indirect_flag, size_t operand_index)
void read(uint8_t const *&it, Chonk::VerificationKey &vk)
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by MSGPACK_FIEL...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
std::vector< uint8_t > to_buffer(T const &value)
unsigned __int128 uint128_t
std::string to_string() const
std::vector< uint8_t > serialize() const
std::vector< Operand > operands
size_t size_in_bytes() const
ExecutionOpCode get_exec_opcode() const