Commit TP4b

This commit is contained in:
Rémi Di Guardia
2022-10-11 17:07:00 +02:00
parent 93b241c32a
commit 49092057f8
44 changed files with 2480 additions and 329 deletions
+111
View File
@@ -0,0 +1,111 @@
"""
CAP, CodeGeneration, CFG construction from linear code
"""
from typing import List
from Lib.Errors import MiniCInternalError
from Lib.FunctionData import FunctionData
from Lib.LinearCode import LinearCode, CodeStatement
from Lib.Statement import (
Instru3A, Comment, Label, AbsoluteJump, ConditionalJump
)
from Lib.Terminator import jump2terminator
from Lib.CFG import Block, BlockInstr, CFG
def find_leaders(instructions: List[CodeStatement]) -> List[int]:
"""
Find the leaders in the given list of instructions as linear code.
Returns a list of indices in the instruction list whose first is 0 and
last is len(instructions)
"""
leaders: List[int] = [0]
# TODO fill leaders (Lab4b, Exercise 3)
# The final "ret" is also a form of jump
leaders.append(len(instructions))
return leaders
def separate_with_leaders(instructions: List[CodeStatement],
leaders: List[int]) -> List[List[CodeStatement]]:
"""
Partition the lists instructions into a list containing for
elements the lists of statements between indices
leaders[i] (included) and leaders[i+1] (excluded).
If leaders[i] = leaders[i+1], do not add the empty list.
"""
chunks: List[List[CodeStatement]] = []
for i in range(0, len(leaders)-1):
start = leaders[i]
end = leaders[i+1]
if start != end:
# Avoid corner-cases when a label immediately follows a jump
chunks.append(instructions[start:end])
return chunks
def prepare_chunk(pre_chunk: List[CodeStatement], fdata: FunctionData) -> tuple[
Label, ConditionalJump | AbsoluteJump | None, List[BlockInstr]]:
"""
Extract the potential label (respectively jump)
at the start (respectively end) of the list instrs_chunk,
and return the tuple with this label, this jump and the
rest of instrs_chunk.
If there is no label at the start then return a fresh label instead,
thanks to fdata (use `fdata.fresh_label(fdata._name)` for instance).
If there is no jump at the end, return None instead.
Raise an error if there is a label not in first position in pre_chunk,
or a jump not in last position.
"""
label = None
jump = None
inner_statements: List[CodeStatement] = pre_chunk
# Extract the first instruction from inner_statements if it is a label, or create a fresh one
raise NotImplementedError() # TODO (Lab4b, Exercise 3)
# Extract the last instruction from inner_statements if it is a jump, or do nothing
raise NotImplementedError() # TODO (Lab4b, Exercise 3)
# Check that there is no other label or jump left in inner_statements
l: List[BlockInstr] = []
for i in inner_statements:
match i:
case AbsoluteJump() | ConditionalJump():
raise MiniCInternalError(
"prepare_chunk: Jump {} not in last position of a chunk"
.format(i))
case Label():
raise MiniCInternalError(
"prepare_chunk: Label {} not in first position of a chunk"
.format(i))
case Instru3A() | Comment():
l.append(i)
return (label, jump, l)
def build_cfg(linCode: LinearCode) -> CFG:
"""Extract the blocks from the linear code and add them to the CFG."""
fdata = linCode.fdata
cfg = CFG(fdata)
instructions = linCode.get_instructions()
# 1. Identify Leaders
leaders = find_leaders(instructions)
# 2. Extract Chunks of Instructions
pre_chunks: List[List[CodeStatement]] = separate_with_leaders(instructions, leaders)
chunks: List[tuple[Label, ConditionalJump | AbsoluteJump | None, List[BlockInstr]]] = [
prepare_chunk(pre_chunk, fdata) for pre_chunk in pre_chunks]
# 3. Build the Blocks
next_label = None
for (label, jump, block_instrs) in reversed(chunks):
term = jump2terminator(jump, next_label)
block = Block(label, block_instrs, term)
cfg.add_block(block)
next_label = label
# 4. Fill the edges
for block in cfg.get_blocks():
for dest in cfg.out_blocks(block):
cfg.add_edge(block, dest)
# 5. Identify the entry label of the CFG
cfg.set_start(chunks[0][0])
return cfg
+43
View File
@@ -0,0 +1,43 @@
"""
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.
"""
# TODO (Lab 4b, Exercise 5)
l: List[Statement] = [] # Linearized CFG
blocks: List[Block] = ordered_blocks_list(cfg)
for j, block in enumerate(blocks):
# 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
+13
View File
@@ -0,0 +1,13 @@
#include "printlib.h"
int main() {
int n,u;
n=6;
println_int(n);
return 0;
}
// EXPECTED
// 6
+15
View File
@@ -0,0 +1,15 @@
#include "printlib.h"
int main() {
int n,u,v;
n=6;
u=12;
v=n+u;
println_int(v);
return 0;
}
// EXPECTED
// 18
+14
View File
@@ -0,0 +1,14 @@
#include "printlib.h"
int main() {
int n,v;
bool u;
n=6;
u=12>n;
println_bool(1<n && u);
return 0;
}
// EXPECTED
// 1
+18
View File
@@ -0,0 +1,18 @@
#include "printlib.h"
int main()
{
int n, u, v;
n = 6;
u = 0;
while (n > 1)
{
n = n - 1;
u = u + n;
}
println_int(u);
return 0;
}
// EXPECTED
// 15
+16
View File
@@ -0,0 +1,16 @@
#include "printlib.h"
int main()
{
int x, y;
x = 2;
if (x < 4)
x = 4;
else
x = 5;
return 0;
}
// EXPECTED
+14
View File
@@ -0,0 +1,14 @@
#include "printlib.h"
int main()
{
int x;
x = 0;
while (x < 4)
{
x = x + 1;
}
return 0;
}
// EXPECTED
Binary file not shown.