Skip to content

Commit

Permalink
Better support Dispatch in header-translator
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Dec 17, 2024
1 parent c7f5b7f commit 276f239
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 25 deletions.
3 changes: 3 additions & 0 deletions crates/header-translator/src/availability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ impl Availability {
"swift" => {
_swift = Some(availability);
}
"driverkit" => {
// Ignore
}
platform if platform.ends_with("_app_extension") => {
// Ignore availability attributes for app extensions
}
Expand Down
7 changes: 5 additions & 2 deletions crates/header-translator/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,17 @@ impl Location {
// Redefined in the framework crate itself.
"Darwin.MacTypes" => vec!["System".into()],

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

// Libc
name if name.starts_with("sys_types") => vec!["libc".into()],
"DarwinFoundation.types.sys_types" => vec!["libc".into()],
"DarwinFoundation.qos" => vec!["libc".into()],
name if name.starts_with("Darwin.POSIX") => vec!["libc".into()],
"_stdio" => vec!["libc".into()],
"_time.timespec" => vec!["libc".into()],

// Will be moved to the `mach2` crate in `libc` v1.0
name if name.starts_with("Darwin.Mach") => vec!["libc".into()],
Expand Down Expand Up @@ -324,7 +327,7 @@ impl<N: ToOptionString> ItemIdentifier<N> {
pub fn with_name(name: N, entity: &Entity<'_>, _context: &Context<'_>) -> Self {
let file = entity
.get_location()
.expect("entity location")
.unwrap_or_else(|| panic!("no entity location: {entity:?}"))
.get_expansion_location()
.file
.expect("expanded location file");
Expand Down
1 change: 1 addition & 0 deletions crates/header-translator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ fn get_translation_unit<'i: 'c, 'c>(
// "usr/include/TargetConditionals.modulemap"
// "System/Library/Frameworks/CoreFoundation.framework/Modules/module.modulemap"
// "usr/include/ObjectiveC.modulemap"
// "usr/include/dispatch.modulemap"
let modulemap =
format!("System/Library/Frameworks/{framework}.framework/Modules/module.modulemap");
// On Mac Catalyst, we need to try to load from System/iOSSupport first.
Expand Down
50 changes: 34 additions & 16 deletions crates/header-translator/src/rust_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ pub enum Primitive {
ISize,
USize,
PtrDiff,
VaList,
// Objective-C
ObjcBool,
NSInteger,
Expand Down Expand Up @@ -309,6 +310,7 @@ impl Primitive {
Self::ISize => "isize",
// TODO: Use core::ffi::c_size_t
Self::USize => "usize",
Self::VaList => "VaList",
// TODO: Use core::ffi::c_ptr_diff_t
Self::PtrDiff => "isize",
Self::ObjcBool => "Bool",
Expand Down Expand Up @@ -339,14 +341,14 @@ impl ItemRef {
self.required_items.clone()
}

fn new(entity: &Entity<'_>, context: &Context<'_>) -> Self {
let entity = entity
fn new(entity_ref: &Entity<'_>, context: &Context<'_>) -> Self {
let entity = entity_ref
.get_location()
.expect("itemref location")
.get_entity()
.expect("itemref entity");

let id = ItemIdentifier::new(&entity, context);
let mut id = ItemIdentifier::new(&entity, context);

if let Some(external) = context.library(id.library_name()).external.get(&id.name) {
let id = ItemIdentifier::from_raw(
Expand Down Expand Up @@ -375,26 +377,39 @@ impl ItemRef {
})
.chain(iter::once(id.clone()))
.collect();
Self {
return Self {
id,
thread_safety,
required_items,
}
} else if matches!(
entity.get_kind(),
EntityKind::ObjCInterfaceDecl | EntityKind::ObjCProtocolDecl
) {
Self {
};
}

match entity.get_kind() {
EntityKind::ObjCInterfaceDecl | EntityKind::ObjCProtocolDecl => Self {
id,
thread_safety: ThreadSafety::from_decl(&entity, context),
required_items: items_required_by_decl(&entity, context),
},
EntityKind::MacroExpansion => {
id.name = entity_ref.get_name().unwrap_or_else(|| {
error!(?entity_ref, ?entity, "macro ref did not have name");
id.name
});
Self {
id: id.clone(),
// We cannot get thread safety from macro expansions
thread_safety: ThreadSafety::dummy(),
// Similarly, we cannot get for required items
required_items: vec![id],
}
}
} else {
error!(?entity, "could not get declaration. Add appropriate external.{}.module = \"...\" to translation-config.toml", id.name);
Self {
id,
thread_safety: ThreadSafety::dummy(),
required_items: vec![],
_ => {
error!(?entity, "could not get declaration. Add appropriate external.{}.module = \"...\" to translation-config.toml", id.name);
Self {
id: id.clone(),
thread_safety: ThreadSafety::dummy(),
required_items: vec![id],
}
}
}
}
Expand Down Expand Up @@ -984,6 +999,9 @@ impl Ty {
"intptr_t" => return Self::Primitive(Primitive::ISize),
"uintptr_t" => return Self::Primitive(Primitive::USize),

// Varargs, still unsupported by Rust.
"__builtin_va_list" => return Self::Primitive(Primitive::VaList),

// MacTypes.h
"UInt8" => return Self::Primitive(Primitive::U8),
"UInt16" => return Self::Primitive(Primitive::U16),
Expand Down
43 changes: 40 additions & 3 deletions crates/header-translator/src/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ pub enum Stmt {
body: Option<()>,
safe: bool,
must_use: bool,
link_name: Option<String>,
},
/// typedef Type TypedefName;
AliasDecl {
Expand Down Expand Up @@ -1059,7 +1060,10 @@ impl Stmt {
| EntityKind::ParmDecl
| EntityKind::EnumDecl
| EntityKind::IntegerLiteral => {}
_ => error!("unknown"),
EntityKind::ObjCIndependentClass => {
// TODO: Might be interesting?
}
_ => error!("unknown typedef child"),
});

let ty = entity
Expand Down Expand Up @@ -1212,7 +1216,19 @@ impl Stmt {
immediate_children(&entity, |entity, _span| match entity.get_kind() {
EntityKind::UnexposedAttr => {
if let Some(attr) = UnexposedAttr::parse(&entity, context) {
error!(?attr, "unknown attribute on enum constant");
match attr {
UnexposedAttr::Enum
| UnexposedAttr::Options
| UnexposedAttr::ClosedEnum
| UnexposedAttr::ErrorEnum => {
if kind.as_ref() != Some(&attr) {
error!(?kind, ?attr, "enum child had attribute that parent did not");
}
}
attr => {
error!(?attr, "unknown attribute on enum constant")
}
}
}
}
EntityKind::VisibilityAttr => {}
Expand Down Expand Up @@ -1367,6 +1383,7 @@ impl Stmt {
let result_type = Ty::parse_function_return(result_type, context);
let mut arguments = Vec::new();
let mut must_use = false;
let mut link_name = None;

if entity.is_static_method() {
warn!("unexpected static method");
Expand Down Expand Up @@ -1402,10 +1419,20 @@ impl Stmt {
EntityKind::WarnUnusedResultAttr => {
must_use = true;
}
EntityKind::PureAttr => {
EntityKind::PureAttr | EntityKind::ConstAttr => {
// Ignore, we currently have no way of marking
// external functions as pure in Rust.
}
EntityKind::AsmLabelAttr => {
let name = entity.get_name().expect("asm label to have name");
let name = if let Some(name) = name.strip_prefix('_') {
name.to_string()
} else {
error!(?name, "symbol did not start with _");
name
};
link_name = Some(name);
}
EntityKind::VisibilityAttr => {
// CG_EXTERN or UIKIT_EXTERN
}
Expand All @@ -1426,6 +1453,7 @@ impl Stmt {
body,
safe: !data.unsafe_,
must_use,
link_name,
}]
}
EntityKind::UnionDecl => {
Expand Down Expand Up @@ -2360,6 +2388,7 @@ impl Stmt {
body: Some(_),
safe: _,
must_use: _,
link_name: _,
} => {
write!(f, "// TODO: ")?;
write!(f, "pub fn {}(", id.name)?;
Expand All @@ -2377,6 +2406,7 @@ impl Stmt {
body: None,
safe: false,
must_use,
link_name,
} => {
// Functions are always C-unwind, since we don't know
// anything about them.
Expand All @@ -2387,6 +2417,9 @@ impl Stmt {
if *must_use {
writeln!(f, " #[must_use]")?;
}
if let Some(link_name) = link_name {
writeln!(f, " #[link_name = {link_name:?}]")?;
}
write!(f, " pub fn {}(", id.name)?;
for (param, arg_ty) in arguments {
let param = handle_reserved(&crate::to_snake_case(param));
Expand All @@ -2405,6 +2438,7 @@ impl Stmt {
body: None,
safe: true,
must_use,
link_name,
} => {
write!(f, "{}", self.cfg_gate_ln(config))?;
write!(f, "{availability}")?;
Expand All @@ -2421,6 +2455,9 @@ impl Stmt {

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

if let Some(link_name) = link_name {
writeln!(f, " #[link_name = {link_name:?}]")?;
}
write!(f, " fn {}(", id.name)?;
for (param, arg_ty) in arguments {
let param = handle_reserved(&crate::to_snake_case(param));
Expand Down
18 changes: 14 additions & 4 deletions crates/header-translator/src/unexposed_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ impl UnexposedAttr {
get_arguments: impl FnOnce() -> T,
) -> Result<Option<Self>, ()> {
Ok(match s {
"NS_ENUM" | "CF_ENUM" => {
"CF_ENUM" | "DISPATCH_ENUM" | "NS_ENUM" => {
let _ = get_arguments();
Some(Self::Enum)
}
"NS_OPTIONS" | "CF_OPTIONS" => {
"CF_OPTIONS" | "DISPATCH_OPTIONS" | "NS_OPTIONS" => {
let _ = get_arguments();
Some(Self::Options)
}
Expand Down Expand Up @@ -84,6 +84,8 @@ impl UnexposedAttr {
let _ = get_arguments();
None
}
// Nullability attributes
s if s.starts_with("DISPATCH_NONNULL") => None,
"NS_SWIFT_SENDABLE" | "AS_SWIFT_SENDABLE" | "CM_SWIFT_SENDABLE"
| "CV_SWIFT_SENDABLE" => Some(Self::Sendable),
"NS_SWIFT_NONSENDABLE" | "CM_SWIFT_NONSENDABLE" | "CV_SWIFT_NONSENDABLE" => {
Expand All @@ -97,14 +99,14 @@ impl UnexposedAttr {
let _ = get_arguments();
None
}
"CF_NOESCAPE" | "NS_NOESCAPE" => Some(Self::NoEscape),
"CF_NOESCAPE" | "DISPATCH_NOESCAPE" | "NS_NOESCAPE" => Some(Self::NoEscape),
// TODO: We could potentially automatically elide this argument
// from the method call, though it's rare enough that it's
// probably not really worth the effort.
"__unused" => None,
// We assume that a function is inline if it has a body, so not
// interesting.
"CF_INLINE" | "NS_INLINE" => None,
"CF_INLINE" | "DISPATCH_ALWAYS_INLINE" | "NS_INLINE" => None,
// We don't synthethize properties, so irrelevant for us.
"NS_REQUIRES_PROPERTY_DEFINITIONS" => None,
// Weak specifiers - would be interesting if Rust supported weak statics
Expand Down Expand Up @@ -159,6 +161,8 @@ impl UnexposedAttr {
| "CT_ENUM_UNAVAILABLE"
| "CT_UNAVAILABLE"
| "COREVIDEO_GL_DEPRECATED"
| "DISPATCH_SWIFT_UNAVAILABLE"
| "DISPATCH_ENUM_API_AVAILABLE"
| "EVENTKITUI_CLASS_AVAILABLE"
| "FPUI_AVAILABLE"
| "MLCOMPUTE_AVAILABLE_STARTING"
Expand Down Expand Up @@ -239,6 +243,7 @@ impl UnexposedAttr {
| "CB_CM_API_AVAILABLE"
| "deprecated"
| "DEPRECATED_ATTRIBUTE"
| "DISPATCH_UNAVAILABLE"
| "INTERAPP_AUDIO_DEPRECATED"
| "MIDICI1_0"
| "MIDICI1_1"
Expand Down Expand Up @@ -279,9 +284,14 @@ impl UnexposedAttr {
}
"CF_IMPLICIT_BRIDGING_ENABLED"
| "CF_REFINED_FOR_SWIFT"
| "DISPATCH_REFINED_FOR_SWIFT"
| "NS_REFINED_FOR_SWIFT"
| "NS_SWIFT_DISABLE_ASYNC"
| "DISPATCH_NOTHROW"
| "NS_SWIFT_NOTHROW" => None,
// Possibly interesting?
"DISPATCH_COLD" => None,
"DISPATCH_MALLOC" => None,
"CF_CONSUMED"
| "CF_RELEASES_ARGUMENT"
| "NS_RELEASES_ARGUMENT"
Expand Down

0 comments on commit 276f239

Please sign in to comment.