-
Notifications
You must be signed in to change notification settings - Fork 391
Add minimal functionality for using GenMC mode #4506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
3fc854d
7fcd173
af9d846
9d7e964
1631c9d
d9a6629
c968c94
24e42d0
61377c8
8579860
44f4f75
b02082b
4eac4f3
0d6db1d
d65d9fb
454bc94
7fb35c3
fb7f726
9578b61
b63acb5
ba5070d
8155688
1114119
b68f8ae
e235cf6
2a97d2c
bc9c428
e223cd9
e87d751
cbd64b9
96b1b54
97444a6
63199f1
46d0673
88ea77d
9ca1a0c
e7a3b98
409164b
74f1fa1
d6d4584
e112b22
a42452b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,32 @@ | ||
pub use cxx::UniquePtr; | ||
|
||
pub use self::ffi::*; | ||
|
||
/// Defined in "genmc/src/Support/SAddr.hpp" | ||
/// FIXME(genmc): `getGlobalAllocStaticMask()` is used to ensure the constant is consistent between Miri and GenMC, | ||
/// but if https://github.com/dtolnay/cxx/issues/1051 is fixed we could share the constant directly. | ||
pub const GENMC_GLOBAL_ADDRESSES_MASK: u64 = 1 << 63; | ||
|
||
#[repr(transparent)] | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub struct GenmcThreadId(pub i32); | ||
|
||
pub const GENMC_MAIN_THREAD_ID: GenmcThreadId = GenmcThreadId(0); | ||
|
||
impl GenmcScalar { | ||
pub const UNINIT: Self = Self { value: 0, is_init: false }; | ||
/// GenMC expects a value for all stores, but we cannot always provide one (e.g., non-atomic writes). | ||
/// FIXME(genmc): remove this if a permanent fix is ever found. | ||
pub const DUMMY: Self = Self::from_u64(0xDEADBEEF); | ||
Patrick-6 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
pub const fn from_u64(value: u64) -> Self { | ||
Self { value, is_init: true } | ||
} | ||
} | ||
|
||
impl Default for GenmcParams { | ||
fn default() -> Self { | ||
Self { | ||
print_random_schedule_seed: false, | ||
do_symmetry_reduction: false, | ||
// FIXME(GenMC): Add defaults for remaining parameters | ||
} | ||
Self { print_random_schedule_seed: false, do_symmetry_reduction: false } | ||
} | ||
} | ||
|
||
|
@@ -20,11 +40,118 @@ mod ffi { | |
pub do_symmetry_reduction: bool, | ||
// FIXME(GenMC): Add remaining parameters. | ||
} | ||
|
||
#[derive(Debug)] | ||
enum ActionKind { | ||
/// Any Mir terminator that's atomic and has load semantics. | ||
Load, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment should make it clear that "load" is "maybe load" and "non-load" is "definitely not a load". |
||
/// Anything that's not a `Load`. | ||
NonLoad, | ||
} | ||
|
||
#[derive(Debug)] | ||
enum MemOrdering { | ||
NotAtomic = 0, | ||
Relaxed = 1, | ||
// We skip 2 in case we support consume. | ||
Acquire = 3, | ||
Release = 4, | ||
AcquireRelease = 5, | ||
SequentiallyConsistent = 6, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
struct GenmcScalar { | ||
value: u64, | ||
is_init: bool, | ||
} | ||
Comment on lines
+63
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have this type with the |
||
|
||
/**** \/ Result & Error types \/ ****/ | ||
|
||
// FIXME(genmc): Rework error handling (likely requires changes on the GenMC side). | ||
|
||
#[must_use] | ||
#[derive(Debug)] | ||
struct LoadResult { | ||
is_read_opt: bool, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this mean? A comment would be good. |
||
read_value: GenmcScalar, | ||
error: UniquePtr<CxxString>, | ||
} | ||
|
||
#[must_use] | ||
#[derive(Debug)] | ||
struct StoreResult { | ||
error: UniquePtr<CxxString>, | ||
isCoMaxWrite: bool, | ||
} | ||
Comment on lines
+71
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These will need to be reworked, but I'm waiting on a review of a PR with changes to how GenMC does error handling. |
||
|
||
/**** /\ Result & Error types /\ ****/ | ||
|
||
unsafe extern "C++" { | ||
include!("MiriInterface.hpp"); | ||
|
||
type MemOrdering; | ||
|
||
// Types for Scheduling queries: | ||
type ActionKind; | ||
|
||
// Result / Error types: | ||
type LoadResult; | ||
type StoreResult; | ||
|
||
type GenmcScalar; | ||
|
||
type MiriGenMCShim; | ||
|
||
fn createGenmcHandle(config: &GenmcParams) -> UniquePtr<MiriGenMCShim>; | ||
fn getGlobalAllocStaticMask() -> u64; | ||
|
||
fn handleExecutionStart(self: Pin<&mut MiriGenMCShim>); | ||
fn handleExecutionEnd(self: Pin<&mut MiriGenMCShim>) -> UniquePtr<CxxString>; | ||
|
||
fn handleLoad( | ||
self: Pin<&mut MiriGenMCShim>, | ||
thread_id: i32, | ||
address: u64, | ||
size: u64, | ||
memory_ordering: MemOrdering, | ||
old_value: GenmcScalar, | ||
) -> LoadResult; | ||
fn handleStore( | ||
self: Pin<&mut MiriGenMCShim>, | ||
thread_id: i32, | ||
address: u64, | ||
size: u64, | ||
value: GenmcScalar, | ||
old_value: GenmcScalar, | ||
memory_ordering: MemOrdering, | ||
) -> StoreResult; | ||
|
||
fn handleMalloc( | ||
self: Pin<&mut MiriGenMCShim>, | ||
thread_id: i32, | ||
size: u64, | ||
alignment: u64, | ||
) -> u64; | ||
fn handleFree(self: Pin<&mut MiriGenMCShim>, thread_id: i32, address: u64, size: u64); | ||
|
||
fn handleThreadCreate(self: Pin<&mut MiriGenMCShim>, thread_id: i32, parent_id: i32); | ||
fn handleThreadJoin(self: Pin<&mut MiriGenMCShim>, thread_id: i32, child_id: i32); | ||
fn handleThreadFinish(self: Pin<&mut MiriGenMCShim>, thread_id: i32, ret_val: u64); | ||
fn handleThreadKill(self: Pin<&mut MiriGenMCShim>, thread_id: i32); | ||
|
||
/**** Scheduling ****/ | ||
fn scheduleNext( | ||
self: Pin<&mut MiriGenMCShim>, | ||
curr_thread_id: i32, | ||
curr_thread_next_instr_kind: ActionKind, | ||
) -> i64; | ||
|
||
fn getBlockedExecutionCount(self: &MiriGenMCShim) -> u64; | ||
fn getExploredExecutionCount(self: &MiriGenMCShim) -> u64; | ||
|
||
/// Check whether there are more executions to explore. | ||
/// If there are more executions, this method prepares for the next execution and returns `true`. | ||
fn isExplorationDone(self: Pin<&mut MiriGenMCShim>) -> bool; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this has to be defined here.