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