cfg_ir.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. """Defines control flow graph IR data structures."""
  2. # Let's just agree to disagree on map vs list comprehensions, pylint.
  3. # pylint: disable=I0011,W0141
  4. class SharedCounter(object):
  5. """Defines a shared counter."""
  6. def __init__(self):
  7. self.index = 0
  8. def next_value(self):
  9. """Gets the next value for this counter."""
  10. result = self.index
  11. self.index += 1
  12. return result
  13. class BasicBlock(object):
  14. """Represents a basic block."""
  15. def __init__(self, counter):
  16. self.parameters = []
  17. self.definitions = []
  18. self.counter = counter
  19. self.index = counter.next_value()
  20. self.flow = UnreachableFlow()
  21. def append_parameter(self, parameter):
  22. """Appends a parameter to this basic block."""
  23. result = Definition(self.counter.next_value(), parameter)
  24. self.parameters.append(result)
  25. return result
  26. def prepend_definition(self, value):
  27. """Defines the given value in this basic block."""
  28. result = Definition(self.counter.next_value(), value)
  29. self.definitions.insert(0, result)
  30. return result
  31. def append_definition(self, value):
  32. """Defines the given value in this basic block."""
  33. result = Definition(self.counter.next_value(), value)
  34. self.definitions.append(result)
  35. return result
  36. def remove_definition(self, definition):
  37. """Removes the given definition from this basic block."""
  38. return self.definitions.remove(definition)
  39. def __str__(self):
  40. return '\n'.join(map(str, self.definitions + [self.flow]))
  41. class Definition(object):
  42. """Maps a value to a variable."""
  43. def __init__(self, index, value):
  44. self.index = index
  45. self.value = value
  46. def redefine(self, new_value):
  47. """Tweaks this definition to take on the given new value."""
  48. self.value = new_value
  49. def __str__(self):
  50. return '$%d = %s' % (self.index, str(self.value))
  51. class Instruction(object):
  52. """Represents an instruction."""
  53. def get_dependencies(self):
  54. """Gets all definitions and instructions on which this instruction depends."""
  55. raise NotImplementedError()
  56. def get_all_dependencies(self):
  57. """Gets all definitions and instructions on which this instruction depends,
  58. along with any dependencies of dependencies."""
  59. results = list(self.get_dependencies())
  60. for item in results:
  61. results.extend(item.get_all_dependencies())
  62. return results
  63. class Branch(Instruction):
  64. """Represents a branch from one basic block to another."""
  65. def __init__(self, block, arguments):
  66. self.block = block
  67. self.arguments = arguments
  68. def get_dependencies(self):
  69. """Gets all definitions and instructions on which this instruction depends."""
  70. return self.arguments
  71. class FlowInstruction(Instruction):
  72. """Represents a control flow instruction which terminates a basic block."""
  73. def branches(self):
  74. """Gets a list of basic blocks targeted by this flow instruction."""
  75. raise NotImplementedError()
  76. class JumpFlow(FlowInstruction):
  77. """Represents a control flow instruction which jumps directly to a basic block."""
  78. def __init__(self, branch):
  79. FlowInstruction.__init__(self)
  80. self.branch = branch
  81. def get_dependencies(self):
  82. """Gets all definitions and instructions on which this instruction depends."""
  83. return self.branches()
  84. def branches(self):
  85. """Gets a list of basic blocks targeted by this flow instruction."""
  86. return [self.branch]
  87. class SelectFlow(FlowInstruction):
  88. """Represents a control flow instruction which jumps to one of two basic blocks depending
  89. on whether a condition is truthy or not."""
  90. def __init__(self, condition, if_branch, else_branch):
  91. FlowInstruction.__init__(self)
  92. self.condition = condition
  93. self.if_branch = if_branch
  94. self.else_branch = else_branch
  95. def get_dependencies(self):
  96. """Gets all definitions and instructions on which this instruction depends."""
  97. return [self.condition] + self.branches()
  98. def branches(self):
  99. """Gets a list of basic blocks targeted by this flow instruction."""
  100. return [self.if_branch, self.else_branch]
  101. class ReturnFlow(FlowInstruction):
  102. """Represents a control flow instruction which terminates the execution of the current
  103. function and returns a value."""
  104. def __init__(self, value):
  105. FlowInstruction.__init__(self)
  106. self.value = value
  107. def get_dependencies(self):
  108. """Gets all definitions and instructions on which this instruction depends."""
  109. return [self.value]
  110. def branches(self):
  111. """Gets a list of basic blocks targeted by this flow instruction."""
  112. return []
  113. class UnreachableFlow(FlowInstruction):
  114. """Represents a control flow instruction which is unreachable."""
  115. def get_dependencies(self):
  116. """Gets all definitions and instructions on which this instruction depends."""
  117. return []
  118. def branches(self):
  119. """Gets a list of basic blocks targeted by this flow instruction."""
  120. return []
  121. class Value(Instruction):
  122. """A value: an instruction that produces some result."""
  123. def get_dependencies(self):
  124. """Gets all definitions and instructions on which this instruction depends."""
  125. raise NotImplementedError()
  126. class BlockParameter(Value):
  127. """A basic block parameter."""
  128. def get_dependencies(self):
  129. """Gets all definitions and instructions on which this instruction depends."""
  130. return []
  131. class FunctionParameter(Value):
  132. """A function parameter."""
  133. def __init__(self, name):
  134. Value.__init__(self)
  135. self.name = name
  136. def get_dependencies(self):
  137. """Gets all definitions and instructions on which this instruction depends."""
  138. return []
  139. class Literal(Value):
  140. """A literal value."""
  141. def __init__(self, literal):
  142. Value.__init__(self)
  143. self.literal = literal
  144. def get_dependencies(self):
  145. """Gets all definitions and instructions on which this instruction depends."""
  146. return []