Skip to content

Commit 32f1211

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 The global variable and struct members have different path to set saw_complex.
1 parent 7fe40e0 commit 32f1211

File tree

7 files changed

+132
-57
lines changed

7 files changed

+132
-57
lines changed

src/codegen/mod.rs

+46
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ fn root_import(ctx: &BindgenContext) -> P<ast::Item> {
3838
struct CodegenResult {
3939
items: Vec<P<ast::Item>>,
4040
saw_union: bool,
41+
saw_complex: bool,
4142
items_seen: HashSet<ItemId>,
4243
/// The set of generated function/var names, needed because in C/C++ is
4344
/// legal to do something like:
@@ -64,6 +65,7 @@ impl CodegenResult {
6465
CodegenResult {
6566
items: vec![],
6667
saw_union: false,
68+
saw_complex: false,
6769
items_seen: Default::default(),
6870
functions_seen: Default::default(),
6971
vars_seen: Default::default(),
@@ -73,6 +75,10 @@ impl CodegenResult {
7375
fn saw_union(&mut self) {
7476
self.saw_union = true;
7577
}
78+
79+
fn saw_complex(&mut self) {
80+
self.saw_complex = true;
81+
}
7682

7783
fn seen(&self, item: ItemId) -> bool {
7884
self.items_seen.contains(&item)
@@ -349,6 +355,9 @@ impl CodeGenerator for Type {
349355
return;
350356
}
351357
TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
358+
TypeKind::Complex(..) => {
359+
result.saw_complex();
360+
}
352361
TypeKind::TemplateAlias(inner, _) => {
353362
// NB: The inner Alias will pick the correct
354363
// applicable_template_args.
@@ -774,6 +783,10 @@ impl CodeGenerator for CompInfo {
774783
template_args_used[i] = true;
775784
}
776785
}
786+
787+
if let &TypeKind::Complex(..) = field_ty.kind() {
788+
result.saw_complex();
789+
}
777790

778791
let ty = field.ty().to_rust_ty(ctx);
779792

@@ -1487,6 +1500,17 @@ impl ToRustTy for Type {
14871500
}
14881501
}
14891502
}
1503+
TypeKind::Complex(fk) => {
1504+
use ir::ty::FloatKind;
1505+
let float_path = match fk {
1506+
FloatKind::Float => aster::ty::TyBuilder::new().f32(),
1507+
FloatKind::Double | FloatKind::LongDouble => {
1508+
aster::ty::TyBuilder::new().f64()
1509+
}
1510+
};
1511+
1512+
quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>)
1513+
}
14901514
TypeKind::Function(ref fs) => {
14911515
let ty = fs.to_rust_ty(ctx, item);
14921516
let prefix = ctx.trait_prefix();
@@ -1756,10 +1780,14 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
17561780
}
17571781

17581782
let saw_union = result.saw_union;
1783+
let saw_complex = result.saw_complex;
17591784
let mut result = result.items;
17601785
if saw_union && !context.options().unstable_rust {
17611786
utils::prepend_union_types(context, &mut result);
17621787
}
1788+
if saw_complex {
1789+
utils::prepend_complex_type(context, &mut result);
1790+
}
17631791
result
17641792
})
17651793
}
@@ -1841,6 +1869,24 @@ mod utils {
18411869
result.extend(old_items.into_iter());
18421870
}
18431871

1872+
pub fn prepend_complex_type(ctx: &BindgenContext,
1873+
result: &mut Vec<P<ast::Item>>) {
1874+
let union_field_decl = quote_item!(ctx.ext_cx(),
1875+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
1876+
#[repr(C)]
1877+
pub struct __BindgenComplex<T> {
1878+
pub re: T,
1879+
pub im: T
1880+
}
1881+
)
1882+
.unwrap();
1883+
1884+
let items = vec![
1885+
union_field_decl,
1886+
];
1887+
let old_items = mem::replace(result, items);
1888+
result.extend(old_items.into_iter());
1889+
}
18441890

18451891
pub fn build_templated_path(item: &Item,
18461892
ctx: &BindgenContext,

src/ir/context.rs

+12
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,18 @@ impl<'ctx> BindgenContext<'ctx> {
695695
CXType_Float => TypeKind::Float(FloatKind::Float),
696696
CXType_Double => TypeKind::Float(FloatKind::Double),
697697
CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
698+
CXType_Complex => {
699+
let float_type = ty.elem_type()
700+
.expect("Not able to resolve complex type?");
701+
let float_kind = match float_type.kind() {
702+
CXType_Float => Some(FloatKind::Float),
703+
CXType_Double => Some(FloatKind::Double),
704+
CXType_LongDouble => Some(FloatKind::LongDouble),
705+
_ => None,
706+
}
707+
.expect("Not able to resolve complex floating type?");
708+
TypeKind::Complex(float_kind)
709+
},
698710
_ => return None,
699711
};
700712

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. complex only exist for floating point.
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

+42-36
Original file line numberDiff line numberDiff line change
@@ -4,81 +4,87 @@
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)]
9-
pub struct Testdouble {
10-
pub mMember: [f64; 2usize],
15+
pub struct TestDouble {
16+
pub mMember: __BindgenComplex<f64>,
1117
}
1218
#[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);
19+
fn bindgen_test_layout_TestDouble() {
20+
assert_eq!(::std::mem::size_of::<TestDouble>() , 16usize);
21+
assert_eq!(::std::mem::align_of::<TestDouble>() , 8usize);
1622
}
17-
impl Clone for Testdouble {
23+
impl Clone for TestDouble {
1824
fn clone(&self) -> Self { *self }
1925
}
2026
#[repr(C)]
2127
#[derive(Debug, Copy)]
22-
pub struct TestdoublePtr {
23-
pub mMember: *mut [f64; 2usize],
28+
pub struct TestDoublePtr {
29+
pub mMember: *mut __BindgenComplex<f64>,
2430
}
2531
#[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);
32+
fn bindgen_test_layout_TestDoublePtr() {
33+
assert_eq!(::std::mem::size_of::<TestDoublePtr>() , 8usize);
34+
assert_eq!(::std::mem::align_of::<TestDoublePtr>() , 8usize);
2935
}
30-
impl Clone for TestdoublePtr {
36+
impl Clone for TestDoublePtr {
3137
fn clone(&self) -> Self { *self }
3238
}
3339
#[repr(C)]
3440
#[derive(Debug, Copy)]
35-
pub struct Testfloat {
36-
pub mMember: [f32; 2usize],
41+
pub struct TestFloat {
42+
pub mMember: __BindgenComplex<f32>,
3743
}
3844
#[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);
45+
fn bindgen_test_layout_TestFloat() {
46+
assert_eq!(::std::mem::size_of::<TestFloat>() , 8usize);
47+
assert_eq!(::std::mem::align_of::<TestFloat>() , 4usize);
4248
}
43-
impl Clone for Testfloat {
49+
impl Clone for TestFloat {
4450
fn clone(&self) -> Self { *self }
4551
}
4652
#[repr(C)]
4753
#[derive(Debug, Copy)]
48-
pub struct TestfloatPtr {
49-
pub mMember: *mut [f32; 2usize],
54+
pub struct TestFloatPtr {
55+
pub mMember: *mut __BindgenComplex<f32>,
5056
}
5157
#[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);
58+
fn bindgen_test_layout_TestFloatPtr() {
59+
assert_eq!(::std::mem::size_of::<TestFloatPtr>() , 8usize);
60+
assert_eq!(::std::mem::align_of::<TestFloatPtr>() , 8usize);
5561
}
56-
impl Clone for TestfloatPtr {
62+
impl Clone for TestFloatPtr {
5763
fn clone(&self) -> Self { *self }
5864
}
5965
#[repr(C)]
6066
#[derive(Debug, Copy)]
61-
pub struct Testint {
62-
pub mMember: [::std::os::raw::c_int; 2usize],
67+
pub struct TestLongDouble {
68+
pub mMember: __BindgenComplex<f64>,
6369
}
6470
#[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);
71+
fn bindgen_test_layout_TestLongDouble() {
72+
assert_eq!(::std::mem::size_of::<TestLongDouble>() , 32usize);
73+
assert_eq!(::std::mem::align_of::<TestLongDouble>() , 16usize);
6874
}
69-
impl Clone for Testint {
75+
impl Clone for TestLongDouble {
7076
fn clone(&self) -> Self { *self }
7177
}
7278
#[repr(C)]
7379
#[derive(Debug, Copy)]
74-
pub struct TestintPtr {
75-
pub mMember: *mut [::std::os::raw::c_int; 2usize],
80+
pub struct TestLongDoublePtr {
81+
pub mMember: *mut __BindgenComplex<f64>,
7682
}
7783
#[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);
84+
fn bindgen_test_layout_TestLongDoublePtr() {
85+
assert_eq!(::std::mem::size_of::<TestLongDoublePtr>() , 8usize);
86+
assert_eq!(::std::mem::align_of::<TestLongDoublePtr>() , 8usize);
8187
}
82-
impl Clone for TestintPtr {
88+
impl Clone for TestLongDoublePtr {
8389
fn clone(&self) -> Self { *self }
8490
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 = "globalValue"]
15+
pub static mut globalValue: __BindgenComplex<f64>;
16+
}

tests/headers/complex.h

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11

2-
#define COMPLEX_TEST(ty_) \
3-
struct Test##ty_ { \
4-
ty_ _Complex mMember; \
5-
\
6-
}; \
7-
struct Test##ty_##Ptr { \
8-
ty_ _Complex* mMember; \
2+
#define COMPLEX_TEST(ty_, name_) \
3+
struct Test##name_ { \
4+
ty_ _Complex mMember; \
5+
\
6+
}; \
7+
struct Test##name_##Ptr { \
8+
ty_ _Complex* mMember; \
99
};
1010

11-
COMPLEX_TEST(double)
12-
COMPLEX_TEST(float)
13-
COMPLEX_TEST(int)
11+
COMPLEX_TEST(double, Double)
12+
COMPLEX_TEST(float, Float)
13+
COMPLEX_TEST(long double, LongDouble)

tests/headers/complex_global.h

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
double _Complex globalValue;

0 commit comments

Comments
 (0)