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;
@@ -97,12 +97,12 @@ impl GccType for Reg {
97
97
98
98
pub trait FnAbiGccExt < ' gcc , ' tcx > {
99
99
// TODO(antoyo): return a function pointer type instead?
100
- fn gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> ( Type < ' gcc > , Vec < Type < ' gcc > > , bool , FxHashSet < usize > ) ;
100
+ fn gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> ( Type < ' gcc > , Vec < Type < ' gcc > > , bool , FxHashSet < usize > , Vec < FnAttribute < ' gcc > > ) ;
101
101
fn ptr_to_gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> Type < ' gcc > ;
102
102
}
103
103
104
104
impl < ' gcc , ' tcx > FnAbiGccExt < ' gcc , ' tcx > for FnAbi < ' tcx , Ty < ' tcx > > {
105
- fn gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> ( Type < ' gcc > , Vec < Type < ' gcc > > , bool , FxHashSet < usize > ) {
105
+ fn gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> ( Type < ' gcc > , Vec < Type < ' gcc > > , bool , FxHashSet < usize > , Vec < FnAttribute < ' gcc > > ) {
106
106
let mut on_stack_param_indices = FxHashSet :: default ( ) ;
107
107
108
108
// This capacity calculation is approximate.
@@ -120,28 +120,33 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
120
120
cx. type_void ( )
121
121
}
122
122
} ;
123
+ let mut non_null_args = Vec :: new ( ) ;
123
124
124
125
#[ cfg( feature = "master" ) ]
125
- let apply_attrs = |ty : Type < ' gcc > , attrs : & ArgAttributes | {
126
- if cx. sess ( ) . opts . optimize != config:: OptLevel :: No
127
- && attrs. regular . contains ( rustc_target:: abi:: call:: ArgAttribute :: NoAlias )
128
- {
129
- ty. make_restrict ( )
130
- } else {
131
- ty
126
+ let mut apply_attrs = |mut ty : Type < ' gcc > , attrs : & ArgAttributes , arg_index : usize | {
127
+ if cx. sess ( ) . opts . optimize == config:: OptLevel :: No {
128
+ return ty;
132
129
}
130
+ if attrs. regular . contains ( rustc_target:: abi:: call:: ArgAttribute :: NoAlias ) {
131
+ ty = ty. make_restrict ( )
132
+ }
133
+ if attrs. regular . contains ( rustc_target:: abi:: call:: ArgAttribute :: NonNull ) {
134
+ non_null_args. push ( arg_index as i32 + 1 ) ;
135
+ }
136
+ ty
133
137
} ;
134
138
#[ cfg( not( feature = "master" ) ) ]
135
- let apply_attrs = |ty : Type < ' gcc > , _attrs : & ArgAttributes | {
139
+ let apply_attrs = |ty : Type < ' gcc > , _attrs : & ArgAttributes , _arg_index : usize | {
136
140
ty
137
141
} ;
138
142
139
143
for arg in self . args . iter ( ) {
140
144
let arg_ty = match arg. mode {
141
145
PassMode :: Ignore => continue ,
142
146
PassMode :: Pair ( a, b) => {
143
- argument_tys. push ( apply_attrs ( arg. layout . scalar_pair_element_gcc_type ( cx, 0 , true ) , & a) ) ;
144
- argument_tys. push ( apply_attrs ( arg. layout . scalar_pair_element_gcc_type ( cx, 1 , true ) , & b) ) ;
147
+ let arg_pos = argument_tys. len ( ) ;
148
+ argument_tys. push ( apply_attrs ( arg. layout . scalar_pair_element_gcc_type ( cx, 0 , true ) , & a, arg_pos) ) ;
149
+ argument_tys. push ( apply_attrs ( arg. layout . scalar_pair_element_gcc_type ( cx, 1 , true ) , & b, arg_pos + 1 ) ) ;
145
150
continue ;
146
151
}
147
152
PassMode :: Cast ( ref cast, pad_i32) => {
@@ -150,30 +155,41 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
150
155
argument_tys. push ( Reg :: i32 ( ) . gcc_type ( cx) ) ;
151
156
}
152
157
let ty = cast. gcc_type ( cx) ;
153
- apply_attrs ( ty, & cast. attrs )
158
+ apply_attrs ( ty, & cast. attrs , argument_tys . len ( ) )
154
159
}
155
160
PassMode :: Indirect { attrs : _, extra_attrs : None , on_stack : true } => {
156
161
// This is a "byval" argument, so we don't apply the `restrict` attribute on it.
157
162
on_stack_param_indices. insert ( argument_tys. len ( ) ) ;
158
163
arg. memory_ty ( cx)
159
164
} ,
160
- PassMode :: Direct ( attrs) => apply_attrs ( arg. layout . immediate_gcc_type ( cx) , & attrs) ,
165
+ PassMode :: Direct ( attrs) => apply_attrs ( arg. layout . immediate_gcc_type ( cx) , & attrs, argument_tys . len ( ) ) ,
161
166
PassMode :: Indirect { attrs, extra_attrs : None , on_stack : false } => {
162
- apply_attrs ( cx. type_ptr_to ( arg. memory_ty ( cx) ) , & attrs)
167
+ apply_attrs ( cx. type_ptr_to ( arg. memory_ty ( cx) ) , & attrs, argument_tys . len ( ) )
163
168
}
164
169
PassMode :: Indirect { attrs, extra_attrs : Some ( extra_attrs) , on_stack } => {
165
170
assert ! ( !on_stack) ;
166
- apply_attrs ( apply_attrs ( cx. type_ptr_to ( arg. memory_ty ( cx) ) , & attrs) , & extra_attrs)
171
+ let ty = apply_attrs ( cx. type_ptr_to ( arg. memory_ty ( cx) ) , & attrs, argument_tys. len ( ) ) ;
172
+ apply_attrs ( ty, & extra_attrs, argument_tys. len ( ) )
167
173
}
168
174
} ;
169
175
argument_tys. push ( arg_ty) ;
170
176
}
171
177
172
- ( return_ty, argument_tys, self . c_variadic , on_stack_param_indices)
178
+ #[ cfg( feature = "master" ) ]
179
+ let fn_attrs = if non_null_args. is_empty ( ) {
180
+ Vec :: new ( )
181
+ } else {
182
+ vec ! [ FnAttribute :: NonNull ( non_null_args) ]
183
+ } ;
184
+ #[ cfg( not( feature = "master" ) ) ]
185
+ let fn_attrs = Vec :: new ( ) ;
186
+
187
+ ( return_ty, argument_tys, self . c_variadic , on_stack_param_indices, fn_attrs)
173
188
}
174
189
175
190
fn ptr_to_gcc_type ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> Type < ' gcc > {
176
- let ( return_type, params, variadic, on_stack_param_indices) = self . gcc_type ( cx) ;
191
+ // FIXME: Should we do something with `fn_attrs`?
192
+ let ( return_type, params, variadic, on_stack_param_indices, _fn_attrs) = self . gcc_type ( cx) ;
177
193
let pointer_type = cx. context . new_function_pointer_type ( None , return_type, & params, variadic) ;
178
194
cx. on_stack_params . borrow_mut ( ) . insert ( pointer_type. dyncast_function_ptr_type ( ) . expect ( "function ptr type" ) , on_stack_param_indices) ;
179
195
pointer_type
0 commit comments