Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dependencies
Browse files Browse the repository at this point in the history
kennykerr committed Jan 21, 2025
1 parent cbcfa6e commit af731c4
Showing 16 changed files with 250 additions and 242 deletions.
10 changes: 6 additions & 4 deletions crates/libs/bindgen/src/signature.rs
Original file line number Diff line number Diff line change
@@ -14,10 +14,6 @@ impl Signature {
.fold(0, |sum, param| sum + std::cmp::max(4, param.size()))
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
self.types().for_each(|ty| ty.dependencies(dependencies));
}

pub fn types(&self) -> impl Iterator<Item = &Type> + '_ {
std::iter::once(&self.return_type)
.chain(self.params.iter().map(|param| &param.ty))
@@ -44,3 +40,9 @@ impl Signature {
false
}
}

impl Dependencies for Signature {
fn combine(&self, dependencies: &mut TypeMap) {
self.types().for_each(|ty| ty.combine(dependencies));
}
}
25 changes: 25 additions & 0 deletions crates/libs/bindgen/src/tables/method_def.rs
Original file line number Diff line number Diff line change
@@ -15,6 +15,17 @@ impl MethodDef {
self.str(3)
}

pub fn import_name(&self) -> Option<&'static str> {
self.impl_map().map_or(None, |map| {
let import_name = map.import_name();
if self.name() != import_name {
Some(import_name)
} else {
None
}
})
}

pub fn params(&self) -> RowIterator<MethodParam> {
self.list(5)
}
@@ -29,6 +40,20 @@ impl MethodDef {
self.impl_map().map_or("", |map| map.scope().name())
}

pub fn calling_convention(&self) -> &'static str {
self.impl_map().map_or("", |map| {
let flags = map.flags();

if flags.contains(PInvokeAttributes::CallConvPlatformapi) {
"system"
} else if flags.contains(PInvokeAttributes::CallConvCdecl) {
"cdecl"
} else {
""
}
})
}

#[track_caller]
pub fn signature(&self, namespace: &str, generics: &[Type]) -> Signature {
let mut blob = self.blob(4);
12 changes: 11 additions & 1 deletion crates/libs/bindgen/src/type_map.rs
Original file line number Diff line number Diff line change
@@ -3,6 +3,16 @@ use super::*;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TypeMap(HashMap<TypeName, HashSet<Type>>);

pub trait Dependencies {
fn combine(&self, dependencies: &mut TypeMap);

fn dependencies(&self) -> TypeMap {
let mut dependencies = TypeMap::new();
self.combine(&mut dependencies);
dependencies
}
}

impl std::ops::Deref for TypeMap {
type Target = HashMap<TypeName, HashSet<Type>>;

@@ -27,7 +37,7 @@ impl TypeMap {
let mut item_dependencies = Self::new();

for ty in types {
ty.dependencies(&mut item_dependencies);
ty.combine(&mut item_dependencies);
}

if item_dependencies.excluded(filter) {
25 changes: 11 additions & 14 deletions crates/libs/bindgen/src/types/class.rs
Original file line number Diff line number Diff line change
@@ -15,9 +15,7 @@ impl Class {
return (Cfg::default(), quote! {});
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
let cfg = Cfg::new(self.def, &dependencies);
let cfg = Cfg::new(self.def, &self.dependencies());
let tokens = cfg.write(writer, false);
(cfg, tokens)
}
@@ -83,7 +81,7 @@ impl Class {
}
);

let factories = required_interfaces.iter().filter_map(|interface| match interface.kind {
let factories = required_interfaces. iter().filter_map(|interface| match interface.kind {
InterfaceKind::Static | InterfaceKind::Composable => {
if interface.def.methods().next().is_none() {
None
@@ -92,10 +90,7 @@ impl Class {
let interface_type = interface.write_name(writer);

let cfg = if writer.config.package {
let mut dependencies = TypeMap::new();
interface.dependencies(&mut dependencies);

class_cfg.difference(interface.def, &dependencies).write(writer, false)
class_cfg.difference(interface.def, &interface.dependencies()).write(writer, false)
} else {
quote! {}
};
@@ -252,12 +247,6 @@ impl Class {
)
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
for interface in self.required_interfaces() {
Type::Interface(interface).dependencies(dependencies);
}
}

fn bases(&self) -> Vec<Self> {
let mut bases = Vec::new();
let mut def = self.def;
@@ -356,3 +345,11 @@ impl Class {
})
}
}

impl Dependencies for Class {
fn combine(&self, dependencies: &mut TypeMap) {
for interface in self.required_interfaces() {
Type::Interface(interface).combine(dependencies);
}
}
}
13 changes: 5 additions & 8 deletions crates/libs/bindgen/src/types/cpp_const.rs
Original file line number Diff line number Diff line change
@@ -32,9 +32,7 @@ impl CppConst {
return quote! {};
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
Cfg::new(self.field, &dependencies).write(writer, false)
Cfg::new(self.field, &self.dependencies()).write(writer, false)
}

pub fn write(&self, writer: &Writer) -> TokenStream {
@@ -137,12 +135,11 @@ impl CppConst {
panic!()
}
}
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
self.field
.ty(None)
.to_const_type()
.dependencies(dependencies);
impl Dependencies for CppConst {
fn combine(&self, dependencies: &mut TypeMap) {
self.field.ty(None).to_const_type().combine(dependencies);
}
}

10 changes: 5 additions & 5 deletions crates/libs/bindgen/src/types/cpp_delegate.rs
Original file line number Diff line number Diff line change
@@ -38,9 +38,7 @@ impl CppDelegate {
return quote! {};
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
Cfg::new(self.def, &dependencies).write(writer, false)
Cfg::new(self.def, &self.dependencies()).write(writer, false)
}

pub fn write(&self, writer: &Writer) -> TokenStream {
@@ -65,11 +63,13 @@ impl CppDelegate {
pub type #name = Option<unsafe extern "system" fn(#params) #return_sig>;
}
}
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
impl Dependencies for CppDelegate {
fn combine(&self, dependencies: &mut TypeMap) {
self.method()
.signature(self.def.namespace(), &[])
.dependencies(dependencies);
.combine(dependencies);
}
}

22 changes: 12 additions & 10 deletions crates/libs/bindgen/src/types/cpp_enum.rs
Original file line number Diff line number Diff line change
@@ -124,22 +124,24 @@ impl CppEnum {
}
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
pub fn size(&self) -> usize {
self.def.underlying_type().size()
}

pub fn align(&self) -> usize {
self.def.underlying_type().align()
}
}

impl Dependencies for CppEnum {
fn combine(&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()
.unwrap_full_name(self.def.namespace(), type_name)
.dependencies(dependencies);
.combine(dependencies);
}
}
}

pub fn size(&self) -> usize {
self.def.underlying_type().size()
}

pub fn align(&self) -> usize {
self.def.underlying_type().align()
}
}
37 changes: 8 additions & 29 deletions crates/libs/bindgen/src/types/cpp_fn.rs
Original file line number Diff line number Diff line change
@@ -28,26 +28,10 @@ impl CppFn {
}

pub fn write_link(&self, writer: &Writer, underlying_types: bool) -> TokenStream {
let name = self.method.name();
let library = self.method.module_name().to_lowercase();
let impl_map = self.method.impl_map().unwrap();
let mut symbol = Some(impl_map.import_name());

if symbol == Some(name) {
symbol = None;
}

let symbol = self.method.import_name();
let name = to_ident(self.method.name());
let impl_flags = impl_map.flags();

let abi = if impl_flags.contains(PInvokeAttributes::CallConvPlatformapi) {
"system"
} else if impl_flags.contains(PInvokeAttributes::CallConvCdecl) {
"cdecl"
} else {
panic!()
};

let abi = self.method.calling_convention();
let signature = self.method.signature(self.namespace, &[]);

let params = signature.params.iter().map(|param| {
@@ -81,19 +65,12 @@ impl CppFn {
return quote! {};
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
Cfg::new(self.method, &dependencies).write(writer, false)
Cfg::new(self.method, &self.dependencies()).write(writer, false)
}

pub fn write(&self, writer: &Writer) -> TokenStream {
let name = to_ident(self.method.name());
let signature = self.method.signature(self.namespace, &[]);
let mut dependencies = TypeMap::new();

if writer.config.package {
self.dependencies(&mut dependencies);
}

let link = self.write_link(writer, false);
let arches = write_arches(self.method);
@@ -271,11 +248,13 @@ impl CppFn {
_ => quote! {},
}
}
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
impl Dependencies for CppFn {
fn combine(&self, dependencies: &mut TypeMap) {
self.method
.signature(self.namespace, &[])
.dependencies(dependencies);
.combine(dependencies);

let dependency = match self.method.name() {
"GetWindowLongPtrA" => Some("GetWindowLongA"),
@@ -289,7 +268,7 @@ impl CppFn {
self.method
.reader()
.unwrap_full_name(self.namespace, dependency)
.dependencies(dependencies);
.combine(dependencies);
}
}
}
48 changes: 23 additions & 25 deletions crates/libs/bindgen/src/types/cpp_interface.rs
Original file line number Diff line number Diff line change
@@ -49,9 +49,7 @@ impl CppInterface {
return (Cfg::default(), quote! {});
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
let cfg = Cfg::new(self.def, &dependencies);
let cfg = Cfg::new(self.def, &self.dependencies());
let tokens = cfg.write(writer, false);
(cfg, tokens)
}
@@ -223,21 +221,20 @@ impl CppInterface {
let impl_name: TokenStream = format!("{}_Impl", self.def.name()).into();

let cfg = if writer.config.package {
fn collect(interface: &CppInterface, dependencies: &mut TypeMap, writer: &Writer) {
fn combine(interface: &CppInterface, dependencies: &mut TypeMap, writer: &Writer) {
for method in interface.get_methods(writer).iter() {
if let CppMethodOrName::Method(method) = method {
dependencies.combine(&method.dependencies);
}
}
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
let mut dependencies = self.dependencies();
combine(self, &mut dependencies, writer);

collect(self, &mut dependencies, writer);
base_interfaces.iter().for_each(|interface| {
if let Type::CppInterface(ty) = interface {
collect(ty, &mut dependencies, writer);
combine(ty, &mut dependencies, writer);
}
});

@@ -417,23 +414,6 @@ impl CppInterface {
quote! { #namespace #name }
}

#[track_caller]
pub fn dependencies(&self, dependencies: &mut TypeMap) {
let base_interfaces = self.base_interfaces();

for interface in &base_interfaces {
interface.dependencies(dependencies);
}

for method in self.def.methods() {
for ty in method.signature(self.def.namespace(), &[]).types() {
if ty.is_core() {
ty.dependencies(dependencies);
}
}
}
}

pub fn base_interfaces(&self) -> Vec<Type> {
let mut bases = vec![];
let mut def = self.def;
@@ -460,3 +440,21 @@ impl CppInterface {
bases
}
}

impl Dependencies for CppInterface {
fn combine(&self, dependencies: &mut TypeMap) {
let base_interfaces = self.base_interfaces();

for interface in &base_interfaces {
interface.combine(dependencies);
}

for method in self.def.methods() {
for ty in method.signature(self.def.namespace(), &[]).types() {
if ty.is_core() {
ty.combine(dependencies);
}
}
}
}
}
5 changes: 1 addition & 4 deletions crates/libs/bindgen/src/types/cpp_method.rs
Original file line number Diff line number Diff line change
@@ -78,16 +78,13 @@ impl ParamHint {
impl CppMethod {
pub fn new(def: MethodDef, namespace: &'static str) -> Self {
let signature = def.signature(namespace, &[]);

let dependencies = signature.dependencies();
let mut param_hints = vec![ParamHint::None; signature.params.len()];

for (position, param) in signature.params.iter().enumerate() {
param_hints[position] = param.into();
}

let mut dependencies = TypeMap::new();
signature.dependencies(&mut dependencies);

for position in 0..signature.params.len() {
// Point len params back to the corresponding ptr params.
match param_hints[position] {
36 changes: 18 additions & 18 deletions crates/libs/bindgen/src/types/cpp_struct.rs
Original file line number Diff line number Diff line change
@@ -51,9 +51,7 @@ impl CppStruct {
return quote! {};
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
Cfg::new(self.def, &dependencies).write(writer, false)
Cfg::new(self.def, &self.dependencies()).write(writer, false)
}

pub fn write(&self, writer: &Writer) -> TokenStream {
@@ -226,21 +224,6 @@ impl CppStruct {
tokens
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
for field in self.def.fields() {
field.ty(Some(self)).dependencies(dependencies);
}

if let Some(attribute) = self.def.find_attribute("AlsoUsableForAttribute") {
if let Some((_, Value::Str(type_name))) = attribute.args().first() {
self.def
.reader()
.unwrap_full_name(self.def.namespace(), type_name)
.dependencies(dependencies);
}
}
}

pub fn is_copyable(&self) -> bool {
if matches!(
self.def.type_name(),
@@ -298,3 +281,20 @@ impl CppStruct {
.unwrap_or(1)
}
}

impl Dependencies for CppStruct {
fn combine(&self, dependencies: &mut TypeMap) {
for field in self.def.fields() {
field.ty(Some(self)).combine(dependencies);
}

if let Some(attribute) = self.def.find_attribute("AlsoUsableForAttribute") {
if let Some((_, Value::Str(type_name))) = attribute.args().first() {
self.def
.reader()
.unwrap_full_name(self.def.namespace(), type_name)
.combine(dependencies);
}
}
}
}
18 changes: 9 additions & 9 deletions crates/libs/bindgen/src/types/delegate.rs
Original file line number Diff line number Diff line change
@@ -16,9 +16,7 @@ impl Delegate {
return quote! {};
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
Cfg::new(self.def, &dependencies).write(writer, false)
Cfg::new(self.def, &self.dependencies()).write(writer, false)
}

pub fn write(&self, writer: &Writer) -> TokenStream {
@@ -201,15 +199,17 @@ impl Delegate {
}
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
pub fn write_name(&self, writer: &Writer) -> TokenStream {
self.type_name().write(writer, &self.generics)
}
}

impl Dependencies for Delegate {
fn combine(&self, dependencies: &mut TypeMap) {
dependencies.combine(&self.method().dependencies);

for ty in &self.generics {
ty.dependencies(dependencies);
ty.combine(dependencies);
}
}

pub fn write_name(&self, writer: &Writer) -> TokenStream {
self.type_name().write(writer, &self.generics)
}
}
68 changes: 34 additions & 34 deletions crates/libs/bindgen/src/types/interface.rs
Original file line number Diff line number Diff line change
@@ -72,9 +72,7 @@ impl Interface {
return (Cfg::default(), quote! {});
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
let cfg = Cfg::new(self.def, &dependencies);
let cfg = Cfg::new(self.def, &self.dependencies());
let tokens = cfg.write(writer, false);
(cfg, tokens)
}
@@ -339,20 +337,20 @@ impl Interface {
let runtime_name = format!("{type_name}");

let cfg = if writer.config.package {
fn collect(interface: &Interface, dependencies: &mut TypeMap, writer: &Writer) {
fn combine(interface: &Interface, dependencies: &mut TypeMap, writer: &Writer) {
for method in interface.get_methods(writer).iter() {
if let MethodOrName::Method(method) = method {
dependencies.combine(&method.dependencies);
}
}
}

let mut dependencies = TypeMap::new();
self.dependencies(&mut dependencies);
collect(self, &mut dependencies, writer);
let mut dependencies = self.dependencies();
combine(self, &mut dependencies, writer);

required_interfaces
.iter()
.for_each(|interface| collect(interface, &mut dependencies, writer));
.for_each(|interface| combine(interface, &mut dependencies, writer));

Cfg::new(self.def, &dependencies).write(writer, false)
} else {
@@ -534,32 +532,6 @@ impl Interface {
interface_signature(self.def, &self.generics)
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
Type::Object.dependencies(dependencies);

for interface in self.required_interfaces() {
Type::Interface(interface).dependencies(dependencies);
}

// Different specializations of Interface may have different generics...
for ty in &self.generics {
ty.dependencies(dependencies);
}

let is_iterable = self.type_name() == TypeName::IIterable;

for method in self.def.methods() {
for ty in method
.signature(self.def.namespace(), &self.generics)
.types()
{
if is_iterable || ty.is_core() {
ty.dependencies(dependencies);
}
}
}
}

pub fn required_interfaces(&self) -> Vec<Self> {
fn walk(interface: &Interface, set: &mut Vec<Interface>) {
for ty in interface
@@ -582,3 +554,31 @@ impl Interface {
set
}
}

impl Dependencies for Interface {
fn combine(&self, dependencies: &mut TypeMap) {
Type::Object.combine(dependencies);

for interface in self.required_interfaces() {
Type::Interface(interface).combine(dependencies);
}

// Different specializations of Interface may have different generics...
for ty in &self.generics {
ty.combine(dependencies);
}

let is_iterable = self.type_name() == TypeName::IIterable;

for method in self.def.methods() {
for ty in method
.signature(self.def.namespace(), &self.generics)
.types()
{
if is_iterable || ty.is_core() {
ty.combine(dependencies);
}
}
}
}
}
4 changes: 1 addition & 3 deletions crates/libs/bindgen/src/types/method.rs
Original file line number Diff line number Diff line change
@@ -11,9 +11,7 @@ pub struct Method {
impl Method {
pub fn new(def: MethodDef, generics: &[Type]) -> Self {
let signature = def.signature("", generics);

let mut dependencies = TypeMap::new();
signature.dependencies(&mut dependencies);
let dependencies = signature.dependencies();

Self {
def,
145 changes: 73 additions & 72 deletions crates/libs/bindgen/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -610,78 +610,6 @@ impl Type {
}
}

#[track_caller]
pub fn dependencies(&self, dependencies: &mut TypeMap) {
let ty = self.decay();

if ty.is_intrinsic() {
return;
}

let mut nested = false;

if let Self::CppStruct(ty) = ty {
if ty.def.namespace().is_empty() {
nested = true;
}
}

let (ty, generics) = ty.split_generic();

for ty in generics {
ty.dependencies(dependencies);
}

if !nested && !dependencies.insert(ty.clone()) {
return;
}

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()),
),
_ => None,
} {
multi.for_each(|multi| {
if ty != multi {
multi.dependencies(dependencies)
}
});
}

match &ty {
Self::Class(ty) => ty.dependencies(dependencies),
Self::Delegate(ty) => ty.dependencies(dependencies),
Self::Enum(..) => {}
Self::Interface(ty) => ty.dependencies(dependencies),
Self::Struct(ty) => ty.dependencies(dependencies),
Self::CppConst(ty) => ty.dependencies(dependencies),
Self::CppDelegate(ty) => ty.dependencies(dependencies),
Self::CppFn(ty) => ty.dependencies(dependencies),
Self::CppInterface(ty) => ty.dependencies(dependencies),
Self::CppStruct(ty) => ty.dependencies(dependencies),
Self::CppEnum(ty) => ty.dependencies(dependencies),

Self::IUnknown => {
Self::GUID.dependencies(dependencies);
Self::HRESULT.dependencies(dependencies);
}

Self::Object => {
Self::IUnknown.dependencies(dependencies);
}

_ => {}
}
}

pub fn is_exclusive(&self) -> bool {
match self {
Self::Interface(ty) => ty.def.has_attribute("ExclusiveToAttribute"),
@@ -1001,6 +929,79 @@ impl Type {
}
}

impl Dependencies for Type {
fn combine(&self, dependencies: &mut TypeMap) {
let ty = self.decay();

if ty.is_intrinsic() {
return;
}

let mut nested = false;

if let Self::CppStruct(ty) = ty {
if ty.def.namespace().is_empty() {
nested = true;
}
}

let (ty, generics) = ty.split_generic();

for ty in generics {
ty.combine(dependencies);
}

if !nested && !dependencies.insert(ty.clone()) {
return;
}

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()),
),
_ => None,
} {
multi.for_each(|multi| {
if ty != multi {
multi.combine(dependencies)
}
});
}

match &ty {
Self::Class(ty) => ty.combine(dependencies),
Self::Delegate(ty) => ty.combine(dependencies),
Self::Enum(..) => {}
Self::Interface(ty) => ty.combine(dependencies),
Self::Struct(ty) => ty.combine(dependencies),
Self::CppConst(ty) => ty.combine(dependencies),
Self::CppDelegate(ty) => ty.combine(dependencies),
Self::CppFn(ty) => ty.combine(dependencies),
Self::CppInterface(ty) => ty.combine(dependencies),
Self::CppStruct(ty) => ty.combine(dependencies),
Self::CppEnum(ty) => ty.combine(dependencies),

Self::IUnknown => {
Self::GUID.combine(dependencies);
Self::HRESULT.combine(dependencies);
}

Self::Object => {
Self::IUnknown.combine(dependencies);
}

_ => {}
}
}
}

pub fn interface_signature(def: TypeDef, generics: &[Type]) -> String {
if generics.is_empty() {
let guid = def.guid_attribute().unwrap();
14 changes: 8 additions & 6 deletions crates/libs/bindgen/src/types/struct.rs
Original file line number Diff line number Diff line change
@@ -83,12 +83,6 @@ impl Struct {
signature
}

pub fn dependencies(&self, dependencies: &mut TypeMap) {
for field in self.def.fields() {
field.ty(None).dependencies(dependencies);
}
}

pub fn is_copyable(&self) -> bool {
self.def.fields().all(|field| field.ty(None).is_copyable())
}
@@ -113,3 +107,11 @@ impl Struct {
.unwrap_or(1)
}
}

impl Dependencies for Struct {
fn combine(&self, dependencies: &mut TypeMap) {
for field in self.def.fields() {
field.ty(None).combine(dependencies);
}
}
}

0 comments on commit af731c4

Please sign in to comment.