@@ -16,8 +16,6 @@ use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
1616use rustc_target:: spec:: Arch ;
1717
1818use crate :: builder:: Builder ;
19- #[ cfg( feature = "master" ) ]
20- use crate :: common:: type_is_pointer;
2119use crate :: context:: CodegenCx ;
2220use crate :: type_of:: LayoutGccExt ;
2321
@@ -153,7 +151,10 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
153151 #[ cfg( not( feature = "master" ) ) ]
154152 let apply_attrs = |ty : Type < ' gcc > , _attrs : & ArgAttributes , _arg_index : usize | ty;
155153
156- for arg in self . args . iter ( ) {
154+ for ( source_arg_index, arg) in self . args . iter ( ) . enumerate ( ) {
155+ #[ cfg( not( feature = "master" ) ) ]
156+ let _ = source_arg_index;
157+
157158 let arg_ty = match arg. mode {
158159 PassMode :: Ignore => continue ,
159160 PassMode :: Pair ( a, b) => {
@@ -179,9 +180,28 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
179180 apply_attrs ( ty, & cast. attrs , argument_tys. len ( ) )
180181 }
181182 PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack : true } => {
182- // This is a "byval" argument, so we don't apply the `restrict` attribute on it.
183- on_stack_param_indices. insert ( argument_tys. len ( ) ) ;
184- arg. layout . gcc_type ( cx)
183+ let x86_interrupt_first_arg = {
184+ #[ cfg( feature = "master" ) ]
185+ {
186+ source_arg_index == 0
187+ && matches ! ( self . conv, CanonAbi :: Interrupt ( InterruptKind :: X86 ) )
188+ }
189+ #[ cfg( not( feature = "master" ) ) ]
190+ {
191+ false
192+ }
193+ } ;
194+
195+ if x86_interrupt_first_arg {
196+ // Rust lowers the first `x86-interrupt` argument as a byval stack slot.
197+ // LLVM represents that as a pointer parameter with `byval`; GCC's
198+ // interrupt attribute likewise requires a pointer-shaped first parameter.
199+ cx. type_ptr_to ( arg. layout . gcc_type ( cx) )
200+ } else {
201+ // This is a "byval" argument, so we don't apply the `restrict` attribute on it.
202+ on_stack_param_indices. insert ( argument_tys. len ( ) ) ;
203+ arg. layout . gcc_type ( cx)
204+ }
185205 }
186206 PassMode :: Direct ( attrs) => {
187207 apply_attrs ( arg. layout . immediate_gcc_type ( cx) , & attrs, argument_tys. len ( ) )
@@ -279,33 +299,3 @@ pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option<FnAttri
279299 } ;
280300 Some ( attribute)
281301}
282-
283- /// GCC's `interrupt` attribute requires the first parameter of an `x86-interrupt`
284- /// function to be a pointer. When it is not, libgccjit aborts codegen with an internal
285- /// error and leaves no object file behind. Detect that case so the backend can emit a
286- /// clean diagnostic and skip the attribute instead of crashing (issue #833).
287- ///
288- /// This works on the already-lowered GCC argument types so callers that have them (e.g.
289- /// `declare_fn`) avoid a redundant ABI lowering. `x86-interrupt` functions return `()`,
290- /// so there is no struct-return pointer prepended and `arguments_type[0]` is the frame
291- /// argument.
292- #[ cfg( feature = "master" ) ]
293- pub fn x86_interrupt_first_arg_is_invalid < ' gcc > (
294- conv : CanonAbi ,
295- arguments_type : & [ Type < ' gcc > ] ,
296- ) -> bool {
297- matches ! ( conv, CanonAbi :: Interrupt ( InterruptKind :: X86 ) )
298- && arguments_type. first ( ) . is_none_or ( |ty| !type_is_pointer ( * ty) )
299- }
300-
301- /// Convenience wrapper around [`x86_interrupt_first_arg_is_invalid`] for callers that only
302- /// hold the `FnAbi` and must lower it themselves. Short-circuits before lowering for the
303- /// common non-`x86-interrupt` case.
304- #[ cfg( feature = "master" ) ]
305- pub fn x86_interrupt_has_invalid_first_arg < ' gcc , ' tcx > (
306- cx : & CodegenCx < ' gcc , ' tcx > ,
307- fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
308- ) -> bool {
309- matches ! ( fn_abi. conv, CanonAbi :: Interrupt ( InterruptKind :: X86 ) )
310- && x86_interrupt_first_arg_is_invalid ( fn_abi. conv , & fn_abi. gcc_type ( cx) . arguments_type )
311- }
0 commit comments