def finalize_optimized_intructions(self): instructions = sorted(self.optimized_instructions[-1].keys()) load_lower = self.load[L_L_B] if self.load[ L_L_B] is not None else self.load[R_L_B] load_inst = set_opcode( self.optimized_instructions[-1][instructions[0]][0], LOAD48) load_inst = modify_offset(load_inst, load_lower) unpkd = unpack_instruction(load_inst) load_inst_str = "r" + str( get_output(unpkd)) + " = *(uint48 *) (r" + str( get_inputs(unpkd)[0]) + " + " + str(unpkd["offset"]) + ")" reg = get_output(unpkd) self.optimized_instructions[-1][instructions[0]] = (load_inst, load_inst_str) for instr_id in instructions[1:]: unpkd = unpack_instruction( self.optimized_instructions[-1][instr_id][0]) if is_store(unpkd) and get_inputs(unpkd)[0] == reg: store_inst = set_opcode( self.optimized_instructions[-1][instr_id][0], STORE48) store_lower = self.store[L_L_B] if self.store[ L_L_B] is not None else self.store[R_L_B] store_inst = modify_offset(store_inst, store_lower) store_inst_str = "*(uint48 *) (r" + str( get_inputs(unpkd)[1]) + " + " + str( unpkd["offset"]) + ") = r" + str(get_inputs(unpkd)[0]) self.optimized_instructions[-1][instr_id] = (store_inst, store_inst_str) else: self.optimized_instructions[-1][instr_id] = (NOP, "NOP")
def after_store(self): unpkd = unpack_instruction(self.instruction) if store_to_size(unpkd) is None: assert False, ("invalid call of after_load, !illegal transition!") offset = unpkd["offset"] if self.size is not None: assert self.size == int(store_to_size(unpkd) / 8) if self.direction == PENDING and self.store[L_L_B] is None and self.store[R_L_B] is None: # first load-store pair self.store[L_L_B], self.store[L_U_B] = offset, offset + self.size elif self.direction == FORWARD: if offset == self.store[L_U_B]: self.store[L_U_B] += self.size elif offset == self.store[R_U_B]: self.store[R_U_B] += self.size elif offset == (self.store[R_U_B] - int(6 / self.size)): self.store[L_L_B], self.store[L_U_B] = offset, offset + self.size else: assert False, ("invalid call of after_store, !illegal transition!") elif self.direction == BACKWARD: if (offset + self.size) == self.store[L_L_B]: self.store[L_L_B] -= self.size elif (offset + self.size) == self.store[R_L_B]: self.store[R_L_B] -= self.size elif (offset + self.size) == (self.store[L_U_B] + (int(6 / self.size) - self.n) * self.size): self.store[R_L_B], self.store[R_U_B] = offset, offset + self.size else: assert False, ("invalid call of after_store, !illegal transition!") self.n += 1 self.optimized_instructions[-1][self.instruction_id] = (self.instruction, "NOP")
def is_contiguous_store(self): unpkd = unpack_instruction(self.instruction) if not is_store(unpkd): return False offset = unpkd["offset"] self.size = int(store_to_size(unpkd) / 8) if get_inputs(unpkd)[0] not in self.regs: return False if self.direction is None: return True if self.direction == PENDING and (offset + self.size == self.store[L_L_B] or self.store[L_U_B] == offset): return True elif self.direction == FORWARD and ( offset == self.store[R_U_B] or offset == self.store[L_U_B] or (not self.is_load_completed() and offset == (self.store[R_U_B] - int(6 / self.size)))): return True elif self.direction == BACKWARD and ( (offset + self.size) == self.store[L_L_B] or (offset + self.size) == self.store[R_L_B] or (not self.is_load_completed() and offset + self.size == (self.store[L_U_B] + (int(6 / self.size) - self.n * self.size)))): return True return False
def finalize_optimized_intructions(self): instructions = sorted(self.optimized_instructions[-1].keys()) load_inst = set_opcode(self.optimized_instructions[-1][instructions[0]][0], LOAD48) load_inst = modify_offset(load_inst, self.load[L_L_B]) unpkd = unpack_instruction(load_inst) load_inst_str = "r"+str(get_output(unpkd))+" = *(uint48 *) (r"+str(get_inputs(unpkd)[0])+" + "+str(unpkd["offset"])+")" store_inst = set_opcode(self.optimized_instructions[-1][instructions[1]][0], STORE48) store_inst = modify_offset(store_inst, self.store[L_L_B]) unpkd = unpack_instruction(store_inst) store_inst_str = "*(uint48 *) (r"+str(get_inputs(unpkd)[1])+" + "+str(unpkd["offset"])+") = r"+str(get_inputs(unpkd)[0]) self.optimized_instructions[-1][instructions[0]] = (load_inst, load_inst_str) self.optimized_instructions[-1][instructions[1]] = (store_inst, store_inst_str) for key in instructions[2:]: self.optimized_instructions[-1][key] = (NOP, "NOP")
def after_store(self): unpkd = unpack_instruction(self.instruction) if store_to_size(unpkd) is None: assert False, ("invalid call of after_load, !illegal transition!") offset = unpkd["offset"] if self.size is not None: assert self.size == int(store_to_size(unpkd) / 8) else: self.size = int(store_to_size(unpkd) / 8) if self.direction is None: # first store self.direction = PENDING self.store[L_L_B], self.store[L_U_B] = offset, offset + self.size elif self.direction == PENDING: # second store if self.store[L_L_B] == offset + self.size: # backward self.direction = BACKWARD self.store[L_L_B] -= self.size elif self.store[L_U_B] == offset: # forward self.direction = FORWARD self.store[R_L_B], self.store[R_U_B] = self.store[ L_L_B], offset + self.size self.store[L_L_B], self.store[L_U_B] = None, None else: assert False, ( "invalid call of after_load, !illegal transition!") elif self.direction == FORWARD: if offset == self.store[L_U_B]: self.store[L_U_B] += self.size elif offset == self.store[R_U_B]: self.store[R_U_B] += self.size elif offset == (self.store[R_U_B] - int(6 / self.size)): self.store[L_L_B], self.store[ L_U_B] = offset, offset + self.size else: assert False, ( "invalid call of after_store, !illegal transition!") elif self.direction == BACKWARD: if (offset + self.size) == self.store[L_L_B]: self.store[L_L_B] -= self.size elif (offset + self.size) == self.store[R_L_B]: self.store[R_L_B] -= self.size elif (offset + self.size) == (self.store[L_U_B] + (int(6 / self.size) - self.n) * self.size): self.store[R_L_B], self.store[ R_U_B] = offset, offset + self.size else: assert False, ( "invalid call of after_store, !illegal transition!") self.optimized_instructions[-1][self.instruction_id] = ( self.instruction, "NOP") self.mem_area_to_reg[offset] = get_inputs(unpkd)[0] self.n += 1
def is_access_on_regs(self): unpkd = unpack_instruction(self.instruction) for inp in get_inputs(unpkd): if inp in self.regs: return True if get_output(unpkd) is not None and get_output(unpkd) in self.regs: return True return False
def is_a_store(self): return is_a_store48(unpack_instruction(self.instruction))
def is_a_load(self): return is_a_load48(unpack_instruction(self.instruction))
def enter_movi0(self): unpkd = unpack_instruction(self.instruction) self.register = get_output(unpkd) self.optimized_instructions[-1][self.instruction_id] = (NOP, "NOP")
def after_accessed(self): self.accessed_data.add(unpack_instruction(self.instruction)["offset"])
def is_accessed(self): unpkd = unpack_instruction(self.instruction) return (is_load(unpkd) and get_output(unpkd) == 10) or \ (is_store(unpkd) and get_inputs(unpkd)[1] == 10) # r10 contains stack
def is_write_to_reg(self): out = get_output(unpack_instruction(self.instruction)) return out is not None and out == self.register
def is_store_from_zeroed_reg_to_stack(self): unpkd = unpack_instruction(self.instruction) return is_store(unpkd) and unpkd[ "offset"] not in self.accessed_data and get_inputs( unpkd)[0] == self.register and get_inputs( unpkd)[1] == 10 # r10 contains stack
def is_movi_to_zero(self): unpkd = unpack_instruction(self.instruction) if is_mov_imm(unpkd) and unpkd["immediate"] == 0: return True else: return False