CAP/MiniC/TP05/SequentializeMoves.py
2024-10-06 19:58:11 +02:00

61 lines
2.4 KiB
Python

"""
CAP, SSA Intro, Elimination and Optimisations
Helper functions to convert a CFG out of SSA Form
for the Smart Allocator.
"""
from typing import List, Set, Tuple
from Lib import RiscV
from Lib.Graphes import DiGraph
from Lib.CFG import BlockInstr
from Lib.Operands import Register, Offset, DataLocation, S
def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInstr]:
"""
Generate a list of move, store and load instructions, depending on
whether the operands are registers or memory locations.
This is an helper function for `sequentialize_moves`.
"""
instr: List[BlockInstr] = []
# TODO Compute the moves (Lab 5b, Exercise 4)
raise NotImplementedError("generate_smart_move")
return instr
def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
) -> List[BlockInstr]:
"""
Take a set of parallel moves represented as (destination, source) pairs,
and return a list of sequential moves which respect the cycles.
Use the register `tmp` S2 for the cycles.
Return a corresponding list of RiscV instructions.
This is an helper function called during SSA exit.
"""
tmp: Register = S[2] # S2 is not a general purpose register
# Build the graph of the moves
move_graph: DiGraph = DiGraph()
for dest, src in parallel_moves:
move_graph.add_edge((src, dest))
# List for the sequentialized moves to do
# Convention: in moves we put (dest, src) for each move
moves: List[Tuple[DataLocation, DataLocation]] = []
# First iteratively remove all the vetices without successors
vars_without_successor = {src
for src, dests in move_graph.neighbourhoods()
if len(dests) == 0}
while vars_without_successor:
# TODO Remove the leaves iteratively (Lab 5b, Exercise 4)
raise NotImplementedError("sequentialize_moves: leaves")
# Then handle the cycles
cycles: List = move_graph.connected_components()
for cycle in cycles:
# TODO Handle each cycle (Lab 5b, Exercise 4)
raise NotImplementedError("sequentialize_moves: cycles")
# Transform the moves to do in actual RiscV instructions
moves_instr: List[BlockInstr] = []
for dest, src in moves:
instrs = generate_smart_move(dest, src)
moves_instr.extend(instrs)
return moves_instr