@@ -8,7 +8,12 @@ pub(crate) enum Flavor {
8
8
FastcallOrVectorcall ,
9
9
}
10
10
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 )
12
17
where
13
18
Ty : TyAbiInterface < ' a , C > + Copy ,
14
19
C : HasDataLayout + HasTargetSpec ,
@@ -128,58 +133,66 @@ where
128
133
}
129
134
}
130
135
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
+ }
134
138
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.
137
148
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()
140
151
141
- let mut free_regs = 2 ;
152
+ // IsSoftFloatABI is only set to true on ARM platforms,
153
+ // which in turn can't be x86?
142
154
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 ( ) ;
156
157
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 : _ } => {
161
161
continue ;
162
162
}
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
+ } ;
163
170
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
+ }
165
177
166
- if size_in_regs == 0 {
167
- continue ;
168
- }
178
+ let size_in_regs = ( arg. layout . size . bits ( ) + 31 ) / 32 ;
169
179
170
- if size_in_regs > free_regs {
171
- break ;
172
- }
180
+ if size_in_regs == 0 {
181
+ continue ;
182
+ }
173
183
174
- free_regs -= size_in_regs;
184
+ if size_in_regs > free_regs {
185
+ break ;
186
+ }
175
187
176
- if arg. layout . size . bits ( ) <= 32 && unit. kind == RegKind :: Integer {
177
- attrs. set ( ArgAttribute :: InReg ) ;
178
- }
188
+ free_regs -= size_in_regs;
179
189
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 ;
183
196
}
184
197
}
185
198
}
0 commit comments