Skip to content

Commit 719efba

Browse files
committed
feat(ast_codegen): add alignment and size data to the schema.
1 parent af18a31 commit 719efba

File tree

11 files changed

+1763
-53
lines changed

11 files changed

+1763
-53
lines changed

crates/oxc_ast/src/generated/assert_layouts.rs

Lines changed: 1001 additions & 0 deletions
Large diffs are not rendered by default.

crates/oxc_ast/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub mod syntax_directed_operations;
3737
mod trivia;
3838

3939
mod generated {
40+
#[cfg(debug_assertions)]
41+
pub mod assert_layouts;
4042
pub mod ast_builder;
4143
pub mod ast_kind;
4244
pub mod span;

tasks/ast_codegen/src/defs.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{REnum, RStruct, RType};
2-
use crate::{schema::Inherit, util::TypeExt, TypeName};
2+
use crate::{layout::KnownLayout, schema::Inherit, util::TypeExt, TypeName};
33
use quote::ToTokens;
44
use serde::Serialize;
55

@@ -9,11 +9,24 @@ pub enum TypeDef {
99
Enum(EnumDef),
1010
}
1111

12+
impl TypeDef {
13+
pub fn name(&self) -> &String {
14+
match self {
15+
Self::Struct(it) => &it.name,
16+
Self::Enum(it) => &it.name,
17+
}
18+
}
19+
}
20+
1221
#[derive(Debug, Serialize)]
1322
pub struct StructDef {
1423
pub name: TypeName,
1524
pub fields: Vec<FieldDef>,
1625
pub has_lifetime: bool,
26+
pub size_64: usize,
27+
pub align_64: usize,
28+
pub size_32: usize,
29+
pub align_32: usize,
1730
}
1831

1932
#[derive(Debug, Serialize)]
@@ -23,6 +36,10 @@ pub struct EnumDef {
2336
/// For `@inherits` inherited enum variants
2437
pub inherits: Vec<EnumInheritDef>,
2538
pub has_lifetime: bool,
39+
pub size_64: usize,
40+
pub align_64: usize,
41+
pub size_32: usize,
42+
pub align_32: usize,
2643
}
2744

2845
#[derive(Debug, Serialize)]
@@ -57,21 +74,47 @@ impl From<&RType> for Option<TypeDef> {
5774

5875
impl From<&REnum> for EnumDef {
5976
fn from(it @ REnum { item, meta }: &REnum) -> Self {
77+
let (size_64, align_64) = meta
78+
.layout_64
79+
.layout()
80+
.map_or_else(|| panic!("Uncalculated layout on {}!", item.ident), KnownLayout::unpack);
81+
let (size_32, align_32) = meta
82+
.layout_32
83+
.layout()
84+
.map_or_else(|| panic!("Uncalculated layout on {}!", item.ident), KnownLayout::unpack);
6085
Self {
6186
name: it.ident().to_string(),
6287
variants: item.variants.iter().map(Into::into).collect(),
63-
has_lifetime: item.generics.lifetimes().count() > 0,
6488
inherits: meta.inherits.iter().map(Into::into).collect(),
89+
has_lifetime: item.generics.lifetimes().count() > 0,
90+
91+
size_64,
92+
align_64,
93+
size_32,
94+
align_32,
6595
}
6696
}
6797
}
6898

6999
impl From<&RStruct> for StructDef {
70-
fn from(it @ RStruct { item, .. }: &RStruct) -> Self {
100+
fn from(it @ RStruct { item, meta }: &RStruct) -> Self {
101+
let (size_64, align_64) = meta
102+
.layout_64
103+
.layout()
104+
.map_or_else(|| panic!("Uncalculated layout on {}!", item.ident), KnownLayout::unpack);
105+
let (size_32, align_32) = meta
106+
.layout_32
107+
.layout()
108+
.map_or_else(|| panic!("Uncalculated layout on {}!", item.ident), KnownLayout::unpack);
71109
Self {
72110
name: it.ident().to_string(),
73111
fields: item.fields.iter().map(Into::into).collect(),
74112
has_lifetime: item.generics.lifetimes().count() > 0,
113+
114+
size_64,
115+
align_64,
116+
size_32,
117+
align_32,
75118
}
76119
}
77120
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use proc_macro2::TokenStream;
2+
use quote::quote;
3+
use syn::{parse_quote, PathArguments, Type};
4+
5+
use crate::{
6+
defs::{EnumDef, StructDef, TypeDef},
7+
output, CodegenCtx, Generator, GeneratorOutput,
8+
};
9+
10+
use super::generated_header;
11+
12+
pub struct AssertLayouts;
13+
14+
impl Generator for AssertLayouts {
15+
fn name(&self) -> &'static str {
16+
stringify!(AssertLayouts)
17+
}
18+
19+
fn generate(&mut self, ctx: &CodegenCtx) -> GeneratorOutput {
20+
let (assertions_64, assertions_32) = ctx
21+
.schema
22+
.definitions
23+
.iter()
24+
.map(|def| {
25+
let typ =
26+
ctx.find(def.name()).and_then(|ty| ty.borrow().as_type()).map(|mut ty| {
27+
if let Type::Path(ty) = &mut ty {
28+
if let Some(seg) = ty.path.segments.first_mut() {
29+
if let PathArguments::AngleBracketed(args) = &mut seg.arguments {
30+
*args = parse_quote!(<'static>);
31+
}
32+
}
33+
}
34+
ty
35+
});
36+
match def {
37+
TypeDef::Struct(StructDef { size_64, align_64, size_32, align_32, .. })
38+
| TypeDef::Enum(EnumDef { size_64, align_64, size_32, align_32, .. }) => (
39+
quote! {
40+
assert!(size_of::<#typ>() == #size_64);
41+
assert!(align_of::<#typ>() == #align_64);
42+
},
43+
quote! {
44+
assert!(size_of::<#typ>() == #size_32);
45+
assert!(align_of::<#typ>() == #align_32);
46+
},
47+
),
48+
}
49+
})
50+
.collect::<(Vec<TokenStream>, Vec<TokenStream>)>();
51+
52+
let header = generated_header!();
53+
54+
GeneratorOutput::Stream((
55+
output(crate::AST_CRATE, "assert_layouts.rs"),
56+
quote! {
57+
#header
58+
59+
use crate::ast::*;
60+
61+
endl!();
62+
63+
#[cfg(target_pointer_width = "64")]
64+
const _: () = { #(#assertions_64)* };
65+
#[cfg(target_pointer_width = "32")]
66+
const _: () = { #(#assertions_32)* };
67+
#[cfg(not(any(target_pointer_width = "64", target_pointer_width = "32")))]
68+
const _: () = panic!("Platforms with pointer width other than 64 or 32 bit are not supported");
69+
},
70+
))
71+
}
72+
}

tasks/ast_codegen/src/generators/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod assert_layouts;
12
mod ast_builder;
23
mod ast_kind;
34
mod impl_get_span;
@@ -39,6 +40,7 @@ macro_rules! generated_header {
3940
pub(crate) use generated_header;
4041
pub(crate) use insert;
4142

43+
pub use assert_layouts::AssertLayouts;
4244
pub use ast_builder::AstBuilderGenerator;
4345
pub use ast_kind::AstKindGenerator;
4446
pub use impl_get_span::ImplGetSpanGenerator;

0 commit comments

Comments
 (0)