1
- use gccjit:: { ToLValue , ToRValue , Type } ;
1
+ use gccjit:: { FnAttribute , ToLValue , ToRValue , Type } ;
2
2
use rustc_codegen_ssa:: traits:: { AbiBuilderMethods , BaseTypeMethods } ;
3
3
use rustc_data_structures:: fx:: FxHashSet ;
4
4
use rustc_middle:: bug;
@@ -98,12 +98,12 @@ impl GccType for Reg {
98
98
99
99
pub trait FnAbiGccExt < ' gcc , ' tcx > {
100
100
// 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 > > ) ;
102
102
fn ptr_to_gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> Type < ' gcc > ;
103
103
}
104
104
105
105
impl < ' 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 > > ) {
107
107
let mut on_stack_param_indices = FxHashSet :: default ( ) ;
108
108
109
109
// This capacity calculation is approximate.
@@ -121,28 +121,33 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
121
121
cx. type_void ( )
122
122
}
123
123
} ;
124
+ let mut non_null_args = Vec :: new ( ) ;
124
125
125
126
#[ 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;
133
130
}
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
134
138
} ;
135
139
#[ 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 | {
137
141
ty
138
142
} ;
139
143
140
144
for arg in self . args . iter ( ) {
141
145
let arg_ty = match arg. mode {
142
146
PassMode :: Ignore => continue ,
143
147
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 ) ) ;
146
151
continue ;
147
152
}
148
153
PassMode :: Cast { ref cast, pad_i32 } => {
@@ -151,30 +156,41 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
151
156
argument_tys. push ( Reg :: i32 ( ) . gcc_type ( cx) ) ;
152
157
}
153
158
let ty = cast. gcc_type ( cx) ;
154
- apply_attrs ( ty, & cast. attrs )
159
+ apply_attrs ( ty, & cast. attrs , argument_tys . len ( ) )
155
160
}
156
161
PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack : true } => {
157
162
// This is a "byval" argument, so we don't apply the `restrict` attribute on it.
158
163
on_stack_param_indices. insert ( argument_tys. len ( ) ) ;
159
164
arg. memory_ty ( cx)
160
165
} ,
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 ( ) ) ,
162
167
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 ( ) )
164
169
}
165
170
PassMode :: Indirect { attrs, meta_attrs : Some ( meta_attrs) , on_stack } => {
166
171
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 ( ) )
168
174
}
169
175
} ;
170
176
argument_tys. push ( arg_ty) ;
171
177
}
172
178
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)
174
189
}
175
190
176
191
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) ;
178
194
let pointer_type = cx. context . new_function_pointer_type ( None , return_type, & params, variadic) ;
179
195
cx. on_stack_params . borrow_mut ( ) . insert ( pointer_type. dyncast_function_ptr_type ( ) . expect ( "function ptr type" ) , on_stack_param_indices) ;
180
196
pointer_type
0 commit comments