diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-11-15 12:48:14 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-15 12:48:14 -0600 |
commit | 6b285e617ede6d3dbd6d2d0129ac81bc992a1593 (patch) | |
tree | ff4d1b4d5f44366960c0c5d9621da6cde4cc5468 /libbindgen/src/codegen/helpers.rs | |
parent | 6e78bb8d56d875619d20e343d0f3109e2d6b6841 (diff) | |
parent | 073b12ff35a8ec6314d655804915f177ce453227 (diff) |
Auto merge of #204 - jdub:logless-library, r=emilio
Split off bindgen library into a sub-crate
- Unfortunately there's a dependency on log via syntex_errors, so we
don't get rid of it all
- I can't find a more sensible way to set dependencies based on whether
you're building the lib or bin
- So `--no-default-features` means you need to know what you're doing,
as only the lib will build without the logging crates for now
- The replacement log macros are pretty gross too, but they show a proof
of concept ;-)
Diffstat (limited to 'libbindgen/src/codegen/helpers.rs')
-rw-r--r-- | libbindgen/src/codegen/helpers.rs | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/libbindgen/src/codegen/helpers.rs b/libbindgen/src/codegen/helpers.rs new file mode 100644 index 00000000..6e5a6f0e --- /dev/null +++ b/libbindgen/src/codegen/helpers.rs @@ -0,0 +1,135 @@ +//! Helpers for code generation that don't need macro expansion. + +use aster; +use ir::layout::Layout; +use syntax::ast; +use syntax::ptr::P; + + +pub mod attributes { + use aster; + use syntax::ast; + + pub fn repr(which: &str) -> ast::Attribute { + aster::AstBuilder::new().attr().list("repr").words(&[which]).build() + } + + pub fn repr_list(which_ones: &[&str]) -> ast::Attribute { + aster::AstBuilder::new().attr().list("repr").words(which_ones).build() + } + + pub fn derives(which_ones: &[&str]) -> ast::Attribute { + aster::AstBuilder::new().attr().list("derive").words(which_ones).build() + } + + pub fn inline() -> ast::Attribute { + aster::AstBuilder::new().attr().word("inline") + } + + pub fn doc(comment: &str) -> ast::Attribute { + aster::AstBuilder::new().attr().doc(comment) + } + + pub fn link_name(name: &str) -> ast::Attribute { + aster::AstBuilder::new().attr().name_value("link_name").str(name) + } +} + +/// Generates a proper type for a field or type with a given `Layout`, that is, +/// a type with the correct size and alignment restrictions. +pub struct BlobTyBuilder { + layout: Layout, +} + +impl BlobTyBuilder { + pub fn new(layout: Layout) -> Self { + BlobTyBuilder { + layout: layout, + } + } + + pub fn build(self) -> P<ast::Ty> { + use std::cmp; + + let ty_name = match self.layout.align { + 8 => "u64", + 4 => "u32", + 2 => "u16", + 1 | _ => "u8", + }; + let data_len = if ty_name == "u8" { + self.layout.size + } else { + self.layout.size / cmp::max(self.layout.align, 1) + }; + + let inner_ty = aster::AstBuilder::new().ty().path().id(ty_name).build(); + if data_len == 1 { + inner_ty + } else { + aster::ty::TyBuilder::new().array(data_len).build(inner_ty) + } + } +} + +pub mod ast_ty { + use aster; + use ir::context::BindgenContext; + use ir::ty::FloatKind; + use syntax::ast; + use syntax::ptr::P; + + pub fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> { + let ident = ctx.rust_ident_raw(&name); + match ctx.options().ctypes_prefix { + Some(ref prefix) => { + let prefix = ctx.rust_ident_raw(prefix); + quote_ty!(ctx.ext_cx(), $prefix::$ident) + } + None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident), + } + } + + pub fn float_kind_rust_type(ctx: &BindgenContext, + fk: FloatKind) + -> P<ast::Ty> { + macro_rules! raw { + ($ty: ident) => { + raw_type(ctx, stringify!($ty)) + } + } + // TODO: we probably should just take the type layout into + // account? + // + // Also, maybe this one shouldn't be the default? + // + // FIXME: `c_longdouble` doesn't seem to be defined in some + // systems, so we use `c_double` directly. + match (fk, ctx.options().convert_floats) { + (FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(), + (FloatKind::Double, true) | + (FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(), + (FloatKind::Float, false) => raw!(c_float), + (FloatKind::Double, false) | + (FloatKind::LongDouble, false) => raw!(c_double), + (FloatKind::Float128, _) => { + aster::ty::TyBuilder::new().array(16).u8() + } + } + } + + pub fn int_expr(val: i64) -> P<ast::Expr> { + use std::i64; + let expr = aster::AstBuilder::new().expr(); + + // This is not representable as an i64 if it's negative, so we + // special-case it. + // + // Fix in aster incoming. + if val == i64::MIN { + expr.neg().uint(1u64 << 63) + } else { + expr.int(val) + } + } +} |