1
- use rustc_middle:: throw_unsup_format;
1
+ use rustc_middle:: { throw_unsup_format, ty } ;
2
2
use tracing:: debug;
3
3
4
- use crate :: concurrency:: genmc:: MAX_ACCESS_SIZE ;
5
4
use crate :: concurrency:: thread:: EvalContextExt as _;
6
- use crate :: {
7
- BlockReason , InterpResult , MachineCallback , MiriInterpCx , OpTy , Scalar , UnblockKind ,
8
- VisitProvenance , VisitWith , callback, interp_ok, throw_ub_format,
9
- } ;
5
+ use crate :: * ;
10
6
11
7
// Handling of code intercepted by Miri in GenMC mode, such as assume statement or `std::sync::Mutex`.
12
8
13
- #[ derive( Clone , Copy ) ]
14
- struct MutexMethodArgs {
15
- address : u64 ,
16
- size : u64 ,
17
- }
18
-
19
9
impl < ' tcx > EvalContextExtPriv < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
20
10
trait EvalContextExtPriv < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
21
- fn parse_mutex_method_args (
11
+ /// Small helper to get the arguments of an intercepted function call.
12
+ fn get_fn_args < const N : usize > (
22
13
& self ,
23
- args : & [ rustc_const_eval :: interpret :: FnArg < ' tcx , crate :: Provenance > ] ,
24
- ) -> InterpResult < ' tcx , MutexMethodArgs > {
25
- assert_eq ! ( args . len ( ) , 1 , "Mutex lock/unlock/try_lock should take exactly 1 argument." ) ;
14
+ instance : ty :: Instance < ' tcx > ,
15
+ args : & [ FnArg < ' tcx > ] ,
16
+ ) -> InterpResult < ' tcx , [ OpTy < ' tcx > ; N ] > {
26
17
let this = self . eval_context_ref ( ) ;
27
- let arg = this. copy_fn_arg ( & args[ 0 ] ) ;
28
- // FIXME(genmc): use actual size of the pointee of `arg`.
29
- let size = 1 ;
30
- // GenMC does not support large accesses, we limit the size to the maximum access size.
31
- interp_ok ( MutexMethodArgs {
32
- address : this. read_target_usize ( & arg) ?,
33
- size : size. min ( MAX_ACCESS_SIZE ) ,
34
- } )
18
+ let args = this. copy_fn_args ( args) ; // FIXME: Should `InPlace` arguments be reset to uninit?
19
+ if let Ok ( ops) = args. try_into ( ) {
20
+ return interp_ok ( ops) ;
21
+ }
22
+ panic ! ( "{} is a diagnostic item expected to have {} arguments" , instance, N ) ;
35
23
}
36
24
37
- fn intercept_mutex_lock ( & mut self , args : MutexMethodArgs ) -> InterpResult < ' tcx > {
25
+ fn intercept_mutex_lock ( & mut self , mutex : MPlaceTy < ' tcx > ) -> InterpResult < ' tcx > {
38
26
debug ! ( "GenMC: handling Mutex::lock()" ) ;
39
- let MutexMethodArgs { address, size } = args;
40
27
let this = self . eval_context_mut ( ) ;
41
28
let genmc_ctx = this. machine . data_race . as_genmc_ref ( ) . unwrap ( ) ;
42
- let genmc_tid = genmc_ctx. active_thread_genmc_tid ( & this. machine ) ;
43
- let result =
44
- genmc_ctx. handle . borrow_mut ( ) . pin_mut ( ) . handle_mutex_lock ( genmc_tid, address, size) ;
29
+
30
+ let result = genmc_ctx. handle . borrow_mut ( ) . pin_mut ( ) . handle_mutex_lock (
31
+ genmc_ctx. active_thread_genmc_tid ( & this. machine ) ,
32
+ mutex. ptr ( ) . addr ( ) . bytes ( ) ,
33
+ mutex. layout . size . bytes ( ) ,
34
+ ) ;
45
35
if let Some ( error) = result. error . as_ref ( ) {
46
36
// FIXME(genmc): improve error handling.
47
37
throw_ub_format ! ( "{}" , error. to_string_lossy( ) ) ;
@@ -58,9 +48,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
58
48
None ,
59
49
crate :: callback!(
60
50
@capture<' tcx> {
61
- genmc_tid: i32 ,
62
- address: u64 ,
63
- size: u64 ,
51
+ mutex: MPlaceTy <' tcx>,
64
52
}
65
53
|this, unblock: crate :: UnblockKind | {
66
54
debug!( "GenMC: handling Mutex::lock: unblocking callback called." ) ;
@@ -69,7 +57,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
69
57
let result = genmc_ctx. handle
70
58
. borrow_mut( )
71
59
. pin_mut( )
72
- . handle_mutex_lock( genmc_tid, address, size) ;
60
+ . handle_mutex_lock(
61
+ genmc_ctx. active_thread_genmc_tid( & this. machine) ,
62
+ mutex. ptr( ) . addr( ) . bytes( ) ,
63
+ mutex. layout. size. bytes( ) ,
64
+ ) ;
73
65
if let Some ( error) = result. error. as_ref( ) {
74
66
// FIXME(genmc): improve error handling.
75
67
throw_ub_format!( "{}" , error. to_string_lossy( ) ) ;
@@ -89,16 +81,16 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
89
81
90
82
fn intercept_mutex_try_lock (
91
83
& mut self ,
92
- args : MutexMethodArgs ,
84
+ mutex : MPlaceTy < ' tcx > ,
93
85
dest : & crate :: PlaceTy < ' tcx > ,
94
86
) -> InterpResult < ' tcx > {
95
87
debug ! ( "GenMC: handling Mutex::try_lock()" ) ;
96
88
let this = self . eval_context_mut ( ) ;
97
89
let genmc_ctx = this. machine . data_race . as_genmc_ref ( ) . unwrap ( ) ;
98
90
let result = genmc_ctx. handle . borrow_mut ( ) . pin_mut ( ) . handle_mutex_try_lock (
99
91
genmc_ctx. active_thread_genmc_tid ( & this. machine ) ,
100
- args . address ,
101
- args . size ,
92
+ mutex . ptr ( ) . addr ( ) . bytes ( ) ,
93
+ mutex . layout . size . bytes ( ) ,
102
94
) ;
103
95
if let Some ( error) = result. error . as_ref ( ) {
104
96
// FIXME(genmc): improve error handling.
@@ -111,14 +103,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
111
103
interp_ok ( ( ) )
112
104
}
113
105
114
- fn intercept_mutex_unlock ( & self , args : MutexMethodArgs ) -> InterpResult < ' tcx > {
106
+ fn intercept_mutex_unlock ( & self , mutex : MPlaceTy < ' tcx > ) -> InterpResult < ' tcx > {
115
107
debug ! ( "GenMC: handling Mutex::unlock()" ) ;
116
108
let this = self . eval_context_ref ( ) ;
117
109
let genmc_ctx = this. machine . data_race . as_genmc_ref ( ) . unwrap ( ) ;
118
110
let result = genmc_ctx. handle . borrow_mut ( ) . pin_mut ( ) . handle_mutex_unlock (
119
111
genmc_ctx. active_thread_genmc_tid ( & this. machine ) ,
120
- args . address ,
121
- args . size ,
112
+ mutex . ptr ( ) . addr ( ) . bytes ( ) ,
113
+ mutex . layout . size . bytes ( ) ,
122
114
) ;
123
115
if let Some ( error) = result. error . as_ref ( ) {
124
116
// FIXME(genmc): improve error handling.
@@ -147,19 +139,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
147
139
148
140
// NOTE: When adding new intercepted functions here, they must also be added to `fn get_function_kind` in `concurrency/genmc/scheduling.rs`.
149
141
use rustc_span:: sym;
150
- interp_ok ( if this. tcx . is_diagnostic_item ( sym:: sys_mutex_lock, instance. def_id ( ) ) {
151
- this. intercept_mutex_lock ( this. parse_mutex_method_args ( args) ?) ?;
152
- true
142
+ if this. tcx . is_diagnostic_item ( sym:: sys_mutex_lock, instance. def_id ( ) ) {
143
+ let [ mutex] = this. get_fn_args ( instance, args) ?;
144
+ let mutex = this. deref_pointer ( & mutex) ?;
145
+ this. intercept_mutex_lock ( mutex) ?;
153
146
} else if this. tcx . is_diagnostic_item ( sym:: sys_mutex_try_lock, instance. def_id ( ) ) {
154
- this. intercept_mutex_try_lock ( this. parse_mutex_method_args ( args) ?, dest) ?;
155
- true
147
+ let [ mutex] = this. get_fn_args ( instance, args) ?;
148
+ let mutex = this. deref_pointer ( & mutex) ?;
149
+ this. intercept_mutex_try_lock ( mutex, dest) ?;
156
150
} else if this. tcx . is_diagnostic_item ( sym:: sys_mutex_unlock, instance. def_id ( ) ) {
157
- this. intercept_mutex_unlock ( this. parse_mutex_method_args ( args) ?) ?;
158
- true
151
+ let [ mutex] = this. get_fn_args ( instance, args) ?;
152
+ let mutex = this. deref_pointer ( & mutex) ?;
153
+ this. intercept_mutex_unlock ( mutex) ?;
159
154
} else {
160
155
// Nothing to intercept.
161
- false
162
- } )
156
+ return interp_ok ( false ) ;
157
+ }
158
+ interp_ok ( true )
163
159
}
164
160
165
161
/// Handle an `assume` statement. This will tell GenMC to block the current thread if the `condition` is false.
0 commit comments