1.1 --- a/micropython/code.py Sat Sep 10 20:29:30 2011 +0200
1.2 +++ b/micropython/code.py Sat Sep 10 20:33:52 2011 +0200
1.3 @@ -45,6 +45,10 @@
1.4
1.5 self.expr_temp = []
1.6
1.7 + # The start of the current assignment target instructions.
1.8 +
1.9 + self.target_start = None
1.10 +
1.11 # Wiring within the code.
1.12
1.13 self.labels = {}
1.14 @@ -144,50 +148,78 @@
1.15
1.16 self.discard_temp(self.expr_temp.pop())
1.17
1.18 + def start_target(self):
1.19 +
1.20 + """
1.21 + Start recording instructions used to define the target of an assignment.
1.22 + """
1.23 +
1.24 + self.target_start = len(self.blocks[-1])
1.25 +
1.26 + def remove_target_ops(self):
1.27 +
1.28 + "Remove the assignment target instructions."
1.29 +
1.30 + del self.blocks[-1].code[self.target_start:]
1.31 + self.target_start = None
1.32 + self.optimiser.clear_active()
1.33 +
1.34 + def get_target_ops(self):
1.35 +
1.36 + "Return the assignment target instructions."
1.37 +
1.38 + return self.blocks[-1].code[self.target_start:]
1.39 +
1.40 def assign_value(self, expr=None):
1.41
1.42 """
1.43 Set the source of an assignment using 'expr' or the current assignment
1.44 - value. This sets the source register of the current instruction.
1.45 + value. This may set the source register of the current instruction.
1.46 """
1.47
1.48 - if expr is None:
1.49 - expr = self.expr_temp[-1]
1.50 + expr = expr or self.expr_temp[-1]
1.51 +
1.52 + # Optimise away constant storage if appropriate.
1.53
1.54 - # Optimise away constant storage if appropriate.
1.55 -
1.56 - if self.optimiser.optimise_constant_storage(expr):
1.57 - self.remove_op()
1.58 - return
1.59 + if self.optimiser.optimise_constant_storage(expr):
1.60 + self.remove_target_ops()
1.61 + return
1.62
1.63 # Otherwise, insert the assignment source.
1.64
1.65 - if expr is not None:
1.66 - expr_copy = expr.copy()
1.67 - assign_op = self.last_op()
1.68 + expr_copy = expr.copy()
1.69 + assign_ops = self.get_target_ops()
1.70 +
1.71 + if not assign_ops:
1.72 + self.target_start = None
1.73 + return
1.74
1.75 - # Either insert the instruction yielding the value and adjust the
1.76 - # assignment source.
1.77 + assign_op = assign_ops[-1]
1.78
1.79 - expr_copy.target = "source"
1.80 + # Either insert the instruction yielding the value and adjust the
1.81 + # assignment source.
1.82
1.83 - if self.insert_op(-1, expr_copy):
1.84 - assign_op.source = "source"
1.85 - self.update_temp(expr, expr_copy)
1.86 + expr_copy.target = "source"
1.87
1.88 - # (Now, the instruction need not be inserted.)
1.89 + if self.insert_op(-1, expr_copy):
1.90 + assign_op.source = "source"
1.91 + self.update_temp(expr, expr_copy)
1.92
1.93 - # Or transfer the working value to the source register.
1.94 + # (Now, the instruction need not be inserted.)
1.95 +
1.96 + # Or transfer the working value to the source register.
1.97
1.98 - elif assign_op.working == "working":
1.99 - self.insert_op(-1, Transfer(source="working_context", target="source_context"))
1.100 - self.insert_op(-1, Transfer(source="working", target="source"))
1.101 - assign_op.source = "source"
1.102 + elif assign_op.working == "working":
1.103 + self.insert_op(-1, Transfer(source="working_context", target="source_context"))
1.104 + self.insert_op(-1, Transfer(source="working", target="source"))
1.105 + assign_op.source = "source"
1.106
1.107 - # Or let the assignment use the working register.
1.108 + # Or let the assignment use the working register.
1.109
1.110 - else:
1.111 - assign_op.source = "working"
1.112 + else:
1.113 + assign_op.source = "working"
1.114 +
1.115 + self.target_start = None
1.116
1.117 def set_target(self, target):
1.118
1.119 @@ -285,7 +317,11 @@
1.120 if isinstance(instruction, LoadTemp) and instruction.attr is not None:
1.121 temp_position = instruction.attr - self.unit.all_local_usage
1.122 self.free_temp(temp_position)
1.123 - self.optimiser.ignore_active_value()
1.124 +
1.125 + # Prevent any requested active value from generating instructions now
1.126 + # that our interest in it has passed.
1.127 +
1.128 + self.optimiser.ignore_active_value()
1.129
1.130 def free_temp(self, temp_position):
1.131
1.132 @@ -361,6 +397,7 @@
1.133
1.134 op = self.blocks[-1].code.pop()
1.135 self.optimiser.clear_active()
1.136 + return op
1.137
1.138 def replace_op(self, op):
1.139
1.140 @@ -375,8 +412,9 @@
1.141 Replace the value-providing active instruction with 'op' if appropriate.
1.142 """
1.143
1.144 - self.optimiser.remove_active_value()
1.145 + removed = self.optimiser.remove_active_value()
1.146 self.new_op(op)
1.147 + return removed
1.148
1.149 def last_op(self):
1.150