Skip to content

Commit

Permalink
Merge pull request #39 from gnzlbg/rs2c
Browse files Browse the repository at this point in the history
Minimal support for fn types in extern statics
  • Loading branch information
alexcrichton committed Oct 16, 2018
2 parents 52394e1 + 30f5187 commit f8bd332
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 9 deletions.
55 changes: 46 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,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 +1198,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.replacen("(*)", &format!("(* __test_static_{}(void))", name), 1);
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 +1247,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 @@ -1290,7 +1317,13 @@ impl<'a> Generator<'a> {
if args.len() == 0 {
args.push("void".to_string());
}
format!("{}(*)({})", ret, args.join(", "))

let s = if ret.contains("(*)") {
ret.replace("(*)", &format!("(*(*)({}))", args.join(", ")))
} else {
format!("{}(*)({})", ret, args.join(", "))
};
s
}
}
ast::TyKind::Array(ref t, ref e) => {
Expand Down Expand Up @@ -1329,6 +1362,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 +1552,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
27 changes: 27 additions & 0 deletions testcrate/src/t1.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,30 @@ 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; }

uint32_t (*nested(uint8_t arg))(uint16_t) {
return NULL;
}

uint32_t (*nested2(uint8_t(*arg0)(uint8_t), uint16_t(*arg1)(uint16_t)))(uint16_t) {
return NULL;
}

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;

uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t) = nested;
uint32_t (*(*T1_fn_ptr_s2)(uint8_t(*arg0)(uint8_t), uint16_t(*arg1)(uint16_t)))(uint16_t) = nested2;
18 changes: 18 additions & 0 deletions testcrate/src/t1.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,22 @@ 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);

// T1_fn_ptr_nested: function pointer to a function, taking a uint8_t, and
// returning a function pointer to a function taking a uint16_t and returning a
// uint32_t
uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t);

// T1_fn_ptr_nested: function pointer to a function, taking a function pointer
// uint8_t -> uint8_t, and returning a function pointer to a function taking a
// uint16_t and returning a uint32_t
uint32_t (*(*T1_fn_ptr_s2)(uint8_t(*)(uint8_t), uint16_t(*)(uint16_t)))(uint16_t);
18 changes: 18 additions & 0 deletions testcrate/src/t1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,21 @@ 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;

pub static T1_fn_ptr_s: unsafe extern "C" fn(u8) -> extern fn(u16)->u32;
pub static T1_fn_ptr_s2: unsafe extern "C" fn(extern fn(u8)->u8,
extern fn(u16)->u16) -> extern fn(u16)->u32;
}

0 comments on commit f8bd332

Please sign in to comment.