11//! Defines hir-level representation of structs, enums and unions
22
3- use std:: { num :: NonZeroU32 , sync:: Arc } ;
3+ use std:: sync:: Arc ;
44
55use base_db:: CrateId ;
66use either:: Either ;
@@ -9,6 +9,7 @@ use hir_expand::{
99 HirFileId , InFile ,
1010} ;
1111use la_arena:: { Arena , ArenaMap } ;
12+ use rustc_abi:: { Integer , IntegerType } ;
1213use syntax:: ast:: { self , HasName , HasVisibility } ;
1314use tt:: { Delimiter , DelimiterKind , Leaf , Subtree , TokenTree } ;
1415
@@ -18,6 +19,7 @@ use crate::{
1819 db:: DefDatabase ,
1920 intern:: Interned ,
2021 item_tree:: { AttrOwner , Field , FieldAstId , Fields , ItemTree , ModItem , RawVisibilityId } ,
22+ layout:: { Align , ReprFlags , ReprOptions } ,
2123 nameres:: diagnostics:: DefDiagnostic ,
2224 src:: HasChildSource ,
2325 src:: HasSource ,
@@ -34,7 +36,7 @@ use cfg::CfgOptions;
3436pub struct StructData {
3537 pub name : Name ,
3638 pub variant_data : Arc < VariantData > ,
37- pub repr : Option < ReprData > ,
39+ pub repr : Option < ReprOptions > ,
3840 pub visibility : RawVisibility ,
3941 pub rustc_has_incoherent_inherent_impls : bool ,
4042}
@@ -43,7 +45,7 @@ pub struct StructData {
4345pub struct EnumData {
4446 pub name : Name ,
4547 pub variants : Arena < EnumVariantData > ,
46- pub repr : Option < ReprData > ,
48+ pub repr : Option < ReprOptions > ,
4749 pub visibility : RawVisibility ,
4850 pub rustc_has_incoherent_inherent_impls : bool ,
4951}
@@ -69,80 +71,91 @@ pub struct FieldData {
6971 pub visibility : RawVisibility ,
7072}
7173
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-
8774fn repr_from_value (
8875 db : & dyn DefDatabase ,
8976 krate : CrateId ,
9077 item_tree : & ItemTree ,
9178 of : AttrOwner ,
92- ) -> Option < ReprData > {
79+ ) -> Option < ReprOptions > {
9380 item_tree. attrs ( db, krate, of) . by_key ( "repr" ) . tt_values ( ) . find_map ( parse_repr_tt)
9481}
9582
96- fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprData > {
83+ fn parse_repr_tt ( tt : & Subtree ) -> Option < ReprOptions > {
9784 match tt. delimiter {
9885 Some ( Delimiter { kind : DelimiterKind :: Parenthesis , .. } ) => { }
9986 _ => return None ,
10087 }
10188
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 ;
10393
10494 let mut tts = tt. token_trees . iter ( ) . peekable ( ) ;
10595 while let Some ( tt) = tts. next ( ) {
10696 if let TokenTree :: Leaf ( Leaf :: Ident ( ident) ) = tt {
107- match & * ident. text {
97+ flags . insert ( match & * ident. text {
10898 "packed" => {
109- data. packed = true ;
110- if let Some ( TokenTree :: Subtree ( _) ) = tts. peek ( ) {
99+ let pack = if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
111100 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 ( )
113113 }
114114 "align" => {
115115 if let Some ( TokenTree :: Subtree ( tt) ) = tts. peek ( ) {
116116 tts. next ( ) ;
117117 if let Some ( TokenTree :: Leaf ( Leaf :: Literal ( lit) ) ) = tt. token_trees . first ( ) {
118118 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) ;
120121 }
121122 }
122123 }
124+ ReprFlags :: empty ( )
123125 }
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 ,
132128 repr => {
133- let is_c = matches ! ( data. kind, ReprKind :: C ) ;
134129 if let Some ( builtin) = BuiltinInt :: from_suffix ( repr)
135130 . map ( Either :: Left )
136131 . or_else ( || BuiltinUint :: from_suffix ( repr) . map ( Either :: Right ) )
137132 {
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+ } ) ;
139151 }
152+ ReprFlags :: empty ( )
140153 }
141- }
154+ } )
142155 }
143156 }
144157
145- Some ( data )
158+ Some ( ReprOptions { int , align : max_align , pack : min_pack , flags , field_shuffle_seed : 0 } )
146159}
147160
148161impl StructData {
@@ -299,10 +312,10 @@ impl EnumData {
299312 Some ( id)
300313 }
301314
302- pub fn variant_body_type ( & self ) -> Either < BuiltinInt , BuiltinUint > {
315+ pub fn variant_body_type ( & self ) -> IntegerType {
303316 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 ) ,
306319 }
307320 }
308321}
0 commit comments