|
@@ -43,7 +43,8 @@ def get_ineligible_local_ids(entry_point):
|
|
|
return ineligible_local_ids
|
|
|
|
|
|
def construct_ssa_form(entry_point):
|
|
|
- """Converts local variables into SSA form in the graph defined by the given entry point."""
|
|
|
+ """Converts local variables into SSA form in the graph defined by the given entry point.
|
|
|
+ A potentially new entry block is returned."""
|
|
|
# Build some helper data structures.
|
|
|
all_blocks = list(cfg_ir.get_all_blocks(entry_point))
|
|
|
ineligible_locals = get_ineligible_local_ids(entry_point)
|
|
@@ -60,6 +61,37 @@ def construct_ssa_form(entry_point):
|
|
|
for block in all_blocks:
|
|
|
state.update_block_branches(block)
|
|
|
|
|
|
+ # Nullify entry point parameters.
|
|
|
+ return nullify_entry_block_parameters(entry_point)
|
|
|
+
|
|
|
+def nullify_entry_block_parameters(entry_point):
|
|
|
+ """Creates or returns an entry block that takes no parameters.
|
|
|
+ The (new) entry block is returned."""
|
|
|
+ # The SSA construction algorithm has the nasty habit of replacing potentially
|
|
|
+ # undefined variables by entry block parameters. Codegen doesn't like that one
|
|
|
+ # bit: it assumes that all block parameters are defined by the branches to those
|
|
|
+ # parameters -- but there usually is no branch to the entry point!
|
|
|
+ #
|
|
|
+ # We can fix this by either replacing the block-parameters in the entry block by
|
|
|
+ # definitions, or by creating a new entry point that jumps to the old entry
|
|
|
+ # point with an argument list. The former construction is more efficient, but it is only
|
|
|
+ # correct if there are no pre-existing branches to the entry point.
|
|
|
+ #
|
|
|
+ # We could build the predecessor map block and use the first option if possible,
|
|
|
+ # but we won't; trivial phi elimination followed by block merging will reduce
|
|
|
+ # the second construction to the first one anyway.
|
|
|
+ if len(entry_point.parameters) == 0:
|
|
|
+ return entry_point
|
|
|
+
|
|
|
+ pre_entry_point = cfg_ir.BasicBlock(entry_point.counter)
|
|
|
+ arg_list = []
|
|
|
+ for _ in entry_point.parameters:
|
|
|
+ literal_def = pre_entry_point.append_definition(cfg_ir.Literal(None))
|
|
|
+ arg_list.append(literal_def)
|
|
|
+
|
|
|
+ pre_entry_point.flow = cfg_ir.create_jump(entry_point, arg_list)
|
|
|
+ return pre_entry_point
|
|
|
+
|
|
|
# The algorithms below are based on
|
|
|
# Simple and Efficient Construction of Static Single Assignment Form by M. Braun et al
|
|
|
# (https://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf).
|
|
@@ -234,6 +266,3 @@ class SSAConstructionState(object):
|
|
|
# Append arguments to the branch.
|
|
|
for _, arg in sorted_pairs:
|
|
|
branch.arguments.append(arg)
|
|
|
-
|
|
|
-
|
|
|
-
|