1.1 --- a/generator.py Thu Jul 05 23:40:53 2018 +0200
1.2 +++ b/generator.py Wed Jul 11 18:33:51 2018 +0200
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 Generate C code from object layouts and other deduced information.
1.6
1.7 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -204,14 +204,12 @@
1.13 # Generate table and structure data.
1.14
1.15 function_instance_attrs = None
1.16 - objects = self.optimiser.attr_table.items()
1.17 + objects = self.optimiser.all_attrs.items()
1.18 objects.sort()
1.19
1.20 self.callables = {}
1.21
1.22 - for ref, indexes in objects:
1.23 - attrnames = self.get_attribute_names(indexes)
1.24 -
1.25 + for ref, attrnames in objects:
1.26 kind = ref.get_kind()
1.27 path = ref.get_origin()
1.28 table_name = encode_tablename(kind, path)
1.29 @@ -613,8 +611,7 @@
1.30 # Obtain the attributes.
1.31
1.32 cls = ref.get_origin()
1.33 - indexes = self.optimiser.attr_table[ref]
1.34 - attrnames = self.get_attribute_names(indexes)
1.35 + attrnames = self.optimiser.all_attrs[ref]
1.36 attrs = self.get_instance_attributes(cls, attrnames)
1.37
1.38 # Set the data, if provided.
1.39 @@ -867,22 +864,6 @@
1.40 num_parameters = len(parameters) + 1
1.41 return num_parameters - (defaults and len(defaults) or 0), num_parameters
1.42
1.43 - def get_attribute_names(self, indexes):
1.44 -
1.45 - """
1.46 - Given a list of attribute table 'indexes', return a list of attribute
1.47 - names.
1.48 - """
1.49 -
1.50 - all_attrnames = self.optimiser.all_attrnames
1.51 - attrnames = []
1.52 - for i in indexes:
1.53 - if i is None:
1.54 - attrnames.append(None)
1.55 - else:
1.56 - attrnames.append(all_attrnames[i])
1.57 - return attrnames
1.58 -
1.59 def get_static_attributes(self, kind, name, attrnames):
1.60
1.61 """
1.62 @@ -987,17 +968,8 @@
1.63 structure of the given 'kind', adding entries to the object 'structure'.
1.64 """
1.65
1.66 - # Populate function instance structures for functions.
1.67 -
1.68 - if ref.has_kind("<function>"):
1.69 - origin = self.function_type
1.70 - structure_ref = Reference("<instance>", self.function_type)
1.71 -
1.72 - # Otherwise, just populate the appropriate structures.
1.73 -
1.74 - else:
1.75 - origin = ref.get_origin()
1.76 - structure_ref = ref
1.77 + structure_ref = self.get_target_structure(ref)
1.78 + origin = structure_ref.get_origin()
1.79
1.80 for attrname in self.optimiser.structures[structure_ref]:
1.81
1.82 @@ -1129,6 +1101,20 @@
1.83
1.84 structure.append(self.encode_member(origin, attrname, attr, kind))
1.85
1.86 + def get_target_structure(self, ref):
1.87 +
1.88 + "Return the target structure type and reference for 'ref'."
1.89 +
1.90 + # Populate function instance structures for functions.
1.91 +
1.92 + if ref.has_kind("<function>"):
1.93 + return Reference("<instance>", self.function_type)
1.94 +
1.95 + # Otherwise, just populate the appropriate structures.
1.96 +
1.97 + else:
1.98 + return ref
1.99 +
1.100 def encode_member(self, path, name, ref, structure_type):
1.101
1.102 """
2.1 --- a/optimiser.py Thu Jul 05 23:40:53 2018 +0200
2.2 +++ b/optimiser.py Wed Jul 11 18:33:51 2018 +0200
2.3 @@ -3,7 +3,7 @@
2.4 """
2.5 Optimise object layouts and generate access instruction plans.
2.6
2.7 -Copyright (C) 2014, 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
2.8 +Copyright (C) 2014, 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This program is free software; you can redistribute it and/or modify it under
2.11 the terms of the GNU General Public License as published by the Free Software
2.12 @@ -413,6 +413,12 @@
2.13 finally:
2.14 f.close()
2.15
2.16 + def is_allocated_attribute(self, attrname):
2.17 +
2.18 + "Return whether 'attrname' is to be allocated in an object."
2.19 +
2.20 + return not attrname.startswith("$t")
2.21 +
2.22 def populate_objects(self):
2.23
2.24 "Populate objects using attribute and usage information."
2.25 @@ -432,8 +438,8 @@
2.26
2.27 # Remove temporary names from structures.
2.28
2.29 - attrnames = filter(lambda x: not x.startswith("$t"), attrnames)
2.30 - self.all_attrs[(objkind, name)] = attrnames
2.31 + attrnames = filter(self.is_allocated_attribute, attrnames)
2.32 + self.all_attrs[Reference(objkind, name)] = attrnames
2.33
2.34 try:
2.35 self.locations = get_allocated_locations(self.all_attrs,
2.36 @@ -495,8 +501,7 @@
2.37
2.38 # Record the structures.
2.39
2.40 - for (objkind, name), attrnames in self.all_attrs.items():
2.41 - key = Reference(objkind, name)
2.42 + for key, attrnames in self.all_attrs.items():
2.43 l = self.structures[key] = [None] * len(attrnames)
2.44
2.45 for attrname in attrnames:
2.46 @@ -719,7 +724,7 @@
2.47
2.48 """
2.49 Get attribute and size information for the object attributes defined by 'd'
2.50 - providing a mapping from (object kind, type name) to attribute names.
2.51 + providing a mapping from object references to attribute names.
2.52
2.53 Return a matrix of attributes (each row entry consisting of column values
2.54 providing attribute names, with value positions corresponding to types
2.55 @@ -736,15 +741,15 @@
2.56 sizes = {}
2.57 objkinds = {}
2.58
2.59 - for objtype, attrnames in d.items():
2.60 - objkind, _name = objtype
2.61 + for ref, attrnames in d.items():
2.62 + objkind = ref.get_kind()
2.63
2.64 for attrname in attrnames:
2.65
2.66 # Record each type supporting the attribute.
2.67
2.68 init_item(attrs, attrname, set)
2.69 - attrs[attrname].add(objtype)
2.70 + attrs[attrname].add(ref)
2.71
2.72 # Maintain a record of the smallest object size supporting the given
2.73 # attribute.
2.74 @@ -761,13 +766,13 @@
2.75
2.76 # Obtain attribute details in order of size and occupancy.
2.77
2.78 - all_objtypes = d.keys()
2.79 + all_refs = d.keys()
2.80
2.81 rsizes = []
2.82 for attrname, size in sizes.items():
2.83 priority = "<instance>" in objkinds[attrname] and 0.5 or 1
2.84 occupied = len(attrs[attrname])
2.85 - key = (priority * size, size, len(all_objtypes) - occupied, attrname)
2.86 + key = (priority * size, size, len(all_refs) - occupied, attrname)
2.87 rsizes.append(key)
2.88
2.89 rsizes.sort()
2.90 @@ -775,20 +780,20 @@
2.91 # Make a matrix of attributes.
2.92
2.93 matrix = {}
2.94 - for attrname, objtypes in attrs.items():
2.95 + for attrname, refs in attrs.items():
2.96
2.97 # Traverse the object types, adding the attribute name if the object
2.98 # type supports the attribute, adding None otherwise.
2.99
2.100 row = []
2.101 - for objtype in all_objtypes:
2.102 - if objtype in objtypes:
2.103 + for ref in all_refs:
2.104 + if ref in refs:
2.105 row.append(attrname)
2.106 else:
2.107 row.append(None)
2.108 matrix[attrname] = row
2.109
2.110 - return matrix, all_objtypes, rsizes
2.111 + return matrix, all_refs, rsizes
2.112
2.113 def get_parameters_and_sizes(d):
2.114