11use std:: borrow:: Borrow ;
22use std:: cmp;
3+ use std:: iter:: zip;
34
45use libc:: c_uint;
56use rustc_abi:: { BackendRepr , HasDataLayout , Primitive , Reg , RegKind , Size } ;
@@ -308,7 +309,9 @@ impl<'ll, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
308309}
309310
310311pub ( crate ) trait FnAbiLlvmExt < ' ll , ' tcx > {
311- fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
312+ fn llvm_return_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
313+ fn llvm_argument_types ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> Vec < & ' ll Type > ;
314+ fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > , name : & [ u8 ] ) -> & ' ll Type ;
312315 fn ptr_to_llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
313316 fn llvm_cconv ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> llvm:: CallConv ;
314317
@@ -325,26 +328,29 @@ pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> {
325328}
326329
327330impl < ' ll , ' tcx > FnAbiLlvmExt < ' ll , ' tcx > for FnAbi < ' tcx , Ty < ' tcx > > {
328- fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type {
331+ fn llvm_return_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type {
332+ match & self . ret . mode {
333+ PassMode :: Ignore => cx. type_void ( ) ,
334+ PassMode :: Direct ( _) | PassMode :: Pair ( ..) => self . ret . layout . immediate_llvm_type ( cx) ,
335+ PassMode :: Cast { cast, pad_i32 : _ } => cast. llvm_type ( cx) ,
336+ PassMode :: Indirect { .. } => cx. type_void ( ) ,
337+ }
338+ }
339+
340+ fn llvm_argument_types ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> Vec < & ' ll Type > {
341+ let indirect_return = matches ! ( self . ret. mode, PassMode :: Indirect { .. } ) ;
342+
329343 // Ignore "extra" args from the call site for C variadic functions.
330344 // Only the "fixed" args are part of the LLVM function signature.
331345 let args =
332346 if self . c_variadic { & self . args [ ..self . fixed_count as usize ] } else { & self . args } ;
333347
334- // This capacity calculation is approximate.
335- let mut llargument_tys = Vec :: with_capacity (
336- self . args . len ( ) + if let PassMode :: Indirect { .. } = self . ret . mode { 1 } else { 0 } ,
337- ) ;
348+ let mut llargument_tys =
349+ Vec :: with_capacity ( args. len ( ) + if indirect_return { 1 } else { 0 } ) ;
338350
339- let llreturn_ty = match & self . ret . mode {
340- PassMode :: Ignore => cx. type_void ( ) ,
341- PassMode :: Direct ( _) | PassMode :: Pair ( ..) => self . ret . layout . immediate_llvm_type ( cx) ,
342- PassMode :: Cast { cast, pad_i32 : _ } => cast. llvm_type ( cx) ,
343- PassMode :: Indirect { .. } => {
344- llargument_tys. push ( cx. type_ptr ( ) ) ;
345- cx. type_void ( )
346- }
347- } ;
351+ if indirect_return {
352+ llargument_tys. push ( cx. type_ptr ( ) ) ;
353+ }
348354
349355 for arg in args {
350356 // Note that the exact number of arguments pushed here is carefully synchronized with
@@ -391,10 +397,45 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
391397 llargument_tys. push ( llarg_ty) ;
392398 }
393399
394- if self . c_variadic {
395- cx. type_variadic_func ( & llargument_tys, llreturn_ty)
400+ llargument_tys
401+ }
402+
403+ fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > , name : & [ u8 ] ) -> & ' ll Type {
404+ let actual_return_ty = self . llvm_return_type ( cx) ;
405+ let actual_argument_tys = self . llvm_argument_types ( cx) ;
406+
407+ if name. starts_with ( b"llvm." )
408+ && let Some ( ( intrinsic, type_params) ) = cx. parse_intrinsic_name ( name)
409+ {
410+ let fn_ty = cx. intrinsic_type ( intrinsic, & type_params) ;
411+
412+ let expected_return_ty = cx. get_return_type ( fn_ty) ;
413+ let expected_argument_tys = cx. func_params_types ( fn_ty) ;
414+
415+ let equate_ty = |rust_ty, llvm_ty| rust_ty == llvm_ty;
416+
417+ if actual_argument_tys. len ( ) != expected_argument_tys. len ( ) {
418+ todo ! ( "A very friendly error msg" )
419+ }
420+
421+ if !equate_ty ( actual_return_ty, expected_return_ty) {
422+ todo ! ( "A very friendly error msg" )
423+ }
424+ for ( actual_argument_ty, expected_argument_ty) in
425+ zip ( actual_argument_tys, expected_argument_tys)
426+ {
427+ if !equate_ty ( actual_argument_ty, expected_argument_ty) {
428+ todo ! ( "A very friendly error msg" )
429+ }
430+ }
431+
432+ fn_ty
396433 } else {
397- cx. type_func ( & llargument_tys, llreturn_ty)
434+ if self . c_variadic {
435+ cx. type_variadic_func ( & actual_argument_tys, actual_return_ty)
436+ } else {
437+ cx. type_func ( & actual_argument_tys, actual_return_ty)
438+ }
398439 }
399440 }
400441
0 commit comments