@@ -9,7 +9,7 @@ use gccjit::Type;
99use gccjit:: { ComparisonOp , Function , FunctionType , RValue , ToRValue , UnaryOp } ;
1010#[ cfg( feature = "master" ) ]
1111use rustc_abi:: ExternAbi ;
12- use rustc_abi:: { BackendRepr , HasDataLayout } ;
12+ use rustc_abi:: { BackendRepr , HasDataLayout , WrappingRange } ;
1313use rustc_codegen_ssa:: MemFlags ;
1414use rustc_codegen_ssa:: base:: wants_msvc_seh;
1515use rustc_codegen_ssa:: common:: IntPredicate ;
@@ -20,19 +20,15 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
2020use rustc_codegen_ssa:: traits:: MiscCodegenMethods ;
2121use rustc_codegen_ssa:: traits:: {
2222 ArgAbiBuilderMethods , BaseTypeCodegenMethods , BuilderMethods , ConstCodegenMethods ,
23- IntrinsicCallBuilderMethods ,
23+ IntrinsicCallBuilderMethods , LayoutTypeCodegenMethods ,
2424} ;
2525use rustc_middle:: bug;
26- #[ cfg( feature = "master" ) ]
27- use rustc_middle:: ty:: layout:: FnAbiOf ;
28- use rustc_middle:: ty:: layout:: LayoutOf ;
26+ use rustc_middle:: ty:: layout:: { FnAbiOf , LayoutOf } ;
2927use rustc_middle:: ty:: { self , Instance , Ty } ;
3028use rustc_span:: { Span , Symbol , sym} ;
3129use rustc_target:: callconv:: { ArgAbi , PassMode } ;
3230
33- #[ cfg( feature = "master" ) ]
34- use crate :: abi:: FnAbiGccExt ;
35- use crate :: abi:: GccType ;
31+ use crate :: abi:: { FnAbiGccExt , GccType } ;
3632use crate :: builder:: Builder ;
3733use crate :: common:: { SignType , TypeReflection } ;
3834use crate :: context:: CodegenCx ;
@@ -609,6 +605,94 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
609605 Ok ( ( ) )
610606 }
611607
608+ fn codegen_llvm_intrinsic_call (
609+ & mut self ,
610+ instance : ty:: Instance < ' tcx > ,
611+ args : & [ OperandRef < ' tcx , Self :: Value > ] ,
612+ is_cleanup : bool ,
613+ ) -> Self :: Value {
614+ let func = if let Some ( & func) = self . intrinsic_instances . borrow ( ) . get ( & instance) {
615+ func
616+ } else {
617+ let sym = self . tcx . symbol_name ( instance) . name ;
618+
619+ let func = if let Some ( func) = self . intrinsics . borrow ( ) . get ( sym) {
620+ * func
621+ } else {
622+ self . linkage . set ( FunctionType :: Extern ) ;
623+ let fn_abi = self . fn_abi_of_instance ( instance, ty:: List :: empty ( ) ) ;
624+ let fn_ty = fn_abi. gcc_type ( self ) ;
625+
626+ let func = match sym {
627+ "llvm.fma.f16" => {
628+ // fma is not a target builtin, but a normal builtin, so we handle it differently
629+ // here.
630+ self . context . get_builtin_function ( "fma" )
631+ }
632+ _ => llvm:: intrinsic ( sym, self ) ,
633+ } ;
634+
635+ self . intrinsics . borrow_mut ( ) . insert ( sym. to_string ( ) , func) ;
636+
637+ self . on_stack_function_params
638+ . borrow_mut ( )
639+ . insert ( func, fn_ty. on_stack_param_indices ) ;
640+ #[ cfg( feature = "master" ) ]
641+ for fn_attr in fn_ty. fn_attributes {
642+ func. add_attribute ( fn_attr) ;
643+ }
644+
645+ crate :: attributes:: from_fn_attrs ( self , func, instance) ;
646+
647+ func
648+ } ;
649+
650+ self . intrinsic_instances . borrow_mut ( ) . insert ( instance, func) ;
651+
652+ func
653+ } ;
654+ let fn_ptr = func. get_address ( None ) ;
655+ let fn_ty = fn_ptr. get_type ( ) ;
656+
657+ let mut llargs = vec ! [ ] ;
658+
659+ for arg in args {
660+ match arg. val {
661+ OperandValue :: ZeroSized => { }
662+ OperandValue :: Immediate ( _) => llargs. push ( arg. immediate ( ) ) ,
663+ OperandValue :: Pair ( a, b) => {
664+ llargs. push ( a) ;
665+ llargs. push ( b) ;
666+ }
667+ OperandValue :: Ref ( op_place_val) => {
668+ let mut llval = op_place_val. llval ;
669+ // We can't use `PlaceRef::load` here because the argument
670+ // may have a type we don't treat as immediate, but the ABI
671+ // used for this call is passing it by-value. In that case,
672+ // the load would just produce `OperandValue::Ref` instead
673+ // of the `OperandValue::Immediate` we need for the call.
674+ llval = self . load ( self . backend_type ( arg. layout ) , llval, op_place_val. align ) ;
675+ if let BackendRepr :: Scalar ( scalar) = arg. layout . backend_repr {
676+ if scalar. is_bool ( ) {
677+ self . range_metadata ( llval, WrappingRange { start : 0 , end : 1 } ) ;
678+ }
679+ // We store bools as `i8` so we need to truncate to `i1`.
680+ llval = self . to_immediate_scalar ( llval, scalar) ;
681+ }
682+ llargs. push ( llval) ;
683+ }
684+ }
685+ }
686+
687+ // FIXME directly use the llvm intrinsic adjustment functions here
688+ let llret = self . call ( fn_ty, None , None , fn_ptr, & llargs, None , None ) ;
689+ if is_cleanup {
690+ self . apply_attrs_to_cleanup_callsite ( llret) ;
691+ }
692+
693+ llret
694+ }
695+
612696 fn abort ( & mut self ) {
613697 let func = self . context . get_builtin_function ( "abort" ) ;
614698 let func: RValue < ' gcc > = unsafe { std:: mem:: transmute ( func) } ;
0 commit comments