@@ -8,7 +8,12 @@ pub(crate) enum Flavor {
88 FastcallOrVectorcall ,
99}
1010
11- pub ( crate ) fn compute_abi_info < ' a , Ty , C > ( cx : & C , fn_abi : & mut FnAbi < ' a , Ty > , flavor : Flavor )
11+ pub ( crate ) struct X86Options {
12+ pub flavor : Flavor ,
13+ pub regparm : Option < u32 > ,
14+ }
15+
16+ pub ( crate ) fn compute_abi_info < ' a , Ty , C > ( cx : & C , fn_abi : & mut FnAbi < ' a , Ty > , opts : X86Options )
1217where
1318 Ty : TyAbiInterface < ' a , C > + Copy ,
1419 C : HasDataLayout + HasTargetSpec ,
@@ -128,58 +133,77 @@ where
128133 }
129134 }
130135
131- if flavor == Flavor :: FastcallOrVectorcall {
132- // Mark arguments as InReg like clang does it,
133- // so our fastcall/vectorcall is compatible with C/C++ fastcall/vectorcall.
136+ fill_inregs ( cx, fn_abi, opts, false ) ;
137+ }
134138
135- // Clang reference: lib/CodeGen/TargetInfo.cpp
136- // See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs()
139+ pub ( crate ) fn fill_inregs < ' a , Ty , C > (
140+ cx : & C ,
141+ fn_abi : & mut FnAbi < ' a , Ty > ,
142+ opts : X86Options ,
143+ rust_abi : bool ,
144+ ) where
145+ Ty : TyAbiInterface < ' a , C > + Copy ,
146+ {
147+ if opts. flavor != Flavor :: FastcallOrVectorcall && opts. regparm . is_none_or ( |x| x == 0 ) {
148+ return ;
149+ }
150+ // Mark arguments as InReg like clang does it,
151+ // so our fastcall/vectorcall is compatible with C/C++ fastcall/vectorcall.
137152
138- // IsSoftFloatABI is only set to true on ARM platforms,
139- // which in turn can't be x86?
153+ // Clang reference: lib/CodeGen/TargetInfo.cpp
154+ // See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs()
140155
141- let mut free_regs = 2 ;
156+ // IsSoftFloatABI is only set to true on ARM platforms,
157+ // which in turn can't be x86?
142158
143- for arg in fn_abi. args . iter_mut ( ) {
144- let attrs = match arg. mode {
145- PassMode :: Ignore
146- | PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack : _ } => {
147- continue ;
148- }
149- PassMode :: Direct ( ref mut attrs) => attrs,
150- PassMode :: Pair ( ..)
151- | PassMode :: Indirect { attrs : _, meta_attrs : Some ( _) , on_stack : _ }
152- | PassMode :: Cast { .. } => {
153- unreachable ! ( "x86 shouldn't be passing arguments by {:?}" , arg. mode)
154- }
155- } ;
159+ // 2 for fastcall/vectorcall, regparm limited by 3 otherwise
160+ let mut free_regs = opts. regparm . unwrap_or ( 2 ) . into ( ) ;
161+
162+ // For types generating PassMode::Cast, InRegs will not be set.
163+ // Maybe, this is a FIXME
164+ let has_casts = fn_abi. args . iter ( ) . any ( |arg| matches ! ( arg. mode, PassMode :: Cast { .. } ) ) ;
165+ if has_casts && rust_abi {
166+ return ;
167+ }
156168
157- // At this point we know this must be a primitive of sorts.
158- let unit = arg. layout . homogeneous_aggregate ( cx) . unwrap ( ) . unit ( ) . unwrap ( ) ;
159- assert_eq ! ( unit. size, arg. layout. size) ;
160- if unit. kind == RegKind :: Float {
169+ for arg in fn_abi. args . iter_mut ( ) {
170+ let attrs = match arg. mode {
171+ PassMode :: Ignore | PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack : _ } => {
161172 continue ;
162173 }
174+ PassMode :: Direct ( ref mut attrs) => attrs,
175+ PassMode :: Pair ( ..)
176+ | PassMode :: Indirect { attrs : _, meta_attrs : Some ( _) , on_stack : _ }
177+ | PassMode :: Cast { .. } => {
178+ unreachable ! ( "x86 shouldn't be passing arguments by {:?}" , arg. mode)
179+ }
180+ } ;
163181
164- let size_in_regs = ( arg. layout . size . bits ( ) + 31 ) / 32 ;
182+ // At this point we know this must be a primitive of sorts.
183+ let unit = arg. layout . homogeneous_aggregate ( cx) . unwrap ( ) . unit ( ) . unwrap ( ) ;
184+ assert_eq ! ( unit. size, arg. layout. size) ;
185+ if matches ! ( unit. kind, RegKind :: Float | RegKind :: Vector ) {
186+ continue ;
187+ }
165188
166- if size_in_regs == 0 {
167- continue ;
168- }
189+ let size_in_regs = ( arg. layout . size . bits ( ) + 31 ) / 32 ;
169190
170- if size_in_regs > free_regs {
171- break ;
172- }
191+ if size_in_regs == 0 {
192+ continue ;
193+ }
173194
174- free_regs -= size_in_regs;
195+ if size_in_regs > free_regs {
196+ break ;
197+ }
175198
176- if arg. layout . size . bits ( ) <= 32 && unit. kind == RegKind :: Integer {
177- attrs. set ( ArgAttribute :: InReg ) ;
178- }
199+ free_regs -= size_in_regs;
179200
180- if free_regs == 0 {
181- break ;
182- }
201+ if arg. layout . size . bits ( ) <= 32 && unit. kind == RegKind :: Integer {
202+ attrs. set ( ArgAttribute :: InReg ) ;
203+ }
204+
205+ if free_regs == 0 {
206+ break ;
183207 }
184208 }
185209}
0 commit comments