Beispiel #1
0
    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
Beispiel #2
0
    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