@@ -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 = match oop {
326+ OverflowOp :: Add => match new_kind {
327+ Int ( I128 ) => "__rust_i128_addo" ,
328+ Uint ( U128 ) => "__rust_u128_addo" ,
329+ _ => unreachable ! ( ) ,
353330 } ,
354- }
331+ OverflowOp :: Sub => match new_kind {
332+ Int ( I128 ) => "__rust_i128_subo" ,
333+ Uint ( U128 ) => "__rust_u128_subo" ,
334+ _ => unreachable ! ( ) ,
335+ } ,
336+ OverflowOp :: Mul => match new_kind {
337+ Int ( I32 ) => "__mulosi4" ,
338+ Int ( I64 ) => "__mulodi4" ,
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) ;
355345 } ;
356346
357347 let intrinsic = self . context . get_builtin_function ( name) ;
@@ -364,6 +354,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
364354 ( res. dereference ( self . location ) . to_rvalue ( ) , overflow)
365355 }
366356
357+ /// `i128` overflow operations with a `fn(i128, i128, &mut i32) -> i128` signature.
367358 pub fn operation_with_overflow (
368359 & self ,
369360 func_name : & str ,
@@ -374,70 +365,65 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
374365 let b_type = rhs. get_type ( ) ;
375366 debug_assert ! ( a_type. dyncast_array( ) . is_some( ) ) ;
376367 debug_assert ! ( b_type. dyncast_array( ) . is_some( ) ) ;
368+ let oflow_type = self . bool_type ;
369+ let oflow_param_type = oflow_type. make_pointer ( ) ;
370+ let res_type = a_type;
371+
372+ let oflow_value = self . current_func ( ) . new_local ( self . location , oflow_type, "overflow" ) ;
373+ let oflow_addr = oflow_value. get_address ( self . location ) ;
374+
377375 let param_a = self . context . new_parameter ( self . location , a_type, "a" ) ;
378376 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" ) ;
377+ let param_oflow = self . context . new_parameter ( self . location , oflow_param_type, "oflow" ) ;
381378
382- let ret_ty = Ty :: new_tup ( self . tcx , & [ self . tcx . types . i128 , self . tcx . types . bool ] ) ;
379+ let res_ty = self . tcx . types . i128 ;
383380 let layout = self
384381 . tcx
385- . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( ret_ty ) )
382+ . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( res_ty ) )
386383 . unwrap ( ) ;
387384
388385 let arg_abi = ArgAbi { layout, mode : PassMode :: Direct ( ArgAttributes :: new ( ) ) } ;
389386 let mut fn_abi = FnAbi {
390- args : vec ! [ arg_abi. clone( ) , arg_abi. clone( ) ] . into_boxed_slice ( ) ,
387+ args : vec ! [ arg_abi. clone( ) , arg_abi. clone( ) , arg_abi . clone ( ) ] . into_boxed_slice ( ) ,
391388 ret : arg_abi,
392389 c_variadic : false ,
393- fixed_count : 2 ,
390+ fixed_count : 3 ,
394391 conv : Conv :: C ,
395392 can_unwind : false ,
396393 } ;
397394 fn_abi. adjust_for_foreign_abi ( self . cx , spec:: abi:: Abi :: C { unwind : false } ) . unwrap ( ) ;
398395
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" ) ;
396+ let ret_indirect = matches ! ( fn_abi. ret. mode, PassMode :: Indirect { .. } ) ;
397+
398+ if ret_indirect {
399+ let res_value = self . current_func ( ) . new_local ( self . location , res_type, "result_value" ) ;
400+ let res_addr = res_value. get_address ( self . location ) ;
401+ let res_param_type = res_type. make_pointer ( ) ;
402+ let param_res = self . context . new_parameter ( self . location , res_param_type, "result" ) ;
403+
410404 let func = self . context . new_function (
411405 self . location ,
412406 FunctionType :: Extern ,
413407 self . type_void ( ) ,
414- & [ return_param , param_a, param_b] ,
408+ & [ param_res , param_a, param_b, param_oflow ] ,
415409 func_name,
416410 false ,
417411 ) ;
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 ( )
412+ let _void =
413+ self . context . new_call ( self . location , func, & [ res_addr, lhs, rhs, oflow_addr] ) ;
414+ ( res_value. to_rvalue ( ) , oflow_value. to_rvalue ( ) )
427415 } else {
428416 let func = self . context . new_function (
429417 self . location ,
430418 FunctionType :: Extern ,
431- return_type . as_type ( ) ,
432- & [ param_a, param_b] ,
419+ res_type ,
420+ & [ param_a, param_b, param_oflow ] ,
433421 func_name,
434422 false ,
435423 ) ;
436- self . context . new_call ( self . location , func, & [ lhs, rhs] )
437- } ;
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)
424+ let res = self . context . new_call ( self . location , func, & [ lhs, rhs, oflow_addr] ) ;
425+ ( res, oflow_value. to_rvalue ( ) )
426+ }
441427 }
442428
443429 pub fn gcc_icmp (
0 commit comments