Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
45 changes: 38 additions & 7 deletions analysis/src/decl.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
use proc_macro2::{Literal, TokenStream};

use crate::{
item::RequireMap,
item::{RequireMap, structure::Length},
name::{ConstantName, FuncPointerName, TypeName, VariableName},
xml::cdecl::{CArrayLen, CDecl, CType},
to_rust::RustTranslator,
xml::{
cdecl::{CArrayLen, CDecl, CType},
cexpr::{self, CExprItem, CExprItems},
},
};

#[derive(Debug)]
Expand All @@ -11,15 +17,18 @@ pub struct Decl {
}

impl Decl {
pub(crate) fn from_c(require_map: &RequireMap, c_decl: &CDecl<'static>) -> Decl {
pub(crate) fn from_c(
require_map: &RequireMap,
c_decl: &CDecl<'static>,
) -> Decl {
Decl {
name: VariableName::new(c_decl.name),
ty: Ty::from_c(require_map, &c_decl.ty),
}
}
}

#[derive(Debug)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mutability {
Not,
Mut,
Expand Down Expand Up @@ -65,25 +74,47 @@ impl CPrimaryType {
}
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum ArrayLen {
Constant(ConstantName),
Literal(u128),
}

#[derive(Debug)]
impl ArrayLen {
pub fn to_rust(&self, translator: &impl RustTranslator) -> TokenStream {
match self {
ArrayLen::Constant(constant_name) => translator.constant_to_rust(*constant_name, true),
ArrayLen::Literal(value) => {
let literal = Literal::u128_unsuffixed(*value);
quote::quote! { #literal }
}
}
}
}

#[derive(Debug, Clone)]
pub enum Ty {
SpecType(TypeName),
SpecFuncPointer(FuncPointerName),
CPrimary(CPrimaryType),
RustType(RustType),
Platform(&'static str),
Ptr(&'static Ty, Mutability),
Ref(&'static Ty, Mutability),
Slice(&'static Ty, Mutability, Option<ArrayLen>),
Array(&'static Ty, ArrayLen),
}

#[derive(Debug, Clone, Copy)]
pub enum RustType {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this abstraction is getting pretty leaky and ugly, but I'm not sure what else to do here :/

Originally I wanted the analysis crate to theoretically be used to generate Vulkan bindings for any programming language (except for the to_rust module obv.).

CStr,
}

impl Ty {
pub(crate) fn from_c(require_map: &RequireMap, c_type: &CType<'static>) -> Ty {
pub(crate) fn from_c(
require_map: &RequireMap,
c_type: &CType<'static>,
) -> Ty {
match c_type {
CType::Base(cbase_type) => {
let name = cbase_type.name;
Expand Down
6 changes: 4 additions & 2 deletions analysis/src/item/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ impl FuncPointer {
params: (xml.params.iter())
.map(|c_decl| Decl::from_c(require_map, c_decl))
.collect(),
return_type: (xml.return_type.as_ref()).map(|c_type| Ty::from_c(require_map, c_type)),
return_type: (xml.return_type.as_ref())
.map(|c_type| Ty::from_c(require_map, c_type)),
})
}
}
Expand Down Expand Up @@ -70,7 +71,8 @@ impl Command {
decl: Decl::from_c(require_map, &param.c_decl),
})
.collect(),
return_type: (xml.return_type.as_ref()).map(|c_type| Ty::from_c(require_map, c_type)),
return_type: (xml.return_type.as_ref())
.map(|c_type| Ty::from_c(require_map, c_type)),
})
}
}
58 changes: 55 additions & 3 deletions analysis/src/item/structure.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
decl::{Decl, Ty},
item::{Named, RequireMap, RequiredBy},
name::TypeName,
name::{EnumeratorName, TypeName, VariableName},
xml,
};
use std::{cmp::Ordering, ops::Range};
Expand All @@ -15,17 +15,33 @@ pub struct BitfieldRange {

#[derive(Debug)]
pub enum StructMember {
Normal(Decl),
Normal(StructDecl),
BitField(Vec<BitfieldRange>),
}

#[derive(Debug)]
pub struct Struct {
pub required_by: RequiredBy,
pub name: TypeName,
pub extends: Vec<TypeName>,
pub structure_type: Option<EnumeratorName>,
pub members: Vec<StructMember>,
}

#[derive(Debug)]
pub struct StructDecl {
pub decl: Decl,
pub len: Vec<Length>,
}

#[derive(Debug, PartialEq, Eq)]
pub enum Length {
Member(VariableName),
NullTerminated,
Pointer,
Custom(&'static str),
}

impl Named<TypeName> for Struct {
fn name(&self) -> TypeName {
self.name
Expand All @@ -40,7 +56,33 @@ impl Struct {

let mut members = Vec::new();
let mut used_bitwidth = None;

let extends = xml
.structextends
.iter()
.map(|&extending| TypeName::new(extending))
.collect();

let mut structure_type = None;

for member in &xml.members {
let lens = if member.len.iter().any(|&s| s.starts_with("latexmath:")) {
&member.altlen
} else {
&member.len
};

let len = lens
.iter()
.map(|&s| match s {
"null-terminated" => Length::NullTerminated,
"1" => Length::Pointer,
name if xml.members.iter().any(|mem| mem.c_decl.name == name) => {
Length::Member(VariableName::new(name))
}
custom => Length::Custom(custom),
})
.collect::<Vec<_>>();
let decl = Decl::from_c(require_map, &member.c_decl);
if let Some(width) = member.c_decl.bitfield_width {
// this is currently the case everywhere,
Expand Down Expand Up @@ -72,13 +114,23 @@ impl Struct {
}
} else {
assert_eq!(used_bitwidth, None, "bitfield not fully used");
members.push(StructMember::Normal(decl));
// should exist only once
if let Some(value) = member.values
&& let Ty::SpecType(ty) = decl.ty
&& ty == TypeName::VK_STRUCTURE_TYPE
&& decl.name.original() == "sType"
{
structure_type = Some(EnumeratorName::new(value));
}
members.push(StructMember::Normal(StructDecl { decl, len }));
}
}

Some(Struct {
required_by,
name: xml.name,
extends,
structure_type,
members,
})
}
Expand Down
9 changes: 6 additions & 3 deletions analysis/src/lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use syn::Ident;

use crate::{
decl::{Decl, Ty},
item::{TypeItem, structure::StructMember},
item::{
TypeItem,
structure::{StructDecl, StructMember},
},
name::TypeName,
};

Expand Down Expand Up @@ -53,10 +56,10 @@ fn determine_for_type(
TypeItem::Struct(item) => item.members.iter().any(|member| {
matches!(
member,
StructMember::Normal(Decl {
StructMember::Normal(StructDecl { decl: Decl{
ty,
..
})if determine_for_type(store, types, ty, true)
}, ..})if determine_for_type(store, types, ty, true)
)
}),
TypeItem::Union(item) => item.members.iter().any(|member| {
Expand Down
2 changes: 2 additions & 0 deletions analysis/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ impl TypeName {
pub const VK_QUEUE: Self = Self::new("VkQueue");
pub const VK_INSTANCE: Self = Self::new("VkInstance");
pub const VK_PHYSICAL_DEVICE: Self = Self::new("VkPhysicalDevice");
pub const VK_STRUCTURE_TYPE: Self = Self::new("VkStructureType");
pub const VK_BOOL32: Self = Self::new("VkBool32");

pub const fn new(original: &'static str) -> Self {
Self(original)
Expand Down
33 changes: 22 additions & 11 deletions analysis/src/to_rust.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::{
decl::{ArrayLen, CPrimaryType, Decl, Mutability, Ty},
decl::{CPrimaryType, Decl, Mutability, RustType, Ty},
lifetime::Lifetime,
name::{
CMacroName, CommandName, ConstantName, EnumeratorName, FuncPointerName, TypeName,
VariableName,
},
xml::cexpr::CExprItem,
};
use proc_macro2::{Literal, TokenStream};
use proc_macro2::{TokenStream};
use quote::quote;
use std::{borrow::Borrow, mem};
use syn::Ident;
Expand All @@ -32,7 +32,9 @@ pub trait RustTranslator {

fn cmacro_to_rust(&self, name: CMacroName, qualified: bool) -> TokenStream;

fn platform_type_to_rust(&self, raw: &'static str, qualified: bool) -> TokenStream;
fn platform_type_to_rust(&self, raw: &str, qualified: bool) -> TokenStream;

fn rust_type_to_rust(&self, ty: &RustType) -> TokenStream;

fn primary_type_to_rust(&self, primary_ty: CPrimaryType) -> TokenStream {
match primary_ty {
Expand Down Expand Up @@ -88,18 +90,27 @@ impl Ty {
let ty = ty.to_rust(translator, lifetime);
quote! { & #lifetime #mutability #ty }
}
Ty::Slice(ty, mutability, len) => {
let mutability = match mutability {
Mutability::Not => quote! {},
Mutability::Mut => quote! { mut },
};
let len = len.as_ref().map(|len| {
let len = len.to_rust(translator);
quote! { ; #len}
});
let ty = ty.to_rust(translator, lifetime);
quote! { & #lifetime #mutability [#ty #len] }
}
Ty::Array(ty, array_len) => {
let ty = ty.to_rust(translator, lifetime);
let array_len = match array_len {
ArrayLen::Constant(constant) => translator.constant_to_rust(*constant, true),
ArrayLen::Literal(value) => {
let literal = Literal::u128_unsuffixed(*value);
quote! { #literal }
}
};

let array_len = array_len.to_rust(translator);
quote! { [#ty; #array_len as _] }
}
Ty::RustType(ty) => {
let ty = translator.rust_type_to_rust(ty);
quote! { #ty }
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions analysis/src/xml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ pub struct StructureMember {
pub c_decl: CDecl<'static>,
pub values: Option<&'static str>,
pub len: Vec<&'static str>,
pub altlen: Option<&'static str>,
pub altlen: Vec<&'static str>,
pub optional: Vec<&'static str>,
}

Expand All @@ -479,7 +479,7 @@ impl StructureMember {
c_decl: CDecl::from_xml(CDeclMode::StructMember, node.children()),
values: attribute(node, "values"),
len: attribute_comma_separated(node, "len"),
altlen: attribute(node, "altlen"),
altlen: attribute_comma_separated(node, "altlen"),
optional: attribute_comma_separated(node, "optional"),
}
}
Expand Down
Loading
Loading