Skip to content

Commit d69f4c7

Browse files
committed
Use __BindegenComplex for C Complex Fix rust-lang#72
C complex only exists for floating point types. C Complex are built in types long double _Complex is not supported. Long double would be an f128, runing generated binding test produces: assertion failed: `(left == right)` (left: `16`, right: `32`)', tests/expectations/tests/complex.rs:72 We test global long double _Complex because it does not require layout tests. Handle all the different way a complex can be present in BindgenContext setting saw_complex.
1 parent b3322dd commit d69f4c7

File tree

9 files changed

+159
-94
lines changed

9 files changed

+159
-94
lines changed

src/codegen/mod.rs

+52-24
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use ir::item::{Item, ItemCanonicalName, ItemCanonicalPath, ItemId};
1313
use ir::item_kind::ItemKind;
1414
use ir::layout::Layout;
1515
use ir::module::Module;
16-
use ir::ty::{Type, TypeKind};
16+
use ir::ty::{FloatKind, Type, TypeKind};
1717
use ir::type_collector::ItemSet;
1818
use ir::var::Var;
1919
use self::helpers::{BlobTyBuilder, attributes};
@@ -336,6 +336,7 @@ impl CodeGenerator for Type {
336336
TypeKind::NullPtr |
337337
TypeKind::Int(..) |
338338
TypeKind::Float(..) |
339+
TypeKind::Complex(..) |
339340
TypeKind::Array(..) |
340341
TypeKind::Pointer(..) |
341342
TypeKind::BlockPointer |
@@ -1560,6 +1561,33 @@ fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
15601561
}
15611562
}
15621563

1564+
fn float_kind_rust_type(ctx: &BindgenContext, fk: FloatKind) -> P<ast::Ty> {
1565+
if ctx.options().convert_floats {
1566+
// TODO: we probably should just take the type layout into
1567+
// account?
1568+
//
1569+
// Also, maybe this one shouldn't be the default?
1570+
match fk {
1571+
FloatKind::Float => aster::ty::TyBuilder::new().f32(),
1572+
FloatKind::Double | FloatKind::LongDouble => {
1573+
aster::ty::TyBuilder::new().f64()
1574+
}
1575+
}
1576+
} else {
1577+
macro_rules! raw {
1578+
($ty: ident) => {
1579+
raw_type(ctx, stringify!($ty))
1580+
}
1581+
}
1582+
// FIXME: `c_longdouble` doesn't seem to be defined in some
1583+
// systems, so we use `c_double` directly.
1584+
match fk {
1585+
FloatKind::Float => raw!(c_float),
1586+
FloatKind::Double | FloatKind::LongDouble => raw!(c_double),
1587+
}
1588+
}
1589+
}
1590+
15631591
impl ToRustTy for Type {
15641592
type Extra = Item;
15651593

@@ -1608,29 +1636,10 @@ impl ToRustTy for Type {
16081636
}
16091637
}
16101638
}
1611-
TypeKind::Float(fk) => {
1612-
use ir::ty::FloatKind;
1613-
if ctx.options().convert_floats {
1614-
// TODO: we probably should just take the type layout into
1615-
// account?
1616-
//
1617-
// Also, maybe this one shouldn't be the default?
1618-
match fk {
1619-
FloatKind::Float => aster::ty::TyBuilder::new().f32(),
1620-
FloatKind::Double | FloatKind::LongDouble => {
1621-
aster::ty::TyBuilder::new().f64()
1622-
}
1623-
}
1624-
} else {
1625-
// FIXME: `c_longdouble` doesn't seem to be defined in some
1626-
// systems, so we use `c_double` directly.
1627-
match fk {
1628-
FloatKind::Float => raw!(c_float),
1629-
FloatKind::Double | FloatKind::LongDouble => {
1630-
raw!(c_double)
1631-
}
1632-
}
1633-
}
1639+
TypeKind::Float(fk) => float_kind_rust_type(ctx, fk),
1640+
TypeKind::Complex(fk) => {
1641+
let float_path = float_kind_rust_type(ctx, fk);
1642+
quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>)
16341643
}
16351644
TypeKind::Function(ref fs) => {
16361645
let ty = fs.to_rust_ty(ctx, item);
@@ -1905,6 +1914,9 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
19051914
if saw_union && !context.options().unstable_rust {
19061915
utils::prepend_union_types(context, &mut result);
19071916
}
1917+
if context.saw_complex() {
1918+
utils::prepend_complex_type(context, &mut result);
1919+
}
19081920
result
19091921
})
19101922
}
@@ -1986,6 +1998,22 @@ mod utils {
19861998
result.extend(old_items.into_iter());
19871999
}
19882000

2001+
pub fn prepend_complex_type(ctx: &BindgenContext,
2002+
result: &mut Vec<P<ast::Item>>) {
2003+
let complex_type = quote_item!(ctx.ext_cx(),
2004+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
2005+
#[repr(C)]
2006+
pub struct __BindgenComplex<T> {
2007+
pub re: T,
2008+
pub im: T
2009+
}
2010+
)
2011+
.unwrap();
2012+
2013+
let items = vec![complex_type];
2014+
let old_items = mem::replace(result, items);
2015+
result.extend(old_items.into_iter());
2016+
}
19892017

19902018
pub fn build_templated_path(item: &Item,
19912019
ctx: &BindgenContext,

src/ir/context.rs

+23
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use cexpr;
55
use clang::{self, Cursor};
66
use parse::ClangItemParser;
77
use std::borrow::Cow;
8+
use std::cell::Cell;
89
use std::collections::{HashMap, hash_map};
910
use std::collections::btree_map::{self, BTreeMap};
1011
use std::fmt;
@@ -99,6 +100,9 @@ pub struct BindgenContext<'ctx> {
99100

100101
/// The options given by the user via cli or other medium.
101102
options: BindgenOptions,
103+
104+
/// Whether a complex was detected anywhere
105+
saw_complex: Cell<bool>,
102106
}
103107

104108
impl<'ctx> BindgenContext<'ctx> {
@@ -134,6 +138,7 @@ impl<'ctx> BindgenContext<'ctx> {
134138
index: index,
135139
translation_unit: translation_unit,
136140
options: options,
141+
saw_complex: Cell::new(false),
137142
};
138143

139144
me.add_item(root_module, None, None);
@@ -697,6 +702,19 @@ impl<'ctx> BindgenContext<'ctx> {
697702
CXType_Float => TypeKind::Float(FloatKind::Float),
698703
CXType_Double => TypeKind::Float(FloatKind::Double),
699704
CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
705+
CXType_Complex => {
706+
let float_type = ty.elem_type()
707+
.expect("Not able to resolve complex type?");
708+
let float_kind = match float_type.kind() {
709+
CXType_Float => FloatKind::Float,
710+
CXType_Double => FloatKind::Double,
711+
CXType_LongDouble => FloatKind::LongDouble,
712+
_ => panic!("Non floating-type complex?"),
713+
};
714+
715+
self.saw_complex.set(true);
716+
TypeKind::Complex(float_kind)
717+
}
700718
_ => return None,
701719
};
702720

@@ -929,6 +947,11 @@ impl<'ctx> BindgenContext<'ctx> {
929947
self.rust_ident_raw("std")
930948
}
931949
}
950+
951+
/// Whether a complex was detected anywhere
952+
pub fn saw_complex(&self) -> bool {
953+
return self.saw_complex.get();
954+
}
932955
}
933956

934957
/// An iterator over whitelisted items.

src/ir/ty.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ impl Type {
334334
TypeKind::Comp(..) |
335335
TypeKind::Int(..) |
336336
TypeKind::Float(..) |
337+
TypeKind::Complex(..) |
337338
TypeKind::Function(..) |
338339
TypeKind::Enum(..) |
339340
TypeKind::Reference(..) |
@@ -384,6 +385,9 @@ pub enum TypeKind {
384385
/// A floating point type.
385386
Float(FloatKind),
386387

388+
/// A complex floating point type.
389+
Complex(FloatKind),
390+
387391
/// A type alias, with a name, that points to another type.
388392
Alias(String, ItemId),
389393

@@ -461,6 +465,7 @@ impl Type {
461465
TypeKind::Named(..) |
462466
TypeKind::Int(..) |
463467
TypeKind::Float(..) |
468+
TypeKind::Complex(..) |
464469
TypeKind::Function(..) |
465470
TypeKind::Enum(..) |
466471
TypeKind::Reference(..) |
@@ -751,17 +756,6 @@ impl Type {
751756
.expect("Not able to resolve array element?");
752757
TypeKind::Array(inner, ty.num_elements().unwrap())
753758
}
754-
// A complex number is always a real and an imaginary part,
755-
// so
756-
// represent that as a two-item array.
757-
CXType_Complex => {
758-
let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
759-
location,
760-
parent_id,
761-
ctx)
762-
.expect("Not able to resolve array element?");
763-
TypeKind::Array(inner, 2)
764-
}
765759
#[cfg(not(feature="llvm_stable"))]
766760
CXType_Elaborated => {
767761
return Self::from_clang_ty(potential_id,

tests/expectations/tests/complex.rs

+28-48
Original file line numberDiff line numberDiff line change
@@ -4,81 +4,61 @@
44
#![allow(non_snake_case)]
55

66

7+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
78
#[repr(C)]
8-
#[derive(Debug, Copy)]
9-
pub struct Testdouble {
10-
pub mMember: [f64; 2usize],
11-
}
12-
#[test]
13-
fn bindgen_test_layout_Testdouble() {
14-
assert_eq!(::std::mem::size_of::<Testdouble>() , 16usize);
15-
assert_eq!(::std::mem::align_of::<Testdouble>() , 8usize);
16-
}
17-
impl Clone for Testdouble {
18-
fn clone(&self) -> Self { *self }
19-
}
20-
#[repr(C)]
21-
#[derive(Debug, Copy)]
22-
pub struct TestdoublePtr {
23-
pub mMember: *mut [f64; 2usize],
24-
}
25-
#[test]
26-
fn bindgen_test_layout_TestdoublePtr() {
27-
assert_eq!(::std::mem::size_of::<TestdoublePtr>() , 8usize);
28-
assert_eq!(::std::mem::align_of::<TestdoublePtr>() , 8usize);
29-
}
30-
impl Clone for TestdoublePtr {
31-
fn clone(&self) -> Self { *self }
9+
pub struct __BindgenComplex<T> {
10+
pub re: T,
11+
pub im: T,
3212
}
3313
#[repr(C)]
3414
#[derive(Debug, Copy)]
35-
pub struct Testfloat {
36-
pub mMember: [f32; 2usize],
15+
pub struct TestDouble {
16+
pub mMember: __BindgenComplex<f64>,
3717
}
3818
#[test]
39-
fn bindgen_test_layout_Testfloat() {
40-
assert_eq!(::std::mem::size_of::<Testfloat>() , 8usize);
41-
assert_eq!(::std::mem::align_of::<Testfloat>() , 4usize);
19+
fn bindgen_test_layout_TestDouble() {
20+
assert_eq!(::std::mem::size_of::<TestDouble>() , 16usize);
21+
assert_eq!(::std::mem::align_of::<TestDouble>() , 8usize);
4222
}
43-
impl Clone for Testfloat {
23+
impl Clone for TestDouble {
4424
fn clone(&self) -> Self { *self }
4525
}
4626
#[repr(C)]
4727
#[derive(Debug, Copy)]
48-
pub struct TestfloatPtr {
49-
pub mMember: *mut [f32; 2usize],
28+
pub struct TestDoublePtr {
29+
pub mMember: *mut __BindgenComplex<f64>,
5030
}
5131
#[test]
52-
fn bindgen_test_layout_TestfloatPtr() {
53-
assert_eq!(::std::mem::size_of::<TestfloatPtr>() , 8usize);
54-
assert_eq!(::std::mem::align_of::<TestfloatPtr>() , 8usize);
32+
fn bindgen_test_layout_TestDoublePtr() {
33+
assert_eq!(::std::mem::size_of::<TestDoublePtr>() , 8usize);
34+
assert_eq!(::std::mem::align_of::<TestDoublePtr>() , 8usize);
5535
}
56-
impl Clone for TestfloatPtr {
36+
impl Clone for TestDoublePtr {
5737
fn clone(&self) -> Self { *self }
5838
}
5939
#[repr(C)]
6040
#[derive(Debug, Copy)]
61-
pub struct Testint {
62-
pub mMember: [::std::os::raw::c_int; 2usize],
41+
pub struct TestFloat {
42+
pub mMember: __BindgenComplex<f32>,
6343
}
6444
#[test]
65-
fn bindgen_test_layout_Testint() {
66-
assert_eq!(::std::mem::size_of::<Testint>() , 8usize);
67-
assert_eq!(::std::mem::align_of::<Testint>() , 4usize);
45+
fn bindgen_test_layout_TestFloat() {
46+
assert_eq!(::std::mem::size_of::<TestFloat>() , 8usize);
47+
assert_eq!(::std::mem::align_of::<TestFloat>() , 4usize);
6848
}
69-
impl Clone for Testint {
49+
impl Clone for TestFloat {
7050
fn clone(&self) -> Self { *self }
7151
}
7252
#[repr(C)]
7353
#[derive(Debug, Copy)]
74-
pub struct TestintPtr {
75-
pub mMember: *mut [::std::os::raw::c_int; 2usize],
54+
pub struct TestFloatPtr {
55+
pub mMember: *mut __BindgenComplex<f32>,
7656
}
7757
#[test]
78-
fn bindgen_test_layout_TestintPtr() {
79-
assert_eq!(::std::mem::size_of::<TestintPtr>() , 8usize);
80-
assert_eq!(::std::mem::align_of::<TestintPtr>() , 8usize);
58+
fn bindgen_test_layout_TestFloatPtr() {
59+
assert_eq!(::std::mem::size_of::<TestFloatPtr>() , 8usize);
60+
assert_eq!(::std::mem::align_of::<TestFloatPtr>() , 8usize);
8161
}
82-
impl Clone for TestintPtr {
62+
impl Clone for TestFloatPtr {
8363
fn clone(&self) -> Self { *self }
8464
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
8+
#[repr(C)]
9+
pub struct __BindgenComplex<T> {
10+
pub re: T,
11+
pub im: T,
12+
}
13+
extern "C" {
14+
#[link_name = "globalValueFloat"]
15+
pub static mut globalValueFloat: __BindgenComplex<f32>;
16+
}
17+
extern "C" {
18+
#[link_name = "globalValueDouble"]
19+
pub static mut globalValueDouble: __BindgenComplex<f64>;
20+
}
21+
extern "C" {
22+
#[link_name = "globalValueLongDouble"]
23+
pub static mut globalValueLongDouble: __BindgenComplex<f64>;
24+
}

tests/expectations/tests/convert-floats.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,25 @@
44
#![allow(non_snake_case)]
55

66

7+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
8+
#[repr(C)]
9+
pub struct __BindgenComplex<T> {
10+
pub re: T,
11+
pub im: T,
12+
}
713
#[repr(C)]
814
#[derive(Debug, Copy)]
915
pub struct foo {
1016
pub bar: ::std::os::raw::c_float,
1117
pub baz: ::std::os::raw::c_float,
1218
pub bazz: ::std::os::raw::c_double,
1319
pub bazzz: *mut ::std::os::raw::c_double,
20+
pub complexFloat: __BindgenComplex<::std::os::raw::c_float>,
21+
pub complexDouble: __BindgenComplex<::std::os::raw::c_double>,
1422
}
1523
#[test]
1624
fn bindgen_test_layout_foo() {
17-
assert_eq!(::std::mem::size_of::<foo>() , 24usize);
25+
assert_eq!(::std::mem::size_of::<foo>() , 48usize);
1826
assert_eq!(::std::mem::align_of::<foo>() , 8usize);
1927
}
2028
impl Clone for foo {

0 commit comments

Comments
 (0)