Skip to content

Commit

Permalink
#19 [asmik] rewrote asmik emit using tafka listener
Browse files Browse the repository at this point in the history
  • Loading branch information
vityaman committed Feb 9, 2024
1 parent 67e45c7 commit e1e9e6a
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 170 deletions.
21 changes: 20 additions & 1 deletion sleepy/asmik/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
from .emit import AsmikUnit, asmik_emit
from sleepy.asmik.argument import Integer, Register
from sleepy.asmik.data import IntegerData
from sleepy.asmik.instruction import (
Addi,
Addim,
Andb,
Brn,
Divi,
Hlt,
Instruction,
Load,
Muli,
Orb,
Remi,
Slti,
Stor,
Xorb,
)

from .unit import AsmikUnit
260 changes: 118 additions & 142 deletions sleepy/asmik/emit.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import override

import sleepy.tafka.representation as tafka
from sleepy.tafka import TafkaUnit
from sleepy.tafka.walker import TafkaWalker

from .argument import Immediate, Integer, Unassigned
from .argument import PhysicalRegister as PhysReg
Expand All @@ -25,7 +27,7 @@
from .memory import Memory


class AsmikEmiter:
class AsmikEmitListener(TafkaWalker.Listener):
def __init__(self) -> None:
self.virt_regs = (VirtReg(n) for n in range(10000))
self.memory = Memory()
Expand All @@ -36,139 +38,57 @@ def __init__(self) -> None:
self.block: tafka.Block
self.block_until: list[tafka.Block] = []

def emit_procedure(self, proc: tafka.Procedure) -> None:
@override
def enter_procedure(self, procedure: tafka.Procedure) -> None:
addr = self.memory.data_put(IntegerData(self.next_instr_addr))
self.resolved[repr(proc.const)] = addr

for i, param in enumerate(proc.parameters):
self.resolved[repr(procedure.const)] = addr
for i, param in enumerate(procedure.parameters):
param_reg = self.reg_var(param)
self.emit_i(mov(param_reg, PhysReg.arg(i + 1)))

self.emit_block(proc.entry)

def emit_block(self, block: tafka.Block) -> None:
if (
len(self.block_until) > 0
and self.block_until[-1].label == block.label
):
return
@override
def exit_procedure(self, procedure: tafka.Procedure) -> None:
pass

@override
def enter_block(self, block: tafka.Block) -> None:
self.resolved[repr(block.label)] = self.next_instr_addr

self.block = block
for statement in block.statements:
self.emit_stmt(statement)

def emit_stmt(self, stmt: tafka.Statement) -> None:
match stmt:
case tafka.Jump() as jump:
self.emit_jump(jump)
case tafka.Set() as set_stmt:
self.emit_set_stmt(set_stmt)

def emit_jump(self, jump: tafka.Jump) -> None:
match jump:
case tafka.Return() as ret:
self.emit_jump_return(ret)
case tafka.Goto() as goto:
self.emit_jump_goto(goto)
case tafka.Conditional() as cond:
self.emit_jump_cond(cond)

def emit_jump_return(self, stmt: tafka.Return) -> None:
self.emit_i(mov(Reg.a1(), self.reg_var(stmt.value)))
self.emit_i(Brn(Reg.ze(), Reg.ra()))

def emit_jump_goto(self, stmt: tafka.Goto) -> None:
label = self.reg_tmp()
label_val = Unassigned(repr(stmt.block.label))
self.emit_i(movi(label, label_val))

self.emit_i(Brn(Reg.ze(), label))

def emit_jump_cond(self, conditional: tafka.Conditional) -> None:
self.block_until.append(conditional.next_block)

cond = self.reg_var(conditional.condition)

els = self.reg_tmp()
els_val = Unassigned(repr(conditional.else_branch.label))
self.emit_i(movi(els, els_val))
@override
def exit_block(self, block: tafka.Block) -> None:
pass

self.emit_i(Brn(cond, els))
@override
def enter_statement(self, statement: tafka.Statement) -> None:
pass

self.emit_block(conditional.then_branch)
self.emit_block(conditional.else_branch)
@override
def exit_statement(self, statement: tafka.Statement) -> None:
pass

self.block_until.pop()
@override
def on_return(self, ret: tafka.Return) -> None:
self.emit_i(mov(Reg.a1(), self.reg_var(ret.value)))
self.emit_i(Brn(Reg.ze(), Reg.ra()))

self.emit_block(conditional.next_block)
@override
def on_goto(self, goto: tafka.Goto) -> None:
label = self.reg_tmp()
self.emit_i(movi(label, Unassigned(repr(goto.block.label))))
self.emit_i(Brn(Reg.ze(), label))

def emit_set_stmt(self, stmt: tafka.Set) -> None:
match stmt.source:
case tafka.Intrinsic() as intrinsic:
self.emit_intrinsic(stmt.target, intrinsic)
case tafka.Invokation() as invokation:
self.emit_invokation(stmt.target, invokation)
@override
def on_conditional(self, conditional: tafka.Conditional) -> None:
else_label = repr(conditional.else_branch.label)

def emit_intrinsic(
self,
target: tafka.Var,
source: tafka.Intrinsic,
) -> None:
dst = self.reg_var(target)
match source:
case tafka.Load(cnst):
self.emit_i(Addim(dst, Reg.ze(), self.addr_of(cnst)))
self.emit_i(Load(dst, dst))
case tafka.Copy(var):
src = self.reg_var(var)
self.emit_i(mov(dst, src))
case tafka.Sum(lhs, rhs):
lhsr = self.reg_var(lhs)
rhsr = self.reg_var(rhs)
self.emit_i(Addi(dst, lhsr, rhsr))
case tafka.Mul(lhs, rhs):
lhsr = self.reg_var(lhs)
rhsr = self.reg_var(rhs)
self.emit_i(Muli(dst, lhsr, rhsr))
case tafka.Div(lhs, rhs):
lhsr = self.reg_var(lhs)
rhsr = self.reg_var(rhs)
self.emit_i(Divi(dst, lhsr, rhsr))
case tafka.Rem(lhs, rhs):
lhsr = self.reg_var(lhs)
rhsr = self.reg_var(rhs)
self.emit_i(Remi(dst, lhsr, rhsr))
case tafka.Eq(lhs, rhs):
lhsr = self.reg_var(lhs)
rhsr = self.reg_var(rhs)

l2r = orb = dst
r2l = self.reg_tmp()
neg = self.reg_tmp()

self.emit_i(Slti(l2r, lhsr, rhsr))
self.emit_i(Slti(r2l, rhsr, lhsr))
self.emit_i(Orb(orb, l2r, r2l))
self.emit_i(Addim(neg, Reg.ze(), Integer(2**64 - 1)))
self.emit_i(Xorb(dst, orb, neg))
case tafka.Lt(lhs, rhs):
lhsr = self.reg_var(lhs)
rhsr = self.reg_var(rhs)
self.emit_i(Slti(dst, lhsr, rhsr))
case tafka.And(lhs, rhs):
lhsr = self.reg_var(lhs)
rhsr = self.reg_var(rhs)
self.emit_i(Andb(dst, lhsr, rhsr))
case tafka.Or(lhs, rhs):
lhsr = self.reg_var(lhs)
rhsr = self.reg_var(rhs)
self.emit_i(Orb(dst, lhsr, rhsr))
case _:
raise NotImplementedError(str(source))
condition = self.reg_var(conditional.condition)
else_address = self.reg_tmp()
self.emit_i(movi(else_address, Unassigned(else_label)))
self.emit_i(Brn(condition, else_address))

def emit_invokation(
@override
def on_invokation(
self,
target: tafka.Var,
source: tafka.Invokation,
Expand All @@ -189,6 +109,84 @@ def emit_invokation(

self.emit_i(mov(Reg.ra(), prev_ra))

@override
def on_load(self, target: tafka.Var, source: tafka.Load) -> None:
dst = self.reg_var(target)
addr = self.addr_of(source.constant)
self.emit_i(Addim(dst, Reg.ze(), addr))
self.emit_i(Load(dst, dst))

@override
def on_copy(self, target: tafka.Var, source: tafka.Copy) -> None:
dst = self.reg_var(target)
src = self.reg_var(source.argument)
self.emit_i(mov(dst, src))

@override
def on_sum(self, target: tafka.Var, source: tafka.Sum) -> None:
dst = self.reg_var(target)
lhsr = self.reg_var(source.left)
rhsr = self.reg_var(source.right)
self.emit_i(Addi(dst, lhsr, rhsr))

@override
def on_mul(self, target: tafka.Var, source: tafka.Mul) -> None:
dst = self.reg_var(target)
lhsr = self.reg_var(source.left)
rhsr = self.reg_var(source.right)
self.emit_i(Muli(dst, lhsr, rhsr))

@override
def on_div(self, target: tafka.Var, source: tafka.Div) -> None:
dst = self.reg_var(target)
lhsr = self.reg_var(source.left)
rhsr = self.reg_var(source.right)
self.emit_i(Divi(dst, lhsr, rhsr))

@override
def on_rem(self, target: tafka.Var, source: tafka.Rem) -> None:
dst = self.reg_var(target)
lhsr = self.reg_var(source.left)
rhsr = self.reg_var(source.right)
self.emit_i(Remi(dst, lhsr, rhsr))

@override
def on_eq(self, target: tafka.Var, source: tafka.Eq) -> None:
rdst = self.reg_var(target)
lhsr = self.reg_var(source.left)
rhsr = self.reg_var(source.right)

l2r = orb = rdst
r2l = self.reg_tmp()
neg = self.reg_tmp()

self.emit_i(Slti(l2r, lhsr, rhsr))
self.emit_i(Slti(r2l, rhsr, lhsr))
self.emit_i(Orb(orb, l2r, r2l))
self.emit_i(Addim(neg, Reg.ze(), Integer(2**64 - 1)))
self.emit_i(Xorb(rdst, orb, neg))

@override
def on_lt(self, target: tafka.Var, source: tafka.Lt) -> None:
dst = self.reg_var(target)
lhsr = self.reg_var(source.left)
rhsr = self.reg_var(source.right)
self.emit_i(Slti(dst, lhsr, rhsr))

@override
def on_and(self, target: tafka.Var, source: tafka.And) -> None:
dst = self.reg_var(target)
lhsr = self.reg_var(source.left)
rhsr = self.reg_var(source.right)
self.emit_i(Andb(dst, lhsr, rhsr))

@override
def on_or(self, target: tafka.Var, source: tafka.Or) -> None:
dst = self.reg_var(target)
lhsr = self.reg_var(source.left)
rhsr = self.reg_var(source.right)
self.emit_i(Orb(dst, lhsr, rhsr))

def emit_i(self, instr: Instruction) -> None:
self.memory.instr.append(instr)

Expand All @@ -215,25 +213,3 @@ def addr_of(self, cnst: tafka.Const) -> Immediate:
@property
def next_instr_addr(self) -> int:
return len(self.memory.instr) * 4


AsmikUnit = AsmikEmiter


def asmik_resolve(asmik: AsmikUnit) -> None:
for instr in asmik.memory.instr:
if (
isinstance(instr, Addim) #
and isinstance(instr.rhs, Unassigned)
):
label = instr.rhs.label
instr.rhs = Integer(asmik.resolved[label])


def asmik_emit(tafka: TafkaUnit) -> AsmikUnit:
asmik = AsmikEmiter()
asmik.emit_block(tafka.main)
for proc in tafka.procedures:
asmik.emit_procedure(proc)
asmik_resolve(asmik)
return asmik
15 changes: 0 additions & 15 deletions sleepy/asmik/text.py

This file was deleted.

48 changes: 48 additions & 0 deletions sleepy/asmik/unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from dataclasses import dataclass

from sleepy.tafka import TafkaUnit, TafkaWalker

from .argument import Integer, Unassigned
from .emit import AsmikEmitListener
from .instruction import Addim
from .memory import Memory


@dataclass
class AsmikUnit:
memory: Memory

@staticmethod
def emited_from(tafka: TafkaUnit) -> "AsmikUnit":
def resolve_addresses(asmik: AsmikEmitListener) -> None:
for instr in asmik.memory.instr:
if (
isinstance(instr, Addim) #
and isinstance(instr.rhs, Unassigned)
):
label = instr.rhs.label
instr.rhs = Integer(asmik.resolved[label])

asmik = AsmikEmitListener()
walker = TafkaWalker(asmik)

walker.explore_block(tafka.main)
for proc in tafka.procedures:
walker.explore_procedure(proc)

resolve_addresses(asmik)

return AsmikUnit(asmik.memory)

def to_text(self) -> str:
text = ""

text += "memory stack\n"
for addr, data in sorted(self.memory.stack.items()):
text += f"{addr:04d}: {data!r}\n"

text += "memory instr\n"
for i, instruction in enumerate(self.memory.instr):
text += f"{(i * 4):04d}: {instruction!r}\n"

return text
Loading

0 comments on commit e1e9e6a

Please sign in to comment.