Expand description
ULLBC to LLBC
We reconstruct the control-flow in the Unstructured LLBC.
The reconstruction algorithm is not written to be efficient (its complexity is probably very bad), but it was not written to be: this is still an early stage and we want the algorithm to generate the best reconstruction as possible. We still need to test the algorithm on more interesting examples, and will consider making it more efficient once it is a bit mature and well tested. Also note that we more importantly focus on making the algorithm sound: the reconstructed program must always be equivalent to the original MIR program, and the fact that the reconstruction preserves this property must be obvious.
Finally, we conjecture the execution time shouldnβt be too much a problem: we donβt expect the translation mechanism to be applied on super huge functions (which will be difficult to formally analyze), and the MIR graphs are actually not that big because statements are grouped into code blocks (a block is made of a list of statements, followed by a terminator - branchings and jumps can only be performed by terminators -, meaning that MIR graphs donβt have that many nodes and edges).
StructsΒ§
- Block
Info π - Small utility
- Block
With πRank - Blocks
Info π - Information used to compute the switch exits. We compute this information for every block in the graph. Note that we make sure to use immutable sets because we rely a lot on cloning.
- CfgInfo π
- This structure contains various information about a functionβs CFG.
- Exit
Info π - The exits of a graph
- Filtered
Loop πParents - Loop
Exit πCandidate Info - Transform
EnumsΒ§
- Goto
Kind π
FunctionsΒ§
- block_
is_ πerror - The terminator of the block is a panic, etc.
- block_
is_ πswitch - build_
cfg_ πinfo - Build the CFGs (the βregularβ CFG and the CFG without backward edges) and compute some information like the loop entries and the switch blocks.
- build_
cfg_ πpartial_ info_ edges - can_
reach_ πouter_ exit - Auxiliary helper
- compute_
loop_ πexit_ candidates - Compute the loop exit candidates.
- compute_
loop_ πexits - See
compute_loop_switch_exits
for explanations about what βexitsβ are. - compute_
loop_ πswitch_ exits - Compute the exits for the loops and the switches (switch on integer and if β¦ then β¦ else β¦). We need to do this because control-flow in MIR is destructured: we have gotos everywhere.
- compute_
switch_ πexits - See
compute_loop_switch_exits
for explanations about what βexitsβ are. - compute_
switch_ πexits_ explore - Compute BlocksInfo for every block in the graph. This information is then used to compute the switch exits.
- filter_
loop_ πparents - get_
goto_ πkind - is_
terminal π - Return
true
if whatever the path we take, evaluating the statement necessarily leads to: - is_
terminal_ πexplore - is_
terminal_ πexplore_ block - list_
reachable π - List the nodes reachable from a starting point. We list the nodes and the depth (in the AST) at which they were found.
- loop_
entry_ πis_ reachable_ from_ inner - Check if a loop entry is reachable from a node, in a graph where we remove the backward edges going directly to the loop entry.
- make_
ord_ πblock_ id - Create an OrdBlockId from a block id and a rank given by a map giving a sort (topological in our use cases) over the graph.
- opt_
block_ πunwrap_ or_ nop - register_
children_ πas_ loop_ exit_ candidates - Register a node and its children as exit candidates for a list of parent loops.
- translate_
block π - Remark: some values are boxed (here, the returned statement) so that they are allocated on the heap. This reduces stack usage (we had problems with stack overflows in the past). A more efficient solution would be to use loops to make this code constant space, but that would require a serious rewriting.
- translate_
body π - translate_
body_ πaux - translate_
child_ πblock parent_span
: we need some span data for the new statement. We use the one for the parent terminator.- translate_
statement π - translate_
terminator π
Type AliasesΒ§
- Cfg π
- Control-Flow Graph
- Flow
Block πId - For the rank we use:
- OrdBlock
Id π