@@ -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 = match oop {
326
+ OverflowOp :: Add => match new_kind {
327
+ Int ( I128 ) => "__rust_i128_addo" ,
328
+ Uint ( U128 ) => "__rust_u128_addo" ,
329
+ _ => unreachable ! ( ) ,
353
330
} ,
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) ;
355
345
} ;
356
346
357
347
let intrinsic = self . context . get_builtin_function ( name) ;
@@ -364,6 +354,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
364
354
( res. dereference ( self . location ) . to_rvalue ( ) , overflow)
365
355
}
366
356
357
+ /// `i128` overflow operations with a `fn(i128, i128, &mut i32) -> i128` signature.
367
358
pub fn operation_with_overflow (
368
359
& self ,
369
360
func_name : & str ,
@@ -374,70 +365,65 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
374
365
let b_type = rhs. get_type ( ) ;
375
366
debug_assert ! ( a_type. dyncast_array( ) . is_some( ) ) ;
376
367
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
+
377
375
let param_a = self . context . new_parameter ( self . location , a_type, "a" ) ;
378
376
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" ) ;
381
378
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 ;
383
380
let layout = self
384
381
. 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 ) )
386
383
. unwrap ( ) ;
387
384
388
385
let arg_abi = ArgAbi { layout, mode : PassMode :: Direct ( ArgAttributes :: new ( ) ) } ;
389
386
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 ( ) ,
391
388
ret : arg_abi,
392
389
c_variadic : false ,
393
- fixed_count : 2 ,
390
+ fixed_count : 3 ,
394
391
conv : Conv :: C ,
395
392
can_unwind : false ,
396
393
} ;
397
394
fn_abi. adjust_for_foreign_abi ( self . cx , spec:: abi:: Abi :: C { unwind : false } ) . unwrap ( ) ;
398
395
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
+
410
404
let func = self . context . new_function (
411
405
self . location ,
412
406
FunctionType :: Extern ,
413
407
self . type_void ( ) ,
414
- & [ return_param , param_a, param_b] ,
408
+ & [ param_res , param_a, param_b, param_oflow ] ,
415
409
func_name,
416
410
false ,
417
411
) ;
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 ( ) )
427
415
} else {
428
416
let func = self . context . new_function (
429
417
self . location ,
430
418
FunctionType :: Extern ,
431
- return_type . as_type ( ) ,
432
- & [ param_a, param_b] ,
419
+ res_type ,
420
+ & [ param_a, param_b, param_oflow ] ,
433
421
func_name,
434
422
false ,
435
423
) ;
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
+ }
441
427
}
442
428
443
429
pub fn gcc_icmp (
0 commit comments