@@ -9,6 +9,12 @@ use rustc_middle::mir::interpret::AllocBytes;
9
9
use crate :: alloc:: discrete_alloc:: MachineAlloc ;
10
10
use crate :: helpers:: ToU64 as _;
11
11
12
+ #[ derive( Clone , Copy , Debug ) ]
13
+ pub enum MiriByteMdata {
14
+ Global ,
15
+ Isolated ,
16
+ }
17
+
12
18
/// Allocation bytes that explicitly handle the layout of the data they're storing.
13
19
/// This is necessary to interface with native code that accesses the program store in Miri.
14
20
#[ derive( Debug ) ]
@@ -21,15 +27,15 @@ pub struct MiriAllocBytes {
21
27
/// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
22
28
ptr : * mut u8 ,
23
29
/// Whether this instance of `MiriAllocBytes` had its allocation created by calling `alloc::alloc()`
24
- /// (true ) or the discrete allocator (false )
25
- alloc_is_global : bool ,
30
+ /// (`Global` ) or the discrete allocator (`Isolated` )
31
+ dsc : MiriByteMdata ,
26
32
}
27
33
28
34
impl Clone for MiriAllocBytes {
29
35
fn clone ( & self ) -> Self {
30
36
let bytes: Cow < ' _ , [ u8 ] > = Cow :: Borrowed ( self ) ;
31
37
let align = Align :: from_bytes ( self . layout . align ( ) . to_u64 ( ) ) . unwrap ( ) ;
32
- MiriAllocBytes :: from_bytes ( bytes, align)
38
+ MiriAllocBytes :: from_bytes ( bytes, align, self . dsc )
33
39
}
34
40
}
35
41
@@ -45,16 +51,15 @@ impl Drop for MiriAllocBytes {
45
51
46
52
// SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
47
53
unsafe {
48
- #[ cfg( target_os = "linux" ) ]
49
- {
50
- if self . alloc_is_global {
51
- alloc:: dealloc ( self . ptr , alloc_layout) ;
52
- } else {
53
- MachineAlloc :: dealloc ( self . ptr , alloc_layout) ;
54
- }
54
+ match self . dsc {
55
+ MiriByteMdata :: Global => alloc:: dealloc ( self . ptr , alloc_layout) ,
56
+ MiriByteMdata :: Isolated => {
57
+ #[ cfg( target_os = "linux" ) ]
58
+ { MachineAlloc :: dealloc ( self . ptr , alloc_layout) }
59
+ #[ cfg( not( target_os = "linux" ) ) ]
60
+ { unreachable ! ( ) }
61
+ } ,
55
62
}
56
- #[ cfg( not( target_os = "linux" ) ) ]
57
- alloc:: dealloc ( self . ptr , alloc_layout) ;
58
63
}
59
64
}
60
65
}
@@ -84,41 +89,45 @@ impl MiriAllocBytes {
84
89
fn alloc_with (
85
90
size : u64 ,
86
91
align : u64 ,
87
- alloc_fn : impl FnOnce ( Layout ) -> ( * mut u8 , bool ) ,
92
+ dsc : MiriByteMdata ,
93
+ alloc_fn : impl FnOnce ( Layout ) -> * mut u8 ,
88
94
) -> Result < MiriAllocBytes , ( ) > {
89
95
let size = usize:: try_from ( size) . map_err ( |_| ( ) ) ?;
90
96
let align = usize:: try_from ( align) . map_err ( |_| ( ) ) ?;
91
97
let layout = Layout :: from_size_align ( size, align) . map_err ( |_| ( ) ) ?;
92
98
// When size is 0 we allocate 1 byte anyway, to ensure each allocation has a unique address.
93
99
let alloc_layout =
94
100
if size == 0 { Layout :: from_size_align ( 1 , align) . unwrap ( ) } else { layout } ;
95
- let ( ptr, alloc_is_global ) = alloc_fn ( alloc_layout) ;
101
+ let ptr = alloc_fn ( alloc_layout) ;
96
102
if ptr. is_null ( ) {
97
103
Err ( ( ) )
98
104
} else {
99
105
// SAFETY: All `MiriAllocBytes` invariants are fulfilled.
100
- Ok ( Self { ptr, layout, alloc_is_global } )
106
+ Ok ( Self { ptr, layout, dsc } )
101
107
}
102
108
}
103
109
}
104
110
105
111
impl AllocBytes for MiriAllocBytes {
106
- fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , align : Align ) -> Self {
112
+ type ByteMetadata = MiriByteMdata ;
113
+
114
+ fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , align : Align , dsc : MiriByteMdata ) -> Self {
107
115
let slice = slice. into ( ) ;
108
116
let size = slice. len ( ) ;
109
117
let align = align. bytes ( ) ;
110
118
// SAFETY: `alloc_fn` will only be used with `size != 0`.
111
119
let alloc_fn = |layout| unsafe {
112
- #[ cfg( target_os = "linux" ) ]
113
- {
114
- MachineAlloc :: alloc ( layout)
115
- }
116
- #[ cfg( not( target_os = "linux" ) ) ]
117
- {
118
- ( alloc:: alloc ( layout) , true )
120
+ match dsc {
121
+ MiriByteMdata :: Global => alloc:: alloc ( layout) ,
122
+ MiriByteMdata :: Isolated => {
123
+ #[ cfg( target_os = "linux" ) ]
124
+ { MachineAlloc :: alloc ( layout) }
125
+ #[ cfg( not( target_os = "linux" ) ) ]
126
+ { unreachable ! ( ) }
127
+ } ,
119
128
}
120
129
} ;
121
- let alloc_bytes = MiriAllocBytes :: alloc_with ( size. to_u64 ( ) , align, alloc_fn)
130
+ let alloc_bytes = MiriAllocBytes :: alloc_with ( size. to_u64 ( ) , align, dsc , alloc_fn)
122
131
. unwrap_or_else ( |( ) | {
123
132
panic ! ( "Miri ran out of memory: cannot create allocation of {size} bytes" )
124
133
} ) ;
@@ -128,21 +137,22 @@ impl AllocBytes for MiriAllocBytes {
128
137
alloc_bytes
129
138
}
130
139
131
- fn zeroed ( size : Size , align : Align ) -> Option < Self > {
140
+ fn zeroed ( size : Size , align : Align , dsc : MiriByteMdata ) -> Option < Self > {
132
141
let size = size. bytes ( ) ;
133
142
let align = align. bytes ( ) ;
134
143
// SAFETY: `alloc_fn` will only be used with `size != 0`.
135
144
let alloc_fn = |layout| unsafe {
136
- #[ cfg( target_os = "linux" ) ]
137
- {
138
- MachineAlloc :: alloc_zeroed ( layout)
139
- }
140
- #[ cfg( not( target_os = "linux" ) ) ]
141
- {
142
- ( alloc:: alloc_zeroed ( layout) , true )
145
+ match dsc {
146
+ MiriByteMdata :: Global => alloc:: alloc_zeroed ( layout) ,
147
+ MiriByteMdata :: Isolated => {
148
+ #[ cfg( target_os = "linux" ) ]
149
+ { MachineAlloc :: alloc_zeroed ( layout) }
150
+ #[ cfg( not( target_os = "linux" ) ) ]
151
+ { unreachable ! ( ) }
152
+ } ,
143
153
}
144
154
} ;
145
- MiriAllocBytes :: alloc_with ( size, align, alloc_fn) . ok ( )
155
+ MiriAllocBytes :: alloc_with ( size, align, dsc , alloc_fn) . ok ( )
146
156
}
147
157
148
158
fn as_mut_ptr ( & mut self ) -> * mut u8 {
@@ -152,4 +162,8 @@ impl AllocBytes for MiriAllocBytes {
152
162
fn as_ptr ( & self ) -> * const u8 {
153
163
self . ptr
154
164
}
165
+
166
+ fn get_mdata ( & self ) -> MiriByteMdata {
167
+ self . dsc
168
+ }
155
169
}
0 commit comments