Skip to content

Commit c32f782

Browse files
authored
Merge pull request rust-lang#39 from gnzlbg/rs2c
Minimal support for fn types in extern statics
2 parents 6876698 + b6c4720 commit c32f782

File tree

4 files changed

+109
-9
lines changed

4 files changed

+109
-9
lines changed

ctest/src/lib.rs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ impl<'a> Generator<'a> {
932932
"i16" => "int16_t".to_string(),
933933
"i32" => "int32_t".to_string(),
934934
"i64" => "int64_t".to_string(),
935-
935+
"( )" => "void".to_string(),
936936
s => (self.opts.type_name)(s, self.structs.contains(s), self.unions.contains(s)),
937937
}
938938
}
@@ -1198,17 +1198,43 @@ impl<'a> Generator<'a> {
11981198
self.tests.push(format!("fn_{}", name));
11991199
}
12001200

1201-
fn test_extern_static(&mut self, name: &str, rust_ty: &str, mutbl: bool) {
1201+
fn test_extern_static(&mut self, name: &str, cname: Option<String>,
1202+
rust_ty: &str, c_ty: &str, mutbl: bool) {
12021203
if (self.opts.skip_static)(name) {
12031204
return
12041205
}
1205-
let c_ty = self.rust_ty_to_c_ty(rust_ty);
1206+
1207+
let cname = cname.unwrap_or_else(|| name.to_string());
1208+
1209+
if rust_ty.contains("extern fn") {
1210+
let c_ty = c_ty.replacen("(*)", &format!("(* __test_static_{}(void))", name), 1);
1211+
t!(writeln!(self.c, r#"
1212+
{ty} {{
1213+
return {cname};
1214+
}}
1215+
"#, ty = c_ty, cname = cname));
1216+
t!(writeln!(self.rust, r#"
1217+
#[inline(never)]
1218+
fn static_{name}() {{
1219+
extern {{
1220+
fn __test_static_{name}() -> {ty};
1221+
}}
1222+
unsafe {{
1223+
same({name} as usize,
1224+
__test_static_{name}() as usize,
1225+
"{name} static");
1226+
}}
1227+
}}
1228+
"#, name = name, ty = rust_ty));
1229+
} else {
1230+
let c_ty = self.rust_ty_to_c_ty(rust_ty);
12061231
t!(writeln!(self.c, r#"
12071232
{mutbl}{ty}* __test_static_{name}(void) {{
1208-
return &{name};
1233+
return &{cname};
12091234
}}
1210-
"#, mutbl = if mutbl { "" } else { "const " }, ty = c_ty, name = name));
1211-
t!(writeln!(self.rust, r#"
1235+
"#, mutbl = if mutbl { "" } else { "const " }, ty = c_ty,
1236+
name = name, cname = cname));
1237+
t!(writeln!(self.rust, r#"
12121238
#[inline(never)]
12131239
fn static_{name}() {{
12141240
extern {{
@@ -1221,6 +1247,7 @@ impl<'a> Generator<'a> {
12211247
}}
12221248
}}
12231249
"#, name = name, mutbl = if mutbl { "mut" } else { "const" }, ty = rust_ty));
1250+
};
12241251
self.tests.push(format!("static_{}", name));
12251252
}
12261253

@@ -1290,7 +1317,13 @@ impl<'a> Generator<'a> {
12901317
if args.len() == 0 {
12911318
args.push("void".to_string());
12921319
}
1293-
format!("{}(*)({})", ret, args.join(", "))
1320+
1321+
let s = if ret.contains("(*)") {
1322+
ret.replace("(*)", &format!("(*(*)({}))", args.join(", ")))
1323+
} else {
1324+
format!("{}(*)({})", ret, args.join(", "))
1325+
};
1326+
s
12941327
}
12951328
}
12961329
ast::TyKind::Array(ref t, ref e) => {
@@ -1329,6 +1362,7 @@ impl<'a> Generator<'a> {
13291362
format!("char*")
13301363
}
13311364
}
1365+
ast::TyKind::Tup(ref v) if v.is_empty() => if rust { "()".to_string() } else { "void".to_string() },
13321366
_ => panic!("unknown ty {:?}", ty),
13331367
}
13341368
}
@@ -1518,8 +1552,11 @@ impl<'a, 'v> Visitor<'v> for Generator<'a> {
15181552
variadic, abi);
15191553
}
15201554
ast::ForeignItemKind::Static(ref ty, mutbl) => {
1521-
let ty = self.ty2name(&ty, true);
1522-
self.test_extern_static(&i.ident.to_string(), &ty, mutbl);
1555+
let rust_ty = self.ty2name(&ty, true);
1556+
let c_ty = self.ty2name(&ty, false);
1557+
let cname = attr::first_attr_value_str_by_name(&i.attrs, "link_name")
1558+
.map(|i| i.to_string());
1559+
self.test_extern_static(&i.ident.to_string(), cname, &rust_ty, &c_ty, mutbl);
15231560
}
15241561
}
15251562
visit::walk_foreign_item(self, i)

ctest/testcrate/src/t1.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,30 @@ void T1h(const int32_t a[4]) {}
1212
void T1i(int32_t a[4]) {}
1313
void T1j(int32_t a[4]) {}
1414
unsigned T1static = 3;
15+
16+
const uint8_t T1_static_u8 = 42;
17+
uint8_t T1_static_mut_u8 = 37;
18+
19+
20+
uint8_t foo(uint8_t a, uint8_t b) { return a + b; }
21+
void bar(uint8_t a) { return; }
22+
void baz(void) { return; }
23+
24+
uint32_t (*nested(uint8_t arg))(uint16_t) {
25+
return NULL;
26+
}
27+
28+
uint32_t (*nested2(uint8_t(*arg0)(uint8_t), uint16_t(*arg1)(uint16_t)))(uint16_t) {
29+
return NULL;
30+
}
31+
32+
uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t) = foo;
33+
uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t) = foo;
34+
void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t) = bar;
35+
void (*const T1_static_const_fn_ptr_unsafe3)(void) = baz;
36+
37+
const uint8_t T1_static_right = 7;
38+
uint8_t (*T1_static_right2)(uint8_t, uint8_t) = foo;
39+
40+
uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t) = nested;
41+
uint32_t (*(*T1_fn_ptr_s2)(uint8_t(*arg0)(uint8_t), uint16_t(*arg1)(uint16_t)))(uint16_t) = nested2;

ctest/testcrate/src/t1.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,22 @@ void T1j(int32_t a[4]);
4747
#define T1C 4
4848

4949
extern uint32_t T1static;
50+
const uint8_t T1_static_u8;
51+
uint8_t T1_static_mut_u8;
52+
uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t);
53+
uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t);
54+
void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t);
55+
void (*const T1_static_const_fn_ptr_unsafe3)(void);
5056

57+
const uint8_t T1_static_right;
58+
uint8_t (*T1_static_right2)(uint8_t, uint8_t);
59+
60+
// T1_fn_ptr_nested: function pointer to a function, taking a uint8_t, and
61+
// returning a function pointer to a function taking a uint16_t and returning a
62+
// uint32_t
63+
uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t);
64+
65+
// T1_fn_ptr_nested: function pointer to a function, taking a function pointer
66+
// uint8_t -> uint8_t, and returning a function pointer to a function taking a
67+
// uint16_t and returning a uint32_t
68+
uint32_t (*(*T1_fn_ptr_s2)(uint8_t(*)(uint8_t), uint16_t(*)(uint16_t)))(uint16_t);

ctest/testcrate/src/t1.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,21 @@ extern {
7171
pub fn foo() {
7272
assert_eq!(1, 1);
7373
}
74+
75+
extern "C" {
76+
pub static T1_static_u8: u8;
77+
pub static mut T1_static_mut_u8: u8;
78+
pub static mut T1_static_mut_fn_ptr: extern "C" fn(u8, u8) -> u8;
79+
pub static T1_static_const_fn_ptr_unsafe: unsafe extern "C" fn(u8, u8) -> u8;
80+
pub static T1_static_const_fn_ptr_unsafe2: unsafe extern "C" fn(u8) -> ();
81+
pub static T1_static_const_fn_ptr_unsafe3: unsafe extern "C" fn() -> ();
82+
83+
#[link_name = "T1_static_right"]
84+
pub static T1_static_wrong: u8;
85+
#[link_name = "T1_static_right2"]
86+
pub static mut T1_static_wrong2: extern "C" fn(u8, u8) -> u8;
87+
88+
pub static T1_fn_ptr_s: unsafe extern "C" fn(u8) -> extern fn(u16)->u32;
89+
pub static T1_fn_ptr_s2: unsafe extern "C" fn(extern fn(u8)->u8,
90+
extern fn(u16)->u16) -> extern fn(u16)->u32;
91+
}

0 commit comments

Comments
 (0)