First cut at constructing a call graph.

This commit is contained in:
Chris Pressey 2019-10-21 14:03:35 +01:00
parent 5912bf2684
commit 87a2f70092
3 changed files with 20 additions and 0 deletions

View File

@ -50,6 +50,13 @@ def process_input_files(filenames, options):
sys.stdout.write(json.dumps(analyzer.exit_contexts_map, indent=4, sort_keys=True, separators=(',', ':')))
sys.stdout.write("\n")
if options.dump_callgraph:
for routine in program.routines:
sys.stdout.write('-----------\n')
sys.stdout.write('{}\n'.format(routine.name))
for called_routine in routine.called_routines:
sys.stdout.write(' {}\n'.format(called_routine.name))
compilation_roster = None
if options.optimize_fallthru:
from sixtypical.fallthru import FallthruAnalyzer
@ -161,6 +168,11 @@ if __name__ == '__main__':
action="store_true",
help="Dump the ordered fallthru map, in JSON, to stdout after analyzing the program."
)
argparser.add_argument(
"--dump-callgraph",
action="store_true",
help="Dump the call graph, in JSON, to stdout after analyzing the program."
)
argparser.add_argument(
"--parse-only",
action="store_true",

View File

@ -143,6 +143,7 @@ class Analyzer(object):
for routine in program.routines:
context = self.analyze_routine(routine)
routine.encountered_gotos = list(context.encountered_gotos()) if context else []
routine.called_routines = list(context.called_routines) if context else []
def analyze_routine(self, routine):
assert isinstance(routine, Routine)
@ -515,6 +516,7 @@ class Analyzer(object):
type = self.get_type(instr.location)
if not isinstance(type, (RoutineType, VectorType)):
raise TypeMismatchError(instr, instr.location.name)
context.mark_as_called(instr.location)
if isinstance(type, VectorType):
type = type.of_type
for ref in type.inputs:

View File

@ -35,6 +35,7 @@ class AnalysisContext(object):
self._terminated = False
self._gotos_encountered = set()
self._pointer_assoc = dict()
self.called_routines = set()
for ref in inputs:
if self.is_constant(ref):
@ -79,6 +80,7 @@ class AnalysisContext(object):
c._writeable = set(self._writeable)
c._pointer_assoc = dict(self._pointer_assoc)
c._gotos_encountered = set(self._gotos_encountered)
c.called_routines = set(self.called_routines)
return c
def update_from(self, other):
@ -94,6 +96,7 @@ class AnalysisContext(object):
self._writeable = set(other._writeable)
self._terminated = other._terminated
self._pointer_assoc = dict(other._pointer_assoc)
self.called_routines = set(other.called_routines)
def each_meaningful(self):
for ref in self._range.keys():
@ -326,3 +329,6 @@ class AnalysisContext(object):
return self.symtab.fetch_local_type(self.routine.name, ref.name).max_range
else:
return self.symtab.fetch_global_type(ref.name).max_range
def mark_as_called(self, routine):
self.called_routines.add(routine)