fn verify(opt: &Opt, package: &str, target: &str) -> CVResult<Status> {
    let beginning = Instant::now();

    // Compile and link the patched file using LTO to generate the entire
    // application in a single LLVM file
    info_at!(
        &opt,
        Verbosity::Informative,
        "  Building {} for verification",
        package
    );
    let bcfile = build(&opt, &package, &target)?;

    info_at!(
        &opt,
        Verbosity::Informative,
        "  Generated LLVM bitcode file {}",
        bcfile.to_string_lossy()
    );

    if let Some(output) = &opt.output {
        std::fs::copy(bcfile, output)?;
        info_at!(
            &opt,
            Verbosity::Informative,
            "Wrote LLVM bitcode file to {}",
            output.to_string_lossy()
        );
        exit(0) // return immediately, do not print status
    }

    // Get the functions we need to verify, and their mangled names.
    let tests = if opt.tests || !opt.test.is_empty() {
        // If using the --tests or --test flags, generate a list of tests and
        // their mangled names.
        info_at!(
            &opt,
            Verbosity::Minor,
            "  Getting list of tests in {}",
            &package
        );
        let mut tests = list_tests(&opt, &target)?;
        if !opt.test.is_empty() {
            tests = tests
                .into_iter()
                .filter(|t| opt.test.iter().any(|f| t.contains(f)))
                .collect();
        }
        if tests.is_empty() {
            Err("  No tests found")?
        }
        let tests: Vec<String> = tests
            .iter()
            .map(|t| format!("{}::{}", package, t))
            .collect();

        // then look up their mangled names in the bcfile
        mangle_functions(&opt, &bcfile, &tests)?
    } else if opt.backend == Backend::Seahorn {
        // Find the entry function (mangled main)
        let mains = mangle_functions(&opt, &bcfile, &[String::from(package) + "::main"])?;
        match mains.as_slice() {
            [(_, _)] => mains,
            [] => Err("  FAILED: can't find the 'main' function")?,
            _ => Err("  FAILED: found more than one 'main' function")?,
        }
    } else {
        vec![("main".to_string(), "main".to_string())]
    };

    // Remove the package name from the function names (important for Klee?) in tests.
    let tests: Vec<_> = tests
        .into_iter()
        .map(|(name, mangled)| {
            if let Some(name) = name.strip_prefix(&format!("{}::", package)) {
                (name.to_string(), mangled)
            } else {
                (name, mangled)
            }
        })
        .collect();

    #[rustfmt::skip]
    info_at!(&opt, Verbosity::Informative, "  Checking {}",
             tests.iter().cloned().unzip::<_, _, Vec<_>, Vec<_>>().0.join(", ")
    );
    info_at!(opt, Verbosity::Trivial, "Mangled: {:?}", tests);

    // For each test function, we run the backend and sift through its
    // output to generate an appropriate status string.
    println!("Running {} test(s)", tests.len());

    let before_verifier = Instant::now();

    let results: Vec<Status> = if opt.jobs > 1 {
        // Run the verification in parallel.

        // `build_global` must not be called more than once!
        // This call configures the thread-pool for `par_iter` below.
        rayon::ThreadPoolBuilder::new()
            .num_threads(opt.jobs)
            .build_global()?;

        tests
            .par_iter() // <- parallelised iterator
            .map(|(name, entry)| verifier_run(&opt, &bcfile, &name, &entry))
            .collect()
    } else {
        // Same as above but without the overhead of rayon
        tests
            .iter() // <- this is the only difference
            .map(|(name, entry)| verifier_run(&opt, &bcfile, &name, &entry))
            .collect()
    };

    // Count pass/fail
    let passes = results.iter().filter(|r| **r == Status::Verified).count();
    let fails = results.len() - passes;
    // randomly pick one failing status (if any)
    let status = results
        .into_iter()
        .find(|r| *r != Status::Verified)
        .unwrap_or(Status::Verified);

    let end = Instant::now();

    // Note use of \n to end line of results in --quiet mode
    println!(
        "\ntest result: {:#}. {} passed; {} failed",
        status, passes, fails
    );

    info_at!(
        &opt,
        Verbosity::Informative,
        "Build {:.3}s",
        before_verifier.duration_since(beginning).as_secs_f32()
    );
    info_at!(
        &opt,
        Verbosity::Informative,
        "Verify {:.3}s",
        end.duration_since(before_verifier).as_secs_f32()
    );
    info_at!(
        &opt,
        Verbosity::Informative,
        "Total {:.3}s",
        end.duration_since(beginning).as_secs_f32()
    );

    Ok(status)
}
/// Compile a Rust crate to generate bitcode and run one of the LLVM verifier
/// backends on the result.
Compile a Rust crate to generate bitcode and run one of the LLVM verifier
backends on the result.
Compile a Rust crate to generate bitcode and run one of the LLVM verifier backends on the result .
fn verify(opt: &Opt, package: &str, target: &str) -> CVResult<Status> {
    let beginning = Instant::now();
    // Compile and link the patched file using LTO to generate the entire
    // application in a single LLVM file
    info_at!(
        &opt,
        Verbosity::Informative,
        "  Building {} for verification",
        package
    );
    let bcfile = build(&opt, &package, &target)?;
    info_at!(
        &opt,
        Verbosity::Informative,
        "  Generated LLVM bitcode file {}",
        bcfile.to_string_lossy()
    );
    if let Some(output) = &opt.output {
        std::fs::copy(bcfile, output)?;
        info_at!(
            &opt,
            Verbosity::Informative,
            "Wrote LLVM bitcode file to {}",
            output.to_string_lossy()
        );
        exit(0) // return immediately, do not print status
    }
    // Get the functions we need to verify, and their mangled names.
    let tests = if opt.tests || !opt.test.is_empty() {
        // If using the --tests or --test flags, generate a list of tests and
        // their mangled names.
        info_at!(
            &opt,
            Verbosity::Minor,
            "  Getting list of tests in {}",
            &package
        );
        let mut tests = list_tests(&opt, &target)?;
        if !opt.test.is_empty() {
            tests = tests
                .into_iter()
                .filter(|t| opt.test.iter().any(|f| t.contains(f)))
                .collect();
        }
        if tests.is_empty() {
            Err("  No tests found")?
        }
        let tests: Vec<String> = tests
            .iter()
            .map(|t| format!("{}::{}", package, t))
            .collect();
        // then look up their mangled names in the bcfile
        mangle_functions(&opt, &bcfile, &tests)?
    } else if opt.backend == Backend::Seahorn {
        // Find the entry function (mangled main)
        let mains = mangle_functions(&opt, &bcfile, &[String::from(package) + "::main"])?;
        match mains.as_slice() {
            [(_, _)] => mains,
            [] => Err("  FAILED: can't find the 'main' function")?,
            _ => Err("  FAILED: found more than one 'main' function")?,
        }
    } else {
        vec![("main".to_string(), "main".to_string())]
    };
    // Remove the package name from the function names (important for Klee?) in tests.
    let tests: Vec<_> = tests
        .into_iter()
        .map(|(name, mangled)| {
            if let Some(name) = name.strip_prefix(&format!("{}::", package)) {
                (name.to_string(), mangled)
            } else {
                (name, mangled)
            }
        })
        .collect();
    #[rustfmt::skip]
    info_at!(&opt, Verbosity::Informative, "  Checking {}",
             tests.iter().cloned().unzip::<_, _, Vec<_>, Vec<_>>().0.join(", ")
    );
    info_at!(opt, Verbosity::Trivial, "Mangled: {:?}", tests);
    // For each test function, we run the backend and sift through its
    // output to generate an appropriate status string.
    println!("Running {} test(s)", tests.len());
    let before_verifier = Instant::now();
    let results: Vec<Status> = if opt.jobs > 1 {
        // Run the verification in parallel.
        // `build_global` must not be called more than once!
        // This call configures the thread-pool for `par_iter` below.
        rayon::ThreadPoolBuilder::new()
            .num_threads(opt.jobs)
            .build_global()?;
        tests
            .par_iter() // <- parallelised iterator
            .map(|(name, entry)| verifier_run(&opt, &bcfile, &name, &entry))
            .collect()
    } else {
        // Same as above but without the overhead of rayon
        tests
            .iter() // <- this is the only difference
            .map(|(name, entry)| verifier_run(&opt, &bcfile, &name, &entry))
            .collect()
    };
    // Count pass/fail
    let passes = results.iter().filter(|r| **r == Status::Verified).count();
    let fails = results.len() - passes;
    // randomly pick one failing status (if any)
    let status = results
        .into_iter()
        .find(|r| *r != Status::Verified)
        .unwrap_or(Status::Verified);
    let end = Instant::now();
    // Note use of \n to end line of results in --quiet mode
    println!(
        "\ntest result: {:#}. {} passed; {} failed",
        status, passes, fails
    );
    info_at!(
        &opt,
        Verbosity::Informative,
        "Build {:.3}s",
        before_verifier.duration_since(beginning).as_secs_f32()
    );
    info_at!(
        &opt,
        Verbosity::Informative,
        "Verify {:.3}s",
        end.duration_since(before_verifier).as_secs_f32()
    );
    info_at!(
        &opt,
        Verbosity::Informative,
        "Total {:.3}s",
        end.duration_since(beginning).as_secs_f32()
    );
    Ok(status)
}
fn verify ( opt : & Opt , package : & str , target : & str ) -> CVResult < Status > { let beginning = Instant :: now ( ) ; // Compile and link the patched file using LTO to generate the entire // application in a single LLVM file info_at ! ( opt Verbosity Informative " " package ) ; let bcfile = build ( & opt , & package , & target ) ? ; info_at ! ( opt Verbosity Informative " " bcfile to_string_lossy ( ) ) ; if let Some ( output ) = & opt . output { std :: fs :: copy ( bcfile , output ) ? ; info_at ! ( opt Verbosity Informative " " output to_string_lossy ( ) ) ; exit ( 0 ) // return immediately, do not print status } // Get the functions we need to verify, and their mangled names. let tests = if opt . tests || ! opt . test . is_empty ( ) { // If using the --tests or --test flags, generate a list of tests and // their mangled names. info_at ! ( opt Verbosity Minor " " package ) ; let mut tests = list_tests ( & opt , & target ) ? ; if ! opt . test . is_empty ( ) { tests = tests . into_iter ( ) . filter ( | t | opt . test . iter ( ) . any ( | f | t . contains ( f ) ) ) . collect ( ) ; } if tests . is_empty ( ) { Err ( " " ) ? } let tests : Vec < String > = tests . iter ( ) . map ( | t | format ! ( " " package t ) ) . collect ( ) ; // then look up their mangled names in the bcfile mangle_functions ( & opt , & bcfile , & tests ) ? } else if opt . backend == Backend :: Seahorn { // Find the entry function (mangled main) let mains = mangle_functions ( & opt , & bcfile , & [ String :: from ( package ) + " " ] ) ? ; match mains . as_slice ( ) { [ ( _ , _ ) ] => mains , [ ] => Err ( " " ) ? , _ => Err ( " " ) ? , } } else { vec ! [ ( " " to_string ( ) " " to_string ( ) ) ] } ; // Remove the package name from the function names (important for Klee?) in tests. let tests : Vec < _ > = tests . into_iter ( ) . map ( | ( name , mangled ) | { if let Some ( name ) = name . strip_prefix ( & format ! ( " " package ) ) { ( name . to_string ( ) , mangled ) } else { ( name , mangled ) } } ) . collect ( ) ; # [ rustfmt :: skip ] info_at ! ( opt Verbosity Informative " " tests iter ( ) cloned ( ) unzip Vec Vec ( ) 0 join ( " " ) ) ; info_at ! ( opt Verbosity Trivial " " tests ) ; // For each test function, we run the backend and sift through its // output to generate an appropriate status string. println ! ( " " tests len ( ) ) ; let before_verifier = Instant :: now ( ) ; let results : Vec < Status > = if opt . jobs > 1 { // Run the verification in parallel. // `build_global` must not be called more than once! // This call configures the thread-pool for `par_iter` below. rayon :: ThreadPoolBuilder :: new ( ) . num_threads ( opt . jobs ) . build_global ( ) ? ; tests . par_iter ( ) // <- parallelised iterator . map ( | ( name , entry ) | verifier_run ( & opt , & bcfile , & name , & entry ) ) . collect ( ) } else { // Same as above but without the overhead of rayon tests . iter ( ) // <- this is the only difference . map ( | ( name , entry ) | verifier_run ( & opt , & bcfile , & name , & entry ) ) . collect ( ) } ; // Count pass/fail let passes = results . iter ( ) . filter ( | r | * * r == Status :: Verified ) . count ( ) ; let fails = results . len ( ) - passes ; // randomly pick one failing status (if any) let status = results . into_iter ( ) . find ( | r | * r != Status :: Verified ) . unwrap_or ( Status :: Verified ) ; let end = Instant :: now ( ) ; // Note use of \n to end line of results in --quiet mode println ! ( " \n " status passes fails ) ; info_at ! ( opt Verbosity Informative " " before_verifier duration_since ( beginning ) as_secs_f32 ( ) ) ; info_at ! ( opt Verbosity Informative " " end duration_since ( before_verifier ) as_secs_f32 ( ) ) ; info_at ! ( opt Verbosity Informative " " end duration_since ( beginning ) as_secs_f32 ( ) ) ; Ok ( status ) }
Compile a Rust crate to generate bitcode and run one of the LLVM verifier
backends on the result.
Compile a Rust crate to generate bitcode and run one of the LLVM verifier backends on the result .
opt
&Opt
package
&str
target
&str
opt
&Opt
package
&str
target
&str