Compare commits

..

No commits in common. "main" and "TP03" have entirely different histories.
main ... TP03

118 changed files with 132 additions and 5717 deletions

View File

@ -17,9 +17,8 @@ class PhiNode(Statement):
""" """
A φ node is a renaming in the CFG, of the form temp_x = φ(temp_0, ..., temp_n). A φ node is a renaming in the CFG, of the form temp_x = φ(temp_0, ..., temp_n).
The field var contains the variable temp_x. The field var contains the variable temp_x.
The field srcs links each corresponding predecessor in the CFG The field srcs relies for each precedent block in the CFG, identified with its label,
---identified by its label---, to the variable temp_i of the φ the variable temp_i of the φ node.
node.
""" """
var: DataLocation var: DataLocation
srcs: Dict[Label, Operand] srcs: Dict[Label, Operand]

View File

@ -1,30 +1,21 @@
# MiniC Compiler # MiniC Compiler
LAB5a (Control Flow Graph in SSA Form) & LAB5b (Smart Register Allocation), CAP 2023-24 LAB5a (Control Flow Graph in SSA Form) & LAB5b (Smart Register Allocation), CAP 2022-23
# Authors # Authors
Augustin LUCAS YOUR NAME HERE
# Contents # Contents
Extension implemented : Optimizing swap TODO:
- Cycles of size 1 : skip - Explain any design choices you may have made.
- Cycles of size 2 : use 3 XOR operations to swap the registers values without any temporary register use - Do not forget to remove all debug traces from your code!
- Did you implement an extension?
# Test design # Test design
No tests were added since some of the `students`' tests from lab4 still failed to execute properly. TODO: give the main objectives of your tests.
# Known bugs # Known bugs
Failing tests: TODO: bugs you could not fix (if any).
- `./TP04/tests/students/ext-for-fortran/test_imbricated_for.c`
- `./TP04/tests/students/ext-for-fortran/test_for.c`
- `./TP04/tests/students/base/test_nested_while.c`
- `./TP04/tests/students/base/test_fibonacci.c`
- `./TP04/tests/provided/dataflow/df03.c`
The bug seems to be related to the handling of Offsets because a lot more tests will fail if temporaries are only assigned to memory (no registers).
This can be done by commenting `TP05/SmartAllocator.py:124`.
This seems to affect `while` and `for` loops as well as regular variables (because variables may not be stored/loaded correctly).

View File

@ -1,5 +1,5 @@
# MiniC Compiler # MiniC Compiler
LAB5 (smart code generation), MIF08 / CAP 2023-24 LAB5 (smart code generation), MIF08 / CAP 2022-23
# Authors # Authors

View File

@ -1,21 +1,26 @@
# MiniC Compiler # MiniC Compiler
LAB4 (simple code generation), MIF08 / CAP 2023-24 LAB4 (simple code generation), MIF08 / CAP 2022-23
# Authors # Authors
Augustin LUCAS YOUR NAME HERE
# Contents # Contents
TODO for STUDENTS : Say a bit about the code infrastructure ...
# Test design # Test design
TODO: explain your tests
# Design choices # Design choices
Booleans are implemented as integers behind the scenes, but type-checking before compilation disables any casting mechanism. TODO: explain your choices. How did you implement boolean not? Did you implement an extension?
As for the previous lab, the Fortran-like for-loop extension has been implemented.
# Known bugs # Known bugs
TODO: Bugs and limitations.
# Checklists # Checklists
A check ([X]) means that the feature is implemented A check ([X]) means that the feature is implemented
@ -23,30 +28,30 @@ and *tested* with appropriate test cases.
## Code generation ## Code generation
- [x] Number Atom - [ ] Number Atom
- [x] Boolean Atom - [ ] Boolean Atom
- [x] Id Atom - [ ] Id Atom
- [x] Additive expression - [ ] Additive expression
- [x] Multiplicative expression - [ ] Multiplicative expression
- [x] UnaryMinus expression - [ ] UnaryMinus expression
- [x] Or expression - [ ] Or expression
- [x] And expression - [ ] And expression
- [x] Equality expression - [ ] Equality expression
- [x] Relational expression (! many cases -> many tests) - [ ] Relational expression (! many cases -> many tests)
- [x] Not expression - [ ] Not expression
## Statements ## Statements
- [x] Prog, assignements - [ ] Prog, assignements
- [x] While - [ ] While
- [x] Cond Block - [ ] Cond Block
- [x] If - [ ] If
- [x] Nested ifs - [ ] Nested ifs
- [x] Nested whiles - [ ] Nested whiles
## Allocation ## Allocation
- [x] Naive allocation - [ ] Naive allocation
- [x] All in memory allocation - [ ] All in memory allocation
- [ ] Massive tests of memory allocation - [ ] Massive tests of memory allocation

View File

@ -1,5 +1,5 @@
# MiniC Compiler # MiniC Compiler
LAB6 (code generation for functions), MIF08 / CAP 2023-24 LAB6 (code generation for functions), MIF08 / CAP 2022-23
# Authors # Authors

View File

@ -1,5 +1,5 @@
# MiniC interpreter and typer # MiniC interpreter and typer
LAB3, MIF08 / CAP / CS444 2023-24 LAB3, MIF08 / CAP / CS444 2022-23
# Authors # Authors

View File

@ -14,25 +14,11 @@ class AllInMemAllocator(Allocator):
before: List[Instruction] = [] before: List[Instruction] = []
after: List[Instruction] = [] after: List[Instruction] = []
new_args: List[Operand] = [] new_args: List[Operand] = []
# TODO: compute before,after,args.
for arg in old_instr.defined(): # TODO: iterate over old_args, check which argument
if isinstance(arg, Temporary): # TODO: is a temporary (e.g. isinstance(..., Temporary)),
after.append(RiscV.sd( # TODO: and if so, generate ld/sd accordingly. Replace the
S[3], arg.get_alloced_loc() # TODO: temporary with S[1], S[2] or S[3] physical registers.
))
new_args.append(S[3])
else:
new_args.append(arg)
for i, arg in enumerate(old_instr.used(), 1):
if isinstance(arg, Temporary):
before.append(RiscV.ld(
S[i], arg.get_alloced_loc()
))
new_args.append(S[i])
else:
new_args.append(arg)
new_instr = old_instr.with_args(new_args) new_instr = old_instr.with_args(new_args)
return before + [new_instr] + after return before + [new_instr] + after

View File

@ -20,13 +20,7 @@ def find_leaders(instructions: List[CodeStatement]) -> List[int]:
last is len(instructions) last is len(instructions)
""" """
leaders: List[int] = [0] leaders: List[int] = [0]
# TODO fill leaders
for i, instr in enumerate(instructions):
if isinstance(instr, Label):
leaders.append(i)
elif isinstance(instr, AbsoluteJump) or isinstance(instr, ConditionalJump):
leaders.append(i+1)
# The final "ret" is also a form of jump # The final "ret" is also a form of jump
leaders.append(len(instructions)) leaders.append(len(instructions))
return leaders return leaders
@ -70,15 +64,9 @@ def prepare_chunk(pre_chunk: List[CodeStatement], fdata: FunctionData) -> tuple[
jump = None jump = None
inner_statements: List[CodeStatement] = pre_chunk inner_statements: List[CodeStatement] = pre_chunk
# Extract the first instruction from inner_statements if it is a label, or create a fresh one # Extract the first instruction from inner_statements if it is a label, or create a fresh one
if isinstance(inner_statements[0], Label): raise NotImplementedError() # TODO
label = inner_statements[0]
inner_statements = inner_statements[1:]
else:
label = fdata.fresh_label(fdata._name)
# Extract the last instruction from inner_statements if it is a jump, or do nothing # Extract the last instruction from inner_statements if it is a jump, or do nothing
if len(inner_statements) > 0 and (isinstance(inner_statements[-1], ConditionalJump) or isinstance(inner_statements[-1], AbsoluteJump)): raise NotImplementedError() # TODO
jump = inner_statements[-1]
inner_statements = inner_statements[:-1]
# Check that there is no other label or jump left in inner_statements # Check that there is no other label or jump left in inner_statements
l: List[BlockInstr] = [] l: List[BlockInstr] = []
for i in inner_statements: for i in inner_statements:

View File

@ -20,6 +20,7 @@ def linearize(cfg: CFG) -> List[Statement]:
""" """
Linearize the given control flow graph as a list of instructions. Linearize the given control flow graph as a list of instructions.
""" """
# TODO
l: List[Statement] = [] # Linearized CFG l: List[Statement] = [] # Linearized CFG
blocks: List[Block] = ordered_blocks_list(cfg) # All blocks of the CFG blocks: List[Block] = ordered_blocks_list(cfg) # All blocks of the CFG
for i, block in enumerate(blocks): for i, block in enumerate(blocks):
@ -33,7 +34,6 @@ def linearize(cfg: CFG) -> List[Statement]:
l.append(ConditionalJump(j.cond, j.op1, j.op2, j.label_then)) l.append(ConditionalJump(j.cond, j.op1, j.op2, j.label_then))
l.append(AbsoluteJump(j.label_else)) l.append(AbsoluteJump(j.label_else))
case AbsoluteJump() as j: case AbsoluteJump() as j:
if i+1 == len(blocks) or j != blocks[i+1].get_label():
l.append(AbsoluteJump(j.label)) l.append(AbsoluteJump(j.label))
case Return(): case Return():
l.append(AbsoluteJump(cfg.get_end())) l.append(AbsoluteJump(cfg.get_end()))

View File

@ -74,13 +74,8 @@ class MiniCCodeGen3AVisitor(MiniCVisitor):
raise MiniCUnsupportedError("float literal") raise MiniCUnsupportedError("float literal")
def visitBooleanAtom(self, ctx) -> Operands.Temporary: def visitBooleanAtom(self, ctx) -> Operands.Temporary:
dest = self._current_function.fdata.fresh_tmp() # true is 1 false is 0
self._current_function.add_instruction( raise NotImplementedError() # TODO
RiscV.li(
dest, Operands.Immediate(1 if ctx.getText() == "true" else 0)
)
)
return dest # true is 1 false is 0
def visitIdAtom(self, ctx) -> Operands.Temporary: def visitIdAtom(self, ctx) -> Operands.Temporary:
try: try:
@ -104,37 +99,13 @@ class MiniCCodeGen3AVisitor(MiniCVisitor):
assert ctx.myop is not None assert ctx.myop is not None
tmpl: Operands.Temporary = self.visit(ctx.expr(0)) tmpl: Operands.Temporary = self.visit(ctx.expr(0))
tmpr: Operands.Temporary = self.visit(ctx.expr(1)) tmpr: Operands.Temporary = self.visit(ctx.expr(1))
tmp = self._current_function.fdata.fresh_tmp() raise NotImplementedError() # TODO
if ctx.myop.type == MiniCParser.PLUS:
self._current_function.add_instruction(
RiscV.add(tmp, tmpl, tmpr)
)
elif ctx.myop.type == MiniCParser.MINUS:
self._current_function.add_instruction(
RiscV.sub(tmp, tmpl, tmpr)
)
else:
raise MiniCInternalError(
f"Unknown additive operator '{ctx.myop}'")
return tmp
def visitOrExpr(self, ctx) -> Operands.Temporary: def visitOrExpr(self, ctx) -> Operands.Temporary:
tmp = self._current_function.fdata.fresh_tmp() raise NotImplementedError() # TODO
t1, t2 = self.visit(ctx.expr(0)), self.visit(ctx.expr(1))
self._current_function.add_instruction(
RiscV.lor(tmp, t1, t2)
)
return tmp
def visitAndExpr(self, ctx) -> Operands.Temporary: def visitAndExpr(self, ctx) -> Operands.Temporary:
tmp = self._current_function.fdata.fresh_tmp() raise NotImplementedError() # TODO
t1, t2 = self.visit(ctx.expr(0)), self.visit(ctx.expr(1))
self._current_function.add_instruction(
RiscV.land(tmp, t1, t2)
)
return tmp
def visitEqualityExpr(self, ctx) -> Operands.Temporary: def visitEqualityExpr(self, ctx) -> Operands.Temporary:
return self.visitRelationalExpr(ctx) return self.visitRelationalExpr(ctx)
@ -146,83 +117,18 @@ class MiniCCodeGen3AVisitor(MiniCVisitor):
print("relational expression:") print("relational expression:")
print(Trees.toStringTree(ctx, [], self._parser)) print(Trees.toStringTree(ctx, [], self._parser))
print("Condition:", c) print("Condition:", c)
raise NotImplementedError() # TODO
dest = self._current_function.fdata.fresh_tmp()
t1 = self.visit(ctx.expr(0))
t2 = self.visit(ctx.expr(1))
endrel = self._current_function.fdata.fresh_label("end_rel")
# dest <- 1
# t1 cond t2 ? jmp end
# dest <- 0
# end:
self._current_function.add_instruction(
RiscV.li(dest, Operands.Immediate(1)))
self._current_function.add_instruction(
RiscV.conditional_jump(endrel, t1, Condition(ctx.myop.type), t2))
self._current_function.add_instruction(
RiscV.li(dest, Operands.Immediate(0)))
self._current_function.add_label(endrel)
return dest
def visitMultiplicativeExpr(self, ctx) -> Operands.Temporary: def visitMultiplicativeExpr(self, ctx) -> Operands.Temporary:
assert ctx.myop is not None assert ctx.myop is not None
div_by_zero_lbl = self._current_function.fdata.get_label_div_by_zero() div_by_zero_lbl = self._current_function.fdata.get_label_div_by_zero()
t1 = self.visit(ctx.expr(0)) raise NotImplementedError() # TODO
t2 = self.visit(ctx.expr(1))
dest = self._current_function.fdata.fresh_tmp()
if ctx.myop.type == MiniCParser.DIV or ctx.myop.type == MiniCParser.MOD:
self._current_function.add_instruction(
RiscV.conditional_jump(div_by_zero_lbl, t2, Condition("beq"), Operands.ZERO))
if ctx.myop.type == MiniCParser.MULT:
self._current_function.add_instruction(
RiscV.mul(dest, t1, t2))
elif ctx.myop.type == MiniCParser.DIV:
self._current_function.add_instruction(
RiscV.div(dest, t1, t2))
elif ctx.myop.type == MiniCParser.MOD:
self._current_function.add_instruction(
RiscV.rem(dest, t1, t2))
else:
raise MiniCInternalError(
f"Unknown additive operator '{ctx.myop}'")
return dest
def visitNotExpr(self, ctx) -> Operands.Temporary: def visitNotExpr(self, ctx) -> Operands.Temporary:
dest = self._current_function.fdata.fresh_tmp() raise NotImplementedError() # TODO
label_neq_zero = self._current_function.fdata.fresh_label("neq_zero")
t1 = self.visit(ctx.expr())
# dest <- 0
# t1 != dest ? jmp neq_zero
# dest <- 1
# neq_zero:
self._current_function.add_instruction(
RiscV.li(dest, Operands.Immediate(0))
)
self._current_function.add_instruction(
RiscV.conditional_jump(label_neq_zero, t1, Condition("bne"), Operands.ZERO)
)
self._current_function.add_instruction(
RiscV.li(dest, Operands.Immediate(1))
)
self._current_function.add_label(label_neq_zero)
return dest
def visitUnaryMinusExpr(self, ctx) -> Operands.Temporary: def visitUnaryMinusExpr(self, ctx) -> Operands.Temporary:
dest = self._current_function.fdata.fresh_tmp() raise NotImplementedError("unaryminusexpr") # TODO
self._current_function.add_instruction(
RiscV.sub(dest, Operands.ZERO, self.visit(ctx.expr()))
)
return dest
def visitProgRule(self, ctx) -> None: def visitProgRule(self, ctx) -> None:
self.visitChildren(ctx) self.visitChildren(ctx)
@ -254,25 +160,8 @@ class MiniCCodeGen3AVisitor(MiniCVisitor):
def visitIfStat(self, ctx) -> None: def visitIfStat(self, ctx) -> None:
if self._debug: if self._debug:
print("if statement") print("if statement")
else_label = self._current_function.fdata.fresh_label("else_if")
end_if_label = self._current_function.fdata.fresh_label("end_if") end_if_label = self._current_function.fdata.fresh_label("end_if")
raise NotImplementedError() # TODO
self._current_function.add_instruction(
RiscV.conditional_jump(
else_label, self.visit(ctx.expr()),
Condition('beq'), Operands.ZERO
)
)
self.visit(ctx.stat_block()[0])
self._current_function.add_instruction(
RiscV.jump(end_if_label)
)
self._current_function.add_label(else_label)
if len(ctx.stat_block()) > 1:
self.visit(ctx.stat_block()[1])
self._current_function.add_label(end_if_label) self._current_function.add_label(end_if_label)
def visitWhileStat(self, ctx) -> None: def visitWhileStat(self, ctx) -> None:
@ -281,31 +170,7 @@ class MiniCCodeGen3AVisitor(MiniCVisitor):
print(Trees.toStringTree(ctx.expr(), [], self._parser)) print(Trees.toStringTree(ctx.expr(), [], self._parser))
print("and block is:") print("and block is:")
print(Trees.toStringTree(ctx.stat_block(), [], self._parser)) print(Trees.toStringTree(ctx.stat_block(), [], self._parser))
raise NotImplementedError() # TODO
# ltest <- fresh_label()
loop_test = self._current_function.fdata.fresh_label("while_test")
# lendwhile <- fresh_label()
end_while = self._current_function.fdata.fresh_label("end_while")
# code.addLabel(ltest)
self._current_function.add_label(loop_test)
# t1 <- GenCodeExpr(b)
# code.add("beq lendwhile, t1, 0")
self._current_function.add_instruction(
RiscV.conditional_jump(
end_while, self.visit(ctx.expr()),
Condition('beq'), Operands.ZERO
)
)
# GenCodeSmt(S) # execute S
self.visit(ctx.stat_block())
# code.add("j ltest") # and jump to the test
self._current_function.add_instruction(
RiscV.jump(loop_test)
)
# code.addLabel(lendwhile) # else it is done.
self._current_function.add_label(end_while)
# visit statements # visit statements
def visitPrintlnintStat(self, ctx) -> None: def visitPrintlnintStat(self, ctx) -> None:
@ -329,79 +194,3 @@ class MiniCCodeGen3AVisitor(MiniCVisitor):
for stat in ctx.stat(): for stat in ctx.stat():
self._current_function.add_comment(Trees.toStringTree(stat, [], self._parser)) self._current_function.add_comment(Trees.toStringTree(stat, [], self._parser))
self.visit(stat) self.visit(stat)
def visitForStat(self, ctx) -> None:
def immediate_to_tmp(op):
if not isinstance(op, Operands.Immediate):
return op
new_op = self._current_function.fdata.fresh_tmp()
self._current_function.add_instruction(
RiscV.li(new_op, op))
return new_op
from_t = immediate_to_tmp(self.visit(ctx.expr(0)))
to_t = immediate_to_tmp(self.visit(ctx.expr(1)))
stride = Operands.Immediate(1)
if len(ctx.expr()) > 2:
stride = self.visit(ctx.expr(2))
stride = immediate_to_tmp(stride)
name = ctx.ID().getText()
if name not in self._symbol_table:
raise MiniCInternalError(
"Variable {} has not been declared before for loop".format(name))
variable = self._symbol_table[name] # variable acting as counter
for_test = self._current_function.fdata.fresh_label("forF_test")
end_for = self._current_function.fdata.fresh_label("end_forF")
body_for = self._current_function.fdata.fresh_label("body_forF")
neg_stride = self._current_function.fdata.fresh_label("neg_stride_forF")
counter = self._current_function.fdata.fresh_tmp() # real counter not affected by var. changes
# counter <- from
self._current_function.add_instruction(
RiscV.mv(counter, from_t))
#* for_test:
# var <- counter
# bge 0 stride neg_stride
# (positive stride here)
# ble counter to end_for
# j body
self._current_function.add_label(for_test)
self._current_function.add_instruction(
RiscV.mv(variable, counter))
self._current_function.add_instruction(
RiscV.conditional_jump(
neg_stride, Operands.ZERO,
Condition(MiniCParser.GTEQ), stride
))
self._current_function.add_instruction(
RiscV.conditional_jump(
end_for, counter,
Condition(MiniCParser.GTEQ), to_t
))
self._current_function.add_instruction(
RiscV.jump(body_for))
#* neg_stride:
# bl to counter end_for
self._current_function.add_label(neg_stride)
self._current_function.add_instruction(
RiscV.conditional_jump(
end_for, to_t,
Condition(MiniCParser.GTEQ), counter
))
#* body:
# <body>
# counter <- counter + stride
# j for_test
self._current_function.add_label(body_for)
self.visit(ctx.stat_block())
self._current_function.add_instruction(
RiscV.add(counter, counter, stride))
self._current_function.add_instruction(
RiscV.jump(for_test))
#* end_for:
self._current_function.add_label(end_for)

View File

@ -1,10 +0,0 @@
#include "printlib.h"
int main() {
println_bool(true + false);
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 4 col 15: invalid type for additive operands: boolean and boolean

View File

@ -1,16 +0,0 @@
#include "printlib.h"
int main() {
bool x, y;
if (x <= y) {
println_string("ok");
}
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 6 col 6: invalid type for non numeric type: boolean

View File

@ -1,14 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
x = 5;
y = 0;
println_int(x/0);
return 0;
}
// SKIP TEST EXPECTED
// EXECCODE 1
// EXPECTED
// Division by 0

View File

@ -1,15 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
if (x != 0) {
y = 12;
} else {
y = -3;
}
println_int(y);
return 0;
}
// EXPECTED
// -3

View File

@ -1,27 +0,0 @@
#include "printlib.h"
int main() {
int num, result, i;
int prev1, prev2, tmp;
result = -1;
num = 15;
if (num < 2) {
result = num;
} else {
prev1 = 1;
prev2 = 0;
for i=2 to num {
tmp = prev1;
prev1 = prev1 + prev2;
prev2 = tmp;
}
result = prev1+prev2;
}
println_int(result);
return 0;
}
// SKIP TEST EXPECTED
// EXPECTED
// 610

View File

@ -1,16 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
if (x) {
y = 5;
}
println_int(y);
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 6 col 2: invalid type for non boolean as condition: integer

View File

@ -1,15 +0,0 @@
#include "printlib.h"
int main() {
int x;
int y;
while (x < 5000) {
y = x+1;
x = y+1;
}
println_int(x);
return 0;
}
// EXPECTED
// 5000

View File

@ -1,19 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
x = 5;
y = 3;
println_int(x%y);
println_int((-x)%y);
y = 0;
println_int(x%y);
return 0;
}
// SKIP TEST EXPECTED
// EXECCODE 1
// EXPECTED
// 2
// -2
// Division by 0

View File

@ -1,12 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
x = 12;
y = 5;
println_int(x*y);
return 0;
}
// EXPECTED
// 60

View File

@ -1,33 +0,0 @@
#include "printlib.h"
int main() {
if (true) {
if (false) {
println_int(-1);
} else {
println_int(1);
}
} else {
println_int(-1);
}
if (false) {
if (false) {
println_int(-1);
} else {
println_int(-1);
}
} else {
if (true) {
println_int(2);
} else {
println_int(-1);
}
}
return 0;
}
// EXPECTED
// 1
// 2

View File

@ -1,25 +0,0 @@
#include "printlib.h"
int main() {
int x, y, z;
while (x < 12) {
while (x < 25) {
x = x+2;
}
}
println_int(x);
x = 0;
while (x < 5) {
x = x+1;
y = y+x;
while (z < 3) {
z = z+y;
}
}
println_int(z);
return 0;
}
// EXPECTED
// 26
// 3

View File

@ -1,14 +0,0 @@
#include "printlib.h"
int main() {
bool x, y;
x = true;
y = false;
println_bool(!x);
println_bool(!y);
return 0;
}
// EXPECTED
// 0
// 1

View File

@ -1,11 +0,0 @@
#include "printlib.h"
int main() {
println_int(!(12+2));
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 4 col 14: invalid type for NOT: only boolean allowed: integer

View File

@ -1,12 +0,0 @@
#include "printlib.h"
int main() {
bool x, y;
x = true;
y = false;
println_bool(x || y);
return 0;
}
// EXPECTED
// 1

View File

@ -1,14 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
println_bool(true);
println_bool(y+2);
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 7 col 2: invalid type for println_bool statement: integer

View File

@ -1,14 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
println_float(15.0);
println_float(y+2);
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 7 col 2: invalid type for println_float statement: integer

View File

@ -1,35 +0,0 @@
#include "printlib.h"
int main() {
println_bool(1 < 2);
println_bool(1 < 1);
println_bool(2 < 1);
println_bool(1 <= 2);
println_bool(1 <= 1);
println_bool(2 <= 1);
println_bool(1 > 2);
println_bool(1 > 1);
println_bool(2 > 1);
println_bool(1 >= 2);
println_bool(1 >= 1);
println_bool(2 >= 1);
return 0;
}
// EXPECTED
// 1
// 0
// 0
// 1
// 1
// 0
// 0
// 0
// 1
// 0
// 1
// 1

View File

@ -1,13 +0,0 @@
#include "printlib.h"
int main() {
int x;
while (x < 12) {
x = x+2;
}
println_int(x);
return 0;
}
// EXPECTED
// 12

View File

@ -1,17 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
while (x) {
y = 5;
x = x+1;
}
println_int(y);
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 6 col 2: invalid type for non boolean as condition: integer

View File

@ -1,32 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
int zero, trois;
trois = 3;
// simple loop
for x=zero to trois {
y = y+3;
}
println_int(y);
println_int(x);
// inversed loop
for x=5 to 1 by -2 {
println_int(x);
}
// empty loop
for x=5 to 0 {
println_int(-1);
}
return 0;
}
// SKIP TEST EXPECTED
// EXPECTED
// 9
// 3
// 5
// 3

View File

@ -1,18 +0,0 @@
#include "printlib.h"
int main() {
int i, count;
for i=0 to 6 {
for i=0 to 6 {
count = count + 1;
}
}
println_int(count);
return 0;
}
// SKIP TEST EXPECTED
// EXPECTED
// 36

View File

@ -1,17 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
float fl;
fl = 12.0;
for x=fl to 3 {
y = y+3;
}
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 8 col 2: invalid type for non-integer from value: float

View File

@ -1,17 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
float fl;
fl = 12.0;
for fl=0 to 3 {
y = y+3;
}
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 8 col 2: invalid type for non-integer for loop counter: float

View File

@ -1,15 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
for x=0 to 3 by 1.0 {
y = y+3;
}
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 6 col 2: invalid type for non-integer stride value: float

View File

@ -1,17 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
float fl;
fl = 12.0;
for x=0 to fl {
y = y+3;
}
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 8 col 2: invalid type for non-integer to value: float

View File

@ -1,15 +0,0 @@
#include "printlib.h"
int main() {
int x, y;
for undef=0 to 3 {
y = y+3;
}
return 0;
}
// SKIP TEST EXPECTED
// EXITCODE 2
// EXPECTED
// In function main: Line 6 col 2: Undefined variable undef

View File

@ -5,8 +5,8 @@ Functions to convert a CFG into SSA Form.
from typing import List, Dict, Set from typing import List, Dict, Set
from Lib.CFG import Block, CFG from Lib.CFG import Block, CFG
from Lib.Operands import Renamer, Operand from Lib.Operands import Renamer
from Lib.Statement import Instruction, Label from Lib.Statement import Instruction
from Lib.PhiNode import PhiNode from Lib.PhiNode import PhiNode
from Lib.Dominators import computeDom, computeDT, computeDF from Lib.Dominators import computeDom, computeDT, computeDF
@ -25,14 +25,8 @@ def insertPhis(cfg: CFG, DF: Dict[Block, Set[Block]]) -> None:
d = queue.pop(0) d = queue.pop(0)
for b in DF[d]: for b in DF[d]:
if b not in has_phi: if b not in has_phi:
srcs: Dict[Label, Operand] = { # TODO add a phi node in block `b` (Lab 5a, Exercise 4)
x.get_label(): var for x in b.get_in() raise NotImplementedError("insertPhis")
}
phi = PhiNode(var, srcs)
b.add_phi(phi)
queue.append(b)
has_phi.add(b)
def rename_block(cfg: CFG, DT: Dict[Block, Set[Block]], renamer: Renamer, b: Block) -> None: def rename_block(cfg: CFG, DT: Dict[Block, Set[Block]], renamer: Renamer, b: Block) -> None:
@ -49,8 +43,7 @@ def rename_block(cfg: CFG, DT: Dict[Block, Set[Block]], renamer: Renamer, b: Blo
for i in succ.get_phis(): for i in succ.get_phis():
assert (isinstance(i, PhiNode)) assert (isinstance(i, PhiNode))
i.rename_from(renamer, b.get_label()) i.rename_from(renamer, b.get_label())
for succ in DT[b]: # TODO recursive call(s) of rename_block (Lab 5a, Exercise 5)
rename_block(cfg, DT, renamer, succ)
def rename_variables(cfg: CFG, DT: Dict[Block, Set[Block]]) -> None: def rename_variables(cfg: CFG, DT: Dict[Block, Set[Block]]) -> None:
@ -61,8 +54,7 @@ def rename_variables(cfg: CFG, DT: Dict[Block, Set[Block]]) -> None:
This is an helper function called during SSA entry. This is an helper function called during SSA entry.
""" """
renamer = Renamer(cfg.fdata._pool) renamer = Renamer(cfg.fdata._pool)
for b in cfg.get_entries(): # TODO initial call(s) to rename_block (Lab 5a, Exercise 5)
rename_block(cfg, DT, renamer, b)
def enter_ssa(cfg: CFG, dom_graphs=False, basename="prog") -> None: def enter_ssa(cfg: CFG, dom_graphs=False, basename="prog") -> None:
@ -74,8 +66,5 @@ def enter_ssa(cfg: CFG, dom_graphs=False, basename="prog") -> None:
`dom_graphs` indicates if we have to print the domination graphs. `dom_graphs` indicates if we have to print the domination graphs.
`basename` is used for the names of the produced graphs. `basename` is used for the names of the produced graphs.
""" """
dom = computeDom(cfg) # TODO implement this function (Lab 5a, Exercise 2)
DT = computeDT(cfg, dom, dom_graphs, basename) raise NotImplementedError("enter_ssa")
DF = computeDF(cfg, dom, DT, dom_graphs, basename)
insertPhis(cfg, DF)
rename_variables(cfg, DT)

View File

@ -6,14 +6,14 @@ Functions to convert a CFG out of SSA Form.
from typing import cast, List from typing import cast, List
from Lib import RiscV from Lib import RiscV
from Lib.CFG import Block, BlockInstr, CFG from Lib.CFG import Block, BlockInstr, CFG
from Lib.Operands import Temporary, DataLocation from Lib.Operands import Temporary
from Lib.Statement import AbsoluteJump, Label from Lib.Statement import AbsoluteJump
from Lib.Terminator import BranchingTerminator, Return from Lib.Terminator import BranchingTerminator, Return
from Lib.PhiNode import PhiNode from Lib.PhiNode import PhiNode
from TP05.SequentializeMoves import sequentialize_moves, generate_smart_move from TP05.SequentializeMoves import sequentialize_moves
def generate_moves_from_phis(phis: List[PhiNode], parent: Block, is_smart: bool=False) -> List[BlockInstr]: def generate_moves_from_phis(phis: List[PhiNode], parent: Block) -> List[BlockInstr]:
""" """
`generate_moves_from_phis(phis, parent)` builds a list of move instructions `generate_moves_from_phis(phis, parent)` builds a list of move instructions
to be inserted in a new block between `parent` and the block with phi nodes to be inserted in a new block between `parent` and the block with phi nodes
@ -21,32 +21,10 @@ def generate_moves_from_phis(phis: List[PhiNode], parent: Block, is_smart: bool=
This is an helper function called during SSA exit. This is an helper function called during SSA exit.
""" """
# (Lab 5a, Exercise 6)
lbl = parent.get_label()
if is_smart:
parallel_moves: set[tuple[DataLocation, DataLocation]] = set()
moves: List[BlockInstr] = [] moves: List[BlockInstr] = []
for phi in phis: # TODO compute 'moves', a list of 'mv' instructions to insert under parent
if lbl not in phi.get_srcs(): # (Lab 5a, Exercise 6)
continue return moves
src = phi.get_srcs()[lbl]
if isinstance(src, Temporary) or isinstance(phi.var, Temporary):
loc1, loc2 = phi.var, src
if isinstance(loc1, Temporary):
loc1 = loc1.get_alloced_loc()
if isinstance(loc2, Temporary):
loc2 = loc2.get_alloced_loc()
moves += generate_smart_move(loc1, cast(DataLocation, loc2))
else:
src = phi.get_srcs()[lbl]
parallel_moves.add((phi.var, cast(DataLocation, src)))
return sequentialize_moves(parallel_moves)+moves
return [
RiscV.mv(
phi.var,
phi.get_srcs()[lbl]
) for phi in phis if lbl in phi.get_srcs()
]
def exit_ssa(cfg: CFG, is_smart: bool) -> None: def exit_ssa(cfg: CFG, is_smart: bool) -> None:
@ -60,22 +38,7 @@ def exit_ssa(cfg: CFG, is_smart: bool) -> None:
b.remove_all_phis() # Remove all phi nodes in the block b.remove_all_phis() # Remove all phi nodes in the block
parents: List[Block] = b.get_in().copy() # Copy as we modify it by adding blocks parents: List[Block] = b.get_in().copy() # Copy as we modify it by adding blocks
for parent in parents: for parent in parents:
# Add the block containing 'moves' to 'cfg' moves = generate_moves_from_phis(phis, parent)
moves_label = cfg.fdata.fresh_label("merge_phi") # TODO Add the block containing 'moves' to 'cfg'
block_moves = Block(moves_label, generate_moves_from_phis(phis, parent, is_smart=is_smart), AbsoluteJump(b.get_label())) # and update edges and jumps accordingly (Lab 5a, Exercise 6)
cfg.add_block(block_moves) raise NotImplementedError("exit_ssa")
# Update parent terminator
j = parent.get_terminator()
match j:
case AbsoluteJump():
new_terminator = AbsoluteJump(moves_label)
case BranchingTerminator():
lbl_else : Label = moves_label if (j.label_else == b.get_label()) else j.label_else
lbl_then : Label = moves_label if (j.label_then == b.get_label()) else j.label_then
new_terminator = BranchingTerminator(j.cond, j.op1, j.op2, lbl_else, lbl_then)
case Return():
new_terminator = AbsoluteJump(moves_label)
block_moves.set_terminator(Return())
parent.set_terminator(new_terminator)

View File

@ -1,6 +1,6 @@
from typing import Dict, Set, Tuple from typing import Dict, Set, Tuple
from Lib.Operands import Temporary from Lib.Operands import Temporary
from Lib.Statement import Statement, regset_to_string, Instru3A from Lib.Statement import Statement, regset_to_string
from Lib.CFG import Block, CFG from Lib.CFG import Block, CFG
from Lib.PhiNode import PhiNode from Lib.PhiNode import PhiNode
@ -35,41 +35,16 @@ class LivenessSSA:
def livein_at_instruction(self, block: Block, pos: int, var: Temporary) -> None: def livein_at_instruction(self, block: Block, pos: int, var: Temporary) -> None:
"""Backward propagation of liveness information at the beginning of an instruction.""" """Backward propagation of liveness information at the beginning of an instruction."""
instr = block.get_all_statements()[pos] raise NotImplementedError("LivenessSSA") # TODO (Lab 5b, Exercise 1)
if isinstance(instr, PhiNode) and var in instr.srcs.values():
bpred = self._cfg.get_block(
next(lbl for lbl, value in instr.srcs.items() if value == var)
)
self.liveout_at_block(bpred, var)
elif pos == 0:
for bpred in block.get_in():
self.liveout_at_block(bpred, var)
else:
self.liveout_at_instruction(block, pos-1, var)
def liveout_at_instruction(self, block: Block, pos: int, var: Temporary) -> None: def liveout_at_instruction(self, block: Block, pos: int, var: Temporary) -> None:
"""Backward propagation of liveness information at the end of an instruction.""" """Backward propagation of liveness information at the end of an instruction."""
instr = block.get_all_statements()[pos] instr = block.get_all_statements()[pos]
raise NotImplementedError("LivenessSSA") # TODO (Lab 5b, Exercise 1)
self._liveout[block, instr].add(var)
if var in instr.defined():
#self._seen[block].add(var)
return
self.livein_at_instruction(block, pos, var)
#self._seen[block].add(var)
def liveout_at_block(self, block: Block, var: Temporary) -> None: def liveout_at_block(self, block: Block, var: Temporary) -> None:
"""Backward propagation of liveness information at the end of a block.""" """Backward propagation of liveness information at the end of a block."""
if var not in self._seen[block]: raise NotImplementedError("LivenessSSA") # TODO (Lab 5b, Exercise 1)
self._seen[block].add(var)
self.liveout_at_instruction(block, len(block.get_all_statements())-1, var)
def gather_uses(self) -> Dict[Temporary, Set[Tuple[Block, int]]]: def gather_uses(self) -> Dict[Temporary, Set[Tuple[Block, int]]]:
""" """
@ -92,9 +67,7 @@ class LivenessSSA:
def conflict_on_phis(self) -> None: def conflict_on_phis(self) -> None:
"""Ensures that variables defined by φ instructions are in conflict with one-another.""" """Ensures that variables defined by φ instructions are in conflict with one-another."""
for block in self._cfg.get_blocks(): raise NotImplementedError("LivenessSSA") # TODO (Lab 5b, Exercise 1)
for phinode in block.get_phis():
self._liveout[block, phinode] = set([v for v in phinode.used() if isinstance(v, Temporary)])
def print_map_in_out(self) -> None: # pragma: no cover def print_map_in_out(self) -> None: # pragma: no cover
"""Print live out sets at each instruction, group by block, useful for debugging!""" """Print live out sets at each instruction, group by block, useful for debugging!"""

View File

@ -18,33 +18,11 @@ def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInst
This is an helper function for `sequentialize_moves`. This is an helper function for `sequentialize_moves`.
""" """
instr: List[BlockInstr] = [] instr: List[BlockInstr] = []
tmp: Register = S[1] # TODO Compute the moves (Lab 5b, Exercise 4)
raise NotImplementedError("generate_smart_move")
match dest, src:
case Register(), Register():
instr.append(RiscV.mv(dest, src))
case Register(), Offset():
instr.append(RiscV.ld(dest, src))
case Offset(), Register():
instr.append(RiscV.sd(src, dest))
case Offset(), Offset():
instr.append(RiscV.ld(tmp, src))
instr.append(RiscV.sd(tmp, dest))
case _, _:
raise ValueError(f"Unsupported operands {type(dest)} <- {type(src)}")
return instr return instr
def swap_registers(r1: Register, r2: Register) -> List[BlockInstr]:
"""Swap two registers"""
return [
RiscV.xor(r1, r1, r2),
RiscV.xor(r2, r1, r2),
RiscV.xor(r1, r1, r2)
]
def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]] def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
) -> List[BlockInstr]: ) -> List[BlockInstr]:
""" """
@ -61,39 +39,22 @@ def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
move_graph.add_edge((src, dest)) move_graph.add_edge((src, dest))
# List for the sequentialized moves to do # List for the sequentialized moves to do
# Convention: in moves we put (dest, src) for each move # Convention: in moves we put (dest, src) for each move
moves: List[Tuple[DataLocation, DataLocation] | BlockInstr] = [] moves: List[Tuple[DataLocation, DataLocation]] = []
# First iteratively remove all the vertices without successors # First iteratively remove all the vetices without successors
vars_without_successor = {src vars_without_successor = {src
for src, dests in move_graph.neighbourhoods() for src, dests in move_graph.neighbourhoods()
if len(dests) == 0} if len(dests) == 0}
while vars_without_successor: while vars_without_successor:
var = vars_without_successor.pop() # TODO Remove the leaves iteratively (Lab 5b, Exercise 4)
for src in move_graph.pred(var): raise NotImplementedError("sequentialize_moves: leaves")
moves.append((var, src))
dests = [dests for sr, dests in move_graph.neighbourhoods() if sr == src][0]
if len(dests) == 1:
vars_without_successor.add(src)
move_graph.delete_vertex(var)
# Then handle the cycles # Then handle the cycles
cycles: List = move_graph.connected_components() cycles: List = move_graph.connected_components()
for cycle in cycles: for cycle in cycles:
if len(cycle) == 1: # TODO Handle each cycle (Lab 5b, Exercise 4)
continue raise NotImplementedError("sequentialize_moves: cycles")
if len(cycle) == 2 and isinstance(cycle[0], Register) and isinstance(cycle[1], Register):
moves += swap_registers(*cycle)
continue
previous = tmp
for var in reversed(cycle):
moves.append((previous, var))
previous = var
moves.append((previous, tmp))
# Transform the moves to do in actual RiscV instructions # Transform the moves to do in actual RiscV instructions
moves_instr: List[BlockInstr] = [] moves_instr: List[BlockInstr] = []
for val in moves: for dest, src in moves:
if isinstance(val, BlockInstr): instrs = generate_smart_move(dest, src)
moves_instr.append(val)
continue
instrs = generate_smart_move(*val)
moves_instr.extend(instrs) moves_instr.extend(instrs)
return moves_instr return moves_instr

View File

@ -1,12 +1,11 @@
from typing import List, Dict from typing import List, Dict
from Lib.Errors import MiniCInternalError from Lib.Errors import MiniCInternalError
from Lib.Operands import Temporary, Operand, S, Offset, DataLocation, GP_REGS from Lib.Operands import Temporary, Operand, S, Offset, DataLocation, GP_REGS
from Lib.Statement import Instruction, Instru3A from Lib.Statement import Instruction
from Lib.Allocator import Allocator from Lib.Allocator import Allocator
from Lib.FunctionData import FunctionData from Lib.FunctionData import FunctionData
from Lib import RiscV from Lib import RiscV
from Lib.Graphes import Graph # For Graph coloring utility functions from Lib.Graphes import Graph # For Graph coloring utility functions
from TP05.SequentializeMoves import generate_smart_move
class SmartAllocator(Allocator): class SmartAllocator(Allocator):
@ -29,27 +28,9 @@ class SmartAllocator(Allocator):
before: List[Instruction] = [] before: List[Instruction] = []
after: List[Instruction] = [] after: List[Instruction] = []
new_args: List[Operand] = [] new_args: List[Operand] = []
# TODO (lab5): Compute before, after, subst. This is similar to what
for arg in old_instr.defined(): # TODO (lab5): replace from the Naive and AllInMem Allocators do (Lab 4).
match arg: raise NotImplementedError("Smart Replace (lab5)") # TODO
case Offset():
after.append(RiscV.sd(S[3], arg))
new_args.append(S[3])
case Temporary():
new_args.append(arg.get_alloced_loc())
case _: # Contains Register()
new_args.append(arg)
for i, arg in enumerate(old_instr.used(), 1):
match arg:
case Offset():
before.append(RiscV.ld(S[i], arg))
new_args.append(S[i])
case Temporary():
new_args.append(arg.get_alloced_loc())
case _: # Contains Register()
new_args.append(arg)
# And now return the new list! # And now return the new list!
instr = old_instr.with_args(new_args) instr = old_instr.with_args(new_args)
return before + [instr] + after return before + [instr] + after
@ -89,12 +70,7 @@ class SmartAllocator(Allocator):
# Iterate over self._liveness._liveout (dictionary containing all # Iterate over self._liveness._liveout (dictionary containing all
# live out temporaries for each instruction), and for each conflict use # live out temporaries for each instruction), and for each conflict use
# self._igraph.add_edge((t1, t2)) to add the corresponding edge. # self._igraph.add_edge((t1, t2)) to add the corresponding edge.
for (block, statement), vars in self._liveness._liveout.items(): raise NotImplementedError("build_interference_graph (lab5)") # TODO
for t1 in list(vars)+statement.defined():
for t2 in vars:
if t1 == t2:
continue
self._igraph.add_edge((t1, t2))
def smart_alloc(self) -> None: def smart_alloc(self) -> None:
""" """
@ -103,7 +79,6 @@ class SmartAllocator(Allocator):
Precondition: the interference graph _igraph must have been built. Precondition: the interference graph _igraph must have been built.
""" """
regs = list(GP_REGS) # Get a writable copy
# Checking the interference graph has been built # Checking the interference graph has been built
if not self._igraph: if not self._igraph:
raise MiniCInternalError("Empty interference graph in the Smart Allocator") raise MiniCInternalError("Empty interference graph in the Smart Allocator")
@ -117,15 +92,7 @@ class SmartAllocator(Allocator):
alloc_dict: Dict[Temporary, DataLocation] = dict() alloc_dict: Dict[Temporary, DataLocation] = dict()
# Use the coloring `coloringreg` to fill `alloc_dict`. # Use the coloring `coloringreg` to fill `alloc_dict`.
# Our version is less than 5 lines of code. # Our version is less than 5 lines of code.
color_dict: Dict[int, DataLocation] = dict() raise NotImplementedError("Allocation based on graph coloring (lab5)") # TODO
for temp in self._fdata._pool.get_all_temps():
if coloringreg[temp] not in color_dict:
color_dict[coloringreg[temp]] = (
regs.pop() if len(regs) > 0 else
self._fdata.fresh_offset()
)
alloc_dict[temp] = color_dict[coloringreg[temp]]
if self._debug: if self._debug:
print("Allocation:") print("Allocation:")
print(alloc_dict) print(alloc_dict)

View File

@ -85,7 +85,6 @@ ALL_IN_MEM_FILES.sort()
ALL_FILES = list(set(ALL_FILES)) ALL_FILES = list(set(ALL_FILES))
ALL_FILES.sort() ALL_FILES.sort()
class TestCodeGen(TestExpectPragmas, TestCompiler): class TestCodeGen(TestExpectPragmas, TestCompiler):
DISABLE_CODEGEN = DISABLE_CODEGEN DISABLE_CODEGEN = DISABLE_CODEGEN
SKIP_NOT_IMPLEMENTED = SKIP_NOT_IMPLEMENTED SKIP_NOT_IMPLEMENTED = SKIP_NOT_IMPLEMENTED

View File

@ -31,7 +31,7 @@ _Academic first semester 2024-2025_
# Week 3: # Week 3:
- :hammer: Lab 2: Thursday 23/09/2024, 13h30-15h30. Room E001 103 & -138 (Grenat) (Samuel Humeau & Emma Nardino) - :hammer: Lab 2: Thursday 23/09/2023, 13h30-15h30. Room E001 103 & -138 (Grenat) (Samuel Humeau & Emma Nardino)
* Lexing & Parsing with ANTLR4 [TP02](TP02/tp2.pdf). * Lexing & Parsing with ANTLR4 [TP02](TP02/tp2.pdf).
* Code in [TP02/](TP02/). * Code in [TP02/](TP02/).
@ -64,84 +64,3 @@ _Academic first semester 2024-2025_
* SSA [slides in english](course/capmif_cours06a_ssa.pdf). * SSA [slides in english](course/capmif_cours06a_ssa.pdf).
# Week 6:
- :hammer: Lab 4b: Monday 14/10/2024, 13h30-15h30. Room E001 (Samuel Humeau & Emma Nardino)
* Control Flow Graph [TP04b](TP04/tp4b.pdf).
* Code in [MiniC/TP04/](MiniC/TP04/).
* Documentation (updated) [here](docs/html/index.html).
- :book: Course: Thursday 17/10/2024, 10h15-12h15. Amphi L (Gabriel Radanne)
* Register allocation [slides in english](course/cap_cours07_regalloc.pdf).
# Week 7:
- :hammer: Lab 5a: Monday 21/10/2024, 13h30-15h30. Room E001 (Samuel Humeau & Emma Nardino)
* Control Flow Graph under SSA Form [TP05a](TP05/tp5a.pdf).
* Code in [MiniC/TP05/](MiniC/TP05/).
* Documentation (updated) [here](docs/html/index.html).
- :book: Course: Thursday 25/10/2024, 10h15-12h15. Amphi B (Gabriel Radanne)
* SSA Optims [slides in english](course/cap_cours06b_ssa_optim.pdf).
# Week 8:
- :hammer: Lab 5b (1/2): Monday 04/11/2024, 13h30-15h30. Room E001 (Samuel Humeau & Emma Nardino)
* Smart Register Allocation [TP05b](TP05/tp5b.pdf).
* Code in [MiniC/TP04/](MiniC/TP05/).
- :book: Course: Thursday 7/11/2024, 10h15-12h15. Amphi B (Gabriel Radanne)
* Beyond Imperative [slides in english](course/cap_cours_bonuscomp.pdf).
# Week 9:
- :hammer: Lab 5b (2/2): Monday 18/11/2024, 13h30-15h30. Room E001 (Samuel Humeau & Emma Nardino)
- :book: Course: Thursday 21/11/2024, 10h15-12h15. Amphi J (Yannick Zakowski)
* Functions: code generation [slides in english](course/cap_cours08_func_codegen.pdf).
# Week 10:
- :notebook: TD: Monday 25/11/2024, 13h30-15h30. Room E001 (Samuel Humeau & Emma Nardino)
- :book: Course: Thursday 28/11/2024, 10h15-12h15. Amphi B (Yannick Zakowski)
* Functions: semantics [slides in english](course/cap_cour309_func_semantics.pdf).
# Week 11:
- :hammer: Choice Lab (1/3): Monday 02/12/2024, 8h00-13h30. Room E001 (Samuel Humeau & Emma Nardino)
* Optimisations under SSA form [TP5c](TP05/tp5c.pdf), code in [MiniC/TPoptim/](MiniC/TPoptim/).
* Parsing and typechecking functions [TP06a](TP06/tp6a.pdf), code in [MiniC/](MiniC/).
* Code generation for functions [TP06b](TP06/tp6b.pdf), code in [MiniC/](MiniC/).
- :book: Course: Thursday 05/12/2024, 10h15-12h15. Amphi B (Yannick Zakowski)
* On parallelism [slides in english](course/cap_cours10_parallelism.pdf).
# Week 12:
- :hammer: Choice Lab (2/3): Thursday 09/12/2024, 13h30-15h30. Room E001 (Samuel Humeau & Emma Nardino)
* Optimisations under SSA form [TP5c](TP05/tp5c.pdf), code in [MiniC/TPoptim/](MiniC/TPoptim/).
* Parsing and typechecking functions [TP06a](TP06/tp6a.pdf), code in [MiniC/](MiniC/).
* Code generation for functions [TP06b](TP06/tp6b.pdf), code in [MiniC/](MiniC/).
* Going Parallel with futures [TPfutures](TPfutures/tpfutures.pdf), code in [TPfutures/MiniC-futures/](TPfutures/MiniC-futures/).
- :book: Course: Thursday 12/12/2024, 10h15-12h15. Amphi B (Yannick Zakowski)
* Verified Compilation [introduction slides](course/cap_cours11_verified.pdf).
* Course on black board
* Additional resources: [Xavier Leroy's class at Collège de France](https://www.college-de-france.fr/en/agenda/lecture/mechanized-semantics-when-the-machine-reasons-about-its-languages)
# Week 13:
- :hammer: Choice Lab (3/3): Monday 16/12/2024, 13h30-15h30. Room E001 (Samuel Humeau & Emma Nardino)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,15 +0,0 @@
/MiniCLexer.py
/MiniCParser.py
/MiniCVisitor.py
/MiniCListener.py
*.dot
*.dot.pdf
*.riscv
*-naive.s
*-gcc.s
*-all_in_mem.s
*-smart.s
*.cfut
*.o
/MiniC.interp
/MiniCLexer.interp

View File

@ -1,14 +0,0 @@
class MiniCRuntimeError(Exception):
pass
class MiniCInternalError(Exception):
pass
class MiniCUnsupportedError(Exception):
pass
class MiniCTypeError(Exception):
pass

View File

@ -1,56 +0,0 @@
PACKAGE = MiniC
# Example: stop at the first failed test:
# make PYTEST_OPTS=-x tests
PYTEST_OPTS =
# Run the whole test infrastructure for a subset of test files e.g.
# make TEST_FILES='TP03/**/bad*.c' tests
ifdef TEST_FILES
export TEST_FILES
endif
PYTEST_BASE_OPTS=-vv -rs --failed-first --cov="$(PWD)" --cov-report=term --cov-report=html
ifndef ANTLR4
abort:
$(error variable ANTLR4 is not set)
endif
all: antlr
.PHONY: antlr
antlr MiniCLexer.py MiniCParser.py: $(PACKAGE).g4
$(ANTLR4) $< -Dlanguage=Python3 -visitor
main-deps: MiniCLexer.py MiniCParser.py MiniCTypingVisitor.py MiniCPPListener.py
%.o: %.c $(HEADERS)
gcc -g -c -Wall -Wextra $< -o $@
$(TESTFILE:%.c=%.o): $(TESTFILE:%.c=%.cfut) $(HEADERS)
gcc -g -c -Iinclude -Wall -Wextra -x c $(TESTFILE:%.c=%.cfut) -o $(TESTFILE:%.c=%.o)
$(TESTFILE:%.c=%.out): $(TESTFILE:%.c=%.o) lib/futurelib.o
gcc -g $(TESTFILE:%.c=%.o) lib/futurelib.o -o $(TESTFILE:%.c=%.out) -lpthread
$(TESTFILE:%.c=%.cfut): main-deps
python3 MiniCC.py $(TESTFILE)
run: $(TESTFILE:%.c=%.out)
$(TESTFILE:%.c=%.out)
test: test_futures.py main-deps
python3 -m pytest $(PYTEST_BASE_OPTS) $(PYTEST_OPTS) ./test_futures.py
tar: clean
dir=$$(basename "$$PWD") && cd .. && \
tar cvfz "$$dir.tgz" --exclude="*.riscv" --exclude=".git" --exclude=".pytest_cache" \
--exclude="htmlcov" "$$dir"
@echo "Created ../$$(basename "$$PWD").tgz"
clean-tests:
cd tests && \
find . \( -iname "*.cfut" -or -iname "*.out" \) -print0 | xargs -0 rm -rf \;
clean: clean-tests
find . \( -iname "*~" -or -iname ".cache*" -or -iname "*.diff" -or -iname "log*.txt" -or -iname "__pycache__" -or -iname "*.tokens" -or -iname "*.interp" -or -iname "*.o" \) -print0 | xargs -0 rm -rf \;
rm -rf *~ $(PACKAGE)Parser.py $(PACKAGE)Lexer.py $(PACKAGE)Visitor.py $(PACKAGE)Listener.py .coverage .benchmarks

View File

@ -1,164 +0,0 @@
grammar MiniC;
prog: include* function* EOF #progRule;
//include statements reduced to string
include: INCLUDE STRING #includestat ;
function
: typee ID OPAR param_l? CPAR OBRACE vardecl_l block RETURN expr SCOL CBRACE #funcDef
| typee ID OPAR param_l? CPAR SCOL #funcDecl
;
vardecl_l: vardecl* #varDeclList;
vardecl: typee id_l SCOL #varDecl;
param: typee ID #paramDecl;
param_l
: param #paramListBase
| param COM param_l #paramList
;
id_l
: ID #idListBase
| ID COM id_l #idList
;
block: stat* #statList;
stat
: assignment SCOL
| if_stat
| while_stat
| print_stat
;
assignment: ID ASSIGN expr #assignStat;
if_stat: IF OPAR expr CPAR then_block=stat_block (ELSE else_block=stat_block)? #ifStat;
stat_block
: OBRACE block CBRACE
| stat
;
while_stat: WHILE OPAR expr CPAR body=stat_block #whileStat;
print_stat
: PRINTINT OPAR expr CPAR SCOL #printlnintStat
| PRINTFLOAT OPAR expr CPAR SCOL #printlnfloatStat
| PRINTBOOL OPAR expr CPAR SCOL #printlnboolStat
| PRINTSTRING OPAR expr CPAR SCOL #printstringStat
;
expr_l
: expr #exprListBase
| expr COM expr_l #exprList
;
expr
: MINUS expr #unaryMinusExpr
| NOT expr #notExpr
| expr myop=(MULT|DIV|MOD) expr #multiplicativeExpr
| expr myop=(PLUS|MINUS) expr #additiveExpr
| expr myop=(GT|LT|GTEQ|LTEQ) expr #relationalExpr
| expr myop=(EQ|NEQ) expr #equalityExpr
| expr AND expr #andExpr
| expr OR expr #orExpr
| ID OPAR expr_l? CPAR #funcCall
| GET OPAR expr CPAR #getCall
| ASYNC OPAR ID COM expr_l? CPAR #asyncFuncCall
| atom #atomExpr
;
atom
: OPAR expr CPAR #parExpr
| INT #intAtom
| FLOAT #floatAtom
| (TRUE | FALSE) #booleanAtom
| ID #idAtom
| STRING #stringAtom
;
typee
: mytype=(INTTYPE|FLOATTYPE|BOOLTYPE|STRINGTYPE|FUTINTTYPE) #basicType
;
ASYNC : 'Async';
GET : 'Get';
OR : '||';
AND : '&&';
EQ : '==';
NEQ : '!=';
GT : '>';
LT : '<';
GTEQ : '>=';
LTEQ : '<=';
PLUS : '+';
MINUS : '-';
MULT : '*';
DIV : '/';
MOD : '%';
NOT : '!';
COL: ':';
SCOL : ';';
COM : ',';
ASSIGN : '=';
OPAR : '(';
CPAR : ')';
OBRACE : '{';
CBRACE : '}';
TRUE : 'true';
FALSE : 'false';
IF : 'if';
ELSE : 'else';
WHILE : 'while';
RETURN : 'return';
PRINTINT : 'println_int';
PRINTBOOL : 'println_bool';
PRINTSTRING : 'println_string';
PRINTFLOAT : 'println_float';
FUTINTTYPE: 'futint';
INTTYPE: 'int';
FLOATTYPE: 'float';
STRINGTYPE: 'string';
BOOLTYPE : 'bool';
INCLUDE : '#include';
ID
: [a-zA-Z_] [a-zA-Z_0-9]*
;
INT
: [0-9]+
;
FLOAT
: [0-9]+ '.' [0-9]*
| '.' [0-9]+
;
STRING
: '"' (~["\r\n] | '""')* '"'
;
COMMENT
// # is a comment in Mini-C, and used for #include in real C so that we ignore #include statements
// BUT now we want to keep includes => # removed
: '//' ~[\r\n]* -> skip
;
SPACE
// here is a little for code rewriting.
: [ \t\r\n] -> channel(HIDDEN)
;

View File

@ -1,112 +0,0 @@
#! /usr/bin/env python3
"""
MiniC-futures Lab. Language Extension for MiniC with future primitives
Usage:
python3 Main.py <filename>
python3 Main.py --help
"""
import traceback
from MiniCLexer import MiniCLexer
from MiniCParser import MiniCParser
from MiniCTypingVisitor import MiniCTypingVisitor, MiniCTypeError
from MiniCPPListener import MiniCPPListener
from Errors import MiniCUnsupportedError, MiniCInternalError
import argparse
from antlr4 import FileStream, CommonTokenStream, ParseTreeWalker
from antlr4.error.ErrorListener import ErrorListener
import os
import sys
class CountErrorListener(ErrorListener):
"""Count number of errors.
Parser provides getNumberOfSyntaxErrors(), but the Lexer
apparently doesn't provide an easy way to know if an error occured
after the fact. Do the counting ourserves with a listener.
"""
def __init__(self):
super(CountErrorListener, self).__init__()
self.count = 0
def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e):
self.count += 1
def main(inputname,
typecheck=True, typecheck_only=False, stdout=False, output_name=None, debug=False):
(basename, rest) = os.path.splitext(inputname)
if not typecheck_only:
if stdout:
output_name = None
elif output_name is None:
output_name = basename + ".cfut"
input_s = FileStream(inputname, encoding='utf-8')
lexer = MiniCLexer(input_s)
counter = CountErrorListener()
lexer._listeners.append(counter)
stream = CommonTokenStream(lexer)
parser = MiniCParser(stream)
parser._listeners.append(counter)
tree = parser.prog()
if counter.count > 0:
exit(3) # Syntax or lexicography errors occurred, don't try to go further.
if typecheck:
typing_visitor = MiniCTypingVisitor()
try:
typing_visitor.visit(tree)
except MiniCTypeError as e:
print(e.args[0])
exit(2)
if typecheck_only:
if debug:
print("Not running code generation because of --disable-codegen.")
return
pw = ParseTreeWalker()
extractor = MiniCPPListener(stream)
pw.walk(extractor, tree)
with open(output_name, 'w') if output_name else sys.stdout as output:
extractor.printrw(output)
# command line management
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Generate code for .c file')
parser.add_argument('filename', type=str,
help='Source file.')
parser.add_argument('--stdout', action='store_true',
help='Generate code to stdout')
parser.add_argument('--debug', action='store_true',
default=False,
help='Emit verbose debug output')
parser.add_argument('--disable-typecheck', action='store_true',
default=False,
help="Don't run the typechecker before generating code")
parser.add_argument('--disable-codegen', action='store_true',
default=False,
help="Run only the typechecker, don't try generating code.")
parser.add_argument('--output', type=str,
help='Generate code to outfile')
args = parser.parse_args()
try:
main(args.filename,
not args.disable_typecheck, args.disable_codegen,
args.stdout, args.output, args.debug,
)
except MiniCUnsupportedError as e:
print(e)
exit(5)
except (MiniCInternalError):
traceback.print_exc()
exit(4)

View File

@ -1,27 +0,0 @@
from MiniCListener import MiniCListener
from antlr4.TokenStreamRewriter import TokenStreamRewriter
class MiniCPPListener(MiniCListener):
def __init__(self, t):
self.rewriter = TokenStreamRewriter(tokens=t)
def printrw(self, output):
output.write(self.rewriter.getText('default', 0, 1000))
def enterProgRule(self, ctx):
"""Adds an include futurelib.h at the beginning of program."""
indexprog = ctx.start.tokenIndex
self.rewriter.insertBeforeIndex(indexprog, '#include \"futurelib.h\"\n')
def exitFuncDef(self, ctx):
"""Adds a call to freeAllFutures at the end of the body of the main function."""
(indexret, endret) = ctx.RETURN().getSourceInterval()
if ctx.ID().getText() == "main":
self.rewriter.insertBeforeIndex(indexret, 'freeAllFutures();\n')
def enterAsyncFuncCall(self, ctx):
"""Adds a & for getting a function pointer to the asynchronous called function."""
indexfunid = ctx.start.tokenIndex # token of async
self.rewriter.insertBeforeIndex(indexfunid + 2, '&')

View File

@ -1,17 +0,0 @@
# Visitor to *typecheck* MiniC files
from typing import List
from MiniCVisitor import MiniCVisitor
from MiniCParser import MiniCParser
from Lib.Errors import MiniCInternalError, MiniCTypeError
from enum import Enum
# NEW: ADD FutInteger
class BaseType(Enum):
Float, Integer, Boolean, String, FutInteger = range(5)
class MiniCTypingVisitor(MiniCVisitor):
# TODO Add your own typer here
pass

View File

@ -1,25 +0,0 @@
# MiniC Compiler
LAB8 (Futures) CAP 2022-23
# Authors
YOUR NAME HERE
# Contents
TODO:
- Explain any design choices you may have made.
- Did you implement a bonus?
# Howto
`make run TESTFILE=tests/provided/test_fut0.c`: launch the compiler, then GCC and run a single file.
# Test design
TODO: explain your tests.
# Known bugs
TODO: bugs you could not fix (if any) and limitations.

View File

@ -1,12 +0,0 @@
#include "stdio.h"
typedef char * string;
typedef int bool;
static const int true = 1;
static const int false = 0;
void print_int(int i) {printf("%i",i);}
void println_int(int i) {printf("%i\n",i);}
void print_string(string);
void println_string(string);

View File

@ -1,34 +0,0 @@
#include <pthread.h>
typedef struct // a struct for storing a future to int
{
int Id;
int Value;
int resolved;
pthread_t tid;
} FutureInt;
typedef FutureInt* futint; // a typedef to deal with the future type of MiniCFut
FutureInt *fresh_future_malloc(); // allocates (malloc) a fresh future and initializes its field
void print_futureInt(FutureInt *fut); // for debug purposes: print a fut int status
void free_future(FutureInt *fut); // frees the pointer allocated by fresh_future
void resolve_future(FutureInt *fut, int val); // function called when an async call is finished
int Get(FutureInt *fut);
// called by the main program:
// checks that the future is resolved and
// returns the value stored in the future
FutureInt *Async(int (*fun)(int), int p);
// asynchronous function call:
// takes a function pointer as parameter and the fun call parameter as second parameter
// returns an unresolved future
// creates a thread to perform the asynchronous function call
void freeAllFutures();
// called at the end of the main block: waits for the resolution of all futures
// and frees all future pointers created by fresh_future

View File

@ -1,77 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include "../include/futurelib.h"
FutureInt *All[70];
// A table of future pointers to store all the futures created
// In a realistic scenario this would be a dynamic structure
int NbAll = 0;
// Number of futures created
typedef struct
// A structure for the argument of thread creation: function pointer and parameter
{
FutureInt *fut;
int (*fun)(int);
int param;
} arg_struct;
FutureInt *fresh_future_malloc()
{
// TODO Exercise 4.2
// Use malloc(sizeof(FutureInt)) and reference created futures
}
void print_futureInt(FutureInt *f)
{
// TODO
// For debug purposes only
}
void free_future(FutureInt *fut)
{
free(fut);
}
void resolve_future(FutureInt *fut, int val)
{
// TODO Exercise 5.1
// Fill fut accordingly
}
int Get(FutureInt *fut)
{
// TODO Exercise 5.2
// Wait until future is resolved (do a sleep(1) between two checks)
// Do not forget to do a pthread_join(fut->tid, NULL);
return 0;
}
void *runTask(void *param)
{
// TODO Exercise 4.1
// function that is launched by the created thread: should call the function and
// deal with the future, using the function resolve_future
// param can be cast to (arg_struct *)
// this function should free the pointer param
return NULL;
}
FutureInt *Async(int (*fun)(int), int p)
{
// TODO Exercise 4.3
// Main system call should be: int err = pthread_create(&fut->tid, NULL, &runTask, (args));
// Allocate a future and space for arguments: args = malloc(sizeof(arg_struct));
// Do not forget to populate args
return NULL;
}
void freeAllFutures()
{
// TODO Exercises 4.4 & 5.3
// 1 - Wait for all futures (Get) to avoid dangling threads (Exercise 5.3)
// 2 - Call free_future for all futures (Exercise 4.4)
}

View File

@ -1,193 +0,0 @@
import collections
import re
import os
import subprocess
import sys
import pytest
testinfo = collections.namedtuple(
'testinfo',
['exitcode', 'execcode', 'output', 'linkargs', 'skip_test_expected'])
default_testinfo = testinfo(
exitcode=0, execcode=0, output='', linkargs=[], skip_test_expected=False)
def cat(filename):
with open(filename, "rb") as f:
for line in f:
sys.stdout.buffer.write(line)
def env_bool_variable(name, globals):
if name not in globals:
globals[name] = False
if name in os.environ:
globals[name] = True
def env_str_variable(name, globals):
if name in os.environ:
globals[name] = os.environ[name]
class TestExpectPragmas(object):
"""Base class for tests that read the expected result as annotations
in test files.
get_expect(file) will parse the file, looking EXPECT and EXITCODE
pragmas.
run_command(command) is a wrapper around subprocess.check_output()
that extracts the output and exit code.
"""
def get_expect(self, filename):
"""Parse "filename" looking for EXPECT and EXITCODE annotations.
Look for a line "EXPECTED" (possibly with whitespaces and
comments). Text after this "EXPECTED" line is the expected
output.
The file may also contain a line like "EXITCODE <n>" where <n>
is an integer, and is the expected exitcode of the command.
The result is cached to avoid re-parsing the file multiple
times.
"""
if filename not in self.__expect:
self.__expect[filename] = self._extract_expect(filename)
return self.__expect[filename]
def remove(self, file):
"""Like os.remove(), but ignore errors, e.g. don't complain if the
file doesn't exist.
"""
try:
os.remove(file)
except OSError:
pass
def run_command(self, cmd, scope="compile"):
"""Run the command cmd (given as [command, arg1, arg2, ...]), and
return testinfo(exitcode=..., output=...) containing the
exit code of the command it its standard output + standard error.
If scope="compile" (resp. "runtime"), then the exitcode (resp.
execcode) is set with the exit status of the command, and the
execcode (resp. exitcode) is set to 0.
"""
try:
output = subprocess.check_output(cmd, timeout=60,
stderr=subprocess.STDOUT)
status = 0
except subprocess.CalledProcessError as e:
output = e.output
status = e.returncode
if scope == "runtime":
return default_testinfo._replace(execcode=status,
output=output.decode())
else:
return default_testinfo._replace(exitcode=status,
output=output.decode())
def skip_if_partial_match(self, actual, expect, ignore_error_message):
if not ignore_error_message:
return False
# TODO: Deal with undefined behavior here?
if expect.exitcode != actual.exitcode:
# Not the same exit code => something's wrong anyway
return False
if actual.exitcode == 3:
# There's a syntax error in both expected and actual,
# but the actual error may slightly differ if we don't
# have the exact same .g4.
return True
# Let the test pass with 'return True' if appropriate.
# Otherwise, continue to the full assertion for a
# complete diagnostic.
if actual.exitcode != 0 and expect.exitcode == actual.exitcode:
if expect.output == '':
# No output expected, but we know there must be an
# error. If there was a particular error message
# expected, we'd have written it in the output,
# hence just ignore the actual message.
return True
# Ignore difference in error message except in the
# line number (ignore the column too, it may
# slightly vary, eg. in "foo" / 4, the error may
# be considered on "foo" or on /):
if re.match(r'^In function [^ :]*: Line [0-9]* col [0-9]*:',
actual.output):
out_loc = re.sub(r' col [0-9]*:.*$', '', actual.output)
exp_loc = re.sub(r' col [0-9]*:.*$', '', expect.output)
if out_loc == exp_loc:
return True
if any(x.output and
(x.output.endswith('has no value yet!' + os.linesep)
or x.output.endswith(' by 0' + os.linesep))
for x in (actual, expect)):
# Ignore the error message when our compiler
# raises this error (either in actual or expect,
# depending on what we're testing).
return True
return False
__expect = {}
def _extract_expect(self, file):
exitcode = 0
execcode = 0
linkargs = []
inside_expected = False
skip_test_expected = False
expected_lines = []
expected_present = False
with open(file, encoding="utf-8") as f:
for line in f.readlines():
# Ignore non-comments
if not re.match(r'\s*//', line):
continue
# Cleanup comment start and whitespaces
line = re.sub(r'\s*//\s*', '', line)
line = re.sub(r'\s*$', '', line)
if line == 'END EXPECTED':
inside_expected = False
elif line.startswith('EXITCODE'):
words = line.split(' ')
assert len(words) == 2
exitcode = int(words[1])
elif line.startswith('EXECCODE'):
words = line.split(' ')
assert len(words) == 2
execcode = int(words[1])
elif line.startswith('LINKARGS'):
words = line.split(' ')
assert len(words) >= 2
linkargs += [w.replace("$dir", os.path.dirname(file))
for w in words[1:]]
elif line == 'EXPECTED':
inside_expected = True
expected_present = True
elif line == 'SKIP TEST EXPECTED':
skip_test_expected = True
elif inside_expected:
expected_lines.append(line)
if not expected_present:
pytest.fail("Missing EXPECTED directive in test file")
if expected_lines == []:
output = ''
else:
output = os.linesep.join(expected_lines) + os.linesep
return testinfo(exitcode=exitcode, execcode=execcode,
output=output, linkargs=linkargs,
skip_test_expected=skip_test_expected)

View File

@ -1,105 +0,0 @@
#! /usr/bin/env python3
import os
import sys
import pytest
import glob
import subprocess
import re
from test_expect_pragma import (
TestExpectPragmas, cat, testinfo,
env_bool_variable, env_str_variable
)
"""
Usage:
python3 test_futur.py
(or make test)
"""
"""
CAP, 2020
Unit test infrastructure for testing futures:
1) compare the actual output to the expected one (in comments)
2) compare the actual output to the one obtained by simulation
"""
DISABLE_TYPECHECK = False
TYPECHECK_ONLY = False
HERE = os.path.dirname(os.path.realpath(__file__))
if HERE == os.path.realpath('.'):
HERE = '.'
TEST_DIR = HERE
IMPLEM_DIR = HERE
MINIC_FUT = os.path.join(IMPLEM_DIR, 'MiniCC.py')
ALL_FILES = glob.glob(os.path.join(TEST_DIR, 'tests/**/[a-zA-Z]*.c'),
recursive=True)
GCC = 'gcc'
if 'TEST_FILES' in os.environ:
ALL_FILES = glob.glob(os.environ['TEST_FILES'], recursive=True)
class TestFuture(TestExpectPragmas):
# Not in test_expect_pragma to get assertion rewritting
def assert_equal(self, actual, expected):
if TYPECHECK_ONLY and expected.exitcode == 0:
# Compiler does not fail => no output expected
assert actual.output == "", \
("Compiler unexpectedly generated some"
"output with --disable-codegen")
assert actual.exitcode == 0, \
"Compiler unexpectedly failed with --disable-codegen"
return
if DISABLE_TYPECHECK and expected.exitcode != 0:
# Test should fail at typecheck, and we don't do
# typechecking => nothing to check.
pytest.skip("Test that doesn't typecheck with --disable-typecheck")
if expected.output is not None and actual.output is not None:
assert actual.output == expected.output, \
"Output of the program is incorrect."
assert actual.exitcode == expected.exitcode, \
"Exit code of the compiler is incorrect"
assert actual.execcode == expected.execcode, \
"Exit code of the execution is incorrect"
def c2c(self, file):
return self.run_command(['python3', MINIC_FUT, file])
def compile_with_gcc(self, file, output_name):
print("Compiling with GCC...")
result = self.run_command(
[GCC, '-Iinclude', '-Ilib', '-x', 'c', file, "lib/futurelib.c",
'--output=' + output_name, '-lpthread'])
print(result.output)
print("Compiling with GCC... DONE")
return result
def compile_and_run(self, file):
basename, _ = os.path.splitext(file)
rw_name = basename + '.cfut'
exec_name = basename + '.out'
print("File: " + rw_name)
resgcc = self.compile_with_gcc(rw_name, exec_name)
if resgcc.exitcode != 0:
return resgcc._replace(exitcode=1, output=None)
res2 = self.run_command(exec_name, scope="runtime")
return res2
@pytest.mark.parametrize('filename', ALL_FILES)
def test_future(self, filename):
expect = self.get_expect(filename)
c2csuccess = self.c2c(filename)
if c2csuccess.exitcode == 0:
actual = self.compile_and_run(filename)
else:
actual = c2csuccess
self.assert_equal(actual, expect)
if __name__ == '__main__':
pytest.main(sys.argv)

View File

@ -1,38 +0,0 @@
#include "compat.h"
// Call future
int slow(int x)
{
int i;
i=0;
while (i<1000) { i=i+1 ; x=2*i+x;}
return x;
}
int summ(int x)
{
int ret,i;
if (x == 1)
ret=1;
else
{
ret = x + summ(x - 1);
i=0;
while (i<100) { i=i+1 ; x=slow(2);}
}
return ret;
}
int main()
{
int val;
val=Async(summ,1);
println_int(val);
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 29 col 4: type mismatch for val: integer and futinteger

View File

@ -1,20 +0,0 @@
#include "compat.h"
// Call future
int functi(int x){
int y;
y=x;
y = 42;
println_int(0);
return y;
}
int main(){
futint fval;
fval = Async(functi,123);
return 0;
}
// EXPECTED
// 0

View File

@ -1,22 +0,0 @@
#include "compat.h"
// Call future
int functi(int x){
int y;
y=x;
y = 42;
return y;
}
int main(){
futint fval;
int val;
fval = Async(functi,123);
val = Get(fval);
println_int(val);
return 0;
}
// EXPECTED
// 42

View File

@ -1,41 +0,0 @@
#include "compat.h"
// Call future
int summ(int x)
{
int ret;
if (x == 1)
ret=1;
else
{
ret=x + summ(x - 1);
}
return ret;
}
int useFuture(futint f)
{
int x;
x=Get(f);
return x+1;
}
int main()
{
int val,x;
futint f,g;
f=Async(summ,15);
g=Async(summ,16);
val=Get(f)+Get(g)+useFuture(g);
println_int(val);
return 0;
}
// EXPECTED
// 393

View File

@ -1,56 +0,0 @@
#include "compat.h"
// Call future
int slow(int x)
{
int i,t;
i=0;
t=0;
while (i<x*1000) { i=i+1 ; t=t+2*i+x;}
return t;
}
int summ(int x)
{
int ret;
int i;
if (x == 1)
ret=1;
else
{
ret = x + summ(x - 1);
i=0;
while (i<100) { i=i+1 ; x=slow(20);}
}
return ret;
}
int summandprint(int x)
{
int ret;
ret=summ(x);
println_int(ret);
return ret;
}
int main()
{
int val;
futint f,g;
f=Async(summandprint,500);
g=Async(summandprint,2);
val=Get(f)+Get(g);
return 0;
}
// EXPECTED
// 3
// 125250

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -45,13 +45,8 @@
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>

View File

@ -1,406 +0,0 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lib.CFG &mdash; MiniC documentation</title>
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../../index.html" class="icon icon-home">
MiniC
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Errors.html">Base library - Errors</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Statement.html">Base library - Statement</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">MiniC</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="../index.html">Module code</a></li>
<li class="breadcrumb-item active">Lib.CFG</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<h1>Source code for Lib.CFG</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Classes for a RiscV CFG: :py:class:`CFG` for the CFG itself,</span>
<span class="sd">and :py:class:`Block` for its basic blocks.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">graphviz</span> <span class="kn">import</span> <span class="n">Digraph</span> <span class="c1"># for dot output</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">cast</span><span class="p">,</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Set</span><span class="p">,</span> <span class="n">Iterator</span>
<span class="kn">from</span> <span class="nn">Lib.Errors</span> <span class="kn">import</span> <span class="n">MiniCInternalError</span>
<span class="kn">from</span> <span class="nn">Lib.Operands</span> <span class="kn">import</span> <span class="p">(</span><span class="n">Operand</span><span class="p">,</span> <span class="n">Immediate</span><span class="p">,</span> <span class="n">Function</span><span class="p">,</span> <span class="n">A0</span><span class="p">)</span>
<span class="kn">from</span> <span class="nn">Lib.Statement</span> <span class="kn">import</span> <span class="p">(</span>
<span class="n">Statement</span><span class="p">,</span> <span class="n">Instru3A</span><span class="p">,</span> <span class="n">Label</span><span class="p">,</span>
<span class="n">AbsoluteJump</span><span class="p">,</span> <span class="n">ConditionalJump</span><span class="p">,</span> <span class="n">Comment</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">Lib.Terminator</span> <span class="kn">import</span> <span class="p">(</span>
<span class="n">Terminator</span><span class="p">,</span> <span class="n">BranchingTerminator</span><span class="p">,</span> <span class="n">Return</span><span class="p">)</span>
<span class="kn">from</span> <span class="nn">Lib.FunctionData</span> <span class="kn">import</span> <span class="p">(</span><span class="n">FunctionData</span><span class="p">,</span> <span class="n">_iter_statements</span><span class="p">,</span> <span class="n">_print_code</span><span class="p">)</span>
<span class="n">BlockInstr</span> <span class="o">=</span> <span class="n">Instru3A</span> <span class="o">|</span> <span class="n">Comment</span>
<div class="viewcode-block" id="Block"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block">[docs]</a><span class="k">class</span> <span class="nc">Block</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A basic block of a :py:class:`CFG` is made of three main parts:</span>
<span class="sd"> - a start :py:class:`label &lt;Lib.Statement.Label&gt;` that uniquely identifies the block in the CFG</span>
<span class="sd"> - the main body of the block, a list of instructions</span>
<span class="sd"> (excluding labels, jumps and branching instructions)</span>
<span class="sd"> - a :py:class:`terminator &lt;Lib.Terminator.Terminator&gt;`</span>
<span class="sd"> that represents the final jump or branching instruction of the block,</span>
<span class="sd"> and points to the successors of the block.</span>
<span class="sd"> See the documentation for :py:class:`Lib.Terminator.Terminator` for further explanations.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">_terminator</span><span class="p">:</span> <span class="n">Terminator</span>
<span class="n">_label</span><span class="p">:</span> <span class="n">Label</span>
<span class="n">_phis</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Statement</span><span class="p">]</span>
<span class="n">_instructions</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">BlockInstr</span><span class="p">]</span>
<span class="n">_in</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="s1">&#39;Block&#39;</span><span class="p">]</span>
<span class="n">_gen</span><span class="p">:</span> <span class="n">Set</span>
<span class="n">_kill</span><span class="p">:</span> <span class="n">Set</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">label</span><span class="p">:</span> <span class="n">Label</span><span class="p">,</span> <span class="n">insts</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">BlockInstr</span><span class="p">],</span> <span class="n">terminator</span><span class="p">:</span> <span class="n">Terminator</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_label</span> <span class="o">=</span> <span class="n">label</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span> <span class="o">=</span> <span class="n">insts</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_in</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_phis</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_terminator</span> <span class="o">=</span> <span class="n">terminator</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_gen</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_kill</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">instr</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">Comment</span><span class="p">)]</span>
<span class="n">instr_str</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">instr</span><span class="p">))</span>
<span class="n">s</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="si">{}</span><span class="s1">:</span><span class="se">\n\n</span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_label</span><span class="p">,</span> <span class="n">instr_str</span><span class="p">)</span>
<span class="k">return</span> <span class="n">s</span>
<div class="viewcode-block" id="Block.to_dot"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.to_dot">[docs]</a> <span class="k">def</span> <span class="nf">to_dot</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span> <span class="c1"># pragma: no cover</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Outputs all statements of the block as a string.&quot;&quot;&quot;</span>
<span class="c1"># dot is weird: lines ending with \l instead of \n are left-aligned.</span>
<span class="n">NEWLINE</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="se">\\</span><span class="s1">l &#39;</span>
<span class="n">instr</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">instr</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_phis</span>
<span class="n">instr</span> <span class="o">+=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">Comment</span><span class="p">)]</span>
<span class="n">instr</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">get_terminator</span><span class="p">()]</span>
<span class="n">instr_str</span> <span class="o">=</span> <span class="n">NEWLINE</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">instr</span><span class="p">))</span>
<span class="n">s</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="si">{}</span><span class="s1">:</span><span class="si">{}{}</span><span class="se">\\</span><span class="s1">l&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_label</span><span class="p">,</span> <span class="n">NEWLINE</span><span class="p">,</span> <span class="n">instr_str</span><span class="p">)</span>
<span class="k">return</span> <span class="n">s</span></div>
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_label</span><span class="p">)</span>
<div class="viewcode-block" id="Block.get_body"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.get_body">[docs]</a> <span class="k">def</span> <span class="nf">get_body</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">BlockInstr</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the statements in the body of the block (no phi-node nor the terminator).&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span></div>
<div class="viewcode-block" id="Block.get_all_statements"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.get_all_statements">[docs]</a> <span class="k">def</span> <span class="nf">get_all_statements</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Statement</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Return all statements of the block</span>
<span class="sd"> (including phi-nodes and the terminator, but not the label of the block).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_phis</span> <span class="o">+</span>
<span class="n">cast</span><span class="p">(</span><span class="n">List</span><span class="p">[</span><span class="n">Statement</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span><span class="p">)</span> <span class="o">+</span>
<span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">get_terminator</span><span class="p">()])</span></div>
<div class="viewcode-block" id="Block.get_body_and_terminator"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.get_body_and_terminator">[docs]</a> <span class="k">def</span> <span class="nf">get_body_and_terminator</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Statement</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Return all statements of the block, except phi-nodes</span>
<span class="sd"> (and the label of the block).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">(</span><span class="n">cast</span><span class="p">(</span><span class="n">List</span><span class="p">[</span><span class="n">Statement</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span><span class="p">)</span> <span class="o">+</span>
<span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">get_terminator</span><span class="p">()])</span></div>
<div class="viewcode-block" id="Block.get_label"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.get_label">[docs]</a> <span class="k">def</span> <span class="nf">get_label</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Label</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the label of the block.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_label</span></div>
<div class="viewcode-block" id="Block.get_in"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.get_in">[docs]</a> <span class="k">def</span> <span class="nf">get_in</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="s1">&#39;Block&#39;</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the list of blocks with an edge to the considered block.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_in</span></div>
<div class="viewcode-block" id="Block.get_terminator"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.get_terminator">[docs]</a> <span class="k">def</span> <span class="nf">get_terminator</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Terminator</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the terminator of the block.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_terminator</span></div>
<div class="viewcode-block" id="Block.set_terminator"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.set_terminator">[docs]</a> <span class="k">def</span> <span class="nf">set_terminator</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">term</span><span class="p">:</span> <span class="n">Terminator</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Set the terminator of the block.&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_terminator</span> <span class="o">=</span> <span class="n">term</span></div>
<div class="viewcode-block" id="Block.get_phis"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.get_phis">[docs]</a> <span class="k">def</span> <span class="nf">get_phis</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Statement</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the list of all φ instructions of the block.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_phis</span></div>
<div class="viewcode-block" id="Block.add_phi"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.add_phi">[docs]</a> <span class="k">def</span> <span class="nf">add_phi</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">phi</span><span class="p">:</span> <span class="n">Statement</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Add a φ instruction to the block.&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_phis</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">phi</span><span class="p">)</span></div>
<div class="viewcode-block" id="Block.set_phis"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.set_phis">[docs]</a> <span class="k">def</span> <span class="nf">set_phis</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">phis</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Statement</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Replace the φ instructions in the block by the given list `phis`.&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_phis</span> <span class="o">=</span> <span class="n">phis</span></div>
<div class="viewcode-block" id="Block.remove_all_phis"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.remove_all_phis">[docs]</a> <span class="k">def</span> <span class="nf">remove_all_phis</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Remove all φ instructions in the block.&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_phis</span> <span class="o">=</span> <span class="p">[]</span></div>
<div class="viewcode-block" id="Block.iter_statements"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.iter_statements">[docs]</a> <span class="k">def</span> <span class="nf">iter_statements</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Iterate over instructions.</span>
<span class="sd"> For each real instruction i (not label or comment), replace it</span>
<span class="sd"> with the list of instructions given by f(i).</span>
<span class="sd"> Assume there is no phi-node.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">assert</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_phis</span> <span class="o">==</span> <span class="p">[])</span>
<span class="n">new_statements</span> <span class="o">=</span> <span class="n">_iter_statements</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span>
<span class="n">end_statements</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">get_terminator</span><span class="p">())</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">end_statements</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">1</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">end_statements</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">Terminator</span><span class="p">):</span>
<span class="n">new_terminator</span> <span class="o">=</span> <span class="n">end_statements</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span> <span class="o">=</span> <span class="n">new_statements</span> <span class="o">+</span> <span class="n">end_statements</span>
<span class="bp">self</span><span class="o">.</span><span class="n">set_terminator</span><span class="p">(</span><span class="n">new_terminator</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">MiniCInternalError</span><span class="p">(</span>
<span class="s2">&quot;Block.iter_statements: Invalid replacement for terminator </span><span class="si">{}</span><span class="s2">:</span><span class="se">\n</span><span class="s2"> </span><span class="si">{}</span><span class="s2">&quot;</span>
<span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">get_terminator</span><span class="p">(),</span> <span class="n">end_statements</span><span class="p">))</span></div>
<div class="viewcode-block" id="Block.add_instruction"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.Block.add_instruction">[docs]</a> <span class="k">def</span> <span class="nf">add_instruction</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instr</span><span class="p">:</span> <span class="n">BlockInstr</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Add an instruction to the body of the block.&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_instructions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">instr</span><span class="p">)</span></div></div>
<div class="viewcode-block" id="CFG"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG">[docs]</a><span class="k">class</span> <span class="nc">CFG</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A complete control-flow graph representing a function.</span>
<span class="sd"> This class is mainly made of a list of basic :py:class:`Block`,</span>
<span class="sd"> a label indicating the :py:meth:`entry point of the function &lt;get_start&gt;`,</span>
<span class="sd"> and an :py:meth:`exit label &lt;get_end&gt;`.</span>
<span class="sd"> As with linear code, metadata about the function can be found</span>
<span class="sd"> in the :py:attr:`fdata` member variable.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">_start</span><span class="p">:</span> <span class="n">Label</span>
<span class="n">_end</span><span class="p">:</span> <span class="n">Label</span>
<span class="n">_blocks</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Label</span><span class="p">,</span> <span class="n">Block</span><span class="p">]</span>
<span class="c1">#: Metadata about the function represented by this CFG</span>
<span class="n">fdata</span><span class="p">:</span> <span class="n">FunctionData</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fdata</span><span class="p">:</span> <span class="n">FunctionData</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span> <span class="o">=</span> <span class="p">{}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">fdata</span> <span class="o">=</span> <span class="n">fdata</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_init_blks</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_end</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fdata</span><span class="o">.</span><span class="n">fresh_label</span><span class="p">(</span><span class="s2">&quot;end&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_init_blks</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Add a block for division by 0.&quot;&quot;&quot;</span>
<span class="c1"># Label for the address of the error message</span>
<span class="c1"># This address is added by print_code</span>
<span class="n">label_div_by_zero_msg</span> <span class="o">=</span> <span class="n">Label</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fdata</span><span class="o">.</span><span class="n">_label_div_by_zero</span><span class="o">.</span><span class="n">name</span> <span class="o">+</span> <span class="s2">&quot;_msg&quot;</span><span class="p">)</span>
<span class="n">blk</span> <span class="o">=</span> <span class="n">Block</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fdata</span><span class="o">.</span><span class="n">_label_div_by_zero</span><span class="p">,</span> <span class="p">[</span>
<span class="n">Instru3A</span><span class="p">(</span><span class="s2">&quot;la&quot;</span><span class="p">,</span> <span class="n">A0</span><span class="p">,</span> <span class="n">label_div_by_zero_msg</span><span class="p">),</span>
<span class="n">Instru3A</span><span class="p">(</span><span class="s2">&quot;call&quot;</span><span class="p">,</span> <span class="n">Function</span><span class="p">(</span><span class="s2">&quot;println_string&quot;</span><span class="p">)),</span>
<span class="n">Instru3A</span><span class="p">(</span><span class="s2">&quot;li&quot;</span><span class="p">,</span> <span class="n">A0</span><span class="p">,</span> <span class="n">Immediate</span><span class="p">(</span><span class="mi">1</span><span class="p">)),</span>
<span class="n">Instru3A</span><span class="p">(</span><span class="s2">&quot;call&quot;</span><span class="p">,</span> <span class="n">Function</span><span class="p">(</span><span class="s2">&quot;exit&quot;</span><span class="p">)),</span>
<span class="p">],</span> <span class="n">terminator</span><span class="o">=</span><span class="n">Return</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add_block</span><span class="p">(</span><span class="n">blk</span><span class="p">)</span>
<div class="viewcode-block" id="CFG.get_start"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.get_start">[docs]</a> <span class="k">def</span> <span class="nf">get_start</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Label</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the entry label of the CFG.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_start</span></div>
<div class="viewcode-block" id="CFG.set_start"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.set_start">[docs]</a> <span class="k">def</span> <span class="nf">set_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">start</span><span class="p">:</span> <span class="n">Label</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Set the entry label of the CFG.&quot;&quot;&quot;</span>
<span class="k">assert</span> <span class="p">(</span><span class="n">start</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_start</span> <span class="o">=</span> <span class="n">start</span></div>
<div class="viewcode-block" id="CFG.get_end"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.get_end">[docs]</a> <span class="k">def</span> <span class="nf">get_end</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Label</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the exit label of the CFG.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_end</span></div>
<div class="viewcode-block" id="CFG.add_block"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.add_block">[docs]</a> <span class="k">def</span> <span class="nf">add_block</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">blk</span><span class="p">:</span> <span class="n">Block</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Add a new block to the CFG.&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span><span class="p">[</span><span class="n">blk</span><span class="o">.</span><span class="n">_label</span><span class="p">]</span> <span class="o">=</span> <span class="n">blk</span></div>
<div class="viewcode-block" id="CFG.get_block"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.get_block">[docs]</a> <span class="k">def</span> <span class="nf">get_block</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="n">Label</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Block</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the block with label `name`.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span><span class="p">[</span><span class="n">name</span><span class="p">]</span></div>
<div class="viewcode-block" id="CFG.get_blocks"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.get_blocks">[docs]</a> <span class="k">def</span> <span class="nf">get_blocks</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Block</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return all the blocks.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">[</span><span class="n">b</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span><span class="o">.</span><span class="n">values</span><span class="p">()]</span></div>
<div class="viewcode-block" id="CFG.get_entries"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.get_entries">[docs]</a> <span class="k">def</span> <span class="nf">get_entries</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Block</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return all the blocks with no predecessors.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">[</span><span class="n">b</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span><span class="o">.</span><span class="n">values</span><span class="p">()</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">b</span><span class="o">.</span><span class="n">get_in</span><span class="p">()]</span></div>
<div class="viewcode-block" id="CFG.add_edge"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.add_edge">[docs]</a> <span class="k">def</span> <span class="nf">add_edge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="p">:</span> <span class="n">Block</span><span class="p">,</span> <span class="n">dest</span><span class="p">:</span> <span class="n">Block</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Add the edge src -&gt; dest in the control flow graph.&quot;&quot;&quot;</span>
<span class="n">dest</span><span class="o">.</span><span class="n">get_in</span><span class="p">()</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">src</span><span class="p">)</span></div>
<span class="c1"># assert (dest.get_label() in src.get_terminator().targets())</span>
<div class="viewcode-block" id="CFG.remove_edge"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.remove_edge">[docs]</a> <span class="k">def</span> <span class="nf">remove_edge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="p">:</span> <span class="n">Block</span><span class="p">,</span> <span class="n">dest</span><span class="p">:</span> <span class="n">Block</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Remove the edge src -&gt; dest in the control flow graph.&quot;&quot;&quot;</span>
<span class="n">dest</span><span class="o">.</span><span class="n">get_in</span><span class="p">()</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">src</span><span class="p">)</span></div>
<span class="c1"># assert (dest.get_label() not in src.get_terminator().targets())</span>
<div class="viewcode-block" id="CFG.out_blocks"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.out_blocks">[docs]</a> <span class="k">def</span> <span class="nf">out_blocks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">block</span><span class="p">:</span> <span class="n">Block</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Block</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Return the list of blocks in the CFG targeted by</span>
<span class="sd"> the Terminator of Block block.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">get_block</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span> <span class="k">for</span> <span class="n">dest</span> <span class="ow">in</span> <span class="n">block</span><span class="o">.</span><span class="n">get_terminator</span><span class="p">()</span><span class="o">.</span><span class="n">targets</span><span class="p">()]</span></div>
<div class="viewcode-block" id="CFG.gather_defs"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.gather_defs">[docs]</a> <span class="k">def</span> <span class="nf">gather_defs</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Return a dictionary associating variables to all the blocks</span>
<span class="sd"> containing one of their definitions.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">defs</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Operand</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]]</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_blocks</span><span class="p">():</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">b</span><span class="o">.</span><span class="n">get_all_statements</span><span class="p">():</span>
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">i</span><span class="o">.</span><span class="n">defined</span><span class="p">():</span>
<span class="k">if</span> <span class="n">v</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">defs</span><span class="p">:</span>
<span class="n">defs</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">b</span><span class="p">}</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">defs</span><span class="p">[</span><span class="n">v</span><span class="p">]</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="k">return</span> <span class="n">defs</span></div>
<div class="viewcode-block" id="CFG.iter_statements"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.iter_statements">[docs]</a> <span class="k">def</span> <span class="nf">iter_statements</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Apply f to all instructions in all the blocks.&quot;&quot;&quot;</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_blocks</span><span class="p">():</span>
<span class="n">b</span><span class="o">.</span><span class="n">iter_statements</span><span class="p">(</span><span class="n">f</span><span class="p">)</span></div>
<div class="viewcode-block" id="CFG.linearize_naive"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.linearize_naive">[docs]</a> <span class="k">def</span> <span class="nf">linearize_naive</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Iterator</span><span class="p">[</span><span class="n">Statement</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Linearize the given control flow graph as a list of instructions.</span>
<span class="sd"> Naive procedure that adds jumps everywhere.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">for</span> <span class="n">label</span><span class="p">,</span> <span class="n">block</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">yield</span> <span class="n">label</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">block</span><span class="o">.</span><span class="n">_instructions</span><span class="p">:</span>
<span class="k">yield</span> <span class="n">i</span>
<span class="k">match</span> <span class="n">block</span><span class="o">.</span><span class="n">get_terminator</span><span class="p">():</span>
<span class="k">case</span> <span class="n">BranchingTerminator</span><span class="p">()</span> <span class="k">as</span> <span class="n">j</span><span class="p">:</span>
<span class="c1"># In case of conditional jump, add the missing edge</span>
<span class="k">yield</span> <span class="n">ConditionalJump</span><span class="p">(</span><span class="n">j</span><span class="o">.</span><span class="n">cond</span><span class="p">,</span> <span class="n">j</span><span class="o">.</span><span class="n">op1</span><span class="p">,</span> <span class="n">j</span><span class="o">.</span><span class="n">op2</span><span class="p">,</span> <span class="n">j</span><span class="o">.</span><span class="n">label_then</span><span class="p">)</span>
<span class="k">yield</span> <span class="n">AbsoluteJump</span><span class="p">(</span><span class="n">j</span><span class="o">.</span><span class="n">label_else</span><span class="p">)</span>
<span class="k">case</span> <span class="n">AbsoluteJump</span><span class="p">()</span> <span class="k">as</span> <span class="n">j</span><span class="p">:</span>
<span class="k">yield</span> <span class="n">AbsoluteJump</span><span class="p">(</span><span class="n">j</span><span class="o">.</span><span class="n">label</span><span class="p">)</span>
<span class="k">case</span> <span class="n">Return</span><span class="p">():</span>
<span class="k">yield</span> <span class="n">AbsoluteJump</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">get_end</span><span class="p">())</span></div>
<div class="viewcode-block" id="CFG.print_code"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.print_code">[docs]</a> <span class="k">def</span> <span class="nf">print_code</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">linearize</span><span class="o">=</span><span class="p">(</span><span class="k">lambda</span> <span class="n">cfg</span><span class="p">:</span> <span class="nb">list</span><span class="p">(</span><span class="n">cfg</span><span class="o">.</span><span class="n">linearize_naive</span><span class="p">())),</span>
<span class="n">comment</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Print the linearization of the CFG.&quot;&quot;&quot;</span>
<span class="n">statements</span> <span class="o">=</span> <span class="n">linearize</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="n">_print_code</span><span class="p">(</span><span class="n">statements</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">fdata</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">init_label</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_start</span><span class="p">,</span>
<span class="n">fin_label</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_end</span><span class="p">,</span> <span class="n">fin_div0</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">comment</span><span class="o">=</span><span class="n">comment</span><span class="p">)</span></div>
<div class="viewcode-block" id="CFG.print_dot"><a class="viewcode-back" href="../../api/Lib.CFG.html#Lib.CFG.CFG.print_dot">[docs]</a> <span class="k">def</span> <span class="nf">print_dot</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">DF</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">view</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># pragma: no cover</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Print the CFG as a graph.&quot;&quot;&quot;</span>
<span class="n">graph</span> <span class="o">=</span> <span class="n">Digraph</span><span class="p">()</span>
<span class="c1"># nodes</span>
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">blk</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">if</span> <span class="n">DF</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">df_str</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2">&quot;</span> <span class="k">if</span> <span class="n">blk</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">DF</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">DF</span><span class="p">[</span><span class="n">blk</span><span class="p">])</span> <span class="k">else</span> <span class="nb">str</span><span class="p">(</span><span class="n">DF</span><span class="p">[</span><span class="n">blk</span><span class="p">])</span>
<span class="n">df_lab</span> <span class="o">=</span> <span class="n">blk</span><span class="o">.</span><span class="n">to_dot</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&quot;</span><span class="se">\n\n</span><span class="s2">Dominance frontier:</span><span class="se">\n</span><span class="s2">&quot;</span> <span class="o">+</span> <span class="n">df_str</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">df_lab</span> <span class="o">=</span> <span class="n">blk</span><span class="o">.</span><span class="n">to_dot</span><span class="p">()</span>
<span class="n">graph</span><span class="o">.</span><span class="n">node</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">blk</span><span class="o">.</span><span class="n">_label</span><span class="p">),</span> <span class="n">label</span><span class="o">=</span><span class="n">df_lab</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="s1">&#39;rectangle&#39;</span><span class="p">)</span>
<span class="c1"># edges</span>
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">blk</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_blocks</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">blk</span><span class="o">.</span><span class="n">get_terminator</span><span class="p">()</span><span class="o">.</span><span class="n">targets</span><span class="p">():</span>
<span class="n">graph</span><span class="o">.</span><span class="n">edge</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">blk</span><span class="o">.</span><span class="n">_label</span><span class="p">),</span> <span class="nb">str</span><span class="p">(</span><span class="n">child</span><span class="p">))</span>
<span class="n">graph</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">view</span><span class="o">=</span><span class="n">view</span><span class="p">)</span></div></div>
</pre></div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, compil-lyon.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>

View File

@ -1,239 +0,0 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lib.Dominators &mdash; MiniC documentation</title>
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../../index.html" class="icon icon-home">
MiniC
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Errors.html">Base library - Errors</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Statement.html">Base library - Statement</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">MiniC</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="../index.html">Module code</a></li>
<li class="breadcrumb-item active">Lib.Dominators</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<h1>Source code for Lib.Dominators</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Utility functions to work with dominators in a :py:class:`CFG &lt;Lib.CFG.CFG&gt;`.</span>
<span class="sd">Do not hesitate to look at the source of the functions</span>
<span class="sd">to get a better understanding of the algorithms.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">Set</span>
<span class="kn">from</span> <span class="nn">graphviz</span> <span class="kn">import</span> <span class="n">Digraph</span>
<span class="kn">from</span> <span class="nn">Lib.CFG</span> <span class="kn">import</span> <span class="n">Block</span><span class="p">,</span> <span class="n">CFG</span>
<div class="viewcode-block" id="computeDom"><a class="viewcode-back" href="../../api/Lib.Dominators.html#Lib.Dominators.computeDom">[docs]</a><span class="k">def</span> <span class="nf">computeDom</span><span class="p">(</span><span class="n">cfg</span><span class="p">:</span> <span class="n">CFG</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `computeDom(cfg)` computes the table associating blocks to their</span>
<span class="sd"> dominators in `cfg`.</span>
<span class="sd"> It works by solving the equation system.</span>
<span class="sd"> This is an helper function called during SSA entry.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">all_blocks</span><span class="p">:</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">cfg</span><span class="o">.</span><span class="n">get_blocks</span><span class="p">())</span>
<span class="n">dominators</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]]</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">all_blocks</span><span class="p">:</span>
<span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">get_in</span><span class="p">():</span> <span class="c1"># If b has some predecessor</span>
<span class="n">dominators</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">=</span> <span class="n">all_blocks</span>
<span class="k">else</span><span class="p">:</span> <span class="c1"># If b has no predecessors</span>
<span class="n">dominators</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">b</span><span class="p">}</span>
<span class="n">new_dominators</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]]</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">all_blocks</span><span class="p">:</span>
<span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">get_in</span><span class="p">():</span>
<span class="n">dom_preds</span> <span class="o">=</span> <span class="p">[</span><span class="n">dominators</span><span class="p">[</span><span class="n">b2</span><span class="p">]</span> <span class="k">for</span> <span class="n">b2</span> <span class="ow">in</span> <span class="n">b</span><span class="o">.</span><span class="n">get_in</span><span class="p">()]</span>
<span class="n">new_dominators</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">b</span><span class="p">}</span><span class="o">.</span><span class="n">union</span><span class="p">(</span><span class="nb">set</span><span class="o">.</span><span class="n">intersection</span><span class="p">(</span><span class="o">*</span><span class="n">dom_preds</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">new_dominators</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">b</span><span class="p">}</span>
<span class="k">if</span> <span class="n">dominators</span> <span class="o">==</span> <span class="n">new_dominators</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">dominators</span> <span class="o">=</span> <span class="n">new_dominators</span>
<span class="n">new_dominators</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">return</span> <span class="n">dominators</span></div>
<div class="viewcode-block" id="printDT"><a class="viewcode-back" href="../../api/Lib.Dominators.html#Lib.Dominators.printDT">[docs]</a><span class="k">def</span> <span class="nf">printDT</span><span class="p">(</span><span class="n">filename</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">graph</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># pragma: no cover</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Display a graphical rendering of the given domination tree.&quot;&quot;&quot;</span>
<span class="n">dot</span> <span class="o">=</span> <span class="n">Digraph</span><span class="p">()</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
<span class="n">dot</span><span class="o">.</span><span class="n">node</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">k</span><span class="o">.</span><span class="n">get_label</span><span class="p">()))</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">k</span><span class="p">]:</span>
<span class="n">dot</span><span class="o">.</span><span class="n">edge</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">k</span><span class="o">.</span><span class="n">get_label</span><span class="p">()),</span> <span class="nb">str</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">get_label</span><span class="p">()))</span>
<span class="n">dot</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">view</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></div>
<div class="viewcode-block" id="computeDT"><a class="viewcode-back" href="../../api/Lib.Dominators.html#Lib.Dominators.computeDT">[docs]</a><span class="k">def</span> <span class="nf">computeDT</span><span class="p">(</span><span class="n">cfg</span><span class="p">:</span> <span class="n">CFG</span><span class="p">,</span> <span class="n">dominators</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]],</span>
<span class="n">dom_graphs</span><span class="p">:</span> <span class="nb">bool</span><span class="p">,</span> <span class="n">basename</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `computeDT(cfg, dominators)` computes the domination tree of `cfg`</span>
<span class="sd"> using the previously computed `dominators`.</span>
<span class="sd"> It returns `DT`, a dictionary which associates a block with its children</span>
<span class="sd"> in the dominator tree.</span>
<span class="sd"> This is an helper function called during SSA entry.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># First, compute the immediate dominators</span>
<span class="n">idominators</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Block</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">b</span><span class="p">,</span> <span class="n">doms</span> <span class="ow">in</span> <span class="n">dominators</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="c1"># The immediate dominator of b is the unique vertex n ≠ b</span>
<span class="c1"># which dominates b and is dominated by all vertices in Dom(b) b.</span>
<span class="n">strict_doms</span> <span class="o">=</span> <span class="n">doms</span> <span class="o">-</span> <span class="p">{</span><span class="n">b</span><span class="p">}</span>
<span class="n">idoms</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">strict_doms</span><span class="p">:</span>
<span class="k">if</span> <span class="n">strict_doms</span><span class="o">.</span><span class="n">issubset</span><span class="p">(</span><span class="n">dominators</span><span class="p">[</span><span class="n">n</span><span class="p">]):</span>
<span class="n">idoms</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">if</span> <span class="n">idoms</span><span class="p">:</span>
<span class="k">assert</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">idoms</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">idominators</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">=</span> <span class="n">idoms</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
<span class="c1"># Then, simply inverse the relation to obtain the domination tree</span>
<span class="n">DT</span> <span class="o">=</span> <span class="p">{</span><span class="n">b</span><span class="p">:</span> <span class="nb">set</span><span class="p">()</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">cfg</span><span class="o">.</span><span class="n">get_blocks</span><span class="p">()}</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">idominator</span> <span class="ow">in</span> <span class="n">idominators</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="n">DT</span><span class="p">[</span><span class="n">idominator</span><span class="p">]</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="c1"># Print the domination tree if asked</span>
<span class="k">if</span> <span class="n">dom_graphs</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2">.</span><span class="si">{}</span><span class="s2">.ssa.DT.dot&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">basename</span><span class="p">,</span> <span class="n">cfg</span><span class="o">.</span><span class="n">fdata</span><span class="o">.</span><span class="n">get_name</span><span class="p">())</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;SSA - domination tree graph:&quot;</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
<span class="n">printDT</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">DT</span><span class="p">)</span>
<span class="k">return</span> <span class="n">DT</span></div>
<span class="k">def</span> <span class="nf">_computeDF_at_block</span><span class="p">(</span>
<span class="n">cfg</span><span class="p">:</span> <span class="n">CFG</span><span class="p">,</span>
<span class="n">dominators</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]],</span>
<span class="n">DT</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]],</span>
<span class="n">b</span><span class="p">:</span> <span class="n">Block</span><span class="p">,</span>
<span class="n">DF</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `_computeDF_at_block(...)` computes the dominance frontier at the given block,</span>
<span class="sd"> by updating `DF`.</span>
<span class="sd"> This is an helper function called during SSA entry.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">S</span><span class="p">:</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">succ</span> <span class="k">for</span> <span class="n">succ</span> <span class="ow">in</span> <span class="n">cfg</span><span class="o">.</span><span class="n">out_blocks</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="k">if</span> <span class="n">succ</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">DT</span><span class="p">[</span><span class="n">b</span><span class="p">]}</span>
<span class="k">for</span> <span class="n">b_succ</span> <span class="ow">in</span> <span class="n">DT</span><span class="p">[</span><span class="n">b</span><span class="p">]:</span>
<span class="n">_computeDF_at_block</span><span class="p">(</span><span class="n">cfg</span><span class="p">,</span> <span class="n">dominators</span><span class="p">,</span> <span class="n">DT</span><span class="p">,</span> <span class="n">b_succ</span><span class="p">,</span> <span class="n">DF</span><span class="p">)</span>
<span class="k">for</span> <span class="n">b_frontier</span> <span class="ow">in</span> <span class="n">DF</span><span class="p">[</span><span class="n">b_succ</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">b</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="n">dominators</span><span class="p">[</span><span class="n">b_frontier</span><span class="p">]</span> <span class="o">-</span> <span class="p">{</span><span class="n">b_frontier</span><span class="p">}):</span>
<span class="n">S</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">b_frontier</span><span class="p">)</span>
<span class="n">DF</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">=</span> <span class="n">S</span>
<div class="viewcode-block" id="computeDF"><a class="viewcode-back" href="../../api/Lib.Dominators.html#Lib.Dominators.computeDF">[docs]</a><span class="k">def</span> <span class="nf">computeDF</span><span class="p">(</span><span class="n">cfg</span><span class="p">:</span> <span class="n">CFG</span><span class="p">,</span> <span class="n">dominators</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]],</span>
<span class="n">DT</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]],</span> <span class="n">dom_graphs</span><span class="p">:</span> <span class="nb">bool</span><span class="p">,</span> <span class="n">basename</span><span class="p">:</span> <span class="nb">str</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `computeDF(...)` computes the dominance frontier of a CFG.</span>
<span class="sd"> It returns `DF` which associates a block to its frontier.</span>
<span class="sd"> This is an helper function called during SSA entry.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">DF</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Block</span><span class="p">,</span> <span class="n">Set</span><span class="p">[</span><span class="n">Block</span><span class="p">]]</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">b_entry</span> <span class="ow">in</span> <span class="n">cfg</span><span class="o">.</span><span class="n">get_entries</span><span class="p">():</span>
<span class="n">_computeDF_at_block</span><span class="p">(</span><span class="n">cfg</span><span class="p">,</span> <span class="n">dominators</span><span class="p">,</span> <span class="n">DT</span><span class="p">,</span> <span class="n">b_entry</span><span class="p">,</span> <span class="n">DF</span><span class="p">)</span>
<span class="c1"># Print the domination frontier on the CFG if asked</span>
<span class="k">if</span> <span class="n">dom_graphs</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2">.</span><span class="si">{}</span><span class="s2">.ssa.DF.dot&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">basename</span><span class="p">,</span> <span class="n">cfg</span><span class="o">.</span><span class="n">fdata</span><span class="o">.</span><span class="n">get_name</span><span class="p">())</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;SSA - dominance frontier graph:&quot;</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
<span class="n">cfg</span><span class="o">.</span><span class="n">print_dot</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">DF</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
<span class="k">return</span> <span class="n">DF</span></div>
</pre></div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, compil-lyon.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>

View File

@ -45,13 +45,8 @@
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>

View File

@ -45,13 +45,8 @@
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>

View File

@ -1,423 +0,0 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lib.Graphes &mdash; MiniC documentation</title>
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../../index.html" class="icon icon-home">
MiniC
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Errors.html">Base library - Errors</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Statement.html">Base library - Statement</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">MiniC</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="../index.html">Module code</a></li>
<li class="breadcrumb-item active">Lib.Graphes</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<h1>Source code for Lib.Graphes</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot; Python Classes for Oriented and Non Oriented Graphs</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">graphviz</span> <span class="kn">import</span> <span class="n">Digraph</span> <span class="c1"># for dot output</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">Set</span><span class="p">,</span> <span class="n">Tuple</span><span class="p">,</span> <span class="n">Any</span>
<div class="viewcode-block" id="GraphError"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GraphError">[docs]</a><span class="k">class</span> <span class="nc">GraphError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Exception raised for self loops.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">message</span><span class="p">:</span> <span class="nb">str</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span></div>
<div class="viewcode-block" id="GeneralGraph"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GeneralGraph">[docs]</a><span class="k">class</span> <span class="nc">GeneralGraph</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> General class regrouping similarities</span>
<span class="sd"> between directed and non oriented graphs.</span>
<span class="sd"> The only differences between the two are:</span>
<span class="sd"> - how to compute the set of edges</span>
<span class="sd"> - how to add an edge</span>
<span class="sd"> - how to print the graph</span>
<span class="sd"> - how to delete a vertex</span>
<span class="sd"> - how to delete an edge</span>
<span class="sd"> - we only color undirected graphs</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">graph_dict</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="n">Set</span><span class="p">]</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">graph_dict</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Initializes a graph object.</span>
<span class="sd"> If no dictionary or None is given,</span>
<span class="sd"> an empty dictionary will be used.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">graph_dict</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">graph_dict</span> <span class="o">=</span> <span class="p">{}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span> <span class="o">=</span> <span class="n">graph_dict</span>
<div class="viewcode-block" id="GeneralGraph.vertices"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GeneralGraph.vertices">[docs]</a> <span class="k">def</span> <span class="nf">vertices</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the vertices of a graph.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span></div>
<div class="viewcode-block" id="GeneralGraph.add_vertex"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GeneralGraph.add_vertex">[docs]</a> <span class="k">def</span> <span class="nf">add_vertex</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vertex</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> If the vertex &quot;vertex&quot; is not in</span>
<span class="sd"> self.graph_dict, a key &quot;vertex&quot; with an empty</span>
<span class="sd"> list as a value is added to the dictionary.</span>
<span class="sd"> Otherwise nothing has to be done.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">vertex</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex</span><span class="p">]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span></div>
<div class="viewcode-block" id="GeneralGraph.edges"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GeneralGraph.edges">[docs]</a> <span class="k">def</span> <span class="nf">edges</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Set</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the edges of the graph.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">[]</span></div>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">res</span> <span class="o">=</span> <span class="s2">&quot;vertices: &quot;</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="n">res</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">k</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot; &quot;</span>
<span class="n">res</span> <span class="o">+=</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">edges: &quot;</span>
<span class="k">for</span> <span class="n">edge</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">edges</span><span class="p">():</span>
<span class="n">res</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">edge</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot; &quot;</span>
<span class="k">return</span> <span class="n">res</span>
<div class="viewcode-block" id="GeneralGraph.dfs_traversal"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GeneralGraph.dfs_traversal">[docs]</a> <span class="k">def</span> <span class="nf">dfs_traversal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">root</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Compute a depth first search of the graph,</span>
<span class="sd"> from the vertex root.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">seen</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">todo</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">root</span><span class="p">]</span>
<span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">todo</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># while todo ...</span>
<span class="n">current</span> <span class="o">=</span> <span class="n">todo</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
<span class="n">seen</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">current</span><span class="p">)</span>
<span class="k">for</span> <span class="n">neighbour</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">current</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">neighbour</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">seen</span><span class="p">:</span>
<span class="n">todo</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">neighbour</span><span class="p">)</span>
<span class="k">return</span> <span class="n">seen</span></div>
<div class="viewcode-block" id="GeneralGraph.is_reachable_from"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GeneralGraph.is_reachable_from">[docs]</a> <span class="k">def</span> <span class="nf">is_reachable_from</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">v1</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">v2</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;True if there is a path from v1 to v2.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">v2</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dfs_traversal</span><span class="p">(</span><span class="n">v1</span><span class="p">)</span></div>
<div class="viewcode-block" id="GeneralGraph.connected_components"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GeneralGraph.connected_components">[docs]</a> <span class="k">def</span> <span class="nf">connected_components</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Compute the list of all connected components of the graph,</span>
<span class="sd"> each component being a list of vetices.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">components</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]]</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">done</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">vertices</span><span class="p">():</span>
<span class="k">if</span> <span class="n">v</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">done</span><span class="p">:</span>
<span class="n">v_comp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dfs_traversal</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="n">components</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">v_comp</span><span class="p">)</span>
<span class="n">done</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">v_comp</span><span class="p">)</span>
<span class="k">return</span> <span class="n">components</span></div>
<div class="viewcode-block" id="GeneralGraph.bfs_traversal"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.GeneralGraph.bfs_traversal">[docs]</a> <span class="k">def</span> <span class="nf">bfs_traversal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">root</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Compute a breadth first search of the graph,</span>
<span class="sd"> from the vertex root.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">seen</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">todo</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">root</span><span class="p">]</span>
<span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">todo</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># while todo ...</span>
<span class="n">current</span> <span class="o">=</span> <span class="n">todo</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="c1"># list.pop(0): for dequeuing (on the left...) !</span>
<span class="n">seen</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">current</span><span class="p">)</span>
<span class="k">for</span> <span class="n">neighbour</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">current</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">neighbour</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">seen</span><span class="p">:</span>
<span class="n">todo</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">neighbour</span><span class="p">)</span>
<span class="k">return</span> <span class="n">seen</span></div></div>
<div class="viewcode-block" id="Graph"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.Graph">[docs]</a><span class="k">class</span> <span class="nc">Graph</span><span class="p">(</span><span class="n">GeneralGraph</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Class for non oriented graphs.&quot;&quot;&quot;</span>
<div class="viewcode-block" id="Graph.edges"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.Graph.edges">[docs]</a> <span class="k">def</span> <span class="nf">edges</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Set</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A static method generating the set of edges</span>
<span class="sd"> (they appear twice in the dictionnary).</span>
<span class="sd"> Return a list of sets.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">edges</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">vertex</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="k">for</span> <span class="n">neighbour</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex</span><span class="p">]:</span>
<span class="k">if</span> <span class="p">{</span><span class="n">neighbour</span><span class="p">,</span> <span class="n">vertex</span><span class="p">}</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">edges</span><span class="p">:</span>
<span class="n">edges</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="n">vertex</span><span class="p">,</span> <span class="n">neighbour</span><span class="p">})</span>
<span class="k">return</span> <span class="n">edges</span></div>
<div class="viewcode-block" id="Graph.add_edge"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.Graph.add_edge">[docs]</a> <span class="k">def</span> <span class="nf">add_edge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">edge</span><span class="p">:</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Add an edge in the graph.</span>
<span class="sd"> edge should be a pair and not (c,c)</span>
<span class="sd"> (we call g.add_edge((v1,v2)))</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="p">(</span><span class="n">vertex1</span><span class="p">,</span> <span class="n">vertex2</span><span class="p">)</span> <span class="o">=</span> <span class="n">edge</span>
<span class="k">if</span> <span class="n">vertex1</span> <span class="o">==</span> <span class="n">vertex2</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">GraphError</span><span class="p">(</span><span class="s2">&quot;Cannot add a self loop on vertex </span><span class="si">{}</span><span class="s2"> in an unoriented graph.&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="nb">str</span><span class="p">(</span><span class="n">vertex1</span><span class="p">)))</span>
<span class="k">if</span> <span class="n">vertex1</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex1</span><span class="p">]</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">vertex2</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">vertex2</span><span class="p">}</span>
<span class="k">if</span> <span class="n">vertex2</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex2</span><span class="p">]</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">vertex1</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">vertex1</span><span class="p">}</span></div>
<div class="viewcode-block" id="Graph.print_dot"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.Graph.print_dot">[docs]</a> <span class="k">def</span> <span class="nf">print_dot</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">colors</span><span class="o">=</span><span class="p">{})</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Print the graph.&quot;&quot;&quot;</span>
<span class="n">color_names</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;yellow&#39;</span><span class="p">,</span> <span class="s1">&#39;cyan&#39;</span><span class="p">,</span> <span class="s1">&#39;magenta&#39;</span><span class="p">]</span> <span class="o">+</span> \
<span class="p">[</span><span class="sa">f</span><span class="s2">&quot;grey</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">10</span><span class="p">)]</span>
<span class="n">color_shapes</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;ellipse&#39;</span><span class="p">,</span> <span class="s1">&#39;box&#39;</span><span class="p">,</span> <span class="s1">&#39;diamond&#39;</span><span class="p">,</span> <span class="s1">&#39;trapezium&#39;</span><span class="p">,</span> <span class="s1">&#39;egg&#39;</span><span class="p">,</span>
<span class="s1">&#39;parallelogram&#39;</span><span class="p">,</span> <span class="s1">&#39;house&#39;</span><span class="p">,</span> <span class="s1">&#39;triangle&#39;</span><span class="p">,</span> <span class="s1">&#39;pentagon&#39;</span><span class="p">,</span> <span class="s1">&#39;hexagon&#39;</span><span class="p">,</span>
<span class="s1">&#39;septagon&#39;</span><span class="p">,</span> <span class="s1">&#39;octagon&#39;</span><span class="p">]</span>
<span class="n">dot</span> <span class="o">=</span> <span class="n">Digraph</span><span class="p">(</span><span class="n">comment</span><span class="o">=</span><span class="s1">&#39;Conflict Graph&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="n">shape</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">colors</span><span class="p">:</span>
<span class="n">color</span> <span class="o">=</span> <span class="s2">&quot;red&quot;</span> <span class="c1"># Graph not colored: red for everyone</span>
<span class="k">elif</span> <span class="n">k</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">colors</span><span class="p">:</span>
<span class="n">color</span> <span class="o">=</span> <span class="s2">&quot;grey&quot;</span> <span class="c1"># Node not colored: grey</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">colors</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">color_names</span><span class="p">):</span>
<span class="n">color</span> <span class="o">=</span> <span class="n">color_names</span><span class="p">[</span><span class="n">colors</span><span class="p">[</span><span class="n">k</span><span class="p">]]</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">color</span> <span class="o">=</span> <span class="s2">&quot;black&quot;</span> <span class="c1"># Too many colors anyway, it won&#39;t be readable.</span>
<span class="n">shape</span> <span class="o">=</span> <span class="n">color_shapes</span><span class="p">[</span><span class="n">n</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">color_shapes</span><span class="p">)]</span>
<span class="n">dot</span><span class="o">.</span><span class="n">node</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">k</span><span class="p">),</span> <span class="n">color</span><span class="o">=</span><span class="n">color</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="n">shape</span><span class="p">)</span>
<span class="k">for</span> <span class="p">(</span><span class="n">v1</span><span class="p">,</span> <span class="n">v2</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">edges</span><span class="p">():</span>
<span class="n">dot</span><span class="o">.</span><span class="n">edge</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">v1</span><span class="p">),</span> <span class="nb">str</span><span class="p">(</span><span class="n">v2</span><span class="p">),</span> <span class="nb">dir</span><span class="o">=</span><span class="s2">&quot;none&quot;</span><span class="p">)</span>
<span class="c1"># print(dot.source)</span>
<span class="n">dot</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">view</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># print in pdf</span></div>
<div class="viewcode-block" id="Graph.delete_vertex"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.Graph.delete_vertex">[docs]</a> <span class="k">def</span> <span class="nf">delete_vertex</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vertex</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Delete a vertex and all the adjacent edges.&quot;&quot;&quot;</span>
<span class="n">gdict</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span>
<span class="k">for</span> <span class="n">neighbour</span> <span class="ow">in</span> <span class="n">gdict</span><span class="p">[</span><span class="n">vertex</span><span class="p">]:</span>
<span class="n">gdict</span><span class="p">[</span><span class="n">neighbour</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">vertex</span><span class="p">)</span>
<span class="k">del</span> <span class="n">gdict</span><span class="p">[</span><span class="n">vertex</span><span class="p">]</span></div>
<div class="viewcode-block" id="Graph.delete_edge"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.Graph.delete_edge">[docs]</a> <span class="k">def</span> <span class="nf">delete_edge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">edge</span><span class="p">:</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="n">Any</span><span class="p">]):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Delete an edge.&quot;&quot;&quot;</span>
<span class="p">(</span><span class="n">v1</span><span class="p">,</span> <span class="n">v2</span><span class="p">)</span> <span class="o">=</span> <span class="n">edge</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">v1</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">v2</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">v2</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">v1</span><span class="p">)</span></div>
<div class="viewcode-block" id="Graph.color"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.Graph.color">[docs]</a> <span class="k">def</span> <span class="nf">color</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="nb">int</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Color the graph with an unlimited number of colors.</span>
<span class="sd"> Return a dict vertex -&gt; color, where color is an integer (0, 1, ...).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">coloring</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">color_with_k_colors</span><span class="p">()</span>
<span class="k">return</span> <span class="n">coloring</span></div>
<span class="c1"># see algo of the course</span>
<div class="viewcode-block" id="Graph.color_with_k_colors"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.Graph.color_with_k_colors">[docs]</a> <span class="k">def</span> <span class="nf">color_with_k_colors</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">K</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">avoidingnodes</span><span class="o">=</span><span class="p">())</span> <span class="o">-&gt;</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="nb">int</span><span class="p">],</span> <span class="nb">bool</span><span class="p">,</span> <span class="n">List</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Color with &lt;= K colors (if K is unspecified, use unlimited colors).</span>
<span class="sd"> Return 3 values:</span>
<span class="sd"> - a dict vertex -&gt; color</span>
<span class="sd"> - a Boolean, True if the coloring succeeded</span>
<span class="sd"> - the set of nodes actually colored</span>
<span class="sd"> Do not color vertices belonging to avoidingnodes.</span>
<span class="sd"> Continue even if the algo fails.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">K</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">K</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">)</span>
<span class="n">todo_vertices</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">is_total</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">gcopy</span> <span class="o">=</span> <span class="n">Graph</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="o">.</span><span class="n">copy</span><span class="p">())</span>
<span class="c1"># suppress nodes that are not to be considered.</span>
<span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">avoidingnodes</span><span class="p">:</span>
<span class="n">gcopy</span><span class="o">.</span><span class="n">delete_vertex</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
<span class="c1"># append nodes in the list according to their degree and node number:</span>
<span class="k">while</span> <span class="n">gcopy</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="n">todo</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">gcopy</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">)</span>
<span class="n">todo</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">v</span><span class="p">:</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">gcopy</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">v</span><span class="p">]),</span> <span class="nb">str</span><span class="p">(</span><span class="n">v</span><span class="p">)))</span>
<span class="n">lower</span> <span class="o">=</span> <span class="n">todo</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">todo_vertices</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">lower</span><span class="p">)</span>
<span class="n">gcopy</span><span class="o">.</span><span class="n">delete_vertex</span><span class="p">(</span><span class="n">lower</span><span class="p">)</span>
<span class="c1"># Now reverse the list: first elements are those with higher degree</span>
<span class="c1"># print(todo_vertices)</span>
<span class="n">todo_vertices</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span> <span class="c1"># in place reversal</span>
<span class="c1"># print(todo_vertices)</span>
<span class="n">coloring</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">colored_nodes</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1"># gdict will be the coloring map to return</span>
<span class="n">gdict</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span>
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">todo_vertices</span><span class="p">:</span>
<span class="n">seen_neighbours</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">gdict</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="k">if</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">coloring</span><span class="p">]</span>
<span class="n">choose_among</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">K</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span>
<span class="n">i</span> <span class="ow">in</span> <span class="p">[</span><span class="n">coloring</span><span class="p">[</span><span class="n">v1</span><span class="p">]</span> <span class="k">for</span> <span class="n">v1</span> <span class="ow">in</span> <span class="n">seen_neighbours</span><span class="p">])]</span>
<span class="k">if</span> <span class="n">choose_among</span><span class="p">:</span>
<span class="c1"># if the node can be colored, I choose the minimal color.</span>
<span class="n">color</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">choose_among</span><span class="p">)</span>
<span class="n">coloring</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="n">color</span>
<span class="n">colored_nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># if I cannot color some node, the coloring is not Total</span>
<span class="c1"># but I continue</span>
<span class="n">is_total</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">return</span> <span class="p">(</span><span class="n">coloring</span><span class="p">,</span> <span class="n">is_total</span><span class="p">,</span> <span class="n">colored_nodes</span><span class="p">)</span></div></div>
<div class="viewcode-block" id="DiGraph"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.DiGraph">[docs]</a><span class="k">class</span> <span class="nc">DiGraph</span><span class="p">(</span><span class="n">GeneralGraph</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Class for directed graphs.&quot;&quot;&quot;</span>
<div class="viewcode-block" id="DiGraph.pred"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.DiGraph.pred">[docs]</a> <span class="k">def</span> <span class="nf">pred</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Set</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return all predecessors of the vertex `v` in the graph.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">{</span><span class="n">src</span> <span class="k">for</span> <span class="n">src</span><span class="p">,</span> <span class="n">dests</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">dests</span><span class="p">}</span></div>
<div class="viewcode-block" id="DiGraph.neighbourhoods"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.DiGraph.neighbourhoods">[docs]</a> <span class="k">def</span> <span class="nf">neighbourhoods</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="n">Set</span><span class="p">]]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return all neighbourhoods in the graph.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="o">.</span><span class="n">items</span><span class="p">())</span></div>
<div class="viewcode-block" id="DiGraph.edges"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.DiGraph.edges">[docs]</a> <span class="k">def</span> <span class="nf">edges</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Set</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot; A static method generating the set of edges&quot;&quot;&quot;</span>
<span class="n">edges</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">vertex</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="k">for</span> <span class="n">neighbour</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex</span><span class="p">]:</span>
<span class="n">edges</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">vertex</span><span class="p">,</span> <span class="n">neighbour</span><span class="p">))</span>
<span class="k">return</span> <span class="n">edges</span></div>
<div class="viewcode-block" id="DiGraph.add_edge"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.DiGraph.add_edge">[docs]</a> <span class="k">def</span> <span class="nf">add_edge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">edge</span><span class="p">:</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Add an edge in the graph.</span>
<span class="sd"> edge should be a pair and not (c,c)</span>
<span class="sd"> (we call g.add_edge((v1,v2)))</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="p">(</span><span class="n">vertex1</span><span class="p">,</span> <span class="n">vertex2</span><span class="p">)</span> <span class="o">=</span> <span class="n">edge</span>
<span class="k">if</span> <span class="n">vertex1</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex1</span><span class="p">]</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">vertex2</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">vertex2</span><span class="p">}</span>
<span class="k">if</span> <span class="n">vertex2</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex2</span><span class="p">]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span></div>
<div class="viewcode-block" id="DiGraph.print_dot"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.DiGraph.print_dot">[docs]</a> <span class="k">def</span> <span class="nf">print_dot</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Print the graph.&quot;&quot;&quot;</span>
<span class="n">dot</span> <span class="o">=</span> <span class="n">Digraph</span><span class="p">(</span><span class="n">comment</span><span class="o">=</span><span class="s1">&#39;Conflict Graph&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">:</span>
<span class="n">shape</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">color</span> <span class="o">=</span> <span class="s2">&quot;grey&quot;</span>
<span class="n">dot</span><span class="o">.</span><span class="n">node</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">k</span><span class="p">),</span> <span class="n">color</span><span class="o">=</span><span class="n">color</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="n">shape</span><span class="p">)</span>
<span class="k">for</span> <span class="p">(</span><span class="n">v1</span><span class="p">,</span> <span class="n">v2</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">edges</span><span class="p">():</span>
<span class="n">dot</span><span class="o">.</span><span class="n">edge</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">v1</span><span class="p">),</span> <span class="nb">str</span><span class="p">(</span><span class="n">v2</span><span class="p">),</span> <span class="nb">dir</span><span class="o">=</span><span class="s2">&quot;none&quot;</span><span class="p">)</span>
<span class="c1"># print(dot.source)</span>
<span class="n">dot</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">view</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># print in pdf</span></div>
<div class="viewcode-block" id="DiGraph.delete_vertex"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.DiGraph.delete_vertex">[docs]</a> <span class="k">def</span> <span class="nf">delete_vertex</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vertex</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Delete a vertex and all the adjacent edges.&quot;&quot;&quot;</span>
<span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">neighbours</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">if</span> <span class="n">vertex</span> <span class="ow">in</span> <span class="n">neighbours</span><span class="p">:</span>
<span class="n">neighbours</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">vertex</span><span class="p">)</span>
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">vertex</span><span class="p">]</span></div>
<div class="viewcode-block" id="DiGraph.delete_edge"><a class="viewcode-back" href="../../api/Lib.Graphes.html#Lib.Graphes.DiGraph.delete_edge">[docs]</a> <span class="k">def</span> <span class="nf">delete_edge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">edge</span><span class="p">:</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Delete an edge.&quot;&quot;&quot;</span>
<span class="p">(</span><span class="n">v1</span><span class="p">,</span> <span class="n">v2</span><span class="p">)</span> <span class="o">=</span> <span class="n">edge</span>
<span class="bp">self</span><span class="o">.</span><span class="n">graph_dict</span><span class="p">[</span><span class="n">v1</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">v2</span><span class="p">)</span></div></div>
</pre></div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, compil-lyon.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>

View File

@ -45,13 +45,8 @@
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>

View File

@ -45,13 +45,8 @@
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>

View File

@ -1,174 +0,0 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lib.PhiNode &mdash; MiniC documentation</title>
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../../index.html" class="icon icon-home">
MiniC
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Errors.html">Base library - Errors</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Statement.html">Base library - Statement</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">MiniC</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="../index.html">Module code</a></li>
<li class="breadcrumb-item active">Lib.PhiNode</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<h1>Source code for Lib.PhiNode</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Classes for φ nodes in a RiscV CFG :py:class:`CFG &lt;Lib.CFG.CFG&gt;` under SSA Form:</span>
<span class="sd">:py:class:`PhiNode` for a statement of the form temp_x = φ(temp_0, ..., temp_n).</span>
<span class="sd">These particular kinds of statements are expected to be in the field</span>
<span class="sd">b._phis for a :py:class:`Block &lt;Lib.CFG.Block&gt;` b.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span>
<span class="kn">from</span> <span class="nn">Lib.Operands</span> <span class="kn">import</span> <span class="n">Operand</span><span class="p">,</span> <span class="n">Temporary</span><span class="p">,</span> <span class="n">DataLocation</span><span class="p">,</span> <span class="n">Renamer</span>
<span class="kn">from</span> <span class="nn">Lib.Statement</span> <span class="kn">import</span> <span class="n">Statement</span><span class="p">,</span> <span class="n">Label</span>
<div class="viewcode-block" id="PhiNode"><a class="viewcode-back" href="../../api/Lib.PhiNode.html#Lib.PhiNode.PhiNode">[docs]</a><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">PhiNode</span><span class="p">(</span><span class="n">Statement</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A φ node is a renaming in the CFG, of the form temp_x = φ(temp_0, ..., temp_n).</span>
<span class="sd"> The field var contains the variable temp_x.</span>
<span class="sd"> The field srcs links each corresponding predecessor in the CFG</span>
<span class="sd"> ---identified by its label---, to the variable temp_i of the φ</span>
<span class="sd"> node.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">var</span><span class="p">:</span> <span class="n">DataLocation</span>
<span class="n">srcs</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Label</span><span class="p">,</span> <span class="n">Operand</span><span class="p">]</span>
<div class="viewcode-block" id="PhiNode.defined"><a class="viewcode-back" href="../../api/Lib.PhiNode.html#Lib.PhiNode.PhiNode.defined">[docs]</a> <span class="k">def</span> <span class="nf">defined</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Operand</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the variable defined by the φ node.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">]</span></div>
<div class="viewcode-block" id="PhiNode.get_srcs"><a class="viewcode-back" href="../../api/Lib.PhiNode.html#Lib.PhiNode.PhiNode.get_srcs">[docs]</a> <span class="k">def</span> <span class="nf">get_srcs</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Label</span><span class="p">,</span> <span class="n">Operand</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Return the dictionnary associating for each previous block the corresponding variable.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">srcs</span></div>
<div class="viewcode-block" id="PhiNode.used"><a class="viewcode-back" href="../../api/Lib.PhiNode.html#Lib.PhiNode.PhiNode.used">[docs]</a> <span class="k">def</span> <span class="nf">used</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Operand</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the variables used by the statement.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">srcs</span><span class="o">.</span><span class="n">values</span><span class="p">())</span></div>
<div class="viewcode-block" id="PhiNode.rename"><a class="viewcode-back" href="../../api/Lib.PhiNode.html#Lib.PhiNode.PhiNode.rename">[docs]</a> <span class="k">def</span> <span class="nf">rename</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">renamer</span><span class="p">:</span> <span class="n">Renamer</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Rename the variable defined by the φ node with a fresh name.&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">,</span> <span class="n">Temporary</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="o">=</span> <span class="n">renamer</span><span class="o">.</span><span class="n">fresh</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">)</span></div>
<div class="viewcode-block" id="PhiNode.rename_from"><a class="viewcode-back" href="../../api/Lib.PhiNode.html#Lib.PhiNode.PhiNode.rename_from">[docs]</a> <span class="k">def</span> <span class="nf">rename_from</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">renamer</span><span class="p">:</span> <span class="n">Renamer</span><span class="p">,</span> <span class="n">label</span><span class="p">:</span> <span class="n">Label</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Rename the variable associated to the block identified by `label`.&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">label</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">srcs</span><span class="p">:</span>
<span class="n">t</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">srcs</span><span class="p">[</span><span class="n">label</span><span class="p">]</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">Temporary</span><span class="p">):</span>
<span class="k">if</span> <span class="n">renamer</span><span class="o">.</span><span class="n">defined</span><span class="p">(</span><span class="n">t</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">srcs</span><span class="p">[</span><span class="n">label</span><span class="p">]</span> <span class="o">=</span> <span class="n">renamer</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">srcs</span><span class="p">[</span><span class="n">label</span><span class="p">]</span></div>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2"> = φ(</span><span class="si">{}</span><span class="s2">)&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">srcs</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">hash</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">,</span> <span class="o">*</span><span class="bp">self</span><span class="o">.</span><span class="n">srcs</span><span class="o">.</span><span class="n">items</span><span class="p">()))</span>
<div class="viewcode-block" id="PhiNode.printIns"><a class="viewcode-back" href="../../api/Lib.PhiNode.html#Lib.PhiNode.PhiNode.printIns">[docs]</a> <span class="k">def</span> <span class="nf">printIns</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stream</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39; # &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">),</span> <span class="n">file</span><span class="o">=</span><span class="n">stream</span><span class="p">)</span></div></div>
</pre></div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, compil-lyon.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>

View File

@ -45,13 +45,8 @@
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>

View File

@ -45,13 +45,8 @@
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li> <li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>

View File

@ -1,264 +0,0 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lib.Terminator &mdash; MiniC documentation</title>
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../../index.html" class="icon icon-home">
MiniC
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Errors.html">Base library - Errors</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Statement.html">Base library - Statement</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">MiniC</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="../index.html">Module code</a></li>
<li class="breadcrumb-item active">Lib.Terminator</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<h1>Source code for Lib.Terminator</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">MIF08, CAP, CFG library - Terminators.</span>
<span class="sd">Each :py:class:`block &lt;Lib.CFG.Block&gt;` of a :py:class:`CFG &lt;Lib.CFG.CFG&gt;`</span>
<span class="sd">ends with a branching instruction called a terminator.</span>
<span class="sd">There are three kinds of terminators:</span>
<span class="sd">- :py:class:`Lib.Statement.AbsoluteJump` is a non-conditional jump</span>
<span class="sd"> to another block of the CFG</span>
<span class="sd">- :py:class:`BranchingTerminator` is a conditional branching</span>
<span class="sd"> instruction with two successor blocks.</span>
<span class="sd"> Unlike the class :py:class:`ConditionalJump &lt;Lib.Statement.ConditionalJump&gt;`</span>
<span class="sd"> that was used in :py:class:`LinearCode &lt;Lib.LinearCode.LinearCode&gt;`,</span>
<span class="sd"> both successor labels have to be specified.</span>
<span class="sd">- :py:class:`Return` marks the end of the function</span>
<span class="sd">During the construction of the CFG, :py:func:`jump2terminator` builds</span>
<span class="sd">a terminator for each extracted chunk of instructions.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span>
<span class="kn">from</span> <span class="nn">Lib.Errors</span> <span class="kn">import</span> <span class="n">MiniCInternalError</span>
<span class="kn">from</span> <span class="nn">Lib.Operands</span> <span class="kn">import</span> <span class="n">Operand</span><span class="p">,</span> <span class="n">Renamer</span><span class="p">,</span> <span class="n">Temporary</span><span class="p">,</span> <span class="n">Condition</span>
<span class="kn">from</span> <span class="nn">Lib.Statement</span> <span class="kn">import</span> <span class="n">AbsoluteJump</span><span class="p">,</span> <span class="n">ConditionalJump</span><span class="p">,</span> <span class="n">Instruction</span><span class="p">,</span> <span class="n">Label</span><span class="p">,</span> <span class="n">Statement</span>
<div class="viewcode-block" id="Return"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.Return">[docs]</a><span class="nd">@dataclass</span><span class="p">(</span><span class="n">unsafe_hash</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Return</span><span class="p">(</span><span class="n">Statement</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;A terminator that marks the end of the function.&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="s2">&quot;return&quot;</span><span class="p">)</span>
<div class="viewcode-block" id="Return.printIns"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.Return.printIns">[docs]</a> <span class="k">def</span> <span class="nf">printIns</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stream</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;return&quot;</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">stream</span><span class="p">)</span></div>
<div class="viewcode-block" id="Return.targets"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.Return.targets">[docs]</a> <span class="k">def</span> <span class="nf">targets</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Label</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the labels targetted by the Return terminator.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">[]</span></div>
<div class="viewcode-block" id="Return.args"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.Return.args">[docs]</a> <span class="k">def</span> <span class="nf">args</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Operand</span><span class="p">]:</span>
<span class="k">return</span> <span class="p">[]</span></div>
<div class="viewcode-block" id="Return.rename"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.Return.rename">[docs]</a> <span class="k">def</span> <span class="nf">rename</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">renamer</span><span class="p">:</span> <span class="n">Renamer</span><span class="p">):</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="Return.substitute"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.Return.substitute">[docs]</a> <span class="k">def</span> <span class="nf">substitute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">subst</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Operand</span><span class="p">,</span> <span class="n">Operand</span><span class="p">]):</span>
<span class="k">if</span> <span class="n">subst</span> <span class="o">!=</span> <span class="p">{}:</span>
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span>
<span class="s2">&quot;substitute: No possible substitution on instruction </span><span class="si">{}</span><span class="s2">&quot;</span>
<span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
<span class="k">return</span> <span class="bp">self</span></div>
<div class="viewcode-block" id="Return.with_args"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.Return.with_args">[docs]</a> <span class="k">def</span> <span class="nf">with_args</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new_args</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Operand</span><span class="p">]):</span>
<span class="k">if</span> <span class="n">new_args</span> <span class="o">!=</span> <span class="p">[]:</span>
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span>
<span class="s2">&quot;substitute: No possible substitution on instruction </span><span class="si">{}</span><span class="s2">&quot;</span>
<span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
<span class="k">return</span> <span class="bp">self</span></div>
<div class="viewcode-block" id="Return.is_read_only"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.Return.is_read_only">[docs]</a> <span class="k">def</span> <span class="nf">is_read_only</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">True</span></div></div>
<div class="viewcode-block" id="BranchingTerminator"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.BranchingTerminator">[docs]</a><span class="nd">@dataclass</span><span class="p">(</span><span class="n">init</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">BranchingTerminator</span><span class="p">(</span><span class="n">Instruction</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;A terminating statement with a condition.&quot;&quot;&quot;</span>
<span class="c1">#: The condition of the branch</span>
<span class="n">cond</span><span class="p">:</span> <span class="n">Condition</span>
<span class="c1">#: The destination label if the condition is true</span>
<span class="n">label_then</span><span class="p">:</span> <span class="n">Label</span>
<span class="c1">#: The destination label if the condition is false</span>
<span class="n">label_else</span><span class="p">:</span> <span class="n">Label</span>
<span class="c1">#: The first operand of the condition</span>
<span class="n">op1</span><span class="p">:</span> <span class="n">Operand</span>
<span class="c1">#: The second operand of the condition</span>
<span class="n">op2</span><span class="p">:</span> <span class="n">Operand</span>
<span class="n">_read_only</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cond</span><span class="p">:</span> <span class="n">Condition</span><span class="p">,</span> <span class="n">op1</span><span class="p">:</span> <span class="n">Operand</span><span class="p">,</span> <span class="n">op2</span><span class="p">:</span> <span class="n">Operand</span><span class="p">,</span>
<span class="n">label_then</span><span class="p">:</span> <span class="n">Label</span><span class="p">,</span> <span class="n">label_else</span><span class="p">:</span> <span class="n">Label</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cond</span> <span class="o">=</span> <span class="n">cond</span>
<span class="bp">self</span><span class="o">.</span><span class="n">label_then</span> <span class="o">=</span> <span class="n">label_then</span>
<span class="bp">self</span><span class="o">.</span><span class="n">label_else</span> <span class="o">=</span> <span class="n">label_else</span>
<span class="bp">self</span><span class="o">.</span><span class="n">op1</span> <span class="o">=</span> <span class="n">op1</span>
<span class="bp">self</span><span class="o">.</span><span class="n">op2</span> <span class="o">=</span> <span class="n">op2</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ins</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cond</span><span class="p">)</span>
<div class="viewcode-block" id="BranchingTerminator.args"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.BranchingTerminator.args">[docs]</a> <span class="k">def</span> <span class="nf">args</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Operand</span><span class="p">]:</span>
<span class="k">return</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">op1</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">op2</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">label_then</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">label_else</span><span class="p">]</span></div>
<div class="viewcode-block" id="BranchingTerminator.targets"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.BranchingTerminator.targets">[docs]</a> <span class="k">def</span> <span class="nf">targets</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Label</span><span class="p">]:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the labels targetted by the Branching terminator.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">label_then</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">label_else</span><span class="p">]</span></div>
<div class="viewcode-block" id="BranchingTerminator.rename"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.BranchingTerminator.rename">[docs]</a> <span class="k">def</span> <span class="nf">rename</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">renamer</span><span class="p">:</span> <span class="n">Renamer</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">op1</span><span class="p">,</span> <span class="n">Temporary</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">op1</span> <span class="o">=</span> <span class="n">renamer</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">op1</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">op2</span><span class="p">,</span> <span class="n">Temporary</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">op2</span> <span class="o">=</span> <span class="n">renamer</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">op2</span><span class="p">)</span></div>
<div class="viewcode-block" id="BranchingTerminator.substitute"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.BranchingTerminator.substitute">[docs]</a> <span class="k">def</span> <span class="nf">substitute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">subst</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="n">Operand</span><span class="p">,</span> <span class="n">Operand</span><span class="p">]):</span>
<span class="k">for</span> <span class="n">op</span> <span class="ow">in</span> <span class="n">subst</span><span class="p">:</span>
<span class="k">if</span> <span class="n">op</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">():</span>
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span>
<span class="s2">&quot;substitute: Operand </span><span class="si">{}</span><span class="s2"> is not present in instruction </span><span class="si">{}</span><span class="s2">&quot;</span>
<span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="bp">self</span><span class="p">))</span>
<span class="n">op1</span> <span class="o">=</span> <span class="n">subst</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">op1</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">op1</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">op1</span><span class="p">,</span> <span class="n">Temporary</span><span class="p">)</span> \
<span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">op1</span>
<span class="n">op2</span> <span class="o">=</span> <span class="n">subst</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">op2</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">op2</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">op2</span><span class="p">,</span> <span class="n">Temporary</span><span class="p">)</span> \
<span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">op2</span>
<span class="k">return</span> <span class="n">BranchingTerminator</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cond</span><span class="p">,</span> <span class="n">op1</span><span class="p">,</span> <span class="n">op2</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">label_then</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">label_else</span><span class="p">)</span></div>
<div class="viewcode-block" id="BranchingTerminator.with_args"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.BranchingTerminator.with_args">[docs]</a> <span class="k">def</span> <span class="nf">with_args</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new_args</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Operand</span><span class="p">]):</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">new_args</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">4</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span>
<span class="s2">&quot;substitute: Invalid number of arguments for instruction </span><span class="si">{}</span><span class="s2">, expected 4 got </span><span class="si">{}</span><span class="s2">&quot;</span>
<span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new_args</span><span class="p">))</span>
<span class="n">op1</span> <span class="o">=</span> <span class="n">new_args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">op2</span> <span class="o">=</span> <span class="n">new_args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">return</span> <span class="n">BranchingTerminator</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cond</span><span class="p">,</span> <span class="n">op1</span><span class="p">,</span> <span class="n">op2</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">label_then</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">label_else</span><span class="p">)</span></div>
<span class="k">def</span> <span class="fm">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">hash</span><span class="p">(</span><span class="nb">super</span><span class="p">)</span></div>
<span class="n">Terminator</span> <span class="o">=</span> <span class="n">Return</span> <span class="o">|</span> <span class="n">AbsoluteJump</span> <span class="o">|</span> <span class="n">BranchingTerminator</span>
<span class="sd">&quot;&quot;&quot;Type alias for terminators&quot;&quot;&quot;</span>
<div class="viewcode-block" id="jump2terminator"><a class="viewcode-back" href="../../api/Lib.Terminator.html#Lib.Terminator.jump2terminator">[docs]</a><span class="k">def</span> <span class="nf">jump2terminator</span><span class="p">(</span><span class="n">j</span><span class="p">:</span> <span class="n">ConditionalJump</span> <span class="o">|</span> <span class="n">AbsoluteJump</span> <span class="o">|</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">next_label</span><span class="p">:</span> <span class="n">Label</span> <span class="o">|</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Terminator</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Construct the Terminator associated to the potential jump j</span>
<span class="sd"> to the potential label next_label.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">match</span> <span class="n">j</span><span class="p">:</span>
<span class="k">case</span> <span class="n">ConditionalJump</span><span class="p">():</span>
<span class="k">if</span> <span class="p">(</span><span class="n">next_label</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">):</span>
<span class="k">raise</span> <span class="n">MiniCInternalError</span><span class="p">(</span>
<span class="s2">&quot;jump2terminator: Missing secondary label for instruction </span><span class="si">{}</span><span class="s2">&quot;</span>
<span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">j</span><span class="p">))</span>
<span class="n">label_else</span> <span class="o">=</span> <span class="n">next_label</span>
<span class="k">return</span> <span class="n">BranchingTerminator</span><span class="p">(</span><span class="n">j</span><span class="o">.</span><span class="n">cond</span><span class="p">,</span> <span class="n">j</span><span class="o">.</span><span class="n">op1</span><span class="p">,</span> <span class="n">j</span><span class="o">.</span><span class="n">op2</span><span class="p">,</span> <span class="n">j</span><span class="o">.</span><span class="n">label</span><span class="p">,</span> <span class="n">label_else</span><span class="p">)</span>
<span class="k">case</span> <span class="n">AbsoluteJump</span><span class="p">():</span>
<span class="k">return</span> <span class="n">AbsoluteJump</span><span class="p">(</span><span class="n">label</span><span class="o">=</span><span class="n">j</span><span class="o">.</span><span class="n">label</span><span class="p">)</span>
<span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span>
<span class="k">if</span> <span class="n">next_label</span><span class="p">:</span>
<span class="k">return</span> <span class="n">AbsoluteJump</span><span class="p">(</span><span class="n">next_label</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">Return</span><span class="p">()</span></div>
</pre></div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, compil-lyon.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>

View File

@ -45,13 +45,8 @@
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="../api/Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="../api/Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="../api/Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="../api/Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.Allocator.html">Temporary allocation</a></li> <li class="toctree-l1"><a class="reference internal" href="../api/Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>
@ -79,17 +74,12 @@
<h1>All modules for which code is available</h1> <h1>All modules for which code is available</h1>
<ul><li><a href="Lib/Allocator.html">Lib.Allocator</a></li> <ul><li><a href="Lib/Allocator.html">Lib.Allocator</a></li>
<li><a href="Lib/CFG.html">Lib.CFG</a></li>
<li><a href="Lib/Dominators.html">Lib.Dominators</a></li>
<li><a href="Lib/Errors.html">Lib.Errors</a></li> <li><a href="Lib/Errors.html">Lib.Errors</a></li>
<li><a href="Lib/FunctionData.html">Lib.FunctionData</a></li> <li><a href="Lib/FunctionData.html">Lib.FunctionData</a></li>
<li><a href="Lib/Graphes.html">Lib.Graphes</a></li>
<li><a href="Lib/LinearCode.html">Lib.LinearCode</a></li> <li><a href="Lib/LinearCode.html">Lib.LinearCode</a></li>
<li><a href="Lib/Operands.html">Lib.Operands</a></li> <li><a href="Lib/Operands.html">Lib.Operands</a></li>
<li><a href="Lib/PhiNode.html">Lib.PhiNode</a></li>
<li><a href="Lib/RiscV.html">Lib.RiscV</a></li> <li><a href="Lib/RiscV.html">Lib.RiscV</a></li>
<li><a href="Lib/Statement.html">Lib.Statement</a></li> <li><a href="Lib/Statement.html">Lib.Statement</a></li>
<li><a href="Lib/Terminator.html">Lib.Terminator</a></li>
</ul> </ul>
</div> </div>

View File

@ -1,7 +0,0 @@
Lib.CFG module
==============
.. automodule:: Lib.CFG
:members:
:undoc-members:
:show-inheritance:

View File

@ -1,7 +0,0 @@
Lib.Dominators module
=====================
.. automodule:: Lib.Dominators
:members:
:undoc-members:
:show-inheritance:

View File

@ -1,7 +0,0 @@
Lib.Graphes module
==================
.. automodule:: Lib.Graphes
:members:
:undoc-members:
:show-inheritance:

View File

@ -1,7 +0,0 @@
Lib.PhiNode module
==================
.. automodule:: Lib.PhiNode
:members:
:undoc-members:
:show-inheritance:

View File

@ -1,7 +0,0 @@
Lib.Terminator module
=====================
.. automodule:: Lib.Terminator
:members:
:undoc-members:
:show-inheritance:

View File

@ -8,17 +8,12 @@ Submodules
:maxdepth: 4 :maxdepth: 4
Lib.Allocator Lib.Allocator
Lib.CFG
Lib.Dominators
Lib.Errors Lib.Errors
Lib.FunctionData Lib.FunctionData
Lib.Graphes
Lib.LinearCode Lib.LinearCode
Lib.Operands Lib.Operands
Lib.PhiNode
Lib.RiscV Lib.RiscV
Lib.Statement Lib.Statement
Lib.Terminator
Module contents Module contents
--------------- ---------------

View File

@ -18,7 +18,6 @@
<script src="../_static/js/theme.js"></script> <script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" /> <link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" /> <link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Lib.CFG module" href="Lib.CFG.html" />
<link rel="prev" title="Lib.LinearCode module" href="Lib.LinearCode.html" /> <link rel="prev" title="Lib.LinearCode module" href="Lib.LinearCode.html" />
</head> </head>
@ -48,7 +47,6 @@
<li class="toctree-l1"><a class="reference internal" href="Lib.RiscV.html">Base library - RISC-V instructions</a></li> <li class="toctree-l1"><a class="reference internal" href="Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Operands.html">Base library - Operands</a></li> <li class="toctree-l1"><a class="reference internal" href="Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.FunctionData.html">Base library - Function data</a></li> <li class="toctree-l1"><a class="reference internal" href="Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.LinearCode.html">Linear intermediate representation</a></li> <li class="toctree-l1"><a class="reference internal" href="Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Temporary allocation</a><ul> <li class="toctree-l1 current"><a class="current reference internal" href="#">Temporary allocation</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#Lib.Allocator.Allocator"><code class="docutils literal notranslate"><span class="pre">Allocator</span></code></a><ul> <li class="toctree-l2"><a class="reference internal" href="#Lib.Allocator.Allocator"><code class="docutils literal notranslate"><span class="pre">Allocator</span></code></a><ul>
@ -64,10 +62,6 @@
</li> </li>
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul> </ul>
</div> </div>
@ -165,7 +159,6 @@ Fail if there are too many temporaries.</p>
</div> </div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer"> <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="Lib.LinearCode.html" class="btn btn-neutral float-left" title="Lib.LinearCode module" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> <a href="Lib.LinearCode.html" class="btn btn-neutral float-left" title="Lib.LinearCode module" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="Lib.CFG.html" class="btn btn-neutral float-right" title="Lib.CFG module" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div> </div>
<hr/> <hr/>

View File

@ -1,375 +0,0 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lib.CFG module &mdash; MiniC documentation</title>
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Lib.Terminator module" href="Lib.Terminator.html" />
<link rel="prev" title="Lib.Allocator module" href="Lib.Allocator.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../index.html" class="icon icon-home">
MiniC
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Lib.Errors.html">Base library - Errors</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Statement.html">Base library - Statement</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Control Flow Graph - CFG and Basic blocks</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#Lib.CFG.Block"><code class="docutils literal notranslate"><span class="pre">Block</span></code></a><ul>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.to_dot"><code class="docutils literal notranslate"><span class="pre">Block.to_dot()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.get_body"><code class="docutils literal notranslate"><span class="pre">Block.get_body()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.get_all_statements"><code class="docutils literal notranslate"><span class="pre">Block.get_all_statements()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.get_body_and_terminator"><code class="docutils literal notranslate"><span class="pre">Block.get_body_and_terminator()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.get_label"><code class="docutils literal notranslate"><span class="pre">Block.get_label()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.get_in"><code class="docutils literal notranslate"><span class="pre">Block.get_in()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.get_terminator"><code class="docutils literal notranslate"><span class="pre">Block.get_terminator()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.set_terminator"><code class="docutils literal notranslate"><span class="pre">Block.set_terminator()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.get_phis"><code class="docutils literal notranslate"><span class="pre">Block.get_phis()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.add_phi"><code class="docutils literal notranslate"><span class="pre">Block.add_phi()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.set_phis"><code class="docutils literal notranslate"><span class="pre">Block.set_phis()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.remove_all_phis"><code class="docutils literal notranslate"><span class="pre">Block.remove_all_phis()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.iter_statements"><code class="docutils literal notranslate"><span class="pre">Block.iter_statements()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.Block.add_instruction"><code class="docutils literal notranslate"><span class="pre">Block.add_instruction()</span></code></a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#Lib.CFG.CFG"><code class="docutils literal notranslate"><span class="pre">CFG</span></code></a><ul>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.fdata"><code class="docutils literal notranslate"><span class="pre">CFG.fdata</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.get_start"><code class="docutils literal notranslate"><span class="pre">CFG.get_start()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.set_start"><code class="docutils literal notranslate"><span class="pre">CFG.set_start()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.get_end"><code class="docutils literal notranslate"><span class="pre">CFG.get_end()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.add_block"><code class="docutils literal notranslate"><span class="pre">CFG.add_block()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.get_block"><code class="docutils literal notranslate"><span class="pre">CFG.get_block()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.get_blocks"><code class="docutils literal notranslate"><span class="pre">CFG.get_blocks()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.get_entries"><code class="docutils literal notranslate"><span class="pre">CFG.get_entries()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.add_edge"><code class="docutils literal notranslate"><span class="pre">CFG.add_edge()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.remove_edge"><code class="docutils literal notranslate"><span class="pre">CFG.remove_edge()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.out_blocks"><code class="docutils literal notranslate"><span class="pre">CFG.out_blocks()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.gather_defs"><code class="docutils literal notranslate"><span class="pre">CFG.gather_defs()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.iter_statements"><code class="docutils literal notranslate"><span class="pre">CFG.iter_statements()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.linearize_naive"><code class="docutils literal notranslate"><span class="pre">CFG.linearize_naive()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.print_code"><code class="docutils literal notranslate"><span class="pre">CFG.print_code()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#Lib.CFG.CFG.print_dot"><code class="docutils literal notranslate"><span class="pre">CFG.print_dot()</span></code></a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Dominators.html">SSA form - Dominance frontier</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">MiniC</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item active">Lib.CFG module</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/api/Lib.CFG.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="module-Lib.CFG">
<span id="lib-cfg-module"></span><h1>Lib.CFG module<a class="headerlink" href="#module-Lib.CFG" title="Permalink to this heading"></a></h1>
<p>Classes for a RiscV CFG: <a class="reference internal" href="#Lib.CFG.CFG" title="Lib.CFG.CFG"><code class="xref py py-class docutils literal notranslate"><span class="pre">CFG</span></code></a> for the CFG itself,
and <a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><code class="xref py py-class docutils literal notranslate"><span class="pre">Block</span></code></a> for its basic blocks.</p>
<dl class="py class">
<dt class="sig sig-object py" id="Lib.CFG.Block">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">Lib.CFG.</span></span><span class="sig-name descname"><span class="pre">Block</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">label</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Label" title="Lib.Statement.Label"><span class="pre">Label</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">insts</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Instru3A" title="Lib.Statement.Instru3A"><span class="pre">Instru3A</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Comment" title="Lib.Statement.Comment"><span class="pre">Comment</span></a><span class="p"><span class="pre">]</span></span></span></em>, <em class="sig-param"><span class="n"><span class="pre">terminator</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.Terminator.html#Lib.Terminator.Return" title="Lib.Terminator.Return"><span class="pre">Return</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.AbsoluteJump" title="Lib.Statement.AbsoluteJump"><span class="pre">AbsoluteJump</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Terminator.html#Lib.Terminator.BranchingTerminator" title="Lib.Terminator.BranchingTerminator"><span class="pre">BranchingTerminator</span></a></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/Lib/CFG.html#Block"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block" title="Permalink to this definition"></a></dt>
<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p>
<p>A basic block of a <a class="reference internal" href="#Lib.CFG.CFG" title="Lib.CFG.CFG"><code class="xref py py-class docutils literal notranslate"><span class="pre">CFG</span></code></a> is made of three main parts:</p>
<ul class="simple">
<li><p>a start <a class="reference internal" href="Lib.Statement.html#Lib.Statement.Label" title="Lib.Statement.Label"><code class="xref py py-class docutils literal notranslate"><span class="pre">label</span></code></a> that uniquely identifies the block in the CFG</p></li>
<li><p>the main body of the block, a list of instructions
(excluding labels, jumps and branching instructions)</p></li>
<li><p>a <a class="reference internal" href="Lib.Terminator.html#Lib.Terminator.Terminator" title="Lib.Terminator.Terminator"><code class="xref py py-class docutils literal notranslate"><span class="pre">terminator</span></code></a>
that represents the final jump or branching instruction of the block,
and points to the successors of the block.
See the documentation for <a class="reference internal" href="Lib.Terminator.html#Lib.Terminator.Terminator" title="Lib.Terminator.Terminator"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lib.Terminator.Terminator</span></code></a> for further explanations.</p></li>
</ul>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.to_dot">
<span class="sig-name descname"><span class="pre">to_dot</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">str</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.to_dot"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.to_dot" title="Permalink to this definition"></a></dt>
<dd><p>Outputs all statements of the block as a string.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.get_body">
<span class="sig-name descname"><span class="pre">get_body</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Instru3A" title="Lib.Statement.Instru3A"><span class="pre">Instru3A</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Comment" title="Lib.Statement.Comment"><span class="pre">Comment</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.get_body"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.get_body" title="Permalink to this definition"></a></dt>
<dd><p>Return the statements in the body of the block (no phi-node nor the terminator).</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.get_all_statements">
<span class="sig-name descname"><span class="pre">get_all_statements</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Statement" title="Lib.Statement.Statement"><span class="pre">Statement</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.get_all_statements"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.get_all_statements" title="Permalink to this definition"></a></dt>
<dd><p>Return all statements of the block
(including phi-nodes and the terminator, but not the label of the block).</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.get_body_and_terminator">
<span class="sig-name descname"><span class="pre">get_body_and_terminator</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Statement" title="Lib.Statement.Statement"><span class="pre">Statement</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.get_body_and_terminator"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.get_body_and_terminator" title="Permalink to this definition"></a></dt>
<dd><p>Return all statements of the block, except phi-nodes
(and the label of the block).</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.get_label">
<span class="sig-name descname"><span class="pre">get_label</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Label" title="Lib.Statement.Label"><span class="pre">Label</span></a></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.get_label"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.get_label" title="Permalink to this definition"></a></dt>
<dd><p>Return the label of the block.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.get_in">
<span class="sig-name descname"><span class="pre">get_in</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.get_in"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.get_in" title="Permalink to this definition"></a></dt>
<dd><p>Return the list of blocks with an edge to the considered block.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.get_terminator">
<span class="sig-name descname"><span class="pre">get_terminator</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><a class="reference internal" href="Lib.Terminator.html#Lib.Terminator.Return" title="Lib.Terminator.Return"><span class="pre">Return</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.AbsoluteJump" title="Lib.Statement.AbsoluteJump"><span class="pre">AbsoluteJump</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Terminator.html#Lib.Terminator.BranchingTerminator" title="Lib.Terminator.BranchingTerminator"><span class="pre">BranchingTerminator</span></a></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.get_terminator"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.get_terminator" title="Permalink to this definition"></a></dt>
<dd><p>Return the terminator of the block.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.set_terminator">
<span class="sig-name descname"><span class="pre">set_terminator</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">term</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.Terminator.html#Lib.Terminator.Return" title="Lib.Terminator.Return"><span class="pre">Return</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.AbsoluteJump" title="Lib.Statement.AbsoluteJump"><span class="pre">AbsoluteJump</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Terminator.html#Lib.Terminator.BranchingTerminator" title="Lib.Terminator.BranchingTerminator"><span class="pre">BranchingTerminator</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.set_terminator"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.set_terminator" title="Permalink to this definition"></a></dt>
<dd><p>Set the terminator of the block.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.get_phis">
<span class="sig-name descname"><span class="pre">get_phis</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Statement" title="Lib.Statement.Statement"><span class="pre">Statement</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.get_phis"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.get_phis" title="Permalink to this definition"></a></dt>
<dd><p>Return the list of all φ instructions of the block.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.add_phi">
<span class="sig-name descname"><span class="pre">add_phi</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">phi</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Statement" title="Lib.Statement.Statement"><span class="pre">Statement</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.add_phi"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.add_phi" title="Permalink to this definition"></a></dt>
<dd><p>Add a φ instruction to the block.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.set_phis">
<span class="sig-name descname"><span class="pre">set_phis</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">phis</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Statement" title="Lib.Statement.Statement"><span class="pre">Statement</span></a><span class="p"><span class="pre">]</span></span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.set_phis"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.set_phis" title="Permalink to this definition"></a></dt>
<dd><p>Replace the φ instructions in the block by the given list <cite>phis</cite>.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.remove_all_phis">
<span class="sig-name descname"><span class="pre">remove_all_phis</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.remove_all_phis"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.remove_all_phis" title="Permalink to this definition"></a></dt>
<dd><p>Remove all φ instructions in the block.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.iter_statements">
<span class="sig-name descname"><span class="pre">iter_statements</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">f</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.iter_statements"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.iter_statements" title="Permalink to this definition"></a></dt>
<dd><p>Iterate over instructions.
For each real instruction i (not label or comment), replace it
with the list of instructions given by f(i).</p>
<p>Assume there is no phi-node.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.Block.add_instruction">
<span class="sig-name descname"><span class="pre">add_instruction</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">instr</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Instru3A" title="Lib.Statement.Instru3A"><span class="pre">Instru3A</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Comment" title="Lib.Statement.Comment"><span class="pre">Comment</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#Block.add_instruction"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.Block.add_instruction" title="Permalink to this definition"></a></dt>
<dd><p>Add an instruction to the body of the block.</p>
</dd></dl>
</dd></dl>
<dl class="py class">
<dt class="sig sig-object py" id="Lib.CFG.CFG">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">Lib.CFG.</span></span><span class="sig-name descname"><span class="pre">CFG</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">fdata</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.FunctionData.html#Lib.FunctionData.FunctionData" title="Lib.FunctionData.FunctionData"><span class="pre">FunctionData</span></a></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG" title="Permalink to this definition"></a></dt>
<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p>
<p>A complete control-flow graph representing a function.
This class is mainly made of a list of basic <a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><code class="xref py py-class docutils literal notranslate"><span class="pre">Block</span></code></a>,
a label indicating the <a class="reference internal" href="#Lib.CFG.CFG.get_start" title="Lib.CFG.CFG.get_start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">entry</span> <span class="pre">point</span> <span class="pre">of</span> <span class="pre">the</span> <span class="pre">function</span></code></a>,
and an <a class="reference internal" href="#Lib.CFG.CFG.get_end" title="Lib.CFG.CFG.get_end"><code class="xref py py-meth docutils literal notranslate"><span class="pre">exit</span> <span class="pre">label</span></code></a>.</p>
<p>As with linear code, metadata about the function can be found
in the <a class="reference internal" href="#Lib.CFG.CFG.fdata" title="Lib.CFG.CFG.fdata"><code class="xref py py-attr docutils literal notranslate"><span class="pre">fdata</span></code></a> member variable.</p>
<dl class="py attribute">
<dt class="sig sig-object py" id="Lib.CFG.CFG.fdata">
<span class="sig-name descname"><span class="pre">fdata</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference internal" href="Lib.FunctionData.html#Lib.FunctionData.FunctionData" title="Lib.FunctionData.FunctionData"><span class="pre">FunctionData</span></a></em><a class="headerlink" href="#Lib.CFG.CFG.fdata" title="Permalink to this definition"></a></dt>
<dd><p>Metadata about the function represented by this CFG</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.get_start">
<span class="sig-name descname"><span class="pre">get_start</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Label" title="Lib.Statement.Label"><span class="pre">Label</span></a></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.get_start"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.get_start" title="Permalink to this definition"></a></dt>
<dd><p>Return the entry label of the CFG.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.set_start">
<span class="sig-name descname"><span class="pre">set_start</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">start</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Label" title="Lib.Statement.Label"><span class="pre">Label</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.set_start"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.set_start" title="Permalink to this definition"></a></dt>
<dd><p>Set the entry label of the CFG.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.get_end">
<span class="sig-name descname"><span class="pre">get_end</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Label" title="Lib.Statement.Label"><span class="pre">Label</span></a></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.get_end"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.get_end" title="Permalink to this definition"></a></dt>
<dd><p>Return the exit label of the CFG.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.add_block">
<span class="sig-name descname"><span class="pre">add_block</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">blk</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.add_block"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.add_block" title="Permalink to this definition"></a></dt>
<dd><p>Add a new block to the CFG.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.get_block">
<span class="sig-name descname"><span class="pre">get_block</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">name</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Label" title="Lib.Statement.Label"><span class="pre">Label</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.get_block"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.get_block" title="Permalink to this definition"></a></dt>
<dd><p>Return the block with label <cite>name</cite>.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.get_blocks">
<span class="sig-name descname"><span class="pre">get_blocks</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.get_blocks"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.get_blocks" title="Permalink to this definition"></a></dt>
<dd><p>Return all the blocks.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.get_entries">
<span class="sig-name descname"><span class="pre">get_entries</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.get_entries"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.get_entries" title="Permalink to this definition"></a></dt>
<dd><p>Return all the blocks with no predecessors.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.add_edge">
<span class="sig-name descname"><span class="pre">add_edge</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">src</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">dest</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.add_edge"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.add_edge" title="Permalink to this definition"></a></dt>
<dd><p>Add the edge src -&gt; dest in the control flow graph.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.remove_edge">
<span class="sig-name descname"><span class="pre">remove_edge</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">src</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">dest</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.remove_edge"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.remove_edge" title="Permalink to this definition"></a></dt>
<dd><p>Remove the edge src -&gt; dest in the control flow graph.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.out_blocks">
<span class="sig-name descname"><span class="pre">out_blocks</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">block</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.out_blocks"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.out_blocks" title="Permalink to this definition"></a></dt>
<dd><p>Return the list of blocks in the CFG targeted by
the Terminator of Block block.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.gather_defs">
<span class="sig-name descname"><span class="pre">gather_defs</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><span class="pre">Any</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Set</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.gather_defs"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.gather_defs" title="Permalink to this definition"></a></dt>
<dd><p>Return a dictionary associating variables to all the blocks
containing one of their definitions.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.iter_statements">
<span class="sig-name descname"><span class="pre">iter_statements</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">f</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.iter_statements"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.iter_statements" title="Permalink to this definition"></a></dt>
<dd><p>Apply f to all instructions in all the blocks.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.linearize_naive">
<span class="sig-name descname"><span class="pre">linearize_naive</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">Iterator</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.Statement.html#Lib.Statement.Statement" title="Lib.Statement.Statement"><span class="pre">Statement</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.linearize_naive"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.linearize_naive" title="Permalink to this definition"></a></dt>
<dd><p>Linearize the given control flow graph as a list of instructions.
Naive procedure that adds jumps everywhere.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.print_code">
<span class="sig-name descname"><span class="pre">print_code</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">output</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">linearize=&lt;function</span> <span class="pre">CFG.&lt;lambda&gt;&gt;</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">comment=None</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.print_code"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.print_code" title="Permalink to this definition"></a></dt>
<dd><p>Print the linearization of the CFG.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="Lib.CFG.CFG.print_dot">
<span class="sig-name descname"><span class="pre">print_dot</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">filename</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">DF</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">view</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/CFG.html#CFG.print_dot"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.CFG.CFG.print_dot" title="Permalink to this definition"></a></dt>
<dd><p>Print the CFG as a graph.</p>
</dd></dl>
</dd></dl>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="Lib.Allocator.html" class="btn btn-neutral float-left" title="Lib.Allocator module" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="Lib.Terminator.html" class="btn btn-neutral float-right" title="Lib.Terminator module" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, compil-lyon.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>

View File

@ -1,161 +0,0 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lib.Dominators module &mdash; MiniC documentation</title>
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Lib.PhiNode module" href="Lib.PhiNode.html" />
<link rel="prev" title="Lib.Terminator module" href="Lib.Terminator.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../index.html" class="icon icon-home">
MiniC
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Lib.Errors.html">Base library - Errors</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Statement.html">Base library - Statement</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.RiscV.html">Base library - RISC-V instructions</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Operands.html">Base library - Operands</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.FunctionData.html">Base library - Function data</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Graphes.html">Base library - Graphs</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.LinearCode.html">Linear intermediate representation</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Allocator.html">Temporary allocation</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.CFG.html">Control Flow Graph - CFG and Basic blocks</a></li>
<li class="toctree-l1"><a class="reference internal" href="Lib.Terminator.html">Control Flow Graph - Terminators</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">SSA form - Dominance frontier</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#Lib.Dominators.computeDom"><code class="docutils literal notranslate"><span class="pre">computeDom()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="#Lib.Dominators.printDT"><code class="docutils literal notranslate"><span class="pre">printDT()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="#Lib.Dominators.computeDT"><code class="docutils literal notranslate"><span class="pre">computeDT()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="#Lib.Dominators.computeDF"><code class="docutils literal notranslate"><span class="pre">computeDF()</span></code></a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Lib.PhiNode.html">SSA form - Phi Nodes</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">MiniC</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item active">Lib.Dominators module</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/api/Lib.Dominators.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="module-Lib.Dominators">
<span id="lib-dominators-module"></span><h1>Lib.Dominators module<a class="headerlink" href="#module-Lib.Dominators" title="Permalink to this heading"></a></h1>
<p>Utility functions to work with dominators in a <a class="reference internal" href="Lib.CFG.html#Lib.CFG.CFG" title="Lib.CFG.CFG"><code class="xref py py-class docutils literal notranslate"><span class="pre">CFG</span></code></a>.</p>
<p>Do not hesitate to look at the source of the functions
to get a better understanding of the algorithms.</p>
<dl class="py function">
<dt class="sig sig-object py" id="Lib.Dominators.computeDom">
<span class="sig-prename descclassname"><span class="pre">Lib.Dominators.</span></span><span class="sig-name descname"><span class="pre">computeDom</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cfg</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.CFG.html#Lib.CFG.CFG" title="Lib.CFG.CFG"><span class="pre">CFG</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Set</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/Dominators.html#computeDom"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.Dominators.computeDom" title="Permalink to this definition"></a></dt>
<dd><p><cite>computeDom(cfg)</cite> computes the table associating blocks to their
dominators in <cite>cfg</cite>.
It works by solving the equation system.</p>
<p>This is an helper function called during SSA entry.</p>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="Lib.Dominators.printDT">
<span class="sig-prename descclassname"><span class="pre">Lib.Dominators.</span></span><span class="sig-name descname"><span class="pre">printDT</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">filename</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">str</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">graph</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Set</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="reference internal" href="../_modules/Lib/Dominators.html#printDT"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.Dominators.printDT" title="Permalink to this definition"></a></dt>
<dd><p>Display a graphical rendering of the given domination tree.</p>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="Lib.Dominators.computeDT">
<span class="sig-prename descclassname"><span class="pre">Lib.Dominators.</span></span><span class="sig-name descname"><span class="pre">computeDT</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cfg</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.CFG.html#Lib.CFG.CFG" title="Lib.CFG.CFG"><span class="pre">CFG</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">dominators</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Set</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dom_graphs</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">bool</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">basename</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">str</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Set</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/Dominators.html#computeDT"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.Dominators.computeDT" title="Permalink to this definition"></a></dt>
<dd><p><cite>computeDT(cfg, dominators)</cite> computes the domination tree of <cite>cfg</cite>
using the previously computed <cite>dominators</cite>.
It returns <cite>DT</cite>, a dictionary which associates a block with its children
in the dominator tree.</p>
<p>This is an helper function called during SSA entry.</p>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="Lib.Dominators.computeDF">
<span class="sig-prename descclassname"><span class="pre">Lib.Dominators.</span></span><span class="sig-name descname"><span class="pre">computeDF</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cfg</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="Lib.CFG.html#Lib.CFG.CFG" title="Lib.CFG.CFG"><span class="pre">CFG</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">dominators</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Set</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></em>, <em class="sig-param"><span class="n"><span class="pre">DT</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Set</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dom_graphs</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">bool</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">basename</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">str</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Set</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="Lib.CFG.html#Lib.CFG.Block" title="Lib.CFG.Block"><span class="pre">Block</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="../_modules/Lib/Dominators.html#computeDF"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#Lib.Dominators.computeDF" title="Permalink to this definition"></a></dt>
<dd><p><cite>computeDF(…)</cite> computes the dominance frontier of a CFG.
It returns <cite>DF</cite> which associates a block to its frontier.</p>
<p>This is an helper function called during SSA entry.</p>
</dd></dl>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="Lib.Terminator.html" class="btn btn-neutral float-left" title="Lib.Terminator module" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="Lib.PhiNode.html" class="btn btn-neutral float-right" title="Lib.PhiNode module" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, compil-lyon.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More