~nch/python-compiler

023e205398040e2595bda27a9610639c60296772 — nc 1 year, 7 months ago 9e372ee
add CMP
3 files changed, 11 insertions(+), 2 deletions(-)

M README.md
M compiler.py
M test_compiler.py
M README.md => README.md +1 -1
@@ 11,7 11,7 @@ for implementing more interesting compiler language features quickly.
* Parser [in progress]
* Type checker/semantic check pass [TODO]
* ANF [in progress]
* Code gen [TODO]
* Code gen [in progress]
* Optimization passes [TODO]
    * Inlining
    * Vectorizing

M compiler.py => compiler.py +5 -1
@@ 666,6 666,10 @@ ops = [
        ## CONTROL FLOW
        (('ret',), lambda _: '\xc3'),

        ## COMPARISONS
        (('cmp', reg32_p, or_p(reg32_p, mem_p(reg32_p))), lambda _, r1, x: b'\x39' + modrm(r1, x)),
        (('cmp', reg64_p, or_p(reg64_p, mem_p(reg64_p))), lambda _, r1, x: b'\x48\x39' + modrm(r1, x)),

        ## MOVS
        # reg -> reg moves get encoded with 0x89 because this is what NASM does. NASM gets used for testing
        # so I did it to be consistent, but someone did a bit more of an analysis here:


@@ 700,7 704,7 @@ def emit(*args):
                break
        else:
            return encoder_f(*args)
    assert False, f"unknown encoding for {args}"
    assert False, f"unknown opcode for {args}"

@singledispatch
def code_gen(node, ctx, g):

M test_compiler.py => test_compiler.py +5 -0
@@ 179,6 179,7 @@ else:
            return f.read()

    def test_emit(self):
        # moves
        self.assertEqual(emit('rax <- rcx'), self.nasm_assemble(b'mov rax, rcx'))
        self.assertEqual(emit('rax <-', 8),  self.nasm_assemble(b'mov rax, 8'))
        self.assertEqual(emit('rax <-', ('rcx', 8)), self.nasm_assemble(b'mov rax, [rcx+8]'))


@@ 188,6 189,10 @@ else:
        self.assertEqual(emit('rcx <- rax'), b'\x48\x89\xc1')
        self.assertEqual(emit('ecx <- eax'), b'\x89\xc1')

        # cmps
        self.assertEqual(emit('cmp eax ecx'), self.nasm_assemble(b'cmp ecx, eax'))
        self.assertEqual(emit('cmp rax rcx'), self.nasm_assemble(b'cmp rcx, rax'))

    '''
    def test_codegen(self):
        t = If(FunctionCall(FunctionCall('b', ()), 2), Return(1), Return(2))