66 lines
2.0 KiB
Python
66 lines
2.0 KiB
Python
"""
|
|
CAP, CodeGeneration, CFG linearization to a list of statements
|
|
"""
|
|
|
|
from typing import List, Set
|
|
|
|
from Lib.Statement import (
|
|
Statement, AbsoluteJump, ConditionalJump
|
|
)
|
|
from Lib.Terminator import (Return, BranchingTerminator)
|
|
from Lib.CFG import Block
|
|
|
|
|
|
def ordered_blocks_list(cfg) -> List[Block]:
|
|
"""
|
|
Compute a list of blocks with optimized ordering for linearization.
|
|
"""
|
|
# TODO (Lab4b, Extension)
|
|
return cfg.get_blocks()
|
|
|
|
|
|
def linearize(cfg) -> List[Statement]:
|
|
"""
|
|
Linearize the given control flow graph as a list of instructions.
|
|
"""
|
|
l: List[Statement] = [] # Linearized CFG
|
|
blocks: List[Block] = ordered_blocks_list(cfg)
|
|
|
|
labdict = {}
|
|
# We make the label dictionary
|
|
for j,block in enumerate(blocks):
|
|
labdict[block.get_label()] = block
|
|
|
|
while blocks != []:
|
|
block = blocks[0]
|
|
if(l != [] and isinstance(l[-1],AbsoluteJump)):
|
|
ll : AbsoluteJump = l[-1]
|
|
# We try to find the next jump according to that.
|
|
try:
|
|
# If we find the instruction
|
|
b = labdict[ll.label]
|
|
if b in blocks:
|
|
# We remove the jump instruction and we select the block to use
|
|
l.pop()
|
|
block = b
|
|
except KeyError:
|
|
pass
|
|
|
|
# We remove the block we used
|
|
blocks.remove(block)
|
|
|
|
# 1. Add the label of the block to the linearization
|
|
l.append(block.get_label())
|
|
# 2. Add the body of the block to the linearization
|
|
l.extend(block.get_body())
|
|
# 3. Add the terminator of the block to the linearization
|
|
match block.get_terminator():
|
|
case BranchingTerminator() as j:
|
|
l.append(ConditionalJump(j.cond, j.op1, j.op2, j.label_then))
|
|
l.append(AbsoluteJump(j.label_else))
|
|
case AbsoluteJump() as j:
|
|
l.append(AbsoluteJump(j.label))
|
|
case Return():
|
|
l.append(AbsoluteJump(cfg.get_end()))
|
|
return l
|