@@ -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,77 @@ 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, false ) ;
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 > (
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.
137
152
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()
140
155
141
- let mut free_regs = 2 ;
156
+ // IsSoftFloatABI is only set to true on ARM platforms,
157
+ // which in turn can't be x86?
142
158
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
+ }
156
168
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 : _ } => {
161
172
continue ;
162
173
}
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
+ } ;
163
181
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
+ }
165
188
166
- if size_in_regs == 0 {
167
- continue ;
168
- }
189
+ let size_in_regs = ( arg. layout . size . bits ( ) + 31 ) / 32 ;
169
190
170
- if size_in_regs > free_regs {
171
- break ;
172
- }
191
+ if size_in_regs == 0 {
192
+ continue ;
193
+ }
173
194
174
- free_regs -= size_in_regs;
195
+ if size_in_regs > free_regs {
196
+ break ;
197
+ }
175
198
176
- if arg. layout . size . bits ( ) <= 32 && unit. kind == RegKind :: Integer {
177
- attrs. set ( ArgAttribute :: InReg ) ;
178
- }
199
+ free_regs -= size_in_regs;
179
200
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 ;
183
207
}
184
208
}
185
209
}
0 commit comments