def test_assert_eq(): encoded = [0x480680017fff8000, 1] instruction = Instruction( off0=0, off1=-1, off2=1, imm=1, dst_register=Register.AP, op0_register=Register.FP, op1_addr=Instruction.Op1Addr.IMM, res=Instruction.Res.OP1, pc_update=Instruction.PcUpdate.REGULAR, ap_update=Instruction.ApUpdate.ADD1, fp_update=Instruction.FpUpdate.REGULAR, opcode=Instruction.Opcode.ASSERT_EQ, ) assert build_instruction( parse_instruction('[ap] = 1; ap++')) == instruction assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction # Remove "ap++". instruction = dataclasses.replace(instruction, ap_update=Instruction.ApUpdate.REGULAR) encoded = [0x400680017fff8000, 1] assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction assert is_call_instruction(*encoded) is False
def test_jmp(): encoded = [0x0129800080027fff] instruction = Instruction( off0=-1, off1=2, off2=0, imm=None, dst_register=Register.FP, op0_register=Register.AP, op1_addr=Instruction.Op1Addr.FP, res=Instruction.Res.ADD, pc_update=Instruction.PcUpdate.JUMP_REL, ap_update=Instruction.ApUpdate.REGULAR, fp_update=Instruction.FpUpdate.REGULAR, opcode=Instruction.Opcode.NOP, ) assert build_instruction( parse_instruction('jmp rel [ap + 2] + [fp]')) == instruction assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction # Change to jmp abs. instruction = dataclasses.replace(instruction, pc_update=Instruction.PcUpdate.JUMP) encoded = [0x00a9800080027fff] assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction assert is_call_instruction(encoded[0], None) is False
def assemble(preprocessed_program: PreprocessedProgram, main_scope: ScopedName = ScopedName(), add_debug_info: bool = False, file_contents_for_debug_info: Dict[str, str] = {}) -> Program: data: List[int] = [] hints: Dict[int, List[CairoHint]] = {} debug_info = DebugInfo(instruction_locations={}, file_contents=file_contents_for_debug_info) \ if add_debug_info else None for inst in preprocessed_program.instructions: for hint, hint_flow_tracking_data in inst.hints: hints.setdefault(len(data), []).append( CairoHint(code=hint.hint_code, accessible_scopes=inst.accessible_scopes, flow_tracking_data=hint_flow_tracking_data)) if debug_info is not None and inst.instruction.location is not None: hint_locations: List[Optional[HintLocation]] = [] for hint, _ in inst.hints: if hint.location is None: hint_locations.append(None) else: hint_locations.append( HintLocation( location=hint.location, n_prefix_newlines=hint.hint.n_prefix_newlines, )) debug_info.instruction_locations[len(data)] = \ InstructionLocation( inst=inst.instruction.location, hints=hint_locations, accessible_scopes=inst.accessible_scopes, flow_tracking_data=inst.flow_tracking_data) data += [ word for word in encode_instruction(build_instruction(inst.instruction), prime=preprocessed_program.prime) ] if debug_info is not None: debug_info.add_autogen_file_contents() return Program(prime=preprocessed_program.prime, data=data, hints=hints, main_scope=main_scope, identifiers=preprocessed_program.identifiers, builtins=preprocessed_program.builtins, reference_manager=preprocessed_program.reference_manager, debug_info=debug_info)
def test_addap(): encoded = [0x40780017fff7fff, 123] instruction = Instruction(off0=-1, off1=-1, off2=1, imm=123, dst_register=Register.FP, op0_register=Register.FP, op1_addr=Instruction.Op1Addr.IMM, res=Instruction.Res.OP1, pc_update=Instruction.PcUpdate.REGULAR, ap_update=Instruction.ApUpdate.ADD, fp_update=Instruction.FpUpdate.REGULAR, opcode=Instruction.Opcode.NOP) assert build_instruction(parse_instruction('ap += 123')) == instruction assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction assert is_call_instruction(*encoded) is False
def assemble(preprocessed_program: PreprocessedProgram, main_scope: ScopedName = ScopedName(), add_debug_info: bool = False, file_contents_for_debug_info: Dict[str, str] = {}) -> Program: data: List[int] = [] hints: Dict[int, CairoHint] = {} debug_info = DebugInfo(instruction_locations={}, file_contents=file_contents_for_debug_info) \ if add_debug_info else None for inst in preprocessed_program.instructions: if inst.hint: hints[len(data)] = CairoHint( code=inst.hint.hint_code, accessible_scopes=inst.accessible_scopes, flow_tracking_data=inst.flow_tracking_data) if debug_info is not None and inst.instruction.location is not None: hint_location = None if inst.hint is not None and inst.hint.location is not None: hint_location = HintLocation( location=inst.hint.location, n_prefix_newlines=inst.hint.n_prefix_newlines, ) debug_info.instruction_locations[len(data)] = \ InstructionLocation( inst=inst.instruction.location, hint=hint_location, accessible_scopes=inst.accessible_scopes, flow_tracking_data=inst.flow_tracking_data) data += [ word for word in encode_instruction(build_instruction(inst.instruction), prime=preprocessed_program.prime) ] return Program(prime=preprocessed_program.prime, data=data, hints=hints, main_scope=main_scope, identifiers=preprocessed_program.identifiers, builtins=preprocessed_program.builtins, reference_manager=preprocessed_program.reference_manager, debug_info=debug_info)
def test_call(): encoded = [0x1104800180018000, 1234] instruction = Instruction( off0=0, off1=1, off2=1, imm=1234, dst_register=Register.AP, op0_register=Register.AP, op1_addr=Instruction.Op1Addr.IMM, res=Instruction.Res.OP1, pc_update=Instruction.PcUpdate.JUMP_REL, ap_update=Instruction.ApUpdate.ADD2, fp_update=Instruction.FpUpdate.AP_PLUS2, opcode=Instruction.Opcode.CALL, ) assert build_instruction(parse_instruction('call rel 1234')) == instruction assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction assert is_call_instruction(*encoded) is True
def test_ret(): encoded = [0x208b7fff7fff7ffe] instruction = Instruction( off0=-2, off1=-1, off2=-1, imm=None, dst_register=Register.FP, op0_register=Register.FP, op1_addr=Instruction.Op1Addr.FP, res=Instruction.Res.OP1, pc_update=Instruction.PcUpdate.JUMP, ap_update=Instruction.ApUpdate.REGULAR, fp_update=Instruction.FpUpdate.DST, opcode=Instruction.Opcode.RET, ) assert build_instruction(parse_instruction('ret')) == instruction assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction assert is_call_instruction(encoded[0], None) is False
def test_jnz(): encoded = [0x020a7ff07fff8003] instruction = Instruction( off0=3, off1=-1, off2=-16, imm=None, dst_register=Register.AP, op0_register=Register.FP, op1_addr=Instruction.Op1Addr.FP, res=Instruction.Res.UNCONSTRAINED, pc_update=Instruction.PcUpdate.JNZ, ap_update=Instruction.ApUpdate.REGULAR, fp_update=Instruction.FpUpdate.REGULAR, opcode=Instruction.Opcode.NOP, ) assert build_instruction( parse_instruction('jmp rel [fp - 16] if [ap + 3] != 0')) == instruction assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction assert is_call_instruction(encoded[0], None) is False
def parse_and_build(inst: str) -> Instruction: """ Parses the given instruction and builds the Instruction instance. """ return build_instruction(parse_instruction(inst))