9
9
// except according to those terms.
10
10
11
11
use llvm:: { self , ValueRef , BasicBlockRef } ;
12
- use rustc_const_eval:: { ErrKind , ConstEvalErr , note_const_eval_err} ;
13
- use rustc:: middle:: lang_items;
14
- use rustc:: middle:: const_val:: ConstInt ;
15
12
use rustc:: ty:: { self , layout, TypeFoldable } ;
16
13
use rustc:: mir;
14
+ use rustc:: middle:: const_val:: ConstInt ;
17
15
use abi:: { Abi , FnType , ArgType } ;
18
16
use base:: { self , Lifetime } ;
19
17
use callee;
20
18
use builder:: Builder ;
21
19
use common:: { self , Funclet } ;
22
- use common:: { C_bool , C_str_slice , C_struct , C_u32 , C_uint , C_undef } ;
23
- use consts;
20
+ use common:: { C_uint , C_undef } ;
24
21
use machine:: llalign_of_min;
25
22
use meth;
26
23
use monomorphize;
@@ -29,7 +26,6 @@ use type_of::{self, align_of};
29
26
use type_:: Type ;
30
27
31
28
use rustc_data_structures:: indexed_vec:: IndexVec ;
32
- use syntax:: symbol:: Symbol ;
33
29
34
30
use std:: cmp;
35
31
@@ -272,124 +268,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
272
268
}
273
269
274
270
mir:: TerminatorKind :: Assert { ref cond, expected, ref msg, target, cleanup } => {
275
- let cond = self . trans_operand ( & bcx, cond) . immediate ( ) ;
276
- let mut const_cond = common:: const_to_opt_u128 ( cond, false ) . map ( |c| c == 1 ) ;
277
-
278
- // This case can currently arise only from functions marked
279
- // with #[rustc_inherit_overflow_checks] and inlined from
280
- // another crate (mostly core::num generic/#[inline] fns),
281
- // while the current crate doesn't use overflow checks.
282
- // NOTE: Unlike binops, negation doesn't have its own
283
- // checked operation, just a comparison with the minimum
284
- // value, so we have to check for the assert message.
285
- if !bcx. ccx . check_overflow ( ) {
286
- use rustc_const_math:: ConstMathErr :: Overflow ;
287
- use rustc_const_math:: Op :: Neg ;
288
-
289
- if let mir:: AssertMessage :: Math ( Overflow ( Neg ) ) = * msg {
290
- const_cond = Some ( expected) ;
291
- }
292
- }
293
-
294
- // Don't translate the panic block if success if known.
295
- if const_cond == Some ( expected) {
296
- funclet_br ( self , bcx, target) ;
297
- return ;
298
- }
299
-
300
- // Pass the condition through llvm.expect for branch hinting.
301
- let expect = bcx. ccx . get_intrinsic ( & "llvm.expect.i1" ) ;
302
- let cond = bcx. call ( expect, & [ cond, C_bool ( bcx. ccx , expected) ] , None ) ;
303
-
304
- // Create the failure block and the conditional branch to it.
305
- let success_block = self . new_block ( "success" ) ;
306
- let panic_block = self . new_block ( "panic" ) ;
307
- if expected {
308
- bcx. cond_br ( cond, success_block. llbb ( ) , panic_block. llbb ( ) ) ;
309
- } else {
310
- bcx. cond_br ( cond, panic_block. llbb ( ) , success_block. llbb ( ) ) ;
311
- }
312
-
313
- // After this point, bcx is the block for the call to panic.
314
- bcx = panic_block;
315
- self . set_debug_loc ( & bcx, terminator. source_info ) ;
316
-
317
- // Get the location information.
318
- let loc = bcx. sess ( ) . codemap ( ) . lookup_char_pos ( span. lo ) ;
319
- let filename = Symbol :: intern ( & loc. file . name ) . as_str ( ) ;
320
- let filename = C_str_slice ( bcx. ccx , filename) ;
321
- let line = C_u32 ( bcx. ccx , loc. line as u32 ) ;
322
-
323
- // Put together the arguments to the panic entry point.
324
- let ( lang_item, args, const_err) = match * msg {
325
- mir:: AssertMessage :: BoundsCheck { ref len, ref index } => {
326
- let len = self . trans_operand ( & mut bcx, len) . immediate ( ) ;
327
- let index = self . trans_operand ( & mut bcx, index) . immediate ( ) ;
328
-
329
- let const_err = common:: const_to_opt_u128 ( len, false )
330
- . and_then ( |len| common:: const_to_opt_u128 ( index, false )
331
- . map ( |index| ErrKind :: IndexOutOfBounds {
332
- len : len as u64 ,
333
- index : index as u64
334
- } ) ) ;
335
-
336
- let file_line = C_struct ( bcx. ccx , & [ filename, line] , false ) ;
337
- let align = llalign_of_min ( bcx. ccx , common:: val_ty ( file_line) ) ;
338
- let file_line = consts:: addr_of ( bcx. ccx ,
339
- file_line,
340
- align,
341
- "panic_bounds_check_loc" ) ;
342
- ( lang_items:: PanicBoundsCheckFnLangItem ,
343
- vec ! [ file_line, index, len] ,
344
- const_err)
345
- }
346
- mir:: AssertMessage :: Math ( ref err) => {
347
- let msg_str = Symbol :: intern ( err. description ( ) ) . as_str ( ) ;
348
- let msg_str = C_str_slice ( bcx. ccx , msg_str) ;
349
- let msg_file_line = C_struct ( bcx. ccx ,
350
- & [ msg_str, filename, line] ,
351
- false ) ;
352
- let align = llalign_of_min ( bcx. ccx , common:: val_ty ( msg_file_line) ) ;
353
- let msg_file_line = consts:: addr_of ( bcx. ccx ,
354
- msg_file_line,
355
- align,
356
- "panic_loc" ) ;
357
- ( lang_items:: PanicFnLangItem ,
358
- vec ! [ msg_file_line] ,
359
- Some ( ErrKind :: Math ( err. clone ( ) ) ) )
360
- }
361
- } ;
362
-
363
- // If we know we always panic, and the error message
364
- // is also constant, then we can produce a warning.
365
- if const_cond == Some ( !expected) {
366
- if let Some ( err) = const_err {
367
- let err = ConstEvalErr { span : span, kind : err } ;
368
- let mut diag = bcx. tcx ( ) . sess . struct_span_warn (
369
- span, "this expression will panic at run-time" ) ;
370
- note_const_eval_err ( bcx. tcx ( ) , & err, span, "expression" , & mut diag) ;
371
- diag. emit ( ) ;
372
- }
373
- }
374
-
375
- // Obtain the panic entry point.
376
- let def_id = common:: langcall ( bcx. tcx ( ) , Some ( span) , "" , lang_item) ;
377
- let instance = ty:: Instance :: mono ( bcx. tcx ( ) , def_id) ;
378
- let llfn = callee:: get_fn ( bcx. ccx , instance) ;
379
-
380
- // Translate the actual panic invoke/call.
381
- if let Some ( unwind) = cleanup {
382
- bcx. invoke ( llfn,
383
- & args,
384
- self . unreachable_block ( ) ,
385
- self . landing_pad_to ( unwind) ,
386
- cleanup_bundle) ;
387
- } else {
388
- bcx. call ( llfn, & args, cleanup_bundle) ;
389
- bcx. unreachable ( ) ;
390
- }
391
-
392
- success_block. br ( self . blocks [ target] ) ;
271
+ bcx = self . trans_assert (
272
+ bcx, cond, expected, msg, cleanup, cleanup_bundle, terminator. source_info
273
+ ) ;
274
+ funclet_br ( self , bcx, target) ;
393
275
}
394
276
395
277
mir:: TerminatorKind :: DropAndReplace { .. } => {
@@ -768,7 +650,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
768
650
/// Return the landingpad wrapper around the given basic block
769
651
///
770
652
/// No-op in MSVC SEH scheme.
771
- fn landing_pad_to ( & mut self , target_bb : mir:: Block ) -> BasicBlockRef {
653
+ pub fn landing_pad_to ( & mut self , target_bb : mir:: Block ) -> BasicBlockRef {
772
654
if let Some ( block) = self . landing_pads [ target_bb] {
773
655
return block;
774
656
}
@@ -797,7 +679,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
797
679
bcx. llbb ( )
798
680
}
799
681
800
- fn unreachable_block ( & mut self ) -> BasicBlockRef {
682
+ pub fn unreachable_block ( & mut self ) -> BasicBlockRef {
801
683
self . unreachable_block . unwrap_or_else ( || {
802
684
let bl = self . new_block ( "unreachable" ) ;
803
685
bl. unreachable ( ) ;
0 commit comments