@@ -4,7 +4,7 @@ use rustc_middle::ty::{
4
4
} ;
5
5
use rustc_target:: abi:: * ;
6
6
7
- use std:: cmp ;
7
+ use std:: assert_matches :: assert_matches ;
8
8
9
9
/// Enforce some basic invariants on layouts.
10
10
pub ( super ) fn sanity_check_layout < ' tcx > (
@@ -68,21 +68,31 @@ pub(super) fn sanity_check_layout<'tcx>(
68
68
}
69
69
70
70
fn check_layout_abi < ' tcx > ( cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > , layout : & TyAndLayout < ' tcx > ) {
71
+ // Verify the ABI mandated alignment and size.
72
+ let align = layout. abi . inherent_align ( cx) . map ( |align| align. abi ) ;
73
+ let size = layout. abi . inherent_size ( cx) ;
74
+ let Some ( ( align, size) ) = align. zip ( size) else {
75
+ assert_matches ! (
76
+ layout. layout. abi( ) ,
77
+ Abi :: Uninhabited | Abi :: Aggregate { .. } ,
78
+ "ABI unexpectedly missing alignment and/or size in {layout:#?}"
79
+ ) ;
80
+ return
81
+ } ;
82
+ assert_eq ! (
83
+ layout. layout. align( ) . abi,
84
+ align,
85
+ "alignment mismatch between ABI and layout in {layout:#?}"
86
+ ) ;
87
+ assert_eq ! (
88
+ layout. layout. size( ) ,
89
+ size,
90
+ "size mismatch between ABI and layout in {layout:#?}"
91
+ ) ;
92
+
93
+ // Verify per-ABI invariants
71
94
match layout. layout . abi ( ) {
72
- Abi :: Scalar ( scalar) => {
73
- // No padding in scalars.
74
- let size = scalar. size ( cx) ;
75
- let align = scalar. align ( cx) . abi ;
76
- assert_eq ! (
77
- layout. layout. size( ) ,
78
- size,
79
- "size mismatch between ABI and layout in {layout:#?}"
80
- ) ;
81
- assert_eq ! (
82
- layout. layout. align( ) . abi,
83
- align,
84
- "alignment mismatch between ABI and layout in {layout:#?}"
85
- ) ;
95
+ Abi :: Scalar ( _) => {
86
96
// Check that this matches the underlying field.
87
97
let inner = skip_newtypes ( cx, layout) ;
88
98
assert ! (
@@ -135,24 +145,6 @@ pub(super) fn sanity_check_layout<'tcx>(
135
145
}
136
146
}
137
147
Abi :: ScalarPair ( scalar1, scalar2) => {
138
- // Sanity-check scalar pairs. Computing the expected size and alignment is a bit of work.
139
- let size1 = scalar1. size ( cx) ;
140
- let align1 = scalar1. align ( cx) . abi ;
141
- let size2 = scalar2. size ( cx) ;
142
- let align2 = scalar2. align ( cx) . abi ;
143
- let align = cmp:: max ( align1, align2) ;
144
- let field2_offset = size1. align_to ( align2) ;
145
- let size = ( field2_offset + size2) . align_to ( align) ;
146
- assert_eq ! (
147
- layout. layout. size( ) ,
148
- size,
149
- "size mismatch between ABI and layout in {layout:#?}"
150
- ) ;
151
- assert_eq ! (
152
- layout. layout. align( ) . abi,
153
- align,
154
- "alignment mismatch between ABI and layout in {layout:#?}" ,
155
- ) ;
156
148
// Check that the underlying pair of fields matches.
157
149
let inner = skip_newtypes ( cx, layout) ;
158
150
assert ! (
@@ -189,8 +181,9 @@ pub(super) fn sanity_check_layout<'tcx>(
189
181
"`ScalarPair` layout for type with less than two non-ZST fields: {inner:#?}"
190
182
)
191
183
} ) ;
192
- assert ! (
193
- fields. next( ) . is_none( ) ,
184
+ assert_matches ! (
185
+ fields. next( ) ,
186
+ None ,
194
187
"`ScalarPair` layout for type with at least three non-ZST fields: {inner:#?}"
195
188
) ;
196
189
// The fields might be in opposite order.
@@ -200,6 +193,10 @@ pub(super) fn sanity_check_layout<'tcx>(
200
193
( offset2, field2, offset1, field1)
201
194
} ;
202
195
// The fields should be at the right offset, and match the `scalar` layout.
196
+ let size1 = scalar1. size ( cx) ;
197
+ let align1 = scalar1. align ( cx) . abi ;
198
+ let size2 = scalar2. size ( cx) ;
199
+ let align2 = scalar2. align ( cx) . abi ;
203
200
assert_eq ! (
204
201
offset1,
205
202
Size :: ZERO ,
@@ -213,10 +210,12 @@ pub(super) fn sanity_check_layout<'tcx>(
213
210
field1. align. abi, align1,
214
211
"`ScalarPair` first field with bad align in {inner:#?}" ,
215
212
) ;
216
- assert ! (
217
- matches!( field1. abi, Abi :: Scalar ( _) ) ,
213
+ assert_matches ! (
214
+ field1. abi,
215
+ Abi :: Scalar ( _) ,
218
216
"`ScalarPair` first field with bad ABI in {inner:#?}" ,
219
217
) ;
218
+ let field2_offset = size1. align_to ( align2) ;
220
219
assert_eq ! (
221
220
offset2, field2_offset,
222
221
"`ScalarPair` second field at bad offset in {inner:#?}" ,
@@ -229,27 +228,14 @@ pub(super) fn sanity_check_layout<'tcx>(
229
228
field2. align. abi, align2,
230
229
"`ScalarPair` second field with bad align in {inner:#?}" ,
231
230
) ;
232
- assert ! (
233
- matches!( field2. abi, Abi :: Scalar ( _) ) ,
231
+ assert_matches ! (
232
+ field2. abi,
233
+ Abi :: Scalar ( _) ,
234
234
"`ScalarPair` second field with bad ABI in {inner:#?}" ,
235
235
) ;
236
236
}
237
- Abi :: Vector { count, element } => {
238
- // No padding in vectors, except possibly for trailing padding to make the size a multiple of align.
239
- let size = element. size ( cx) * count;
240
- let align = cx. data_layout ( ) . vector_align ( size) . abi ;
241
- let size = size. align_to ( align) ; // needed e.g. for vectors of size 3
237
+ Abi :: Vector { element, .. } => {
242
238
assert ! ( align >= element. align( cx) . abi) ; // just sanity-checking `vector_align`.
243
- assert_eq ! (
244
- layout. layout. size( ) ,
245
- size,
246
- "size mismatch between ABI and layout in {layout:#?}"
247
- ) ;
248
- assert_eq ! (
249
- layout. layout. align( ) . abi,
250
- align,
251
- "alignment mismatch between ABI and layout in {layout:#?}"
252
- ) ;
253
239
// FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
254
240
}
255
241
Abi :: Uninhabited | Abi :: Aggregate { .. } => { } // Nothing to check.
0 commit comments