Skip to content

Commit 55c78bb

Browse files
celinvaladpaco-aws
andauthored
Re-enable RMC to allow users to verify non-public main. (#656)
* Re-enable RMC to allow users to verify non-public main. Users don't usually set their main function to be public and we should enable them to verify their main function. For now, users will have to manually set the create type when running RMC directly. For cargo rmc, this should be automatically set up by cargo. * Update src/tools/dashboard/src/books.rs Co-authored-by: Adrian Palacios <[email protected]> Co-authored-by: Adrian Palacios <[email protected]>
1 parent d63fb1c commit 55c78bb

File tree

8 files changed

+40
-62
lines changed

8 files changed

+40
-62
lines changed

scripts/rmc-rustc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ then
5353
echo ${RMC_PATH}
5454
else
5555
set_rmc_lib_path
56-
RMC_FLAGS="--crate-type=lib \
57-
-Z codegen-backend=gotoc \
56+
RMC_FLAGS="-Z codegen-backend=gotoc \
5857
-Z trim-diagnostic-paths=no \
5958
-Z human_readable_cgu_names \
6059
--cfg=rmc \

scripts/rmc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ def get_config(option):
264264

265265
rustflags = rustc_flags(mangler, symbol_table_passes) + get_config("--rmc-flags").split()
266266
rustc_path = get_config("--rmc-path").strip()
267-
build_cmd = ["cargo", "build", "--lib", "--target-dir", str(target_dir)]
267+
build_cmd = ["cargo", "build", "--target-dir", str(target_dir)]
268268
if build_target:
269269
build_cmd += ["--target", str(build_target)]
270270
build_env = os.environ

src/test/cargo-rmc/simple-main/Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ name = "empty-main"
55
version = "0.1.0"
66
edition = "2018"
77

8-
[lib]
9-
path="src/main.rs"
10-
118
[dependencies]
129

1310
[workspace]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
3-
pub fn main() {
3+
fn main() {
44
assert!(1 == 2);
55
}

src/test/expected/one-assert/test.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
3-
4-
pub fn main() {
3+
// rmc-flags: --function check_assert
4+
// compile-flags: --crate-type lib
5+
#[no_mangle]
6+
pub fn check_assert() {
57
let x: u8 = rmc::nondet();
68
let y = x;
79
assert!(x == y);

src/test/rmc/ArithOperators/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
3-
pub fn main() {
3+
fn main() {
44
let a: u32 = rmc::nondet();
55
assert!(a / 2 <= a);
66
assert!(a / 2 * 2 >= a / 2);

src/tools/compiletest/src/runtest.rs

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,26 +2273,7 @@ impl<'test> TestCx<'test> {
22732273
/// Runs RMC on the test file specified by `self.testpaths.file`. An error
22742274
/// message is printed to stdout if the verification result is not expected.
22752275
fn verify(&self) {
2276-
// Other modes call self.compile_test(...). However, we cannot call it here for two reasons:
2277-
// 1. It calls rustc instead of RMC
2278-
// 2. It may pass some options that do not make sense for RMC
2279-
// So we create our own command to execute RMC and pass it to self.compose_and_run_compiler(...) directly.
2280-
let mut rmc = Command::new("rmc");
2281-
// We cannot pass rustc flags directly to RMC. Instead, we add them
2282-
// to the current environment through the `RUSTFLAGS` environment
2283-
// variable. RMC recognizes the variable and adds those flags to its
2284-
// internal call to rustc.
2285-
if !self.props.compile_flags.is_empty() {
2286-
rmc.env("RUSTFLAGS", self.props.compile_flags.join(" "));
2287-
}
2288-
// Pass the test path along with RMC and CBMC flags parsed from comments at the top of the test file.
2289-
rmc.args(&self.props.rmc_flags)
2290-
.arg("--input")
2291-
.arg(&self.testpaths.file)
2292-
.arg("--cbmc-args")
2293-
.args(&self.props.cbmc_flags);
2294-
self.add_rmc_dir_to_path(&mut rmc);
2295-
let proc_res = self.compose_and_run_compiler(rmc, None);
2276+
let proc_res = self.run_rmc();
22962277
// If the test file contains expected failures in some locations, ensure
22972278
// that verification does indeed fail in those locations
22982279
if proc_res.stdout.contains("EXPECTED FAIL") {
@@ -2390,20 +2371,35 @@ impl<'test> TestCx<'test> {
23902371
self.verify_output(&proc_res, &expected);
23912372
}
23922373

2393-
/// Runs RMC on the test file specified by `self.testpaths.file`. An error
2394-
/// message is printed to stdout if verification output does not contain
2395-
/// the expected output in `expected` file.
2396-
fn run_expected_test(&self) {
2397-
// We create our own command for the same reasons listed in `run_rmc_test` method.
2374+
/// Common method used to run RMC on a single file test.
2375+
fn run_rmc(&self) -> ProcRes {
2376+
// Other modes call self.compile_test(...). However, we cannot call it here for two reasons:
2377+
// 1. It calls rustc instead of RMC
2378+
// 2. It may pass some options that do not make sense for RMC
2379+
// So we create our own command to execute RMC and pass it to self.compose_and_run_compiler(...) directly.
23982380
let mut rmc = Command::new("rmc");
2381+
// We cannot pass rustc flags directly to RMC. Instead, we add them
2382+
// to the current environment through the `RUSTFLAGS` environment
2383+
// variable. RMC recognizes the variable and adds those flags to its
2384+
// internal call to rustc.
2385+
if !self.props.compile_flags.is_empty() {
2386+
rmc.env("RUSTFLAGS", self.props.compile_flags.join(" "));
2387+
}
23992388
// Pass the test path along with RMC and CBMC flags parsed from comments at the top of the test file.
24002389
rmc.args(&self.props.rmc_flags)
24012390
.arg("--input")
24022391
.arg(&self.testpaths.file)
24032392
.arg("--cbmc-args")
24042393
.args(&self.props.cbmc_flags);
24052394
self.add_rmc_dir_to_path(&mut rmc);
2406-
let proc_res = self.compose_and_run_compiler(rmc, None);
2395+
self.compose_and_run_compiler(rmc, None)
2396+
}
2397+
2398+
/// Runs RMC on the test file specified by `self.testpaths.file`. An error
2399+
/// message is printed to stdout if verification output does not contain
2400+
/// the expected output in `expected` file.
2401+
fn run_expected_test(&self) {
2402+
let proc_res = self.run_rmc();
24072403
let expected =
24082404
fs::read_to_string(self.testpaths.file.parent().unwrap().join("expected")).unwrap();
24092405
self.verify_output(&proc_res, &expected);
@@ -2414,16 +2410,7 @@ impl<'test> TestCx<'test> {
24142410
/// abstraction. At a later stage, it should be possible to add command-line
24152411
/// arguments to test specific abstractions and modules.
24162412
fn run_stub_test(&self) {
2417-
let mut rmc = Command::new("rmc");
2418-
// Arguments to choose specific abstraction are currently provided as
2419-
// as rmc-flags in the test file
2420-
rmc.args(&self.props.rmc_flags)
2421-
.arg("--input")
2422-
.arg(&self.testpaths.file)
2423-
.arg("--cbmc-args")
2424-
.args(&self.props.cbmc_flags);
2425-
self.add_rmc_dir_to_path(&mut rmc);
2426-
let proc_res = self.compose_and_run_compiler(rmc, None);
2413+
let proc_res = self.run_rmc();
24272414
if !proc_res.status.success() {
24282415
self.fatal_proc_rec(
24292416
"test failed: expected verification success, got failure",

src/tools/dashboard/src/books.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,6 @@ fn prepend_props(path: &Path, example: &mut Example, config_paths: &mut HashSet<
281281
example.code = format!("{}{}", props, example.code);
282282
}
283283

284-
/// Make the main function of a test public so it can be verified by rmc.
285-
fn pub_main(code: String) -> String {
286-
code.replace("fn main", "pub fn main")
287-
}
288-
289284
/// Extracts examples from the markdown file specified by `par_from`,
290285
/// pre-processes those examples, and saves them in the directory specified by
291286
/// `par_to`.
@@ -296,17 +291,15 @@ fn extract(par_from: &Path, par_to: &Path, config_paths: &mut HashSet<PathBuf>)
296291
for mut example in examples.0 {
297292
apply_diff(par_to, &mut example, config_paths);
298293
example.config.edition = Some(example.config.edition.unwrap_or(Edition::Edition2021));
299-
example.code = pub_main(
300-
rustdoc::doctest::make_test(
301-
&example.code,
302-
None,
303-
false,
304-
&Default::default(),
305-
example.config.edition.unwrap(),
306-
None,
307-
)
308-
.0,
309-
);
294+
example.code = rustdoc::doctest::make_test(
295+
&example.code,
296+
None,
297+
false,
298+
&Default::default(),
299+
example.config.edition.unwrap(),
300+
None,
301+
)
302+
.0;
310303
prepend_props(par_to, &mut example, config_paths);
311304
let rs_path = par_to.join(format!("{}.rs", example.line));
312305
fs::create_dir_all(rs_path.parent().unwrap()).unwrap();

0 commit comments

Comments
 (0)