From 9b0ea24698b184a46d430c7e993ab4762ccb3006 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 8 Jan 2025 13:24:14 -0600 Subject: [PATCH] simpler static reader --- crates/libs/bindgen/src/tables/attribute.rs | 2 +- crates/libs/bindgen/src/tables/method_def.rs | 3 +- crates/libs/bindgen/src/tables/type_def.rs | 2 +- crates/libs/bindgen/src/types/class.rs | 10 +++---- crates/libs/bindgen/src/types/cpp_enum.rs | 3 +- crates/libs/bindgen/src/types/cpp_fn.rs | 3 +- crates/libs/bindgen/src/types/cpp_struct.rs | 3 +- crates/libs/bindgen/src/types/mod.rs | 29 ++++---------------- crates/libs/bindgen/src/winmd/blob.rs | 4 --- crates/libs/bindgen/src/winmd/codes.rs | 8 ------ crates/libs/bindgen/src/winmd/file.rs | 7 ----- crates/libs/bindgen/src/winmd/reader.rs | 17 ++++++++++-- crates/libs/bindgen/src/winmd/row.rs | 5 ---- crates/libs/bindgen/src/writer/cpp_handle.rs | 2 +- 14 files changed, 34 insertions(+), 64 deletions(-) diff --git a/crates/libs/bindgen/src/tables/attribute.rs b/crates/libs/bindgen/src/tables/attribute.rs index 0b5d2e8679..48320bab3f 100644 --- a/crates/libs/bindgen/src/tables/attribute.rs +++ b/crates/libs/bindgen/src/tables/attribute.rs @@ -29,7 +29,7 @@ impl Attribute { let ret_type = sig.read_usize(); std::debug_assert_eq!(ret_type, 1); let mut args = Vec::with_capacity(fixed_arg_count); - let reader = self.reader(); + let reader = reader(); for _ in 0..fixed_arg_count { let arg = match Type::from_blob(&mut sig, None, &[]) { diff --git a/crates/libs/bindgen/src/tables/method_def.rs b/crates/libs/bindgen/src/tables/method_def.rs index 6098bf253e..3c5f30cb9a 100644 --- a/crates/libs/bindgen/src/tables/method_def.rs +++ b/crates/libs/bindgen/src/tables/method_def.rs @@ -36,6 +36,7 @@ impl MethodDef { let _param_count = blob.read_usize(); let mut return_type = Type::from_blob(&mut blob, None, generics); let mut return_param = None; + let reader = reader(); let mut params = vec![]; @@ -61,7 +62,7 @@ impl MethodDef { if !param_is_output { if let Some(attribute) = param.find_attribute("AssociatedEnumAttribute") { if let Some((_, Value::Str(name))) = attribute.args().first() { - let overload = param.reader().unwrap_full_name(namespace, name); + let overload = reader.unwrap_full_name(namespace, name); ty = Type::PrimitiveOrEnum(Box::new(ty), Box::new(overload)); } diff --git a/crates/libs/bindgen/src/tables/type_def.rs b/crates/libs/bindgen/src/tables/type_def.rs index f5bb1b59f3..c1b34dc64c 100644 --- a/crates/libs/bindgen/src/tables/type_def.rs +++ b/crates/libs/bindgen/src/tables/type_def.rs @@ -81,7 +81,7 @@ impl TypeDef { if let Some(attribute) = self.find_attribute("RAIIFreeAttribute") { if let Some((_, Value::Str(name))) = attribute.args().first() { if let Some(Type::CppFn(ty)) = - self.reader().with_full_name(self.namespace(), name).next() + reader().with_full_name(self.namespace(), name).next() { return Some(ty); } diff --git a/crates/libs/bindgen/src/types/class.rs b/crates/libs/bindgen/src/types/class.rs index f5df2aa36c..fa9ce56303 100644 --- a/crates/libs/bindgen/src/types/class.rs +++ b/crates/libs/bindgen/src/types/class.rs @@ -253,7 +253,7 @@ impl Class { fn bases(&self) -> Vec { let mut bases = Vec::new(); let mut def = self.def; - let reader = def.reader(); + let reader = reader(); loop { let extends = def.extends().unwrap(); @@ -309,6 +309,8 @@ impl Class { walk(base.def, &[], true, &mut set); } + let reader = reader(); + for attribute in self.def.attributes() { let kind = match attribute.name() { "StaticAttribute" | "ActivatableAttribute" => InterfaceKind::Static, @@ -318,10 +320,8 @@ impl Class { for (_, arg) in attribute.args() { if let Value::TypeName(tn) = arg { - let Type::Interface(mut interface) = self - .def - .reader() - .unwrap_full_name(tn.namespace(), tn.name()) + let Type::Interface(mut interface) = + reader.unwrap_full_name(tn.namespace(), tn.name()) else { panic!("type not found: {tn}"); }; diff --git a/crates/libs/bindgen/src/types/cpp_enum.rs b/crates/libs/bindgen/src/types/cpp_enum.rs index 91e95e88b6..59f1fcdc33 100644 --- a/crates/libs/bindgen/src/types/cpp_enum.rs +++ b/crates/libs/bindgen/src/types/cpp_enum.rs @@ -127,8 +127,7 @@ impl CppEnum { pub fn dependencies(&self, dependencies: &mut TypeMap) { if let Some(attribute) = self.def.find_attribute("AlsoUsableForAttribute") { if let Some((_, Value::Str(type_name))) = attribute.args().first() { - self.def - .reader() + reader() .unwrap_full_name(self.def.namespace(), type_name) .dependencies(dependencies); } diff --git a/crates/libs/bindgen/src/types/cpp_fn.rs b/crates/libs/bindgen/src/types/cpp_fn.rs index 412b6423e2..bad1cfad33 100644 --- a/crates/libs/bindgen/src/types/cpp_fn.rs +++ b/crates/libs/bindgen/src/types/cpp_fn.rs @@ -278,8 +278,7 @@ impl CppFn { }; if let Some(dependency) = dependency { - self.method - .reader() + reader() .unwrap_full_name(self.namespace, dependency) .dependencies(dependencies); } diff --git a/crates/libs/bindgen/src/types/cpp_struct.rs b/crates/libs/bindgen/src/types/cpp_struct.rs index 12bb5e1cf5..3939fe3630 100644 --- a/crates/libs/bindgen/src/types/cpp_struct.rs +++ b/crates/libs/bindgen/src/types/cpp_struct.rs @@ -228,8 +228,7 @@ impl CppStruct { if let Some(attribute) = self.def.find_attribute("AlsoUsableForAttribute") { if let Some((_, Value::Str(type_name))) = attribute.args().first() { - self.def - .reader() + reader() .unwrap_full_name(self.def.namespace(), type_name) .dependencies(dependencies); } diff --git a/crates/libs/bindgen/src/types/mod.rs b/crates/libs/bindgen/src/types/mod.rs index c52f8951a1..01856b1b7c 100644 --- a/crates/libs/bindgen/src/types/mod.rs +++ b/crates/libs/bindgen/src/types/mod.rs @@ -224,8 +224,7 @@ impl Type { } } - code.reader() - .unwrap_full_name(code_name.namespace(), code_name.name()) + reader().unwrap_full_name(code_name.namespace(), code_name.name()) } #[track_caller] @@ -298,9 +297,7 @@ impl Type { let code = blob.decode::(); let code_name = code.type_name(); - let mut ty = blob - .reader() - .unwrap_full_name(code_name.namespace(), code_name.name()); + let mut ty = reader().unwrap_full_name(code_name.namespace(), code_name.name()); let mut item_generics = vec![]; @@ -573,17 +570,11 @@ impl Type { pub fn split_generic(&self) -> (Type, Vec) { match self { Self::Interface(ty) if !ty.generics.is_empty() => { - let base = ty - .def - .reader() - .unwrap_full_name(ty.def.namespace(), ty.def.name()); + let base = reader().unwrap_full_name(ty.def.namespace(), ty.def.name()); (base, ty.generics.clone()) } Self::Delegate(ty) if !ty.generics.is_empty() => { - let base = ty - .def - .reader() - .unwrap_full_name(ty.def.namespace(), ty.def.name()); + let base = reader().unwrap_full_name(ty.def.namespace(), ty.def.name()); (base, ty.generics.clone()) } _ => (self.clone(), vec![]), @@ -630,16 +621,8 @@ impl Type { } if let Some(multi) = match &ty { - Self::CppStruct(ty) => Some( - ty.def - .reader() - .with_full_name(ty.def.namespace(), ty.def.name()), - ), - Self::CppFn(ty) => Some( - ty.method - .reader() - .with_full_name(ty.namespace, ty.method.name()), - ), + Self::CppStruct(ty) => Some(reader().with_full_name(ty.def.namespace(), ty.def.name())), + Self::CppFn(ty) => Some(reader().with_full_name(ty.namespace, ty.method.name())), _ => None, } { multi.for_each(|multi| { diff --git a/crates/libs/bindgen/src/winmd/blob.rs b/crates/libs/bindgen/src/winmd/blob.rs index 53181950c5..7c82b493f0 100644 --- a/crates/libs/bindgen/src/winmd/blob.rs +++ b/crates/libs/bindgen/src/winmd/blob.rs @@ -18,10 +18,6 @@ impl Blob { Self { file, slice } } - pub fn reader(&self) -> &'static Reader { - self.file.reader() - } - fn peek(&self) -> (usize, usize) { if self[0] & 0x80 == 0 { (self[0] as usize, 1) diff --git a/crates/libs/bindgen/src/winmd/codes.rs b/crates/libs/bindgen/src/winmd/codes.rs index 77d650487a..b755ceda5a 100644 --- a/crates/libs/bindgen/src/winmd/codes.rs +++ b/crates/libs/bindgen/src/winmd/codes.rs @@ -83,12 +83,4 @@ impl TypeDefOrRef { rest => panic!("{rest:?}"), } } - - pub fn reader(&self) -> &'static Reader { - match self { - Self::TypeDef(row) => row.reader(), - Self::TypeRef(row) => row.reader(), - Self::TypeSpec(row) => row.reader(), - } - } } diff --git a/crates/libs/bindgen/src/winmd/file.rs b/crates/libs/bindgen/src/winmd/file.rs index 7c707c83fb..63a670d5a8 100644 --- a/crates/libs/bindgen/src/winmd/file.rs +++ b/crates/libs/bindgen/src/winmd/file.rs @@ -1,7 +1,6 @@ use super::*; pub struct File { - pub(crate) reader: *const Reader, bytes: Vec, strings: usize, blobs: usize, @@ -46,7 +45,6 @@ impl File { pub fn new(bytes: Vec) -> Option { let mut result = File { bytes, - reader: std::ptr::null(), strings: 0, blobs: 0, tables: Default::default(), @@ -655,11 +653,6 @@ impl File { pub(crate) fn table(&'static self) -> RowIterator { RowIterator::new(self, 0..self.tables[R::TABLE].len) } - - pub(crate) fn reader(&self) -> &'static Reader { - // Safety: At this point the File is already pointing to a valid Reader. - unsafe { &*self.reader } - } } fn section_from_rva(sections: &[IMAGE_SECTION_HEADER], rva: u32) -> Option<&IMAGE_SECTION_HEADER> { diff --git a/crates/libs/bindgen/src/winmd/reader.rs b/crates/libs/bindgen/src/winmd/reader.rs index 7a0facb9d1..8d59b32cf4 100644 --- a/crates/libs/bindgen/src/winmd/reader.rs +++ b/crates/libs/bindgen/src/winmd/reader.rs @@ -1,4 +1,17 @@ use super::*; +use std::sync::atomic::{AtomicPtr, Ordering}; + +static READER: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + +pub fn reader() -> &'static Reader { + let ptr = READER.load(Ordering::Relaxed); + + if ptr.is_null() { + panic!(); + } else { + unsafe { &*ptr } + } +} fn insert(types: &mut HashMap<&'static str, Vec>, name: &'static str, ty: Type) { types.entry(name).or_default().push(ty); @@ -18,8 +31,7 @@ impl Reader { pub fn new(files: Vec) -> &'static Self { let reader = Box::leak(Box::new(Self(HashMap::new()))); - for mut file in files { - file.reader = reader; + for file in files { let file = Box::leak(Box::new(file)); let mut nested = HashMap::>::new(); @@ -167,6 +179,7 @@ impl Reader { } } + READER.store(reader, Ordering::Relaxed); reader } diff --git a/crates/libs/bindgen/src/winmd/row.rs b/crates/libs/bindgen/src/winmd/row.rs index d965c1e2bb..afa72233a1 100644 --- a/crates/libs/bindgen/src/winmd/row.rs +++ b/crates/libs/bindgen/src/winmd/row.rs @@ -21,11 +21,6 @@ pub trait AsRow: Copy { self.to_row().file } - fn reader(&self) -> &'static Reader { - // Safety: At this point the File is already pointing to a valid Reader. - unsafe { &*self.file().reader } - } - fn index(&self) -> usize { self.to_row().index } diff --git a/crates/libs/bindgen/src/writer/cpp_handle.rs b/crates/libs/bindgen/src/writer/cpp_handle.rs index 722f0b7495..b5bd35af2c 100644 --- a/crates/libs/bindgen/src/writer/cpp_handle.rs +++ b/crates/libs/bindgen/src/writer/cpp_handle.rs @@ -111,7 +111,7 @@ impl Writer { if let Some(attribute) = def.find_attribute("AlsoUsableForAttribute") { if let Some((_, Value::Str(type_name))) = attribute.args().first() { - let ty = def.reader().unwrap_full_name(def.namespace(), type_name); + let ty = reader().unwrap_full_name(def.namespace(), type_name); let ty = ty.write_name(self);