def graph_call(self, graph, fixed, args_hs, tsgraph_accum=None, hs_callable=None): input_args_hs = list(args_hs) graph = self.get_graph_for_call(graph, fixed, input_args_hs) if tsgraph_accum is not None: tsgraph_accum.append(graph) # save this if the caller cares # propagate fixing of arguments in the function to the caller for inp_arg_hs, arg_hs in zip(input_args_hs, args_hs): if isinstance(arg_hs, hintmodel.SomeLLAbstractConstant): assert len(inp_arg_hs.origins) == 1 [o] = inp_arg_hs.origins.keys() if o.read_fixed(): for o in arg_hs.origins: o.set_fixed() hs_res = self.annotator.recursivecall(graph, self.position_key, input_args_hs) # look on which input args the hs_res result depends on if isinstance(hs_res, hintmodel.SomeLLAbstractConstant): if (hs_callable is not None and not isinstance(hs_callable, hintmodel.SomeLLAbstractConstant)): hs_res = hintmodel.variableoftype(hs_res.concretetype, hs_res.deepfrozen) else: deps_hs = [] for hs_inputarg, hs_arg in zip(input_args_hs, args_hs): if isinstance(hs_inputarg, hintmodel.SomeLLAbstractConstant): assert len(hs_inputarg.origins) == 1 [o] = hs_inputarg.origins.keys() if o in hs_res.origins: deps_hs.append(hs_arg) if fixed: deps_hs.append(hs_res) hs_res = hintmodel.reorigin(hs_res, hs_callable, *deps_hs) return hs_res
def compute_at_fixpoint(self): binding = self.annotator.binding # for the entry point, we need to remove the 'myorigin' of # the input arguments (otherwise they will always be green, # as there is no call to the entry point to make them red) tsgraph = self.annotator.translator.graphs[0] for v in tsgraph.getargs(): hs_arg = binding(v) if isinstance(hs_arg, hintmodel.SomeLLAbstractConstant): hs_arg.myorigin = None # for convenience, force the return var to be red too, as # the timeshifter doesn't support anything else if self.annotator.policy.entrypoint_returns_red: v = tsgraph.getreturnvar() hs_red = hintmodel.variableoftype(v.concretetype) self.annotator.setbinding(v, hs_red) # propagate the green/red constraints log.event("Computing maximal green set...") greenorigindependencies = {} callreturndependencies = {} for origin in self.originflags.values(): origin.greenargs = True origin.record_dependencies(greenorigindependencies, callreturndependencies) while True: progress = False # check all calls to see if they are green calls or not for origin, graphs in callreturndependencies.items(): if self.is_green_call(origin.spaceop): pass # green call => don't force spaceop.result to red else: # non-green calls: replace the dependency with a regular # dependency from graph.getreturnvar() to spaceop.result del callreturndependencies[origin] retdeps = greenorigindependencies.setdefault(origin, []) for graph in graphs: retdeps.append(graph.getreturnvar()) # propagate normal dependencies for origin, deps in greenorigindependencies.items(): for v in deps: if not binding(v).is_green(): # not green => force the origin to be red too origin.greenargs = False del greenorigindependencies[origin] progress = True break if not progress: break for callfamily in self.tsgraph_maximal_call_families.infos(): if len(callfamily.tsgraphs) > 1: # if at least one graph in the family returns a red, # we force a red as the return of all of them returns_red = False for graph in callfamily.tsgraphs: if not binding(graph.getreturnvar()).is_green(): returns_red = True if returns_red: for graph in callfamily.tsgraphs: v = graph.getreturnvar() hs_red = hintmodel.variableoftype(v.concretetype) self.annotator.setbinding(v, hs_red) # compute and cache the signature of the graphs before they are # modified by further code ha = self.annotator for tsgraph in ha.translator.graphs: sig_hs = ([ha.binding(v) for v in tsgraph.getargs()], ha.binding(tsgraph.getreturnvar())) self.tsgraphsigs[tsgraph] = sig_hs