1
- use std:: ops:: ControlFlow ;
1
+ use std:: ops:: { ControlFlow , RangeInclusive } ;
2
2
3
3
use super :: { Byte , Def , Ref } ;
4
4
32
32
Byte ( Byte ) ,
33
33
}
34
34
35
+ #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
36
+ pub ( crate ) enum Endian {
37
+ Little ,
38
+ Big ,
39
+ }
40
+
41
+ #[ cfg( feature = "rustc" ) ]
42
+ impl From < rustc_abi:: Endian > for Endian {
43
+ fn from ( order : rustc_abi:: Endian ) -> Endian {
44
+ match order {
45
+ rustc_abi:: Endian :: Little => Endian :: Little ,
46
+ rustc_abi:: Endian :: Big => Endian :: Big ,
47
+ }
48
+ }
49
+ }
50
+
35
51
impl < D , R > Tree < D , R >
36
52
where
37
53
D : Def ,
@@ -59,22 +75,62 @@ where
59
75
60
76
/// A `Tree` representing the layout of `bool`.
61
77
pub ( crate ) fn bool ( ) -> Self {
62
- Self :: Byte ( Byte :: new ( 0x00 ..=0x01 ) )
78
+ Self :: byte ( 0x00 ..=0x01 )
63
79
}
64
80
65
81
/// A `Tree` whose layout matches that of a `u8`.
66
82
pub ( crate ) fn u8 ( ) -> Self {
67
- Self :: Byte ( Byte :: new ( 0x00 ..=0xFF ) )
83
+ Self :: byte ( 0x00 ..=0xFF )
68
84
}
69
85
70
- /// A `Tree` whose layout accepts exactly the given bit pattern.
71
- pub ( crate ) fn from_bits ( bits : u8 ) -> Self {
72
- Self :: Byte ( Byte :: from_val ( bits) )
86
+ /// A `Tree` whose layout matches that of a `char`.
87
+ pub ( crate ) fn char ( order : Endian ) -> Self {
88
+ // `char`s can be in the following ranges:
89
+ // - [0, 0xD7FF]
90
+ // - [0xE000, 10FFFF]
91
+ //
92
+ // All other `char` values are illegal. We can thus represent a `char`
93
+ // as a union of three possible layouts:
94
+ // - 00 00 [00, D7] XX
95
+ // - 00 00 [E0, FF] XX
96
+ // - 00 [01, 10] XX XX
97
+
98
+ const _0: RangeInclusive < u8 > = 0 ..=0 ;
99
+ const BYTE : RangeInclusive < u8 > = 0x00 ..=0xFF ;
100
+ // OverB(B) = 0xD800,
101
+ // UnderC(C) = 0xDFFF,
102
+ let x = Self :: from_big_endian ( order, [ _0, _0, 0x00 ..=0xD7 , BYTE ] ) ;
103
+ let y = Self :: from_big_endian ( order, [ _0, _0, 0xE0 ..=0xFF , BYTE ] ) ;
104
+ let z = Self :: from_big_endian ( order, [ _0, 0x01 ..=0x10 , BYTE , BYTE ] ) ;
105
+ Self :: alt ( [ x, y, z] )
106
+ }
107
+
108
+ /// A `Tree` whose layout matches `std::num::NonZeroXxx`.
109
+ #[ allow( dead_code) ]
110
+ pub ( crate ) fn nonzero ( width_in_bytes : u64 ) -> Self {
111
+ const BYTE : RangeInclusive < u8 > = 0x00 ..=0xFF ;
112
+ const NONZERO : RangeInclusive < u8 > = 0x01 ..=0xFF ;
113
+
114
+ ( 0 ..width_in_bytes)
115
+ . map ( |nz_idx| {
116
+ ( 0 ..width_in_bytes)
117
+ . map ( |pos| Self :: byte ( if pos == nz_idx { NONZERO } else { BYTE } ) )
118
+ . fold ( Self :: unit ( ) , Self :: then)
119
+ } )
120
+ . fold ( Self :: uninhabited ( ) , Self :: or)
121
+ }
122
+
123
+ pub ( crate ) fn bytes < const N : usize , B : Into < Byte > > ( bytes : [ B ; N ] ) -> Self {
124
+ Self :: seq ( bytes. map ( B :: into) . map ( Self :: Byte ) )
125
+ }
126
+
127
+ pub ( crate ) fn byte ( byte : impl Into < Byte > ) -> Self {
128
+ Self :: Byte ( byte. into ( ) )
73
129
}
74
130
75
131
/// A `Tree` whose layout is a number of the given width.
76
- pub ( crate ) fn number ( width_in_bytes : usize ) -> Self {
77
- Self :: Seq ( vec ! [ Self :: u8 ( ) ; width_in_bytes] )
132
+ pub ( crate ) fn number ( width_in_bytes : u64 ) -> Self {
133
+ Self :: Seq ( vec ! [ Self :: u8 ( ) ; width_in_bytes. try_into ( ) . unwrap ( ) ] )
78
134
}
79
135
80
136
/// A `Tree` whose layout is entirely padding of the given width.
@@ -125,13 +181,35 @@ where
125
181
Self :: Byte ( ..) | Self :: Ref ( ..) | Self :: Def ( ..) => true ,
126
182
}
127
183
}
128
- }
129
184
130
- impl < D , R > Tree < D , R >
131
- where
132
- D : Def ,
133
- R : Ref ,
134
- {
185
+ /// Produces a `Tree` which represents a sequence of bytes stored in
186
+ /// `order`.
187
+ ///
188
+ /// `bytes` is taken to be in big-endian byte order, and its order will be
189
+ /// swapped if `order == Endian::Little`.
190
+ pub ( crate ) fn from_big_endian < const N : usize , B : Into < Byte > > (
191
+ order : Endian ,
192
+ mut bytes : [ B ; N ] ,
193
+ ) -> Self {
194
+ if order == Endian :: Little {
195
+ ( & mut bytes[ ..] ) . reverse ( ) ;
196
+ }
197
+
198
+ Self :: bytes ( bytes)
199
+ }
200
+
201
+ /// Produces a `Tree` where each of the trees in `trees` are sequenced one
202
+ /// after another.
203
+ pub ( crate ) fn seq < const N : usize > ( trees : [ Tree < D , R > ; N ] ) -> Self {
204
+ trees. into_iter ( ) . fold ( Tree :: unit ( ) , Self :: then)
205
+ }
206
+
207
+ /// Produces a `Tree` where each of the trees in `trees` are accepted as
208
+ /// alternative layouts.
209
+ pub ( crate ) fn alt < const N : usize > ( trees : [ Tree < D , R > ; N ] ) -> Self {
210
+ trees. into_iter ( ) . fold ( Tree :: uninhabited ( ) , Self :: or)
211
+ }
212
+
135
213
/// Produces a new `Tree` where `other` is sequenced after `self`.
136
214
pub ( crate ) fn then ( self , other : Self ) -> Self {
137
215
match ( self , other) {
@@ -222,17 +300,17 @@ pub(crate) mod rustc {
222
300
223
301
ty:: Float ( nty) => {
224
302
let width = nty. bit_width ( ) / 8 ;
225
- Ok ( Self :: number ( width as _ ) )
303
+ Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) )
226
304
}
227
305
228
306
ty:: Int ( nty) => {
229
307
let width = nty. normalize ( pointer_size. bits ( ) as _ ) . bit_width ( ) . unwrap ( ) / 8 ;
230
- Ok ( Self :: number ( width as _ ) )
308
+ Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) )
231
309
}
232
310
233
311
ty:: Uint ( nty) => {
234
312
let width = nty. normalize ( pointer_size. bits ( ) as _ ) . bit_width ( ) . unwrap ( ) / 8 ;
235
- Ok ( Self :: number ( width as _ ) )
313
+ Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) )
236
314
}
237
315
238
316
ty:: Tuple ( members) => Self :: from_tuple ( ( ty, layout) , members, cx) ,
@@ -249,11 +327,41 @@ pub(crate) mod rustc {
249
327
. fold ( Tree :: unit ( ) , |tree, elt| tree. then ( elt) ) )
250
328
}
251
329
252
- ty:: Adt ( adt_def, _args_ref) if !ty. is_box ( ) => match adt_def. adt_kind ( ) {
253
- AdtKind :: Struct => Self :: from_struct ( ( ty, layout) , * adt_def, cx) ,
254
- AdtKind :: Enum => Self :: from_enum ( ( ty, layout) , * adt_def, cx) ,
255
- AdtKind :: Union => Self :: from_union ( ( ty, layout) , * adt_def, cx) ,
256
- } ,
330
+ ty:: Adt ( adt_def, _args_ref) if !ty. is_box ( ) => {
331
+ let ( lo, hi) = cx. tcx ( ) . layout_scalar_valid_range ( adt_def. did ( ) ) ;
332
+
333
+ use core:: ops:: Bound :: * ;
334
+ let is_transparent = adt_def. repr ( ) . transparent ( ) ;
335
+ match ( adt_def. adt_kind ( ) , lo, hi) {
336
+ ( AdtKind :: Struct , Unbounded , Unbounded ) => {
337
+ Self :: from_struct ( ( ty, layout) , * adt_def, cx)
338
+ }
339
+ ( AdtKind :: Struct , Included ( 1 ) , Included ( hi) ) if is_transparent => {
340
+ let field_ty = ty_field ( cx, ( ty, layout) , FieldIdx :: from_usize ( 0 ) ) ;
341
+ let width_bits = match field_ty. kind ( ) {
342
+ ty:: Float ( nty) => nty. bit_width ( ) ,
343
+ ty:: Int ( nty) => {
344
+ nty. normalize ( pointer_size. bits ( ) as _ ) . bit_width ( ) . unwrap ( )
345
+ }
346
+ ty:: Uint ( nty) => {
347
+ nty. normalize ( pointer_size. bits ( ) as _ ) . bit_width ( ) . unwrap ( )
348
+ }
349
+ _ => return Err ( Err :: NotYetSupported ) ,
350
+ } ;
351
+ if hi != ( 1u128 << ( width_bits) ) - 1 {
352
+ return Err ( Err :: NotYetSupported ) ;
353
+ }
354
+ Ok ( Self :: nonzero ( width_bits / 8 ) )
355
+ }
356
+ ( AdtKind :: Enum , Unbounded , Unbounded ) => {
357
+ Self :: from_enum ( ( ty, layout) , * adt_def, cx)
358
+ }
359
+ ( AdtKind :: Union , Unbounded , Unbounded ) => {
360
+ Self :: from_union ( ( ty, layout) , * adt_def, cx)
361
+ }
362
+ _ => Err ( Err :: NotYetSupported ) ,
363
+ }
364
+ }
257
365
258
366
ty:: Ref ( lifetime, ty, mutability) => {
259
367
let layout = layout_of ( cx, * ty) ?;
@@ -268,6 +376,10 @@ pub(crate) mod rustc {
268
376
} ) )
269
377
}
270
378
379
+ ty:: Char => Ok ( Self :: char ( cx. tcx ( ) . data_layout . endian . into ( ) ) ) ,
380
+
381
+ ty:: Alias ( _kind, ty) => Self :: from_ty ( ty. to_ty ( cx. tcx ( ) ) , cx) ,
382
+
271
383
_ => Err ( Err :: NotYetSupported ) ,
272
384
}
273
385
}
@@ -450,7 +562,7 @@ pub(crate) mod rustc {
450
562
& bytes[ bytes. len ( ) - size. bytes_usize ( ) ..]
451
563
}
452
564
} ;
453
- Self :: Seq ( bytes. iter ( ) . map ( |& b| Self :: from_bits ( b) ) . collect ( ) )
565
+ Self :: Seq ( bytes. iter ( ) . map ( |& b| Self :: byte ( b) ) . collect ( ) )
454
566
}
455
567
456
568
/// Constructs a `Tree` from a union.
0 commit comments