Esempio n. 1
0
    def analyze_constraints(self, program, model, jsengine, runs, threads,
                            jsprogram, use_alloy):
        matched = None
        unmatched = None

        config = Config()
        config.command = jsengine
        config.input_file = jsprogram
        config.threads = threads
        config.number = runs
        config.silent = True
        config.models = True

        if use_alloy:
            labelling_vars = [y[2] for y in [x.split(" ") for x in model.split("\n") if len(x.split(" "))>2] \
                              if y[2][:len(LABELLING_VAR_PREF)] == LABELLING_VAR_PREF]
        else:
            labelling_vars = [x.split(" ")[0] for x in model.split("\n") \
                              if x[:len(LABELLING_VAR_PREF)] == LABELLING_VAR_PREF]

        if len(labelling_vars) == 0:
            Logger.error("No labelling vars defined")
            return None

        if use_alloy:
            self.al_consamanager.labelling_vars = labelling_vars
        else:
            self.c4_consamanager.labelling_vars = labelling_vars

        (matched, unmatched) = self.__load_outputs(config.number, self.outfile,
                                                   jsengine)

        if (matched is None) and (unmatched is None):
            timer = Logger.start_timer("Run Litmus")
            (matched, unmatched) = run_litmus(config)
            Logger.stop_timer(timer)
            self.__save_outputs(config.number, self.outfile, jsengine, matched,
                                unmatched)

        timer = Logger.start_timer("Analyze output")

        parser = BeParser()
        mexecs = parser.executions_from_string("\n".join(matched), program)
        uexecs = parser.executions_from_string("\n".join(unmatched), program)

        Logger.log(" -> Found %s matched models" % (len(matched)), 0)
        Logger.log(" -> Found %s unmatched models" % (len(unmatched)), 0)

        if len(unmatched) == 0:
            Logger.error("No unmatched models")
            Logger.stop_timer(timer)
            return None

        rels = [x for x in RELATIONS if x != AO]

        matched = self.al_encoder.print_assert_exl_execs(mexecs, rels) if use_alloy else \
                  self.c4_encoder.print_assert_exl_execs(mexecs, rels)
        unmatched = self.al_encoder.print_assert_exl_execs(uexecs, rels) if use_alloy else \
                    self.c4_encoder.print_assert_exl_execs(uexecs, rels)

        objs = []
        Logger.log("\nMatched models analysis", 0)
        Logger.msg("Solving... ", 0)

        if use_alloy:
            vmodel = "\n".join([
                model, matched,
                self.al_encoder.print_run_condition(program, True)
            ])
            objs = self.al_solver.compute_models(vmodel, self.al_consamanager,
                                                 objs)
            mmodels = " | ".join([x[1] for x in objs])
        else:
            vmodel = "%s\n%s" % (model, matched)
            objs = self.c4_solver.compute_models(vmodel, self.c4_consamanager,
                                                 objs)
            mmodels = " | ".join(objs)

        Logger.log(" DONE", 0)
        mmodels = self.bsolver.simplify(mmodels, True)
        self.__print_models(mmodels)

        objs = []
        Logger.log("Unmatched models analysis", 0)
        Logger.msg("Solving... ", 0)

        if use_alloy:
            vmodel = "\n".join([
                model, unmatched,
                self.al_encoder.print_run_condition(program, True)
            ])
            objs = self.al_solver.compute_models(vmodel, self.al_consamanager,
                                                 objs)
            nmodels = " | ".join([x[1] for x in objs])
        else:
            vmodel = "%s\n%s" % (model, unmatched)
            objs = self.c4_solver.compute_models(vmodel, self.c4_consamanager,
                                                 objs)
            nmodels = " | ".join(objs)

        Logger.log(" DONE", 0)
        nmodels = self.bsolver.simplify(nmodels, True)
        self.__print_models(nmodels)

        Logger.log("Difference analysis (exist support(matched) in unmatched)",
                   0)
        diffmodels = self.bsolver.support_exist(" | ".join(mmodels),
                                                " | ".join(nmodels), True)
        self.__print_models(diffmodels)

        self.user_defined_analyses(mmodels, nmodels)

        Logger.stop_timer(timer)
        return (mmodels, nmodels, diffmodels)
Esempio n. 2
0
def main(args):
    parser = argparse.ArgumentParser(
        description='EMME: ECMAScript Memory Model Evaluator',
        formatter_class=RawTextHelpFormatter)

    parser.add_argument('input_file',
                        metavar='program',
                        type=str,
                        help='the input file describing the program')

    jsprinters = [
        " - \"%s\": %s" % (x.get_name(), x.get_desc())
        for x in PrintersFactory.get_printers_by_type(PrinterType.PROGRAMS)
    ]
    config = Config()

    # Files generation

    parser.set_defaults(jsprinter=config.jsprinter)
    parser.add_argument(
        '-p',
        '--jsprinter',
        metavar='jsprinter',
        type=str,
        nargs='?',
        help='select the JS printer between (Default is \"%s\"):\n%s' %
        (config.jsprinter, "\n".join(jsprinters)))

    parser.set_defaults(jsdir=None)
    parser.add_argument(
        '-d',
        '--jsdir',
        metavar='jsdir',
        type=str,
        nargs='?',
        help=
        'directory where to store all JS programs. (Default is the same as the input file)'
    )

    parser.set_defaults(graphviz=False)
    parser.add_argument(
        '-g',
        '--graphviz',
        dest='graphviz',
        action='store_true',
        help=
        "generates the png files of each execution (requires neato). (Default is \"%s\")"
        % False)

    parser.set_defaults(relations=config.printing_relations)
    parser.add_argument(
        '-r',
        '--relations',
        metavar='relations',
        type=str,
        nargs='?',
        help=
        'a (comma separated) list of relations to consider in the graphviz file.\nKeyword \"%s\" means all.'
        % ALL)

    parser.set_defaults(prefix=None)
    parser.add_argument(
        '-x',
        '--prefix',
        metavar='prefix',
        type=str,
        nargs='?',
        help=
        'directory where to store the results. (Default is the same as the input file)'
    )

    # Possible analyses

    parser.set_defaults(synth=False)
    parser.add_argument(
        '--synth',
        dest='synth',
        action='store_true',
        help="enables equivalent programs synthesis. (Default is \"%s\")" %
        False)

    parser.set_defaults(unmatched=False)
    parser.add_argument(
        '--unmatched',
        dest='unmatched',
        action='store_true',
        help="enables unmatched outputs analysis. (Default is \"%s\")" % False)

    parser.set_defaults(jsengine=None)
    parser.add_argument(
        '--jsengine',
        metavar='jsengine',
        type=str,
        nargs='?',
        help=
        'the command used to call the JavaScript engine, to use with \"--unmatched\".'
    )

    parser.set_defaults(runs=10)
    parser.add_argument(
        '-n',
        '--runs',
        metavar='runs',
        type=str,
        help=
        'number of runs for the unmatched outputs analysis, to use with \"--unmatched\".\n(Default is \"10\")'
    )

    # Solvers selection

    parser.set_defaults(use_cvc4=False)
    parser.add_argument(
        '-c',
        '--use-cvc4',
        dest='use_cvc4',
        action='store_true',
        help="relies on CVC4 instead of Alloy Analyzer. (Default is \"%s\")" %
        False)

    parser.set_defaults(best=False)
    parser.add_argument(
        '-b',
        '--best',
        dest='best',
        action='store_true',
        help=
        "relies on CVC4 or Alloy Analyzer for best performance. (Default is \"%s\")"
        % False)

    # Simple configurations

    parser.set_defaults(verbosity=1)
    parser.add_argument('-v',
                        dest='verbosity',
                        metavar="verbosity",
                        type=int,
                        help="verbosity level. (Default is \"%s\")" % 1)

    parser.set_defaults(nexecs=-1)
    parser.add_argument(
        '-e',
        '--max-executions',
        dest='nexecs',
        metavar='nexecs',
        type=int,
        help='maximum number of executions. (Default is \"unlimited\")')

    parser.set_defaults(force_solving=False)
    parser.add_argument(
        '-f',
        '--force-solving',
        dest='force_solving',
        action='store_true',
        help=
        "forces the solving part by discharging the previous models. (Default is \"%s\")"
        % False)

    parser.set_defaults(skip_solving=False)
    parser.add_argument('-k',
                        '--skip-solving',
                        dest='skip_solving',
                        action='store_true',
                        help="skips the solving part. (Default is \"%s\")" %
                        False)

    parser.set_defaults(silent=False)
    parser.add_argument('-l',
                        '--silent',
                        dest='silent',
                        action='store_true',
                        help="silent mode. (Default is \"%s\")" % False)

    parser.set_defaults(check_sat=False)
    parser.add_argument(
        '-s',
        '--only-sat',
        dest='check_sat',
        action='store_true',
        help="performs only the satisfiability checking. (Default is \"%s\")" %
        False)

    parser.set_defaults(only_model=False)
    parser.add_argument(
        '-m',
        '--only-model',
        dest='only_model',
        action='store_true',
        help="exits right after the model generation. (Default is \"%s\")" %
        False)

    # Advanced configurations

    parser.set_defaults(threads=1)
    parser.add_argument(
        '-j',
        '--threads',
        metavar='number',
        type=int,
        help='number of threads - EXPERIMENTAL. (Default is \"1\")')

    parser.set_defaults(debug=False)
    parser.add_argument('--debug',
                        dest='debug',
                        action='store_true',
                        help="enables debugging setup. (Default is \"%s\")" %
                        False)

    parser.set_defaults(time=False)
    parser.add_argument(
        '-t',
        '--time',
        dest='time',
        action='store_true',
        help="enables time debugging setup. (Default is \"%s\")" % False)

    parser.set_defaults(no_expand_bounded_sets=False)
    parser.add_argument(
        '--no-exbounded',
        dest='no_expand_bounded_sets',
        action='store_true',
        help=
        "disables the bounded sets quantifier expansion. (Default is \"%s\")" %
        False)

    parser.set_defaults(defines=None)
    parser.add_argument(
        '--defines',
        metavar='defines',
        type=str,
        nargs='?',
        help='the set of preprocessor\'s defines. (Default is none)')

    parser.set_defaults(preproc=CPP)
    parser.add_argument(
        '--preproc',
        metavar='preproc',
        type=str,
        nargs='?',
        help='the memory model preprocessor. (Default is \"%s\")' % CPP)

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    args = parser.parse_args(args)

    prefix = args.prefix

    if not prefix:
        prefix = args.input_file.split("/")
        prefix[-1] = prefix[-1].split(".")[0]
        prefix = "/".join(prefix)
        prefix += "/"

    if not os.path.exists(args.input_file):
        print("File not found: \"%s\"" % args.input_file)
        return 1

    config.inputfile = args.input_file
    config.prefix = prefix
    config.preproc = args.preproc
    config.expand_bounded_sets = not args.no_expand_bounded_sets
    config.verbosity = args.verbosity
    config.defines = args.defines
    config.sat = args.check_sat
    config.only_model = args.only_model
    config.skip_solving = args.skip_solving
    config.printing_relations = args.relations
    config.graphviz = args.graphviz
    config.jsdir = args.jsdir
    config.debug = args.debug
    config.force_solving = args.force_solving
    config.threads = args.threads
    config.jsengine = args.jsengine
    config.runs = args.runs
    config.nexecs = args.nexecs
    config.use_alloy = not args.use_cvc4
    config.unmatched = args.unmatched
    config.time = args.time

    if args.jsprinter in [
            str(x.get_name())
            for x in PrintersFactory.get_printers_by_type(PrinterType.PROGRAMS)
    ]:
        config.jsprinter = args.jsprinter
    else:
        Logger.error("Printer \"%s\" not found" % (args.jsprinter))

    if config.unmatched and not config.jsengine:
        Logger.error("JavaScript engine not specified")
        return 1

    if not config.use_alloy:
        try:
            import CVC4
        except Exception:
            Logger.error("Error importing CVC4 module")
            return 1

    if args.synth and args.best:
        config.hybrid = True

    if not args.synth and not args.unmatched and args.best:
        config.use_alloy = True

    if args.silent:
        config.verbosity = 0

    if args.relations == ALL:
        config.printing_relations = None

    Logger.verbosity = config.verbosity

    Logger.log("** Processing file \"%s\" **" % (config.inputfile), -1)

    try:
        Logger.time = config.time
        ret = -1
        ret = analyze_program(config)

        if ret == 0 and args.synth:
            ret = synth_program(config)
        if ret == 0 and args.unmatched:
            ret = unmatched_analysis(config)

        #cleanup
        if not config.debug:
            del_file(config.block_type)
            del_file(config.bound_int)
            del_file(config.alloy_model)
            del_file(config.cvc_model)
            del_file(config.cvc_model_ex)
            del_file(config.id_type)
            del_file(config.instance)

        Logger.log("\nExiting...", 0)
        return ret
    except Exception as e:
        if config.debug: raise
        print("\nERROR! Run with --debug option for more information")
        return 1