Exemplo n.º 1
0
def generate_llvm_config(args=None, **kwargs):

    constants = []

    # get config full string
    out = mx.OutputCapture()
    mx_sulong.llvm_tool(["llvm-config", "--version"] + list(args), out=out)
    full_version = out.data.strip()
    # NOTE: do not add full version until we need it to avoid regeneration
    # constants.append(("VERSION_FULL", full_version, "Full LLVM version string."))
    # version without suffix
    s = full_version.split("-", 3)
    version = s[0]
    constants.append(("VERSION", version, "LLVM version string."))
    # major, minor, patch
    s = version.split(".", 3)
    major_version, minor_version, patch_version = s[0], s[1], s[2]
    constants.append(("VERSION_MAJOR", int(major_version),
                      "Major version of the LLVM API."))
    constants.append(("VERSION_MINOR", int(minor_version),
                      "Minor version of the LLVM API."))
    constants.append(("VERSION_PATCH", int(patch_version),
                      "Patch version of the LLVM API."))

    file_comment = "GENERATED BY 'mx {}'. DO NOT MODIFY.".format(
        GENERATE_LLVM_CONFIG)

    _write_llvm_config_java(constants, file_comment)
    _write_llvm_config_mx(constants, file_comment)
Exemplo n.º 2
0
 def run_lli(input_f, out_f, err_f):
     additional_clang_input = [
         mx_subst.path_substitutions.substitute(ci)
         for ci in parsed_args.clang_input or []
     ]
     toolchain_clang = mx_sulong._get_toolchain_tool("native,CC")
     mx_sulong.llvm_tool([
         toolchain_clang, "-O0", "-Wno-everything", "-o", tmp_out,
         input_f
     ] + additional_clang_input)
     with open(out_f, 'w') as o, open(err_f, 'w') as e:
         mx.command_function('lli')(parsed_args.lli_arg + [tmp_out],
                                    timeout=lli_timeout,
                                    nonZeroIsFatal=False,
                                    out=o,
                                    err=e)
Exemplo n.º 3
0
def fuzz(args=None, out=None):
    parser = ArgumentParser(prog='mx fuzz', description='')
    parser.add_argument('--seed',
                        help='Seed used for randomness.',
                        metavar='<seed>',
                        type=int,
                        default=int(time.time()))
    parser.add_argument(
        '--size',
        help=
        'Approximate size for the generated testcases in lines of code. (default:  %(default)s)',
        metavar='<size>',
        type=int,
        default=30)
    parser.add_argument(
        '--timeout',
        help=
        'Timeout for running the generated program. (default:  %(default)s)',
        metavar='<timeout>',
        type=int,
        default=10)
    parser.add_argument(
        '--generator',
        help='Tool used for generating the testcases. (default:  %(default)s)',
        choices=("llvm-stress", "csmith"),
        default="llvm-stress")
    parser.add_argument(
        '--nrtestcases',
        help='Number of testcases to be generated. (default:  %(default)s)',
        metavar='<nrtestcases>',
        type=int,
        default=10)
    parser.add_argument('outdir',
                        help='The output directory.',
                        metavar='<outdir>')
    parsed_args = parser.parse_args(args)

    tmp_dir = None
    try:
        tmp_dir = tempfile.mkdtemp()
        tmp_ll = os.path.join(tmp_dir, 'tmp.ll')
        tmp_main_ll = os.path.join(tmp_dir, 'tmp.main.ll')
        tmp_c = os.path.join(tmp_dir, 'tmp.c')
        tmp_out = os.path.join(tmp_dir, 'tmp.out')
        tmp_sulong_out = os.path.join(tmp_dir, 'tmp_sulong_out.txt')
        tmp_bin_out = os.path.join(tmp_dir, 'tmp_bin_out.txt')
        tmp_sulong_err = os.path.join(tmp_dir, 'tmp_sulong_err.txt')
        tmp_bin_err = os.path.join(tmp_dir, 'tmp_bin_err.txt')
        rand = Random(parsed_args.seed)

        passed = 0
        invalid = 0
        gen = []
        for _ in range(parsed_args.nrtestcases):
            toolchain_clang = mx_sulong._get_toolchain_tool("native,CC")
            if parsed_args.generator == "llvm-stress":
                _run_fuzz_tool("llvm-stress", [
                    "-o", tmp_ll, "--size",
                    str(parsed_args.size), "--seed",
                    str(rand.randint(0, 10000000))
                ])
                fuzz_main = os.path.join(
                    mx.dependency('SULONG_TOOLS',
                                  fatalIfMissing=True).get_output(), "src",
                    "fuzzmain.c")
                mx.run([
                    toolchain_clang, "-O0", "-Wno-everything", "-o", tmp_out,
                    tmp_ll, fuzz_main
                ])
                mx_sulong.llvm_tool([
                    "clang", "-O0", "-Wno-everything", "-S", "-emit-llvm",
                    "-o", tmp_main_ll, fuzz_main
                ])
                mx_sulong.llvm_tool(
                    ["llvm-link", "-o", tmp_ll, tmp_ll, tmp_main_ll])
                mx_sulong.llvm_tool(["llvm-dis", "-o", tmp_ll, tmp_ll])
            else:
                csmith_exe = "csmith"
                csmith_headers = mx.get_env('CSMITH_HEADERS', None)
                if not csmith_headers:
                    mx.abort("Environment variable `CSMITH_HEADERS` not set")
                mx.run([
                    csmith_exe, "-o", tmp_c, "--seed",
                    str(rand.randint(0, 10000000))
                ])
                mx.run([
                    toolchain_clang, "-O0", "-Wno-everything",
                    "-I" + csmith_headers, "-o", tmp_out, tmp_c
                ])
                mx_sulong.llvm_tool([
                    "clang", "-O0", "-Wno-everything", "-S", "-emit-llvm",
                    "-I" + csmith_headers, "-o", tmp_ll, tmp_c
                ])
                gen.append((tmp_c, 'autogen.c'))
            timeout = parsed_args.timeout
            with open(tmp_sulong_out, 'w') as o, open(tmp_sulong_err,
                                                      'w') as e:
                mx_sulong.runLLVM([
                    '--llvm.llDebug', '--llvm.traceIR',
                    '--experimental-options', tmp_out
                ],
                                  timeout=timeout,
                                  nonZeroIsFatal=False,
                                  out=o,
                                  err=e)
            with open(tmp_bin_out, 'w') as o, open(tmp_bin_err, 'w') as e:
                try:
                    mx.run([tmp_out], timeout=timeout, out=o, err=e)
                except SystemExit:
                    invalid += 1
                    continue

            if all(
                    filecmp.cmp(sulong_f, bin_f, shallow=False)
                    for sulong_f, bin_f in ((tmp_sulong_out, tmp_bin_out),
                                            (tmp_sulong_err, tmp_bin_err))):
                passed += 1
            else:
                now = str(datetime.datetime.now())
                now = now.replace(":", "_").replace(" ", "_")
                current_out_dir = os.path.join(
                    parsed_args.outdir, now + "_" + parsed_args.generator)
                os.makedirs(current_out_dir)
                gen += [
                    (tmp_ll, 'autogen.ll'),
                    (tmp_out, 'autogen'),
                    (tmp_sulong_out, 'sulong_out.txt'),
                    (tmp_bin_out, 'bin_out.txt'),
                    (tmp_sulong_err, 'sulong_err.txt'),
                    (tmp_bin_err, 'bin_err.txt'),
                ]
                for tmp_f, gen_f_name in gen:
                    shutil.copy(tmp_f, os.path.join(current_out_dir,
                                                    gen_f_name))
    finally:
        if tmp_dir:
            shutil.rmtree(tmp_dir)
    mx.log("Test report")
    mx.log("total testcases: {} seed: {}".format(parsed_args.nrtestcases,
                                                 parsed_args.seed))
    mx.log("interesting testcases: {} invalid testcases: {}".format(
        parsed_args.nrtestcases - invalid - passed, invalid))
Exemplo n.º 4
0
def ll_reduce(args=None, out=None):
    parser = ArgumentParser(prog='mx ll-reduce', description='')
    parser.add_argument(
        '--interestingness-test',
        help=
        'Command which exits with code 1 if a given .ll file is interesting and exits with code 0 otherwise. (default:  %(default)s)',
        metavar='<interestingnesstest>',
        default='mx check-interesting')
    parser.add_argument('--seed',
                        help='Seed used for randomness.',
                        metavar='<seed>',
                        type=int,
                        default=int(time.time()))
    parser.add_argument(
        '--timeout',
        help=
        'Time in seconds until no new reduction operations are permitted to start.',
        metavar='<timeout>',
        type=int,
        default=None)
    parser.add_argument(
        '--timeout-stabilized',
        help=
        'Time in seconds that should pass since no successful minimal reduction operation has been performed until no new reduction operations are permitted to start.',
        metavar='<timeout-stabilized>',
        type=int,
        default=10)
    parser.add_argument(
        '--clang-input',
        help=
        'Additional input files that should be forwarded to clang. No reductions will be performed on these files. Mx path substitutions are enabled.',
        metavar='<clanginputs>',
        nargs='*')
    parser.add_argument('--lli-arg',
                        help='Additional arguments passed to lli.',
                        metavar='<lli arg>',
                        nargs='*')
    parser.add_argument(
        '--output',
        help='The output file. If omitted, <input>.reduced.ll is used.',
        metavar='<output>',
        default=None)
    parser.add_argument('input', help='The input file.', metavar='<input>')
    parsed_args = parser.parse_args(args)

    mx.log("Running ll-reduce with the following configuration:")
    for k, v in vars(parsed_args).items():
        mx.log("{:>30}: {}".format(k, v))

    tmp_dir = None
    nrmutations = 4
    starttime = time.time()
    starttime_stabilized = None
    tmp_ll = None

    try:
        tmp_dir = tempfile.mkdtemp()
        tmp_bc = os.path.join(tmp_dir, 'tmp.bc')
        tmp_ll = os.path.join(tmp_dir, 'tmp1.ll')
        tmp_ll_reduced = os.path.join(tmp_dir, 'tmp2.ll')
        tmp_out = os.path.join(tmp_dir, 'tmp.out')
        tmp_sulong_out_original = os.path.join(tmp_dir,
                                               'tmp_sulong_out_original.txt')
        tmp_sulong_err_original = os.path.join(tmp_dir,
                                               'tmp_sulong_err_original.txt')
        rand = Random(parsed_args.seed)
        lli_timeout = 10

        def count_lines(file_name):
            i = 0
            with open(file_name) as f:
                for i, _ in enumerate(f, 1):
                    pass
            return i

        def run_lli(input_f, out_f, err_f):
            additional_clang_input = [
                mx_subst.path_substitutions.substitute(ci)
                for ci in parsed_args.clang_input or []
            ]
            toolchain_clang = mx_sulong._get_toolchain_tool("native,CC")
            mx_sulong.llvm_tool([
                toolchain_clang, "-O0", "-Wno-everything", "-o", tmp_out,
                input_f
            ] + additional_clang_input)
            with open(out_f, 'w') as o, open(err_f, 'w') as e:
                mx.command_function('lli')(parsed_args.lli_arg + [tmp_out],
                                           timeout=lli_timeout,
                                           nonZeroIsFatal=False,
                                           out=o,
                                           err=e)

        def run_interestingness_test(interestingness_test, input_file):
            return mx.run(shlex.split(interestingness_test) + [input_file],
                          nonZeroIsFatal=False)

        def run_llvm_reduce(nrmutations, input_bc, output_ll):
            reduce_out = mx.OutputCapture()
            try:
                args = [
                    input_bc, "-ignore_remaining_args=1", "-mtriple",
                    "x86_64-unknown-linux-gnu", "-nrmutations",
                    str(nrmutations), "-seed",
                    str(rand.randint(0, 10000000)), "-o", output_ll
                ]
                _run_fuzz_tool("llvm-reduce",
                               args,
                               out=reduce_out,
                               err=reduce_out)
            except SystemExit as se:
                mx.log_error(reduce_out.data)
                mx.abort("Error executing llvm-reduce: {}".format(se))

        shutil.copy(parsed_args.input, tmp_ll)

        # check whether the input is interesting
        orig_interesting = run_interestingness_test(
            parsed_args.interestingness_test, tmp_ll)
        if not orig_interesting:
            mx.abort("Input program is not interesting!")

        run_lli(tmp_ll, tmp_sulong_out_original, tmp_sulong_err_original)
        while True:
            if parsed_args.timeout and time.time(
            ) - starttime > parsed_args.timeout:
                mx.log("Timeout exceeded")
                break
            if starttime_stabilized and time.time(
            ) - starttime_stabilized > parsed_args.timeout_stabilized:
                mx.log("Result stabilized (no more progress)")
                break
            mx_sulong.llvm_tool(["llvm-as", "-o", tmp_bc, tmp_ll])
            mx.log(
                "nrmutations: {} filesize: {} bytes (bc), number of lines {} (ll)"
                .format(nrmutations, os.path.getsize(tmp_bc),
                        count_lines(tmp_ll)))
            run_llvm_reduce(nrmutations, tmp_bc, tmp_ll_reduced)
            reduced_interesting = run_interestingness_test(
                parsed_args.interestingness_test, tmp_ll_reduced)
            if reduced_interesting:
                if not filecmp.cmp(tmp_ll, tmp_ll_reduced, shallow=False):
                    tmp_ll, tmp_ll_reduced = tmp_ll_reduced, tmp_ll
                    nrmutations *= 2
                    starttime_stabilized = None
                    continue
                mx.log("Reduced file is identical to input file!")
            if nrmutations > 1:
                nrmutations //= 2
            else:
                if not starttime_stabilized:
                    starttime_stabilized = time.time()
    finally:
        if tmp_ll and os.path.isfile(tmp_ll):
            result = parsed_args.output or (
                os.path.splitext(parsed_args.input)[0] + ".reduced.ll")
            mx.log("Writing reduced ll file to {}".format(result))
            shutil.copy(tmp_ll, result)
        if tmp_dir:
            shutil.rmtree(tmp_dir)