summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example-graphviz-ir.pngbin842576 -> 1343520 bytes
-rw-r--r--src/clang.rs6
-rw-r--r--src/codegen/mod.rs3
-rw-r--r--src/codegen/struct_layout.rs6
-rw-r--r--src/ir/context.rs31
-rw-r--r--src/ir/dot.rs53
-rw-r--r--src/ir/function.rs14
-rw-r--r--src/ir/item.rs29
-rw-r--r--src/ir/item_kind.rs20
-rw-r--r--src/ir/mod.rs1
-rw-r--r--src/ir/module.rs12
-rw-r--r--src/ir/ty.rs57
-rw-r--r--src/ir/var.rs18
-rw-r--r--tests/expectations/tests/layout_large_align_field.rs419
-rw-r--r--tests/headers/layout_large_align_field.h97
15 files changed, 717 insertions, 49 deletions
diff --git a/example-graphviz-ir.png b/example-graphviz-ir.png
index c990f7e7..1e554a83 100644
--- a/example-graphviz-ir.png
+++ b/example-graphviz-ir.png
Binary files differ
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. */
+};