-
-
Notifications
You must be signed in to change notification settings - Fork 466
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ast_codegen): add alignment and size data to the schema.
- Loading branch information
Showing
12 changed files
with
3,552 additions
and
1,071 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
2,124 changes: 1,062 additions & 1,062 deletions
2,124
crates/oxc_ast/src/generated/assert_layouts.rs
Large diffs are not rendered by default.
Oops, something went wrong.
1,899 changes: 1,899 additions & 0 deletions
1,899
crates/oxc_ast/src/generated/assert_repr_rust_layout.rs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
405 changes: 405 additions & 0 deletions
405
crates/oxc_ast_macros/src/generated/ast_field_order_data.rs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use proc_macro2::TokenStream; | ||
use quote::format_ident; | ||
use syn::{Field, Fields, FieldsNamed, FieldsUnnamed, ItemStruct}; | ||
|
||
const DUMMY: &str = "DUMMY"; | ||
|
||
#[inline] | ||
pub fn reorder_fields(ty: &mut ItemStruct, data: &[u8]) { | ||
let (Fields::Named(FieldsNamed { named: fields, .. }) | ||
| Fields::Unnamed(FieldsUnnamed { unnamed: fields, .. })) = &mut ty.fields | ||
else { | ||
debug_assert!(false, "Entered unreachable code!"); | ||
// SAFETY: We don't generate any ordering data for empty structs, And the debug assertions | ||
// are on in CI runs; The debug assertion above would ensure any possible mistake gets caught | ||
// by tests early on in the PR's life span. This allows us to avoid a branch here. | ||
unsafe { std::hint::unreachable_unchecked() } | ||
}; | ||
|
||
// TODO: We can replace this with uninitialized memory, It might be faster if we use one byte | ||
// to check if a field is placeholder or not and keep the rest of the bytes uninitialized as we | ||
// never read them. I'm not sure if it is safe with a mutable reference or not but I believe it | ||
// would be safe with exclusive ownership of the field. | ||
let mut pick = Field { | ||
attrs: Vec::default(), | ||
vis: syn::Visibility::Inherited, | ||
mutability: syn::FieldMutability::None, | ||
ident: Some(format_ident!("{DUMMY}")), | ||
colon_token: None, | ||
ty: syn::Type::Verbatim(TokenStream::default()), | ||
}; | ||
// TODO: use bit array here? | ||
let mut is_ordered = vec![false; fields.len()]; | ||
let mut target; | ||
// Best case O(n), Worst case O(2n) | ||
for i in 0..fields.len() { | ||
if is_ordered[i] { | ||
continue; | ||
} | ||
|
||
let field = &mut fields[i]; | ||
// `pick` the first unordered field | ||
pick = std::mem::replace(field, pick); | ||
// capture its ideal position | ||
target = data[i]; | ||
|
||
// while we have something in our `pick` | ||
while pick.ident.as_ref().is_some_and(|it| it != DUMMY) { | ||
// select the slot of target position | ||
let field = &mut fields[target as usize]; | ||
// put the picked field in the target slot and pick the previous item | ||
pick = std::mem::replace(field, pick); | ||
// mark the field as ordered | ||
is_ordered[target as usize] = true; | ||
// capture the ideal position of our new pick | ||
target = data[target as usize]; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
use itertools::Itertools; | ||
use proc_macro2::TokenStream; | ||
use quote::quote; | ||
use syn::ItemStruct; | ||
|
||
use crate::{layout::Layout, output, schema::RType, CodegenCtx, Generator, GeneratorOutput}; | ||
|
||
use super::{define_generator, generated_header}; | ||
|
||
define_generator! { | ||
pub struct AstFieldOrder; | ||
} | ||
|
||
impl Generator for AstFieldOrder { | ||
fn name(&self) -> &'static str { | ||
stringify!(AstFieldOrder) | ||
} | ||
|
||
fn generate(&mut self, ctx: &CodegenCtx) -> GeneratorOutput { | ||
let orders_64 = ctx | ||
.ty_table | ||
.iter() | ||
.filter(|ty| matches!(&*ty.borrow(), RType::Struct(s) if !s.item.fields.is_empty())) | ||
.map(|ty| { | ||
let RType::Struct(ty) = &*ty.borrow() else { unreachable!() }; | ||
generate_orders(&ty.item, &ty.meta.layout_64) | ||
}); | ||
let orders_32 = ctx | ||
.ty_table | ||
.iter() | ||
.filter(|ty| matches!(&*ty.borrow(), RType::Struct(s) if !s.item.fields.is_empty())) | ||
.map(|ty| { | ||
let RType::Struct(ty) = &*ty.borrow() else { unreachable!() }; | ||
generate_orders(&ty.item, &ty.meta.layout_64) | ||
}); | ||
let header = generated_header!(); | ||
GeneratorOutput::Stream(( | ||
output(crate::AST_MACROS_CRATE, "ast_field_order_data.rs"), | ||
quote! { | ||
#header | ||
use lazy_static::lazy_static; | ||
use rustc_hash::FxHashMap; | ||
|
||
endl!(); | ||
|
||
pub fn get(ident: &str) -> Option<&[u8]> { | ||
|
||
#[cfg(not(any(target_pointer_width = "64", target_pointer_width = "32")))] | ||
std::compile_error!( | ||
"Platforms with pointer width other than 64 or 32 bit are not supported" | ||
); | ||
#[cfg(target_pointer_width = "64")] | ||
lazy_static! { | ||
static ref DATA: FxHashMap<&'static str, &'static [u8]> = | ||
FxHashMap::from_iter([#(#orders_64),*]); | ||
} | ||
#[cfg(target_pointer_width = "32")] | ||
lazy_static! { | ||
static ref DATA: FxHashMap<&'static str, &'static [u8]> = | ||
FxHashMap::from_iter([#(#orders_32),*]); | ||
} | ||
|
||
|
||
DATA.get(ident).copied() | ||
} | ||
}, | ||
)) | ||
} | ||
} | ||
|
||
fn generate_orders(ty: &ItemStruct, layout: &Layout) -> Option<TokenStream> { | ||
let ident = &ty.ident.to_string(); | ||
let Layout::Layout(layout) = layout else { panic!("Layout isn't determined yet!") }; | ||
let offsets = layout.offsets(); | ||
if let Some(offsets) = offsets { | ||
let orders = offsets | ||
.iter() | ||
.zip(ty.fields.iter().enumerate()) | ||
.sorted_by(|a, b| Ord::cmp(a.0, b.0)) | ||
.map(|(_, fi)| fi) | ||
.enumerate() | ||
.sorted_by(|a, b| Ord::cmp(&a.1 .0, &b.1 .0)) | ||
.map(|it| { | ||
u8::try_from(it.0).expect("We have no AST type with enough fields to exhaust `u8`.") | ||
}); | ||
Some(quote!((#ident, &[#(#orders),*][..]))) | ||
} else { | ||
None | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters