Skip to content

Commit 19dddfb

Browse files
Patrick-6RalfJung
andcommitted
Implement basic support for running Miri with GenMC.
- Implement memory allocation compatible with GenMC. - Extract address generator struct from Miri's allocator. - Support thread creation and joining. - Support atomic load and store. - Support scheduling through GenMC. - Add tests for GenMC mode. - Add clang-format file for C++ code in Miri. - Update genmc-sys crate license to MIT/Apache to match GenMC dependency. - Add documentation for GenMC mode. Note: this commit depends on changes to GenMC not yet upstreamed to its official repository. Co-authored-by: Ralf Jung <[email protected]>
1 parent 04c6d9b commit 19dddfb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+3572
-429
lines changed

Cargo.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ harness = false
7070

7171
[features]
7272
default = ["stack-cache", "native-lib"]
73-
genmc = ["dep:genmc-sys"] # this enables a GPL dependency!
73+
genmc = ["dep:genmc-sys"]
7474
stack-cache = []
7575
stack-cache-consistency-check = ["stack-cache"]
7676
tracing = ["serde_json"]

doc/genmc.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ Miri-GenMC integrates that model checker into Miri.
99

1010
## Usage
1111

12-
**IMPORTANT: The license of GenMC and thus the `genmc-sys` crate in the Miri repo is currently "GPL-3.0-or-later", so a binary produced with the `genmc` feature is subject to the requirements of the GPL. As long as that remains the case, the `genmc` feature of Miri is OFF-BY-DEFAULT and must be OFF for all Miri releases.**
13-
14-
For testing/developing Miri-GenMC (while keeping in mind the licensing issues):
12+
For testing/developing Miri-GenMC:
1513
- clone the Miri repo.
1614
- build Miri-GenMC with `./miri build --features=genmc`.
1715
- OR: install Miri-GenMC in the current system with `./miri install --features=genmc`
@@ -21,6 +19,21 @@ Basic usage:
2119
MIRIFLAGS="-Zmiri-genmc" cargo miri run
2220
```
2321

22+
Note that `cargo miri test` in GenMC mode is currently not supported.
23+
24+
### Supported Parameters
25+
26+
- `-Zmiri-genmc`: Enable GenMC mode (not required if any other GenMC options are used).
27+
- `-Zmiri-genmc-log=LOG_LEVEL`: Change the log level for GenMC. Default: `warning`.
28+
- `quiet`: Disable logging.
29+
- `error`: Print errors.
30+
- `warning`: Print errors and warnings.
31+
- `tip`: Print errors, warnings and tips.
32+
- If Miri is built with debug assertions, there are additional log levels available (downgraded to `tip` without debug assertions):
33+
- `debug1`: Print revisits considered by GenMC.
34+
- `debug2`: Print the execution graph after every memory access.
35+
- `debug3`: Print reads-from values considered by GenMC.
36+
2437
<!-- FIXME(genmc): explain options. -->
2538

2639
<!-- FIXME(genmc): explain Miri-GenMC specific functions. -->
@@ -57,6 +70,15 @@ The process for obtaining them is as follows:
5770
If you place this directory inside the Miri folder, it is recommended to call it `genmc-src` as that tells `./miri fmt` to avoid
5871
formatting the Rust files inside that folder.
5972

73+
### Formatting the C++ code
74+
75+
For formatting the C++ code we provide a `.clang-format` file in the `genmc-sys` directory.
76+
With `clang-format` installed, run this command to format the c++ files (replace the `-i` with `--dry-run` to just see the changes.):
77+
```
78+
find ./genmc-sys/cpp/ -name "*.cpp" -o -name "*.hpp" | xargs clang-format --style=file:"./genmc-sys/.clang-format" -i
79+
```
80+
NOTE: this is currently not done automatically on pull requests to Miri.
81+
6082
<!-- FIXME(genmc): explain how submitting code to GenMC should be handled. -->
6183

6284
<!-- FIXME(genmc): explain development. -->

genmc-sys/.clang-format

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# .clang-format
2+
3+
BasedOnStyle: LLVM
4+
Standard: c++20
5+
6+
ColumnLimit: 100
7+
AllowShortFunctionsOnASingleLine: Empty
8+
AllowShortIfStatementsOnASingleLine: false
9+
AllowShortLoopsOnASingleLine: false
10+
AllowShortBlocksOnASingleLine: Empty
11+
BreakBeforeBraces: Attach
12+
13+
BinPackArguments: false
14+
BinPackParameters: false
15+
AllowAllParametersOfDeclarationOnNextLine: false
16+
AlwaysBreakAfterReturnType: None
17+
18+
# Force parameters to break and align
19+
AlignAfterOpenBracket: BlockIndent
20+
AllowAllArgumentsOnNextLine: false
21+
22+
# Spacing around braces and parentheses
23+
SpaceBeforeCtorInitializerColon: true
24+
SpaceBeforeInheritanceColon: true
25+
SpaceInEmptyBlock: false
26+
SpacesInContainerLiterals: true
27+
SpacesInParensOptions:
28+
InCStyleCasts: false
29+
InConditionalStatements: false
30+
InEmptyParentheses: false
31+
Other: false
32+
SpacesInSquareBrackets: false
33+
34+
# Brace spacing for initializers
35+
Cpp11BracedListStyle: false
36+
SpaceBeforeCpp11BracedList: true
37+
38+
# Import grouping: group standard, external, and project includes.
39+
IncludeBlocks: Regroup
40+
SortIncludes: true
41+
42+
# Granularity: sort includes per module/file.
43+
IncludeIsMainRegex: '([-_](test|unittest))?$'
44+
45+
# Miscellaneous
46+
SpaceAfterCStyleCast: true
47+
SpaceBeforeParens: ControlStatements
48+
PointerAlignment: Left
49+
IndentCaseLabels: true
50+
IndentWidth: 4
51+
TabWidth: 4
52+
UseTab: Never

genmc-sys/Cargo.toml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
[package]
22
authors = ["Miri Team"]
3-
# The parts in this repo are MIT OR Apache-2.0, but we are linking in
4-
# code from https://github.com/MPI-SWS/genmc which is GPL-3.0-or-later.
5-
license = "(MIT OR Apache-2.0) AND GPL-3.0-or-later"
3+
license = "MIT OR Apache-2.0"
64
name = "genmc-sys"
75
version = "0.1.0"
86
edition = "2024"
97

108
[dependencies]
11-
cxx = { version = "1.0.160", features = ["c++20"] }
9+
cxx = { version = "1.0.173", features = ["c++20"] }
1210

1311
[build-dependencies]
1412
cc = "1.2.30"
1513
cmake = "0.1.54"
1614
git2 = { version = "0.20.2", default-features = false, features = ["https"] }
17-
cxx-build = { version = "1.0.160", features = ["parallel"] }
15+
cxx-build = { version = "1.0.173", features = ["parallel"] }

genmc-sys/build.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ mod downloading {
2626
use super::GENMC_DOWNLOAD_PATH;
2727

2828
/// The GenMC repository the we get our commit from.
29-
pub(crate) const GENMC_GITHUB_URL: &str = "https://github.com/MPI-SWS/genmc.git";
29+
pub(crate) const GENMC_GITHUB_URL: &str = "https://gitlab.inf.ethz.ch/public-plf/genmc.git";
3030
/// The GenMC commit we depend on. It must be available on the specified GenMC repository.
31-
pub(crate) const GENMC_COMMIT: &str = "3438dd2c1202cd4a47ed7881d099abf23e4167ab";
31+
pub(crate) const GENMC_COMMIT: &str = "af9cc9ccd5d412b16defc35dbf36571c63a19c76";
3232

3333
pub(crate) fn download_genmc() -> PathBuf {
3434
let Ok(genmc_download_path) = PathBuf::from_str(GENMC_DOWNLOAD_PATH);
@@ -176,6 +176,11 @@ fn link_to_llvm(config_file: &Path) -> (String, String) {
176176

177177
/// Build the GenMC model checker library and the Rust-C++ interop library with cxx.rs
178178
fn compile_cpp_dependencies(genmc_path: &Path) {
179+
// Give each step a separate build directory to prevent interference.
180+
let out_dir = PathBuf::from(std::env::var("OUT_DIR").as_deref().unwrap());
181+
let genmc_build_dir = out_dir.join("genmc");
182+
let interface_build_dir = out_dir.join("miri_genmc");
183+
179184
// Part 1:
180185
// Compile the GenMC library using cmake.
181186

@@ -186,8 +191,11 @@ fn compile_cpp_dependencies(genmc_path: &Path) {
186191
let enable_genmc_debug = matches!(std::env::var("PROFILE").as_deref().unwrap(), "debug");
187192

188193
let mut config = cmake::Config::new(cmakelists_path);
189-
config.profile(GENMC_CMAKE_PROFILE);
190-
config.define("GENMC_DEBUG", if enable_genmc_debug { "ON" } else { "OFF" });
194+
config
195+
.always_configure(false) // We don't need to reconfigure on subsequent compilation runs.
196+
.out_dir(genmc_build_dir)
197+
.profile(GENMC_CMAKE_PROFILE)
198+
.define("GENMC_DEBUG", if enable_genmc_debug { "ON" } else { "OFF" });
191199

192200
// The actual compilation happens here:
193201
let genmc_install_dir = config.build();
@@ -210,6 +218,13 @@ fn compile_cpp_dependencies(genmc_path: &Path) {
210218
// These definitions are parsed into a cmake list and then printed to the config.h file, so they are ';' separated.
211219
let definitions = llvm_definitions.split(";");
212220

221+
let cpp_files = [
222+
"./cpp/src/MiriInterface/EventHandling.cpp",
223+
"./cpp/src/MiriInterface/Exploration.cpp",
224+
"./cpp/src/MiriInterface/Setup.cpp",
225+
"./cpp/src/MiriInterface/ThreadManagement.cpp",
226+
];
227+
213228
let mut bridge = cxx_build::bridge("src/lib.rs");
214229
// FIXME(genmc,cmake): Remove once the GenMC debug setting is available in the config.h file.
215230
if enable_genmc_debug {
@@ -223,32 +238,27 @@ fn compile_cpp_dependencies(genmc_path: &Path) {
223238
.std("c++23")
224239
.include(genmc_include_dir)
225240
.include(llvm_include_dirs)
226-
.include("./src_cpp")
227-
.file("./src_cpp/MiriInterface.hpp")
228-
.file("./src_cpp/MiriInterface.cpp")
241+
.include("./cpp/include")
242+
.files(&cpp_files)
243+
.out_dir(interface_build_dir)
229244
.compile("genmc_interop");
230245

231246
// Link the Rust-C++ interface library generated by cxx_build:
232247
println!("cargo::rustc-link-lib=static=genmc_interop");
233248
}
234249

235250
fn main() {
236-
// Make sure we don't accidentally distribute a binary with GPL code.
237-
if option_env!("RUSTC_STAGE").is_some() {
238-
panic!(
239-
"genmc should not be enabled in the rustc workspace since it includes a GPL dependency"
240-
);
241-
}
242-
243251
// Select which path to use for the GenMC repo:
244-
let genmc_path = if let Ok(genmc_src_path) = std::env::var("GENMC_SRC_PATH") {
252+
let genmc_path = if let Some(genmc_src_path) = option_env!("GENMC_SRC_PATH") {
245253
let genmc_src_path =
246254
PathBuf::from_str(&genmc_src_path).expect("GENMC_SRC_PATH should contain a valid path");
247255
assert!(
248256
genmc_src_path.exists(),
249257
"GENMC_SRC_PATH={} does not exist!",
250258
genmc_src_path.display()
251259
);
260+
// Rebuild files in the given path change.
261+
println!("cargo::rerun-if-changed={}", genmc_src_path.display());
252262
genmc_src_path
253263
} else {
254264
downloading::download_genmc()
@@ -263,5 +273,5 @@ fn main() {
263273
// cloned (since cargo detects that as a file modification).
264274
println!("cargo::rerun-if-changed={RUST_CXX_BRIDGE_FILE_PATH}");
265275
println!("cargo::rerun-if-changed=./src");
266-
println!("cargo::rerun-if-changed=./src_cpp");
276+
println!("cargo::rerun-if-changed=./cpp");
267277
}

0 commit comments

Comments
 (0)