1- use gccjit:: { ToLValue , ToRValue , Type } ;
1+ use gccjit:: { FnAttribute , ToLValue , ToRValue , Type } ;
22use rustc_codegen_ssa:: traits:: { AbiBuilderMethods , BaseTypeMethods } ;
33use rustc_data_structures:: fx:: FxHashSet ;
44use rustc_middle:: bug;
@@ -98,12 +98,12 @@ impl GccType for Reg {
9898
9999pub trait FnAbiGccExt < ' gcc , ' tcx > {
100100 // TODO(antoyo): return a function pointer type instead?
101- fn gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> ( Type < ' gcc > , Vec < Type < ' gcc > > , bool , FxHashSet < usize > ) ;
101+ fn gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> ( Type < ' gcc > , Vec < Type < ' gcc > > , bool , FxHashSet < usize > , Vec < FnAttribute < ' gcc > > ) ;
102102 fn ptr_to_gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> Type < ' gcc > ;
103103}
104104
105105impl < ' gcc , ' tcx > FnAbiGccExt < ' gcc , ' tcx > for FnAbi < ' tcx , Ty < ' tcx > > {
106- fn gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> ( Type < ' gcc > , Vec < Type < ' gcc > > , bool , FxHashSet < usize > ) {
106+ fn gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> ( Type < ' gcc > , Vec < Type < ' gcc > > , bool , FxHashSet < usize > , Vec < FnAttribute < ' gcc > > ) {
107107 let mut on_stack_param_indices = FxHashSet :: default ( ) ;
108108
109109 // This capacity calculation is approximate.
@@ -121,28 +121,33 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
121121 cx. type_void ( )
122122 }
123123 } ;
124+ let mut non_null_args = Vec :: new ( ) ;
124125
125126 #[ cfg( feature = "master" ) ]
126- let apply_attrs = |ty : Type < ' gcc > , attrs : & ArgAttributes | {
127- if cx. sess ( ) . opts . optimize != config:: OptLevel :: No
128- && attrs. regular . contains ( rustc_target:: abi:: call:: ArgAttribute :: NoAlias )
129- {
130- ty. make_restrict ( )
131- } else {
132- ty
127+ let mut apply_attrs = |mut ty : Type < ' gcc > , attrs : & ArgAttributes , arg_index : usize | {
128+ if cx. sess ( ) . opts . optimize == config:: OptLevel :: No {
129+ return ty;
133130 }
131+ if attrs. regular . contains ( rustc_target:: abi:: call:: ArgAttribute :: NoAlias ) {
132+ ty = ty. make_restrict ( )
133+ }
134+ if attrs. regular . contains ( rustc_target:: abi:: call:: ArgAttribute :: NonNull ) {
135+ non_null_args. push ( arg_index as i32 + 1 ) ;
136+ }
137+ ty
134138 } ;
135139 #[ cfg( not( feature = "master" ) ) ]
136- let apply_attrs = |ty : Type < ' gcc > , _attrs : & ArgAttributes | {
140+ let apply_attrs = |ty : Type < ' gcc > , _attrs : & ArgAttributes , _arg_index : usize | {
137141 ty
138142 } ;
139143
140144 for arg in self . args . iter ( ) {
141145 let arg_ty = match arg. mode {
142146 PassMode :: Ignore => continue ,
143147 PassMode :: Pair ( a, b) => {
144- argument_tys. push ( apply_attrs ( arg. layout . scalar_pair_element_gcc_type ( cx, 0 ) , & a) ) ;
145- argument_tys. push ( apply_attrs ( arg. layout . scalar_pair_element_gcc_type ( cx, 1 ) , & b) ) ;
148+ let arg_pos = argument_tys. len ( ) ;
149+ argument_tys. push ( apply_attrs ( arg. layout . scalar_pair_element_gcc_type ( cx, 0 ) , & a, arg_pos) ) ;
150+ argument_tys. push ( apply_attrs ( arg. layout . scalar_pair_element_gcc_type ( cx, 1 ) , & b, arg_pos + 1 ) ) ;
146151 continue ;
147152 }
148153 PassMode :: Cast { ref cast, pad_i32 } => {
@@ -151,30 +156,41 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
151156 argument_tys. push ( Reg :: i32 ( ) . gcc_type ( cx) ) ;
152157 }
153158 let ty = cast. gcc_type ( cx) ;
154- apply_attrs ( ty, & cast. attrs )
159+ apply_attrs ( ty, & cast. attrs , argument_tys . len ( ) )
155160 }
156161 PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack : true } => {
157162 // This is a "byval" argument, so we don't apply the `restrict` attribute on it.
158163 on_stack_param_indices. insert ( argument_tys. len ( ) ) ;
159164 arg. memory_ty ( cx)
160165 } ,
161- PassMode :: Direct ( attrs) => apply_attrs ( arg. layout . immediate_gcc_type ( cx) , & attrs) ,
166+ PassMode :: Direct ( attrs) => apply_attrs ( arg. layout . immediate_gcc_type ( cx) , & attrs, argument_tys . len ( ) ) ,
162167 PassMode :: Indirect { attrs, meta_attrs : None , on_stack : false } => {
163- apply_attrs ( cx. type_ptr_to ( arg. memory_ty ( cx) ) , & attrs)
168+ apply_attrs ( cx. type_ptr_to ( arg. memory_ty ( cx) ) , & attrs, argument_tys . len ( ) )
164169 }
165170 PassMode :: Indirect { attrs, meta_attrs : Some ( meta_attrs) , on_stack } => {
166171 assert ! ( !on_stack) ;
167- apply_attrs ( apply_attrs ( cx. type_ptr_to ( arg. memory_ty ( cx) ) , & attrs) , & meta_attrs)
172+ let ty = apply_attrs ( cx. type_ptr_to ( arg. memory_ty ( cx) ) , & attrs, argument_tys. len ( ) ) ;
173+ apply_attrs ( ty, & meta_attrs, argument_tys. len ( ) )
168174 }
169175 } ;
170176 argument_tys. push ( arg_ty) ;
171177 }
172178
173- ( return_ty, argument_tys, self . c_variadic , on_stack_param_indices)
179+ #[ cfg( feature = "master" ) ]
180+ let fn_attrs = if non_null_args. is_empty ( ) {
181+ Vec :: new ( )
182+ } else {
183+ vec ! [ FnAttribute :: NonNull ( non_null_args) ]
184+ } ;
185+ #[ cfg( not( feature = "master" ) ) ]
186+ let fn_attrs = Vec :: new ( ) ;
187+
188+ ( return_ty, argument_tys, self . c_variadic , on_stack_param_indices, fn_attrs)
174189 }
175190
176191 fn ptr_to_gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> Type < ' gcc > {
177- let ( return_type, params, variadic, on_stack_param_indices) = self . gcc_type ( cx) ;
192+ // FIXME: Should we do something with `fn_attrs`?
193+ let ( return_type, params, variadic, on_stack_param_indices, _fn_attrs) = self . gcc_type ( cx) ;
178194 let pointer_type = cx. context . new_function_pointer_type ( None , return_type, & params, variadic) ;
179195 cx. on_stack_params . borrow_mut ( ) . insert ( pointer_type. dyncast_function_ptr_type ( ) . expect ( "function ptr type" ) , on_stack_param_indices) ;
180196 pointer_type
0 commit comments