Skip to content

Commit 1ac34c2

Browse files
committed
Compute data layout of types
1 parent 0340b51 commit 1ac34c2

File tree

16 files changed

+2823
-157
lines changed

16 files changed

+2823
-157
lines changed

crates/hir-def/src/adt.rs

+34-39
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Defines hir-level representation of structs, enums and unions
22
3-
use std::{num::NonZeroU32, sync::Arc};
3+
use std::sync::Arc;
44

55
use base_db::CrateId;
66
use either::Either;
@@ -18,6 +18,7 @@ use crate::{
1818
db::DefDatabase,
1919
intern::Interned,
2020
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
21+
layout::{Align, ReprFlags, ReprOptions},
2122
nameres::diagnostics::DefDiagnostic,
2223
src::HasChildSource,
2324
src::HasSource,
@@ -34,15 +35,15 @@ use cfg::CfgOptions;
3435
pub struct StructData {
3536
pub name: Name,
3637
pub variant_data: Arc<VariantData>,
37-
pub repr: Option<ReprData>,
38+
pub repr: Option<ReprOptions>,
3839
pub visibility: RawVisibility,
3940
}
4041

4142
#[derive(Debug, Clone, PartialEq, Eq)]
4243
pub struct EnumData {
4344
pub name: Name,
4445
pub variants: Arena<EnumVariantData>,
45-
pub repr: Option<ReprData>,
46+
pub repr: Option<ReprOptions>,
4647
pub visibility: RawVisibility,
4748
}
4849

@@ -67,80 +68,74 @@ pub struct FieldData {
6768
pub visibility: RawVisibility,
6869
}
6970

70-
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
71-
pub enum ReprKind {
72-
C,
73-
BuiltinInt { builtin: Either<BuiltinInt, BuiltinUint>, is_c: bool },
74-
Transparent,
75-
Default,
76-
}
77-
78-
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
79-
pub struct ReprData {
80-
pub kind: ReprKind,
81-
pub packed: bool,
82-
pub align: Option<NonZeroU32>,
83-
}
84-
8571
fn repr_from_value(
8672
db: &dyn DefDatabase,
8773
krate: CrateId,
8874
item_tree: &ItemTree,
8975
of: AttrOwner,
90-
) -> Option<ReprData> {
76+
) -> Option<ReprOptions> {
9177
item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
9278
}
9379

94-
fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
80+
fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
9581
match tt.delimiter {
9682
Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {}
9783
_ => return None,
9884
}
9985

100-
let mut data = ReprData { kind: ReprKind::Default, packed: false, align: None };
86+
let mut flags = ReprFlags::empty();
87+
let mut int = None;
88+
let mut max_align: Option<Align> = None;
89+
let mut min_pack: Option<Align> = None;
10190

10291
let mut tts = tt.token_trees.iter().peekable();
10392
while let Some(tt) = tts.next() {
10493
if let TokenTree::Leaf(Leaf::Ident(ident)) = tt {
105-
match &*ident.text {
94+
flags.insert(match &*ident.text {
10695
"packed" => {
107-
data.packed = true;
108-
if let Some(TokenTree::Subtree(_)) = tts.peek() {
96+
let pack = if let Some(TokenTree::Subtree(tt)) = tts.peek() {
10997
tts.next();
110-
}
98+
if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
99+
lit.text.parse().unwrap_or_default()
100+
} else {
101+
0
102+
}
103+
} else {
104+
0
105+
};
106+
let pack = Align::from_bytes(pack).unwrap();
107+
min_pack =
108+
Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack });
109+
ReprFlags::empty()
111110
}
112111
"align" => {
113112
if let Some(TokenTree::Subtree(tt)) = tts.peek() {
114113
tts.next();
115114
if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
116115
if let Ok(align) = lit.text.parse() {
117-
data.align = Some(align);
116+
let align = Align::from_bytes(align).ok();
117+
max_align = max_align.max(align);
118118
}
119119
}
120120
}
121+
ReprFlags::empty()
121122
}
122-
"C" => {
123-
if let ReprKind::BuiltinInt { is_c, .. } = &mut data.kind {
124-
*is_c = true;
125-
} else {
126-
data.kind = ReprKind::C;
127-
}
128-
}
129-
"transparent" => data.kind = ReprKind::Transparent,
123+
"C" => ReprFlags::IS_C,
124+
"transparent" => ReprFlags::IS_TRANSPARENT,
130125
repr => {
131-
let is_c = matches!(data.kind, ReprKind::C);
132126
if let Some(builtin) = BuiltinInt::from_suffix(repr)
133127
.map(Either::Left)
134128
.or_else(|| BuiltinUint::from_suffix(repr).map(Either::Right))
135129
{
136-
data.kind = ReprKind::BuiltinInt { builtin, is_c };
130+
int = Some(builtin);
137131
}
132+
ReprFlags::empty()
138133
}
139-
}
134+
})
140135
}
141136
}
142137

143-
Some(data)
138+
Some(ReprOptions { int, align: max_align, pack: min_pack, flags })
144139
}
145140

146141
impl StructData {
@@ -283,7 +278,7 @@ impl EnumData {
283278

284279
pub fn variant_body_type(&self) -> Either<BuiltinInt, BuiltinUint> {
285280
match self.repr {
286-
Some(ReprData { kind: ReprKind::BuiltinInt { builtin, .. }, .. }) => builtin,
281+
Some(ReprOptions { int: Some(builtin), .. }) => builtin,
287282
_ => Either::Left(BuiltinInt::Isize),
288283
}
289284
}

0 commit comments

Comments
 (0)