Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
def test_locations():
    code_with_marks = """\
 [ap ] = [ fp + 2];  ap ++
 ^***********************^
 ^***************^
 ^***^
  ^^
         ^*******^
           ^****^
           ^^
                ^
"""

    lines = code_with_marks.splitlines()
    code, marks = lines[0], lines[1:]
    expr = parse_instruction(code)
    exprs = [
        expr,
        expr.body,
        expr.body.a,
        expr.body.a.addr,
        expr.body.b,
        expr.body.b.addr,
        expr.body.b.addr.a,
        expr.body.b.addr.b,
    ]
    assert len(exprs) == len(marks)
    for expr, mark in zip(exprs, marks):
        assert get_location_marks(code, expr.location) == code + '\n' + mark
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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
Exemplo n.º 8
0
def test_instruction():
    # AssertEq.
    expr = parse_instruction('[ap] = [fp]; ap++')
    assert expr == \
        InstructionAst(
            body=AssertEqInstruction(
                a=ExprDeref(
                    addr=ExprReg(reg=Register.AP)),
                b=ExprDeref(
                    addr=ExprReg(reg=Register.FP))),
            inc_ap=True)
    assert expr.format() == '[ap] = [fp]; ap++'
    assert parse_instruction(
        '[ap+5] = [fp]+[ap] - 5').format() == '[ap + 5] = [fp] + [ap] - 5'
    assert parse_instruction('[ap+5]+3= [fp]*7;ap  ++ ').format() == \
        '[ap + 5] + 3 = [fp] * 7; ap++'

    # Jump.
    expr = parse_instruction('jmp rel [ap] + x; ap++')
    assert expr == \
        InstructionAst(
            body=JumpInstruction(
                val=ExprOperator(
                    a=ExprDeref(addr=ExprReg(reg=Register.AP)),
                    op='+',
                    b=ExprIdentifier(name='x')),
                relative=True),
            inc_ap=True)
    assert expr.format() == 'jmp rel [ap] + x; ap++'
    assert parse_instruction(' jmp   abs[ap]+x').format() == 'jmp abs [ap] + x'
    # Make sure the following are not OK.
    with pytest.raises(ParserError):
        parse_instruction('jmp abs')
    with pytest.raises(ParserError):
        parse_instruction('jmpabs[ap]')

    # JumpToLabel.
    expr = parse_instruction('jmp label')
    assert expr == \
        InstructionAst(
            body=JumpToLabelInstruction(
                label=ExprIdentifier(name='label'),
                condition=None),
            inc_ap=False)
    assert expr.format() == 'jmp label'
    # Make sure the following are not OK.
    with pytest.raises(ParserError):
        parse_instruction('jmp [fp]')
    with pytest.raises(ParserError):
        parse_instruction('jmp 7')

    # Jnz.
    expr = parse_instruction('jmp rel [ap] + x if [fp + 3] != 0')
    assert expr == \
        InstructionAst(
            body=JnzInstruction(
                jump_offset=ExprOperator(
                    a=ExprDeref(addr=ExprReg(reg=Register.AP)),
                    op='+',
                    b=ExprIdentifier(name='x')),
                condition=ExprDeref(
                    addr=ExprOperator(
                        a=ExprReg(reg=Register.FP),
                        op='+',
                        b=ExprConst(val=3)))),
            inc_ap=False)
    assert expr.format() == 'jmp rel [ap] + x if [fp + 3] != 0'
    assert parse_instruction(' jmp   rel 17  if[fp]!=0;ap++').format() == \
        'jmp rel 17 if [fp] != 0; ap++'
    # Make sure the following are not OK.
    with pytest.raises(ParserError):
        parse_instruction('jmprel 17 if x != 0')
    with pytest.raises(ParserError):
        parse_instruction('jmp 17 if x')
    with pytest.raises(ParserError, match='!= 0'):
        parse_instruction('jmp rel 17 if x != 2')
    with pytest.raises(ParserError):
        parse_instruction('jmp rel [fp] ifx != 0')

    # Jnz to label.
    expr = parse_instruction('jmp label if [fp] != 0')
    assert expr == \
        InstructionAst(
            body=JumpToLabelInstruction(
                label=ExprIdentifier('label'),
                condition=ExprDeref(addr=ExprReg(reg=Register.FP))),
            inc_ap=False)
    assert expr.format() == 'jmp label if [fp] != 0'
    # Make sure the following are not OK.
    with pytest.raises(ParserError):
        parse_instruction('jmp [fp] if [fp] != 0')
    with pytest.raises(ParserError):
        parse_instruction('jmp 7 if [fp] != 0')

    # Call abs.
    expr = parse_instruction('call abs [fp] + x')
    assert expr == \
        InstructionAst(
            body=CallInstruction(
                val=ExprOperator(
                    a=ExprDeref(addr=ExprReg(reg=Register.FP)),
                    op='+',
                    b=ExprIdentifier(name='x')),
                relative=False),
            inc_ap=False)
    assert expr.format() == 'call abs [fp] + x'
    assert parse_instruction(
        'call   abs   17;ap++').format() == 'call abs 17; ap++'
    # Make sure the following are not OK.
    with pytest.raises(ParserError):
        parse_instruction('call abs')
    with pytest.raises(ParserError):
        parse_instruction('callabs 7')

    # Call rel.
    expr = parse_instruction('call rel [ap] + x')
    assert expr == \
        InstructionAst(
            body=CallInstruction(
                val=ExprOperator(
                    a=ExprDeref(addr=ExprReg(reg=Register.AP)),
                    op='+',
                    b=ExprIdentifier(name='x')),
                relative=True),
            inc_ap=False)
    assert expr.format() == 'call rel [ap] + x'
    assert parse_instruction(
        'call   rel   17;ap++').format() == 'call rel 17; ap++'
    # Make sure the following are not OK.
    with pytest.raises(ParserError):
        parse_instruction('call rel')
    with pytest.raises(ParserError):
        parse_instruction('callrel 7')

    # Call label.
    expr = parse_instruction('call label')
    assert expr == \
        InstructionAst(
            body=CallLabelInstruction(
                label=ExprIdentifier(name='label')),
            inc_ap=False)
    assert expr.format() == 'call label'
    assert parse_instruction(
        'call   label ;ap++').format() == 'call label; ap++'
    # Make sure the following are not OK.
    with pytest.raises(ParserError):
        parse_instruction('call [fp]')
    with pytest.raises(ParserError):
        parse_instruction('call 7')

    # Ret.
    expr = parse_instruction('ret')
    assert expr == \
        InstructionAst(
            body=RetInstruction(),
            inc_ap=False)
    assert expr.format() == 'ret'

    # AddAp.
    expr = parse_instruction('ap += [fp] + 2')
    assert expr == \
        InstructionAst(
            body=AddApInstruction(
                expr=ExprOperator(
                    a=ExprDeref(
                        addr=ExprReg(reg=Register.FP)),
                    op='+',
                    b=ExprConst(val=2))),
            inc_ap=False)
    assert expr.format() == 'ap += [fp] + 2'
    assert parse_instruction('ap  +=[ fp]+   2').format() == 'ap += [fp] + 2'
    assert parse_instruction(
        'ap  +=[ fp]+   2;ap ++').format() == 'ap += [fp] + 2; ap++'
Exemplo n.º 9
0
def parse_and_build(inst: str) -> Instruction:
    """
    Parses the given instruction and builds the Instruction instance.
    """
    return build_instruction(parse_instruction(inst))