@@ -4,14 +4,14 @@ use log::trace;
4
4
5
5
use rustc_hir:: def_id:: DefId ;
6
6
use rustc_middle:: mir;
7
- use rustc_target:: { abi:: { Align , Size } , spec:: PanicStrategy } ;
7
+ use rustc_target:: { abi:: { Align , Size } , spec:: { PanicStrategy , abi :: Abi } } ;
8
8
use rustc_middle:: ty;
9
9
use rustc_apfloat:: Float ;
10
10
use rustc_span:: symbol:: sym;
11
11
12
12
use crate :: * ;
13
13
use super :: backtrace:: EvalContextExt as _;
14
- use helpers:: check_arg_count;
14
+ use helpers:: { check_abi , check_arg_count} ;
15
15
16
16
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
17
17
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
@@ -112,6 +112,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
112
112
fn emulate_foreign_item (
113
113
& mut self ,
114
114
def_id : DefId ,
115
+ abi : Abi ,
115
116
args : & [ OpTy < ' tcx , Tag > ] ,
116
117
ret : Option < ( PlaceTy < ' tcx , Tag > , mir:: BasicBlock ) > ,
117
118
unwind : Option < mir:: BasicBlock > ,
@@ -130,25 +131,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
130
131
let ( dest, ret) = match ret {
131
132
None => match link_name {
132
133
"miri_start_panic" => {
134
+ check_abi ( abi, Abi :: Rust ) ?;
133
135
this. handle_miri_start_panic ( args, unwind) ?;
134
136
return Ok ( None ) ;
135
137
}
136
138
// This matches calls to the foreign item `panic_impl`.
137
139
// The implementation is provided by the function with the `#[panic_handler]` attribute.
138
140
"panic_impl" => {
141
+ check_abi ( abi, Abi :: Rust ) ?;
139
142
let panic_impl_id = tcx. lang_items ( ) . panic_impl ( ) . unwrap ( ) ;
140
143
let panic_impl_instance = ty:: Instance :: mono ( tcx, panic_impl_id) ;
141
144
return Ok ( Some ( & * this. load_mir ( panic_impl_instance. def , None ) ?) ) ;
142
145
}
143
146
| "exit"
144
147
| "ExitProcess"
145
148
=> {
149
+ check_abi ( abi, if link_name == "exit" { Abi :: C } else { Abi :: System } ) ?;
146
150
let & [ code] = check_arg_count ( args) ?;
147
151
// it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
148
152
let code = this. read_scalar ( code) ?. to_i32 ( ) ?;
149
153
throw_machine_stop ! ( TerminationInfo :: Exit ( code. into( ) ) ) ;
150
154
}
151
155
"abort" => {
156
+ check_abi ( abi, Abi :: C ) ?;
152
157
throw_machine_stop ! ( TerminationInfo :: Abort ( "the program aborted execution" . to_owned( ) ) )
153
158
}
154
159
_ => throw_unsup_format ! ( "can't call (diverging) foreign function: {}" , link_name) ,
@@ -165,6 +170,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
165
170
// Normally, this will be either `libpanic_unwind` or `libpanic_abort`, but it could
166
171
// also be a custom user-provided implementation via `#![feature(panic_runtime)]`
167
172
"__rust_start_panic" | "__rust_panic_cleanup" => {
173
+ check_abi ( abi, Abi :: C ) ?;
168
174
// This replicates some of the logic in `inject_panic_runtime`.
169
175
// FIXME: is there a way to reuse that logic?
170
176
let panic_runtime = match this. tcx . sess . panic_strategy ( ) {
@@ -179,7 +185,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
179
185
}
180
186
181
187
// Third: functions that return.
182
- if this. emulate_foreign_item_by_name ( link_name, args, dest, ret) ? {
188
+ if this. emulate_foreign_item_by_name ( link_name, abi , args, dest, ret) ? {
183
189
trace ! ( "{:?}" , this. dump_place( * dest) ) ;
184
190
this. go_to_block ( ret) ;
185
191
}
@@ -193,6 +199,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
193
199
fn emulate_foreign_item_by_name (
194
200
& mut self ,
195
201
link_name : & str ,
202
+ abi : Abi ,
196
203
args : & [ OpTy < ' tcx , Tag > ] ,
197
204
dest : PlaceTy < ' tcx , Tag > ,
198
205
ret : mir:: BasicBlock ,
@@ -204,6 +211,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
204
211
match link_name {
205
212
// Miri-specific extern functions
206
213
"miri_static_root" => {
214
+ check_abi ( abi, Abi :: Rust ) ?;
207
215
let & [ ptr] = check_arg_count ( args) ?;
208
216
let ptr = this. read_scalar ( ptr) ?. check_init ( ) ?;
209
217
let ptr = this. force_ptr ( ptr) ?;
@@ -215,23 +223,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
215
223
216
224
// Obtains a Miri backtrace. See the README for details.
217
225
"miri_get_backtrace" => {
226
+ check_abi ( abi, Abi :: Rust ) ?;
218
227
this. handle_miri_get_backtrace ( args, dest) ?;
219
228
}
220
229
221
230
// Resolves a Miri backtrace frame. See the README for details.
222
231
"miri_resolve_frame" => {
232
+ check_abi ( abi, Abi :: Rust ) ?;
223
233
this. handle_miri_resolve_frame ( args, dest) ?;
224
234
}
225
235
226
236
227
237
// Standard C allocation
228
238
"malloc" => {
239
+ check_abi ( abi, Abi :: C ) ?;
229
240
let & [ size] = check_arg_count ( args) ?;
230
241
let size = this. read_scalar ( size) ?. to_machine_usize ( this) ?;
231
242
let res = this. malloc ( size, /*zero_init:*/ false , MiriMemoryKind :: C ) ;
232
243
this. write_scalar ( res, dest) ?;
233
244
}
234
245
"calloc" => {
246
+ check_abi ( abi, Abi :: C ) ?;
235
247
let & [ items, len] = check_arg_count ( args) ?;
236
248
let items = this. read_scalar ( items) ?. to_machine_usize ( this) ?;
237
249
let len = this. read_scalar ( len) ?. to_machine_usize ( this) ?;
@@ -241,11 +253,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
241
253
this. write_scalar ( res, dest) ?;
242
254
}
243
255
"free" => {
256
+ check_abi ( abi, Abi :: C ) ?;
244
257
let & [ ptr] = check_arg_count ( args) ?;
245
258
let ptr = this. read_scalar ( ptr) ?. check_init ( ) ?;
246
259
this. free ( ptr, MiriMemoryKind :: C ) ?;
247
260
}
248
261
"realloc" => {
262
+ check_abi ( abi, Abi :: C ) ?;
249
263
let & [ old_ptr, new_size] = check_arg_count ( args) ?;
250
264
let old_ptr = this. read_scalar ( old_ptr) ?. check_init ( ) ?;
251
265
let new_size = this. read_scalar ( new_size) ?. to_machine_usize ( this) ?;
@@ -257,6 +271,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
257
271
// (Usually these would be forwarded to to `#[global_allocator]`; we instead implement a generic
258
272
// allocation that also checks that all conditions are met, such as not permitting zero-sized allocations.)
259
273
"__rust_alloc" => {
274
+ check_abi ( abi, Abi :: Rust ) ?;
260
275
let & [ size, align] = check_arg_count ( args) ?;
261
276
let size = this. read_scalar ( size) ?. to_machine_usize ( this) ?;
262
277
let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
@@ -269,6 +284,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
269
284
this. write_scalar ( ptr, dest) ?;
270
285
}
271
286
"__rust_alloc_zeroed" => {
287
+ check_abi ( abi, Abi :: Rust ) ?;
272
288
let & [ size, align] = check_arg_count ( args) ?;
273
289
let size = this. read_scalar ( size) ?. to_machine_usize ( this) ?;
274
290
let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
@@ -283,6 +299,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
283
299
this. write_scalar ( ptr, dest) ?;
284
300
}
285
301
"__rust_dealloc" => {
302
+ check_abi ( abi, Abi :: Rust ) ?;
286
303
let & [ ptr, old_size, align] = check_arg_count ( args) ?;
287
304
let ptr = this. read_scalar ( ptr) ?. check_init ( ) ?;
288
305
let old_size = this. read_scalar ( old_size) ?. to_machine_usize ( this) ?;
@@ -296,6 +313,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
296
313
) ?;
297
314
}
298
315
"__rust_realloc" => {
316
+ check_abi ( abi, Abi :: Rust ) ?;
299
317
let & [ ptr, old_size, align, new_size] = check_arg_count ( args) ?;
300
318
let ptr = this. force_ptr ( this. read_scalar ( ptr) ?. check_init ( ) ?) ?;
301
319
let old_size = this. read_scalar ( old_size) ?. to_machine_usize ( this) ?;
@@ -316,6 +334,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
316
334
317
335
// C memory handling functions
318
336
"memcmp" => {
337
+ check_abi ( abi, Abi :: C ) ?;
319
338
let & [ left, right, n] = check_arg_count ( args) ?;
320
339
let left = this. read_scalar ( left) ?. check_init ( ) ?;
321
340
let right = this. read_scalar ( right) ?. check_init ( ) ?;
@@ -336,6 +355,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
336
355
this. write_scalar ( Scalar :: from_i32 ( result) , dest) ?;
337
356
}
338
357
"memrchr" => {
358
+ check_abi ( abi, Abi :: C ) ?;
339
359
let & [ ptr, val, num] = check_arg_count ( args) ?;
340
360
let ptr = this. read_scalar ( ptr) ?. check_init ( ) ?;
341
361
let val = this. read_scalar ( val) ?. to_i32 ( ) ? as u8 ;
@@ -354,6 +374,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
354
374
}
355
375
}
356
376
"memchr" => {
377
+ check_abi ( abi, Abi :: C ) ?;
357
378
let & [ ptr, val, num] = check_arg_count ( args) ?;
358
379
let ptr = this. read_scalar ( ptr) ?. check_init ( ) ?;
359
380
let val = this. read_scalar ( val) ?. to_i32 ( ) ? as u8 ;
@@ -371,6 +392,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
371
392
}
372
393
}
373
394
"strlen" => {
395
+ check_abi ( abi, Abi :: C ) ?;
374
396
let & [ ptr] = check_arg_count ( args) ?;
375
397
let ptr = this. read_scalar ( ptr) ?. check_init ( ) ?;
376
398
let n = this. memory . read_c_str ( ptr) ?. len ( ) ;
@@ -386,6 +408,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
386
408
| "asinf"
387
409
| "atanf"
388
410
=> {
411
+ check_abi ( abi, Abi :: C ) ?;
389
412
let & [ f] = check_arg_count ( args) ?;
390
413
// FIXME: Using host floats.
391
414
let f = f32:: from_bits ( this. read_scalar ( f) ?. to_u32 ( ) ?) ;
@@ -405,6 +428,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
405
428
| "hypotf"
406
429
| "atan2f"
407
430
=> {
431
+ check_abi ( abi, Abi :: C ) ?;
408
432
let & [ f1, f2] = check_arg_count ( args) ?;
409
433
// underscore case for windows, here and below
410
434
// (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
@@ -426,6 +450,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
426
450
| "asin"
427
451
| "atan"
428
452
=> {
453
+ check_abi ( abi, Abi :: C ) ?;
429
454
let & [ f] = check_arg_count ( args) ?;
430
455
// FIXME: Using host floats.
431
456
let f = f64:: from_bits ( this. read_scalar ( f) ?. to_u64 ( ) ?) ;
@@ -445,6 +470,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
445
470
| "hypot"
446
471
| "atan2"
447
472
=> {
473
+ check_abi ( abi, Abi :: C ) ?;
448
474
let & [ f1, f2] = check_arg_count ( args) ?;
449
475
// FIXME: Using host floats.
450
476
let f1 = f64:: from_bits ( this. read_scalar ( f1) ?. to_u64 ( ) ?) ;
@@ -460,6 +486,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
460
486
| "ldexp"
461
487
| "scalbn"
462
488
=> {
489
+ check_abi ( abi, Abi :: C ) ?;
463
490
let & [ x, exp] = check_arg_count ( args) ?;
464
491
// For radix-2 (binary) systems, `ldexp` and `scalbn` are the same.
465
492
let x = this. read_scalar ( x) ?. to_f64 ( ) ?;
@@ -481,10 +508,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
481
508
482
509
// Architecture-specific shims
483
510
"llvm.x86.sse2.pause" if this. tcx . sess . target . arch == "x86" || this. tcx . sess . target . arch == "x86_64" => {
511
+ check_abi ( abi, Abi :: C ) ?;
484
512
let & [ ] = check_arg_count ( args) ?;
485
513
this. yield_active_thread ( ) ;
486
514
}
487
515
"llvm.aarch64.hint" if this. tcx . sess . target . arch == "aarch64" => {
516
+ check_abi ( abi, Abi :: C ) ?;
488
517
let & [ hint] = check_arg_count ( args) ?;
489
518
let hint = this. read_scalar ( hint) ?. to_i32 ( ) ?;
490
519
match hint {
@@ -499,8 +528,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
499
528
500
529
// Platform-specific shims
501
530
_ => match this. tcx . sess . target . os . as_str ( ) {
502
- "linux" | "macos" => return shims:: posix:: foreign_items:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, args, dest, ret) ,
503
- "windows" => return shims:: windows:: foreign_items:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, args, dest, ret) ,
531
+ "linux" | "macos" => return shims:: posix:: foreign_items:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, abi , args, dest, ret) ,
532
+ "windows" => return shims:: windows:: foreign_items:: EvalContextExt :: emulate_foreign_item_by_name ( this, link_name, abi , args, dest, ret) ,
504
533
target => throw_unsup_format ! ( "the target `{}` is not supported" , target) ,
505
534
}
506
535
} ;
0 commit comments