@@ -448,12 +448,89 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
448448 operand : & Operand < ' tcx > ,
449449) -> Option < ConstValue < ' tcx > > {
450450 match operand {
451- Operand :: Copy ( _) | Operand :: Move ( _) => None ,
452451 Operand :: Constant ( const_) => match const_. literal {
453452 ConstantKind :: Ty ( const_) => {
454453 fx. monomorphize ( const_) . eval ( fx. tcx , ParamEnv :: reveal_all ( ) ) . val . try_to_value ( )
455454 }
456455 ConstantKind :: Val ( val, _) => Some ( val) ,
457456 } ,
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+ }
458535 }
459536}
0 commit comments