@@ -41,21 +41,41 @@ impl Lower128Bit {
4141 let ( basic_blocks, local_decls) = mir. basic_blocks_and_local_decls_mut ( ) ;
4242 for block in basic_blocks. iter_mut ( ) {
4343 for i in ( 0 ..block. statements . len ( ) ) . rev ( ) {
44- let lang_item =
45- if let Some ( lang_item) = lower_to ( & block. statements [ i] , local_decls, tcx) {
46- lang_item
44+ let ( lang_item, rhs_kind) =
45+ if let Some ( ( lang_item, rhs_kind) ) =
46+ lower_to ( & block. statements [ i] , local_decls, tcx)
47+ {
48+ ( lang_item, rhs_kind)
4749 } else {
4850 continue ;
4951 } ;
5052
53+ let rhs_override_ty = rhs_kind. ty ( tcx) ;
54+ let cast_local =
55+ match rhs_override_ty {
56+ None => None ,
57+ Some ( ty) => {
58+ let local_decl = LocalDecl :: new_internal (
59+ ty, block. statements [ i] . source_info . span ) ;
60+ Some ( local_decls. push ( local_decl) )
61+ } ,
62+ } ;
63+
64+ let storage_dead = cast_local. map ( |local| {
65+ Statement {
66+ source_info : block. statements [ i] . source_info ,
67+ kind : StatementKind :: StorageDead ( local) ,
68+ }
69+ } ) ;
5170 let after_call = BasicBlockData {
52- statements : block. statements . drain ( ( i+1 ) ..) . collect ( ) ,
71+ statements : storage_dead. into_iter ( )
72+ . chain ( block. statements . drain ( ( i+1 ) ..) ) . collect ( ) ,
5373 is_cleanup : block. is_cleanup ,
5474 terminator : block. terminator . take ( ) ,
5575 } ;
5676
5777 let bin_statement = block. statements . pop ( ) . unwrap ( ) ;
58- let ( source_info, lvalue, lhs, rhs) = match bin_statement {
78+ let ( source_info, lvalue, lhs, mut rhs) = match bin_statement {
5979 Statement {
6080 source_info,
6181 kind : StatementKind :: Assign (
@@ -71,6 +91,23 @@ impl Lower128Bit {
7191 _ => bug ! ( "Statement doesn't match pattern any more?" ) ,
7292 } ;
7393
94+ if let Some ( local) = cast_local {
95+ block. statements . push ( Statement {
96+ source_info : source_info,
97+ kind : StatementKind :: StorageLive ( local) ,
98+ } ) ;
99+ block. statements . push ( Statement {
100+ source_info : source_info,
101+ kind : StatementKind :: Assign (
102+ Lvalue :: Local ( local) ,
103+ Rvalue :: Cast (
104+ CastKind :: Misc ,
105+ rhs,
106+ rhs_override_ty. unwrap ( ) ) ) ,
107+ } ) ;
108+ rhs = Operand :: Consume ( Lvalue :: Local ( local) ) ;
109+ }
110+
74111 let call_did = check_lang_item_type (
75112 lang_item, & lvalue, & lhs, & rhs, local_decls, tcx) ;
76113
@@ -118,7 +155,7 @@ fn check_lang_item_type<'a, 'tcx, D>(
118155}
119156
120157fn lower_to < ' a , ' tcx , D > ( statement : & Statement < ' tcx > , local_decls : & D , tcx : TyCtxt < ' a , ' tcx , ' tcx > )
121- -> Option < LangItem >
158+ -> Option < ( LangItem , RhsKind ) >
122159 where D : HasLocalDecls < ' tcx >
123160{
124161 match statement. kind {
@@ -139,6 +176,23 @@ fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCt
139176 None
140177}
141178
179+ #[ derive( Copy , Clone ) ]
180+ enum RhsKind {
181+ Unchanged ,
182+ ForceU128 ,
183+ ForceU32 ,
184+ }
185+
186+ impl RhsKind {
187+ fn ty < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) -> Option < Ty < ' tcx > > {
188+ match * self {
189+ RhsKind :: Unchanged => None ,
190+ RhsKind :: ForceU128 => Some ( tcx. types . u128 ) ,
191+ RhsKind :: ForceU32 => Some ( tcx. types . u32 ) ,
192+ }
193+ }
194+ }
195+
142196fn sign_of_128bit ( ty : Ty ) -> Option < bool > {
143197 match ty. sty {
144198 TypeVariants :: TyInt ( syntax:: ast:: IntTy :: I128 ) => Some ( true ) ,
@@ -147,39 +201,39 @@ fn sign_of_128bit(ty: Ty) -> Option<bool> {
147201 }
148202}
149203
150- fn item_for_op ( bin_op : BinOp , is_signed : bool ) -> Option < LangItem > {
204+ fn item_for_op ( bin_op : BinOp , is_signed : bool ) -> Option < ( LangItem , RhsKind ) > {
151205 let i = match ( bin_op, is_signed) {
152- ( BinOp :: Add , true ) => LangItem :: I128AddFnLangItem ,
153- ( BinOp :: Add , false ) => LangItem :: U128AddFnLangItem ,
154- ( BinOp :: Sub , true ) => LangItem :: I128SubFnLangItem ,
155- ( BinOp :: Sub , false ) => LangItem :: U128SubFnLangItem ,
156- ( BinOp :: Mul , true ) => LangItem :: I128MulFnLangItem ,
157- ( BinOp :: Mul , false ) => LangItem :: U128MulFnLangItem ,
158- ( BinOp :: Div , true ) => LangItem :: I128DivFnLangItem ,
159- ( BinOp :: Div , false ) => LangItem :: U128DivFnLangItem ,
160- ( BinOp :: Rem , true ) => LangItem :: I128RemFnLangItem ,
161- ( BinOp :: Rem , false ) => LangItem :: U128RemFnLangItem ,
162- ( BinOp :: Shl , true ) => LangItem :: I128ShlFnLangItem ,
163- ( BinOp :: Shl , false ) => LangItem :: U128ShlFnLangItem ,
164- ( BinOp :: Shr , true ) => LangItem :: I128ShrFnLangItem ,
165- ( BinOp :: Shr , false ) => LangItem :: U128ShrFnLangItem ,
206+ ( BinOp :: Add , true ) => ( LangItem :: I128AddFnLangItem , RhsKind :: Unchanged ) ,
207+ ( BinOp :: Add , false ) => ( LangItem :: U128AddFnLangItem , RhsKind :: Unchanged ) ,
208+ ( BinOp :: Sub , true ) => ( LangItem :: I128SubFnLangItem , RhsKind :: Unchanged ) ,
209+ ( BinOp :: Sub , false ) => ( LangItem :: U128SubFnLangItem , RhsKind :: Unchanged ) ,
210+ ( BinOp :: Mul , true ) => ( LangItem :: I128MulFnLangItem , RhsKind :: Unchanged ) ,
211+ ( BinOp :: Mul , false ) => ( LangItem :: U128MulFnLangItem , RhsKind :: Unchanged ) ,
212+ ( BinOp :: Div , true ) => ( LangItem :: I128DivFnLangItem , RhsKind :: Unchanged ) ,
213+ ( BinOp :: Div , false ) => ( LangItem :: U128DivFnLangItem , RhsKind :: Unchanged ) ,
214+ ( BinOp :: Rem , true ) => ( LangItem :: I128RemFnLangItem , RhsKind :: Unchanged ) ,
215+ ( BinOp :: Rem , false ) => ( LangItem :: U128RemFnLangItem , RhsKind :: Unchanged ) ,
216+ ( BinOp :: Shl , true ) => ( LangItem :: I128ShlFnLangItem , RhsKind :: ForceU32 ) ,
217+ ( BinOp :: Shl , false ) => ( LangItem :: U128ShlFnLangItem , RhsKind :: ForceU32 ) ,
218+ ( BinOp :: Shr , true ) => ( LangItem :: I128ShrFnLangItem , RhsKind :: ForceU32 ) ,
219+ ( BinOp :: Shr , false ) => ( LangItem :: U128ShrFnLangItem , RhsKind :: ForceU32 ) ,
166220 _ => return None ,
167221 } ;
168222 Some ( i)
169223}
170224
171- fn item_for_checked_op ( bin_op : BinOp , is_signed : bool ) -> Option < LangItem > {
225+ fn item_for_checked_op ( bin_op : BinOp , is_signed : bool ) -> Option < ( LangItem , RhsKind ) > {
172226 let i = match ( bin_op, is_signed) {
173- ( BinOp :: Add , true ) => LangItem :: I128AddoFnLangItem ,
174- ( BinOp :: Add , false ) => LangItem :: U128AddoFnLangItem ,
175- ( BinOp :: Sub , true ) => LangItem :: I128SuboFnLangItem ,
176- ( BinOp :: Sub , false ) => LangItem :: U128SuboFnLangItem ,
177- ( BinOp :: Mul , true ) => LangItem :: I128MuloFnLangItem ,
178- ( BinOp :: Mul , false ) => LangItem :: U128MuloFnLangItem ,
179- ( BinOp :: Shl , true ) => LangItem :: I128ShloFnLangItem ,
180- ( BinOp :: Shl , false ) => LangItem :: U128ShloFnLangItem ,
181- ( BinOp :: Shr , true ) => LangItem :: I128ShroFnLangItem ,
182- ( BinOp :: Shr , false ) => LangItem :: U128ShroFnLangItem ,
227+ ( BinOp :: Add , true ) => ( LangItem :: I128AddoFnLangItem , RhsKind :: Unchanged ) ,
228+ ( BinOp :: Add , false ) => ( LangItem :: U128AddoFnLangItem , RhsKind :: Unchanged ) ,
229+ ( BinOp :: Sub , true ) => ( LangItem :: I128SuboFnLangItem , RhsKind :: Unchanged ) ,
230+ ( BinOp :: Sub , false ) => ( LangItem :: U128SuboFnLangItem , RhsKind :: Unchanged ) ,
231+ ( BinOp :: Mul , true ) => ( LangItem :: I128MuloFnLangItem , RhsKind :: Unchanged ) ,
232+ ( BinOp :: Mul , false ) => ( LangItem :: U128MuloFnLangItem , RhsKind :: Unchanged ) ,
233+ ( BinOp :: Shl , true ) => ( LangItem :: I128ShloFnLangItem , RhsKind :: ForceU128 ) ,
234+ ( BinOp :: Shl , false ) => ( LangItem :: U128ShloFnLangItem , RhsKind :: ForceU128 ) ,
235+ ( BinOp :: Shr , true ) => ( LangItem :: I128ShroFnLangItem , RhsKind :: ForceU128 ) ,
236+ ( BinOp :: Shr , false ) => ( LangItem :: U128ShroFnLangItem , RhsKind :: ForceU128 ) ,
183237 _ => bug ! ( "That should be all the checked ones?" ) ,
184238 } ;
185239 Some ( i)
0 commit comments