def drop_op(config: Configuration) -> None: """ Logic functin for the DROP opcode. """ if config.enable_logic_fn_logging: logger.debug("%s()", config.current_instruction.opcode.text) config.pop_operand()
def if_op(config: Configuration) -> None: """ Logic function for the IF opcode """ instruction = cast(If, config.current_instruction) if config.enable_logic_fn_logging: logger.debug("%s()", instruction.opcode.text) value = config.pop_operand() arity = len(instruction.result_type) if value: label = Label( arity=arity, instructions=instruction.instructions, is_loop=False, ) else: label = Label( arity=arity, instructions=instruction.else_instructions, is_loop=False, ) config.push_label(label)
def store_op(config: Configuration) -> None: """ Logic function for the various *STORE* memory opcodes. """ instruction = cast(MemoryOp, config.current_instruction) if config.enable_logic_fn_logging: logger.debug("%s()", instruction.opcode.text) memarg = instruction.memarg memory_address = config.frame_module.memory_addrs[0] mem = config.store.mems[memory_address] value = config.pop_operand() base_offset = config.pop_u32() memory_location = numpy.uint32(base_offset + memarg.offset) # TODO: update this section to use the `ValType.pack_bytes` API if instruction.valtype.is_integer_type: wrapped_value = instruction.memory_bit_size.wrap_type(value) encoded_value = wrapped_value.tobytes() elif instruction.valtype.is_float_type: encoded_value = value.tobytes() else: raise Exception("Invariant") assert len(encoded_value) == instruction.memory_bit_size.value // 8 mem.write(memory_location, encoded_value)
def set_local_op(config: Configuration) -> None: """ Logic functin for the SET_LOCAL opcode. """ instruction = cast(LocalOp, config.current_instruction) if config.enable_logic_fn_logging: logger.debug("%s()", instruction.opcode.text) value = config.pop_operand() config.frame_locals[instruction.local_idx] = value
def _setup_call(config: Configuration, function_address: FunctionAddress) -> None: """ Helper function used when entering a new frame during execution. """ function = config.store.funcs[function_address] function_args = tuple( reversed( [config.pop_operand() for _ in range(len(function.type.params))])) _setup_function_invocation(config, function_address, function_args)
def br_if_op(config: Configuration) -> None: """ Logic function for the BR_IF opcode """ if config.enable_logic_fn_logging: logger.debug("%s()", config.current_instruction.opcode.text) value = config.pop_operand() if value: instruction = cast(BrIf, config.current_instruction) _br(config, instruction.label_idx)
def ieqz_op(config: Configuration) -> None: """ Common logic function for the integer EQZ opcodes """ value = config.pop_operand() if config.enable_logic_fn_logging: logger.debug("%s(%s)", config.current_instruction.opcode.text, value) if value == 0: config.push_operand(constants.U32_ONE) else: config.push_operand(constants.U32_ZERO)
def set_global_op(config: Configuration) -> None: """ Logic functin for the SET_GLOBAL opcode. """ instruction = cast(GlobalOp, config.current_instruction) if config.enable_logic_fn_logging: logger.debug("%s()", instruction.opcode.text) global_address = config.frame_module.global_addrs[instruction.global_idx] global_ = config.store.globals[global_address] if global_.mut is not Mutability.var: raise Exception("Attempt to set immutable global") value = config.pop_operand() config.store.globals[global_address] = GlobalInstance(global_.valtype, value, global_.mut)
def _return_from_function(config: Configuration) -> None: """ Helper function for when the control flow for a frame exits. """ valn = tuple(config.pop_operand() for _ in range(config.frame_arity)) # discard all of the current labels before popping the frame. while config.has_active_label: config.pop_label() config.pop_frame() if config.has_active_frame: config.extend_operands(valn) else: config.extend_results(valn)
def ipopcnt_op(config: Configuration) -> None: """ Common logic function for the integer POPCNT opcodes """ instruction = cast(UnOp, config.current_instruction) value = config.pop_operand() if config.enable_logic_fn_logging: logger.debug("%s(%s)", instruction.opcode.text, value) if value == 0: config.push_operand(instruction.valtype.zero) else: config.push_operand( instruction.valtype.value(bin(int(value)).count('1')))
def br_table_op(config: Configuration) -> None: """ Logic function for the BR_TABLE opcode """ instruction = cast(BrTable, config.current_instruction) if config.enable_logic_fn_logging: logger.debug("%s()", instruction.opcode.text) label_indices = instruction.label_indices default_label_idx = instruction.default_idx idx = config.pop_operand() if idx < len(label_indices): label_idx = label_indices[int(idx)] _br(config, label_idx) else: _br(config, default_label_idx)
def _br(config: Configuration, label_idx: LabelIdx) -> None: """ Helper function for the BR, BR_IF, and BR_TABLE opcodes. """ label = config.get_label_by_idx(label_idx) # take any return values off of the stack before popping labels valn = tuple(config.pop_operand() for _ in range(label.arity)) if label.is_loop: # For loops we keep the label which represents the loop on the stack # since the continuation of a loop is beginning back at the beginning # of the loop itself. for _ in range(label_idx): config.pop_label() config.seek_to_instruction_idx(0) else: for _ in range(label_idx + 1): config.pop_label() # put return values back on the stack. config.extend_operands(valn)