Skip to content

Commit 276f239

Browse files
committed
Better support Dispatch in header-translator
1 parent c7f5b7f commit 276f239

File tree

6 files changed

+97
-25
lines changed

6 files changed

+97
-25
lines changed

crates/header-translator/src/availability.rs

+3
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ impl Availability {
213213
"swift" => {
214214
_swift = Some(availability);
215215
}
216+
"driverkit" => {
217+
// Ignore
218+
}
216219
platform if platform.ends_with("_app_extension") => {
217220
// Ignore availability attributes for app extensions
218221
}

crates/header-translator/src/id.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,17 @@ impl Location {
135135
// Redefined in the framework crate itself.
136136
"Darwin.MacTypes" => vec!["System".into()],
137137

138-
// Built-in
138+
// Built-ins
139139
"DarwinFoundation.types.machine_types" => vec!["System".into()],
140+
"_Builtin_stdarg.va_list" => vec!["System".into()],
140141

141142
// Libc
142143
name if name.starts_with("sys_types") => vec!["libc".into()],
143144
"DarwinFoundation.types.sys_types" => vec!["libc".into()],
145+
"DarwinFoundation.qos" => vec!["libc".into()],
144146
name if name.starts_with("Darwin.POSIX") => vec!["libc".into()],
145147
"_stdio" => vec!["libc".into()],
148+
"_time.timespec" => vec!["libc".into()],
146149

147150
// Will be moved to the `mach2` crate in `libc` v1.0
148151
name if name.starts_with("Darwin.Mach") => vec!["libc".into()],
@@ -324,7 +327,7 @@ impl<N: ToOptionString> ItemIdentifier<N> {
324327
pub fn with_name(name: N, entity: &Entity<'_>, _context: &Context<'_>) -> Self {
325328
let file = entity
326329
.get_location()
327-
.expect("entity location")
330+
.unwrap_or_else(|| panic!("no entity location: {entity:?}"))
328331
.get_expansion_location()
329332
.file
330333
.expect("expanded location file");

crates/header-translator/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ fn get_translation_unit<'i: 'c, 'c>(
353353
// "usr/include/TargetConditionals.modulemap"
354354
// "System/Library/Frameworks/CoreFoundation.framework/Modules/module.modulemap"
355355
// "usr/include/ObjectiveC.modulemap"
356+
// "usr/include/dispatch.modulemap"
356357
let modulemap =
357358
format!("System/Library/Frameworks/{framework}.framework/Modules/module.modulemap");
358359
// On Mac Catalyst, we need to try to load from System/iOSSupport first.

crates/header-translator/src/rust_type.rs

+34-16
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ pub enum Primitive {
251251
ISize,
252252
USize,
253253
PtrDiff,
254+
VaList,
254255
// Objective-C
255256
ObjcBool,
256257
NSInteger,
@@ -309,6 +310,7 @@ impl Primitive {
309310
Self::ISize => "isize",
310311
// TODO: Use core::ffi::c_size_t
311312
Self::USize => "usize",
313+
Self::VaList => "VaList",
312314
// TODO: Use core::ffi::c_ptr_diff_t
313315
Self::PtrDiff => "isize",
314316
Self::ObjcBool => "Bool",
@@ -339,14 +341,14 @@ impl ItemRef {
339341
self.required_items.clone()
340342
}
341343

342-
fn new(entity: &Entity<'_>, context: &Context<'_>) -> Self {
343-
let entity = entity
344+
fn new(entity_ref: &Entity<'_>, context: &Context<'_>) -> Self {
345+
let entity = entity_ref
344346
.get_location()
345347
.expect("itemref location")
346348
.get_entity()
347349
.expect("itemref entity");
348350

349-
let id = ItemIdentifier::new(&entity, context);
351+
let mut id = ItemIdentifier::new(&entity, context);
350352

351353
if let Some(external) = context.library(id.library_name()).external.get(&id.name) {
352354
let id = ItemIdentifier::from_raw(
@@ -375,26 +377,39 @@ impl ItemRef {
375377
})
376378
.chain(iter::once(id.clone()))
377379
.collect();
378-
Self {
380+
return Self {
379381
id,
380382
thread_safety,
381383
required_items,
382-
}
383-
} else if matches!(
384-
entity.get_kind(),
385-
EntityKind::ObjCInterfaceDecl | EntityKind::ObjCProtocolDecl
386-
) {
387-
Self {
384+
};
385+
}
386+
387+
match entity.get_kind() {
388+
EntityKind::ObjCInterfaceDecl | EntityKind::ObjCProtocolDecl => Self {
388389
id,
389390
thread_safety: ThreadSafety::from_decl(&entity, context),
390391
required_items: items_required_by_decl(&entity, context),
392+
},
393+
EntityKind::MacroExpansion => {
394+
id.name = entity_ref.get_name().unwrap_or_else(|| {
395+
error!(?entity_ref, ?entity, "macro ref did not have name");
396+
id.name
397+
});
398+
Self {
399+
id: id.clone(),
400+
// We cannot get thread safety from macro expansions
401+
thread_safety: ThreadSafety::dummy(),
402+
// Similarly, we cannot get for required items
403+
required_items: vec![id],
404+
}
391405
}
392-
} else {
393-
error!(?entity, "could not get declaration. Add appropriate external.{}.module = \"...\" to translation-config.toml", id.name);
394-
Self {
395-
id,
396-
thread_safety: ThreadSafety::dummy(),
397-
required_items: vec![],
406+
_ => {
407+
error!(?entity, "could not get declaration. Add appropriate external.{}.module = \"...\" to translation-config.toml", id.name);
408+
Self {
409+
id: id.clone(),
410+
thread_safety: ThreadSafety::dummy(),
411+
required_items: vec![id],
412+
}
398413
}
399414
}
400415
}
@@ -984,6 +999,9 @@ impl Ty {
984999
"intptr_t" => return Self::Primitive(Primitive::ISize),
9851000
"uintptr_t" => return Self::Primitive(Primitive::USize),
9861001

1002+
// Varargs, still unsupported by Rust.
1003+
"__builtin_va_list" => return Self::Primitive(Primitive::VaList),
1004+
9871005
// MacTypes.h
9881006
"UInt8" => return Self::Primitive(Primitive::U8),
9891007
"UInt16" => return Self::Primitive(Primitive::U16),

crates/header-translator/src/stmt.rs

+40-3
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ pub enum Stmt {
529529
body: Option<()>,
530530
safe: bool,
531531
must_use: bool,
532+
link_name: Option<String>,
532533
},
533534
/// typedef Type TypedefName;
534535
AliasDecl {
@@ -1059,7 +1060,10 @@ impl Stmt {
10591060
| EntityKind::ParmDecl
10601061
| EntityKind::EnumDecl
10611062
| EntityKind::IntegerLiteral => {}
1062-
_ => error!("unknown"),
1063+
EntityKind::ObjCIndependentClass => {
1064+
// TODO: Might be interesting?
1065+
}
1066+
_ => error!("unknown typedef child"),
10631067
});
10641068

10651069
let ty = entity
@@ -1212,7 +1216,19 @@ impl Stmt {
12121216
immediate_children(&entity, |entity, _span| match entity.get_kind() {
12131217
EntityKind::UnexposedAttr => {
12141218
if let Some(attr) = UnexposedAttr::parse(&entity, context) {
1215-
error!(?attr, "unknown attribute on enum constant");
1219+
match attr {
1220+
UnexposedAttr::Enum
1221+
| UnexposedAttr::Options
1222+
| UnexposedAttr::ClosedEnum
1223+
| UnexposedAttr::ErrorEnum => {
1224+
if kind.as_ref() != Some(&attr) {
1225+
error!(?kind, ?attr, "enum child had attribute that parent did not");
1226+
}
1227+
}
1228+
attr => {
1229+
error!(?attr, "unknown attribute on enum constant")
1230+
}
1231+
}
12161232
}
12171233
}
12181234
EntityKind::VisibilityAttr => {}
@@ -1367,6 +1383,7 @@ impl Stmt {
13671383
let result_type = Ty::parse_function_return(result_type, context);
13681384
let mut arguments = Vec::new();
13691385
let mut must_use = false;
1386+
let mut link_name = None;
13701387

13711388
if entity.is_static_method() {
13721389
warn!("unexpected static method");
@@ -1402,10 +1419,20 @@ impl Stmt {
14021419
EntityKind::WarnUnusedResultAttr => {
14031420
must_use = true;
14041421
}
1405-
EntityKind::PureAttr => {
1422+
EntityKind::PureAttr | EntityKind::ConstAttr => {
14061423
// Ignore, we currently have no way of marking
14071424
// external functions as pure in Rust.
14081425
}
1426+
EntityKind::AsmLabelAttr => {
1427+
let name = entity.get_name().expect("asm label to have name");
1428+
let name = if let Some(name) = name.strip_prefix('_') {
1429+
name.to_string()
1430+
} else {
1431+
error!(?name, "symbol did not start with _");
1432+
name
1433+
};
1434+
link_name = Some(name);
1435+
}
14091436
EntityKind::VisibilityAttr => {
14101437
// CG_EXTERN or UIKIT_EXTERN
14111438
}
@@ -1426,6 +1453,7 @@ impl Stmt {
14261453
body,
14271454
safe: !data.unsafe_,
14281455
must_use,
1456+
link_name,
14291457
}]
14301458
}
14311459
EntityKind::UnionDecl => {
@@ -2360,6 +2388,7 @@ impl Stmt {
23602388
body: Some(_),
23612389
safe: _,
23622390
must_use: _,
2391+
link_name: _,
23632392
} => {
23642393
write!(f, "// TODO: ")?;
23652394
write!(f, "pub fn {}(", id.name)?;
@@ -2377,6 +2406,7 @@ impl Stmt {
23772406
body: None,
23782407
safe: false,
23792408
must_use,
2409+
link_name,
23802410
} => {
23812411
// Functions are always C-unwind, since we don't know
23822412
// anything about them.
@@ -2387,6 +2417,9 @@ impl Stmt {
23872417
if *must_use {
23882418
writeln!(f, " #[must_use]")?;
23892419
}
2420+
if let Some(link_name) = link_name {
2421+
writeln!(f, " #[link_name = {link_name:?}]")?;
2422+
}
23902423
write!(f, " pub fn {}(", id.name)?;
23912424
for (param, arg_ty) in arguments {
23922425
let param = handle_reserved(&crate::to_snake_case(param));
@@ -2405,6 +2438,7 @@ impl Stmt {
24052438
body: None,
24062439
safe: true,
24072440
must_use,
2441+
link_name,
24082442
} => {
24092443
write!(f, "{}", self.cfg_gate_ln(config))?;
24102444
write!(f, "{availability}")?;
@@ -2421,6 +2455,9 @@ impl Stmt {
24212455

24222456
writeln!(f, " extern \"C-unwind\" {{")?;
24232457

2458+
if let Some(link_name) = link_name {
2459+
writeln!(f, " #[link_name = {link_name:?}]")?;
2460+
}
24242461
write!(f, " fn {}(", id.name)?;
24252462
for (param, arg_ty) in arguments {
24262463
let param = handle_reserved(&crate::to_snake_case(param));

crates/header-translator/src/unexposed_attr.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ impl UnexposedAttr {
3737
get_arguments: impl FnOnce() -> T,
3838
) -> Result<Option<Self>, ()> {
3939
Ok(match s {
40-
"NS_ENUM" | "CF_ENUM" => {
40+
"CF_ENUM" | "DISPATCH_ENUM" | "NS_ENUM" => {
4141
let _ = get_arguments();
4242
Some(Self::Enum)
4343
}
44-
"NS_OPTIONS" | "CF_OPTIONS" => {
44+
"CF_OPTIONS" | "DISPATCH_OPTIONS" | "NS_OPTIONS" => {
4545
let _ = get_arguments();
4646
Some(Self::Options)
4747
}
@@ -84,6 +84,8 @@ impl UnexposedAttr {
8484
let _ = get_arguments();
8585
None
8686
}
87+
// Nullability attributes
88+
s if s.starts_with("DISPATCH_NONNULL") => None,
8789
"NS_SWIFT_SENDABLE" | "AS_SWIFT_SENDABLE" | "CM_SWIFT_SENDABLE"
8890
| "CV_SWIFT_SENDABLE" => Some(Self::Sendable),
8991
"NS_SWIFT_NONSENDABLE" | "CM_SWIFT_NONSENDABLE" | "CV_SWIFT_NONSENDABLE" => {
@@ -97,14 +99,14 @@ impl UnexposedAttr {
9799
let _ = get_arguments();
98100
None
99101
}
100-
"CF_NOESCAPE" | "NS_NOESCAPE" => Some(Self::NoEscape),
102+
"CF_NOESCAPE" | "DISPATCH_NOESCAPE" | "NS_NOESCAPE" => Some(Self::NoEscape),
101103
// TODO: We could potentially automatically elide this argument
102104
// from the method call, though it's rare enough that it's
103105
// probably not really worth the effort.
104106
"__unused" => None,
105107
// We assume that a function is inline if it has a body, so not
106108
// interesting.
107-
"CF_INLINE" | "NS_INLINE" => None,
109+
"CF_INLINE" | "DISPATCH_ALWAYS_INLINE" | "NS_INLINE" => None,
108110
// We don't synthethize properties, so irrelevant for us.
109111
"NS_REQUIRES_PROPERTY_DEFINITIONS" => None,
110112
// Weak specifiers - would be interesting if Rust supported weak statics
@@ -159,6 +161,8 @@ impl UnexposedAttr {
159161
| "CT_ENUM_UNAVAILABLE"
160162
| "CT_UNAVAILABLE"
161163
| "COREVIDEO_GL_DEPRECATED"
164+
| "DISPATCH_SWIFT_UNAVAILABLE"
165+
| "DISPATCH_ENUM_API_AVAILABLE"
162166
| "EVENTKITUI_CLASS_AVAILABLE"
163167
| "FPUI_AVAILABLE"
164168
| "MLCOMPUTE_AVAILABLE_STARTING"
@@ -239,6 +243,7 @@ impl UnexposedAttr {
239243
| "CB_CM_API_AVAILABLE"
240244
| "deprecated"
241245
| "DEPRECATED_ATTRIBUTE"
246+
| "DISPATCH_UNAVAILABLE"
242247
| "INTERAPP_AUDIO_DEPRECATED"
243248
| "MIDICI1_0"
244249
| "MIDICI1_1"
@@ -279,9 +284,14 @@ impl UnexposedAttr {
279284
}
280285
"CF_IMPLICIT_BRIDGING_ENABLED"
281286
| "CF_REFINED_FOR_SWIFT"
287+
| "DISPATCH_REFINED_FOR_SWIFT"
282288
| "NS_REFINED_FOR_SWIFT"
283289
| "NS_SWIFT_DISABLE_ASYNC"
290+
| "DISPATCH_NOTHROW"
284291
| "NS_SWIFT_NOTHROW" => None,
292+
// Possibly interesting?
293+
"DISPATCH_COLD" => None,
294+
"DISPATCH_MALLOC" => None,
285295
"CF_CONSUMED"
286296
| "CF_RELEASES_ARGUMENT"
287297
| "NS_RELEASES_ARGUMENT"

0 commit comments

Comments
 (0)