diff options
-rw-r--r-- | example-graphviz-ir.png | bin | 842576 -> 1343520 bytes | |||
-rw-r--r-- | src/clang.rs | 6 | ||||
-rw-r--r-- | src/codegen/mod.rs | 3 | ||||
-rw-r--r-- | src/codegen/struct_layout.rs | 6 | ||||
-rw-r--r-- | src/ir/context.rs | 31 | ||||
-rw-r--r-- | src/ir/dot.rs | 53 | ||||
-rw-r--r-- | src/ir/function.rs | 14 | ||||
-rw-r--r-- | src/ir/item.rs | 29 | ||||
-rw-r--r-- | src/ir/item_kind.rs | 20 | ||||
-rw-r--r-- | src/ir/mod.rs | 1 | ||||
-rw-r--r-- | src/ir/module.rs | 12 | ||||
-rw-r--r-- | src/ir/ty.rs | 57 | ||||
-rw-r--r-- | src/ir/var.rs | 18 | ||||
-rw-r--r-- | tests/expectations/tests/layout_large_align_field.rs | 419 | ||||
-rw-r--r-- | tests/headers/layout_large_align_field.h | 97 |
15 files changed, 717 insertions, 49 deletions
diff --git a/example-graphviz-ir.png b/example-graphviz-ir.png Binary files differindex c990f7e7..1e554a83 100644 --- a/example-graphviz-ir.png +++ b/example-graphviz-ir.png diff --git a/src/clang.rs b/src/clang.rs index 613e08e8..a3919579 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -875,7 +875,11 @@ impl Type { pub fn named(&self) -> Type { unsafe { Type { - x: clang_Type_getNamedType(self.x), + x: if clang_Type_getNamedType::is_loaded() { + clang_Type_getNamedType(self.x) + } else { + self.x + }, } } } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 77f654e6..aab59946 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -10,6 +10,7 @@ use ir::annotations::FieldAccessorKind; use ir::comp::{Base, CompInfo, CompKind, Field, Method, MethodKind}; use ir::context::{BindgenContext, ItemId}; use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; +use ir::dot; use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; use ir::function::{Function, FunctionSig}; use ir::int::IntKind; @@ -2502,7 +2503,7 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> { } if let Some(path) = context.options().emit_ir_graphviz.as_ref() { - match context.emit_ir_graphviz(path.clone()) { + match dot::write_dot_file(context, path) { Ok(()) => info!("Your dot file was generated successfully into: {}", path), Err(e) => error!("{}", e), } diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs index 24938c16..724bef98 100644 --- a/src/codegen/struct_layout.rs +++ b/src/codegen/struct_layout.rs @@ -197,7 +197,7 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> { }; // Otherwise the padding is useless. - let need_padding = padding_bytes >= field_layout.align; + let need_padding = padding_bytes >= field_layout.align || field_layout.align > mem::size_of::<*mut ()>(); self.latest_offset += padding_bytes; @@ -213,7 +213,7 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> { field_layout); if need_padding && padding_bytes != 0 { - Some(Layout::new(padding_bytes, field_layout.align)) + Some(Layout::new(padding_bytes, cmp::min(field_layout.align, mem::size_of::<*mut ()>()))) } else { None } @@ -262,6 +262,8 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> { Layout::new(padding_bytes, layout.align) }; + debug!("pad bytes to struct {}, {:?}", name, layout); + Some(self.padding_field(layout)) } else { None diff --git a/src/ir/context.rs b/src/ir/context.rs index 7383c09a..d2fb2bef 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -5,7 +5,7 @@ use super::int::IntKind; use super::item::{Item, ItemCanonicalPath, ItemSet}; use super::item_kind::ItemKind; use super::module::{Module, ModuleKind}; -use super::traversal::{self, Edge, ItemTraversal, Trace}; +use super::traversal::{self, Edge, ItemTraversal}; use super::ty::{FloatKind, TemplateDeclaration, Type, TypeKind}; use BindgenOptions; use cexpr; @@ -18,8 +18,6 @@ use std::cell::Cell; use std::collections::{HashMap, hash_map}; use std::collections::btree_map::{self, BTreeMap}; use std::fmt; -use std::fs::File; -use std::io::{self, Write}; use std::iter::IntoIterator; use syntax::ast::Ident; use syntax::codemap::{DUMMY_SP, Span}; @@ -1111,33 +1109,6 @@ impl<'ctx> BindgenContext<'ctx> { &self.options } - /// Output graphviz dot file. - pub fn emit_ir_graphviz(&self, path: String) -> io::Result<()> { - let file = try!(File::create(path)); - let mut dot_file = io::BufWriter::new(file); - writeln!(&mut dot_file, "digraph {{")?; - - let mut err: Option<io::Result<_>> = None; - - for (id, item) in self.items() { - writeln!(&mut dot_file, "{} {};", id.0, item.dot_attributes(self))?; - - item.trace(self, &mut |sub_id: ItemId, _edge_kind| { - match writeln!(&mut dot_file, "{} -> {};", id.0, sub_id.as_usize()) { - Ok(_) => {}, - Err(e) => err = Some(Err(e)), - } - }, &()); - - if err.is_some() { - return err.unwrap(); - } - } - - writeln!(&mut dot_file, "}}")?; - Ok(()) - } - /// Tokenizes a namespace cursor in order to get the name and kind of the /// namespace, fn tokenize_namespace(&self, diff --git a/src/ir/dot.rs b/src/ir/dot.rs new file mode 100644 index 00000000..b7a117bb --- /dev/null +++ b/src/ir/dot.rs @@ -0,0 +1,53 @@ +//! Generating Graphviz `dot` files from our IR. + +use std::fs::File; +use std::io::{self, Write}; +use std::path::Path; +use super::context::{BindgenContext, ItemId}; +use super::traversal::Trace; + +/// A trait for anything that can write attributes as `<table>` rows to a dot +/// file. +pub trait DotAttributes { + /// Write this thing's attributes to the given output. Each attribute must + /// be its own `<tr>...</tr>`. + fn dot_attributes<W>(&self, ctx: &BindgenContext, out: &mut W) -> io::Result<()> + where W: io::Write; +} + +/// Write a graphviz dot file containing our IR. +pub fn write_dot_file<P>(ctx: &BindgenContext, path: P) -> io::Result<()> + where P: AsRef<Path> +{ + let file = try!(File::create(path)); + let mut dot_file = io::BufWriter::new(file); + try!(writeln!(&mut dot_file, "digraph {{")); + + let mut err: Option<io::Result<_>> = None; + + for (id, item) in ctx.items() { + try!(writeln!(&mut dot_file, + r#"{} [fontname="courier", label=< <table border="0">"#, + id.as_usize())); + try!(item.dot_attributes(ctx, &mut dot_file)); + try!(writeln!(&mut dot_file, r#"</table> >];"#)); + + item.trace(ctx, &mut |sub_id: ItemId, _edge_kind| { + if err.is_some() { + return; + } + + match writeln!(&mut dot_file, "{} -> {};", id.as_usize(), sub_id.as_usize()) { + Ok(_) => {}, + Err(e) => err = Some(Err(e)), + } + }, &()); + + if let Some(err) = err { + return err; + } + } + + try!(writeln!(&mut dot_file, "}}")); + Ok(()) +} diff --git a/src/ir/function.rs b/src/ir/function.rs index 22b9c9b0..daa30b89 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -1,12 +1,14 @@ //! Intermediate representation for C/C++ functions and methods. use super::context::{BindgenContext, ItemId}; +use super::dot::DotAttributes; use super::item::Item; use super::traversal::{Trace, Tracer}; use super::ty::TypeKind; use clang; use clang_sys::CXCallingConv; use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; +use std::io; use syntax::abi; /// A function declaration, with a signature, arguments, and argument names. @@ -59,6 +61,18 @@ impl Function { } } +impl DotAttributes for Function { + fn dot_attributes<W>(&self, _ctx: &BindgenContext, out: &mut W) -> io::Result<()> + where W: io::Write + { + if let Some(ref mangled) = self.mangled_name { + try!(writeln!(out, "<tr><td>mangled name</td><td>{}</td></tr>", mangled)); + } + + Ok(()) + } +} + /// A function signature. #[derive(Debug)] pub struct FunctionSig { diff --git a/src/ir/item.rs b/src/ir/item.rs index 8f16a96f..bd401aba 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -3,6 +3,7 @@ use super::annotations::Annotations; use super::context::{BindgenContext, ItemId, PartialType}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; +use super::dot::{DotAttributes}; use super::function::Function; use super::item_kind::ItemKind; use super::module::Module; @@ -15,6 +16,7 @@ use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; use std::fmt::Write; use std::iter; +use std::io; /// A trait to get the canonical name from an item. /// @@ -372,20 +374,6 @@ impl Item { self.id } - /// Get this `Item`'s dot attributes. - pub fn dot_attributes(&self, ctx: &BindgenContext) -> String { - format!("[fontname=\"courier\", label=< \ - <table border=\"0\"> \ - <tr><td>ItemId({})</td></tr> \ - <tr><td>name</td><td>{}</td></tr> \ - <tr><td>kind</td><td>{}</td></tr> \ - </table> \ - >]", - self.id.as_usize(), - self.name(ctx).get(), - self.kind.kind_name()) - } - /// Get this `Item`'s parent's identifier. /// /// For the root module, the parent's ID is its own ID. @@ -928,6 +916,19 @@ impl Item { /// A set of items. pub type ItemSet = BTreeSet<ItemId>; +impl DotAttributes for Item { + fn dot_attributes<W>(&self, ctx: &BindgenContext, out: &mut W) -> io::Result<()> + where W: io::Write + { + try!(writeln!(out, + "<tr><td>{:?}</td></tr> + <tr><td>name</td><td>{}</td></tr>", + self.id, + self.name(ctx).get())); + self.kind.dot_attributes(ctx, out) + } +} + impl TemplateDeclaration for ItemId { fn template_params(&self, ctx: &BindgenContext) -> Option<Vec<ItemId>> { ctx.resolve_item_fallible(*self) diff --git a/src/ir/item_kind.rs b/src/ir/item_kind.rs index 3ff06731..6dfd6764 100644 --- a/src/ir/item_kind.rs +++ b/src/ir/item_kind.rs @@ -1,5 +1,8 @@ //! Different variants of an `Item` in our intermediate representation. +use std::io; +use super::context::BindgenContext; +use super::dot::DotAttributes; use super::function::Function; use super::module::Module; use super::ty::Type; @@ -39,7 +42,7 @@ impl ItemKind { ItemKind::Type(..) => "Type", ItemKind::Function(..) => "Function", ItemKind::Var(..) => "Var" - } + } } /// Is this a module? @@ -122,3 +125,18 @@ impl ItemKind { self.as_var().expect("Not a var") } } + +impl DotAttributes for ItemKind { + fn dot_attributes<W>(&self, ctx: &BindgenContext, out: &mut W) -> io::Result<()> + where W: io::Write + { + try!(writeln!(out, "<tr><td>kind</td><td>{}</td></tr>", self.kind_name())); + + match *self { + ItemKind::Module(ref module) => module.dot_attributes(ctx, out), + ItemKind::Type(ref ty) => ty.dot_attributes(ctx, out), + ItemKind::Function(ref func) => func.dot_attributes(ctx, out), + ItemKind::Var(ref var) => var.dot_attributes(ctx, out), + } + } +} diff --git a/src/ir/mod.rs b/src/ir/mod.rs index e624e46b..ba549c51 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -7,6 +7,7 @@ pub mod annotations; pub mod comp; pub mod context; pub mod derive; +pub mod dot; pub mod enum_ty; pub mod function; pub mod int; diff --git a/src/ir/module.rs b/src/ir/module.rs index 6b6c535b..6787e3f9 100644 --- a/src/ir/module.rs +++ b/src/ir/module.rs @@ -1,6 +1,8 @@ //! Intermediate representation for modules (AKA C++ namespaces). +use std::io; use super::context::{BindgenContext, ItemId}; +use super::dot::DotAttributes; use clang; use parse::{ClangSubItemParser, ParseError, ParseResult}; use parse_one; @@ -56,6 +58,16 @@ impl Module { } } +impl DotAttributes for Module { + fn dot_attributes<W>(&self, _ctx: &BindgenContext, out: &mut W) -> io::Result<()> + where W: io::Write + { + writeln!(out, + "<tr><td>ModuleKind</td><td>{:?}</td></tr>", + self.kind) + } +} + impl ClangSubItemParser for Module { fn parse(cursor: clang::Cursor, ctx: &mut BindgenContext) diff --git a/src/ir/ty.rs b/src/ir/ty.rs index c3ec4039..44a88744 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -3,6 +3,7 @@ use super::comp::CompInfo; use super::context::{BindgenContext, ItemId}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; +use super::dot::DotAttributes; use super::enum_ty::Enum; use super::function::FunctionSig; use super::int::IntKind; @@ -12,6 +13,7 @@ use super::objc::ObjCInterface; use super::traversal::{Trace, Tracer}; use clang::{self, Cursor}; use parse::{ClangItemParser, ParseError, ParseResult}; +use std::io; use std::mem; /// Template declaration related methods. @@ -384,6 +386,61 @@ impl Type { } } +impl DotAttributes for Type { + fn dot_attributes<W>(&self, ctx: &BindgenContext, out: &mut W) -> io::Result<()> + where W: io::Write + { + if let Some(ref layout) = self.layout { + try!(writeln!(out, + "<tr><td>size</td><td>{}</td></tr> + <tr><td>align</td><td>{}</td></tr>", + layout.size, + layout.align)); + if layout.packed { + try!(writeln!(out, "<tr><td>packed</td><td>true</td></tr>")); + } + } + + if self.is_const { + try!(writeln!(out, "<tr><td>const</td><td>true</td></tr>")); + } + + self.kind.dot_attributes(ctx, out) + } +} + +impl DotAttributes for TypeKind { + fn dot_attributes<W>(&self, _ctx: &BindgenContext, out: &mut W) -> io::Result<()> + where W: io::Write + { + write!(out, + "<tr><td>TypeKind</td><td>{}</td></tr>", + match *self { + TypeKind::Void => "Void", + TypeKind::NullPtr => "NullPtr", + TypeKind::Comp(..) => "Comp", + TypeKind::Int(..) => "Int", + TypeKind::Float(..) => "Float", + TypeKind::Complex(..) => "Complex", + TypeKind::Alias(..) => "Alias", + TypeKind::TemplateAlias(..) => "TemplateAlias", + TypeKind::Array(..) => "Array", + TypeKind::Function(..) => "Function", + TypeKind::Enum(..) => "Enum", + TypeKind::Pointer(..) => "Pointer", + TypeKind::BlockPointer => "BlockPointer", + TypeKind::Reference(..) => "Reference", + TypeKind::TemplateInstantiation(..) => "TemplateInstantiation", + TypeKind::ResolvedTypeRef(..) => "ResolvedTypeRef", + TypeKind::Named => "Named", + TypeKind::ObjCInterface(..) => "ObjCInterface", + TypeKind::UnresolvedTypeRef(..) => { + unreachable!("there shouldn't be any more of these anymore") + } + }) + } +} + #[test] fn is_invalid_named_type_valid() { let ty = Type::new(Some("foo".into()), None, TypeKind::Named, false); diff --git a/src/ir/var.rs b/src/ir/var.rs index 6cfcdae7..c6d7a1c5 100644 --- a/src/ir/var.rs +++ b/src/ir/var.rs @@ -1,6 +1,7 @@ //! Intermediate representation of variables. use super::context::{BindgenContext, ItemId}; +use super::dot::DotAttributes; use super::function::cursor_mangling; use super::int::IntKind; use super::item::Item; @@ -8,6 +9,7 @@ use super::ty::{FloatKind, TypeKind}; use cexpr; use clang; use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; +use std::io; use std::num::Wrapping; /// The type for a constant variable. @@ -84,6 +86,22 @@ impl Var { } } +impl DotAttributes for Var { + fn dot_attributes<W>(&self, _ctx: &BindgenContext, out: &mut W) -> io::Result<()> + where W: io::Write + { + if self.is_const { + try!(writeln!(out, "<tr><td>const</td><td>true</td></tr>")); + } + + if let Some(ref mangled) = self.mangled_name { + try!(writeln!(out, "<tr><td>mangled name</td><td>{}</td></tr>", mangled)); + } + + Ok(()) + } +} + impl ClangSubItemParser for Var { fn parse(cursor: clang::Cursor, ctx: &mut BindgenContext) diff --git a/tests/expectations/tests/layout_large_align_field.rs b/tests/expectations/tests/layout_large_align_field.rs new file mode 100644 index 00000000..820e4210 --- /dev/null +++ b/tests/expectations/tests/layout_large_align_field.rs @@ -0,0 +1,419 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>); +impl <T> __IncompleteArrayField<T> { + #[inline] + pub fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ptr(&self) -> *const T { ::std::mem::transmute(self) } + #[inline] + pub unsafe fn as_mut_ptr(&mut self) -> *mut T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl <T> ::std::fmt::Debug for __IncompleteArrayField<T> { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +impl <T> ::std::clone::Clone for __IncompleteArrayField<T> { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl <T> ::std::marker::Copy for __IncompleteArrayField<T> { } +pub const RTE_CACHE_LINE_SIZE: ::std::os::raw::c_uint = 64; +pub const RTE_LIBRTE_IP_FRAG_MAX_FRAG: ::std::os::raw::c_uint = 4; +pub const IP_LAST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_LAST_FRAG_IDX; +pub const IP_FIRST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_FIRST_FRAG_IDX; +pub const IP_MIN_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MIN_FRAG_NUM; +pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum _bindgen_ty_1 { + IP_LAST_FRAG_IDX = 0, + IP_FIRST_FRAG_IDX = 1, + IP_MIN_FRAG_NUM = 2, + IP_MAX_FRAG_NUM = 4, +} +/** @internal fragmented mbuf */ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct ip_frag { + /**< offset into the packet */ + pub ofs: u16, + /**< length of fragment */ + pub len: u16, + /**< fragment mbuf */ + pub mb: *mut rte_mbuf, +} +#[test] +fn bindgen_test_layout_ip_frag() { + assert_eq!(::std::mem::size_of::<ip_frag>() , 16usize , concat ! ( + "Size of: " , stringify ! ( ip_frag ) )); + assert_eq! (::std::mem::align_of::<ip_frag>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( ip_frag ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag ) ) . ofs as * const _ as usize } + , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag ) , "::" , + stringify ! ( ofs ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag ) ) . len as * const _ as usize } + , 2usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag ) , "::" , + stringify ! ( len ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag ) ) . mb as * const _ as usize } + , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag ) , "::" , + stringify ! ( mb ) )); +} +impl Clone for ip_frag { + fn clone(&self) -> Self { *self } +} +impl Default for ip_frag { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +/** @internal <src addr, dst_addr, id> to uniquely indetify fragmented datagram. */ +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct ip_frag_key { + /**< src address, first 8 bytes used for IPv4 */ + pub src_dst: [u64; 4usize], + /**< dst address */ + pub id: u32, + /**< src/dst key length */ + pub key_len: u32, +} +#[test] +fn bindgen_test_layout_ip_frag_key() { + assert_eq!(::std::mem::size_of::<ip_frag_key>() , 40usize , concat ! ( + "Size of: " , stringify ! ( ip_frag_key ) )); + assert_eq! (::std::mem::align_of::<ip_frag_key>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( ip_frag_key ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_key ) ) . src_dst as * const _ as + usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_key ) , "::" , + stringify ! ( src_dst ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_key ) ) . id as * const _ as + usize } , 32usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_key ) , "::" , + stringify ! ( id ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_key ) ) . key_len as * const _ as + usize } , 36usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_key ) , "::" , + stringify ! ( key_len ) )); +} +impl Clone for ip_frag_key { + fn clone(&self) -> Self { *self } +} +/** + * @internal Fragmented packet to reassemble. + * First two entries in the frags[] array are for the last and first fragments. + */ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct ip_frag_pkt { + /**< LRU list */ + pub lru: ip_frag_pkt__bindgen_ty_1, + /**< fragmentation key */ + pub key: ip_frag_key, + /**< creation timestamp */ + pub start: u64, + /**< expected reassembled size */ + pub total_size: u32, + /**< size of fragments received */ + pub frag_size: u32, + /**< index of next entry to fill */ + pub last_idx: u32, + /**< fragments */ + pub frags: [ip_frag; 4usize], + pub __bindgen_padding_0: [u64; 6usize], +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct ip_frag_pkt__bindgen_ty_1 { + pub tqe_next: *mut ip_frag_pkt, + pub tqe_prev: *mut *mut ip_frag_pkt, +} +#[test] +fn bindgen_test_layout_ip_frag_pkt__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::<ip_frag_pkt__bindgen_ty_1>() , 16usize , + concat ! ( + "Size of: " , stringify ! ( ip_frag_pkt__bindgen_ty_1 ) )); + assert_eq! (::std::mem::align_of::<ip_frag_pkt__bindgen_ty_1>() , 8usize , + concat ! ( + "Alignment of " , stringify ! ( ip_frag_pkt__bindgen_ty_1 ) + )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt__bindgen_ty_1 ) ) . tqe_next + as * const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( + ip_frag_pkt__bindgen_ty_1 ) , "::" , stringify ! ( tqe_next ) + )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt__bindgen_ty_1 ) ) . tqe_prev + as * const _ as usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( + ip_frag_pkt__bindgen_ty_1 ) , "::" , stringify ! ( tqe_prev ) + )); +} +impl Clone for ip_frag_pkt__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +impl Default for ip_frag_pkt__bindgen_ty_1 { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[test] +fn bindgen_test_layout_ip_frag_pkt() { + assert_eq!(::std::mem::size_of::<ip_frag_pkt>() , 192usize , concat ! ( + "Size of: " , stringify ! ( ip_frag_pkt ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt ) ) . lru as * const _ as + usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_pkt ) , "::" , + stringify ! ( lru ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt ) ) . key as * const _ as + usize } , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_pkt ) , "::" , + stringify ! ( key ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt ) ) . start as * const _ as + usize } , 56usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_pkt ) , "::" , + stringify ! ( start ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt ) ) . total_size as * const _ + as usize } , 64usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_pkt ) , "::" , + stringify ! ( total_size ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt ) ) . frag_size as * const _ + as usize } , 68usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_pkt ) , "::" , + stringify ! ( frag_size ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt ) ) . last_idx as * const _ + as usize } , 72usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_pkt ) , "::" , + stringify ! ( last_idx ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_pkt ) ) . frags as * const _ as + usize } , 80usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_pkt ) , "::" , + stringify ! ( frags ) )); +} +impl Clone for ip_frag_pkt { + fn clone(&self) -> Self { *self } +} +impl Default for ip_frag_pkt { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct ip_pkt_list { + pub tqh_first: *mut ip_frag_pkt, + pub tqh_last: *mut *mut ip_frag_pkt, +} +#[test] +fn bindgen_test_layout_ip_pkt_list() { + assert_eq!(::std::mem::size_of::<ip_pkt_list>() , 16usize , concat ! ( + "Size of: " , stringify ! ( ip_pkt_list ) )); + assert_eq! (::std::mem::align_of::<ip_pkt_list>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( ip_pkt_list ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_pkt_list ) ) . tqh_first as * const _ + as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_pkt_list ) , "::" , + stringify ! ( tqh_first ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_pkt_list ) ) . tqh_last as * const _ + as usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_pkt_list ) , "::" , + stringify ! ( tqh_last ) )); +} +impl Clone for ip_pkt_list { + fn clone(&self) -> Self { *self } +} +impl Default for ip_pkt_list { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +/** fragmentation table statistics */ +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct ip_frag_tbl_stat { + /**< total # of find/insert attempts. */ + pub find_num: u64, + /**< # of add ops. */ + pub add_num: u64, + /**< # of del ops. */ + pub del_num: u64, + /**< # of reuse (del/add) ops. */ + pub reuse_num: u64, + /**< total # of add failures. */ + pub fail_total: u64, + /**< # of 'no space' add failures. */ + pub fail_nospace: u64, + pub __bindgen_padding_0: [u64; 2usize], +} +#[test] +fn bindgen_test_layout_ip_frag_tbl_stat() { + assert_eq!(::std::mem::size_of::<ip_frag_tbl_stat>() , 64usize , concat ! + ( "Size of: " , stringify ! ( ip_frag_tbl_stat ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_tbl_stat ) ) . find_num as * + const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_tbl_stat ) , + "::" , stringify ! ( find_num ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_tbl_stat ) ) . add_num as * const + _ as usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_tbl_stat ) , + "::" , stringify ! ( add_num ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_tbl_stat ) ) . del_num as * const + _ as usize } , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_tbl_stat ) , + "::" , stringify ! ( del_num ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_tbl_stat ) ) . reuse_num as * + const _ as usize } , 24usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_tbl_stat ) , + "::" , stringify ! ( reuse_num ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_tbl_stat ) ) . fail_total as * + const _ as usize } , 32usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_tbl_stat ) , + "::" , stringify ! ( fail_total ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ip_frag_tbl_stat ) ) . fail_nospace as * + const _ as usize } , 40usize , concat ! ( + "Alignment of field: " , stringify ! ( ip_frag_tbl_stat ) , + "::" , stringify ! ( fail_nospace ) )); +} +impl Clone for ip_frag_tbl_stat { + fn clone(&self) -> Self { *self } +} +/** fragmentation table */ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct rte_ip_frag_tbl { + /**< ttl for table entries. */ + pub max_cycles: u64, + /**< hash value mask. */ + pub entry_mask: u32, + /**< max entries allowed. */ + pub max_entries: u32, + /**< entries in use. */ + pub use_entries: u32, + /**< hash assocaitivity. */ + pub bucket_entries: u32, + /**< total size of the table. */ + pub nb_entries: u32, + /**< num of associativity lines. */ + pub nb_buckets: u32, + /**< last used entry. */ + pub last: *mut ip_frag_pkt, + /**< LRU list for table entries. */ + pub lru: ip_pkt_list, + pub __bindgen_padding_0: u64, + /**< statistics counters. */ + pub stat: ip_frag_tbl_stat, + /**< hash table. */ + pub pkt: __IncompleteArrayField<ip_frag_pkt>, +} +#[test] +fn bindgen_test_layout_rte_ip_frag_tbl() { + assert_eq!(::std::mem::size_of::<rte_ip_frag_tbl>() , 128usize , concat ! + ( "Size of: " , stringify ! ( rte_ip_frag_tbl ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . max_cycles as * + const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( max_cycles ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . entry_mask as * + const _ as usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( entry_mask ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . max_entries as * + const _ as usize } , 12usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( max_entries ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . use_entries as * + const _ as usize } , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( use_entries ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . bucket_entries as * + const _ as usize } , 20usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( bucket_entries ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . nb_entries as * + const _ as usize } , 24usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( nb_entries ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . nb_buckets as * + const _ as usize } , 28usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( nb_buckets ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . last as * const _ + as usize } , 32usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( last ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . lru as * const _ as + usize } , 40usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( lru ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . stat as * const _ + as usize } , 64usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( stat ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const rte_ip_frag_tbl ) ) . pkt as * const _ as + usize } , 128usize , concat ! ( + "Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) , + "::" , stringify ! ( pkt ) )); +} +impl Clone for rte_ip_frag_tbl { + fn clone(&self) -> Self { *self } +} +impl Default for rte_ip_frag_tbl { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +/**< fragment mbuf */ +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct rte_mbuf { + pub _address: u8, +} +impl Clone for rte_mbuf { + fn clone(&self) -> Self { *self } +} diff --git a/tests/headers/layout_large_align_field.h b/tests/headers/layout_large_align_field.h new file mode 100644 index 00000000..f4f412c6 --- /dev/null +++ b/tests/headers/layout_large_align_field.h @@ -0,0 +1,97 @@ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +#define RTE_CACHE_LINE_SIZE 64 + +/** + * Force alignment + */ +#define __rte_aligned(a) __attribute__((__aligned__(a))) + +/** + * Force alignment to cache line. + */ +#define __rte_cache_aligned __rte_aligned(RTE_CACHE_LINE_SIZE) + +#define RTE_LIBRTE_IP_FRAG_MAX_FRAG 4 + +enum { + IP_LAST_FRAG_IDX, /**< index of last fragment */ + IP_FIRST_FRAG_IDX, /**< index of first fragment */ + IP_MIN_FRAG_NUM, /**< minimum number of fragments */ + IP_MAX_FRAG_NUM = RTE_LIBRTE_IP_FRAG_MAX_FRAG, + /**< maximum number of fragments per packet */ +}; + +/** @internal fragmented mbuf */ +struct ip_frag { + uint16_t ofs; /**< offset into the packet */ + uint16_t len; /**< length of fragment */ + struct rte_mbuf *mb; /**< fragment mbuf */ +}; + +/** @internal <src addr, dst_addr, id> to uniquely indetify fragmented datagram. */ +struct ip_frag_key { + uint64_t src_dst[4]; /**< src address, first 8 bytes used for IPv4 */ + uint32_t id; /**< dst address */ + uint32_t key_len; /**< src/dst key length */ +}; + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/** + * @internal Fragmented packet to reassemble. + * First two entries in the frags[] array are for the last and first fragments. + */ +struct ip_frag_pkt { + TAILQ_ENTRY(ip_frag_pkt) lru; /**< LRU list */ + struct ip_frag_key key; /**< fragmentation key */ + uint64_t start; /**< creation timestamp */ + uint32_t total_size; /**< expected reassembled size */ + uint32_t frag_size; /**< size of fragments received */ + uint32_t last_idx; /**< index of next entry to fill */ + struct ip_frag frags[IP_MAX_FRAG_NUM]; /**< fragments */ +} __rte_cache_aligned; + +TAILQ_HEAD(ip_pkt_list, ip_frag_pkt); /**< @internal fragments tailq */ + +/** fragmentation table statistics */ +struct ip_frag_tbl_stat { + uint64_t find_num; /**< total # of find/insert attempts. */ + uint64_t add_num; /**< # of add ops. */ + uint64_t del_num; /**< # of del ops. */ + uint64_t reuse_num; /**< # of reuse (del/add) ops. */ + uint64_t fail_total; /**< total # of add failures. */ + uint64_t fail_nospace; /**< # of 'no space' add failures. */ +} __rte_cache_aligned; + +/** fragmentation table */ +struct rte_ip_frag_tbl { + uint64_t max_cycles; /**< ttl for table entries. */ + uint32_t entry_mask; /**< hash value mask. */ + uint32_t max_entries; /**< max entries allowed. */ + uint32_t use_entries; /**< entries in use. */ + uint32_t bucket_entries; /**< hash assocaitivity. */ + uint32_t nb_entries; /**< total size of the table. */ + uint32_t nb_buckets; /**< num of associativity lines. */ + struct ip_frag_pkt *last; /**< last used entry. */ + struct ip_pkt_list lru; /**< LRU list for table entries. */ + struct ip_frag_tbl_stat stat; /**< statistics counters. */ + __extension__ struct ip_frag_pkt pkt[0]; /**< hash table. */ +}; |