@@ -448,12 +448,89 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
448
448
operand : & Operand < ' tcx > ,
449
449
) -> Option < ConstValue < ' tcx > > {
450
450
match operand {
451
- Operand :: Copy ( _) | Operand :: Move ( _) => None ,
452
451
Operand :: Constant ( const_) => match const_. literal {
453
452
ConstantKind :: Ty ( const_) => {
454
453
fx. monomorphize ( const_) . eval ( fx. tcx , ParamEnv :: reveal_all ( ) ) . val . try_to_value ( )
455
454
}
456
455
ConstantKind :: Val ( val, _) => Some ( val) ,
457
456
} ,
457
+ // FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
458
+ // inside a temporary before being passed to the intrinsic requiring the const argument.
459
+ // This code tries to find a single constant defining definition of the referenced local.
460
+ Operand :: Copy ( place) | Operand :: Move ( place) => {
461
+ if !place. projection . is_empty ( ) {
462
+ return None ;
463
+ }
464
+ let mut computed_const_val = None ;
465
+ for bb_data in fx. mir . basic_blocks ( ) {
466
+ for stmt in & bb_data. statements {
467
+ match & stmt. kind {
468
+ StatementKind :: Assign ( local_and_rvalue) if & local_and_rvalue. 0 == place => {
469
+ match & local_and_rvalue. 1 {
470
+ Rvalue :: Cast ( CastKind :: Misc , operand, ty) => {
471
+ if computed_const_val. is_some ( ) {
472
+ return None ; // local assigned twice
473
+ }
474
+ if !matches ! ( ty. kind( ) , ty:: Uint ( _) | ty:: Int ( _) ) {
475
+ return None ;
476
+ }
477
+ let const_val = mir_operand_get_const_val ( fx, operand) ?;
478
+ if fx. layout_of ( ty) . size
479
+ != const_val. try_to_scalar_int ( ) ?. size ( )
480
+ {
481
+ return None ;
482
+ }
483
+ computed_const_val = Some ( const_val) ;
484
+ }
485
+ Rvalue :: Use ( operand) => {
486
+ computed_const_val = mir_operand_get_const_val ( fx, operand)
487
+ }
488
+ _ => return None ,
489
+ }
490
+ }
491
+ StatementKind :: SetDiscriminant { place : stmt_place, variant_index : _ }
492
+ if & * * stmt_place == place =>
493
+ {
494
+ return None ;
495
+ }
496
+ StatementKind :: LlvmInlineAsm ( _) | StatementKind :: CopyNonOverlapping ( _) => {
497
+ return None ;
498
+ } // conservative handling
499
+ StatementKind :: Assign ( _)
500
+ | StatementKind :: FakeRead ( _)
501
+ | StatementKind :: SetDiscriminant { .. }
502
+ | StatementKind :: StorageLive ( _)
503
+ | StatementKind :: StorageDead ( _)
504
+ | StatementKind :: Retag ( _, _)
505
+ | StatementKind :: AscribeUserType ( _, _)
506
+ | StatementKind :: Coverage ( _)
507
+ | StatementKind :: Nop => { }
508
+ }
509
+ }
510
+ match & bb_data. terminator ( ) . kind {
511
+ TerminatorKind :: Goto { .. }
512
+ | TerminatorKind :: SwitchInt { .. }
513
+ | TerminatorKind :: Resume
514
+ | TerminatorKind :: Abort
515
+ | TerminatorKind :: Return
516
+ | TerminatorKind :: Unreachable
517
+ | TerminatorKind :: Drop { .. }
518
+ | TerminatorKind :: Assert { .. } => { }
519
+ TerminatorKind :: DropAndReplace { .. }
520
+ | TerminatorKind :: Yield { .. }
521
+ | TerminatorKind :: GeneratorDrop
522
+ | TerminatorKind :: FalseEdge { .. }
523
+ | TerminatorKind :: FalseUnwind { .. } => unreachable ! ( ) ,
524
+ TerminatorKind :: InlineAsm { .. } => return None ,
525
+ TerminatorKind :: Call { destination : Some ( ( call_place, _) ) , .. }
526
+ if call_place == place =>
527
+ {
528
+ return None ;
529
+ }
530
+ TerminatorKind :: Call { .. } => { }
531
+ }
532
+ }
533
+ computed_const_val
534
+ }
458
535
}
459
536
}
0 commit comments