From 766ff6802e99080c2336bb8abfac9a4db897b7ee Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 16 Sep 2021 20:04:49 +0200 Subject: [PATCH] Calculate a score for fields The score is the access cost on Cortex-M0+ thumb builds, expressed in instructions. This commit does not have any provisions to calculate different scores based on the target architecture, so it's only meaningful when running this script with `-t armv6m-unknown-eabi`. Go with a simple model: direct access is possible for the first 128 fields of a structure, direct access costs 1 instruction, indirect access costs 3 instructions. The score calculation assumes that each lexical use in the source code corresponds to one access. This does not take into account unused code, inlining, uses from application code, etc. Signed-off-by: Gilles Peskine --- scripts/field_report.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/scripts/field_report.py b/scripts/field_report.py index a6fe932b6d..858c24f125 100755 --- a/scripts/field_report.py +++ b/scripts/field_report.py @@ -52,6 +52,21 @@ class FieldInfo: def uses(self) -> int: return self.lexical_uses + def is_indirect(self) -> bool: + """Whether access to this field is indirect on ARM Cortex-M0+.""" + word_offset = self.offset // self.align + return word_offset >= 128 + + def score(self) -> int: + """A field's score is an estimate of its access cost. + + The cost is calculated as the number of instructions needed to + access the field on ARM Cortex-M0+, multiplied by the number of uses + of the field inside the library. + """ + cost_per_use = 1 + 2 * self.is_indirect() + return self.uses() * cost_per_use + class Ast: """Abstract representation of the source code.""" @@ -166,12 +181,12 @@ class Ast: prefix: str, field: FieldInfo) -> None: """Print information about a structure field. - Format: .,,,,use_count + Format: .,,,,, """ - out.write('{},{},{},{},{}\n'.format( + out.write('{},{},{},{},{},{}\n'.format( prefix + field.node.spelling, field.size, field.align, field.offset, - field.uses() + field.uses(), field.score() )) def report_fields(self, out: typing_util.Writable) -> None: