summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/helpers.rs47
-rwxr-xr-xsrc/codegen/mod.rs57
-rw-r--r--src/ir/context.rs26
-rw-r--r--src/ir/ty.rs16
4 files changed, 106 insertions, 40 deletions
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
index 234dcbcc..016ba478 100644
--- a/src/codegen/helpers.rs
+++ b/src/codegen/helpers.rs
@@ -71,3 +71,50 @@ impl BlobTyBuilder {
}
}
}
+
+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()
+ }
+ }
+ }
+}
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 3bee69b6..1511f629 100755
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -336,6 +336,7 @@ impl CodeGenerator for Type {
TypeKind::NullPtr |
TypeKind::Int(..) |
TypeKind::Float(..) |
+ TypeKind::Complex(..) |
TypeKind::Array(..) |
TypeKind::Pointer(..) |
TypeKind::BlockPointer |
@@ -1549,21 +1550,12 @@ impl ItemToRustTy for Item {
}
}
-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),
- }
-}
-
impl ToRustTy for Type {
type Extra = Item;
fn to_rust_ty(&self, ctx: &BindgenContext, item: &Item) -> P<ast::Ty> {
+ use self::helpers::ast_ty::*;
+
macro_rules! raw {
($ty: ident) => {
raw_type(ctx, stringify!($ty))
@@ -1608,24 +1600,12 @@ impl ToRustTy for Type {
}
}
}
- TypeKind::Float(fk) => {
- // 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.
- use ir::ty::FloatKind;
- 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(),
- }
+ TypeKind::Float(fk) => float_kind_rust_type(ctx, fk),
+ TypeKind::Complex(fk) => {
+ let float_path = float_kind_rust_type(ctx, fk);
+
+ ctx.generated_bindegen_complex();
+ quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>)
}
TypeKind::Function(ref fs) => {
let ty = fs.to_rust_ty(ctx, item);
@@ -1900,6 +1880,9 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
if saw_union && !context.options().unstable_rust {
utils::prepend_union_types(context, &mut result);
}
+ if context.need_bindegen_complex_type() {
+ utils::prepend_complex_type(context, &mut result);
+ }
result
})
}
@@ -1981,6 +1964,22 @@ mod utils {
result.extend(old_items.into_iter());
}
+ pub fn prepend_complex_type(ctx: &BindgenContext,
+ result: &mut Vec<P<ast::Item>>) {
+ let complex_type = quote_item!(ctx.ext_cx(),
+ #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
+ #[repr(C)]
+ pub struct __BindgenComplex<T> {
+ pub re: T,
+ pub im: T
+ }
+ )
+ .unwrap();
+
+ let items = vec![complex_type];
+ let old_items = mem::replace(result, items);
+ result.extend(old_items.into_iter());
+ }
pub fn build_templated_path(item: &Item,
ctx: &BindgenContext,
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 92c6fb49..c7949bef 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -5,6 +5,7 @@ use cexpr;
use clang::{self, Cursor};
use parse::ClangItemParser;
use std::borrow::Cow;
+use std::cell::Cell;
use std::collections::{HashMap, hash_map};
use std::collections::btree_map::{self, BTreeMap};
use std::fmt;
@@ -99,6 +100,9 @@ pub struct BindgenContext<'ctx> {
/// The options given by the user via cli or other medium.
options: BindgenOptions,
+
+ /// Whether a bindgen complex was generated
+ generated_bindegen_complex: Cell<bool>,
}
impl<'ctx> BindgenContext<'ctx> {
@@ -134,6 +138,7 @@ impl<'ctx> BindgenContext<'ctx> {
index: index,
translation_unit: translation_unit,
options: options,
+ generated_bindegen_complex: Cell::new(false),
};
me.add_item(root_module, None, None);
@@ -698,6 +703,17 @@ impl<'ctx> BindgenContext<'ctx> {
CXType_Double => TypeKind::Float(FloatKind::Double),
CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
CXType_Float128 => TypeKind::Float(FloatKind::Float128),
+ CXType_Complex => {
+ let float_type = ty.elem_type()
+ .expect("Not able to resolve complex type?");
+ let float_kind = match float_type.kind() {
+ CXType_Float => FloatKind::Float,
+ CXType_Double => FloatKind::Double,
+ CXType_LongDouble => FloatKind::LongDouble,
+ _ => panic!("Non floating-type complex?"),
+ };
+ TypeKind::Complex(float_kind)
+ }
_ => return None,
};
@@ -930,6 +946,16 @@ impl<'ctx> BindgenContext<'ctx> {
self.rust_ident_raw("std")
}
}
+
+ /// Call if a binden complex is generated
+ pub fn generated_bindegen_complex(&self) {
+ self.generated_bindegen_complex.set(true)
+ }
+
+ /// Whether we need to generate the binden complex type
+ pub fn need_bindegen_complex_type(&self) -> bool {
+ self.generated_bindegen_complex.get()
+ }
}
/// An iterator over whitelisted items.
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 4c2ef5d8..d5ac6116 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -334,6 +334,7 @@ impl Type {
TypeKind::Comp(..) |
TypeKind::Int(..) |
TypeKind::Float(..) |
+ TypeKind::Complex(..) |
TypeKind::Function(..) |
TypeKind::Enum(..) |
TypeKind::Reference(..) |
@@ -386,6 +387,9 @@ pub enum TypeKind {
/// A floating point type.
Float(FloatKind),
+ /// A complex floating point type.
+ Complex(FloatKind),
+
/// A type alias, with a name, that points to another type.
Alias(String, ItemId),
@@ -463,6 +467,7 @@ impl Type {
TypeKind::Named(..) |
TypeKind::Int(..) |
TypeKind::Float(..) |
+ TypeKind::Complex(..) |
TypeKind::Function(..) |
TypeKind::Enum(..) |
TypeKind::Reference(..) |
@@ -801,17 +806,6 @@ impl Type {
.expect("Not able to resolve array element?");
TypeKind::Array(inner, ty.num_elements().unwrap())
}
- // A complex number is always a real and an imaginary part,
- // so
- // represent that as a two-item array.
- CXType_Complex => {
- let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
- location,
- parent_id,
- ctx)
- .expect("Not able to resolve array element?");
- TypeKind::Array(inner, 2)
- }
#[cfg(not(feature="llvm_stable"))]
CXType_Elaborated => {
return Self::from_clang_ty(potential_id,