Skip to content

Commit

Permalink
#16 [asm] added procedures virt codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
vityaman committed Feb 6, 2024
1 parent d227ef2 commit 6c8d5f4
Show file tree
Hide file tree
Showing 16 changed files with 333 additions and 255 deletions.
19 changes: 15 additions & 4 deletions sleepy/asmik/argument.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ def ze() -> "PhysicalRegister":
return PhysicalRegister("ze")

@staticmethod
def a1() -> "PhysicalRegister":
return PhysicalRegister("a1")
def ip() -> "PhysicalRegister":
return PhysicalRegister("ip")

@staticmethod
def sp() -> "PhysicalRegister":
return PhysicalRegister("sp")

@staticmethod
def ra() -> "PhysicalRegister":
return PhysicalRegister("ra")

@staticmethod
def ip() -> "PhysicalRegister":
return PhysicalRegister("ip")
def a1() -> "PhysicalRegister":
return PhysicalRegister("a1")


@dataclass(repr=False)
Expand All @@ -44,6 +48,13 @@ class PhysicalRegister(Register):
def __repr__(self) -> str:
return self.name

@staticmethod
def arg(number: int) -> "PhysicalRegister":
max_number = 6
if number > max_number:
raise NotImplementedError
return PhysicalRegister(f"a{number}")


class Immediate(Argument):
pass
Expand Down
2 changes: 1 addition & 1 deletion sleepy/asmik/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ def size_in_bytes(self) -> int:

@override
def __repr__(self) -> str:
return f"{self.value} # const({self.value}): int"
return f"{self.value}"
56 changes: 42 additions & 14 deletions sleepy/asmik/emit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from sleepy.tafka.emit import TafkaUnit

from .argument import Immediate, Integer, Unassigned
from .argument import PhysicalRegister as PhysReg
from .argument import Register as Reg
from .argument import VirtualRegister as VirtReg
from .data import IntegerData
Expand All @@ -27,23 +28,32 @@
class AsmikEmiter:
def __init__(self) -> None:
self.virt_regs = (VirtReg(n) for n in range(10000))
self.unassigned: dict[str, int] = {}
self.memory = Memory()
self.regs: dict[str, VirtReg] = {}
self.regs: dict[str, Reg] = {}

self.resolved: dict[str, int] = {}

self.block: tafka.Block
self.block_until: list[tafka.Block] = []

def emit_procedure(self, proc: 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):
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

self.resolved[repr(block.label)] = len(self.memory.instr) * 4
self.resolved[repr(block.label)] = self.next_instr_addr

self.block = block
for statement in block.statements:
Expand All @@ -67,20 +77,14 @@ def emit_jump(self, jump: tafka.Jump) -> None:

def emit_jump_return(self, stmt: tafka.Return) -> None:
self.emit_i(mov(Reg.a1(), self.reg_var(stmt.value)))
false = self.reg_tmp()
self.emit_i(movi(false, Integer(0)))
self.emit_i(Brn(false, Reg.ra()))
self.emit_i(Brn(Reg.ze(), Reg.ra()))

def emit_jump_goto(self, stmt: tafka.Goto) -> None:
false = self.reg_tmp()
false_val = Integer(0)
self.emit_i(movi(false, false_val))

label = self.reg_tmp()
label_val = Unassigned(repr(stmt.block.label))
self.emit_i(movi(label, label_val))

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

def emit_jump_cond(self, conditional: tafka.Conditional) -> None:
self.block_until.append(conditional.next_block)
Expand Down Expand Up @@ -165,12 +169,27 @@ def emit_invokation(
target: tafka.Var,
source: tafka.Invokation,
) -> None:
raise NotImplementedError
for i, arg in enumerate(source.args):
arg_reg = self.reg_var(arg)
self.emit_i(mov(PhysReg.arg(i + 1), arg_reg))

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

self.emit_i(Addim(Reg.ra(), Reg.ip(), Integer(4)))

proc_reg = self.reg_var(source.closure)
self.emit_i(Brn(Reg.ze(), proc_reg))

res_reg = self.reg_var(target)
self.emit_i(mov(res_reg, Reg.a1()))

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

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

def reg_var(self, var: tafka.Var) -> VirtReg:
def reg_var(self, var: tafka.Var) -> Reg:
var_repr = repr(var)
if var_repr not in self.regs:
self.regs[var_repr] = self.reg_tmp()
Expand All @@ -185,7 +204,14 @@ def addr_of(self, cnst: tafka.Const) -> Immediate:
data = IntegerData(int(cnst.name))
addr = self.memory.data_put(data)
return Integer(addr)
raise NotImplementedError
case tafka.Signature():
return Unassigned(repr(cnst))
case _:
raise NotImplementedError

@property
def next_instr_addr(self) -> int:
return len(self.memory.instr) * 4


AsmikUnit = AsmikEmiter
Expand All @@ -204,5 +230,7 @@ def asmik_resolve(asmik: AsmikUnit) -> None:
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
8 changes: 7 additions & 1 deletion sleepy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

def main() -> None:
source = """
(if (eq 1 1) 999 666)
(def id (lambda (n int) n))
(def a (id 1))
(def b (id 11))
(def c (id 111))
(if (and (eq a 1)
(and (eq b 11)
(eq c 111))) 1 0)
"""

syntax = parse_program(source)
Expand Down
6 changes: 5 additions & 1 deletion sleepy/tafka/representation/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from .kind import Kind, Signature
from .node import Node
from .rvalue import RValue
from .symbol import Var
from .symbol import Const, Var


class Statement(Node):
Expand Down Expand Up @@ -98,6 +98,10 @@ def signature(self) -> Signature:
self.value,
)

@property
def const(self) -> Const:
return Const(self.name, self.signature)

@override
def __repr__(self) -> str:
return (
Expand Down
34 changes: 28 additions & 6 deletions test/asmik/test_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,37 @@
("(def a 7) a", "7"),
("(def a 70) (def b 8) (sum a b)", "78"),
(
(
"(def a 1) "
"(def b a) "
"(def a (sum 1 a)) "
"(if (and (eq a 2) (eq b 1)) 1 0)"
),
"""
(def a 1)
(def b a)
(def a (sum 1 a))
(if (and (eq a 2) (eq b 1)) 1 0)
""",
"1",
),
("(if (eq 1 0) (if (eq 1 1) 0 0) (if (eq 1 0) 0 1))", "1"),
(
"""
(def id (lambda (n int) n))
(def a (id 1))
(def b (id 11))
(def c (id 111))
(if (and (eq a 1)
(and (eq b 11)
(eq c 111))) 1 0)
""",
"1",
),
(
"""
(def qsum (lambda (a int b int)
(sum (mul a a) (mul b b))))
(if (and (eq (qsum 1 2) 5)
(and (eq (qsum 2 2) 8)
(eq (qsum 1 1) 2))) 1 0)
""",
"1",
),
],
)
def test_evaluate(src: str, res: str) -> None:
Expand Down
7 changes: 3 additions & 4 deletions test/golden/group/arithmetics/1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ tafka: |-
asmik-virt: |-
memory stack
0000: 5 # const(5): int
0008: 2 # const(2): int
0000: 5
0008: 2
memory instr
0000: addim v0, ze, 0
0004: load v0, v0
Expand All @@ -34,5 +34,4 @@ asmik-virt: |-
0048: remi v7, v5, v6
0052: addi v8, v2, v7
0056: addim a1, v8, 0
0060: addim v9, ze, 0
0064: brn v9, ra
0060: brn ze, ra
35 changes: 16 additions & 19 deletions test/golden/group/conditional/1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ tafka: |-
var(2): bool = eq(var(0): int, var(1): int): bool
if var(2): bool then label(0) else label(1) end label(2)
label(0):
var(3): int = load(const(1): int): int
goto label(2)
var(3): int = load(const(1): int): int
goto label(2)
label(1):
var(4): int = load(const(1): int): int
var(3): int = copy(var(4): int): int
goto label(2)
var(4): int = load(const(1): int): int
var(3): int = copy(var(4): int): int
goto label(2)
label(2):
return var(3): int
asmik-virt: |-
memory stack
0000: 1 # const(1): int
0000: 1
memory instr
0000: addim v0, ze, 0
0004: load v0, v0
Expand All @@ -30,19 +30,16 @@ asmik-virt: |-
0024: orb v2, v2, v3
0028: addim v4, ze, 18446744073709551615
0032: xorb v2, v2, v4
0036: addim v5, ze, 64
0036: addim v5, ze, 60
0040: brn v2, v5
0044: addim v6, ze, 0
0048: load v6, v6
0052: addim v7, ze, 0
0056: addim v8, ze, 88
0060: brn v7, v8
0064: addim v9, ze, 0
0068: load v9, v9
0072: addim v6, v9, 0
0076: addim v10, ze, 0
0080: addim v11, ze, 88
0084: brn v10, v11
0088: addim a1, v6, 0
0092: addim v12, ze, 0
0096: brn v12, ra
0052: addim v7, ze, 80
0056: brn ze, v7
0060: addim v8, ze, 0
0064: load v8, v8
0068: addim v6, v8, 0
0072: addim v9, ze, 80
0076: brn ze, v9
0080: addim a1, v6, 0
0084: brn ze, ra
Loading

0 comments on commit 6c8d5f4

Please sign in to comment.