1.1 --- a/translator.py Tue Mar 07 18:10:00 2017 +0100
1.2 +++ b/translator.py Tue Mar 07 19:28:33 2017 +0100
1.3 @@ -804,6 +804,10 @@
1.4 self.in_conditional = False
1.5 self.function_target = 0
1.6
1.7 + # Volatile locals for exception handling.
1.8 +
1.9 + self.volatile_locals = set()
1.10 +
1.11 # Process any guards defined for the parameters.
1.12
1.13 for name in self.importer.function_parameters.get(function_name):
1.14 @@ -1388,12 +1392,23 @@
1.15
1.16 location = self.get_access_location(n.name)
1.17
1.18 + # Mark any local assignments as volatile in exception blocks.
1.19 +
1.20 + if expr and self.in_function and not is_global and self.in_try_except:
1.21 + self.make_volatile(n.name)
1.22 +
1.23 # Qualified names are used for resolved static references or for
1.24 # static namespace members. The reference should be configured to return
1.25 # such names.
1.26
1.27 return TrResolvedNameRef(n.name, ref, expr=expr, is_global=is_global, location=location)
1.28
1.29 + def make_volatile(self, name):
1.30 +
1.31 + "Record 'name' as volatile in the current namespace."
1.32 +
1.33 + self.volatile_locals.add(name)
1.34 +
1.35 def process_not_node(self, n):
1.36
1.37 "Process the given operator node 'n'."
1.38 @@ -1714,23 +1729,23 @@
1.39
1.40 self.out = StringIO()
1.41
1.42 - def end_unit(self, name):
1.43 -
1.44 - "Add declarations and generated code."
1.45 -
1.46 - # Restore the output stream.
1.47 + def end_unit(self):
1.48 +
1.49 + "Restore the output stream."
1.50
1.51 out = self.out
1.52 self.out = self.out_toplevel
1.53 + return out
1.54 +
1.55 + def flush_unit(self, name, out):
1.56 +
1.57 + "Add declarations and generated code."
1.58
1.59 self.write_temporaries(name)
1.60 print >>self.out
1.61 out.seek(0)
1.62 self.out.write(out.read())
1.63
1.64 - self.indent -= 1
1.65 - print >>self.out, "}"
1.66 -
1.67 def start_module(self):
1.68
1.69 "Write the start of each module's main function."
1.70 @@ -1757,22 +1772,38 @@
1.71
1.72 "End each module by closing its main function."
1.73
1.74 - self.end_unit(self.name)
1.75 + out = self.end_unit()
1.76 + self.flush_unit(self.name, out)
1.77 +
1.78 + self.indent -= 1
1.79 + print >>self.out, "}"
1.80
1.81 def start_function(self, name):
1.82
1.83 "Start the function having the given 'name'."
1.84
1.85 + self.indent += 1
1.86 +
1.87 + self.start_unit()
1.88 +
1.89 + def end_function(self, name):
1.90 +
1.91 + "End the function having the given 'name'."
1.92 +
1.93 + out = self.end_unit()
1.94 +
1.95 + # Write the signature at the top indentation level.
1.96 +
1.97 + self.indent -= 1
1.98 self.write_parameters(name)
1.99 -
1.100 print >>self.out, "{"
1.101 - self.indent += 1
1.102
1.103 # Obtain local names from parameters.
1.104
1.105 parameters = self.importer.function_parameters[name]
1.106 locals = self.importer.function_locals[name].keys()
1.107 names = []
1.108 + volatile_names = []
1.109
1.110 for n in locals:
1.111
1.112 @@ -1782,21 +1813,27 @@
1.113
1.114 if n.startswith("$l") or n in parameters or n == "self":
1.115 continue
1.116 - names.append(encode_path(n))
1.117 -
1.118 - # Emit required local names.
1.119 + if n in self.volatile_locals:
1.120 + volatile_names.append(encode_path(n))
1.121 + else:
1.122 + names.append(encode_path(n))
1.123 +
1.124 + # Emit required local names at the function indentation level.
1.125 +
1.126 + self.indent += 1
1.127
1.128 if names:
1.129 names.sort()
1.130 self.writeline("__attr %s;" % ", ".join(names))
1.131
1.132 - self.start_unit()
1.133 -
1.134 - def end_function(self, name):
1.135 -
1.136 - "End the function having the given 'name'."
1.137 -
1.138 - self.end_unit(name)
1.139 + if volatile_names:
1.140 + volatile_names.sort()
1.141 + self.writeline("volatile __attr %s;" % ", ".join(volatile_names))
1.142 +
1.143 + self.flush_unit(name, out)
1.144 +
1.145 + self.indent -= 1
1.146 + print >>self.out, "}"
1.147 print >>self.out
1.148
1.149 def write_parameters(self, name):
1.150 @@ -1818,7 +1855,9 @@
1.151 # Generate aliases for the parameters.
1.152
1.153 for parameter in self.importer.function_parameters[name]:
1.154 - l.append("__attr %s" % encode_path(parameter))
1.155 + l.append("%s__attr %s" % (
1.156 + parameter in self.volatile_locals and "volatile " or "",
1.157 + encode_path(parameter)))
1.158
1.159 self.writeline("__attr %s(%s)" % (
1.160 encode_function_pointer(name), ", ".join(l)))