1
1
//! Defines hir-level representation of structs, enums and unions
2
2
3
- use std:: { num :: NonZeroU32 , sync:: Arc } ;
3
+ use std:: sync:: Arc ;
4
4
5
5
use base_db:: CrateId ;
6
6
use either:: Either ;
@@ -9,6 +9,7 @@ use hir_expand::{
9
9
HirFileId , InFile ,
10
10
} ;
11
11
use la_arena:: { Arena , ArenaMap } ;
12
+ use rustc_abi:: { Integer , IntegerType } ;
12
13
use syntax:: ast:: { self , HasName , HasVisibility } ;
13
14
use tt:: { Delimiter , DelimiterKind , Leaf , Subtree , TokenTree } ;
14
15
@@ -18,6 +19,7 @@ use crate::{
18
19
db:: DefDatabase ,
19
20
intern:: Interned ,
20
21
item_tree:: { AttrOwner , Field , FieldAstId , Fields , ItemTree , ModItem , RawVisibilityId } ,
22
+ layout:: { Align , ReprFlags , ReprOptions } ,
21
23
nameres:: diagnostics:: DefDiagnostic ,
22
24
src:: HasChildSource ,
23
25
src:: HasSource ,
@@ -34,7 +36,7 @@ use cfg::CfgOptions;
34
36
pub struct StructData {
35
37
pub name : Name ,
36
38
pub variant_data : Arc < VariantData > ,
37
- pub repr : Option < ReprData > ,
39
+ pub repr : Option < ReprOptions > ,
38
40
pub visibility : RawVisibility ,
39
41
pub rustc_has_incoherent_inherent_impls : bool ,
40
42
}
@@ -43,7 +45,7 @@ pub struct StructData {
43
45
pub struct EnumData {
44
46
pub name : Name ,
45
47
pub variants : Arena < EnumVariantData > ,
46
- pub repr : Option < ReprData > ,
48
+ pub repr : Option < ReprOptions > ,
47
49
pub visibility : RawVisibility ,
48
50
pub rustc_has_incoherent_inherent_impls : bool ,
49
51
}
@@ -69,80 +71,91 @@ pub struct FieldData {
69
71
pub visibility : RawVisibility ,
70
72
}
71
73
72
- #[ derive( Copy , Debug , Clone , PartialEq , Eq ) ]
73
- pub enum ReprKind {
74
- C ,
75
- BuiltinInt { builtin : Either < BuiltinInt , BuiltinUint > , is_c : bool } ,
76
- Transparent ,
77
- Default ,
78
- }
79
-
80
- #[ derive( Copy , Debug , Clone , PartialEq , Eq ) ]
81
- pub struct ReprData {
82
- pub kind : ReprKind ,
83
- pub packed : bool ,
84
- pub align : Option < NonZeroU32 > ,
85
- }
86
-
87
74
fn repr_from_value (
88
75
db : & dyn DefDatabase ,
89
76
krate : CrateId ,
90
77
item_tree : & ItemTree ,
91
78
of : AttrOwner ,
92
- ) -> Option < ReprData > {
79
+ ) -> Option < ReprOptions > {
93
80
item_tree. attrs ( db, krate, of) . by_key ( "repr" ) . tt_values ( ) . find_map ( parse_repr_tt)
94
81
}
95
82
96
- fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprData > {
83
+ fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprOptions > {
97
84
match tt. delimiter {
98
85
Some ( Delimiter { kind : DelimiterKind :: Parenthesis , .. } ) => { }
99
86
_ => return None ,
100
87
}
101
88
102
- let mut data = ReprData { kind : ReprKind :: Default , packed : false , align : None } ;
89
+ let mut flags = ReprFlags :: empty ( ) ;
90
+ let mut int = None ;
91
+ let mut max_align: Option < Align > = None ;
92
+ let mut min_pack: Option < Align > = None ;
103
93
104
94
let mut tts = tt. token_trees . iter ( ) . peekable ( ) ;
105
95
while let Some ( tt) = tts. next ( ) {
106
96
if let TokenTree :: Leaf ( Leaf :: Ident ( ident) ) = tt {
107
- match & * ident. text {
97
+ flags . insert ( match & * ident. text {
108
98
"packed" => {
109
- data. packed = true ;
110
- if let Some ( TokenTree :: Subtree ( _) ) = tts. peek ( ) {
99
+ let pack = if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
111
100
tts. next ( ) ;
112
- }
101
+ if let Some ( TokenTree :: Leaf ( Leaf :: Literal ( lit) ) ) = tt. token_trees . first ( ) {
102
+ lit. text . parse ( ) . unwrap_or_default ( )
103
+ } else {
104
+ 0
105
+ }
106
+ } else {
107
+ 0
108
+ } ;
109
+ let pack = Align :: from_bytes ( pack) . unwrap ( ) ;
110
+ min_pack =
111
+ Some ( if let Some ( min_pack) = min_pack { min_pack. min ( pack) } else { pack } ) ;
112
+ ReprFlags :: empty ( )
113
113
}
114
114
"align" => {
115
115
if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
116
116
tts. next ( ) ;
117
117
if let Some ( TokenTree :: Leaf ( Leaf :: Literal ( lit) ) ) = tt. token_trees . first ( ) {
118
118
if let Ok ( align) = lit. text . parse ( ) {
119
- data. align = Some ( align) ;
119
+ let align = Align :: from_bytes ( align) . ok ( ) ;
120
+ max_align = max_align. max ( align) ;
120
121
}
121
122
}
122
123
}
124
+ ReprFlags :: empty ( )
123
125
}
124
- "C" => {
125
- if let ReprKind :: BuiltinInt { is_c, .. } = & mut data. kind {
126
- * is_c = true ;
127
- } else {
128
- data. kind = ReprKind :: C ;
129
- }
130
- }
131
- "transparent" => data. kind = ReprKind :: Transparent ,
126
+ "C" => ReprFlags :: IS_C ,
127
+ "transparent" => ReprFlags :: IS_TRANSPARENT ,
132
128
repr => {
133
- let is_c = matches ! ( data. kind, ReprKind :: C ) ;
134
129
if let Some ( builtin) = BuiltinInt :: from_suffix ( repr)
135
130
. map ( Either :: Left )
136
131
. or_else ( || BuiltinUint :: from_suffix ( repr) . map ( Either :: Right ) )
137
132
{
138
- data. kind = ReprKind :: BuiltinInt { builtin, is_c } ;
133
+ int = Some ( match builtin {
134
+ Either :: Left ( bi) => match bi {
135
+ BuiltinInt :: Isize => IntegerType :: Pointer ( true ) ,
136
+ BuiltinInt :: I8 => IntegerType :: Fixed ( Integer :: I8 , true ) ,
137
+ BuiltinInt :: I16 => IntegerType :: Fixed ( Integer :: I16 , true ) ,
138
+ BuiltinInt :: I32 => IntegerType :: Fixed ( Integer :: I32 , true ) ,
139
+ BuiltinInt :: I64 => IntegerType :: Fixed ( Integer :: I64 , true ) ,
140
+ BuiltinInt :: I128 => IntegerType :: Fixed ( Integer :: I128 , true ) ,
141
+ } ,
142
+ Either :: Right ( bu) => match bu {
143
+ BuiltinUint :: Usize => IntegerType :: Pointer ( false ) ,
144
+ BuiltinUint :: U8 => IntegerType :: Fixed ( Integer :: I8 , false ) ,
145
+ BuiltinUint :: U16 => IntegerType :: Fixed ( Integer :: I16 , false ) ,
146
+ BuiltinUint :: U32 => IntegerType :: Fixed ( Integer :: I32 , false ) ,
147
+ BuiltinUint :: U64 => IntegerType :: Fixed ( Integer :: I64 , false ) ,
148
+ BuiltinUint :: U128 => IntegerType :: Fixed ( Integer :: I128 , false ) ,
149
+ } ,
150
+ } ) ;
139
151
}
152
+ ReprFlags :: empty ( )
140
153
}
141
- }
154
+ } )
142
155
}
143
156
}
144
157
145
- Some ( data )
158
+ Some ( ReprOptions { int , align : max_align , pack : min_pack , flags , field_shuffle_seed : 0 } )
146
159
}
147
160
148
161
impl StructData {
@@ -299,10 +312,10 @@ impl EnumData {
299
312
Some ( id)
300
313
}
301
314
302
- pub fn variant_body_type ( & self ) -> Either < BuiltinInt , BuiltinUint > {
315
+ pub fn variant_body_type ( & self ) -> IntegerType {
303
316
match self . repr {
304
- Some ( ReprData { kind : ReprKind :: BuiltinInt { builtin, .. } , .. } ) => builtin,
305
- _ => Either :: Left ( BuiltinInt :: Isize ) ,
317
+ Some ( ReprOptions { int : Some ( builtin) , .. } ) => builtin,
318
+ _ => IntegerType :: Pointer ( true ) ,
306
319
}
307
320
}
308
321
}
0 commit comments