Compare commits
49 Commits
Author | SHA1 | Date | |
---|---|---|---|
293c52d967 | |||
|
f488adc39b | ||
|
316d71c5cc | ||
|
ac51b2cc1d | ||
|
206c6272df | ||
|
f164364595 | ||
|
ec0fe5ddb4 | ||
|
b0f49c056d | ||
|
587924218a | ||
df9ebe0a3b | |||
|
05a926c8a8 | ||
|
b85cd1c394 | ||
|
81c1d6ad7a | ||
|
b3c13261dd | ||
a30f035d06 | |||
d91c1df685 | |||
d668ab98aa | |||
|
a5ed9e903d | ||
9e371fb015 | |||
|
41d4685997 | ||
|
64c185a9c6 | ||
13c0c3d09e | |||
|
b25448f96e | ||
38731699fc | |||
abcc75cdd4 | |||
|
0b4c228fec | ||
874b1e9b39 | |||
|
75d751abb0 | ||
73f3dbeeb0 | |||
|
59197cf20a | ||
|
1bf5661331 | ||
|
cc774e8f9a | ||
f6b232f72f | |||
|
d65989d733 | ||
b8af070658 | |||
fcf4e29532 | |||
0651175da6 | |||
7479ee19d8 | |||
|
8a3da3d91e | ||
|
ade74f306e | ||
|
861e84f909 | ||
4c7a2c85a2 | |||
b7601abd73 | |||
|
8231c383d9 | ||
|
d8bae99959 | ||
6372c09fd9 | |||
|
570de9d4f5 | ||
|
2a1596793e | ||
|
bfcce272c9 |
@ -17,8 +17,9 @@ 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 relies for each precedent block in the CFG, identified with its label,
|
The field srcs links each corresponding predecessor in the CFG
|
||||||
the variable temp_i of the φ node.
|
---identified by its label---, to the variable temp_i of the φ
|
||||||
|
node.
|
||||||
"""
|
"""
|
||||||
var: DataLocation
|
var: DataLocation
|
||||||
srcs: Dict[Label, Operand]
|
srcs: Dict[Label, Operand]
|
||||||
|
@ -1,21 +1,30 @@
|
|||||||
# MiniC Compiler
|
# MiniC Compiler
|
||||||
LAB5a (Control Flow Graph in SSA Form) & LAB5b (Smart Register Allocation), CAP 2022-23
|
LAB5a (Control Flow Graph in SSA Form) & LAB5b (Smart Register Allocation), CAP 2023-24
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
YOUR NAME HERE
|
Augustin LUCAS
|
||||||
|
|
||||||
# Contents
|
# Contents
|
||||||
|
|
||||||
TODO:
|
Extension implemented : Optimizing swap
|
||||||
- Explain any design choices you may have made.
|
- Cycles of size 1 : skip
|
||||||
- Do not forget to remove all debug traces from your code!
|
- Cycles of size 2 : use 3 XOR operations to swap the registers values without any temporary register use
|
||||||
- Did you implement an extension?
|
|
||||||
|
|
||||||
# Test design
|
# Test design
|
||||||
|
|
||||||
TODO: give the main objectives of your tests.
|
No tests were added since some of the `students`' tests from lab4 still failed to execute properly.
|
||||||
|
|
||||||
# Known bugs
|
# Known bugs
|
||||||
|
|
||||||
TODO: bugs you could not fix (if any).
|
Failing tests:
|
||||||
|
- `./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).
|
@ -1,5 +1,5 @@
|
|||||||
# MiniC Compiler
|
# MiniC Compiler
|
||||||
LAB5 (smart code generation), MIF08 / CAP 2022-23
|
LAB5 (smart code generation), MIF08 / CAP 2023-24
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
|
@ -1,26 +1,21 @@
|
|||||||
# MiniC Compiler
|
# MiniC Compiler
|
||||||
LAB4 (simple code generation), MIF08 / CAP 2022-23
|
LAB4 (simple code generation), MIF08 / CAP 2023-24
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
YOUR NAME HERE
|
Augustin LUCAS
|
||||||
|
|
||||||
# Contents
|
# Contents
|
||||||
|
|
||||||
TODO for STUDENTS : Say a bit about the code infrastructure ...
|
|
||||||
|
|
||||||
# Test design
|
# Test design
|
||||||
|
|
||||||
TODO: explain your tests
|
|
||||||
|
|
||||||
# Design choices
|
# Design choices
|
||||||
|
|
||||||
TODO: explain your choices. How did you implement boolean not? Did you implement an extension?
|
Booleans are implemented as integers behind the scenes, but type-checking before compilation disables any casting mechanism.
|
||||||
|
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
|
||||||
@ -28,30 +23,30 @@ and *tested* with appropriate test cases.
|
|||||||
|
|
||||||
## Code generation
|
## Code generation
|
||||||
|
|
||||||
- [ ] Number Atom
|
- [x] Number Atom
|
||||||
- [ ] Boolean Atom
|
- [x] Boolean Atom
|
||||||
- [ ] Id Atom
|
- [x] Id Atom
|
||||||
- [ ] Additive expression
|
- [x] Additive expression
|
||||||
- [ ] Multiplicative expression
|
- [x] Multiplicative expression
|
||||||
- [ ] UnaryMinus expression
|
- [x] UnaryMinus expression
|
||||||
- [ ] Or expression
|
- [x] Or expression
|
||||||
- [ ] And expression
|
- [x] And expression
|
||||||
- [ ] Equality expression
|
- [x] Equality expression
|
||||||
- [ ] Relational expression (! many cases -> many tests)
|
- [x] Relational expression (! many cases -> many tests)
|
||||||
- [ ] Not expression
|
- [x] Not expression
|
||||||
|
|
||||||
## Statements
|
## Statements
|
||||||
|
|
||||||
- [ ] Prog, assignements
|
- [x] Prog, assignements
|
||||||
- [ ] While
|
- [x] While
|
||||||
- [ ] Cond Block
|
- [x] Cond Block
|
||||||
- [ ] If
|
- [x] If
|
||||||
- [ ] Nested ifs
|
- [x] Nested ifs
|
||||||
- [ ] Nested whiles
|
- [x] Nested whiles
|
||||||
|
|
||||||
## Allocation
|
## Allocation
|
||||||
|
|
||||||
- [ ] Naive allocation
|
- [x] Naive allocation
|
||||||
- [ ] All in memory allocation
|
- [x] All in memory allocation
|
||||||
- [ ] Massive tests of memory allocation
|
- [ ] Massive tests of memory allocation
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# MiniC Compiler
|
# MiniC Compiler
|
||||||
LAB6 (code generation for functions), MIF08 / CAP 2022-23
|
LAB6 (code generation for functions), MIF08 / CAP 2023-24
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# MiniC interpreter and typer
|
# MiniC interpreter and typer
|
||||||
LAB3, MIF08 / CAP / CS444 2022-23
|
LAB3, MIF08 / CAP / CS444 2023-24
|
||||||
|
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
@ -14,11 +14,25 @@ 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.
|
|
||||||
# TODO: iterate over old_args, check which argument
|
for arg in old_instr.defined():
|
||||||
# TODO: is a temporary (e.g. isinstance(..., Temporary)),
|
if isinstance(arg, Temporary):
|
||||||
# TODO: and if so, generate ld/sd accordingly. Replace the
|
after.append(RiscV.sd(
|
||||||
# TODO: temporary with S[1], S[2] or S[3] physical registers.
|
S[3], arg.get_alloced_loc()
|
||||||
|
))
|
||||||
|
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
|
||||||
|
|
||||||
|
@ -20,7 +20,13 @@ 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
|
||||||
@ -64,9 +70,15 @@ 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
|
||||||
raise NotImplementedError() # TODO
|
if isinstance(inner_statements[0], Label):
|
||||||
|
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
|
||||||
raise NotImplementedError() # TODO
|
if len(inner_statements) > 0 and (isinstance(inner_statements[-1], ConditionalJump) or isinstance(inner_statements[-1], AbsoluteJump)):
|
||||||
|
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:
|
||||||
|
@ -20,7 +20,6 @@ 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):
|
||||||
@ -34,6 +33,7 @@ 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()))
|
||||||
|
@ -74,8 +74,13 @@ class MiniCCodeGen3AVisitor(MiniCVisitor):
|
|||||||
raise MiniCUnsupportedError("float literal")
|
raise MiniCUnsupportedError("float literal")
|
||||||
|
|
||||||
def visitBooleanAtom(self, ctx) -> Operands.Temporary:
|
def visitBooleanAtom(self, ctx) -> Operands.Temporary:
|
||||||
# true is 1 false is 0
|
dest = self._current_function.fdata.fresh_tmp()
|
||||||
raise NotImplementedError() # TODO
|
self._current_function.add_instruction(
|
||||||
|
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:
|
||||||
@ -99,13 +104,37 @@ 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))
|
||||||
raise NotImplementedError() # TODO
|
tmp = self._current_function.fdata.fresh_tmp()
|
||||||
|
|
||||||
|
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:
|
||||||
raise NotImplementedError() # TODO
|
tmp = self._current_function.fdata.fresh_tmp()
|
||||||
|
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:
|
||||||
raise NotImplementedError() # TODO
|
tmp = self._current_function.fdata.fresh_tmp()
|
||||||
|
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)
|
||||||
@ -117,18 +146,83 @@ 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()
|
||||||
raise NotImplementedError() # TODO
|
t1 = self.visit(ctx.expr(0))
|
||||||
|
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:
|
||||||
raise NotImplementedError() # TODO
|
dest = self._current_function.fdata.fresh_tmp()
|
||||||
|
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:
|
||||||
raise NotImplementedError("unaryminusexpr") # TODO
|
dest = self._current_function.fdata.fresh_tmp()
|
||||||
|
|
||||||
|
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)
|
||||||
@ -160,8 +254,25 @@ 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:
|
||||||
@ -170,7 +281,31 @@ 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:
|
||||||
@ -194,3 +329,79 @@ 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)
|
||||||
|
10
MiniC/TP04/tests/students/base/test_add_boolean.c
Normal file
10
MiniC/TP04/tests/students/base/test_add_boolean.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#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
|
16
MiniC/TP04/tests/students/base/test_comp_bool.c
Normal file
16
MiniC/TP04/tests/students/base/test_comp_bool.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#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
|
14
MiniC/TP04/tests/students/base/test_div_0.c
Normal file
14
MiniC/TP04/tests/students/base/test_div_0.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#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
|
15
MiniC/TP04/tests/students/base/test_else.c
Normal file
15
MiniC/TP04/tests/students/base/test_else.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "printlib.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int x, y;
|
||||||
|
if (x != 0) {
|
||||||
|
y = 12;
|
||||||
|
} else {
|
||||||
|
y = -3;
|
||||||
|
}
|
||||||
|
println_int(y);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECTED
|
||||||
|
// -3
|
27
MiniC/TP04/tests/students/base/test_fibonacci.c
Normal file
27
MiniC/TP04/tests/students/base/test_fibonacci.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#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
|
16
MiniC/TP04/tests/students/base/test_if_nonbool.c
Normal file
16
MiniC/TP04/tests/students/base/test_if_nonbool.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#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
|
15
MiniC/TP04/tests/students/base/test_mem_alloc.c
Normal file
15
MiniC/TP04/tests/students/base/test_mem_alloc.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#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
|
19
MiniC/TP04/tests/students/base/test_mod.c
Normal file
19
MiniC/TP04/tests/students/base/test_mod.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#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
|
12
MiniC/TP04/tests/students/base/test_mul.c
Normal file
12
MiniC/TP04/tests/students/base/test_mul.c
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "printlib.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int x, y;
|
||||||
|
x = 12;
|
||||||
|
y = 5;
|
||||||
|
println_int(x*y);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECTED
|
||||||
|
// 60
|
33
MiniC/TP04/tests/students/base/test_nested_if.c
Normal file
33
MiniC/TP04/tests/students/base/test_nested_if.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#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
|
25
MiniC/TP04/tests/students/base/test_nested_while.c
Normal file
25
MiniC/TP04/tests/students/base/test_nested_while.c
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#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
|
14
MiniC/TP04/tests/students/base/test_not.c
Normal file
14
MiniC/TP04/tests/students/base/test_not.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "printlib.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
bool x, y;
|
||||||
|
x = true;
|
||||||
|
y = false;
|
||||||
|
println_bool(!x);
|
||||||
|
println_bool(!y);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECTED
|
||||||
|
// 0
|
||||||
|
// 1
|
11
MiniC/TP04/tests/students/base/test_not_int.c
Normal file
11
MiniC/TP04/tests/students/base/test_not_int.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#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
|
12
MiniC/TP04/tests/students/base/test_or.c
Normal file
12
MiniC/TP04/tests/students/base/test_or.c
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "printlib.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
bool x, y;
|
||||||
|
x = true;
|
||||||
|
y = false;
|
||||||
|
println_bool(x || y);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECTED
|
||||||
|
// 1
|
14
MiniC/TP04/tests/students/base/test_println_bool.c
Normal file
14
MiniC/TP04/tests/students/base/test_println_bool.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#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
|
14
MiniC/TP04/tests/students/base/test_println_float.c
Normal file
14
MiniC/TP04/tests/students/base/test_println_float.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#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
|
35
MiniC/TP04/tests/students/base/test_relational.c
Normal file
35
MiniC/TP04/tests/students/base/test_relational.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#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
|
13
MiniC/TP04/tests/students/base/test_while.c
Normal file
13
MiniC/TP04/tests/students/base/test_while.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "printlib.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int x;
|
||||||
|
while (x < 12) {
|
||||||
|
x = x+2;
|
||||||
|
}
|
||||||
|
println_int(x);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECTED
|
||||||
|
// 12
|
17
MiniC/TP04/tests/students/base/test_while_nonbool.c
Normal file
17
MiniC/TP04/tests/students/base/test_while_nonbool.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#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
|
32
MiniC/TP04/tests/students/ext-for-fortran/test_for.c
Normal file
32
MiniC/TP04/tests/students/ext-for-fortran/test_for.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#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
|
@ -0,0 +1,18 @@
|
|||||||
|
#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
|
@ -0,0 +1,17 @@
|
|||||||
|
#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
|
17
MiniC/TP04/tests/students/ext-for-fortran/test_invalid_id.c
Normal file
17
MiniC/TP04/tests/students/ext-for-fortran/test_invalid_id.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#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
|
@ -0,0 +1,15 @@
|
|||||||
|
#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
|
17
MiniC/TP04/tests/students/ext-for-fortran/test_invalid_to.c
Normal file
17
MiniC/TP04/tests/students/ext-for-fortran/test_invalid_to.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#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
|
@ -0,0 +1,15 @@
|
|||||||
|
#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
|
@ -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
|
from Lib.Operands import Renamer, Operand
|
||||||
from Lib.Statement import Instruction
|
from Lib.Statement import Instruction, Label
|
||||||
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,8 +25,14 @@ 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:
|
||||||
# TODO add a phi node in block `b` (Lab 5a, Exercise 4)
|
srcs: Dict[Label, Operand] = {
|
||||||
raise NotImplementedError("insertPhis")
|
x.get_label(): var for x in b.get_in()
|
||||||
|
}
|
||||||
|
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:
|
||||||
@ -43,7 +49,8 @@ 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())
|
||||||
# TODO recursive call(s) of rename_block (Lab 5a, Exercise 5)
|
for succ in DT[b]:
|
||||||
|
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:
|
||||||
@ -54,7 +61,8 @@ 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)
|
||||||
# TODO initial call(s) to rename_block (Lab 5a, Exercise 5)
|
for b in cfg.get_entries():
|
||||||
|
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:
|
||||||
@ -66,5 +74,8 @@ 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.
|
||||||
"""
|
"""
|
||||||
# TODO implement this function (Lab 5a, Exercise 2)
|
dom = computeDom(cfg)
|
||||||
raise NotImplementedError("enter_ssa")
|
DT = computeDT(cfg, dom, dom_graphs, basename)
|
||||||
|
DF = computeDF(cfg, dom, DT, dom_graphs, basename)
|
||||||
|
insertPhis(cfg, DF)
|
||||||
|
rename_variables(cfg, DT)
|
@ -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
|
from Lib.Operands import Temporary, DataLocation
|
||||||
from Lib.Statement import AbsoluteJump
|
from Lib.Statement import AbsoluteJump, Label
|
||||||
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
|
from TP05.SequentializeMoves import sequentialize_moves, generate_smart_move
|
||||||
|
|
||||||
|
|
||||||
def generate_moves_from_phis(phis: List[PhiNode], parent: Block) -> List[BlockInstr]:
|
def generate_moves_from_phis(phis: List[PhiNode], parent: Block, is_smart: bool=False) -> 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,10 +21,32 @@ def generate_moves_from_phis(phis: List[PhiNode], parent: Block) -> List[BlockIn
|
|||||||
|
|
||||||
This is an helper function called during SSA exit.
|
This is an helper function called during SSA exit.
|
||||||
"""
|
"""
|
||||||
moves: List[BlockInstr] = []
|
|
||||||
# TODO compute 'moves', a list of 'mv' instructions to insert under parent
|
|
||||||
# (Lab 5a, Exercise 6)
|
# (Lab 5a, Exercise 6)
|
||||||
return moves
|
lbl = parent.get_label()
|
||||||
|
if is_smart:
|
||||||
|
parallel_moves: set[tuple[DataLocation, DataLocation]] = set()
|
||||||
|
moves: List[BlockInstr] = []
|
||||||
|
for phi in phis:
|
||||||
|
if lbl not in phi.get_srcs():
|
||||||
|
continue
|
||||||
|
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:
|
||||||
@ -38,7 +60,22 @@ 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:
|
||||||
moves = generate_moves_from_phis(phis, parent)
|
# Add the block containing 'moves' to 'cfg'
|
||||||
# TODO Add the block containing 'moves' to 'cfg'
|
moves_label = cfg.fdata.fresh_label("merge_phi")
|
||||||
# and update edges and jumps accordingly (Lab 5a, Exercise 6)
|
block_moves = Block(moves_label, generate_moves_from_phis(phis, parent, is_smart=is_smart), AbsoluteJump(b.get_label()))
|
||||||
raise NotImplementedError("exit_ssa")
|
cfg.add_block(block_moves)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
@ -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
|
from Lib.Statement import Statement, regset_to_string, Instru3A
|
||||||
from Lib.CFG import Block, CFG
|
from Lib.CFG import Block, CFG
|
||||||
from Lib.PhiNode import PhiNode
|
from Lib.PhiNode import PhiNode
|
||||||
|
|
||||||
@ -35,16 +35,41 @@ 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."""
|
||||||
raise NotImplementedError("LivenessSSA") # TODO (Lab 5b, Exercise 1)
|
instr = block.get_all_statements()[pos]
|
||||||
|
|
||||||
|
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."""
|
||||||
raise NotImplementedError("LivenessSSA") # TODO (Lab 5b, Exercise 1)
|
if var not in self._seen[block]:
|
||||||
|
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]]]:
|
||||||
"""
|
"""
|
||||||
@ -67,7 +92,9 @@ 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."""
|
||||||
raise NotImplementedError("LivenessSSA") # TODO (Lab 5b, Exercise 1)
|
for block in self._cfg.get_blocks():
|
||||||
|
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!"""
|
||||||
|
@ -18,11 +18,33 @@ 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] = []
|
||||||
# TODO Compute the moves (Lab 5b, Exercise 4)
|
tmp: Register = S[1]
|
||||||
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]:
|
||||||
"""
|
"""
|
||||||
@ -39,22 +61,39 @@ 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]] = []
|
moves: List[Tuple[DataLocation, DataLocation] | BlockInstr] = []
|
||||||
# First iteratively remove all the vetices without successors
|
# First iteratively remove all the vertices 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:
|
||||||
# TODO Remove the leaves iteratively (Lab 5b, Exercise 4)
|
var = vars_without_successor.pop()
|
||||||
raise NotImplementedError("sequentialize_moves: leaves")
|
for src in move_graph.pred(var):
|
||||||
|
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:
|
||||||
# TODO Handle each cycle (Lab 5b, Exercise 4)
|
if len(cycle) == 1:
|
||||||
raise NotImplementedError("sequentialize_moves: cycles")
|
continue
|
||||||
|
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 dest, src in moves:
|
for val in moves:
|
||||||
instrs = generate_smart_move(dest, src)
|
if isinstance(val, BlockInstr):
|
||||||
|
moves_instr.append(val)
|
||||||
|
continue
|
||||||
|
instrs = generate_smart_move(*val)
|
||||||
moves_instr.extend(instrs)
|
moves_instr.extend(instrs)
|
||||||
return moves_instr
|
return moves_instr
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
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
|
from Lib.Statement import Instruction, Instru3A
|
||||||
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):
|
||||||
@ -28,9 +29,27 @@ 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
|
|
||||||
# TODO (lab5): replace from the Naive and AllInMem Allocators do (Lab 4).
|
for arg in old_instr.defined():
|
||||||
raise NotImplementedError("Smart Replace (lab5)") # TODO
|
match arg:
|
||||||
|
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
|
||||||
@ -70,7 +89,12 @@ 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.
|
||||||
raise NotImplementedError("build_interference_graph (lab5)") # TODO
|
for (block, statement), vars in self._liveness._liveout.items():
|
||||||
|
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:
|
||||||
"""
|
"""
|
||||||
@ -79,6 +103,7 @@ 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")
|
||||||
@ -92,7 +117,15 @@ 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.
|
||||||
raise NotImplementedError("Allocation based on graph coloring (lab5)") # TODO
|
color_dict: Dict[int, DataLocation] = dict()
|
||||||
|
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)
|
||||||
|
@ -85,6 +85,7 @@ 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
|
||||||
|
83
PLANNING.md
83
PLANNING.md
@ -31,7 +31,7 @@ _Academic first semester 2024-2025_
|
|||||||
|
|
||||||
# Week 3:
|
# Week 3:
|
||||||
|
|
||||||
- :hammer: Lab 2: Thursday 23/09/2023, 13h30-15h30. Room E001 103 & -138 (Grenat) (Samuel Humeau & Emma Nardino)
|
- :hammer: Lab 2: Thursday 23/09/2024, 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,3 +64,84 @@ _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)
|
||||||
|
BIN
TD/td_cap.pdf
Normal file
BIN
TD/td_cap.pdf
Normal file
Binary file not shown.
BIN
TD/td_cap_correction_incomplete.pdf
Normal file
BIN
TD/td_cap_correction_incomplete.pdf
Normal file
Binary file not shown.
BIN
TP04/tp4b.pdf
Normal file
BIN
TP04/tp4b.pdf
Normal file
Binary file not shown.
BIN
TP05/tp5a.pdf
Normal file
BIN
TP05/tp5a.pdf
Normal file
Binary file not shown.
BIN
TP05/tp5b.pdf
Normal file
BIN
TP05/tp5b.pdf
Normal file
Binary file not shown.
BIN
TP05/tp5c.pdf
Normal file
BIN
TP05/tp5c.pdf
Normal file
Binary file not shown.
BIN
TP06/tp6a.pdf
Normal file
BIN
TP06/tp6a.pdf
Normal file
Binary file not shown.
BIN
TP06/tp6b.pdf
Normal file
BIN
TP06/tp6b.pdf
Normal file
Binary file not shown.
15
TPfutures/MiniC-futures/.gitignore
vendored
Normal file
15
TPfutures/MiniC-futures/.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/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
|
14
TPfutures/MiniC-futures/Errors.py
Normal file
14
TPfutures/MiniC-futures/Errors.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
class MiniCRuntimeError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MiniCInternalError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MiniCUnsupportedError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MiniCTypeError(Exception):
|
||||||
|
pass
|
56
TPfutures/MiniC-futures/Makefile
Normal file
56
TPfutures/MiniC-futures/Makefile
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
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
|
164
TPfutures/MiniC-futures/MiniC.g4
Normal file
164
TPfutures/MiniC-futures/MiniC.g4
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
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)
|
||||||
|
;
|
||||||
|
|
112
TPfutures/MiniC-futures/MiniCC.py
Normal file
112
TPfutures/MiniC-futures/MiniCC.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#! /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)
|
27
TPfutures/MiniC-futures/MiniCPPListener.py
Normal file
27
TPfutures/MiniC-futures/MiniCPPListener.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
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, '&')
|
17
TPfutures/MiniC-futures/MiniCTypingVisitor.py
Normal file
17
TPfutures/MiniC-futures/MiniCTypingVisitor.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# 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
|
25
TPfutures/MiniC-futures/README.md
Normal file
25
TPfutures/MiniC-futures/README.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# 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.
|
||||||
|
|
12
TPfutures/MiniC-futures/include/compat.h
Normal file
12
TPfutures/MiniC-futures/include/compat.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#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);
|
34
TPfutures/MiniC-futures/include/futurelib.h
Normal file
34
TPfutures/MiniC-futures/include/futurelib.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#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
|
77
TPfutures/MiniC-futures/lib/futurelib.c
Normal file
77
TPfutures/MiniC-futures/lib/futurelib.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#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)
|
||||||
|
}
|
193
TPfutures/MiniC-futures/test_expect_pragma.py
Normal file
193
TPfutures/MiniC-futures/test_expect_pragma.py
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
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)
|
105
TPfutures/MiniC-futures/test_futures.py
Executable file
105
TPfutures/MiniC-futures/test_futures.py
Executable file
@ -0,0 +1,105 @@
|
|||||||
|
#! /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)
|
38
TPfutures/MiniC-futures/tests/provided/bad_type_fut1.c
Normal file
38
TPfutures/MiniC-futures/tests/provided/bad_type_fut1.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#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
|
||||||
|
|
20
TPfutures/MiniC-futures/tests/provided/test_fut0.c
Normal file
20
TPfutures/MiniC-futures/tests/provided/test_fut0.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#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
|
22
TPfutures/MiniC-futures/tests/provided/test_fut1.c
Normal file
22
TPfutures/MiniC-futures/tests/provided/test_fut1.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#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
|
41
TPfutures/MiniC-futures/tests/provided/test_fut2.c
Normal file
41
TPfutures/MiniC-futures/tests/provided/test_fut2.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#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
|
56
TPfutures/MiniC-futures/tests/provided/test_fut4.c
Normal file
56
TPfutures/MiniC-futures/tests/provided/test_fut4.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#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
|
BIN
TPfutures/tpfutures.pdf
Normal file
BIN
TPfutures/tpfutures.pdf
Normal file
Binary file not shown.
BIN
course/cap_cours06b_ssa_optim.pdf
Normal file
BIN
course/cap_cours06b_ssa_optim.pdf
Normal file
Binary file not shown.
BIN
course/cap_cours07_regalloc.pdf
Normal file
BIN
course/cap_cours07_regalloc.pdf
Normal file
Binary file not shown.
BIN
course/cap_cours08_func_codegen.pdf
Normal file
BIN
course/cap_cours08_func_codegen.pdf
Normal file
Binary file not shown.
BIN
course/cap_cours09_func_semantics.pdf
Normal file
BIN
course/cap_cours09_func_semantics.pdf
Normal file
Binary file not shown.
BIN
course/cap_cours10_parallelism.pdf
Normal file
BIN
course/cap_cours10_parallelism.pdf
Normal file
Binary file not shown.
BIN
course/cap_cours11_verified.pdf
Normal file
BIN
course/cap_cours11_verified.pdf
Normal file
Binary file not shown.
BIN
course/cap_cours_bonuscomp.pdf
Normal file
BIN
course/cap_cours_bonuscomp.pdf
Normal file
Binary file not shown.
BIN
dm_cap.pdf
Normal file
BIN
dm_cap.pdf
Normal file
Binary file not shown.
@ -45,8 +45,13 @@
|
|||||||
<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>
|
||||||
|
406
docs/html/_modules/Lib/CFG.html
Normal file
406
docs/html/_modules/Lib/CFG.html
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
<!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 — 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">"""</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">"""</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">"""</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 <Lib.Statement.Label>` 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 <Lib.Terminator.Terminator>`</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"> """</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">'Block'</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">'</span><span class="se">\n</span><span class="s1">'</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">'</span><span class="si">{}</span><span class="s1">:</span><span class="se">\n\n</span><span class="si">{}</span><span class="s1">'</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">-></span> <span class="nb">str</span><span class="p">:</span> <span class="c1"># pragma: no cover</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Outputs all statements of the block as a string."""</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">'</span><span class="se">\\</span><span class="s1">l '</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">'</span><span class="si">{}</span><span class="s1">:</span><span class="si">{}{}</span><span class="se">\\</span><span class="s1">l'</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">-></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">"""Return the statements in the body of the block (no phi-node nor the terminator)."""</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">-></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">"""</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"> """</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">-></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">"""</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"> """</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">-></span> <span class="n">Label</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Return the label of the block."""</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">-></span> <span class="n">List</span><span class="p">[</span><span class="s1">'Block'</span><span class="p">]:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Return the list of blocks with an edge to the considered block."""</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">-></span> <span class="n">Terminator</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Return the terminator of the block."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Set the terminator of the block."""</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">-></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">"""Return the list of all φ instructions of the block."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Add a φ instruction to the block."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Replace the φ instructions in the block by the given list `phis`."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Remove all φ instructions in the block."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""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"> """</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">>=</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">"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">"</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Add an instruction to the body of the block."""</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">"""</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 <get_start>`,</span>
|
||||||
|
<span class="sd"> and an :py:meth:`exit label <get_end>`.</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"> """</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">"end"</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Add a block for division by 0."""</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">"_msg"</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">"la"</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">"call"</span><span class="p">,</span> <span class="n">Function</span><span class="p">(</span><span class="s2">"println_string"</span><span class="p">)),</span>
|
||||||
|
<span class="n">Instru3A</span><span class="p">(</span><span class="s2">"li"</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">"call"</span><span class="p">,</span> <span class="n">Function</span><span class="p">(</span><span class="s2">"exit"</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">-></span> <span class="n">Label</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Return the entry label of the CFG."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Set the entry label of the CFG."""</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">-></span> <span class="n">Label</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Return the exit label of the CFG."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Add a new block to the CFG."""</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">-></span> <span class="n">Block</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Return the block with label `name`."""</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">-></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">"""Return all the blocks."""</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">-></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">"""Return all the blocks with no predecessors."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Add the edge src -> dest in the control flow graph."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Remove the edge src -> dest in the control flow graph."""</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">-></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">"""</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"> """</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">-></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">"""</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"> """</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Apply f to all instructions in all the blocks."""</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">-></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">"""</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"> """</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Print the linearization of the CFG."""</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">-></span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># pragma: no cover</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Print the CFG as a graph."""</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">"</span><span class="si">{}</span><span class="s2">"</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">"</span><span class="se">\n\n</span><span class="s2">Dominance frontier:</span><span class="se">\n</span><span class="s2">"</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">'rectangle'</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>© 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>
|
239
docs/html/_modules/Lib/Dominators.html
Normal file
239
docs/html/_modules/Lib/Dominators.html
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
<!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 — 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">"""</span>
|
||||||
|
<span class="sd">Utility functions to work with dominators in a :py:class:`CFG <Lib.CFG.CFG>`.</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">"""</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">-></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">"""</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"> """</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">-></span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># pragma: no cover</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Display a graphical rendering of the given domination tree."""</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">-></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">"""</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"> """</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">"</span><span class="si">{}</span><span class="s2">.</span><span class="si">{}</span><span class="s2">.ssa.DT.dot"</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">"SSA - domination tree graph:"</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""</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"> """</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">-></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">"""</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"> """</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">"</span><span class="si">{}</span><span class="s2">.</span><span class="si">{}</span><span class="s2">.ssa.DF.dot"</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">"SSA - dominance frontier graph:"</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>© 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>
|
@ -45,8 +45,13 @@
|
|||||||
<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>
|
||||||
|
@ -45,8 +45,13 @@
|
|||||||
<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>
|
||||||
|
423
docs/html/_modules/Lib/Graphes.html
Normal file
423
docs/html/_modules/Lib/Graphes.html
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
<!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 — 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">""" Python Classes for Oriented and Non Oriented Graphs</span>
|
||||||
|
<span class="sd">"""</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">"""Exception raised for self loops.</span>
|
||||||
|
<span class="sd"> """</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">"""</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"> """</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">"""</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"> """</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">-></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">"""Return the vertices of a graph."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""</span>
|
||||||
|
<span class="sd"> If the vertex "vertex" is not in</span>
|
||||||
|
<span class="sd"> self.graph_dict, a key "vertex" 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"> """</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">-></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">"""Return the edges of the graph."""</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">"vertices: "</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">" "</span>
|
||||||
|
<span class="n">res</span> <span class="o">+=</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">edges: "</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">" "</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">-></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">"""</span>
|
||||||
|
<span class="sd"> Compute a depth first search of the graph,</span>
|
||||||
|
<span class="sd"> from the vertex root.</span>
|
||||||
|
<span class="sd"> """</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">></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">-></span> <span class="nb">bool</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""True if there is a path from v1 to v2."""</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">-></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">"""</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"> """</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">-></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">"""</span>
|
||||||
|
<span class="sd"> Compute a breadth first search of the graph,</span>
|
||||||
|
<span class="sd"> from the vertex root.</span>
|
||||||
|
<span class="sd"> """</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">></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">"""Class for non oriented graphs."""</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">-></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">"""</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"> """</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""</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"> """</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">"Cannot add a self loop on vertex </span><span class="si">{}</span><span class="s2"> in an unoriented graph."</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Print the graph."""</span>
|
||||||
|
<span class="n">color_names</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'red'</span><span class="p">,</span> <span class="s1">'blue'</span><span class="p">,</span> <span class="s1">'green'</span><span class="p">,</span> <span class="s1">'yellow'</span><span class="p">,</span> <span class="s1">'cyan'</span><span class="p">,</span> <span class="s1">'magenta'</span><span class="p">]</span> <span class="o">+</span> \
|
||||||
|
<span class="p">[</span><span class="sa">f</span><span class="s2">"grey</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">"</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">'ellipse'</span><span class="p">,</span> <span class="s1">'box'</span><span class="p">,</span> <span class="s1">'diamond'</span><span class="p">,</span> <span class="s1">'trapezium'</span><span class="p">,</span> <span class="s1">'egg'</span><span class="p">,</span>
|
||||||
|
<span class="s1">'parallelogram'</span><span class="p">,</span> <span class="s1">'house'</span><span class="p">,</span> <span class="s1">'triangle'</span><span class="p">,</span> <span class="s1">'pentagon'</span><span class="p">,</span> <span class="s1">'hexagon'</span><span class="p">,</span>
|
||||||
|
<span class="s1">'septagon'</span><span class="p">,</span> <span class="s1">'octagon'</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">'Conflict Graph'</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">"red"</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">"grey"</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"><</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">"black"</span> <span class="c1"># Too many colors anyway, it won'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">"none"</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Delete a vertex and all the adjacent edges."""</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">"""Delete an edge."""</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">-></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">"""</span>
|
||||||
|
<span class="sd"> Color the graph with an unlimited number of colors.</span>
|
||||||
|
<span class="sd"> Return a dict vertex -> color, where color is an integer (0, 1, ...).</span>
|
||||||
|
<span class="sd"> """</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">-></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">"""</span>
|
||||||
|
<span class="sd"> Color with <= K colors (if K is unspecified, use unlimited colors).</span>
|
||||||
|
|
||||||
|
<span class="sd"> Return 3 values:</span>
|
||||||
|
|
||||||
|
<span class="sd"> - a dict vertex -> 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"> """</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">"""Class for directed graphs."""</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">-></span> <span class="n">Set</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Return all predecessors of the vertex `v` in the graph."""</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">-></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">"""Return all neighbourhoods in the graph."""</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">-></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">""" A static method generating the set of edges"""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""</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"> """</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Print the graph."""</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">'Conflict Graph'</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">"grey"</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">"none"</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Delete a vertex and all the adjacent edges."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Delete an edge."""</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>© 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>
|
@ -45,8 +45,13 @@
|
|||||||
<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>
|
||||||
|
@ -45,8 +45,13 @@
|
|||||||
<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>
|
||||||
|
174
docs/html/_modules/Lib/PhiNode.html
Normal file
174
docs/html/_modules/Lib/PhiNode.html
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
<!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 — 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">"""</span>
|
||||||
|
<span class="sd">Classes for φ nodes in a RiscV CFG :py:class:`CFG <Lib.CFG.CFG>` 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 <Lib.CFG.Block>` b.</span>
|
||||||
|
<span class="sd">"""</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">"""</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"> """</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">-></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">"""Return the variable defined by the φ node."""</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">-></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">"""</span>
|
||||||
|
<span class="sd"> Return the dictionnary associating for each previous block the corresponding variable.</span>
|
||||||
|
<span class="sd"> """</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">-></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">"""Return the variables used by the statement."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Rename the variable defined by the φ node with a fresh name."""</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">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""Rename the variable associated to the block identified by `label`."""</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">"</span><span class="si">{}</span><span class="s2"> = φ(</span><span class="si">{}</span><span class="s2">)"</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">' # '</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>© 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>
|
@ -45,8 +45,13 @@
|
|||||||
<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>
|
||||||
|
@ -45,8 +45,13 @@
|
|||||||
<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>
|
||||||
|
264
docs/html/_modules/Lib/Terminator.html
Normal file
264
docs/html/_modules/Lib/Terminator.html
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
<!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 — 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">"""</span>
|
||||||
|
<span class="sd">MIF08, CAP, CFG library - Terminators.</span>
|
||||||
|
|
||||||
|
<span class="sd">Each :py:class:`block <Lib.CFG.Block>` of a :py:class:`CFG <Lib.CFG.CFG>`</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 <Lib.Statement.ConditionalJump>`</span>
|
||||||
|
<span class="sd"> that was used in :py:class:`LinearCode <Lib.LinearCode.LinearCode>`,</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">"""</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">"""A terminator that marks the end of the function."""</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">"return"</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">"return"</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">-></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">"""Return the labels targetted by the Return terminator."""</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">-></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">"substitute: No possible substitution on instruction </span><span class="si">{}</span><span class="s2">"</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">"substitute: No possible substitution on instruction </span><span class="si">{}</span><span class="s2">"</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">-></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">"""A terminating statement with a condition."""</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">-></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">-></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">"""Return the labels targetted by the Branching terminator."""</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">"substitute: Operand </span><span class="si">{}</span><span class="s2"> is not present in instruction </span><span class="si">{}</span><span class="s2">"</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">"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">"</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">"""Type alias for terminators"""</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">-></span> <span class="n">Terminator</span><span class="p">:</span>
|
||||||
|
<span class="w"> </span><span class="sd">"""</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"> """</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">"jump2terminator: Missing secondary label for instruction </span><span class="si">{}</span><span class="s2">"</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>© 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>
|
@ -45,8 +45,13 @@
|
|||||||
<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>
|
||||||
@ -74,12 +79,17 @@
|
|||||||
|
|
||||||
<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>
|
||||||
|
7
docs/html/_sources/api/Lib.CFG.rst.txt
Normal file
7
docs/html/_sources/api/Lib.CFG.rst.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Lib.CFG module
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. automodule:: Lib.CFG
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
7
docs/html/_sources/api/Lib.Dominators.rst.txt
Normal file
7
docs/html/_sources/api/Lib.Dominators.rst.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Lib.Dominators module
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. automodule:: Lib.Dominators
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
7
docs/html/_sources/api/Lib.Graphes.rst.txt
Normal file
7
docs/html/_sources/api/Lib.Graphes.rst.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Lib.Graphes module
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. automodule:: Lib.Graphes
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
7
docs/html/_sources/api/Lib.PhiNode.rst.txt
Normal file
7
docs/html/_sources/api/Lib.PhiNode.rst.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Lib.PhiNode module
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. automodule:: Lib.PhiNode
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
7
docs/html/_sources/api/Lib.Terminator.rst.txt
Normal file
7
docs/html/_sources/api/Lib.Terminator.rst.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Lib.Terminator module
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. automodule:: Lib.Terminator
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
@ -8,12 +8,17 @@ 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
|
||||||
---------------
|
---------------
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
<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>
|
||||||
|
|
||||||
@ -47,6 +48,7 @@
|
|||||||
<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>
|
||||||
@ -62,6 +64,10 @@
|
|||||||
</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>
|
||||||
@ -159,6 +165,7 @@ 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/>
|
||||||
|
375
docs/html/api/Lib.CFG.html
Normal file
375
docs/html/api/Lib.CFG.html
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
<!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 — 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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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">→</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 -> 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">→</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 -> 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">→</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">→</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">→</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">→</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=<function</span> <span class="pre">CFG.<lambda>></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">→</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">→</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>© 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>
|
161
docs/html/api/Lib.Dominators.html
Normal file
161
docs/html/api/Lib.Dominators.html
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<!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 — 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">→</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">→</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">→</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">→</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>© 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
Loading…
x
Reference in New Issue
Block a user