@@ -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,66 @@ 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) ;
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 > ( cx : & C , fn_abi : & mut FnAbi < ' a , Ty > , opts : X86Options )
140+ where
141+ Ty : TyAbiInterface < ' a , C > + Copy ,
142+ {
143+ if opts. flavor != Flavor :: FastcallOrVectorcall && !opts. regparm . is_some_and ( |x| x > 0 ) {
144+ return ;
145+ }
146+ // Mark arguments as InReg like clang does it,
147+ // so our fastcall/vectorcall is compatible with C/C++ fastcall/vectorcall.
137148
138- // IsSoftFloatABI is only set to true on ARM platforms,
139- // which in turn can't be x86?
149+ // Clang reference: lib/CodeGen/TargetInfo.cpp
150+ // See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs()
140151
141- let mut free_regs = 2 ;
152+ // IsSoftFloatABI is only set to true on ARM platforms,
153+ // which in turn can't be x86?
142154
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- } ;
155+ // 2 for fastcall/vectorcall, regparm limited by 3 otherwise
156+ let mut free_regs = opts. regparm . unwrap_or ( 2 ) . into ( ) ;
156157
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 {
158+ for arg in fn_abi. args . iter_mut ( ) {
159+ let attrs = match arg. mode {
160+ PassMode :: Ignore | PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack : _ } => {
161161 continue ;
162162 }
163+ PassMode :: Direct ( ref mut attrs) => attrs,
164+ PassMode :: Pair ( ..)
165+ | PassMode :: Indirect { attrs : _, meta_attrs : Some ( _) , on_stack : _ }
166+ | PassMode :: Cast { .. } => {
167+ unreachable ! ( "x86 shouldn't be passing arguments by {:?}" , arg. mode)
168+ }
169+ } ;
163170
164- let size_in_regs = ( arg. layout . size . bits ( ) + 31 ) / 32 ;
171+ // At this point we know this must be a primitive of sorts.
172+ let unit = arg. layout . homogeneous_aggregate ( cx) . unwrap ( ) . unit ( ) . unwrap ( ) ;
173+ assert_eq ! ( unit. size, arg. layout. size) ;
174+ if unit. kind == RegKind :: Float {
175+ continue ;
176+ }
165177
166- if size_in_regs == 0 {
167- continue ;
168- }
178+ let size_in_regs = ( arg. layout . size . bits ( ) + 31 ) / 32 ;
169179
170- if size_in_regs > free_regs {
171- break ;
172- }
180+ if size_in_regs == 0 {
181+ continue ;
182+ }
173183
174- free_regs -= size_in_regs;
184+ if size_in_regs > free_regs {
185+ break ;
186+ }
175187
176- if arg. layout . size . bits ( ) <= 32 && unit. kind == RegKind :: Integer {
177- attrs. set ( ArgAttribute :: InReg ) ;
178- }
188+ free_regs -= size_in_regs;
179189
180- if free_regs == 0 {
181- break ;
182- }
190+ if arg. layout . size . bits ( ) <= 32 && unit. kind == RegKind :: Integer {
191+ attrs. set ( ArgAttribute :: InReg ) ;
192+ }
193+
194+ if free_regs == 0 {
195+ break ;
183196 }
184197 }
185198}
0 commit comments