@@ -322,36 +322,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
322322 } ,
323323 }
324324 } else {
325- match new_kind {
326- Int ( I128 ) | Uint ( U128 ) => {
327- let func_name = match oop {
328- OverflowOp :: Add => match new_kind {
329- Int ( I128 ) => "__rust_i128_addo" ,
330- Uint ( U128 ) => "__rust_u128_addo" ,
331- _ => unreachable ! ( ) ,
332- } ,
333- OverflowOp :: Sub => match new_kind {
334- Int ( I128 ) => "__rust_i128_subo" ,
335- Uint ( U128 ) => "__rust_u128_subo" ,
336- _ => unreachable ! ( ) ,
337- } ,
338- OverflowOp :: Mul => match new_kind {
339- Int ( I128 ) => "__rust_i128_mulo" , // TODO(antoyo): use __muloti4d instead?
340- Uint ( U128 ) => "__rust_u128_mulo" ,
341- _ => unreachable ! ( ) ,
342- } ,
343- } ;
344- return self . operation_with_overflow ( func_name, lhs, rhs) ;
345- }
346- _ => match oop {
347- OverflowOp :: Mul => match new_kind {
348- Int ( I32 ) => "__mulosi4" ,
349- Int ( I64 ) => "__mulodi4" ,
350- _ => unreachable ! ( ) ,
351- } ,
352- _ => unimplemented ! ( "overflow operation for {:?}" , new_kind) ,
325+ let ( func_name, width) = match oop {
326+ OverflowOp :: Add => match new_kind {
327+ Int ( I128 ) => ( "__rust_i128_addo" , 128 ) ,
328+ Uint ( U128 ) => ( "__rust_u128_addo" , 128 ) ,
329+ _ => unreachable ! ( ) ,
353330 } ,
354- }
331+ OverflowOp :: Sub => match new_kind {
332+ Int ( I128 ) => ( "__rust_i128_subo" , 128 ) ,
333+ Uint ( U128 ) => ( "__rust_u128_subo" , 128 ) ,
334+ _ => unreachable ! ( ) ,
335+ } ,
336+ OverflowOp :: Mul => match new_kind {
337+ Int ( I32 ) => ( "__mulosi4" , 32 ) ,
338+ Int ( I64 ) => ( "__mulodi4" , 64 ) ,
339+ Int ( I128 ) => ( "__rust_i128_mulo" , 128 ) , // TODO(antoyo): use __muloti4d instead?
340+ Uint ( U128 ) => ( "__rust_u128_mulo" , 128 ) ,
341+ _ => unreachable ! ( ) ,
342+ } ,
343+ } ;
344+ return self . operation_with_overflow ( func_name, lhs, rhs, width) ;
355345 } ;
356346
357347 let intrinsic = self . context . get_builtin_function ( name) ;
@@ -364,80 +354,87 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
364354 ( res. dereference ( self . location ) . to_rvalue ( ) , overflow)
365355 }
366356
357+ /// Non-`__builtin_*` overflow operations with a `fn(T, T, &mut i32) -> T` signature.
367358 pub fn operation_with_overflow (
368359 & self ,
369360 func_name : & str ,
370361 lhs : RValue < ' gcc > ,
371362 rhs : RValue < ' gcc > ,
363+ width : u64 ,
372364 ) -> ( RValue < ' gcc > , RValue < ' gcc > ) {
373365 let a_type = lhs. get_type ( ) ;
374366 let b_type = rhs. get_type ( ) ;
375367 debug_assert ! ( a_type. dyncast_array( ) . is_some( ) ) ;
376368 debug_assert ! ( b_type. dyncast_array( ) . is_some( ) ) ;
369+ let overflow_type = self . i32_type ;
370+ let overflow_param_type = overflow_type. make_pointer ( ) ;
371+ let res_type = a_type;
372+
373+ let overflow_value =
374+ self . current_func ( ) . new_local ( self . location , overflow_type, "overflow" ) ;
375+ let overflow_addr = overflow_value. get_address ( self . location ) ;
376+
377377 let param_a = self . context . new_parameter ( self . location , a_type, "a" ) ;
378378 let param_b = self . context . new_parameter ( self . location , b_type, "b" ) ;
379- let result_field = self . context . new_field ( self . location , a_type, "result" ) ;
380- let overflow_field = self . context . new_field ( self . location , self . bool_type , "overflow" ) ;
381-
382- let ret_ty = Ty :: new_tup ( self . tcx , & [ self . tcx . types . i128 , self . tcx . types . bool ] ) ;
379+ let param_overflow =
380+ self . context . new_parameter ( self . location , overflow_param_type, "overflow" ) ;
381+
382+ let a_elem_type = a_type. dyncast_array ( ) . expect ( "non-array a value" ) ;
383+ debug_assert ! ( a_elem_type. is_integral( ) ) ;
384+ let res_ty = match width {
385+ 32 => self . tcx . types . i32 ,
386+ 64 => self . tcx . types . i64 ,
387+ 128 => self . tcx . types . i128 ,
388+ _ => unreachable ! ( "unexpected integer size" ) ,
389+ } ;
383390 let layout = self
384391 . tcx
385- . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( ret_ty ) )
392+ . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( res_ty ) )
386393 . unwrap ( ) ;
387394
388395 let arg_abi = ArgAbi { layout, mode : PassMode :: Direct ( ArgAttributes :: new ( ) ) } ;
389396 let mut fn_abi = FnAbi {
390- args : vec ! [ arg_abi. clone( ) , arg_abi. clone( ) ] . into_boxed_slice ( ) ,
397+ args : vec ! [ arg_abi. clone( ) , arg_abi. clone( ) , arg_abi . clone ( ) ] . into_boxed_slice ( ) ,
391398 ret : arg_abi,
392399 c_variadic : false ,
393- fixed_count : 2 ,
400+ fixed_count : 3 ,
394401 conv : Conv :: C ,
395402 can_unwind : false ,
396403 } ;
397404 fn_abi. adjust_for_foreign_abi ( self . cx , spec:: abi:: Abi :: C { unwind : false } ) . unwrap ( ) ;
398405
399- let indirect = matches ! ( fn_abi. ret. mode, PassMode :: Indirect { .. } ) ;
400-
401- let return_type = self
402- . context
403- . new_struct_type ( self . location , "result_overflow" , & [ result_field, overflow_field] ) ;
404- let result = if indirect {
405- let return_value =
406- self . current_func ( ) . new_local ( self . location , return_type. as_type ( ) , "return_value" ) ;
407- let return_param_type = return_type. as_type ( ) . make_pointer ( ) ;
408- let return_param =
409- self . context . new_parameter ( self . location , return_param_type, "return_value" ) ;
406+ let ret_indirect = matches ! ( fn_abi. ret. mode, PassMode :: Indirect { .. } ) ;
407+
408+ let result = if ret_indirect {
409+ let res_value = self . current_func ( ) . new_local ( self . location , res_type, "result_value" ) ;
410+ let res_addr = res_value. get_address ( self . location ) ;
411+ let res_param_type = res_type. make_pointer ( ) ;
412+ let param_res = self . context . new_parameter ( self . location , res_param_type, "result" ) ;
413+
410414 let func = self . context . new_function (
411415 self . location ,
412416 FunctionType :: Extern ,
413417 self . type_void ( ) ,
414- & [ return_param , param_a, param_b] ,
418+ & [ param_res , param_a, param_b, param_overflow ] ,
415419 func_name,
416420 false ,
417421 ) ;
418- self . llbb ( ) . add_eval (
419- self . location ,
420- self . context . new_call ( self . location , func, & [
421- return_value. get_address ( self . location ) ,
422- lhs,
423- rhs,
424- ] ) ,
425- ) ;
426- return_value. to_rvalue ( )
422+ let _void =
423+ self . context . new_call ( self . location , func, & [ res_addr, lhs, rhs, overflow_addr] ) ;
424+ res_value. to_rvalue ( )
427425 } else {
428426 let func = self . context . new_function (
429427 self . location ,
430428 FunctionType :: Extern ,
431- return_type . as_type ( ) ,
432- & [ param_a, param_b] ,
429+ res_type ,
430+ & [ param_a, param_b, param_overflow ] ,
433431 func_name,
434432 false ,
435433 ) ;
436- self . context . new_call ( self . location , func, & [ lhs, rhs] )
434+ self . context . new_call ( self . location , func, & [ lhs, rhs, overflow_addr ] )
437435 } ;
438- let overflow = result. access_field ( self . location , overflow_field) ;
439- let int_result = result. access_field ( self . location , result_field) ;
440- ( int_result, overflow)
436+
437+ ( result, self . context . new_cast ( self . location , overflow_value, self . bool_type ) . to_rvalue ( ) )
441438 }
442439
443440 pub fn gcc_icmp (
0 commit comments