Skip to content

Commit

Permalink
Minimal support for fn types in extern statics
Browse files Browse the repository at this point in the history
  • Loading branch information
gnzlbg committed Oct 16, 2018
1 parent 52394e1 commit 9375d57
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 9 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Automated tests of FFI bindings.
[dependencies]
syntex_syntax = "0.59.1"
cc = "1.0.1"
syn = { version = "0.15", features = ["full"] }

[workspace]
members = ["testcrate"]
48 changes: 40 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

extern crate cc;
extern crate syntex_syntax as syntax;
extern crate syn;

use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
Expand Down Expand Up @@ -932,7 +933,7 @@ impl<'a> Generator<'a> {
"i16" => "int16_t".to_string(),
"i32" => "int32_t".to_string(),
"i64" => "int64_t".to_string(),

"( )" => "void".to_string(),
s => (self.opts.type_name)(s, self.structs.contains(s), self.unions.contains(s)),
}
}
Expand Down Expand Up @@ -1198,17 +1199,43 @@ impl<'a> Generator<'a> {
self.tests.push(format!("fn_{}", name));
}

fn test_extern_static(&mut self, name: &str, rust_ty: &str, mutbl: bool) {
fn test_extern_static(&mut self, name: &str, cname: Option<String>,
rust_ty: &str, c_ty: &str, mutbl: bool) {
if (self.opts.skip_static)(name) {
return
}
let c_ty = self.rust_ty_to_c_ty(rust_ty);

let cname = cname.unwrap_or_else(|| name.to_string());

if rust_ty.contains("extern fn") {
let c_ty = c_ty.replace("(*)", &format!("(* __test_static_{}(void))", name));
t!(writeln!(self.c, r#"
{ty} {{
return {cname};
}}
"#, ty = c_ty, cname = cname));
t!(writeln!(self.rust, r#"
#[inline(never)]
fn static_{name}() {{
extern {{
fn __test_static_{name}() -> {ty};
}}
unsafe {{
same({name} as usize,
__test_static_{name}() as usize,
"{name} static");
}}
}}
"#, name = name, ty = rust_ty));
} else {
let c_ty = self.rust_ty_to_c_ty(rust_ty);
t!(writeln!(self.c, r#"
{mutbl}{ty}* __test_static_{name}(void) {{
return &{name};
return &{cname};
}}
"#, mutbl = if mutbl { "" } else { "const " }, ty = c_ty, name = name));
t!(writeln!(self.rust, r#"
"#, mutbl = if mutbl { "" } else { "const " }, ty = c_ty,
name = name, cname = cname));
t!(writeln!(self.rust, r#"
#[inline(never)]
fn static_{name}() {{
extern {{
Expand All @@ -1221,6 +1248,7 @@ impl<'a> Generator<'a> {
}}
}}
"#, name = name, mutbl = if mutbl { "mut" } else { "const" }, ty = rust_ty));
};
self.tests.push(format!("static_{}", name));
}

Expand Down Expand Up @@ -1329,6 +1357,7 @@ impl<'a> Generator<'a> {
format!("char*")
}
}
ast::TyKind::Tup(ref v) if v.is_empty() => if rust { "()".to_string() } else { "void".to_string() },
_ => panic!("unknown ty {:?}", ty),
}
}
Expand Down Expand Up @@ -1518,8 +1547,11 @@ impl<'a, 'v> Visitor<'v> for Generator<'a> {
variadic, abi);
}
ast::ForeignItemKind::Static(ref ty, mutbl) => {
let ty = self.ty2name(&ty, true);
self.test_extern_static(&i.ident.to_string(), &ty, mutbl);
let rust_ty = self.ty2name(&ty, true);
let c_ty = self.ty2name(&ty, false);
let cname = attr::first_attr_value_str_by_name(&i.attrs, "link_name")
.map(|i| i.to_string());
self.test_extern_static(&i.ident.to_string(), cname, &rust_ty, &c_ty, mutbl);
}
}
visit::walk_foreign_item(self, i)
Expand Down
17 changes: 17 additions & 0 deletions testcrate/src/t1.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,20 @@ void T1h(const int32_t a[4]) {}
void T1i(int32_t a[4]) {}
void T1j(int32_t a[4]) {}
unsigned T1static = 3;

const uint8_t T1_static_u8 = 42;
uint8_t T1_static_mut_u8 = 37;


uint8_t foo(uint8_t a, uint8_t b) { return a + b; }
void bar(uint8_t a) { return; }
void baz(void) { return; }


uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t) = foo;
uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t) = foo;
void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t) = bar;
void (*const T1_static_const_fn_ptr_unsafe3)(void) = baz;

const uint8_t T1_static_right = 7;
uint8_t (*T1_static_right2)(uint8_t, uint8_t) = foo;
10 changes: 9 additions & 1 deletion testcrate/src/t1.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,12 @@ void T1j(int32_t a[4]);
#define T1C 4

extern uint32_t T1static;

const uint8_t T1_static_u8;
uint8_t T1_static_mut_u8;
uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t);
uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t);
void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t);
void (*const T1_static_const_fn_ptr_unsafe3)(void);

const uint8_t T1_static_right;
uint8_t (*T1_static_right2)(uint8_t, uint8_t);
14 changes: 14 additions & 0 deletions testcrate/src/t1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,17 @@ extern {
pub fn foo() {
assert_eq!(1, 1);
}

extern "C" {
pub static T1_static_u8: u8;
pub static mut T1_static_mut_u8: u8;
pub static mut T1_static_mut_fn_ptr: extern "C" fn(u8, u8) -> u8;
pub static T1_static_const_fn_ptr_unsafe: unsafe extern "C" fn(u8, u8) -> u8;
pub static T1_static_const_fn_ptr_unsafe2: unsafe extern "C" fn(u8) -> ();
pub static T1_static_const_fn_ptr_unsafe3: unsafe extern "C" fn() -> ();

#[link_name = "T1_static_right"]
pub static T1_static_wrong: u8;
#[link_name = "T1_static_right2"]
pub static mut T1_static_wrong2: extern "C" fn(u8, u8) -> u8;
}

0 comments on commit 9375d57

Please sign in to comment.