|
@@ -43,18 +43,74 @@ class SimpleBlock(object):
|
|
|
self.body = body
|
|
|
self.next_block = next_block
|
|
|
|
|
|
+ def lower(self, state):
|
|
|
+ """Lowers this 'simple' block to a tree."""
|
|
|
+ return tree_ir.create_block(
|
|
|
+ state.lower_block(self.body),
|
|
|
+ self.next_block.lower(state))
|
|
|
+
|
|
|
class LoopBlock(object):
|
|
|
"""A 'loop' block in the relooper algorithm."""
|
|
|
def __init__(self, inner, next_block):
|
|
|
self.inner = inner
|
|
|
self.next_block = next_block
|
|
|
|
|
|
+ def lower(self, state):
|
|
|
+ """Lowers this 'loop' block to a tree."""
|
|
|
+ old_loop = state.current_loop
|
|
|
+ state.current_loop = self
|
|
|
+ inner = tree_ir.LoopInstruction(
|
|
|
+ tree_ir.create_block(
|
|
|
+ self.inner.lower(state),
|
|
|
+ tree_ir.BreakInstruction()))
|
|
|
+ state.current_loop = old_loop
|
|
|
+ return tree_ir.create_block(
|
|
|
+ inner,
|
|
|
+ self.next_block.lower(state))
|
|
|
+
|
|
|
class MultipleBlock(object):
|
|
|
- """A 'multiple' block in the relooper algorithm."""
|
|
|
+ """A 'multiple' block in the relooper algorithm that does _not_ require a loop."""
|
|
|
def __init__(self, handled_blocks, next_block):
|
|
|
self.handled_blocks = handled_blocks
|
|
|
self.next_block = next_block
|
|
|
|
|
|
+ def lower_handled_blocks(self, state):
|
|
|
+ """Lowers the handled blocks of this 'multiple' block to a tree."""
|
|
|
+ result = tree_ir.EmptyInstruction()
|
|
|
+ for entry, block in self.handled_blocks:
|
|
|
+ result = tree_ir.SelectInstruction(
|
|
|
+ tree_ir.BinaryInstruction(
|
|
|
+ state.label_variable,
|
|
|
+ '==',
|
|
|
+ tree_ir.LiteralInstruction(state.get_label_value(entry))),
|
|
|
+ block.lower(state),
|
|
|
+ result)
|
|
|
+ return result
|
|
|
+
|
|
|
+ def lower(self, state):
|
|
|
+ """Lowers this 'multiple' block to a tree."""
|
|
|
+ return tree_ir.create_block(
|
|
|
+ self.lower_handled_blocks(state),
|
|
|
+ self.next_block.lower(state))
|
|
|
+
|
|
|
+class MultipleLoopBlock(MultipleBlock):
|
|
|
+ """A 'multiple' block in the relooper algorithm."""
|
|
|
+ def __init__(self, handled_blocks, next_block):
|
|
|
+ MultipleBlock.__init__(self, handled_blocks, next_block)
|
|
|
+
|
|
|
+ def lower(self, state):
|
|
|
+ """Lowers this 'multiple' block to a tree."""
|
|
|
+ old_loop = state.current_loop
|
|
|
+ state.current_loop = self
|
|
|
+ inner = tree_ir.LoopInstruction(
|
|
|
+ tree_ir.create_block(
|
|
|
+ self.lower_handled_blocks(state),
|
|
|
+ tree_ir.BreakInstruction()))
|
|
|
+ state.current_loop = old_loop
|
|
|
+ return tree_ir.create_block(
|
|
|
+ inner,
|
|
|
+ self.next_block.lower(state))
|
|
|
+
|
|
|
class ContinueFlow(cfg_ir.FlowInstruction):
|
|
|
"""Represents a control flow instruction which continues to the next loop iteration."""
|
|
|
def __init__(self, loop):
|
|
@@ -95,6 +151,9 @@ def solipsize(graph_component, loop, entry_blocks, next_blocks):
|
|
|
all_blocks = set()
|
|
|
reachable_from_inner = set()
|
|
|
for block in graph_component.blocks:
|
|
|
+ if block in next_blocks:
|
|
|
+ continue
|
|
|
+
|
|
|
all_blocks.add(block)
|
|
|
for branch in block.flow.branches():
|
|
|
if branch.block in entry_blocks:
|
|
@@ -137,10 +196,8 @@ def to_relooper_loop(graph_component):
|
|
|
else:
|
|
|
next_blocks.append(block)
|
|
|
|
|
|
- inner_component = FlowGraphComponent(
|
|
|
- entry_blocks, inner_blocks, graph_component.reachable)
|
|
|
reachable_from_inner, inner_component = solipsize(
|
|
|
- inner_component, result, entry_blocks, next_blocks)
|
|
|
+ graph_component, result, entry_blocks, next_blocks)
|
|
|
result.inner = reloop(inner_component)
|
|
|
|
|
|
next_component = FlowGraphComponent(
|
|
@@ -188,7 +245,7 @@ def to_relooper_multiple_or_loop(graph_component):
|
|
|
|
|
|
next_entries.difference_update(exclusive_entries.keys())
|
|
|
|
|
|
- result = MultipleBlock({}, None)
|
|
|
+ result = MultipleLoopBlock({}, None)
|
|
|
for entry, exclusive_blocks in exclusive_entries.items():
|
|
|
other_blocks = set(graph_component.blocks)
|
|
|
other_blocks.difference_update(exclusive_blocks)
|
|
@@ -216,3 +273,55 @@ def reloop(graph_component):
|
|
|
return to_relooper_loop(graph_component)
|
|
|
else:
|
|
|
return to_relooper_multiple_or_loop(graph_component)
|
|
|
+
|
|
|
+class LoweringState(object):
|
|
|
+ """Stores information related to the relooper->tree conversion."""
|
|
|
+ def __init__(self, jit):
|
|
|
+ self.jit = jit
|
|
|
+ self.label_variable = tree_ir.VariableName('__label')
|
|
|
+ self.label_map = {}
|
|
|
+ self.definition_loads = {}
|
|
|
+
|
|
|
+ def get_label_value(self, block):
|
|
|
+ """Gets the label value for the given block."""
|
|
|
+ if block in self.label_map:
|
|
|
+ return self.label_map[block]
|
|
|
+ else:
|
|
|
+ result = len(self.label_map)
|
|
|
+ self.label_map[block] = result
|
|
|
+ return result
|
|
|
+
|
|
|
+ def load_definition(self, definition):
|
|
|
+ """Loads the given definition's variable."""
|
|
|
+ if definition in self.definition_loads:
|
|
|
+ return self.definition_loads[definition]
|
|
|
+
|
|
|
+ if definition.instruction.has_value():
|
|
|
+ raise NotImplementedError()
|
|
|
+ else:
|
|
|
+ raise NotImplementedError()
|
|
|
+
|
|
|
+ def lower_block(self, block):
|
|
|
+ """Lowers the given (relooped) block to a tree."""
|
|
|
+ statements = []
|
|
|
+ for definition in block.definitions:
|
|
|
+ statements.append(self.lower_definition(definition))
|
|
|
+ statements.append(self.lower_flow(block.flow))
|
|
|
+ return tree_ir.create_block(statements)
|
|
|
+
|
|
|
+ def lower_definition(self, definition):
|
|
|
+ """Lowers the given definition to a tree."""
|
|
|
+ instruction = definition.value
|
|
|
+ tree_instruction = self.lower_instruction(instruction)
|
|
|
+ if instruction.has_value():
|
|
|
+ return self.load_definition(definition).create_store(tree_instruction)
|
|
|
+ else:
|
|
|
+ return tree_instruction
|
|
|
+
|
|
|
+ def lower_instruction(self, instruction):
|
|
|
+ """Lowers the given instruction to a tree."""
|
|
|
+ raise NotImplementedError()
|
|
|
+
|
|
|
+ def lower_flow(self, flow):
|
|
|
+ """Lowers the given (relooped) flow instruction to a tree."""
|
|
|
+ raise NotImplementedError()
|