1.1 --- a/micropython/code.py Thu Sep 01 00:35:47 2011 +0200
1.2 +++ b/micropython/code.py Mon Sep 05 00:16:33 2011 +0200
1.3 @@ -126,8 +126,8 @@
1.4
1.5 """
1.6 Record the current active value for an assignment. If the optional
1.7 - 'immediate' parameter if set to a false value always allocates new
1.8 - temporary storage to hold the recorded value; otherwise, the
1.9 + 'immediate' parameter is set to a false value, new temporary storage to
1.10 + hold the recorded value will be allocated; otherwise, the
1.11 value-providing instruction may be replicated in order to provide the
1.12 active value later on.
1.13 """
1.14 @@ -163,10 +163,31 @@
1.15 # Otherwise, insert the assignment source.
1.16
1.17 if expr is not None:
1.18 - expr = expr.copy()
1.19 - expr.target = "source"
1.20 - self.insert_op(-1, expr)
1.21 - self.last_op().source = "source"
1.22 + expr_copy = expr.copy()
1.23 + assign_op = self.last_op()
1.24 +
1.25 + # Either insert the instruction yielding the value and adjust the
1.26 + # assignment source.
1.27 +
1.28 + expr_copy.target = "source"
1.29 +
1.30 + if self.insert_op(-1, expr_copy):
1.31 + assign_op.source = "source"
1.32 + self.update_temp(expr, expr_copy)
1.33 +
1.34 + # (Now, the instruction need not be inserted.)
1.35 +
1.36 + # Or transfer the working value to the source register.
1.37 +
1.38 + elif assign_op.working == "working":
1.39 + self.insert_op(-1, Transfer(source="working_context", target="source_context"))
1.40 + self.insert_op(-1, Transfer(source="working", target="source"))
1.41 + assign_op.source = "source"
1.42 +
1.43 + # Or let the assignment use the working register.
1.44 +
1.45 + else:
1.46 + assign_op.source = "working"
1.47
1.48 def set_target(self, target):
1.49
1.50 @@ -198,13 +219,34 @@
1.51 def get_temp(self):
1.52
1.53 """
1.54 - Add a temporary storage instruction for the current value and return a
1.55 - sequence of access instructions.
1.56 + Return a temporary storage access instruction for the current value.
1.57 + Initially, this instruction is not associated with an allocated unit of
1.58 + temporary storage, and if used as a new instruction will not be added to
1.59 + the code, but if the current value changes, the 'set_temp' method will
1.60 + be called by the optimiser and a unit of storage will be allocated.
1.61 """
1.62
1.63 - position_in_frame = self.reserve_temp()
1.64 - self.new_op(StoreTemp(position_in_frame))
1.65 - return LoadTemp(position_in_frame)
1.66 + temp = LoadTemp(None)
1.67 + self.optimiser.request_active_value(temp, self.blocks[-1], len(self.blocks[-1].code))
1.68 + return temp
1.69 +
1.70 + def set_temp(self, temp, block, pos):
1.71 +
1.72 + """
1.73 + Emit a storage instruction for the given 'temp' loading instruction,
1.74 + reserving a new temporary storage location.
1.75 + """
1.76 +
1.77 + if temp.attr is None:
1.78 + temp.attr = self.reserve_temp()
1.79 + block.insert(pos, StoreTemp(temp.attr))
1.80 +
1.81 + def update_temp(self, temp, updated):
1.82 +
1.83 + "Update 'temp' using the given 'updated' instruction."
1.84 +
1.85 + if isinstance(temp, LoadTemp):
1.86 + temp.attr = updated.attr
1.87
1.88 def reserve_temp(self, temp_position=None):
1.89
1.90 @@ -240,9 +282,10 @@
1.91
1.92 "Discard any temporary storage position used by 'instruction'."
1.93
1.94 - if isinstance(instruction, LoadTemp):
1.95 + if isinstance(instruction, LoadTemp) and instruction.attr is not None:
1.96 temp_position = instruction.attr - self.unit.all_local_usage
1.97 self.free_temp(temp_position)
1.98 + self.optimiser.ignore_active_value()
1.99
1.100 def free_temp(self, temp_position):
1.101
1.102 @@ -276,22 +319,41 @@
1.103 was added.
1.104 """
1.105
1.106 - # Optimise load operations employed by this instruction.
1.107 -
1.108 - if self.optimiser.optimise_away_no_operations(op) or self.optimiser.optimise_unused_handlers(op):
1.109 + if not self.check_op(op):
1.110 return 0
1.111
1.112 # Add the operation to the current block.
1.113
1.114 - self.blocks[-1].code.append(op)
1.115 self.optimiser.set_new(op)
1.116 + self.blocks[-1].append(op)
1.117 return 1
1.118
1.119 def insert_op(self, i, op):
1.120
1.121 "Insert at index 'i' in the current block the instruction 'op'."
1.122
1.123 - self.blocks[-1].code.insert(i, op)
1.124 + if not self.check_op(op):
1.125 + return 0
1.126 +
1.127 + self.blocks[-1].insert(i, op)
1.128 + return 1
1.129 +
1.130 + def check_op(self, op):
1.131 +
1.132 + "Return whether the given 'op' is to be added to the code."
1.133 +
1.134 + # Optimise away temporary storage instructions where the active value is
1.135 + # still available and was not recorded.
1.136 +
1.137 + if isinstance(op, LoadTemp) and op.attr is None:
1.138 + return 0
1.139 +
1.140 + # Optimise load operations employed by this instruction.
1.141 +
1.142 + if self.optimiser.optimise_away_no_operations(op) or self.optimiser.optimise_unused_handlers(op):
1.143 + return 0
1.144 +
1.145 + return 1
1.146
1.147 def remove_op(self):
1.148