@@ -16,13 +16,15 @@ pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
16
16
use rustc_middle:: ty:: Ty ;
17
17
use rustc_session:: config;
18
18
pub use rustc_target:: abi:: call:: * ;
19
- use rustc_target:: abi:: { self , HasDataLayout , Int } ;
19
+ use rustc_target:: abi:: { self , HasDataLayout , Int , Size } ;
20
20
pub use rustc_target:: spec:: abi:: Abi ;
21
21
use rustc_target:: spec:: SanitizerSet ;
22
22
23
23
use libc:: c_uint;
24
24
use smallvec:: SmallVec ;
25
25
26
+ use std:: cmp;
27
+
26
28
pub trait ArgAttributesExt {
27
29
fn apply_attrs_to_llfn ( & self , idx : AttributePlace , cx : & CodegenCx < ' _ , ' _ > , llfn : & Value ) ;
28
30
fn apply_attrs_to_callsite (
@@ -130,42 +132,36 @@ impl LlvmType for Reg {
130
132
impl LlvmType for CastTarget {
131
133
fn llvm_type < ' ll > ( & self , cx : & CodegenCx < ' ll , ' _ > ) -> & ' ll Type {
132
134
let rest_ll_unit = self . rest . unit . llvm_type ( cx) ;
133
- let ( rest_count, rem_bytes ) = if self . rest . unit . size . bytes ( ) == 0 {
134
- ( 0 , 0 )
135
+ let rest_count = if self . rest . total == Size :: ZERO {
136
+ 0
135
137
} else {
136
- (
137
- self . rest . total . bytes ( ) / self . rest . unit . size . bytes ( ) ,
138
- self . rest . total . bytes ( ) % self . rest . unit . size . bytes ( ) ,
139
- )
138
+ assert_ne ! (
139
+ self . rest. unit. size,
140
+ Size :: ZERO ,
141
+ "total size {:?} cannot be divided into units of zero size" ,
142
+ self . rest. total
143
+ ) ;
144
+ if self . rest . total . bytes ( ) % self . rest . unit . size . bytes ( ) != 0 {
145
+ assert_eq ! ( self . rest. unit. kind, RegKind :: Integer , "only int regs can be split" ) ;
146
+ }
147
+ self . rest . total . bytes ( ) . div_ceil ( self . rest . unit . size . bytes ( ) )
140
148
} ;
141
149
150
+ // Simplify to a single unit or an array if there's no prefix.
151
+ // This produces the same layout, but using a simpler type.
142
152
if self . prefix . iter ( ) . all ( |x| x. is_none ( ) ) {
143
- // Simplify to a single unit when there is no prefix and size <= unit size
144
- if self . rest . total <= self . rest . unit . size {
153
+ if rest_count == 1 {
145
154
return rest_ll_unit;
146
155
}
147
156
148
- // Simplify to array when all chunks are the same size and type
149
- if rem_bytes == 0 {
150
- return cx. type_array ( rest_ll_unit, rest_count) ;
151
- }
152
- }
153
-
154
- // Create list of fields in the main structure
155
- let mut args: Vec < _ > = self
156
- . prefix
157
- . iter ( )
158
- . flat_map ( |option_reg| option_reg. map ( |reg| reg. llvm_type ( cx) ) )
159
- . chain ( ( 0 ..rest_count) . map ( |_| rest_ll_unit) )
160
- . collect ( ) ;
161
-
162
- // Append final integer
163
- if rem_bytes != 0 {
164
- // Only integers can be really split further.
165
- assert_eq ! ( self . rest. unit. kind, RegKind :: Integer ) ;
166
- args. push ( cx. type_ix ( rem_bytes * 8 ) ) ;
157
+ return cx. type_array ( rest_ll_unit, rest_count) ;
167
158
}
168
159
160
+ // Generate a struct type with the prefix and the "rest" arguments.
161
+ let prefix_args =
162
+ self . prefix . iter ( ) . flat_map ( |option_reg| option_reg. map ( |reg| reg. llvm_type ( cx) ) ) ;
163
+ let rest_args = ( 0 ..rest_count) . map ( |_| rest_ll_unit) ;
164
+ let args: Vec < _ > = prefix_args. chain ( rest_args) . collect ( ) ;
169
165
cx. type_struct ( & args, false )
170
166
}
171
167
}
0 commit comments