Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added constructor return type for wasm32 target #1877

Merged
merged 3 commits into from Aug 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/ir/context.rs
Expand Up @@ -577,6 +577,14 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
}

/// Returns `true` if the target architecture is wasm32
pub fn is_target_wasm32(&self) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work if building with clang 4 or 3.9 (target_info will be null), but maybe that's fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt that wasm backend even existed for those versions of clang and as such I don't think what would be an issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to update the test expectations for these two versions, as we run CI on those. To do that you need to add the file in tests/expectations/tests/libclang-3.9 (and same for 4).

With that bit, this patch looks great, thank you!

match self.target_info {
Some(ref ti) => ti.triple.starts_with("wasm32-"),
None => false,
}
}

/// Creates a timer for the current bindgen phase. If time_phases is `true`,
/// the timer will print to stderr when it is dropped, otherwise it will do
/// nothing.
Expand Down
10 changes: 9 additions & 1 deletion src/ir/function.rs
Expand Up @@ -495,7 +495,15 @@ impl FunctionSig {
} else {
ty.ret_type().ok_or(ParseError::Continue)?
};
let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);

let ret = if is_constructor && ctx.is_target_wasm32() {
// Constructors in Clang wasm32 target return a pointer to the object
// being constructed.
let void = Item::builtin_type(TypeKind::Void, false, ctx);
Item::builtin_type(TypeKind::Pointer(void), false, ctx)
} else {
Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx)
};

// Clang plays with us at "find the calling convention", see #549 and
// co. This seems to be a better fix than that commit.
Expand Down
37 changes: 37 additions & 0 deletions tests/expectations/tests/libclang-3.9/wasm-constructor-returns.rs
@@ -0,0 +1,37 @@
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Foo {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_Foo() {
assert_eq!(
::std::mem::size_of::<Foo>(),
1usize,
concat!("Size of: ", stringify!(Foo))
);
assert_eq!(
::std::mem::align_of::<Foo>(),
1usize,
concat!("Alignment of ", stringify!(Foo))
);
}
extern "C" {
#[link_name = "\u{1}_ZN3FooC1Ei"]
pub fn Foo_Foo(this: *mut Foo, var: ::std::os::raw::c_int);
}
impl Foo {
#[inline]
pub unsafe fn new(var: ::std::os::raw::c_int) -> Self {
let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
Foo_Foo(__bindgen_tmp.as_mut_ptr(), var);
__bindgen_tmp.assume_init()
}
}
37 changes: 37 additions & 0 deletions tests/expectations/tests/libclang-4/wasm-constructor-returns.rs
@@ -0,0 +1,37 @@
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Foo {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_Foo() {
assert_eq!(
::std::mem::size_of::<Foo>(),
1usize,
concat!("Size of: ", stringify!(Foo))
);
assert_eq!(
::std::mem::align_of::<Foo>(),
1usize,
concat!("Alignment of ", stringify!(Foo))
);
}
extern "C" {
#[link_name = "\u{1}_ZN3FooC1Ei"]
pub fn Foo_Foo(this: *mut Foo, var: ::std::os::raw::c_int);
}
impl Foo {
#[inline]
pub unsafe fn new(var: ::std::os::raw::c_int) -> Self {
let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
Foo_Foo(__bindgen_tmp.as_mut_ptr(), var);
__bindgen_tmp.assume_init()
}
}
40 changes: 40 additions & 0 deletions tests/expectations/tests/wasm-constructor-returns.rs
@@ -0,0 +1,40 @@
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Foo {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_Foo() {
assert_eq!(
::std::mem::size_of::<Foo>(),
1usize,
concat!("Size of: ", stringify!(Foo))
);
assert_eq!(
::std::mem::align_of::<Foo>(),
1usize,
concat!("Alignment of ", stringify!(Foo))
);
}
extern "C" {
#[link_name = "\u{1}_ZN3FooC1Ei"]
pub fn Foo_Foo(
this: *mut Foo,
var: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_void;
}
impl Foo {
#[inline]
pub unsafe fn new(var: ::std::os::raw::c_int) -> Self {
let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
Foo_Foo(__bindgen_tmp.as_mut_ptr(), var);
__bindgen_tmp.assume_init()
}
}
7 changes: 7 additions & 0 deletions tests/headers/wasm-constructor-returns.hpp
@@ -0,0 +1,7 @@
// bindgen-flags: --generate constructors,types -- -fvisibility=default --target=wasm32-unknown-emscripten

class Foo {
public:
Foo(int var);
};