# HG changeset patch # User Paul Boddie # Date 1487353938 -3600 # Node ID 6eaa4b2f2534e45fad07127c7125fd35dce1ede0 # Parent 7754692ebe545587663f20b0a5f0e658404ffee6 Changed local context storage to employ arrays, similar to those employed for targets, with access instructions being parameterised with the appropriate array index. This should avoid sequence point warnings for context storage operations. diff -r 7754692ebe54 -r 6eaa4b2f2534 encoders.py --- a/encoders.py Fri Feb 17 18:49:57 2017 +0100 +++ b/encoders.py Fri Feb 17 18:52:18 2017 +0100 @@ -210,10 +210,18 @@ "__load_static_ignore", "__load_static_replace", "__load_static_test", ) +context_values = ( + "", + ) + +context_ops = ( + "", "", + ) + reference_acting_ops = attribute_ops + checked_ops + typename_ops attribute_producing_ops = attribute_loading_ops + checked_loading_ops -def encode_access_instruction(instruction, subs): +def encode_access_instruction(instruction, subs, context_index): """ Encode the 'instruction' - a sequence starting with an operation and @@ -223,6 +231,9 @@ The 'subs' parameter defines a mapping of substitutions for special values used in instructions. + The 'context_index' parameter defines the position in local context storage + for the referenced context or affected by a context operation. + Return both the encoded instruction and a collection of substituted names. """ @@ -230,53 +241,60 @@ args = instruction[1:] substituted = set() - if not args: - argstr = "" + # Encode the arguments. - else: - # Encode the arguments. - - a = [] + a = [] + if args: converting_op = op for arg in args: - s, _substituted = encode_access_instruction_arg(arg, subs, converting_op) + s, _substituted = encode_access_instruction_arg(arg, subs, converting_op, context_index) substituted.update(_substituted) a.append(s) converting_op = None - # Modify certain arguments. + # Modify certain arguments. - # Convert attribute name arguments to position symbols. + # Convert attribute name arguments to position symbols. - if op in attribute_ops: - arg = a[1] - a[1] = encode_symbol("pos", arg) + if op in attribute_ops: + arg = a[1] + a[1] = encode_symbol("pos", arg) + + # Convert attribute name arguments to position and code symbols. - # Convert attribute name arguments to position and code symbols. + elif op in checked_ops: + arg = a[1] + a[1] = encode_symbol("pos", arg) + a.insert(2, encode_symbol("code", arg)) - elif op in checked_ops: - arg = a[1] - a[1] = encode_symbol("pos", arg) - a.insert(2, encode_symbol("code", arg)) + # Convert type name arguments to position and code symbols. - # Convert type name arguments to position and code symbols. + elif op in typename_ops: + arg = encode_type_attribute(args[1]) + a[1] = encode_symbol("pos", arg) + a.insert(2, encode_symbol("code", arg)) - elif op in typename_ops: - arg = encode_type_attribute(args[1]) - a[1] = encode_symbol("pos", arg) - a.insert(2, encode_symbol("code", arg)) + # Obtain addresses of type arguments. + + elif op in type_ops: + a[1] = "&%s" % a[1] - # Obtain addresses of type arguments. + # Obtain addresses of static objects. + + elif op in static_ops: + a[-1] = "&%s" % a[-1] - elif op in type_ops: - a[1] = "&%s" % a[1] + # Add context storage information to certain operations. - # Obtain addresses of static objects. + elif op in context_ops: + a.insert(0, context_index) - elif op in static_ops: - a[-1] = "&%s" % a[-1] + # Define any argument string. + if a: argstr = "(%s)" % ", ".join(map(str, a)) + else: + argstr = "" # Substitute the first element of the instruction, which may not be an # operation at all. @@ -300,16 +318,19 @@ return "%s%s" % (op, argstr), substituted -def encode_access_instruction_arg(arg, subs, op): +def encode_access_instruction_arg(arg, subs, op, context_index): """ - Encode 'arg' using 'subs' to define substitutions, returning a tuple - containing the encoded form of 'arg' along with a collection of any - substituted values. + Encode 'arg' using 'subs' to define substitutions, 'op' to indicate the + operation to which the argument belongs, and 'context_index' to indicate any + affected context storage. + + Return a tuple containing the encoded form of 'arg' along with a collection + of any substituted values. """ if isinstance(arg, tuple): - encoded, substituted = encode_access_instruction(arg, subs) + encoded, substituted = encode_access_instruction(arg, subs, context_index) # Convert attribute results to references where required. @@ -321,7 +342,13 @@ # Special values only need replacing, not encoding. elif subs.has_key(arg): - return subs.get(arg), set([arg]) + + # Handle values modified by storage details. + + if arg in context_values: + return "%s(%s)" % (subs.get(arg), context_index), set([arg]) + else: + return subs.get(arg), set([arg]) # Convert static references to the appropriate type. diff -r 7754692ebe54 -r 6eaa4b2f2534 templates/ops.h --- a/templates/ops.h Fri Feb 17 18:49:57 2017 +0100 +++ b/templates/ops.h Fri Feb 17 18:52:18 2017 +0100 @@ -73,7 +73,8 @@ __attr __test_context(__ref context, __attr attr); __attr __update_context(__ref context, __attr attr); -#define __set_context(__ATTR) (__tmp_context = (__ATTR).value) +#define __get_context(__TARGET) (__tmp_contexts[__TARGET]) +#define __set_context(__TARGET, __ATTR) (__tmp_contexts[__TARGET] = (__ATTR).value) #define __set_accessor(__ATTR) (__tmp_value = (__ATTR).value) #define __set_target_accessor(__ATTR) (__tmp_target_value = (__ATTR).value) diff -r 7754692ebe54 -r 6eaa4b2f2534 translator.py --- a/translator.py Fri Feb 17 18:49:57 2017 +0100 +++ b/translator.py Fri Feb 17 18:52:18 2017 +0100 @@ -739,8 +739,8 @@ } temp_subs = { - "" : "__tmp_context", - "" : "__tmp_context", + "" : "__tmp_contexts", + "" : "__tmp_contexts", "" : "__tmp_value", "" : "__tmp_target_value", "" : "__tmp_value", @@ -748,6 +748,7 @@ } op_subs = { + "" : "__get_context", "" : "__set_context", "" : "__set_accessor", "" : "__set_target_accessor", @@ -759,11 +760,16 @@ output = [] substituted = set() + # The context set or retrieved will be that used by any enclosing + # invocation. + + context_index = self.function_target - 1 + # Obtain encoded versions of each instruction, accumulating temporary # variables. for instruction in self.optimiser.access_instructions[location]: - encoded, _substituted = encode_access_instruction(instruction, subs) + encoded, _substituted = encode_access_instruction(instruction, subs, context_index) output.append(encoded) substituted.update(_substituted) @@ -1253,7 +1259,8 @@ if context_required: if have_access_context: - args = ["(__attr) {.value=__tmp_context}"] + self.record_temp("__tmp_contexts") + args = ["(__attr) {.value=__tmp_contexts[%d]}" % self.function_target] else: self.record_temp("__tmp_targets") args = ["__CONTEXT_AS_VALUE(__tmp_targets[%d])" % self.function_target] @@ -1367,12 +1374,13 @@ # Methods accessed via unidentified accessors are obtained. elif function: + self.record_temp("__tmp_contexts") self.record_temp("__tmp_targets") if context_required: if have_access_context: - stages.append("__get_function(__tmp_context, __tmp_targets[%d])" % ( - self.function_target)) + stages.append("__get_function(__tmp_contexts[%d], __tmp_targets[%d])" % ( + self.function_target, self.function_target)) else: stages.append("__get_function(__CONTEXT_AS_VALUE(__tmp_targets[%d]).value, __tmp_targets[%d])" % ( self.function_target, self.function_target)) @@ -1925,14 +1933,15 @@ # Provide space for the given number of targets. + targets = self.importer.function_targets.get(name) + if self.uses_temp(name, "__tmp_targets"): - targets = self.importer.function_targets.get(name) self.writeline("__attr __tmp_targets[%d];" % targets) + if self.uses_temp(name, "__tmp_contexts"): + self.writeline("__ref __tmp_contexts[%d];" % targets) # Add temporary variable usage details. - if self.uses_temp(name, "__tmp_context"): - self.writeline("__ref __tmp_context;") if self.uses_temp(name, "__tmp_value"): self.writeline("__ref __tmp_value;") if self.uses_temp(name, "__tmp_target_value"):