summaryrefslogtreecommitdiff
path: root/libbindgen/src/codegen/helpers.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-11-15 12:48:14 -0600
committerGitHub <noreply@github.com>2016-11-15 12:48:14 -0600
commit6b285e617ede6d3dbd6d2d0129ac81bc992a1593 (patch)
treeff4d1b4d5f44366960c0c5d9621da6cde4cc5468 /libbindgen/src/codegen/helpers.rs
parent6e78bb8d56d875619d20e343d0f3109e2d6b6841 (diff)
parent073b12ff35a8ec6314d655804915f177ce453227 (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.rs135
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)
+ }
+ }
+}