@@ -322,36 +322,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
322
322
} ,
323
323
}
324
324
} 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 ! ( ) ,
353
330
} ,
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) ;
355
345
} ;
356
346
357
347
let intrinsic = self . context . get_builtin_function ( name) ;
@@ -364,80 +354,87 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
364
354
( res. dereference ( self . location ) . to_rvalue ( ) , overflow)
365
355
}
366
356
357
+ /// Non-`__builtin_*` overflow operations with a `fn(T, T, &mut i32) -> T` signature.
367
358
pub fn operation_with_overflow (
368
359
& self ,
369
360
func_name : & str ,
370
361
lhs : RValue < ' gcc > ,
371
362
rhs : RValue < ' gcc > ,
363
+ width : u64 ,
372
364
) -> ( RValue < ' gcc > , RValue < ' gcc > ) {
373
365
let a_type = lhs. get_type ( ) ;
374
366
let b_type = rhs. get_type ( ) ;
375
367
debug_assert ! ( a_type. dyncast_array( ) . is_some( ) ) ;
376
368
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
+
377
377
let param_a = self . context . new_parameter ( self . location , a_type, "a" ) ;
378
378
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
+ } ;
383
390
let layout = self
384
391
. 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 ) )
386
393
. unwrap ( ) ;
387
394
388
395
let arg_abi = ArgAbi { layout, mode : PassMode :: Direct ( ArgAttributes :: new ( ) ) } ;
389
396
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 ( ) ,
391
398
ret : arg_abi,
392
399
c_variadic : false ,
393
- fixed_count : 2 ,
400
+ fixed_count : 3 ,
394
401
conv : Conv :: C ,
395
402
can_unwind : false ,
396
403
} ;
397
404
fn_abi. adjust_for_foreign_abi ( self . cx , spec:: abi:: Abi :: C { unwind : false } ) . unwrap ( ) ;
398
405
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
+
410
414
let func = self . context . new_function (
411
415
self . location ,
412
416
FunctionType :: Extern ,
413
417
self . type_void ( ) ,
414
- & [ return_param , param_a, param_b] ,
418
+ & [ param_res , param_a, param_b, param_overflow ] ,
415
419
func_name,
416
420
false ,
417
421
) ;
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 ( )
427
425
} else {
428
426
let func = self . context . new_function (
429
427
self . location ,
430
428
FunctionType :: Extern ,
431
- return_type . as_type ( ) ,
432
- & [ param_a, param_b] ,
429
+ res_type ,
430
+ & [ param_a, param_b, param_overflow ] ,
433
431
func_name,
434
432
false ,
435
433
) ;
436
- self . context . new_call ( self . location , func, & [ lhs, rhs] )
434
+ self . context . new_call ( self . location , func, & [ lhs, rhs, overflow_addr ] )
437
435
} ;
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 ( ) )
441
438
}
442
439
443
440
pub fn gcc_icmp (
0 commit comments