From 01763ef539c65f99227521b489edbd1c293cffff Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 3 Dec 2024 09:05:56 -0600 Subject: [PATCH] natural type sort --- crates/libs/bindgen/src/libraries.rs | 4 +-- crates/libs/bindgen/src/type_name.rs | 16 +++++++++- crates/libs/bindgen/src/types/mod.rs | 47 +++++++++++++++++++++++++++- crates/libs/bindgen/src/winmd/row.rs | 17 +++------- 4 files changed, 67 insertions(+), 17 deletions(-) diff --git a/crates/libs/bindgen/src/libraries.rs b/crates/libs/bindgen/src/libraries.rs index 77686aecce..b019b3c8db 100644 --- a/crates/libs/bindgen/src/libraries.rs +++ b/crates/libs/bindgen/src/libraries.rs @@ -34,7 +34,7 @@ fn combine_libraries( if flags.contains(PInvokeAttributes::CallConvPlatformapi) { let arches = ty.method.arches(); - let params = if arches.is_empty() || arches.contains("x86") { + let params = if (arches == 0) || (arches & 1 == 1) { ty.method.signature(ty.namespace, &[]).size() } else { 0 @@ -67,7 +67,7 @@ fn cpp_fn(types: &[Type]) -> Option { for ty in &functions { let arches = ty.method.arches(); - if arches.is_empty() || arches.contains("x86") { + if (arches == 0) || (arches & 1 == 1) { return Some(ty.clone()); } } diff --git a/crates/libs/bindgen/src/type_name.rs b/crates/libs/bindgen/src/type_name.rs index 9245b08a8c..e0830e52cf 100644 --- a/crates/libs/bindgen/src/type_name.rs +++ b/crates/libs/bindgen/src/type_name.rs @@ -1,8 +1,22 @@ use super::*; -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct TypeName(pub &'static str, pub &'static str); +impl Ord for TypeName { + fn cmp(&self, other: &Self) -> Ordering { + // Type names are sorted before namespaces. The `Type` sort order depends on this. + // This is more efficient in general as many types typically share a namespace. + (self.1, self.0).cmp(&(other.1, other.0)) + } +} + +impl PartialOrd for TypeName { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl TypeName { pub const Object: Self = Self("System", "Object"); pub const GUID: Self = Self("System", "Guid"); diff --git a/crates/libs/bindgen/src/types/mod.rs b/crates/libs/bindgen/src/types/mod.rs index e01e5426dd..2eec9dba02 100644 --- a/crates/libs/bindgen/src/types/mod.rs +++ b/crates/libs/bindgen/src/types/mod.rs @@ -28,7 +28,7 @@ pub use method::*; pub use r#enum::*; pub use r#struct::*; -#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Type { CppFn(CppFn), Class(Class), @@ -80,6 +80,18 @@ pub enum Type { BSTR, } +impl Ord for Type { + fn cmp(&self, other: &Self) -> Ordering { + self.sort_key().cmp(&(other.sort_key())) + } +} + +impl PartialOrd for Type { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + #[derive(PartialEq)] pub enum Remap { Type(Type), @@ -88,6 +100,39 @@ pub enum Remap { } impl Type { + fn sort_key(&self) -> (bool, TypeName, i32, i32) { + // This sorts types as follows: + // 1. functions are placed first + // 2. type name + // 3. type namespace + // 4. architecture + // 5. overloaded types + + let kind = match self { + Self::CppFn(..) => 0, + Self::Class(..) => 1, + Self::Interface(..) => 2, + Self::CppInterface(..) => 3, + Self::Delegate(..) => 4, + Self::CppDelegate(..) => 5, + Self::Enum(..) => 6, + Self::CppEnum(..) => 7, + Self::Struct(..) => 8, + Self::CppStruct(..) => 9, + Self::CppConst(..) => 10, + _ => -1, + }; + + let arches = match self { + Self::CppFn(ty) => ty.method.arches(), + Self::CppStruct(ty) => ty.def.arches(), + Self::CppDelegate(ty) => ty.def.arches(), + _ => 0, + }; + + (kind != 0, self.type_name(), arches, kind) + } + fn is_intrinsic(&self) -> bool { matches!( self, diff --git a/crates/libs/bindgen/src/winmd/row.rs b/crates/libs/bindgen/src/winmd/row.rs index bc0de58b52..d965c1e2bb 100644 --- a/crates/libs/bindgen/src/winmd/row.rs +++ b/crates/libs/bindgen/src/winmd/row.rs @@ -86,7 +86,7 @@ pub trait HasAttributes { fn find_attribute(&self, name: &str) -> Option; fn has_attribute(&self, name: &str) -> bool; fn guid_attribute(&self) -> Option; - fn arches(&self) -> HashSet<&'static str>; + fn arches(&self) -> i32; } impl> HasAttributes for R { @@ -142,21 +142,12 @@ impl> HasAttributes for R { }) } - fn arches(&self) -> HashSet<&'static str> { - let mut arches = HashSet::new(); + fn arches(&self) -> i32 { + let mut arches = 0; if let Some(attribute) = self.find_attribute("SupportedArchitectureAttribute") { if let Some((_, Value::I32(value))) = attribute.args().first() { - if value & 1 == 1 { - arches.insert("x86"); - } - if value & 2 == 2 { - arches.insert("x86_64"); - arches.insert("arm64ec"); - } - if value & 4 == 4 { - arches.insert("aarch64"); - } + arches = *value; } }