From a9933ec6f3f7872b3c7213c0bae95be8aebc7a7c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 2 Dec 2023 22:49:59 +0100 Subject: [PATCH 1/6] Allow creating and loading instance variables with the same name --- Cargo.lock | 16 + crates/objc2/CHANGELOG.md | 20 ++ crates/objc2/Cargo.toml | 1 + crates/objc2/examples/class_with_lifetime.rs | 45 ++- crates/objc2/examples/introspection.rs | 6 +- crates/objc2/src/declare/ivar.rs | 20 +- crates/objc2/src/declare/mod.rs | 174 ++++++++++- crates/objc2/src/runtime/mod.rs | 288 +++++++++-------- crates/objc2/src/test_utils.rs | 14 +- crates/objc2/tests/declare_class.rs | 67 +--- .../expected/apple-aarch64.s | 290 +++++++----------- .../expected/apple-armv7s.s | 180 ++++------- .../expected/apple-old-x86.s | 279 +++++++---------- .../test_declare_class/expected/apple-x86.s | 279 +++++++---------- .../expected/apple-x86_64.s | 122 ++++---- crates/tests/src/test_object.rs | 18 +- 16 files changed, 857 insertions(+), 962 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f1968698e..c935d3617 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,6 +34,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "basic-toml" version = "0.1.7" @@ -279,6 +285,15 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -302,6 +317,7 @@ version = "0.4.1" dependencies = [ "iai", "malloc_buf", + "memoffset", "objc-sys", "objc2-encode", "objc2-proc-macros", diff --git a/crates/objc2/CHANGELOG.md b/crates/objc2/CHANGELOG.md index e9ccd18fd..c3ab4498d 100644 --- a/crates/objc2/CHANGELOG.md +++ b/crates/objc2/CHANGELOG.md @@ -85,6 +85,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). implement `IsAllowedMutable`. * Disallow the ability to use non-`Self`-like types as the receiver in `declare_class!`. +* Allow adding instance variables with the same name on Apple platforms. +* **BREAKING**: Make loading instance variables robust and sound in the face + of instance variables with the same name. + + To read or write the instance variable for an object, you should now use the + `load`, `load_ptr` and `load_mut` methods on `Ivar`, instead of the `ivar`, + `ivar_ptr` and `ivar_mut` methods on `AnyObject`. + + This _is_ more verbose, but it also ensures that the class for the instance + variable you're loading is the same as the one the instance variable you + want to access is defined on. + + ```rust + // Before + let number = unsafe { *obj.ivar::("number") }; + + // After + let ivar = cls.instance_variable("number").unwrap(); + let number = unsafe { *ivar.load::(&obj) }; + ``` ### Removed * **BREAKING**: Removed `ProtocolType` implementation for `NSObject`. diff --git a/crates/objc2/Cargo.toml b/crates/objc2/Cargo.toml index fd3e781d4..05df438de 100644 --- a/crates/objc2/Cargo.toml +++ b/crates/objc2/Cargo.toml @@ -108,6 +108,7 @@ objc2-proc-macros = { path = "../objc2-proc-macros", version = "0.1.1", optional [dev-dependencies] iai = { version = "0.1", git = "https://github.com/madsmtm/iai", branch = "callgrind" } static_assertions = "1.1.0" +memoffset = "0.9.0" [[bench]] name = "autorelease" diff --git a/crates/objc2/examples/class_with_lifetime.rs b/crates/objc2/examples/class_with_lifetime.rs index 54410530d..50d9ca844 100644 --- a/crates/objc2/examples/class_with_lifetime.rs +++ b/crates/objc2/examples/class_with_lifetime.rs @@ -4,36 +4,19 @@ use std::marker::PhantomData; use std::sync::Once; -use objc2::declare::{ClassBuilder, Ivar, IvarEncode, IvarType}; +use objc2::declare::ClassBuilder; use objc2::mutability::Mutable; use objc2::rc::Id; use objc2::runtime::{AnyClass, NSObject, Sel}; use objc2::{msg_send, msg_send_id, sel}; use objc2::{ClassType, Encoding, Message, RefEncode}; -/// Helper type for the instance variable -struct NumberIvar<'a> { - // Doesn't actually matter what we put here, but we have to use the - // lifetime parameter somehow - p: PhantomData<&'a mut u8>, -} - -unsafe impl<'a> IvarType for NumberIvar<'a> { - type Type = IvarEncode<&'a mut u8>; - const NAME: &'static str = "_number_ptr"; -} - /// Struct that represents our custom object. #[repr(C)] pub struct MyObject<'a> { // Required to give MyObject the proper layout superclass: NSObject, - // SAFETY: The ivar is declared below, and is properly initialized in the - // designated initializer. - // - // Note! Attempting to acess the ivar before it has been initialized is - // undefined behaviour! - number: Ivar>, + p: PhantomData<&'a mut u8>, } unsafe impl RefEncode for MyObject<'_> { @@ -50,8 +33,12 @@ impl<'a> MyObject<'a> { ) -> Option<&'s mut Self> { let this: Option<&mut Self> = unsafe { msg_send![super(self), init] }; this.map(|this| { - // Properly initialize the number reference - Ivar::write(&mut this.number, ptr.expect("got NULL number ptr")); + let ivar = Self::class().instance_variable("number").unwrap(); + // SAFETY: The ivar is added with the same type below + unsafe { + ivar.load_ptr::<&mut u8>(&this.superclass) + .write(ptr.expect("got NULL number ptr")) + }; this }) } @@ -62,12 +49,16 @@ impl<'a> MyObject<'a> { unsafe { msg_send_id![Self::alloc(), initWithPtr: number] } } - pub fn get(&self) -> &u8 { - &self.number + pub fn get(&self) -> u8 { + let ivar = Self::class().instance_variable("number").unwrap(); + // SAFETY: The ivar is added with the same type below, and is initialized in `init_with_ptr` + unsafe { **ivar.load::<&mut u8>(&self.superclass) } } pub fn set(&mut self, number: u8) { - **self.number = number; + let ivar = Self::class().instance_variable("number").unwrap(); + // SAFETY: The ivar is added with the same type below, and is initialized in `init_with_ptr` + unsafe { **ivar.load_mut::<&mut u8>(&mut self.superclass) = number }; } } @@ -84,7 +75,7 @@ unsafe impl<'a> ClassType for MyObject<'a> { let superclass = NSObject::class(); let mut builder = ClassBuilder::new(Self::NAME, superclass).unwrap(); - builder.add_static_ivar::>(); + builder.add_ivar::<&mut u8>("number"); unsafe { builder.add_method( @@ -112,7 +103,7 @@ fn main() { let mut number = 54; let mut obj = MyObject::new(&mut number); - assert_eq!(*obj.get(), 54); + assert_eq!(obj.get(), 54); // It is not possible to convert to `Id`, since that would loose // the lifetime information that `MyObject` stores. @@ -131,7 +122,7 @@ fn main() { // But we can now mutate the referenced `number` obj.set(7); - assert_eq!(*obj.get(), 7); + assert_eq!(obj.get(), 7); drop(obj); // And now that we've dropped `obj`, we can access `number` again diff --git a/crates/objc2/examples/introspection.rs b/crates/objc2/examples/introspection.rs index 66f62c3f9..a7c8109b0 100644 --- a/crates/objc2/examples/introspection.rs +++ b/crates/objc2/examples/introspection.rs @@ -49,9 +49,7 @@ fn main() { println!("NSObject address: {obj:p}"); - // Access an ivar of the object - // - // As before, you should not rely on the `isa` ivar being available! - let isa = unsafe { *obj.ivar::<*const AnyClass>("isa") }; + // Read an ivar on the object + let isa: *const AnyClass = unsafe { *ivar.load(&obj) }; println!("NSObject isa: {isa:?}"); } diff --git a/crates/objc2/src/declare/ivar.rs b/crates/objc2/src/declare/ivar.rs index d9dbedd74..d89b32a6e 100644 --- a/crates/objc2/src/declare/ivar.rs +++ b/crates/objc2/src/declare/ivar.rs @@ -5,7 +5,7 @@ use core::ops::{Deref, DerefMut}; use core::ptr::{self, NonNull}; use crate::encode::Encode; -use crate::runtime::{ivar_offset, AnyObject}; +use crate::runtime::AnyObject; pub(crate) mod private { pub trait Sealed {} @@ -92,9 +92,13 @@ pub unsafe trait IvarType { const NAME: &'static str; #[doc(hidden)] - unsafe fn __offset(ptr: NonNull) -> isize { - let obj = unsafe { ptr.as_ref() }; - ivar_offset(obj.class(), Self::NAME, &Self::Type::ENCODING) + unsafe fn __ivar_ptr(ptr: NonNull) -> NonNull { + // FIXME: This is currently unsound! Looking up the instance variable + // dynamically will return the wrong variable if two variables with + // the same name exist. + let ivar = unsafe { ptr.as_ref() }.lookup_instance_variable_dynamically(Self::NAME); + ivar.debug_assert_encoding(&Self::Type::ENCODING); + unsafe { AnyObject::ivar_at_offset(ptr, ivar.offset()) } } } @@ -215,9 +219,7 @@ impl Ivar { // Note: We technically don't have provenance over the object, nor the // ivar, but the object doesn't have provenance over the ivar either, // so that is fine. - let offset = unsafe { T::__offset(ptr) }; - // SAFETY: The offset is valid - unsafe { AnyObject::ivar_at_offset::(ptr, offset) } + unsafe { T::__ivar_ptr(ptr) } } /// Get a mutable pointer to the instance variable. @@ -238,9 +240,7 @@ impl Ivar { let ptr: NonNull = NonNull::from(self).cast(); // SAFETY: Same as `as_inner_ptr` - let offset = unsafe { T::__offset(ptr) }; - // SAFETY: The offset is valid - unsafe { AnyObject::ivar_at_offset::(ptr, offset) } + unsafe { T::__ivar_ptr(ptr) } } /// Sets the value of the instance variable. diff --git a/crates/objc2/src/declare/mod.rs b/crates/objc2/src/declare/mod.rs index 490da7310..44c6adefe 100644 --- a/crates/objc2/src/declare/mod.rs +++ b/crates/objc2/src/declare/mod.rs @@ -96,8 +96,9 @@ impl Log2Alignment for T { /// ) -> Option<&mut AnyObject> { /// let this: Option<&mut AnyObject> = msg_send![super(this, NSObject::class()), init]; /// this.map(|this| { +/// let ivar = AnyClass::get("MyNumber").unwrap().instance_variable("_number").unwrap(); /// // SAFETY: The ivar is added with the same type above -/// this.set_ivar::>("_number", Cell::new(number)); +/// *ivar.load_mut::>(this) = Cell::new(number); /// this /// }) /// } @@ -131,8 +132,9 @@ impl Log2Alignment for T { /// /// // Add an Objective-C method for setting the number /// extern "C" fn my_number_set(this: &NSObject, _cmd: Sel, number: u32) { +/// let ivar = AnyClass::get("MyNumber").unwrap().instance_variable("_number").unwrap(); /// // SAFETY: The ivar is added with the same type above -/// unsafe { this.ivar::>("_number") }.set(number); +/// unsafe { ivar.load::>(this) }.set(number); /// } /// unsafe { /// builder.add_method(sel!(setNumber:), my_number_set as extern "C" fn(_, _, _)); @@ -140,8 +142,9 @@ impl Log2Alignment for T { /// /// // Add an Objective-C method for getting the number /// extern "C" fn my_number_get(this: &NSObject, _cmd: Sel) -> u32 { +/// let ivar = AnyClass::get("MyNumber").unwrap().instance_variable("_number").unwrap(); /// // SAFETY: The ivar is added with the same type above -/// unsafe { this.ivar::>("_number") }.get() +/// unsafe { ivar.load::>(this) }.get() /// } /// unsafe { /// builder.add_method(sel!(number), my_number_get as extern "C" fn(_, _) -> _); @@ -404,25 +407,17 @@ impl ClassBuilder { align: u8, encoding: &Encoding, ) { - // `class_addIvar` sadly doesn't check this for us. - // - // We must _always_ do the check, since there is no way for the user - // to statically know if the superclass has a declared instance - // variable on it, since that may change if a new version of the - // library/framework the class came from is released. - if let Some(_ivar) = self - .superclass() - .and_then(|superclass| superclass.instance_variable(name)) - { - panic!("instance variable {name:?} already exists on a superclass"); - } - let c_name = CString::new(name).unwrap(); let encoding = CString::new(encoding.to_string()).unwrap(); // Note: The Objective-C runtime contains functionality to do stuff // with "instance variable layouts", but we don't have to touch any of // that, it was only used in the garbage-collecting runtime. + // + // Note: On GNUStep, instance variables cannot have the same name + // on subclasses as it has on superclasses. + // + // See let success = Bool::from_raw(unsafe { ffi::class_addIvar( self.as_mut_ptr(), @@ -614,12 +609,16 @@ mod tests { use std::collections::hash_map::DefaultHasher; use std::hash::Hash; + use memoffset::offset_of; + use super::*; use crate::encode::RefEncode; use crate::mutability::Immutable; use crate::rc::Id; use crate::runtime::{NSObject, NSObjectProtocol}; - use crate::{declare_class, extern_methods, msg_send, test_utils, ClassType, ProtocolType}; + use crate::{ + declare_class, extern_methods, msg_send, msg_send_id, test_utils, ClassType, ProtocolType, + }; #[test] fn test_alignment() { @@ -945,4 +944,145 @@ mod tests { assert!(obj1.is_kind_of::()); assert!(obj1.is_kind_of::()); } + + #[test] + #[cfg_attr( + feature = "gnustep-1-7", + ignore = "ivars cannot have the same name on GNUStep" + )] + fn test_ivar_sizing() { + #[repr(align(16))] + struct U128align16([u64; 2]); + + unsafe impl Encode for U128align16 { + const ENCODING: Encoding = <[u64; 2]>::ENCODING; + } + + let mut superclass = + ClassBuilder::new("DeclareClassDuplicateIvarSuperclass", NSObject::class()).unwrap(); + superclass.add_ivar::("ivar1"); + superclass.add_ivar::("ivar2"); + superclass.add_ivar::("ivar3"); + superclass.add_ivar::<[u8; 0]>("ivar4"); + let superclass = superclass.register(); + + let mut subclass = + ClassBuilder::new("DeclareClassDuplicateIvarSubclass", superclass).unwrap(); + // Try to overwrite instance variables + subclass.add_ivar::("ivar1"); + subclass.add_ivar::("ivar2"); + subclass.add_ivar::<*const AnyObject>("ivar3"); + subclass.add_ivar::("ivar4"); + let subclass = subclass.register(); + + // Test that ivar layout matches that of C + // + // In particular, ivars are not reordered, though any extra padding on + // superclasses are utilized on subclasses. + #[repr(C)] + struct NSObjectLayout { + isa: *const AnyClass, + } + assert_eq!( + NSObject::class().instance_size(), + mem::size_of::(), + ); + + #[repr(C)] + struct SuperLayout { + isa: *const AnyClass, + ivar1: u8, + // Padding (7 on 64bit, 11 on 32bit) + ivar2: U128align16, + ivar3: u8, + ivar4: [u8; 0], + // Padding (15 in Rust, 7 on 64bit, 3 on 32bit) + } + // Class's ivar size is only rounded up to a pointer-sized boundary, + // not all the way up to the maximum alignment. + // + // This is surprising, but actually fine, since Objective-C objects + // are never packed closely like Rust structs would be in an array. + assert_eq!( + superclass.instance_size(), + mem::size_of::() - 16 + mem::size_of::<*const AnyClass>(), + ); + + #[repr(C)] + struct SubLayout { + isa: *const AnyClass, + ivar1: u8, + // Padding (7 on 64bit, 11 on 32bit) + ivar2: U128align16, + ivar3: u8, + ivar4: [u8; 0], + // Padding (1) + ivar1_b: i16, + // Padding (4) + ivar2_b: usize, + ivar3_b: *const AnyObject, + ivar4_b: usize, + } + assert_eq!(subclass.instance_size(), mem::size_of::()); + + let superclass_ivar1 = superclass.instance_variable("ivar1").unwrap(); + let superclass_ivar2 = superclass.instance_variable("ivar2").unwrap(); + let superclass_ivar3 = superclass.instance_variable("ivar3").unwrap(); + let superclass_ivar4 = superclass.instance_variable("ivar4").unwrap(); + let subclass_ivar1 = subclass.instance_variable("ivar1").unwrap(); + let subclass_ivar2 = subclass.instance_variable("ivar2").unwrap(); + let subclass_ivar3 = subclass.instance_variable("ivar3").unwrap(); + let subclass_ivar4 = subclass.instance_variable("ivar4").unwrap(); + + // Ensure that duplicate names do not conflict + assert_ne!(superclass_ivar1, subclass_ivar1); + assert_ne!(superclass_ivar2, subclass_ivar2); + assert_ne!(superclass_ivar3, subclass_ivar3); + assert_ne!(superclass_ivar4, subclass_ivar4); + + // Ensure that all offsets are as expected + assert_eq!( + superclass_ivar1.offset(), + offset_of!(SuperLayout, ivar1) as isize + ); + assert_eq!( + superclass_ivar2.offset(), + offset_of!(SuperLayout, ivar2) as isize + ); + assert_eq!( + superclass_ivar3.offset(), + offset_of!(SuperLayout, ivar3) as isize + ); + assert_eq!( + superclass_ivar4.offset(), + offset_of!(SuperLayout, ivar4) as isize + ); + assert_eq!( + subclass_ivar1.offset(), + offset_of!(SubLayout, ivar1_b) as isize + ); + assert_eq!( + subclass_ivar2.offset(), + offset_of!(SubLayout, ivar2_b) as isize + ); + assert_eq!( + subclass_ivar3.offset(), + offset_of!(SubLayout, ivar3_b) as isize + ); + assert_eq!( + subclass_ivar4.offset(), + offset_of!(SubLayout, ivar4_b) as isize + ); + + // Ensure our ivar loading works correctly + let obj: Id = unsafe { msg_send_id![subclass, new] }; + let ptr = unsafe { *subclass_ivar3.load::<*const AnyObject>(&obj) }; + assert!(ptr.is_null()); + + // Illustration of what goes wrong with the naive approach of loading + // the Ivar dynamically; in short, we can't be sure of which instance + // variable we're refering to here. + // + // let ivar = *obj.get_ivar::("ivar3"); + } } diff --git a/crates/objc2/src/runtime/mod.rs b/crates/objc2/src/runtime/mod.rs index b8cfd823b..d54ccaa2a 100644 --- a/crates/objc2/src/runtime/mod.rs +++ b/crates/objc2/src/runtime/mod.rs @@ -333,6 +333,126 @@ impl Ivar { let encoding = unsafe { CStr::from_ptr(ffi::ivar_getTypeEncoding(self.as_ptr())) }; str::from_utf8(encoding.to_bytes()).unwrap() } + + #[inline] + pub(crate) fn debug_assert_encoding(&self, _expected: &Encoding) { + #[cfg(debug_assertions)] + { + let encoding = self.type_encoding(); + assert!( + _expected.equivalent_to_str(encoding), + "wrong encoding. Tried to retrieve ivar with encoding {encoding}, but the encoding of the given type was {_expected}", + ); + } + } + + /// Returns a pointer to the instance variable / ivar on the given object. + /// + /// This is similar to [`UnsafeCell::get`], see that for more information + /// on what is and isn't safe to do. + /// + /// Usually you will have defined the instance variable yourself with + /// [`ClassBuilder::add_ivar`], the type of the ivar `T` must match the + /// type used in that. + /// + /// Library implementors are strongly encouraged to expose a safe + /// interface to the ivar. + /// + /// [`UnsafeCell::get`]: core::cell::UnsafeCell::get + /// [`ClassBuilder::add_ivar`]: crate::declare::ClassBuilder::add_ivar + /// + /// + /// # Panics + /// + /// Panics when `debug_assertions` are enabled if the type encoding of the + /// ivar differs from the type encoding of `T`. + /// + /// + /// # Safety + /// + /// The object must have the given instance variable on it, and it must be + /// of type `T`. Any invariants that the object have assumed about the + /// value of the instance variable must not be violated. + /// + /// Note that an object can have multiple instance variables with the same + /// name; you must ensure that when the instance variable was retrieved, + /// was retrieved from the class that it was defined on. In particular, + /// getting a class dynamically using e.g. [`AnyObject::class`], and using + /// an instance variable from that here is _not_ sound in general. + /// + /// No thread syncronization is done on accesses to the variable, so you + /// must ensure that any access to the returned pointer do not cause data + /// races, and that Rust's mutability rules are not otherwise violated. + #[inline] + pub unsafe fn load_ptr(&self, obj: &AnyObject) -> *mut T { + self.debug_assert_encoding(&T::ENCODING); + + let ptr = NonNull::from(obj); + // SAFETY: That the ivar is valid is ensured by the caller + let ptr = unsafe { AnyObject::ivar_at_offset::(ptr, self.offset()) }; + + // Safe as *mut T because `self` is `UnsafeCell` + ptr.as_ptr() + } + + /// Returns a reference to the instance variable with the given name. + /// + /// See [`Ivar::load_ptr`] for more information. + /// + /// + /// # Panics + /// + /// Panics when `debug_assertions` are enabled if the type encoding of the + /// ivar differs from the type encoding of `T`. + /// + /// + /// # Safety + /// + /// The object must have the given instance variable on it, and it must be + /// of type `T`. + /// + /// No thread syncronization is done, so you must ensure that no other + /// thread is concurrently mutating the variable. This requirement can be + /// considered upheld if all mutation happens through [`Ivar::load_mut`] + /// (since that takes the object mutably). + #[inline] + pub unsafe fn load<'obj, T: Encode>(&self, obj: &'obj AnyObject) -> &'obj T { + // SAFETY: That the ivar is valid as `&T` is ensured by the caller, + // and the reference is properly bound to the object. + unsafe { self.load_ptr::(obj).as_ref().unwrap_unchecked() } + } + + /// Returns a mutable reference to the ivar with the given name. + /// + /// See [`Ivar::load_ptr`] for more information. + /// + /// + /// # Panics + /// + /// Panics when `debug_assertions` are enabled if the type encoding of the + /// ivar differs from the type encoding of `T`. + /// + /// + /// # Safety + /// + /// The object must have an instance variable with the given name, and it + /// must be of type `T`. + /// + /// This access happens through `&mut`, which means we know it to be the + /// only reference, hence you do not need to do any work to ensure that + /// data races do not happen. + #[inline] + pub unsafe fn load_mut<'obj, T: Encode>(&self, obj: &'obj mut AnyObject) -> &'obj mut T { + self.debug_assert_encoding(&T::ENCODING); + + let ptr = NonNull::from(obj); + // SAFETY: That the ivar is valid is ensured by the caller + let mut ptr = unsafe { AnyObject::ivar_at_offset::(ptr, self.offset()) }; + + // SAFETY: That the ivar is valid as `&mut T` is ensured by taking an + // `&mut` object + unsafe { ptr.as_mut() } + } } standard_pointer_impls!(Ivar); @@ -711,6 +831,12 @@ impl AnyClass { /// Returns the ivar for a specified instance variable of self, or /// [`None`] if self has no ivar with the given name. + /// + /// If the instance variable was not found on the specified class, the + /// superclasses are searched. + /// + /// Attempting to access or modify instance variables of a class that you + /// do no control may invoke undefined behaviour. #[doc(alias = "class_getInstanceVariable")] pub fn instance_variable(&self, name: &str) -> Option<&Ivar> { let name = CString::new(name).unwrap(); @@ -999,20 +1125,6 @@ impl fmt::Display for AnyProtocol { } } -pub(crate) fn ivar_offset(cls: &AnyClass, name: &str, expected: &Encoding) -> isize { - match cls.instance_variable(name) { - Some(ivar) => { - let encoding = ivar.type_encoding(); - assert!( - expected.equivalent_to_str(encoding), - "wrong encoding. Tried to retrieve ivar with encoding {encoding}, but the encoding of the given type was {expected}", - ); - ivar.offset() - } - None => panic!("ivar {name} not found on class {cls}"), - } -} - /// An Objective-C object. /// /// This is slightly different from [`NSObject`] in that it may represent an @@ -1134,60 +1246,13 @@ impl AnyObject { ptr } - /// Returns a pointer to the instance variable / ivar with the given name. - /// - /// This is similar to [`UnsafeCell::get`], see that for more information - /// on what is and isn't safe to do. - /// - /// Usually you will have defined the instance variable yourself with - /// [`ClassBuilder::add_ivar`], the type of the ivar `T` must match the - /// type used in that. - /// - /// Attempting to access or modify private implementation details of a - /// class that you do no control using this is not supported, and may - /// invoke undefined behaviour. - /// - /// Library implementors are strongly encouraged to expose a safe - /// interface to the ivar. - /// - /// [`UnsafeCell::get`]: core::cell::UnsafeCell::get - /// [`ClassBuilder::add_ivar`]: crate::declare::ClassBuilder::add_ivar - /// - /// - /// # Panics - /// - /// May panic if the object has no ivar with the given name. May also - /// panic if the type encoding of the ivar differs from the type encoding - /// of `T`. - /// - /// This should purely seen as help while debugging and is not guaranteed - /// (e.g. it may be disabled when `debug_assertions` are off). - /// - /// - /// # Safety - /// - /// The object must have an instance variable with the given name, and it - /// must be of type `T`. Any invariants that the object have assumed about - /// the value of the instance variable must not be violated. - /// - /// No thread syncronization is done on accesses to the variable, so you - /// must ensure that any access to the returned pointer do not cause data - /// races, and that Rust's mutability rules are not otherwise violated. - pub unsafe fn ivar_ptr(&self, name: &str) -> *mut T { - let offset = ivar_offset(self.class(), name, &T::ENCODING); - - let ptr = NonNull::from(self); - // SAFETY: The offset is valid - let ptr = unsafe { Self::ivar_at_offset::(ptr, offset) }; - - // Safe as *mut T because `self` is `UnsafeCell` - ptr.as_ptr() + pub(crate) fn lookup_instance_variable_dynamically(&self, name: &str) -> &'static Ivar { + let cls = self.class(); + cls.instance_variable(name) + .unwrap_or_else(|| panic!("ivar {name} not found on class {cls}")) } - /// Returns a reference to the instance variable with the given name. - /// - /// See [`AnyObject::ivar_ptr`] for more information, including on when - /// this panics. + /// Use [`Ivar::load`] instead. /// /// /// # Safety @@ -1195,31 +1260,15 @@ impl AnyObject { /// The object must have an instance variable with the given name, and it /// must be of type `T`. /// - /// No thread syncronization is done, so you must ensure that no other - /// thread is concurrently mutating the variable. This requirement can be - /// considered upheld if all mutation happens through - /// [`AnyObject::ivar_mut`] (since that takes `&mut self`). - pub unsafe fn ivar(&self, name: &str) -> &T { - // SAFETY: Upheld by caller. - unsafe { self.ivar_ptr::(name).as_ref().unwrap_unchecked() } - } - - /// Use [`AnyObject::ivar`] instead. - /// - /// - /// # Safety - /// - /// See [`AnyObject::ivar`]. - #[deprecated = "Use `AnyObject::ivar` instead."] + /// See [`Ivar::load_ptr`] for details surrounding this. + #[deprecated = "this is difficult to use correctly, use `Ivar::load` instead."] pub unsafe fn get_ivar(&self, name: &str) -> &T { + let ivar = self.lookup_instance_variable_dynamically(name); // SAFETY: Upheld by caller - unsafe { self.ivar::(name) } + unsafe { ivar.load::(self) } } - /// Returns a mutable reference to the ivar with the given name. - /// - /// See [`AnyObject::ivar_ptr`] for more information, including on when - /// this panics. + /// Use [`Ivar::load_mut`] instead. /// /// /// # Safety @@ -1227,44 +1276,12 @@ impl AnyObject { /// The object must have an instance variable with the given name, and it /// must be of type `T`. /// - /// This access happens through `&mut self`, which means we know it to be - /// the only reference, hence you do not need to do any work to ensure - /// that data races do not happen. - pub unsafe fn ivar_mut(&mut self, name: &str) -> &mut T { - let offset = ivar_offset(self.class(), name, &T::ENCODING); - - let ptr = NonNull::from(self); - // SAFETY: The offset is valid - let mut ptr = unsafe { Self::ivar_at_offset::(ptr, offset) }; - - // SAFETY: - unsafe { ptr.as_mut() } - } - - /// Use [`AnyObject::ivar_mut`] instead. - /// - /// - /// # Safety - /// - /// Same as [`AnyObject::ivar_mut`]. - #[deprecated = "Use `AnyObject::ivar_mut` instead."] + /// See [`Ivar::load_ptr`] for details surrounding this. + #[deprecated = "this is difficult to use correctly, use `Ivar::load_mut` instead."] pub unsafe fn get_mut_ivar(&mut self, name: &str) -> &mut T { + let ivar = self.lookup_instance_variable_dynamically(name); // SAFETY: Upheld by caller - unsafe { self.ivar_mut::(name) } - } - - /// Sets the value of the ivar with the given name. - /// - /// This is a shorthand for [`AnyObject::ivar_mut`], see that for more - /// information. - /// - /// - /// # Safety - /// - /// Same as [`AnyObject::ivar_mut`]. - pub unsafe fn set_ivar(&mut self, name: &str, value: T) { - // SAFETY: Invariants upheld by caller - unsafe { *self.ivar_mut::(name) = value }; + unsafe { ivar.load_mut::(self) } } // objc_setAssociatedObject @@ -1476,27 +1493,32 @@ mod tests { #[test] fn test_object() { let mut obj = test_utils::custom_object(); - assert_eq!(obj.class(), test_utils::custom_class()); + let cls = test_utils::custom_class(); + assert_eq!(obj.class(), cls); - let result = unsafe { - obj.set_ivar::("_foo", 4); - *obj.ivar::("_foo") - }; + let ivar = cls.instance_variable("_foo").unwrap(); + + unsafe { *ivar.load_mut::(&mut obj) = 4 }; + let result = unsafe { *ivar.load::(&obj) }; assert_eq!(result, 4); } #[test] - #[should_panic = "ivar unknown not found on class CustomObject"] fn test_object_ivar_unknown() { - let obj = test_utils::custom_object(); - let _ = unsafe { *obj.ivar::("unknown") }; + let cls = test_utils::custom_class(); + assert_eq!(cls.instance_variable("unknown"), None); } #[test] - #[should_panic = "wrong encoding. Tried to retrieve ivar with encoding I, but the encoding of the given type was C"] + #[cfg_attr( + debug_assertions, + should_panic = "wrong encoding. Tried to retrieve ivar with encoding I, but the encoding of the given type was C" + )] fn test_object_ivar_wrong_type() { let obj = test_utils::custom_object(); - let _ = unsafe { *obj.ivar::("_foo") }; + let cls = test_utils::custom_class(); + let ivar = cls.instance_variable("_foo").unwrap(); + let _ = unsafe { *ivar.load::(&obj) }; } #[test] diff --git a/crates/objc2/src/test_utils.rs b/crates/objc2/src/test_utils.rs index 6b0e964b2..efd66a82d 100644 --- a/crates/objc2/src/test_utils.rs +++ b/crates/objc2/src/test_utils.rs @@ -93,15 +93,18 @@ pub(crate) fn custom_class() -> &'static AnyClass { } extern "C" fn custom_obj_set_foo(this: &mut AnyObject, _cmd: Sel, foo: u32) { - unsafe { this.set_ivar::("_foo", foo) } + let ivar = this.class().instance_variable("_foo").unwrap(); + unsafe { *ivar.load_mut::(this) = foo } } extern "C" fn custom_obj_get_foo(this: &AnyObject, _cmd: Sel) -> u32 { - unsafe { *this.ivar::("_foo") } + let ivar = this.class().instance_variable("_foo").unwrap(); + unsafe { *ivar.load::(this) } } extern "C" fn custom_obj_get_foo_reference(this: &AnyObject, _cmd: Sel) -> &u32 { - unsafe { this.ivar::("_foo") } + let ivar = this.class().instance_variable("_foo").unwrap(); + unsafe { ivar.load::(this) } } extern "C" fn custom_obj_get_struct(_this: &AnyObject, _cmd: Sel) -> CustomStruct { @@ -118,9 +121,8 @@ pub(crate) fn custom_class() -> &'static AnyClass { } extern "C" fn custom_obj_set_bar(this: &mut AnyObject, _cmd: Sel, bar: u32) { - unsafe { - this.set_ivar::("_foo", bar); - } + let ivar = this.class().instance_variable("_bar").unwrap(); + unsafe { *ivar.load_mut::(this) = bar } } extern "C" fn custom_obj_add_number_to_number( diff --git a/crates/objc2/tests/declare_class.rs b/crates/objc2/tests/declare_class.rs index 329a500f6..08a9d0622 100644 --- a/crates/objc2/tests/declare_class.rs +++ b/crates/objc2/tests/declare_class.rs @@ -2,7 +2,7 @@ use core::ptr::{self, NonNull}; use objc2::declare::IvarEncode; -use objc2::mutability::{Immutable, Mutable}; +use objc2::mutability::Immutable; use objc2::rc::Id; use objc2::runtime::NSObject; use objc2::{declare_class, extern_methods, sel, ClassType}; @@ -388,71 +388,6 @@ fn test_duplicate_ivar() { let _ = DeclareClassDuplicateIvar::class(); } -#[test] -#[should_panic = "instance variable \"ivar\" already exists on a superclass"] -fn test_subclass_duplicate_ivar() { - declare_class!( - struct Cls { - ivar_superclass: IvarEncode, - } - - mod ivars; - - unsafe impl ClassType for Cls { - type Super = NSObject; - type Mutability = Mutable; - const NAME: &'static str = "DeclareClassDuplicateIvarSuperclass"; - } - ); - - declare_class!( - struct SubCls { - ivar_subclass: IvarEncode, - } - - mod ivars_subclass; - - unsafe impl ClassType for SubCls { - type Super = Cls; - type Mutability = Mutable; - const NAME: &'static str = "DeclareClassDuplicateIvarSubclass"; - } - ); - - extern_methods!( - unsafe impl SubCls { - #[method_id(new)] - fn new() -> Id; - } - ); - - let _ = SubCls::class(); - - // The rest is to show what would go wrong if it didn't panic - - assert_eq!(Cls::class().instance_size(), 16); - assert_eq!(SubCls::class().instance_size(), 16); - - let mut obj = SubCls::new(); - - // Zero-initialized - assert_eq!(*obj.ivar_superclass, 0); - assert_eq!(*obj.ivar_subclass, 0); - - *obj.ivar_subclass = 2; - - assert_eq!(*obj.ivar_superclass, 2); - assert_eq!(*obj.ivar_subclass, 2); - - *obj.ivar_superclass = 3; - - assert_eq!(*obj.ivar_superclass, 3); - assert_eq!(*obj.ivar_subclass, 3); - - let ivar_dynamically = unsafe { obj.ivar::("ivar") }; - assert_eq!(*ivar_dynamically, 3); -} - declare_class!( #[derive(Debug)] struct OutParam; diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s index c366c0484..93f74d995 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s @@ -33,18 +33,18 @@ Lloh5: Lloh6: add x1, x1, l_anon.[ID].12@PAGEOFF Lloh7: - adrp x5, l_anon.[ID].13@PAGE + adrp x5, l_anon.[ID].15@PAGE Lloh8: - add x5, x5, l_anon.[ID].13@PAGEOFF + add x5, x5, l_anon.[ID].15@PAGEOFF add x0, sp, #8 mov w2, #4 mov w3, #1 mov w4, #0 bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) Lloh9: - adrp x1, l_anon.[ID].14@PAGE + adrp x1, l_anon.[ID].13@PAGE Lloh10: - add x1, x1, l_anon.[ID].14@PAGEOFF + add x1, x1, l_anon.[ID].13@PAGEOFF Lloh11: adrp x19, l_anon.[ID].2@PAGE Lloh12: @@ -363,30 +363,22 @@ _access_ivars: add x29, sp, #32 bl _get_obj mov x19, x0 - bl _object_getClass Lloh86: adrp x1, l_anon.[ID].12@PAGE Lloh87: add x1, x1, l_anon.[ID].12@PAGEOFF -Lloh88: - adrp x3, l_anon.[ID].13@PAGE -Lloh89: - add x3, x3, l_anon.[ID].13@PAGEOFF mov w2, #4 - bl SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0) + bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + bl _ivar_getOffset ldrb w20, [x19, x0] +Lloh88: + adrp x1, l_anon.[ID].13@PAGE +Lloh89: + add x1, x1, l_anon.[ID].13@PAGEOFF mov x0, x19 - bl _object_getClass -Lloh90: - adrp x1, l_anon.[ID].14@PAGE -Lloh91: - add x1, x1, l_anon.[ID].14@PAGEOFF -Lloh92: - adrp x3, l_anon.[ID].2@PAGE -Lloh93: - add x3, x3, l_anon.[ID].2@PAGEOFF mov w2, #4 - bl SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0) + bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + bl _ivar_getOffset ldr x21, [x19, x0] mov x0, x19 bl _objc_release @@ -396,8 +388,6 @@ Lloh93: ldp x20, x19, [sp, #16] ldp x22, x21, [sp], #48 ret - .loh AdrpAdd Lloh92, Lloh93 - .loh AdrpAdd Lloh90, Lloh91 .loh AdrpAdd Lloh88, Lloh89 .loh AdrpAdd Lloh86, Lloh87 @@ -407,16 +397,16 @@ SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh95: +Lloh91: add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF ldapr x8, [x8] cmp x8, #3 b.ne LBB6_3 -Lloh96: +Lloh92: adrp x0, l_anon.[ID].11@PAGE -Lloh97: +Lloh93: add x0, x0, l_anon.[ID].11@PAGEOFF mov w1, #15 bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) @@ -430,47 +420,47 @@ LBB6_3: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh98: +Lloh94: adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh99: +Lloh95: add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF -Lloh100: +Lloh96: adrp x3, l_anon.[ID].0@PAGE -Lloh101: +Lloh97: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh102: +Lloh98: adrp x4, l_anon.[ID].16@PAGE -Lloh103: +Lloh99: add x4, x4, l_anon.[ID].16@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) -Lloh104: +Lloh100: adrp x0, l_anon.[ID].11@PAGE -Lloh105: +Lloh101: add x0, x0, l_anon.[ID].11@PAGEOFF mov w1, #15 bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) cbnz x0, LBB6_2 LBB6_4: -Lloh106: +Lloh102: adrp x0, l_anon.[ID].8@PAGE -Lloh107: +Lloh103: add x0, x0, l_anon.[ID].8@PAGEOFF -Lloh108: +Lloh104: adrp x2, l_anon.[ID].16@PAGE -Lloh109: +Lloh105: add x2, x2, l_anon.[ID].16@PAGEOFF mov w1, #43 bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh94, Lloh95 + .loh AdrpAdd Lloh90, Lloh91 + .loh AdrpAdd Lloh92, Lloh93 + .loh AdrpAdd Lloh100, Lloh101 + .loh AdrpAdd Lloh98, Lloh99 .loh AdrpAdd Lloh96, Lloh97 + .loh AdrpAdd Lloh94, Lloh95 .loh AdrpAdd Lloh104, Lloh105 .loh AdrpAdd Lloh102, Lloh103 - .loh AdrpAdd Lloh100, Lloh101 - .loh AdrpAdd Lloh98, Lloh99 - .loh AdrpAdd Lloh108, Lloh109 - .loh AdrpAdd Lloh106, Lloh107 .p2align 2 SYM(::class::{closure#0}::__objc2_dealloc, 0): @@ -480,26 +470,22 @@ SYM(::class::REGISTER_CLASS, 0),8,3 diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-armv7s.s b/crates/test-assembly/crates/test_declare_class/expected/apple-armv7s.s index 55f165c2a..a970c1400 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-armv7s.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-armv7s.s @@ -32,8 +32,8 @@ LPC1_1: cmp r0, #0 beq LBB1_6 str r0, [sp, #8] - movw r1, :lower16:(l_anon.[ID].13-(LPC1_2+8)) - movt r1, :upper16:(l_anon.[ID].13-(LPC1_2+8)) + movw r1, :lower16:(l_anon.[ID].15-(LPC1_2+8)) + movt r1, :upper16:(l_anon.[ID].15-(LPC1_2+8)) LPC1_2: add r1, pc, r1 mov r0, #0 @@ -53,8 +53,8 @@ LPC1_4: add r8, pc, r8 mov r0, #2 stm sp, {r0, r8} - movw r1, :lower16:(L_anon.[ID].14-(LPC1_5+8)) - movt r1, :upper16:(L_anon.[ID].14-(LPC1_5+8)) + movw r1, :lower16:(L_anon.[ID].13-(LPC1_5+8)) + movt r1, :upper16:(L_anon.[ID].13-(LPC1_5+8)) LPC1_5: add r1, pc, r1 mov r0, r4 @@ -321,30 +321,22 @@ _access_ivars: add r7, sp, #12 bl _get_obj mov r4, r0 - bl _object_getClass movw r1, :lower16:(L_anon.[ID].12-(LPC5_0+8)) movt r1, :upper16:(L_anon.[ID].12-(LPC5_0+8)) LPC5_0: add r1, pc, r1 - movw r3, :lower16:(l_anon.[ID].13-(LPC5_1+8)) - movt r3, :upper16:(l_anon.[ID].13-(LPC5_1+8)) -LPC5_1: - add r3, pc, r3 mov r2, #4 - bl SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0) + bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + bl _ivar_getOffset ldrb r5, [r4, r0] - mov r0, r4 - bl _object_getClass - movw r1, :lower16:(L_anon.[ID].14-(LPC5_2+8)) - movt r1, :upper16:(L_anon.[ID].14-(LPC5_2+8)) -LPC5_2: + movw r1, :lower16:(L_anon.[ID].13-(LPC5_1+8)) + movt r1, :upper16:(L_anon.[ID].13-(LPC5_1+8)) +LPC5_1: add r1, pc, r1 - movw r3, :lower16:(l_anon.[ID].2-(LPC5_3+8)) - movt r3, :upper16:(l_anon.[ID].2-(LPC5_3+8)) -LPC5_3: - add r3, pc, r3 + mov r0, r4 mov r2, #4 - bl SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0) + bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + bl _ivar_getOffset ldr r6, [r4, r0] mov r0, r4 bl _objc_release @@ -420,25 +412,21 @@ SYM(::class::REGISTER_CLASS, 0),4,2 diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-old-x86.s b/crates/test-assembly/crates/test_declare_class/expected/apple-old-x86.s index 396066212..398486075 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-old-x86.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-old-x86.s @@ -35,7 +35,7 @@ L1$pb: je LBB1_6 mov dword ptr [ebp - 16], eax sub esp, 8 - lea eax, [esi + l_anon.[ID].13-L1$pb] + lea eax, [esi + l_anon.[ID].15-L1$pb] lea ecx, [esi + L_anon.[ID].12-L1$pb] lea ebx, [ebp - 16] push eax @@ -47,7 +47,7 @@ L1$pb: call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) add esp, 24 lea ecx, [esi + l_anon.[ID].2-L1$pb] - lea eax, [esi + L_anon.[ID].14-L1$pb] + lea eax, [esi + L_anon.[ID].13-L1$pb] push ecx push 2 push 4 @@ -286,36 +286,24 @@ L5$pb: pop edi call _get_obj mov esi, eax - sub esp, 12 - push eax - call _object_getClass - add esp, 16 - lea ecx, [edi + l_anon.[ID].13-L5$pb] - lea edx, [edi + L_anon.[ID].12-L5$pb] - push ecx - push 4 - push edx - push eax - call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0) - add esp, 16 + lea eax, [edi + L_anon.[ID].12-L5$pb] + mov dword ptr [esp + 4], eax + mov dword ptr [esp], esi + mov dword ptr [esp + 8], 4 + call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + mov dword ptr [esp], eax + call _ivar_getOffset movzx ebx, byte ptr [esi + eax] - sub esp, 12 - push esi - call _object_getClass - add esp, 16 - lea ecx, [edi + l_anon.[ID].2-L5$pb] - lea edx, [edi + L_anon.[ID].14-L5$pb] - push ecx - push 4 - push edx - push eax - call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0) - add esp, 16 + lea eax, [edi + L_anon.[ID].13-L5$pb] + mov dword ptr [esp + 4], eax + mov dword ptr [esp], esi + mov dword ptr [esp + 8], 4 + call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + mov dword ptr [esp], eax + call _ivar_getOffset mov edi, dword ptr [esi + eax] - sub esp, 12 - push esi + mov dword ptr [esp], esi call _objc_release - add esp, 16 mov eax, ebx mov edx, edi add esp, 12 @@ -386,40 +374,32 @@ SYM(::class::REGISTER_CLASS, 0),4,2 diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-x86.s b/crates/test-assembly/crates/test_declare_class/expected/apple-x86.s index 340c9a0e3..95b03257c 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-x86.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-x86.s @@ -35,7 +35,7 @@ L1$pb: je LBB1_6 mov dword ptr [ebp - 16], eax sub esp, 8 - lea eax, [esi + l_anon.[ID].13-L1$pb] + lea eax, [esi + l_anon.[ID].15-L1$pb] lea ecx, [esi + L_anon.[ID].12-L1$pb] lea ebx, [ebp - 16] push eax @@ -47,7 +47,7 @@ L1$pb: call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) add esp, 24 lea ecx, [esi + l_anon.[ID].2-L1$pb] - lea eax, [esi + L_anon.[ID].14-L1$pb] + lea eax, [esi + L_anon.[ID].13-L1$pb] push ecx push 2 push 4 @@ -286,36 +286,24 @@ L5$pb: pop edi call _get_obj mov esi, eax - sub esp, 12 - push eax - call _object_getClass - add esp, 16 - lea ecx, [edi + l_anon.[ID].13-L5$pb] - lea edx, [edi + L_anon.[ID].12-L5$pb] - push ecx - push 4 - push edx - push eax - call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0) - add esp, 16 + lea eax, [edi + L_anon.[ID].12-L5$pb] + mov dword ptr [esp + 4], eax + mov dword ptr [esp], esi + mov dword ptr [esp + 8], 4 + call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + mov dword ptr [esp], eax + call _ivar_getOffset movzx ebx, byte ptr [esi + eax] - sub esp, 12 - push esi - call _object_getClass - add esp, 16 - lea ecx, [edi + l_anon.[ID].2-L5$pb] - lea edx, [edi + L_anon.[ID].14-L5$pb] - push ecx - push 4 - push edx - push eax - call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0) - add esp, 16 + lea eax, [edi + L_anon.[ID].13-L5$pb] + mov dword ptr [esp + 4], eax + mov dword ptr [esp], esi + mov dword ptr [esp + 8], 4 + call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + mov dword ptr [esp], eax + call _ivar_getOffset mov edi, dword ptr [esi + eax] - sub esp, 12 - push esi + mov dword ptr [esp], esi call _objc_release - add esp, 16 mov eax, ebx mov edx, edi add esp, 12 @@ -386,40 +374,32 @@ SYM(::class::REGISTER_CLASS, 0),4,2 diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s index bc4820489..1d6570287 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s @@ -29,14 +29,14 @@ SYM(::call_once::<::class::REGISTER_CLASS, 0),8,3 diff --git a/crates/tests/src/test_object.rs b/crates/tests/src/test_object.rs index abb5fde52..45e80605f 100644 --- a/crates/tests/src/test_object.rs +++ b/crates/tests/src/test_object.rs @@ -138,11 +138,13 @@ impl MyTestObject { } fn var1_ivar(&self) -> &c_int { - unsafe { self.inner.ivar("var1") } + let ivar = Self::class().instance_variable("var1").unwrap(); + unsafe { ivar.load(&self.inner) } } fn var1_ivar_mut(&mut self) -> &mut c_int { - unsafe { self.inner.ivar_mut("var1") } + let ivar = Self::class().instance_variable("var1").unwrap(); + unsafe { ivar.load_mut(&mut self.inner) } } fn add_to_ivar1(&mut self, number: c_int) { @@ -154,11 +156,13 @@ impl MyTestObject { } fn var2_ivar(&self) -> &Bool { - unsafe { self.inner.ivar("var2") } + let ivar = Self::class().instance_variable("var2").unwrap(); + unsafe { ivar.load(&self.inner) } } fn var2_ivar_mut(&mut self) -> &mut Bool { - unsafe { self.inner.ivar_mut("var2") } + let ivar = Self::class().instance_variable("var2").unwrap(); + unsafe { ivar.load_mut(&mut self.inner) } } fn var3(&self) -> *mut AnyObject { @@ -170,11 +174,13 @@ impl MyTestObject { } fn var3_ivar(&self) -> &*mut AnyObject { - unsafe { self.inner.ivar("var3") } + let ivar = Self::class().instance_variable("var3").unwrap(); + unsafe { ivar.load(&self.inner) } } fn var3_ivar_mut(&mut self) -> &mut *mut AnyObject { - unsafe { self.inner.ivar_mut("var3") } + let ivar = Self::class().instance_variable("var3").unwrap(); + unsafe { ivar.load_mut(&mut self.inner) } } } From bfc5414d1b6e9a68c6beb3644124425cc9a10a8b Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 28 Nov 2023 00:09:28 +0100 Subject: [PATCH 2/6] Refactor declare_class! assembly test --- .../expected/apple-aarch64.s | 1808 ++++++++++++----- .../expected/apple-armv7s.s | 835 -------- .../expected/apple-old-x86.s | 849 -------- .../test_declare_class/expected/apple-x86.s | 849 -------- .../expected/apple-x86_64.s | 1121 ++++++---- .../crates/test_declare_class/lib.rs | 165 +- 6 files changed, 2142 insertions(+), 3485 deletions(-) diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s index 93f74d995..8e8074c7c 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s @@ -1,10 +1,18 @@ .section __TEXT,__text,regular,pure_instructions .p2align 2 -SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): +SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): ret .p2align 2 -SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): +SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): + ret + + .p2align 2 +SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): + ret + + .p2align 2 +SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): sub sp, sp, #64 stp x22, x21, [sp, #16] stp x20, x19, [sp, #32] @@ -13,7 +21,7 @@ SYM(::call_once::<::class::{closure#0}::__objc2_dealloc, 0)@PAGE -Lloh21: - add x5, x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGEOFF + add x5, x5, _method_simple@PAGEOFF add x0, sp, #8 - mov x2, x20 + mov x2, x19 mov x3, #0 - mov x4, x21 bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) +Lloh19: + adrp x8, L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f@PAGE +Lloh20: + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f@PAGEOFF] +Lloh21: + adrp x20, l_anon.[ID].6@PAGE Lloh22: - adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE + add x20, x20, l_anon.[ID].6@PAGEOFF Lloh23: - ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] + adrp x5, _method_bool@PAGE Lloh24: - ldr x1, [x8] -Lloh25: - adrp x5, _init@PAGE -Lloh26: - add x5, x5, _init@PAGEOFF + add x5, x5, _method_bool@PAGEOFF add x0, sp, #8 mov x2, x20 - mov x3, #0 - mov x4, x19 + mov w3, #1 + mov x4, x20 bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) +Lloh25: + adrp x8, L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00@PAGE +Lloh26: + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00@PAGEOFF] Lloh27: - adrp x8, L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2@PAGE + adrp x21, l_anon.[ID].4@PAGE Lloh28: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2@PAGEOFF] + add x21, x21, l_anon.[ID].4@PAGEOFF Lloh29: - adrp x5, _class_method@PAGE + adrp x5, _method_id@PAGE Lloh30: - add x5, x5, _class_method@PAGEOFF + add x5, x5, _method_id@PAGEOFF add x0, sp, #8 - mov x2, x20 + mov x2, x19 mov x3, #0 mov x4, x21 - bl SYM(objc2::declare::ClassBuilder::add_class_method_inner::GENERATED_ID, 0) + bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) Lloh31: - adrp x8, L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09@PAGE Lloh32: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09@PAGEOFF] Lloh33: - adrp x5, _method@PAGE + adrp x5, _method_id_with_param@PAGE Lloh34: - add x5, x5, _method@PAGEOFF + add x5, x5, _method_id_with_param@PAGEOFF add x0, sp, #8 mov x2, x20 - mov x3, #0 + mov w3, #1 mov x4, x21 bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) Lloh35: - adrp x8, L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5@PAGE + adrp x0, l_anon.[ID].23@PAGE Lloh36: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5@PAGEOFF] + add x0, x0, l_anon.[ID].23@PAGEOFF + mov w1, #8 + bl SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) + cbz x0, LBB3_4 + mov x1, x0 + add x0, sp, #8 + bl SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) +LBB3_4: Lloh37: - adrp x21, l_anon.[ID].4@PAGE + adrp x0, l_anon.[ID].24@PAGE Lloh38: - add x21, x21, l_anon.[ID].4@PAGEOFF + add x0, x0, l_anon.[ID].24@PAGEOFF + mov w1, #9 + bl SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) + cbz x0, LBB3_6 + mov x1, x0 + add x0, sp, #8 + bl SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) +LBB3_6: Lloh39: - adrp x5, _method_bool@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571@PAGE Lloh40: - add x5, x5, _method_bool@PAGEOFF - add x0, sp, #8 - mov x2, x21 - mov w3, #1 - mov x4, x21 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571@PAGEOFF] Lloh41: - adrp x8, L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce@PAGE + adrp x2, l_anon.[ID].9@PAGE Lloh42: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce@PAGEOFF] + add x2, x2, l_anon.[ID].9@PAGEOFF Lloh43: - adrp x5, _method_id@PAGE + adrp x4, l_anon.[ID].4@PAGE Lloh44: - add x5, x5, _method_id@PAGEOFF - add x0, sp, #8 - mov x2, x20 - mov x3, #0 - mov x4, x19 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + add x4, x4, l_anon.[ID].4@PAGEOFF Lloh45: - adrp x8, L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f@PAGE -Lloh46: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f@PAGEOFF] -Lloh47: - adrp x5, _method_id_with_param@PAGE -Lloh48: - add x5, x5, _method_id_with_param@PAGEOFF - add x0, sp, #8 - mov x2, x21 - mov w3, #1 - mov x4, x19 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) -Lloh49: - adrp x0, l_anon.[ID].17@PAGE -Lloh50: - add x0, x0, l_anon.[ID].17@PAGEOFF - mov w1, #9 - bl SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) - cbz x0, LBB1_4 - mov x1, x0 - add x0, sp, #8 - bl SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) -LBB1_4: -Lloh51: - adrp x8, L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166@PAGE -Lloh52: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166@PAGEOFF] -Lloh53: - adrp x2, l_anon.[ID].7@PAGE -Lloh54: - add x2, x2, l_anon.[ID].7@PAGEOFF -Lloh55: - adrp x4, l_anon.[ID].2@PAGE -Lloh56: - add x4, x4, l_anon.[ID].2@PAGEOFF -Lloh57: adrp x5, _copyWithZone@PAGE -Lloh58: +Lloh46: add x5, x5, _copyWithZone@PAGEOFF add x0, sp, #8 mov w3, #1 @@ -199,691 +167,1463 @@ Lloh58: ldp x22, x21, [sp, #16] add sp, sp, #64 ret -LBB1_5: -Lloh59: - adrp x0, l_anon.[ID].8@PAGE -Lloh60: - add x0, x0, l_anon.[ID].8@PAGEOFF -Lloh61: - adrp x2, l_anon.[ID].10@PAGE -Lloh62: - add x2, x2, l_anon.[ID].10@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) -LBB1_6: -Lloh63: +LBB3_7: +Lloh47: adrp x0, l_anon.[ID].11@PAGE -Lloh64: +Lloh48: add x0, x0, l_anon.[ID].11@PAGEOFF -Lloh65: - adrp x2, l_anon.[ID].16@PAGE -Lloh66: - add x2, x2, l_anon.[ID].16@PAGEOFF - mov w1, #15 +Lloh49: + adrp x2, l_anon.[ID].13@PAGE +Lloh50: + add x2, x2, l_anon.[ID].13@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) +LBB3_8: +Lloh51: + adrp x0, l_anon.[ID].15@PAGE +Lloh52: + add x0, x0, l_anon.[ID].15@PAGEOFF +Lloh53: + adrp x2, l_anon.[ID].22@PAGE +Lloh54: + add x2, x2, l_anon.[ID].22@PAGEOFF + mov w1, #7 bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) .loh AdrpAdd Lloh3, Lloh4 .loh AdrpLdrGotLdr Lloh0, Lloh1, Lloh2 - .loh AdrpAdd Lloh49, Lloh50 - .loh AdrpAdd Lloh47, Lloh48 - .loh AdrpLdr Lloh45, Lloh46 - .loh AdrpAdd Lloh43, Lloh44 - .loh AdrpLdr Lloh41, Lloh42 - .loh AdrpAdd Lloh39, Lloh40 - .loh AdrpAdd Lloh37, Lloh38 - .loh AdrpLdr Lloh35, Lloh36 + .loh AdrpAdd Lloh35, Lloh36 .loh AdrpAdd Lloh33, Lloh34 .loh AdrpLdr Lloh31, Lloh32 .loh AdrpAdd Lloh29, Lloh30 - .loh AdrpLdr Lloh27, Lloh28 - .loh AdrpAdd Lloh25, Lloh26 - .loh AdrpLdrGotLdr Lloh22, Lloh23, Lloh24 - .loh AdrpAdd Lloh20, Lloh21 - .loh AdrpAdd Lloh18, Lloh19 - .loh AdrpAdd Lloh16, Lloh17 - .loh AdrpLdrGotLdr Lloh13, Lloh14, Lloh15 + .loh AdrpAdd Lloh27, Lloh28 + .loh AdrpLdr Lloh25, Lloh26 + .loh AdrpAdd Lloh23, Lloh24 + .loh AdrpAdd Lloh21, Lloh22 + .loh AdrpLdr Lloh19, Lloh20 + .loh AdrpAdd Lloh17, Lloh18 + .loh AdrpAdd Lloh15, Lloh16 + .loh AdrpLdr Lloh13, Lloh14 .loh AdrpAdd Lloh11, Lloh12 .loh AdrpAdd Lloh9, Lloh10 .loh AdrpAdd Lloh7, Lloh8 - .loh AdrpAdd Lloh5, Lloh6 - .loh AdrpAdd Lloh57, Lloh58 - .loh AdrpAdd Lloh55, Lloh56 + .loh AdrpLdr Lloh5, Lloh6 + .loh AdrpAdd Lloh37, Lloh38 + .loh AdrpAdd Lloh45, Lloh46 + .loh AdrpAdd Lloh43, Lloh44 + .loh AdrpAdd Lloh41, Lloh42 + .loh AdrpLdr Lloh39, Lloh40 + .loh AdrpAdd Lloh49, Lloh50 + .loh AdrpAdd Lloh47, Lloh48 .loh AdrpAdd Lloh53, Lloh54 - .loh AdrpLdr Lloh51, Lloh52 - .loh AdrpAdd Lloh61, Lloh62 - .loh AdrpAdd Lloh59, Lloh60 - .loh AdrpAdd Lloh65, Lloh66 - .loh AdrpAdd Lloh63, Lloh64 + .loh AdrpAdd Lloh51, Lloh52 .p2align 2 -SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 +SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): + sub sp, sp, #48 + stp x20, x19, [sp, #16] + stp x29, x30, [sp, #32] + add x29, sp, #32 ldr x8, [x0] - str x8, [sp, #8] + ldrb w9, [x8] + strb wzr, [x8] + cbz w9, LBB4_3 +Lloh55: + adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE +Lloh56: + ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] +Lloh57: + ldr x2, [x8] +Lloh58: + adrp x0, l_anon.[ID].16@PAGE +Lloh59: + add x0, x0, l_anon.[ID].16@PAGEOFF + mov w1, #9 + bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) + cbz x0, LBB4_4 + str x0, [sp, #8] +Lloh60: + adrp x1, l_anon.[ID].18@PAGE +Lloh61: + add x1, x1, l_anon.[ID].18@PAGEOFF +Lloh62: + adrp x19, l_anon.[ID].4@PAGE +Lloh63: + add x19, x19, l_anon.[ID].4@PAGEOFF add x0, sp, #8 - bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - ldp x29, x30, [sp, #16] - add sp, sp, #32 - ret - - .globl _get_class - .p2align 2 -_get_class: - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 + mov w2, #4 + mov w3, #8 + mov w4, #3 + mov x5, x19 + bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) +Lloh64: + adrp x1, l_anon.[ID].17@PAGE +Lloh65: + add x1, x1, l_anon.[ID].17@PAGEOFF + add x0, sp, #8 + mov w2, #11 + mov w3, #8 + mov w4, #3 + mov x5, x19 + bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) +Lloh66: + adrp x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGE Lloh67: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGEOFF] Lloh68: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF - ldapr x8, [x8] - cmp x8, #3 - b.ne LBB3_3 + ldr x1, [x8] Lloh69: - adrp x0, l_anon.[ID].11@PAGE + adrp x20, l_anon.[ID].3@PAGE Lloh70: - add x0, x0, l_anon.[ID].11@PAGEOFF - mov w1, #15 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB3_4 -LBB3_2: - ldp x29, x30, [sp, #16] - add sp, sp, #32 - ret -LBB3_3: - mov w8, #1 - strb w8, [sp, #7] - add x8, sp, #7 - str x8, [sp, #8] + add x20, x20, l_anon.[ID].3@PAGEOFF Lloh71: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE + adrp x4, l_anon.[ID].5@PAGE Lloh72: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + add x4, x4, l_anon.[ID].5@PAGEOFF Lloh73: - adrp x3, l_anon.[ID].0@PAGE + adrp x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGE Lloh74: - add x3, x3, l_anon.[ID].0@PAGEOFF + add x5, x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGEOFF + add x0, sp, #8 + mov x2, x20 + mov x3, #0 + bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) Lloh75: - adrp x4, l_anon.[ID].16@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE Lloh76: - add x4, x4, l_anon.[ID].16@PAGEOFF - add x2, sp, #8 - mov w1, #0 - bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] Lloh77: - adrp x0, l_anon.[ID].11@PAGE + ldr x1, [x8] Lloh78: - add x0, x0, l_anon.[ID].11@PAGEOFF - mov w1, #15 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB3_2 -LBB3_4: + adrp x5, _init_drop_ivars@PAGE Lloh79: - adrp x0, l_anon.[ID].8@PAGE + add x5, x5, _init_drop_ivars@PAGEOFF + add x0, sp, #8 + mov x2, x20 + mov x3, #0 + mov x4, x19 + bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + ldr x0, [sp, #8] + bl SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) + ldp x29, x30, [sp, #32] + ldp x20, x19, [sp, #16] + add sp, sp, #48 + ret +LBB4_3: Lloh80: - add x0, x0, l_anon.[ID].8@PAGEOFF + adrp x0, l_anon.[ID].11@PAGE Lloh81: - adrp x2, l_anon.[ID].16@PAGE + add x0, x0, l_anon.[ID].11@PAGEOFF Lloh82: - add x2, x2, l_anon.[ID].16@PAGEOFF + adrp x2, l_anon.[ID].13@PAGE +Lloh83: + add x2, x2, l_anon.[ID].13@PAGEOFF mov w1, #43 bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh67, Lloh68 - .loh AdrpAdd Lloh69, Lloh70 - .loh AdrpAdd Lloh77, Lloh78 - .loh AdrpAdd Lloh75, Lloh76 - .loh AdrpAdd Lloh73, Lloh74 - .loh AdrpAdd Lloh71, Lloh72 - .loh AdrpAdd Lloh81, Lloh82 - .loh AdrpAdd Lloh79, Lloh80 - - .globl _get_obj - .p2align 2 -_get_obj: - stp x29, x30, [sp, #-16]! - mov x29, sp - bl _get_class -Lloh83: - adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE +LBB4_4: Lloh84: - ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] + adrp x0, l_anon.[ID].16@PAGE Lloh85: - ldr x1, [x8] - ldp x29, x30, [sp], #16 - b _objc_msgSend - .loh AdrpLdrGotLdr Lloh83, Lloh84, Lloh85 + add x0, x0, l_anon.[ID].16@PAGEOFF +Lloh86: + adrp x2, l_anon.[ID].28@PAGE +Lloh87: + add x2, x2, l_anon.[ID].28@PAGEOFF + mov w1, #9 + bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) + .loh AdrpAdd Lloh58, Lloh59 + .loh AdrpLdrGotLdr Lloh55, Lloh56, Lloh57 + .loh AdrpAdd Lloh78, Lloh79 + .loh AdrpLdrGotLdr Lloh75, Lloh76, Lloh77 + .loh AdrpAdd Lloh73, Lloh74 + .loh AdrpAdd Lloh71, Lloh72 + .loh AdrpAdd Lloh69, Lloh70 + .loh AdrpLdrGotLdr Lloh66, Lloh67, Lloh68 + .loh AdrpAdd Lloh64, Lloh65 + .loh AdrpAdd Lloh62, Lloh63 + .loh AdrpAdd Lloh60, Lloh61 + .loh AdrpAdd Lloh82, Lloh83 + .loh AdrpAdd Lloh80, Lloh81 + .loh AdrpAdd Lloh86, Lloh87 + .loh AdrpAdd Lloh84, Lloh85 - .globl _access_ivars .p2align 2 -_access_ivars: - stp x22, x21, [sp, #-48]! +SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): + sub sp, sp, #48 stp x20, x19, [sp, #16] stp x29, x30, [sp, #32] add x29, sp, #32 - bl _get_obj - mov x19, x0 -Lloh86: - adrp x1, l_anon.[ID].12@PAGE -Lloh87: - add x1, x1, l_anon.[ID].12@PAGEOFF - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldrb w20, [x19, x0] + ldr x8, [x0] + ldrb w9, [x8] + strb wzr, [x8] + cbz w9, LBB5_3 Lloh88: - adrp x1, l_anon.[ID].13@PAGE + adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE Lloh89: - add x1, x1, l_anon.[ID].13@PAGEOFF + ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] +Lloh90: + ldr x2, [x8] +Lloh91: + adrp x0, l_anon.[ID].14@PAGE +Lloh92: + add x0, x0, l_anon.[ID].14@PAGEOFF + mov w1, #15 + bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) + cbz x0, LBB5_4 + str x0, [sp, #8] +Lloh93: + adrp x1, l_anon.[ID].20@PAGE +Lloh94: + add x1, x1, l_anon.[ID].20@PAGEOFF +Lloh95: + adrp x5, l_anon.[ID].25@PAGE +Lloh96: + add x5, x5, l_anon.[ID].25@PAGEOFF + add x0, sp, #8 + mov w2, #4 + mov w3, #1 + mov w4, #0 + bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) +Lloh97: + adrp x1, l_anon.[ID].19@PAGE +Lloh98: + add x1, x1, l_anon.[ID].19@PAGEOFF +Lloh99: + adrp x5, l_anon.[ID].26@PAGE +Lloh100: + add x5, x5, l_anon.[ID].26@PAGEOFF + add x0, sp, #8 + mov w2, #4 + mov w3, #4 + mov w4, #2 + bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) +Lloh101: + adrp x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGE +Lloh102: + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGEOFF] +Lloh103: + ldr x1, [x8] +Lloh104: + adrp x19, l_anon.[ID].3@PAGE +Lloh105: + add x19, x19, l_anon.[ID].3@PAGEOFF +Lloh106: + adrp x4, l_anon.[ID].5@PAGE +Lloh107: + add x4, x4, l_anon.[ID].5@PAGEOFF +Lloh108: + adrp x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGE +Lloh109: + add x5, x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGEOFF + add x0, sp, #8 + mov x2, x19 + mov x3, #0 + bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) +Lloh110: + adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE +Lloh111: + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] +Lloh112: + ldr x1, [x8] +Lloh113: + adrp x4, l_anon.[ID].4@PAGE +Lloh114: + add x4, x4, l_anon.[ID].4@PAGEOFF +Lloh115: + adrp x5, _init_forgetable_ivars@PAGE +Lloh116: + add x5, x5, _init_forgetable_ivars@PAGEOFF + add x0, sp, #8 + mov x2, x19 + mov x3, #0 + bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + ldr x0, [sp, #8] + bl SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) + ldp x29, x30, [sp, #32] + ldp x20, x19, [sp, #16] + add sp, sp, #48 + ret +LBB5_3: +Lloh117: + adrp x0, l_anon.[ID].11@PAGE +Lloh118: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh119: + adrp x2, l_anon.[ID].13@PAGE +Lloh120: + add x2, x2, l_anon.[ID].13@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) +LBB5_4: +Lloh121: + adrp x0, l_anon.[ID].14@PAGE +Lloh122: + add x0, x0, l_anon.[ID].14@PAGEOFF +Lloh123: + adrp x2, l_anon.[ID].27@PAGE +Lloh124: + add x2, x2, l_anon.[ID].27@PAGEOFF + mov w1, #15 + bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) + .loh AdrpAdd Lloh91, Lloh92 + .loh AdrpLdrGotLdr Lloh88, Lloh89, Lloh90 + .loh AdrpAdd Lloh115, Lloh116 + .loh AdrpAdd Lloh113, Lloh114 + .loh AdrpLdrGotLdr Lloh110, Lloh111, Lloh112 + .loh AdrpAdd Lloh108, Lloh109 + .loh AdrpAdd Lloh106, Lloh107 + .loh AdrpAdd Lloh104, Lloh105 + .loh AdrpLdrGotLdr Lloh101, Lloh102, Lloh103 + .loh AdrpAdd Lloh99, Lloh100 + .loh AdrpAdd Lloh97, Lloh98 + .loh AdrpAdd Lloh95, Lloh96 + .loh AdrpAdd Lloh93, Lloh94 + .loh AdrpAdd Lloh119, Lloh120 + .loh AdrpAdd Lloh117, Lloh118 + .loh AdrpAdd Lloh123, Lloh124 + .loh AdrpAdd Lloh121, Lloh122 + + .p2align 2 +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 + ldr x8, [x0] + str x8, [sp, #8] + add x0, sp, #8 + bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + ldp x29, x30, [sp, #16] + add sp, sp, #32 + ret + + .p2align 2 +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 + ldr x8, [x0] + str x8, [sp, #8] + add x0, sp, #8 + bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + ldp x29, x30, [sp, #16] + add sp, sp, #32 + ret + + .p2align 2 +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 + ldr x8, [x0] + str x8, [sp, #8] + add x0, sp, #8 + bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + ldp x29, x30, [sp, #16] + add sp, sp, #32 + ret + + .globl _access_forgetable_ivars_class + .p2align 2 +_access_forgetable_ivars_class: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 +Lloh125: + adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh126: + add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB9_3 +Lloh127: + adrp x0, l_anon.[ID].14@PAGE +Lloh128: + add x0, x0, l_anon.[ID].14@PAGEOFF + mov w1, #15 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbz x0, LBB9_4 +LBB9_2: + ldp x29, x30, [sp, #16] + add sp, sp, #32 + ret +LBB9_3: + mov w8, #1 + strb w8, [sp, #7] + add x8, sp, #7 + str x8, [sp, #8] +Lloh129: + adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh130: + add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh131: + adrp x3, l_anon.[ID].2@PAGE +Lloh132: + add x3, x3, l_anon.[ID].2@PAGEOFF +Lloh133: + adrp x4, l_anon.[ID].27@PAGE +Lloh134: + add x4, x4, l_anon.[ID].27@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) +Lloh135: + adrp x0, l_anon.[ID].14@PAGE +Lloh136: + add x0, x0, l_anon.[ID].14@PAGEOFF + mov w1, #15 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbnz x0, LBB9_2 +LBB9_4: +Lloh137: + adrp x0, l_anon.[ID].11@PAGE +Lloh138: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh139: + adrp x2, l_anon.[ID].27@PAGE +Lloh140: + add x2, x2, l_anon.[ID].27@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) + .loh AdrpAdd Lloh125, Lloh126 + .loh AdrpAdd Lloh127, Lloh128 + .loh AdrpAdd Lloh135, Lloh136 + .loh AdrpAdd Lloh133, Lloh134 + .loh AdrpAdd Lloh131, Lloh132 + .loh AdrpAdd Lloh129, Lloh130 + .loh AdrpAdd Lloh139, Lloh140 + .loh AdrpAdd Lloh137, Lloh138 + + .globl _access_forgetable_ivars + .p2align 2 +_access_forgetable_ivars: + stp x20, x19, [sp, #-32]! + stp x29, x30, [sp, #16] + add x29, sp, #16 + mov x19, x0 +Lloh141: + adrp x1, l_anon.[ID].20@PAGE +Lloh142: + add x1, x1, l_anon.[ID].20@PAGEOFF + mov w2, #4 + bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + bl _ivar_getOffset + ldrb w20, [x19, x0] +Lloh143: + adrp x1, l_anon.[ID].19@PAGE +Lloh144: + add x1, x1, l_anon.[ID].19@PAGEOFF mov x0, x19 mov w2, #4 bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) bl _ivar_getOffset - ldr x21, [x19, x0] + ldr w1, [x19, x0] + mov x0, x20 + ldp x29, x30, [sp, #16] + ldp x20, x19, [sp], #32 + ret + .loh AdrpAdd Lloh143, Lloh144 + .loh AdrpAdd Lloh141, Lloh142 + + .globl SYM(::drop, 0) + .p2align 2 +SYM(::drop, 0): + ; InlineAsm Start + ; InlineAsm End + ret + + .globl _access_drop_ivars_class + .p2align 2 +_access_drop_ivars_class: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 +Lloh145: + adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh146: + add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB12_3 +Lloh147: + adrp x0, l_anon.[ID].16@PAGE +Lloh148: + add x0, x0, l_anon.[ID].16@PAGEOFF + mov w1, #9 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbz x0, LBB12_4 +LBB12_2: + ldp x29, x30, [sp, #16] + add sp, sp, #32 + ret +LBB12_3: + mov w8, #1 + strb w8, [sp, #7] + add x8, sp, #7 + str x8, [sp, #8] +Lloh149: + adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh150: + add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh151: + adrp x3, l_anon.[ID].1@PAGE +Lloh152: + add x3, x3, l_anon.[ID].1@PAGEOFF +Lloh153: + adrp x4, l_anon.[ID].28@PAGE +Lloh154: + add x4, x4, l_anon.[ID].28@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) +Lloh155: + adrp x0, l_anon.[ID].16@PAGE +Lloh156: + add x0, x0, l_anon.[ID].16@PAGEOFF + mov w1, #9 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbnz x0, LBB12_2 +LBB12_4: +Lloh157: + adrp x0, l_anon.[ID].11@PAGE +Lloh158: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh159: + adrp x2, l_anon.[ID].28@PAGE +Lloh160: + add x2, x2, l_anon.[ID].28@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) + .loh AdrpAdd Lloh145, Lloh146 + .loh AdrpAdd Lloh147, Lloh148 + .loh AdrpAdd Lloh155, Lloh156 + .loh AdrpAdd Lloh153, Lloh154 + .loh AdrpAdd Lloh151, Lloh152 + .loh AdrpAdd Lloh149, Lloh150 + .loh AdrpAdd Lloh159, Lloh160 + .loh AdrpAdd Lloh157, Lloh158 + + .globl _access_drop_ivars + .p2align 2 +_access_drop_ivars: + stp x20, x19, [sp, #-32]! + stp x29, x30, [sp, #16] + add x29, sp, #16 + mov x19, x0 +Lloh161: + adrp x1, l_anon.[ID].18@PAGE +Lloh162: + add x1, x1, l_anon.[ID].18@PAGEOFF + mov w2, #4 + bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + bl _ivar_getOffset + ldr x0, [x19, x0] + ldp x29, x30, [sp, #16] + ldp x20, x19, [sp], #32 + ret + .loh AdrpAdd Lloh161, Lloh162 + + .globl SYM(::class, 0) + .p2align 2 +SYM(::class, 0): + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 +Lloh163: + adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh164: + add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB14_3 +Lloh165: + adrp x0, l_anon.[ID].15@PAGE +Lloh166: + add x0, x0, l_anon.[ID].15@PAGEOFF + mov w1, #7 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbz x0, LBB14_4 +LBB14_2: + ldp x29, x30, [sp, #16] + add sp, sp, #32 + ret +LBB14_3: + mov w8, #1 + strb w8, [sp, #7] + add x8, sp, #7 + str x8, [sp, #8] +Lloh167: + adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh168: + add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh169: + adrp x3, l_anon.[ID].0@PAGE +Lloh170: + add x3, x3, l_anon.[ID].0@PAGEOFF +Lloh171: + adrp x4, l_anon.[ID].22@PAGE +Lloh172: + add x4, x4, l_anon.[ID].22@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) +Lloh173: + adrp x0, l_anon.[ID].15@PAGE +Lloh174: + add x0, x0, l_anon.[ID].15@PAGEOFF + mov w1, #7 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbnz x0, LBB14_2 +LBB14_4: +Lloh175: + adrp x0, l_anon.[ID].11@PAGE +Lloh176: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh177: + adrp x2, l_anon.[ID].22@PAGE +Lloh178: + add x2, x2, l_anon.[ID].22@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) + .loh AdrpAdd Lloh163, Lloh164 + .loh AdrpAdd Lloh165, Lloh166 + .loh AdrpAdd Lloh173, Lloh174 + .loh AdrpAdd Lloh171, Lloh172 + .loh AdrpAdd Lloh169, Lloh170 + .loh AdrpAdd Lloh167, Lloh168 + .loh AdrpAdd Lloh177, Lloh178 + .loh AdrpAdd Lloh175, Lloh176 + + .globl _get_class + .p2align 2 +_get_class: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 +Lloh179: + adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh180: + add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB15_3 +Lloh181: + adrp x0, l_anon.[ID].15@PAGE +Lloh182: + add x0, x0, l_anon.[ID].15@PAGEOFF + mov w1, #7 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbz x0, LBB15_4 +LBB15_2: + ldp x29, x30, [sp, #16] + add sp, sp, #32 + ret +LBB15_3: + mov w8, #1 + strb w8, [sp, #7] + add x8, sp, #7 + str x8, [sp, #8] +Lloh183: + adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh184: + add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh185: + adrp x3, l_anon.[ID].0@PAGE +Lloh186: + add x3, x3, l_anon.[ID].0@PAGEOFF +Lloh187: + adrp x4, l_anon.[ID].22@PAGE +Lloh188: + add x4, x4, l_anon.[ID].22@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) +Lloh189: + adrp x0, l_anon.[ID].15@PAGE +Lloh190: + add x0, x0, l_anon.[ID].15@PAGEOFF + mov w1, #7 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbnz x0, LBB15_2 +LBB15_4: +Lloh191: + adrp x0, l_anon.[ID].11@PAGE +Lloh192: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh193: + adrp x2, l_anon.[ID].22@PAGE +Lloh194: + add x2, x2, l_anon.[ID].22@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) + .loh AdrpAdd Lloh179, Lloh180 + .loh AdrpAdd Lloh181, Lloh182 + .loh AdrpAdd Lloh189, Lloh190 + .loh AdrpAdd Lloh187, Lloh188 + .loh AdrpAdd Lloh185, Lloh186 + .loh AdrpAdd Lloh183, Lloh184 + .loh AdrpAdd Lloh193, Lloh194 + .loh AdrpAdd Lloh191, Lloh192 + + .globl _method_simple + .p2align 2 +_method_simple: + ret + + .globl _method_bool + .p2align 2 +_method_bool: + eor w0, w2, #0x1 + ret + + .globl _method_id + .p2align 2 +_method_id: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 +Lloh195: + adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh196: + add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB18_3 +Lloh197: + adrp x0, l_anon.[ID].15@PAGE +Lloh198: + add x0, x0, l_anon.[ID].15@PAGEOFF + mov w1, #7 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbz x0, LBB18_4 +LBB18_2: +Lloh199: + adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE +Lloh200: + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] +Lloh201: + ldr x1, [x8] + bl _objc_msgSend + bl _objc_autoreleaseReturnValue + ldp x29, x30, [sp, #16] + add sp, sp, #32 + ret +LBB18_3: + mov w8, #1 + strb w8, [sp, #7] + add x8, sp, #7 + str x8, [sp, #8] +Lloh202: + adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh203: + add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh204: + adrp x3, l_anon.[ID].0@PAGE +Lloh205: + add x3, x3, l_anon.[ID].0@PAGEOFF +Lloh206: + adrp x4, l_anon.[ID].22@PAGE +Lloh207: + add x4, x4, l_anon.[ID].22@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) +Lloh208: + adrp x0, l_anon.[ID].15@PAGE +Lloh209: + add x0, x0, l_anon.[ID].15@PAGEOFF + mov w1, #7 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbnz x0, LBB18_2 +LBB18_4: +Lloh210: + adrp x0, l_anon.[ID].11@PAGE +Lloh211: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh212: + adrp x2, l_anon.[ID].22@PAGE +Lloh213: + add x2, x2, l_anon.[ID].22@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) + .loh AdrpAdd Lloh195, Lloh196 + .loh AdrpAdd Lloh197, Lloh198 + .loh AdrpLdrGotLdr Lloh199, Lloh200, Lloh201 + .loh AdrpAdd Lloh208, Lloh209 + .loh AdrpAdd Lloh206, Lloh207 + .loh AdrpAdd Lloh204, Lloh205 + .loh AdrpAdd Lloh202, Lloh203 + .loh AdrpAdd Lloh212, Lloh213 + .loh AdrpAdd Lloh210, Lloh211 + + .globl _method_id_with_param + .p2align 2 +_method_id_with_param: + stp x20, x19, [sp, #-32]! + stp x29, x30, [sp, #16] + add x29, sp, #16 + mov x20, x2 + bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) + mov x19, x0 + tbz w20, #0, LBB19_2 + bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) + mov x20, x0 mov x0, x19 bl _objc_release - mov x0, x20 - mov x1, x21 - ldp x29, x30, [sp, #32] - ldp x20, x19, [sp, #16] - ldp x22, x21, [sp], #48 + mov x19, x20 +LBB19_2: + mov x0, x19 + ldp x29, x30, [sp, #16] + ldp x20, x19, [sp], #32 + b _objc_autoreleaseReturnValue + + .globl _copyWithZone + .p2align 2 +_copyWithZone: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 +Lloh214: + adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh215: + add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB20_3 +Lloh216: + adrp x0, l_anon.[ID].15@PAGE +Lloh217: + add x0, x0, l_anon.[ID].15@PAGEOFF + mov w1, #7 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbz x0, LBB20_4 +LBB20_2: +Lloh218: + adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE +Lloh219: + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] +Lloh220: + ldr x1, [x8] + bl _objc_msgSend + ldp x29, x30, [sp, #16] + add sp, sp, #32 ret - .loh AdrpAdd Lloh88, Lloh89 - .loh AdrpAdd Lloh86, Lloh87 +LBB20_3: + mov w8, #1 + strb w8, [sp, #7] + add x8, sp, #7 + str x8, [sp, #8] +Lloh221: + adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh222: + add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh223: + adrp x3, l_anon.[ID].0@PAGE +Lloh224: + add x3, x3, l_anon.[ID].0@PAGEOFF +Lloh225: + adrp x4, l_anon.[ID].22@PAGE +Lloh226: + add x4, x4, l_anon.[ID].22@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) +Lloh227: + adrp x0, l_anon.[ID].15@PAGE +Lloh228: + add x0, x0, l_anon.[ID].15@PAGEOFF + mov w1, #7 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbnz x0, LBB20_2 +LBB20_4: +Lloh229: + adrp x0, l_anon.[ID].11@PAGE +Lloh230: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh231: + adrp x2, l_anon.[ID].22@PAGE +Lloh232: + add x2, x2, l_anon.[ID].22@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) + .loh AdrpAdd Lloh214, Lloh215 + .loh AdrpAdd Lloh216, Lloh217 + .loh AdrpLdrGotLdr Lloh218, Lloh219, Lloh220 + .loh AdrpAdd Lloh227, Lloh228 + .loh AdrpAdd Lloh225, Lloh226 + .loh AdrpAdd Lloh223, Lloh224 + .loh AdrpAdd Lloh221, Lloh222 + .loh AdrpAdd Lloh231, Lloh232 + .loh AdrpAdd Lloh229, Lloh230 - .globl SYM(::class, 0) + .globl SYM(::class, 0) .p2align 2 -SYM(::class, 0): +SYM(::class, 0): sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh90: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh91: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh233: + adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh234: + add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF ldapr x8, [x8] cmp x8, #3 - b.ne LBB6_3 -Lloh92: - adrp x0, l_anon.[ID].11@PAGE -Lloh93: - add x0, x0, l_anon.[ID].11@PAGEOFF + b.ne LBB21_3 +Lloh235: + adrp x0, l_anon.[ID].14@PAGE +Lloh236: + add x0, x0, l_anon.[ID].14@PAGEOFF mov w1, #15 bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB6_4 -LBB6_2: + cbz x0, LBB21_4 +LBB21_2: ldp x29, x30, [sp, #16] add sp, sp, #32 ret -LBB6_3: +LBB21_3: mov w8, #1 strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh94: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh95: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF -Lloh96: - adrp x3, l_anon.[ID].0@PAGE -Lloh97: - add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh98: - adrp x4, l_anon.[ID].16@PAGE -Lloh99: - add x4, x4, l_anon.[ID].16@PAGEOFF +Lloh237: + adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh238: + add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh239: + adrp x3, l_anon.[ID].2@PAGE +Lloh240: + add x3, x3, l_anon.[ID].2@PAGEOFF +Lloh241: + adrp x4, l_anon.[ID].27@PAGE +Lloh242: + add x4, x4, l_anon.[ID].27@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) -Lloh100: - adrp x0, l_anon.[ID].11@PAGE -Lloh101: - add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh243: + adrp x0, l_anon.[ID].14@PAGE +Lloh244: + add x0, x0, l_anon.[ID].14@PAGEOFF mov w1, #15 bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB6_2 -LBB6_4: -Lloh102: - adrp x0, l_anon.[ID].8@PAGE -Lloh103: - add x0, x0, l_anon.[ID].8@PAGEOFF -Lloh104: - adrp x2, l_anon.[ID].16@PAGE -Lloh105: - add x2, x2, l_anon.[ID].16@PAGEOFF + cbnz x0, LBB21_2 +LBB21_4: +Lloh245: + adrp x0, l_anon.[ID].11@PAGE +Lloh246: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh247: + adrp x2, l_anon.[ID].27@PAGE +Lloh248: + add x2, x2, l_anon.[ID].27@PAGEOFF mov w1, #43 bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh90, Lloh91 - .loh AdrpAdd Lloh92, Lloh93 - .loh AdrpAdd Lloh100, Lloh101 - .loh AdrpAdd Lloh98, Lloh99 - .loh AdrpAdd Lloh96, Lloh97 - .loh AdrpAdd Lloh94, Lloh95 - .loh AdrpAdd Lloh104, Lloh105 - .loh AdrpAdd Lloh102, Lloh103 + .loh AdrpAdd Lloh233, Lloh234 + .loh AdrpAdd Lloh235, Lloh236 + .loh AdrpAdd Lloh243, Lloh244 + .loh AdrpAdd Lloh241, Lloh242 + .loh AdrpAdd Lloh239, Lloh240 + .loh AdrpAdd Lloh237, Lloh238 + .loh AdrpAdd Lloh247, Lloh248 + .loh AdrpAdd Lloh245, Lloh246 .p2align 2 -SYM(::class::{closure#0}::__objc2_dealloc, 0): - sub sp, sp, #48 - stp x20, x19, [sp, #16] - stp x29, x30, [sp, #32] - add x29, sp, #32 - mov x19, x1 - mov x20, x0 -Lloh106: - adrp x1, l_anon.[ID].13@PAGE -Lloh107: - add x1, x1, l_anon.[ID].13@PAGEOFF - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr x0, [x20, x0] - cbz x0, LBB7_2 - bl _objc_release -LBB7_2: -Lloh108: +SYM(::class::{closure#0}::__objc2_dealloc, 0): + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 +Lloh249: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh109: +Lloh250: ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh110: +Lloh251: ldr x8, [x8] - stp x20, x8, [sp] + stp x0, x8, [sp] mov x0, sp - mov x1, x19 bl _objc_msgSendSuper - ldp x29, x30, [sp, #32] - ldp x20, x19, [sp, #16] - add sp, sp, #48 + ldp x29, x30, [sp, #16] + add sp, sp, #32 ret - .loh AdrpAdd Lloh106, Lloh107 - .loh AdrpLdrGotLdr Lloh108, Lloh109, Lloh110 + .loh AdrpLdrGotLdr Lloh249, Lloh250, Lloh251 - .globl _init + .globl _init_forgetable_ivars .p2align 2 -_init: +_init_forgetable_ivars: sub sp, sp, #48 stp x20, x19, [sp, #16] stp x29, x30, [sp, #32] add x29, sp, #32 -Lloh111: +Lloh252: adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE -Lloh112: +Lloh253: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] -Lloh113: +Lloh254: ldr x1, [x8] -Lloh114: +Lloh255: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh115: +Lloh256: ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh116: +Lloh257: ldr x8, [x8] stp x0, x8, [sp] mov x0, sp bl _objc_msgSendSuper mov x19, x0 - cbz x0, LBB8_2 -Lloh117: - adrp x1, l_anon.[ID].12@PAGE -Lloh118: - add x1, x1, l_anon.[ID].12@PAGEOFF + cbz x0, LBB23_2 +Lloh258: + adrp x1, l_anon.[ID].20@PAGE +Lloh259: + add x1, x1, l_anon.[ID].20@PAGEOFF mov x0, x19 mov w2, #4 bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) bl _ivar_getOffset mov w8, #42 strb w8, [x19, x0] -Lloh119: - adrp x1, l_anon.[ID].13@PAGE -Lloh120: - add x1, x1, l_anon.[ID].13@PAGEOFF +Lloh260: + adrp x1, l_anon.[ID].19@PAGE +Lloh261: + add x1, x1, l_anon.[ID].19@PAGEOFF mov x0, x19 mov w2, #4 bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) bl _ivar_getOffset - str xzr, [x19, x0] -LBB8_2: + mov w8, #43 + str w8, [x19, x0] +LBB23_2: mov x0, x19 ldp x29, x30, [sp, #32] ldp x20, x19, [sp, #16] add sp, sp, #48 ret - .loh AdrpLdrGotLdr Lloh114, Lloh115, Lloh116 - .loh AdrpLdrGotLdr Lloh111, Lloh112, Lloh113 - .loh AdrpAdd Lloh119, Lloh120 - .loh AdrpAdd Lloh117, Lloh118 - - .globl _class_method - .p2align 2 -_class_method: - ret - - .globl _method - .p2align 2 -_method: - ret + .loh AdrpLdrGotLdr Lloh255, Lloh256, Lloh257 + .loh AdrpLdrGotLdr Lloh252, Lloh253, Lloh254 + .loh AdrpAdd Lloh260, Lloh261 + .loh AdrpAdd Lloh258, Lloh259 - .globl _method_bool - .p2align 2 -_method_bool: - eor w0, w2, #0x1 - ret - - .globl _method_id + .globl SYM(::class, 0) .p2align 2 -_method_id: - stp x20, x19, [sp, #-32]! +SYM(::class, 0): + sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 - mov x19, x0 -Lloh121: - adrp x1, l_anon.[ID].13@PAGE -Lloh122: - add x1, x1, l_anon.[ID].13@PAGEOFF - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr x0, [x19, x0] - cbz x0, LBB12_2 - bl _objc_retain -LBB12_2: +Lloh262: + adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh263: + add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB24_3 +Lloh264: + adrp x0, l_anon.[ID].16@PAGE +Lloh265: + add x0, x0, l_anon.[ID].16@PAGEOFF + mov w1, #9 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbz x0, LBB24_4 +LBB24_2: ldp x29, x30, [sp, #16] - ldp x20, x19, [sp], #32 - b _objc_autoreleaseReturnValue - .loh AdrpAdd Lloh121, Lloh122 + add sp, sp, #32 + ret +LBB24_3: + mov w8, #1 + strb w8, [sp, #7] + add x8, sp, #7 + str x8, [sp, #8] +Lloh266: + adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE +Lloh267: + add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh268: + adrp x3, l_anon.[ID].1@PAGE +Lloh269: + add x3, x3, l_anon.[ID].1@PAGEOFF +Lloh270: + adrp x4, l_anon.[ID].28@PAGE +Lloh271: + add x4, x4, l_anon.[ID].28@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) +Lloh272: + adrp x0, l_anon.[ID].16@PAGE +Lloh273: + add x0, x0, l_anon.[ID].16@PAGEOFF + mov w1, #9 + bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + cbnz x0, LBB24_2 +LBB24_4: +Lloh274: + adrp x0, l_anon.[ID].11@PAGE +Lloh275: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh276: + adrp x2, l_anon.[ID].28@PAGE +Lloh277: + add x2, x2, l_anon.[ID].28@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) + .loh AdrpAdd Lloh262, Lloh263 + .loh AdrpAdd Lloh264, Lloh265 + .loh AdrpAdd Lloh272, Lloh273 + .loh AdrpAdd Lloh270, Lloh271 + .loh AdrpAdd Lloh268, Lloh269 + .loh AdrpAdd Lloh266, Lloh267 + .loh AdrpAdd Lloh276, Lloh277 + .loh AdrpAdd Lloh274, Lloh275 - .globl _method_id_with_param .p2align 2 -_method_id_with_param: - stp x22, x21, [sp, #-48]! +SYM(::class::{closure#0}::__objc2_dealloc, 0): + sub sp, sp, #48 stp x20, x19, [sp, #16] stp x29, x30, [sp, #32] add x29, sp, #32 - mov x21, x2 + mov x19, x1 mov x20, x0 - bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) - mov x19, x0 - cbz w21, LBB13_5 -Lloh123: - adrp x1, l_anon.[ID].13@PAGE -Lloh124: - add x1, x1, l_anon.[ID].13@PAGEOFF + bl SYM(::drop, 0) +Lloh278: + adrp x1, l_anon.[ID].18@PAGE +Lloh279: + add x1, x1, l_anon.[ID].18@PAGEOFF mov x0, x20 mov w2, #4 bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) bl _ivar_getOffset ldr x0, [x20, x0] - cbz x0, LBB13_3 - bl _objc_retain - mov x20, x0 - b LBB13_4 -LBB13_3: - mov x20, #0 -LBB13_4: - mov x0, x19 + cbz x0, LBB25_2 bl _objc_release - mov x19, x20 -LBB13_5: - mov x0, x19 +LBB25_2: +Lloh280: + adrp x1, l_anon.[ID].17@PAGE +Lloh281: + add x1, x1, l_anon.[ID].17@PAGEOFF + mov x0, x20 + mov w2, #11 + bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + bl _ivar_getOffset + ldr x0, [x20, x0] + cbz x0, LBB25_4 + bl _objc_release +LBB25_4: +Lloh282: + adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE +Lloh283: + ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] +Lloh284: + ldr x8, [x8] + stp x20, x8, [sp] + mov x0, sp + mov x1, x19 + bl _objc_msgSendSuper ldp x29, x30, [sp, #32] ldp x20, x19, [sp, #16] - ldp x22, x21, [sp], #48 - b _objc_autoreleaseReturnValue - .loh AdrpAdd Lloh123, Lloh124 + add sp, sp, #48 + ret + .loh AdrpAdd Lloh278, Lloh279 + .loh AdrpAdd Lloh280, Lloh281 + .loh AdrpLdrGotLdr Lloh282, Lloh283, Lloh284 - .globl _copyWithZone + .globl _init_drop_ivars .p2align 2 -_copyWithZone: - stp x22, x21, [sp, #-48]! +_init_drop_ivars: + sub sp, sp, #48 stp x20, x19, [sp, #16] stp x29, x30, [sp, #32] add x29, sp, #32 - mov x20, x0 - bl _get_obj +Lloh285: + adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE +Lloh286: + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] +Lloh287: + ldr x1, [x8] +Lloh288: + adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE +Lloh289: + ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] +Lloh290: + ldr x8, [x8] + stp x0, x8, [sp] + mov x0, sp + bl _objc_msgSendSuper mov x19, x0 - cbz x0, LBB14_5 -Lloh125: - adrp x21, l_anon.[ID].12@PAGE -Lloh126: - add x21, x21, l_anon.[ID].12@PAGEOFF - mov x0, x20 - mov x1, x21 - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldrb w22, [x20, x0] + cbz x0, LBB26_2 + bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) + mov x20, x0 +Lloh291: + adrp x1, l_anon.[ID].18@PAGE +Lloh292: + add x1, x1, l_anon.[ID].18@PAGEOFF mov x0, x19 - mov x1, x21 - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - strb w22, [x19, x0] -Lloh127: - adrp x1, l_anon.[ID].13@PAGE -Lloh128: - add x1, x1, l_anon.[ID].13@PAGEOFF - mov x0, x20 mov w2, #4 bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) bl _ivar_getOffset - ldr x0, [x20, x0] - cbz x0, LBB14_3 - bl _objc_retain + str x20, [x19, x0] + bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) mov x20, x0 - b LBB14_4 -LBB14_3: - mov x20, #0 -LBB14_4: -Lloh129: - adrp x1, l_anon.[ID].13@PAGE -Lloh130: - add x1, x1, l_anon.[ID].13@PAGEOFF +Lloh293: + adrp x1, l_anon.[ID].17@PAGE +Lloh294: + add x1, x1, l_anon.[ID].17@PAGEOFF mov x0, x19 - mov w2, #4 + mov w2, #11 bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) bl _ivar_getOffset str x20, [x19, x0] -LBB14_5: +LBB26_2: mov x0, x19 ldp x29, x30, [sp, #32] ldp x20, x19, [sp, #16] - ldp x22, x21, [sp], #48 + add sp, sp, #48 ret - .loh AdrpAdd Lloh127, Lloh128 - .loh AdrpAdd Lloh125, Lloh126 - .loh AdrpAdd Lloh129, Lloh130 + .loh AdrpLdrGotLdr Lloh288, Lloh289, Lloh290 + .loh AdrpLdrGotLdr Lloh285, Lloh286, Lloh287 + .loh AdrpAdd Lloh293, Lloh294 + .loh AdrpAdd Lloh291, Lloh292 .section __DATA,__const .p2align 3, 0x0 l_anon.[ID].0: - .quad SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) + .quad SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) .asciz "\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000" - .quad SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) - .quad SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + .quad SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) + .quad SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - .section __TEXT,__const .p2align 3, 0x0 l_anon.[ID].1: - .byte 0 + .quad SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) + .asciz "\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000" + .quad SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) + .quad SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) .p2align 3, 0x0 l_anon.[ID].2: + .quad SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) + .asciz "\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000" + .quad SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) + .quad SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + + .section __TEXT,__const + .p2align 3, 0x0 +l_anon.[ID].3: + .byte 0 + + .p2align 3, 0x0 +l_anon.[ID].4: .byte 19 .space 39 .p2align 3, 0x0 -l_anon.[ID].3: +l_anon.[ID].5: .byte 17 .space 39 .p2align 3, 0x0 -l_anon.[ID].4: +l_anon.[ID].6: .byte 16 .space 39 -l_anon.[ID].5: +l_anon.[ID].7: .ascii "_NSZone" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].6: +l_anon.[ID].8: .byte 28 .space 7 - .quad l_anon.[ID].5 + .quad l_anon.[ID].7 .asciz "\007\000\000\000\000\000\000" - .quad l_anon.[ID].1 + .quad l_anon.[ID].3 .space 8 .p2align 3, 0x0 -l_anon.[ID].7: +l_anon.[ID].9: .byte 25 .space 7 - .quad l_anon.[ID].6 + .quad l_anon.[ID].8 .space 24 .section __TEXT,__const -l_anon.[ID].8: + .p2align 3, 0x0 +l_anon.[ID].10: + .byte 21 + .space 39 + +l_anon.[ID].11: .ascii "called `Option::unwrap()` on a `None` value" -l_anon.[ID].9: +l_anon.[ID].12: .ascii "$RUSTC/library/std/src/sync/once.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].10: - .quad l_anon.[ID].9 +l_anon.[ID].13: + .quad l_anon.[ID].12 .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" .section __TEXT,__const -l_anon.[ID].11: - .ascii "CustomClassName" +l_anon.[ID].14: + .ascii "ForgetableIvars" - .section __TEXT,__literal4,4byte_literals -l_anon.[ID].12: - .ascii "_foo" +l_anon.[ID].15: + .ascii "NoIvars" -l_anon.[ID].13: +l_anon.[ID].16: + .ascii "DropIvars" + +l_anon.[ID].17: + .ascii "_obj_option" + + .section __TEXT,__literal4,4byte_literals +l_anon.[ID].18: .ascii "_obj" +l_anon.[ID].19: + .ascii "_bar" + +l_anon.[ID].20: + .ascii "_foo" + .section __TEXT,__const -l_anon.[ID].14: +l_anon.[ID].21: .ascii "crates/$DIR/lib.rs" - .p2align 3, 0x0 -l_anon.[ID].15: - .byte 5 - .space 39 - .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].16: - .quad l_anon.[ID].14 - .asciz "5\000\000\000\000\000\000\000\f\000\000\000\001\000\000" +l_anon.[ID].22: + .quad l_anon.[ID].21 + .asciz "5\000\000\000\000\000\000\000\017\000\000\000\001\000\000" + +.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 + .section __TEXT,__literal8,8byte_literals +l_anon.[ID].23: + .ascii "NSObject" -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .section __TEXT,__const -l_anon.[ID].17: +l_anon.[ID].24: .ascii "NSCopying" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_d874ee9262978be2 -L_OBJC_METH_VAR_NAME_d874ee9262978be2: + .globl L_OBJC_METH_VAR_NAME_f249b8b52b9a1205 +L_OBJC_METH_VAR_NAME_f249b8b52b9a1205: .asciz "classMethod" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2 + .globl L_OBJC_SELECTOR_REFERENCES_f249b8b52b9a1205 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2: - .quad L_OBJC_METH_VAR_NAME_d874ee9262978be2 +L_OBJC_SELECTOR_REFERENCES_f249b8b52b9a1205: + .quad L_OBJC_METH_VAR_NAME_f249b8b52b9a1205 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_d874ee9262978be2 + .globl L_OBJC_IMAGE_INFO_f249b8b52b9a1205 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_d874ee9262978be2: +L_OBJC_IMAGE_INFO_f249b8b52b9a1205: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc -L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc: + .globl L_OBJC_METH_VAR_NAME_2607fe9c3979c381 +L_OBJC_METH_VAR_NAME_2607fe9c3979c381: .asciz "method" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc + .globl L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc: - .quad L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc +L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381: + .quad L_OBJC_METH_VAR_NAME_2607fe9c3979c381 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_4539fd1dbda0cddc + .globl L_OBJC_IMAGE_INFO_2607fe9c3979c381 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4539fd1dbda0cddc: +L_OBJC_IMAGE_INFO_2607fe9c3979c381: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 -L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5: + .globl L_OBJC_METH_VAR_NAME_5a4952192b00de7f +L_OBJC_METH_VAR_NAME_5a4952192b00de7f: .asciz "methodBool:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5 + .globl L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5: - .quad L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 +L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f: + .quad L_OBJC_METH_VAR_NAME_5a4952192b00de7f .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5 + .globl L_OBJC_IMAGE_INFO_5a4952192b00de7f .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5: +L_OBJC_IMAGE_INFO_5a4952192b00de7f: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_f7f521670860b0ce -L_OBJC_METH_VAR_NAME_f7f521670860b0ce: + .globl L_OBJC_METH_VAR_NAME_bf0386bc74a73c00 +L_OBJC_METH_VAR_NAME_bf0386bc74a73c00: .asciz "methodId" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce + .globl L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce: - .quad L_OBJC_METH_VAR_NAME_f7f521670860b0ce +L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00: + .quad L_OBJC_METH_VAR_NAME_bf0386bc74a73c00 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_f7f521670860b0ce + .globl L_OBJC_IMAGE_INFO_bf0386bc74a73c00 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_f7f521670860b0ce: +L_OBJC_IMAGE_INFO_bf0386bc74a73c00: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6addfcf634c6232f -L_OBJC_METH_VAR_NAME_6addfcf634c6232f: + .globl L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09 +L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09: .asciz "methodIdWithParam:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f + .globl L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f: - .quad L_OBJC_METH_VAR_NAME_6addfcf634c6232f +L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09: + .quad L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_6addfcf634c6232f + .globl L_OBJC_IMAGE_INFO_6f0ab2a047fe4a09 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6addfcf634c6232f: +L_OBJC_IMAGE_INFO_6f0ab2a047fe4a09: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 -L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166: + .globl L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571 +L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571: .asciz "copyWithZone:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166 + .globl L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166: - .quad L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 +L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571: + .quad L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_4a8c690dbc9d8166 + .globl L_OBJC_IMAGE_INFO_062e7a5fdd2d2571 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4a8c690dbc9d8166: +L_OBJC_IMAGE_INFO_062e7a5fdd2d2571: .asciz "\000\000\000\000@\000\000" + .section __TEXT,__const + .p2align 3, 0x0 +l_anon.[ID].25: + .byte 5 + .space 39 + + .p2align 3, 0x0 +l_anon.[ID].26: + .byte 7 + .space 39 + + .section __DATA,__const + .p2align 3, 0x0 +l_anon.[ID].27: + .quad l_anon.[ID].21 + .asciz "5\000\000\000\000\000\000\000I\000\000\000\001\000\000" + +.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 + .p2align 3, 0x0 +l_anon.[ID].28: + .quad l_anon.[ID].21 + .asciz "5\000\000\000\000\000\000\000u\000\000\000\001\000\000" + +.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .subsections_via_symbols diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-armv7s.s b/crates/test-assembly/crates/test_declare_class/expected/apple-armv7s.s index a970c1400..a6e83e1ef 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-armv7s.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-armv7s.s @@ -1,838 +1,3 @@ .section __TEXT,__text,regular,pure_instructions .syntax unified - .p2align 2 - .code 32 -SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): - bx lr - - .p2align 2 - .code 32 -SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): - push {r4, r5, r7, lr} - add r7, sp, #8 - push {r8, r10, r11} - sub sp, sp, #12 - ldr r0, [r0] - ldrb r1, [r0] - mov r2, #0 - strb r2, [r0] - cmp r1, #0 - beq LBB1_5 - movw r0, :lower16:(LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-(LPC1_0+8)) - movt r0, :upper16:(LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-(LPC1_0+8)) -LPC1_0: - ldr r0, [pc, r0] - ldr r2, [r0] - movw r0, :lower16:(l_anon.[ID].11-(LPC1_1+8)) - movt r0, :upper16:(l_anon.[ID].11-(LPC1_1+8)) -LPC1_1: - add r0, pc, r0 - mov r1, #15 - bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) - cmp r0, #0 - beq LBB1_6 - str r0, [sp, #8] - movw r1, :lower16:(l_anon.[ID].15-(LPC1_2+8)) - movt r1, :upper16:(l_anon.[ID].15-(LPC1_2+8)) -LPC1_2: - add r1, pc, r1 - mov r0, #0 - strd r0, r1, [sp] - movw r1, :lower16:(L_anon.[ID].12-(LPC1_3+8)) - movt r1, :upper16:(L_anon.[ID].12-(LPC1_3+8)) -LPC1_3: - add r1, pc, r1 - add r4, sp, #8 - mov r0, r4 - mov r2, #4 - mov r3, #1 - bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) - movw r8, :lower16:(l_anon.[ID].2-(LPC1_4+8)) - movt r8, :upper16:(l_anon.[ID].2-(LPC1_4+8)) -LPC1_4: - add r8, pc, r8 - mov r0, #2 - stm sp, {r0, r8} - movw r1, :lower16:(L_anon.[ID].13-(LPC1_5+8)) - movt r1, :upper16:(L_anon.[ID].13-(LPC1_5+8)) -LPC1_5: - add r1, pc, r1 - mov r0, r4 - mov r2, #4 - mov r3, #4 - bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) - movw r0, :lower16:(LL_OBJC_SELECTOR_REFERENCES_dealloc$non_lazy_ptr-(LPC1_6+8)) - movt r0, :upper16:(LL_OBJC_SELECTOR_REFERENCES_dealloc$non_lazy_ptr-(LPC1_6+8)) -LPC1_6: - ldr r0, [pc, r0] - ldr r1, [r0] - movw r11, :lower16:(SYM(::class::{closure#0}::__objc2_dealloc, 0)-(LPC1_7+8)) - movt r11, :upper16:(SYM(::class::{closure#0}::__objc2_dealloc, 0)-(LPC1_7+8)) -LPC1_7: - add r11, pc, r11 - movw r10, :lower16:(l_anon.[ID].3-(LPC1_8+8)) - movt r10, :upper16:(l_anon.[ID].3-(LPC1_8+8)) -LPC1_8: - add r10, pc, r10 - strd r10, r11, [sp] - movw r5, :lower16:(l_anon.[ID].1-(LPC1_9+8)) - movt r5, :upper16:(l_anon.[ID].1-(LPC1_9+8)) -LPC1_9: - add r5, pc, r5 - mov r0, r4 - mov r2, r5 - mov r3, #0 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - movw r0, :lower16:(LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr-(LPC1_10+8)) - movt r0, :upper16:(LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr-(LPC1_10+8)) -LPC1_10: - ldr r0, [pc, r0] - ldr r1, [r0] - movw r9, :lower16:(_init-(LPC1_11+8)) - movt r9, :upper16:(_init-(LPC1_11+8)) -LPC1_11: - add r9, pc, r9 - strd r8, r9, [sp] - mov r0, r4 - mov r2, r5 - mov r3, #0 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - movw r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2-(LPC1_12+8)) - movt r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2-(LPC1_12+8)) -LPC1_12: - ldr r1, [pc, r1] - movw r11, :lower16:(_class_method-(LPC1_13+8)) - movt r11, :upper16:(_class_method-(LPC1_13+8)) -LPC1_13: - add r11, pc, r11 - strd r10, r11, [sp] - mov r0, r4 - mov r2, r5 - mov r3, #0 - bl SYM(objc2::declare::ClassBuilder::add_class_method_inner::GENERATED_ID, 0) - movw r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc-(LPC1_14+8)) - movt r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc-(LPC1_14+8)) -LPC1_14: - ldr r1, [pc, r1] - movw r11, :lower16:(_method-(LPC1_15+8)) - movt r11, :upper16:(_method-(LPC1_15+8)) -LPC1_15: - add r11, pc, r11 - strd r10, r11, [sp] - mov r0, r4 - mov r2, r5 - mov r3, #0 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - movw r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5-(LPC1_16+8)) - movt r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5-(LPC1_16+8)) -LPC1_16: - ldr r1, [pc, r1] - movw r3, :lower16:(_method_bool-(LPC1_17+8)) - movt r3, :upper16:(_method_bool-(LPC1_17+8)) -LPC1_17: - add r3, pc, r3 - movw r10, :lower16:(l_anon.[ID].4-(LPC1_18+8)) - movt r10, :upper16:(l_anon.[ID].4-(LPC1_18+8)) -LPC1_18: - add r10, pc, r10 - str r10, [sp] - str r3, [sp, #4] - mov r0, r4 - mov r2, r10 - mov r3, #1 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - movw r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce-(LPC1_19+8)) - movt r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce-(LPC1_19+8)) -LPC1_19: - ldr r1, [pc, r1] - movw r9, :lower16:(_method_id-(LPC1_20+8)) - movt r9, :upper16:(_method_id-(LPC1_20+8)) -LPC1_20: - add r9, pc, r9 - strd r8, r9, [sp] - mov r0, r4 - mov r2, r5 - mov r3, #0 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - movw r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f-(LPC1_21+8)) - movt r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f-(LPC1_21+8)) -LPC1_21: - ldr r1, [pc, r1] - movw r9, :lower16:(_method_id_with_param-(LPC1_22+8)) - movt r9, :upper16:(_method_id_with_param-(LPC1_22+8)) -LPC1_22: - add r9, pc, r9 - strd r8, r9, [sp] - mov r0, r4 - mov r2, r10 - mov r3, #1 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - movw r0, :lower16:(l_anon.[ID].17-(LPC1_23+8)) - movt r0, :upper16:(l_anon.[ID].17-(LPC1_23+8)) -LPC1_23: - add r0, pc, r0 - mov r1, #9 - bl SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) - cmp r0, #0 - beq LBB1_4 - mov r1, r0 - add r0, sp, #8 - bl SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) -LBB1_4: - movw r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166-(LPC1_24+8)) - movt r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166-(LPC1_24+8)) -LPC1_24: - ldr r1, [pc, r1] - movw r9, :lower16:(_copyWithZone-(LPC1_25+8)) - movt r9, :upper16:(_copyWithZone-(LPC1_25+8)) -LPC1_25: - add r9, pc, r9 - strd r8, r9, [sp] - movw r2, :lower16:(l_anon.[ID].7-(LPC1_26+8)) - movt r2, :upper16:(l_anon.[ID].7-(LPC1_26+8)) -LPC1_26: - add r2, pc, r2 - add r0, sp, #8 - mov r3, #1 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - ldr r0, [sp, #8] - bl SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) - sub sp, r7, #20 - pop {r8, r10, r11} - pop {r4, r5, r7, pc} -LBB1_5: - movw r0, :lower16:(l_anon.[ID].8-(LPC1_27+8)) - movt r0, :upper16:(l_anon.[ID].8-(LPC1_27+8)) -LPC1_27: - add r0, pc, r0 - movw r2, :lower16:(l_anon.[ID].10-(LPC1_28+8)) - movt r2, :upper16:(l_anon.[ID].10-(LPC1_28+8)) -LPC1_28: - add r2, pc, r2 - mov r1, #43 - mov lr, pc - b SYM(core::panicking::panic::GENERATED_ID, 0) -LBB1_6: - movw r0, :lower16:(l_anon.[ID].11-(LPC1_29+8)) - movt r0, :upper16:(l_anon.[ID].11-(LPC1_29+8)) -LPC1_29: - add r0, pc, r0 - movw r2, :lower16:(l_anon.[ID].16-(LPC1_30+8)) - movt r2, :upper16:(l_anon.[ID].16-(LPC1_30+8)) -LPC1_30: - add r2, pc, r2 - mov r1, #15 - mov lr, pc - b SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) - - .p2align 2 - .code 32 -SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): - push {r7, lr} - mov r7, sp - sub sp, sp, #4 - ldr r0, [r0] - str r0, [sp] - mov r0, sp - bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - mov sp, r7 - pop {r7, pc} - - .globl _get_class - .p2align 2 - .code 32 -_get_class: - push {r7, lr} - mov r7, sp - sub sp, sp, #12 - movw r0, :lower16:(SYM(::class::REGISTER_CLASS, 0)-(LPC3_0+8)) - movt r0, :upper16:(SYM(::class::REGISTER_CLASS, 0)-(LPC3_0+8)) -LPC3_0: - add r0, pc, r0 - ldr r0, [r0] - dmb ish - cmp r0, #3 - bne LBB3_3 -LBB3_1: - movw r0, :lower16:(l_anon.[ID].11-(LPC3_4+8)) - movt r0, :upper16:(l_anon.[ID].11-(LPC3_4+8)) -LPC3_4: - add r0, pc, r0 - mov r1, #15 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cmp r0, #0 - movne sp, r7 - popne {r7, pc} -LBB3_2: - movw r0, :lower16:(l_anon.[ID].8-(LPC3_5+8)) - movt r0, :upper16:(l_anon.[ID].8-(LPC3_5+8)) -LPC3_5: - add r0, pc, r0 - movw r2, :lower16:(l_anon.[ID].16-(LPC3_6+8)) - movt r2, :upper16:(l_anon.[ID].16-(LPC3_6+8)) -LPC3_6: - add r2, pc, r2 - mov r1, #43 - mov lr, pc - b SYM(core::panicking::panic::GENERATED_ID, 0) -LBB3_3: - mov r0, #1 - strb r0, [r7, #-5] - sub r0, r7, #5 - str r0, [r7, #-4] - movw r1, :lower16:(l_anon.[ID].16-(LPC3_1+8)) - movt r1, :upper16:(l_anon.[ID].16-(LPC3_1+8)) -LPC3_1: - add r1, pc, r1 - movw r0, :lower16:(SYM(::class::REGISTER_CLASS, 0)-(LPC3_2+8)) - movt r0, :upper16:(SYM(::class::REGISTER_CLASS, 0)-(LPC3_2+8)) -LPC3_2: - add r0, pc, r0 - movw r3, :lower16:(l_anon.[ID].0-(LPC3_3+8)) - movt r3, :upper16:(l_anon.[ID].0-(LPC3_3+8)) -LPC3_3: - add r3, pc, r3 - str r1, [sp] - sub r2, r7, #4 - mov r1, #0 - bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - b LBB3_1 - - .globl _get_obj - .p2align 2 - .code 32 -_get_obj: - push {r7, lr} - mov r7, sp - bl _get_class - movw r1, :lower16:(LL_OBJC_SELECTOR_REFERENCES_new$non_lazy_ptr-(LPC4_0+8)) - movt r1, :upper16:(LL_OBJC_SELECTOR_REFERENCES_new$non_lazy_ptr-(LPC4_0+8)) -LPC4_0: - ldr r1, [pc, r1] - ldr r1, [r1] - pop {r7, lr} - b _objc_msgSend - - .globl _access_ivars - .p2align 2 - .code 32 -_access_ivars: - push {r4, r5, r6, r7, lr} - add r7, sp, #12 - bl _get_obj - mov r4, r0 - movw r1, :lower16:(L_anon.[ID].12-(LPC5_0+8)) - movt r1, :upper16:(L_anon.[ID].12-(LPC5_0+8)) -LPC5_0: - add r1, pc, r1 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldrb r5, [r4, r0] - movw r1, :lower16:(L_anon.[ID].13-(LPC5_1+8)) - movt r1, :upper16:(L_anon.[ID].13-(LPC5_1+8)) -LPC5_1: - add r1, pc, r1 - mov r0, r4 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr r6, [r4, r0] - mov r0, r4 - bl _objc_release - mov r0, r5 - mov r1, r6 - pop {r4, r5, r6, r7, pc} - - .globl SYM(::class, 0) - .p2align 2 - .code 32 -SYM(::class, 0): - push {r7, lr} - mov r7, sp - sub sp, sp, #12 - movw r0, :lower16:(SYM(::class::REGISTER_CLASS, 0)-(LPC6_0+8)) - movt r0, :upper16:(SYM(::class::REGISTER_CLASS, 0)-(LPC6_0+8)) -LPC6_0: - add r0, pc, r0 - ldr r0, [r0] - dmb ish - cmp r0, #3 - bne LBB6_3 -LBB6_1: - movw r0, :lower16:(l_anon.[ID].11-(LPC6_4+8)) - movt r0, :upper16:(l_anon.[ID].11-(LPC6_4+8)) -LPC6_4: - add r0, pc, r0 - mov r1, #15 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cmp r0, #0 - movne sp, r7 - popne {r7, pc} -LBB6_2: - movw r0, :lower16:(l_anon.[ID].8-(LPC6_5+8)) - movt r0, :upper16:(l_anon.[ID].8-(LPC6_5+8)) -LPC6_5: - add r0, pc, r0 - movw r2, :lower16:(l_anon.[ID].16-(LPC6_6+8)) - movt r2, :upper16:(l_anon.[ID].16-(LPC6_6+8)) -LPC6_6: - add r2, pc, r2 - mov r1, #43 - mov lr, pc - b SYM(core::panicking::panic::GENERATED_ID, 0) -LBB6_3: - mov r0, #1 - strb r0, [r7, #-5] - sub r0, r7, #5 - str r0, [r7, #-4] - movw r1, :lower16:(l_anon.[ID].16-(LPC6_1+8)) - movt r1, :upper16:(l_anon.[ID].16-(LPC6_1+8)) -LPC6_1: - add r1, pc, r1 - movw r0, :lower16:(SYM(::class::REGISTER_CLASS, 0)-(LPC6_2+8)) - movt r0, :upper16:(SYM(::class::REGISTER_CLASS, 0)-(LPC6_2+8)) -LPC6_2: - add r0, pc, r0 - movw r3, :lower16:(l_anon.[ID].0-(LPC6_3+8)) - movt r3, :upper16:(l_anon.[ID].0-(LPC6_3+8)) -LPC6_3: - add r3, pc, r3 - str r1, [sp] - sub r2, r7, #4 - mov r1, #0 - bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - b LBB6_1 - - .p2align 2 - .code 32 -SYM(::class::{closure#0}::__objc2_dealloc, 0): - push {r4, r5, r7, lr} - add r7, sp, #8 - sub sp, sp, #8 - mov r4, r1 - mov r5, r0 - movw r1, :lower16:(L_anon.[ID].13-(LPC7_0+8)) - movt r1, :upper16:(L_anon.[ID].13-(LPC7_0+8)) -LPC7_0: - add r1, pc, r1 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr r0, [r5, r0] - cmp r0, #0 - beq LBB7_2 - bl _objc_release -LBB7_2: - movw r0, :lower16:(LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-(LPC7_1+8)) - movt r0, :upper16:(LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-(LPC7_1+8)) -LPC7_1: - ldr r0, [pc, r0] - ldr r0, [r0] - str r5, [sp] - str r0, [sp, #4] - mov r0, sp - mov r1, r4 - bl _objc_msgSendSuper - sub sp, r7, #8 - pop {r4, r5, r7, pc} - - .globl _init - .p2align 2 - .code 32 -_init: - push {r4, r7, lr} - add r7, sp, #4 - sub sp, sp, #8 - movw r1, :lower16:(LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr-(LPC8_0+8)) - movt r1, :upper16:(LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr-(LPC8_0+8)) -LPC8_0: - ldr r1, [pc, r1] - ldr r1, [r1] - movw r2, :lower16:(LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-(LPC8_1+8)) - movt r2, :upper16:(LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-(LPC8_1+8)) -LPC8_1: - ldr r2, [pc, r2] - ldr r2, [r2] - stm sp, {r0, r2} - mov r0, sp - bl _objc_msgSendSuper - mov r4, r0 - cmp r0, #0 - beq LBB8_2 - movw r1, :lower16:(L_anon.[ID].12-(LPC8_2+8)) - movt r1, :upper16:(L_anon.[ID].12-(LPC8_2+8)) -LPC8_2: - add r1, pc, r1 - mov r0, r4 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - mov r1, #42 - strb r1, [r4, r0] - movw r1, :lower16:(L_anon.[ID].13-(LPC8_3+8)) - movt r1, :upper16:(L_anon.[ID].13-(LPC8_3+8)) -LPC8_3: - add r1, pc, r1 - mov r0, r4 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - mov r1, #0 - str r1, [r4, r0] -LBB8_2: - mov r0, r4 - sub sp, r7, #4 - pop {r4, r7, pc} - - .globl _class_method - .p2align 2 - .code 32 -_class_method: - bx lr - - .globl _method - .p2align 2 - .code 32 -_method: - bx lr - - .globl _method_bool - .p2align 2 - .code 32 -_method_bool: - clz r0, r2 - lsr r0, r0, #5 - bx lr - - .globl _method_id - .p2align 2 - .code 32 -_method_id: - push {r4, r7, lr} - add r7, sp, #4 - mov r4, r0 - movw r1, :lower16:(L_anon.[ID].13-(LPC12_0+8)) - movt r1, :upper16:(L_anon.[ID].13-(LPC12_0+8)) -LPC12_0: - add r1, pc, r1 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr r0, [r4, r0] - cmp r0, #0 - beq LBB12_2 - bl _objc_retain - pop {r4, r7, lr} - b _objc_autoreleaseReturnValue -LBB12_2: - mov r0, #0 - pop {r4, r7, lr} - b _objc_autoreleaseReturnValue - - .globl _method_id_with_param - .p2align 2 - .code 32 -_method_id_with_param: - push {r4, r5, r6, r7, lr} - add r7, sp, #12 - mov r6, r2 - mov r5, r0 - bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) - mov r4, r0 - cmp r6, #0 - beq LBB13_5 - movw r1, :lower16:(L_anon.[ID].13-(LPC13_0+8)) - movt r1, :upper16:(L_anon.[ID].13-(LPC13_0+8)) -LPC13_0: - add r1, pc, r1 - mov r0, r5 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr r0, [r5, r0] - cmp r0, #0 - beq LBB13_3 - bl _objc_retain - mov r5, r0 - b LBB13_4 -LBB13_3: - mov r5, #0 -LBB13_4: - mov r0, r4 - bl _objc_release - mov r4, r5 -LBB13_5: - mov r0, r4 - pop {r4, r5, r6, r7, lr} - b _objc_autoreleaseReturnValue - - .globl _copyWithZone - .p2align 2 - .code 32 -_copyWithZone: - push {r4, r5, r6, r7, lr} - add r7, sp, #12 - push {r8} - mov r5, r0 - bl _get_obj - mov r4, r0 - cmp r0, #0 - beq LBB14_5 - movw r8, :lower16:(L_anon.[ID].12-(LPC14_0+8)) - movt r8, :upper16:(L_anon.[ID].12-(LPC14_0+8)) -LPC14_0: - add r8, pc, r8 - mov r0, r5 - mov r1, r8 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldrb r6, [r5, r0] - mov r0, r4 - mov r1, r8 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - strb r6, [r4, r0] - movw r1, :lower16:(L_anon.[ID].13-(LPC14_1+8)) - movt r1, :upper16:(L_anon.[ID].13-(LPC14_1+8)) -LPC14_1: - add r1, pc, r1 - mov r0, r5 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr r0, [r5, r0] - cmp r0, #0 - beq LBB14_3 - bl _objc_retain - mov r5, r0 - b LBB14_4 -LBB14_3: - mov r5, #0 -LBB14_4: - movw r1, :lower16:(L_anon.[ID].13-(LPC14_2+8)) - movt r1, :upper16:(L_anon.[ID].13-(LPC14_2+8)) -LPC14_2: - add r1, pc, r1 - mov r0, r4 - mov r2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - str r5, [r4, r0] -LBB14_5: - mov r0, r4 - pop {r8} - pop {r4, r5, r6, r7, pc} - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].0: - .long SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) - .asciz "\004\000\000\000\004\000\000" - .long SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) - .long SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - - .section __TEXT,__const - .p2align 2, 0x0 -l_anon.[ID].1: - .byte 0 - - .p2align 2, 0x0 -l_anon.[ID].2: - .byte 19 - .space 19 - - .p2align 2, 0x0 -l_anon.[ID].3: - .byte 17 - .space 19 - - .p2align 2, 0x0 -l_anon.[ID].4: - .space 1 - .space 19 - -l_anon.[ID].5: - .ascii "_NSZone" - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].6: - .byte 28 - .space 3 - .long l_anon.[ID].5 - .asciz "\007\000\000" - .long l_anon.[ID].1 - .space 4 - - .p2align 2, 0x0 -l_anon.[ID].7: - .byte 25 - .space 3 - .long l_anon.[ID].6 - .space 12 - - .section __TEXT,__const -l_anon.[ID].8: - .ascii "called `Option::unwrap()` on a `None` value" - -l_anon.[ID].9: - .ascii "$RUSTC/library/std/src/sync/once.rs" - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].10: - .long l_anon.[ID].9 - .asciz "p\000\000\000\225\000\000\0002\000\000" - - .section __TEXT,__const -l_anon.[ID].11: - .ascii "CustomClassName" - - .section __TEXT,__literal4,4byte_literals -L_anon.[ID].12: - .ascii "_foo" - -L_anon.[ID].13: - .ascii "_obj" - - .section __TEXT,__const -l_anon.[ID].14: - .ascii "crates/$DIR/lib.rs" - - .p2align 2, 0x0 -l_anon.[ID].15: - .byte 5 - .space 19 - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].16: - .long l_anon.[ID].14 - .asciz "5\000\000\000\f\000\000\000\001\000\000" - -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),4,2 - .section __TEXT,__const -l_anon.[ID].17: - .ascii "NSCopying" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_d874ee9262978be2 -L_OBJC_METH_VAR_NAME_d874ee9262978be2: - .asciz "classMethod" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2: - .long L_OBJC_METH_VAR_NAME_d874ee9262978be2 - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_d874ee9262978be2 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_d874ee9262978be2: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc -L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc: - .asciz "method" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc: - .long L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_4539fd1dbda0cddc - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4539fd1dbda0cddc: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 -L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5: - .asciz "methodBool:" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5: - .long L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_f7f521670860b0ce -L_OBJC_METH_VAR_NAME_f7f521670860b0ce: - .asciz "methodId" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce: - .long L_OBJC_METH_VAR_NAME_f7f521670860b0ce - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_f7f521670860b0ce - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_f7f521670860b0ce: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6addfcf634c6232f -L_OBJC_METH_VAR_NAME_6addfcf634c6232f: - .asciz "methodIdWithParam:" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f: - .long L_OBJC_METH_VAR_NAME_6addfcf634c6232f - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_6addfcf634c6232f - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6addfcf634c6232f: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 -L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166: - .asciz "copyWithZone:" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166: - .long L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_4a8c690dbc9d8166 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4a8c690dbc9d8166: - .asciz "\000\000\000\000@\000\000" - - .section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers - .p2align 2, 0x0 -LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr: - .indirect_symbol L_OBJC_CLASSLIST_REFERENCES_$_NSObject - .long 0 -LL_OBJC_SELECTOR_REFERENCES_dealloc$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_dealloc - .long 0 -LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_init - .long 0 -LL_OBJC_SELECTOR_REFERENCES_new$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_new - .long 0 - .subsections_via_symbols diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-old-x86.s b/crates/test-assembly/crates/test_declare_class/expected/apple-old-x86.s index 398486075..d3cea7aab 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-old-x86.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-old-x86.s @@ -1,852 +1,3 @@ .section __TEXT,__text,regular,pure_instructions .intel_syntax noprefix - .p2align 4, 0x90 -SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): - push ebp - mov ebp, esp - pop ebp - ret - - .p2align 4, 0x90 -SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 12 - call L1$pb -L1$pb: - pop esi - mov eax, dword ptr [ebp + 8] - mov eax, dword ptr [eax] - cmp byte ptr [eax], 0 - mov byte ptr [eax], 0 - je LBB1_5 - mov eax, dword ptr [esi + LL_OBJC_CLASS_REFERENCES_NSObject$non_lazy_ptr-L1$pb] - sub esp, 4 - lea edi, [esi + l_anon.[ID].11-L1$pb] - push dword ptr [eax] - push 15 - push edi - call SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) - add esp, 16 - test eax, eax - je LBB1_6 - mov dword ptr [ebp - 16], eax - sub esp, 8 - lea eax, [esi + l_anon.[ID].15-L1$pb] - lea ecx, [esi + L_anon.[ID].12-L1$pb] - lea ebx, [ebp - 16] - push eax - push 0 - push 1 - push 4 - push ecx - push ebx - call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) - add esp, 24 - lea ecx, [esi + l_anon.[ID].2-L1$pb] - lea eax, [esi + L_anon.[ID].13-L1$pb] - push ecx - push 2 - push 4 - push 4 - push eax - push ebx - call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) - add esp, 32 - mov eax, dword ptr [esi + LL_OBJC_SELECTOR_REFERENCES_dealloc$non_lazy_ptr-L1$pb] - sub esp, 8 - lea ecx, [esi + SYM(::class::{closure#0}::__objc2_dealloc, 0)-L1$pb] - lea edi, [esi + l_anon.[ID].3-L1$pb] - lea edx, [esi + l_anon.[ID].1-L1$pb] - push ecx - push edi - push 0 - push edx - mov edi, edx - push dword ptr [eax] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 32 - mov eax, dword ptr [esi + LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr-L1$pb] - sub esp, 8 - lea ecx, [esi + _init-L1$pb] - push ecx - lea ecx, [esi + l_anon.[ID].2-L1$pb] - push ecx - push 0 - push edi - push dword ptr [eax] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _class_method-L1$pb] - push eax - lea eax, [esi + l_anon.[ID].3-L1$pb] - push eax - push 0 - push edi - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_class_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _method-L1$pb] - push eax - lea eax, [esi + l_anon.[ID].3-L1$pb] - push eax - push 0 - push edi - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _method_bool-L1$pb] - lea ecx, [esi + l_anon.[ID].4-L1$pb] - push eax - push ecx - push 1 - push ecx - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _method_id-L1$pb] - push eax - lea edi, [esi + l_anon.[ID].2-L1$pb] - push edi - push 0 - lea eax, [esi + l_anon.[ID].1-L1$pb] - push eax - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _method_id_with_param-L1$pb] - push eax - push edi - push 1 - lea eax, [esi + l_anon.[ID].4-L1$pb] - push eax - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + l_anon.[ID].17-L1$pb] - push 9 - push eax - call SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) - add esp, 16 - test eax, eax - je LBB1_4 - sub esp, 8 - push eax - push ebx - call SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) - add esp, 16 -LBB1_4: - sub esp, 8 - lea eax, [esi + _copyWithZone-L1$pb] - lea ecx, [esi + l_anon.[ID].7-L1$pb] - push eax - lea eax, [esi + l_anon.[ID].2-L1$pb] - push eax - push 1 - push ecx - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 20 - push dword ptr [ebp - 16] - call SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) - add esp, 28 - pop esi - pop edi - pop ebx - pop ebp - ret -LBB1_5: - sub esp, 4 - lea eax, [esi + l_anon.[ID].10-L1$pb] - lea ecx, [esi + l_anon.[ID].8-L1$pb] - push eax - push 43 - push ecx - call SYM(core::panicking::panic::GENERATED_ID, 0) -LBB1_6: - sub esp, 4 - lea eax, [esi + l_anon.[ID].16-L1$pb] - push eax - push 15 - push edi - call SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) - - .p2align 4, 0x90 -SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): - push ebp - mov ebp, esp - sub esp, 24 - mov eax, dword ptr [ebp + 8] - mov eax, dword ptr [eax] - mov dword ptr [ebp - 4], eax - lea eax, [ebp - 4] - mov dword ptr [esp], eax - call SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - add esp, 24 - pop ebp - ret - - .globl _get_class - .p2align 4, 0x90 -_get_class: - push ebp - mov ebp, esp - push edi - push esi - sub esp, 16 - call L3$pb -L3$pb: - pop esi - mov eax, dword ptr [esi + SYM(::class::REGISTER_CLASS, 0)-L3$pb] - cmp eax, 3 - jne LBB3_1 -LBB3_2: - sub esp, 8 - lea eax, [esi + l_anon.[ID].11-L3$pb] - push 15 - push eax - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - add esp, 16 - test eax, eax - je LBB3_4 - add esp, 16 - pop esi - pop edi - pop ebp - ret -LBB3_1: - mov byte ptr [ebp - 9], 1 - lea eax, [ebp - 9] - mov dword ptr [ebp - 16], eax - sub esp, 12 - lea eax, [esi + l_anon.[ID].16-L3$pb] - lea ecx, [esi + l_anon.[ID].0-L3$pb] - lea edx, [ebp - 16] - lea edi, [esi + SYM(::class::REGISTER_CLASS, 0)-L3$pb] - push eax - push ecx - push edx - push 0 - push edi - call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - add esp, 32 - jmp LBB3_2 -LBB3_4: - sub esp, 4 - lea eax, [esi + l_anon.[ID].16-L3$pb] - lea ecx, [esi + l_anon.[ID].8-L3$pb] - push eax - push 43 - push ecx - call SYM(core::panicking::panic::GENERATED_ID, 0) - - .globl _get_obj - .p2align 4, 0x90 -_get_obj: - push ebp - mov ebp, esp - push esi - push eax - call L4$pb -L4$pb: - pop esi - call _get_class - mov ecx, dword ptr [esi + LL_OBJC_SELECTOR_REFERENCES_new$non_lazy_ptr-L4$pb] - sub esp, 8 - push dword ptr [ecx] - push eax - call _objc_msgSend - add esp, 20 - pop esi - pop ebp - ret - - .globl _access_ivars - .p2align 4, 0x90 -_access_ivars: - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 12 - call L5$pb -L5$pb: - pop edi - call _get_obj - mov esi, eax - lea eax, [edi + L_anon.[ID].12-L5$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - movzx ebx, byte ptr [esi + eax] - lea eax, [edi + L_anon.[ID].13-L5$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov edi, dword ptr [esi + eax] - mov dword ptr [esp], esi - call _objc_release - mov eax, ebx - mov edx, edi - add esp, 12 - pop esi - pop edi - pop ebx - pop ebp - ret - - .globl SYM(::class, 0) - .p2align 4, 0x90 -SYM(::class, 0): - push ebp - mov ebp, esp - push edi - push esi - sub esp, 16 - call L6$pb -L6$pb: - pop esi - mov eax, dword ptr [esi + SYM(::class::REGISTER_CLASS, 0)-L6$pb] - cmp eax, 3 - jne LBB6_1 -LBB6_2: - sub esp, 8 - lea eax, [esi + l_anon.[ID].11-L6$pb] - push 15 - push eax - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - add esp, 16 - test eax, eax - je LBB6_4 - add esp, 16 - pop esi - pop edi - pop ebp - ret -LBB6_1: - mov byte ptr [ebp - 9], 1 - lea eax, [ebp - 9] - mov dword ptr [ebp - 16], eax - sub esp, 12 - lea eax, [esi + l_anon.[ID].16-L6$pb] - lea ecx, [esi + l_anon.[ID].0-L6$pb] - lea edx, [ebp - 16] - lea edi, [esi + SYM(::class::REGISTER_CLASS, 0)-L6$pb] - push eax - push ecx - push edx - push 0 - push edi - call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - add esp, 32 - jmp LBB6_2 -LBB6_4: - sub esp, 4 - lea eax, [esi + l_anon.[ID].16-L6$pb] - lea ecx, [esi + l_anon.[ID].8-L6$pb] - push eax - push 43 - push ecx - call SYM(core::panicking::panic::GENERATED_ID, 0) - - .p2align 4, 0x90 -SYM(::class::{closure#0}::__objc2_dealloc, 0): - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 28 - call L7$pb -L7$pb: - pop ebx - mov esi, dword ptr [ebp + 12] - mov edi, dword ptr [ebp + 8] - lea eax, [ebx + L_anon.[ID].13-L7$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], edi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov eax, dword ptr [edi + eax] - test eax, eax - je LBB7_2 - mov dword ptr [esp], eax - call _objc_release -LBB7_2: - mov eax, dword ptr [ebx + LL_OBJC_CLASS_REFERENCES_NSObject$non_lazy_ptr-L7$pb] - mov eax, dword ptr [eax] - mov dword ptr [ebp - 20], edi - mov dword ptr [ebp - 16], eax - mov dword ptr [esp + 4], esi - lea eax, [ebp - 20] - mov dword ptr [esp], eax - call _objc_msgSendSuper - add esp, 28 - pop esi - pop edi - pop ebx - pop ebp - ret - - .globl _init - .p2align 4, 0x90 -_init: - push ebp - mov ebp, esp - push edi - push esi - sub esp, 16 - call L8$pb -L8$pb: - pop edi - mov eax, dword ptr [ebp + 8] - mov ecx, dword ptr [edi + LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr-L8$pb] - mov ecx, dword ptr [ecx] - mov edx, dword ptr [edi + LL_OBJC_CLASS_REFERENCES_NSObject$non_lazy_ptr-L8$pb] - mov edx, dword ptr [edx] - mov dword ptr [ebp - 16], eax - mov dword ptr [ebp - 12], edx - sub esp, 8 - lea eax, [ebp - 16] - push ecx - push eax - call _objc_msgSendSuper - add esp, 16 - mov esi, eax - test eax, eax - je LBB8_2 - sub esp, 4 - lea eax, [edi + L_anon.[ID].12-L8$pb] - push 4 - push eax - push esi - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - add esp, 4 - push eax - call _ivar_getOffset - add esp, 16 - mov byte ptr [esi + eax], 42 - sub esp, 4 - lea eax, [edi + L_anon.[ID].13-L8$pb] - push 4 - push eax - push esi - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - add esp, 4 - push eax - call _ivar_getOffset - add esp, 16 - mov dword ptr [esi + eax], 0 -LBB8_2: - mov eax, esi - add esp, 16 - pop esi - pop edi - pop ebp - ret - - .globl _class_method - .p2align 4, 0x90 -_class_method: - push ebp - mov ebp, esp - pop ebp - ret - - .globl _method - .p2align 4, 0x90 -_method: - push ebp - mov ebp, esp - pop ebp - ret - - .globl _method_bool - .p2align 4, 0x90 -_method_bool: - push ebp - mov ebp, esp - xor eax, eax - cmp byte ptr [ebp + 16], 0 - sete al - pop ebp - ret - - .globl _method_id - .p2align 4, 0x90 -_method_id: - push ebp - mov ebp, esp - push esi - sub esp, 20 - call L12$pb -L12$pb: - pop eax - mov esi, dword ptr [ebp + 8] - lea eax, [eax + L_anon.[ID].13-L12$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov eax, dword ptr [esi + eax] - test eax, eax - je LBB12_1 - mov dword ptr [esp], eax - call _objc_retain - jmp LBB12_3 -LBB12_1: - xor eax, eax -LBB12_3: - mov dword ptr [esp], eax - call _objc_autoreleaseReturnValue - add esp, 20 - pop esi - pop ebp - ret - - .globl _method_id_with_param - .p2align 4, 0x90 -_method_id_with_param: - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 12 - call L13$pb -L13$pb: - pop ebx - call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) - mov esi, eax - cmp byte ptr [ebp + 16], 0 - je LBB13_5 - mov edi, dword ptr [ebp + 8] - lea eax, [ebx + L_anon.[ID].13-L13$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], edi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov eax, dword ptr [edi + eax] - test eax, eax - je LBB13_2 - mov dword ptr [esp], eax - call _objc_retain - mov edi, eax - jmp LBB13_4 -LBB13_2: - xor edi, edi -LBB13_4: - mov dword ptr [esp], esi - call _objc_release - mov esi, edi -LBB13_5: - mov dword ptr [esp], esi - call _objc_autoreleaseReturnValue - add esp, 12 - pop esi - pop edi - pop ebx - pop ebp - ret - - .globl _copyWithZone - .p2align 4, 0x90 -_copyWithZone: - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 28 - call L14$pb -L14$pb: - pop ebx - call _get_obj - mov esi, eax - test eax, eax - je LBB14_5 - mov edi, dword ptr [ebp + 8] - lea ecx, [ebx + L_anon.[ID].12-L14$pb] - mov dword ptr [esp + 4], ecx - mov dword ptr [esp], edi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - movzx eax, byte ptr [edi + eax] - mov byte ptr [ebp - 13], al - lea eax, [ebx + L_anon.[ID].12-L14$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - movzx ecx, byte ptr [ebp - 13] - mov byte ptr [esi + eax], cl - lea ebx, [ebx + L_anon.[ID].13-L14$pb] - mov dword ptr [esp + 4], ebx - mov dword ptr [esp], edi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov eax, dword ptr [edi + eax] - test eax, eax - je LBB14_2 - mov dword ptr [esp], eax - call _objc_retain - mov edi, eax - jmp LBB14_4 -LBB14_2: - xor edi, edi -LBB14_4: - mov dword ptr [esp + 4], ebx - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov dword ptr [esi + eax], edi -LBB14_5: - mov eax, esi - add esp, 28 - pop esi - pop edi - pop ebx - pop ebp - ret - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].0: - .long SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) - .asciz "\004\000\000\000\004\000\000" - .long SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) - .long SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - - .section __TEXT,__const - .p2align 2, 0x0 -l_anon.[ID].1: - .byte 0 - - .p2align 2, 0x0 -l_anon.[ID].2: - .byte 19 - .space 19 - - .p2align 2, 0x0 -l_anon.[ID].3: - .byte 17 - .space 19 - - .p2align 2, 0x0 -l_anon.[ID].4: - .space 1 - .space 19 - -l_anon.[ID].5: - .ascii "_NSZone" - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].6: - .byte 28 - .space 3 - .long l_anon.[ID].5 - .asciz "\007\000\000" - .long l_anon.[ID].1 - .space 4 - - .p2align 2, 0x0 -l_anon.[ID].7: - .byte 25 - .space 3 - .long l_anon.[ID].6 - .space 12 - - .section __TEXT,__const -l_anon.[ID].8: - .ascii "called `Option::unwrap()` on a `None` value" - -l_anon.[ID].9: - .ascii "$RUSTC/library/std/src/sync/once.rs" - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].10: - .long l_anon.[ID].9 - .asciz "p\000\000\000\225\000\000\0002\000\000" - - .section __TEXT,__const -l_anon.[ID].11: - .ascii "CustomClassName" - - .section __TEXT,__literal4,4byte_literals -L_anon.[ID].12: - .ascii "_foo" - -L_anon.[ID].13: - .ascii "_obj" - - .section __TEXT,__const -l_anon.[ID].14: - .ascii "crates/$DIR/lib.rs" - - .p2align 2, 0x0 -l_anon.[ID].15: - .byte 5 - .space 19 - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].16: - .long l_anon.[ID].14 - .asciz "5\000\000\000\f\000\000\000\001\000\000" - -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),4,2 - .section __TEXT,__const -l_anon.[ID].17: - .ascii "NSCopying" - - .section __TEXT,__cstring,cstring_literals - .globl L_OBJC_METH_VAR_NAME_d874ee9262978be2 -L_OBJC_METH_VAR_NAME_d874ee9262978be2: - .asciz "classMethod" - - .section __OBJC,__message_refs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2: - .long L_OBJC_METH_VAR_NAME_d874ee9262978be2 - - .section __OBJC,__image_info - .globl L_OBJC_IMAGE_INFO_d874ee9262978be2 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_d874ee9262978be2: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__cstring,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc -L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc: - .asciz "method" - - .section __OBJC,__message_refs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc: - .long L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc - - .section __OBJC,__image_info - .globl L_OBJC_IMAGE_INFO_4539fd1dbda0cddc - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4539fd1dbda0cddc: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__cstring,cstring_literals - .globl L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 -L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5: - .asciz "methodBool:" - - .section __OBJC,__message_refs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5: - .long L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 - - .section __OBJC,__image_info - .globl L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__cstring,cstring_literals - .globl L_OBJC_METH_VAR_NAME_f7f521670860b0ce -L_OBJC_METH_VAR_NAME_f7f521670860b0ce: - .asciz "methodId" - - .section __OBJC,__message_refs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce: - .long L_OBJC_METH_VAR_NAME_f7f521670860b0ce - - .section __OBJC,__image_info - .globl L_OBJC_IMAGE_INFO_f7f521670860b0ce - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_f7f521670860b0ce: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__cstring,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6addfcf634c6232f -L_OBJC_METH_VAR_NAME_6addfcf634c6232f: - .asciz "methodIdWithParam:" - - .section __OBJC,__message_refs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f: - .long L_OBJC_METH_VAR_NAME_6addfcf634c6232f - - .section __OBJC,__image_info - .globl L_OBJC_IMAGE_INFO_6addfcf634c6232f - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6addfcf634c6232f: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__cstring,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 -L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166: - .asciz "copyWithZone:" - - .section __OBJC,__message_refs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166: - .long L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 - - .section __OBJC,__image_info - .globl L_OBJC_IMAGE_INFO_4a8c690dbc9d8166 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4a8c690dbc9d8166: - .asciz "\000\000\000\000@\000\000" - - .section __IMPORT,__pointers,non_lazy_symbol_pointers -LL_OBJC_CLASS_REFERENCES_NSObject$non_lazy_ptr: - .indirect_symbol L_OBJC_CLASS_REFERENCES_NSObject - .long 0 -LL_OBJC_SELECTOR_REFERENCES_dealloc$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_dealloc - .long 0 -LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_init - .long 0 -LL_OBJC_SELECTOR_REFERENCES_new$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_new - .long 0 - .subsections_via_symbols diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-x86.s b/crates/test-assembly/crates/test_declare_class/expected/apple-x86.s index 95b03257c..d3cea7aab 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-x86.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-x86.s @@ -1,852 +1,3 @@ .section __TEXT,__text,regular,pure_instructions .intel_syntax noprefix - .p2align 4, 0x90 -SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): - push ebp - mov ebp, esp - pop ebp - ret - - .p2align 4, 0x90 -SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 12 - call L1$pb -L1$pb: - pop esi - mov eax, dword ptr [ebp + 8] - mov eax, dword ptr [eax] - cmp byte ptr [eax], 0 - mov byte ptr [eax], 0 - je LBB1_5 - mov eax, dword ptr [esi + LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-L1$pb] - sub esp, 4 - lea edi, [esi + l_anon.[ID].11-L1$pb] - push dword ptr [eax] - push 15 - push edi - call SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) - add esp, 16 - test eax, eax - je LBB1_6 - mov dword ptr [ebp - 16], eax - sub esp, 8 - lea eax, [esi + l_anon.[ID].15-L1$pb] - lea ecx, [esi + L_anon.[ID].12-L1$pb] - lea ebx, [ebp - 16] - push eax - push 0 - push 1 - push 4 - push ecx - push ebx - call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) - add esp, 24 - lea ecx, [esi + l_anon.[ID].2-L1$pb] - lea eax, [esi + L_anon.[ID].13-L1$pb] - push ecx - push 2 - push 4 - push 4 - push eax - push ebx - call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) - add esp, 32 - mov eax, dword ptr [esi + LL_OBJC_SELECTOR_REFERENCES_dealloc$non_lazy_ptr-L1$pb] - sub esp, 8 - lea ecx, [esi + SYM(::class::{closure#0}::__objc2_dealloc, 0)-L1$pb] - lea edi, [esi + l_anon.[ID].3-L1$pb] - lea edx, [esi + l_anon.[ID].1-L1$pb] - push ecx - push edi - push 0 - push edx - mov edi, edx - push dword ptr [eax] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 32 - mov eax, dword ptr [esi + LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr-L1$pb] - sub esp, 8 - lea ecx, [esi + _init-L1$pb] - push ecx - lea ecx, [esi + l_anon.[ID].2-L1$pb] - push ecx - push 0 - push edi - push dword ptr [eax] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _class_method-L1$pb] - push eax - lea eax, [esi + l_anon.[ID].3-L1$pb] - push eax - push 0 - push edi - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_class_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _method-L1$pb] - push eax - lea eax, [esi + l_anon.[ID].3-L1$pb] - push eax - push 0 - push edi - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _method_bool-L1$pb] - lea ecx, [esi + l_anon.[ID].4-L1$pb] - push eax - push ecx - push 1 - push ecx - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _method_id-L1$pb] - push eax - lea edi, [esi + l_anon.[ID].2-L1$pb] - push edi - push 0 - lea eax, [esi + l_anon.[ID].1-L1$pb] - push eax - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + _method_id_with_param-L1$pb] - push eax - push edi - push 1 - lea eax, [esi + l_anon.[ID].4-L1$pb] - push eax - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 24 - lea eax, [esi + l_anon.[ID].17-L1$pb] - push 9 - push eax - call SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) - add esp, 16 - test eax, eax - je LBB1_4 - sub esp, 8 - push eax - push ebx - call SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) - add esp, 16 -LBB1_4: - sub esp, 8 - lea eax, [esi + _copyWithZone-L1$pb] - lea ecx, [esi + l_anon.[ID].7-L1$pb] - push eax - lea eax, [esi + l_anon.[ID].2-L1$pb] - push eax - push 1 - push ecx - push dword ptr [esi + L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166-L1$pb] - push ebx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - add esp, 20 - push dword ptr [ebp - 16] - call SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) - add esp, 28 - pop esi - pop edi - pop ebx - pop ebp - ret -LBB1_5: - sub esp, 4 - lea eax, [esi + l_anon.[ID].10-L1$pb] - lea ecx, [esi + l_anon.[ID].8-L1$pb] - push eax - push 43 - push ecx - call SYM(core::panicking::panic::GENERATED_ID, 0) -LBB1_6: - sub esp, 4 - lea eax, [esi + l_anon.[ID].16-L1$pb] - push eax - push 15 - push edi - call SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) - - .p2align 4, 0x90 -SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): - push ebp - mov ebp, esp - sub esp, 24 - mov eax, dword ptr [ebp + 8] - mov eax, dword ptr [eax] - mov dword ptr [ebp - 4], eax - lea eax, [ebp - 4] - mov dword ptr [esp], eax - call SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - add esp, 24 - pop ebp - ret - - .globl _get_class - .p2align 4, 0x90 -_get_class: - push ebp - mov ebp, esp - push edi - push esi - sub esp, 16 - call L3$pb -L3$pb: - pop esi - mov eax, dword ptr [esi + SYM(::class::REGISTER_CLASS, 0)-L3$pb] - cmp eax, 3 - jne LBB3_1 -LBB3_2: - sub esp, 8 - lea eax, [esi + l_anon.[ID].11-L3$pb] - push 15 - push eax - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - add esp, 16 - test eax, eax - je LBB3_4 - add esp, 16 - pop esi - pop edi - pop ebp - ret -LBB3_1: - mov byte ptr [ebp - 9], 1 - lea eax, [ebp - 9] - mov dword ptr [ebp - 16], eax - sub esp, 12 - lea eax, [esi + l_anon.[ID].16-L3$pb] - lea ecx, [esi + l_anon.[ID].0-L3$pb] - lea edx, [ebp - 16] - lea edi, [esi + SYM(::class::REGISTER_CLASS, 0)-L3$pb] - push eax - push ecx - push edx - push 0 - push edi - call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - add esp, 32 - jmp LBB3_2 -LBB3_4: - sub esp, 4 - lea eax, [esi + l_anon.[ID].16-L3$pb] - lea ecx, [esi + l_anon.[ID].8-L3$pb] - push eax - push 43 - push ecx - call SYM(core::panicking::panic::GENERATED_ID, 0) - - .globl _get_obj - .p2align 4, 0x90 -_get_obj: - push ebp - mov ebp, esp - push esi - push eax - call L4$pb -L4$pb: - pop esi - call _get_class - mov ecx, dword ptr [esi + LL_OBJC_SELECTOR_REFERENCES_new$non_lazy_ptr-L4$pb] - sub esp, 8 - push dword ptr [ecx] - push eax - call _objc_msgSend - add esp, 20 - pop esi - pop ebp - ret - - .globl _access_ivars - .p2align 4, 0x90 -_access_ivars: - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 12 - call L5$pb -L5$pb: - pop edi - call _get_obj - mov esi, eax - lea eax, [edi + L_anon.[ID].12-L5$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - movzx ebx, byte ptr [esi + eax] - lea eax, [edi + L_anon.[ID].13-L5$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov edi, dword ptr [esi + eax] - mov dword ptr [esp], esi - call _objc_release - mov eax, ebx - mov edx, edi - add esp, 12 - pop esi - pop edi - pop ebx - pop ebp - ret - - .globl SYM(::class, 0) - .p2align 4, 0x90 -SYM(::class, 0): - push ebp - mov ebp, esp - push edi - push esi - sub esp, 16 - call L6$pb -L6$pb: - pop esi - mov eax, dword ptr [esi + SYM(::class::REGISTER_CLASS, 0)-L6$pb] - cmp eax, 3 - jne LBB6_1 -LBB6_2: - sub esp, 8 - lea eax, [esi + l_anon.[ID].11-L6$pb] - push 15 - push eax - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - add esp, 16 - test eax, eax - je LBB6_4 - add esp, 16 - pop esi - pop edi - pop ebp - ret -LBB6_1: - mov byte ptr [ebp - 9], 1 - lea eax, [ebp - 9] - mov dword ptr [ebp - 16], eax - sub esp, 12 - lea eax, [esi + l_anon.[ID].16-L6$pb] - lea ecx, [esi + l_anon.[ID].0-L6$pb] - lea edx, [ebp - 16] - lea edi, [esi + SYM(::class::REGISTER_CLASS, 0)-L6$pb] - push eax - push ecx - push edx - push 0 - push edi - call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - add esp, 32 - jmp LBB6_2 -LBB6_4: - sub esp, 4 - lea eax, [esi + l_anon.[ID].16-L6$pb] - lea ecx, [esi + l_anon.[ID].8-L6$pb] - push eax - push 43 - push ecx - call SYM(core::panicking::panic::GENERATED_ID, 0) - - .p2align 4, 0x90 -SYM(::class::{closure#0}::__objc2_dealloc, 0): - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 28 - call L7$pb -L7$pb: - pop ebx - mov esi, dword ptr [ebp + 12] - mov edi, dword ptr [ebp + 8] - lea eax, [ebx + L_anon.[ID].13-L7$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], edi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov eax, dword ptr [edi + eax] - test eax, eax - je LBB7_2 - mov dword ptr [esp], eax - call _objc_release -LBB7_2: - mov eax, dword ptr [ebx + LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-L7$pb] - mov eax, dword ptr [eax] - mov dword ptr [ebp - 20], edi - mov dword ptr [ebp - 16], eax - mov dword ptr [esp + 4], esi - lea eax, [ebp - 20] - mov dword ptr [esp], eax - call _objc_msgSendSuper - add esp, 28 - pop esi - pop edi - pop ebx - pop ebp - ret - - .globl _init - .p2align 4, 0x90 -_init: - push ebp - mov ebp, esp - push edi - push esi - sub esp, 16 - call L8$pb -L8$pb: - pop edi - mov eax, dword ptr [ebp + 8] - mov ecx, dword ptr [edi + LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr-L8$pb] - mov ecx, dword ptr [ecx] - mov edx, dword ptr [edi + LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr-L8$pb] - mov edx, dword ptr [edx] - mov dword ptr [ebp - 16], eax - mov dword ptr [ebp - 12], edx - sub esp, 8 - lea eax, [ebp - 16] - push ecx - push eax - call _objc_msgSendSuper - add esp, 16 - mov esi, eax - test eax, eax - je LBB8_2 - sub esp, 4 - lea eax, [edi + L_anon.[ID].12-L8$pb] - push 4 - push eax - push esi - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - add esp, 4 - push eax - call _ivar_getOffset - add esp, 16 - mov byte ptr [esi + eax], 42 - sub esp, 4 - lea eax, [edi + L_anon.[ID].13-L8$pb] - push 4 - push eax - push esi - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - add esp, 4 - push eax - call _ivar_getOffset - add esp, 16 - mov dword ptr [esi + eax], 0 -LBB8_2: - mov eax, esi - add esp, 16 - pop esi - pop edi - pop ebp - ret - - .globl _class_method - .p2align 4, 0x90 -_class_method: - push ebp - mov ebp, esp - pop ebp - ret - - .globl _method - .p2align 4, 0x90 -_method: - push ebp - mov ebp, esp - pop ebp - ret - - .globl _method_bool - .p2align 4, 0x90 -_method_bool: - push ebp - mov ebp, esp - xor eax, eax - cmp byte ptr [ebp + 16], 0 - sete al - pop ebp - ret - - .globl _method_id - .p2align 4, 0x90 -_method_id: - push ebp - mov ebp, esp - push esi - sub esp, 20 - call L12$pb -L12$pb: - pop eax - mov esi, dword ptr [ebp + 8] - lea eax, [eax + L_anon.[ID].13-L12$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov eax, dword ptr [esi + eax] - test eax, eax - je LBB12_1 - mov dword ptr [esp], eax - call _objc_retain - jmp LBB12_3 -LBB12_1: - xor eax, eax -LBB12_3: - mov dword ptr [esp], eax - call _objc_autoreleaseReturnValue - add esp, 20 - pop esi - pop ebp - ret - - .globl _method_id_with_param - .p2align 4, 0x90 -_method_id_with_param: - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 12 - call L13$pb -L13$pb: - pop ebx - call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) - mov esi, eax - cmp byte ptr [ebp + 16], 0 - je LBB13_5 - mov edi, dword ptr [ebp + 8] - lea eax, [ebx + L_anon.[ID].13-L13$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], edi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov eax, dword ptr [edi + eax] - test eax, eax - je LBB13_2 - mov dword ptr [esp], eax - call _objc_retain - mov edi, eax - jmp LBB13_4 -LBB13_2: - xor edi, edi -LBB13_4: - mov dword ptr [esp], esi - call _objc_release - mov esi, edi -LBB13_5: - mov dword ptr [esp], esi - call _objc_autoreleaseReturnValue - add esp, 12 - pop esi - pop edi - pop ebx - pop ebp - ret - - .globl _copyWithZone - .p2align 4, 0x90 -_copyWithZone: - push ebp - mov ebp, esp - push ebx - push edi - push esi - sub esp, 28 - call L14$pb -L14$pb: - pop ebx - call _get_obj - mov esi, eax - test eax, eax - je LBB14_5 - mov edi, dword ptr [ebp + 8] - lea ecx, [ebx + L_anon.[ID].12-L14$pb] - mov dword ptr [esp + 4], ecx - mov dword ptr [esp], edi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - movzx eax, byte ptr [edi + eax] - mov byte ptr [ebp - 13], al - lea eax, [ebx + L_anon.[ID].12-L14$pb] - mov dword ptr [esp + 4], eax - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - movzx ecx, byte ptr [ebp - 13] - mov byte ptr [esi + eax], cl - lea ebx, [ebx + L_anon.[ID].13-L14$pb] - mov dword ptr [esp + 4], ebx - mov dword ptr [esp], edi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov eax, dword ptr [edi + eax] - test eax, eax - je LBB14_2 - mov dword ptr [esp], eax - call _objc_retain - mov edi, eax - jmp LBB14_4 -LBB14_2: - xor edi, edi -LBB14_4: - mov dword ptr [esp + 4], ebx - mov dword ptr [esp], esi - mov dword ptr [esp + 8], 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov dword ptr [esp], eax - call _ivar_getOffset - mov dword ptr [esi + eax], edi -LBB14_5: - mov eax, esi - add esp, 28 - pop esi - pop edi - pop ebx - pop ebp - ret - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].0: - .long SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) - .asciz "\004\000\000\000\004\000\000" - .long SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) - .long SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - - .section __TEXT,__const - .p2align 2, 0x0 -l_anon.[ID].1: - .byte 0 - - .p2align 2, 0x0 -l_anon.[ID].2: - .byte 19 - .space 19 - - .p2align 2, 0x0 -l_anon.[ID].3: - .byte 17 - .space 19 - - .p2align 2, 0x0 -l_anon.[ID].4: - .space 1 - .space 19 - -l_anon.[ID].5: - .ascii "_NSZone" - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].6: - .byte 28 - .space 3 - .long l_anon.[ID].5 - .asciz "\007\000\000" - .long l_anon.[ID].1 - .space 4 - - .p2align 2, 0x0 -l_anon.[ID].7: - .byte 25 - .space 3 - .long l_anon.[ID].6 - .space 12 - - .section __TEXT,__const -l_anon.[ID].8: - .ascii "called `Option::unwrap()` on a `None` value" - -l_anon.[ID].9: - .ascii "$RUSTC/library/std/src/sync/once.rs" - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].10: - .long l_anon.[ID].9 - .asciz "p\000\000\000\225\000\000\0002\000\000" - - .section __TEXT,__const -l_anon.[ID].11: - .ascii "CustomClassName" - - .section __TEXT,__literal4,4byte_literals -L_anon.[ID].12: - .ascii "_foo" - -L_anon.[ID].13: - .ascii "_obj" - - .section __TEXT,__const -l_anon.[ID].14: - .ascii "crates/$DIR/lib.rs" - - .p2align 2, 0x0 -l_anon.[ID].15: - .byte 5 - .space 19 - - .section __DATA,__const - .p2align 2, 0x0 -l_anon.[ID].16: - .long l_anon.[ID].14 - .asciz "5\000\000\000\f\000\000\000\001\000\000" - -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),4,2 - .section __TEXT,__const -l_anon.[ID].17: - .ascii "NSCopying" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_d874ee9262978be2 -L_OBJC_METH_VAR_NAME_d874ee9262978be2: - .asciz "classMethod" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2: - .long L_OBJC_METH_VAR_NAME_d874ee9262978be2 - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_d874ee9262978be2 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_d874ee9262978be2: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc -L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc: - .asciz "method" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc: - .long L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_4539fd1dbda0cddc - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4539fd1dbda0cddc: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 -L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5: - .asciz "methodBool:" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5: - .long L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_f7f521670860b0ce -L_OBJC_METH_VAR_NAME_f7f521670860b0ce: - .asciz "methodId" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce: - .long L_OBJC_METH_VAR_NAME_f7f521670860b0ce - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_f7f521670860b0ce - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_f7f521670860b0ce: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6addfcf634c6232f -L_OBJC_METH_VAR_NAME_6addfcf634c6232f: - .asciz "methodIdWithParam:" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f: - .long L_OBJC_METH_VAR_NAME_6addfcf634c6232f - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_6addfcf634c6232f - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6addfcf634c6232f: - .asciz "\000\000\000\000@\000\000" - - .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 -L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166: - .asciz "copyWithZone:" - - .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166 - .p2align 2, 0x0 -L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166: - .long L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 - - .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_4a8c690dbc9d8166 - .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4a8c690dbc9d8166: - .asciz "\000\000\000\000@\000\000" - - .section __IMPORT,__pointers,non_lazy_symbol_pointers -LL_OBJC_CLASSLIST_REFERENCES_$_NSObject$non_lazy_ptr: - .indirect_symbol L_OBJC_CLASSLIST_REFERENCES_$_NSObject - .long 0 -LL_OBJC_SELECTOR_REFERENCES_dealloc$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_dealloc - .long 0 -LL_OBJC_SELECTOR_REFERENCES_init$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_init - .long 0 -LL_OBJC_SELECTOR_REFERENCES_new$non_lazy_ptr: - .indirect_symbol L_OBJC_SELECTOR_REFERENCES_new - .long 0 - .subsections_via_symbols diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s index 1d6570287..4716eb56e 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s @@ -1,14 +1,28 @@ .section __TEXT,__text,regular,pure_instructions .intel_syntax noprefix .p2align 4, 0x90 -SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): +SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): push rbp mov rbp, rsp pop rbp ret .p2align 4, 0x90 -SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): +SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): + push rbp + mov rbp, rsp + pop rbp + ret + + .p2align 4, 0x90 +SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): + push rbp + mov rbp, rsp + pop rbp + ret + + .p2align 4, 0x90 +SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): push rbp mov rbp, rsp push r15 @@ -19,97 +33,75 @@ SYM(::call_once::<::class::{closure#0}::__objc2_dealloc, 0)] - mov rdi, rbx - mov rdx, r15 - xor ecx, ecx - mov r8, r12 - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] - mov rsi, qword ptr [rax] - lea r9, [rip + _init] mov rdi, rbx - mov rdx, r15 + mov rdx, r14 xor ecx, ecx - mov r8, r14 - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2] - lea r9, [rip + _class_method] - mov rdi, rbx - mov rdx, r15 - xor ecx, ecx - mov r8, r12 call SYM(objc2::declare::ClassBuilder::add_class_method_inner::GENERATED_ID, 0) - mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc] - lea r9, [rip + _method] + mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381] + lea r8, [rip + l_anon.[ID].5] + lea r9, [rip + _method_simple] mov rdi, rbx - mov rdx, r15 + mov rdx, r14 xor ecx, ecx - mov r8, r12 call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5] - lea r12, [rip + l_anon.[ID].4] + mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f] + lea r15, [rip + l_anon.[ID].6] lea r9, [rip + _method_bool] mov ecx, 1 mov rdi, rbx - mov rdx, r12 - mov r8, r12 + mov rdx, r15 + mov r8, r15 call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce] + mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00] + lea r12, [rip + l_anon.[ID].4] lea r9, [rip + _method_id] mov rdi, rbx - mov rdx, r15 + mov rdx, r14 xor ecx, ecx - mov r8, r14 + mov r8, r12 call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f] + mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09] lea r9, [rip + _method_id_with_param] mov ecx, 1 mov rdi, rbx - mov rdx, r12 - mov r8, r14 + mov rdx, r15 + mov r8, r12 call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - lea rdi, [rip + l_anon.[ID].17] + lea rdi, [rip + L_anon.[ID].23] + mov esi, 8 + call SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) + test rax, rax + je LBB3_4 + lea rdi, [rbp - 40] + mov rsi, rax + call SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) +LBB3_4: + lea rdi, [rip + l_anon.[ID].24] mov esi, 9 call SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) test rax, rax - je LBB1_4 + je LBB3_6 lea rdi, [rbp - 40] mov rsi, rax call SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) -LBB1_4: - mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166] - lea rdx, [rip + l_anon.[ID].7] - lea r8, [rip + l_anon.[ID].2] +LBB3_6: + mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571] + lea rdx, [rip + l_anon.[ID].9] + lea r8, [rip + l_anon.[ID].4] lea r9, [rip + _copyWithZone] lea rdi, [rbp - 40] mov ecx, 1 @@ -123,183 +115,569 @@ LBB1_4: pop r15 pop rbp ret -LBB1_5: - lea rdi, [rip + l_anon.[ID].8] - lea rdx, [rip + l_anon.[ID].10] +LBB3_7: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].13] + mov esi, 43 + call SYM(core::panicking::panic::GENERATED_ID, 0) +LBB3_8: + lea rdi, [rip + l_anon.[ID].15] + lea rdx, [rip + l_anon.[ID].22] + mov esi, 7 + call SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) + + .p2align 4, 0x90 +SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): + push rbp + mov rbp, rsp + push r15 + push r14 + push rbx + push rax + mov rax, qword ptr [rdi] + cmp byte ptr [rax], 0 + mov byte ptr [rax], 0 + je LBB4_3 + mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] + mov rdx, qword ptr [rax] + lea rdi, [rip + l_anon.[ID].16] + mov esi, 9 + call SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) + test rax, rax + je LBB4_4 + mov qword ptr [rbp - 32], rax + lea rsi, [rip + L_anon.[ID].18] + lea rbx, [rip + l_anon.[ID].4] + lea r14, [rbp - 32] + mov edx, 4 + mov ecx, 8 + mov rdi, r14 + mov r8d, 3 + mov r9, rbx + call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + lea rsi, [rip + l_anon.[ID].17] + mov edx, 11 + mov ecx, 8 + mov rdi, r14 + mov r8d, 3 + mov r9, rbx + call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPCREL] + mov rsi, qword ptr [rax] + lea r15, [rip + l_anon.[ID].3] + lea r8, [rip + l_anon.[ID].5] + lea r9, [rip + SYM(::class::{closure#0}::__objc2_dealloc, 0)] + mov rdi, r14 + mov rdx, r15 + xor ecx, ecx + call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] + mov rsi, qword ptr [rax] + lea r9, [rip + _init_drop_ivars] + mov rdi, r14 + mov rdx, r15 + xor ecx, ecx + mov r8, rbx + call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + mov rdi, qword ptr [rbp - 32] + call SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) + add rsp, 8 + pop rbx + pop r14 + pop r15 + pop rbp + ret +LBB4_3: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].13] mov esi, 43 call SYM(core::panicking::panic::GENERATED_ID, 0) -LBB1_6: +LBB4_4: + lea rdi, [rip + l_anon.[ID].16] + lea rdx, [rip + l_anon.[ID].28] + mov esi, 9 + call SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) + + .p2align 4, 0x90 +SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): + push rbp + mov rbp, rsp + push r14 + push rbx + sub rsp, 16 + mov rax, qword ptr [rdi] + cmp byte ptr [rax], 0 + mov byte ptr [rax], 0 + je LBB5_3 + mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] + mov rdx, qword ptr [rax] + lea rdi, [rip + l_anon.[ID].14] + mov esi, 15 + call SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) + test rax, rax + je LBB5_4 + mov qword ptr [rbp - 24], rax + lea rsi, [rip + L_anon.[ID].20] + lea r9, [rip + l_anon.[ID].25] + lea rbx, [rbp - 24] + mov edx, 4 + mov ecx, 1 + mov rdi, rbx + xor r8d, r8d + call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + lea rsi, [rip + L_anon.[ID].19] + lea r9, [rip + l_anon.[ID].26] + mov edx, 4 + mov ecx, 4 + mov rdi, rbx + mov r8d, 2 + call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPCREL] + mov rsi, qword ptr [rax] + lea r14, [rip + l_anon.[ID].3] + lea r8, [rip + l_anon.[ID].5] + lea r9, [rip + SYM(::class::{closure#0}::__objc2_dealloc, 0)] + mov rdi, rbx + mov rdx, r14 + xor ecx, ecx + call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] + mov rsi, qword ptr [rax] + lea r8, [rip + l_anon.[ID].4] + lea r9, [rip + _init_forgetable_ivars] + mov rdi, rbx + mov rdx, r14 + xor ecx, ecx + call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + mov rdi, qword ptr [rbp - 24] + call SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) + add rsp, 16 + pop rbx + pop r14 + pop rbp + ret +LBB5_3: lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].16] + lea rdx, [rip + l_anon.[ID].13] + mov esi, 43 + call SYM(core::panicking::panic::GENERATED_ID, 0) +LBB5_4: + lea rdi, [rip + l_anon.[ID].14] + lea rdx, [rip + l_anon.[ID].27] mov esi, 15 call SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) .p2align 4, 0x90 -SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): + push rbp + mov rbp, rsp + sub rsp, 16 + mov rax, qword ptr [rdi] + mov qword ptr [rbp - 8], rax + lea rdi, [rbp - 8] + call SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + add rsp, 16 + pop rbp + ret + + .p2align 4, 0x90 +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): + push rbp + mov rbp, rsp + sub rsp, 16 + mov rax, qword ptr [rdi] + mov qword ptr [rbp - 8], rax + lea rdi, [rbp - 8] + call SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + add rsp, 16 + pop rbp + ret + + .p2align 4, 0x90 +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): push rbp mov rbp, rsp sub rsp, 16 mov rax, qword ptr [rdi] mov qword ptr [rbp - 8], rax lea rdi, [rbp - 8] - call SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + call SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) add rsp, 16 pop rbp - ret + ret + + .globl _access_forgetable_ivars_class + .p2align 4, 0x90 +_access_forgetable_ivars_class: + push rbp + mov rbp, rsp + sub rsp, 16 + mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] + cmp rax, 3 + jne LBB9_1 +LBB9_2: + lea rdi, [rip + l_anon.[ID].14] + mov esi, 15 + call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + test rax, rax + je LBB9_4 + add rsp, 16 + pop rbp + ret +LBB9_1: + mov byte ptr [rbp - 1], 1 + lea rax, [rbp - 1] + mov qword ptr [rbp - 16], rax + lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] + lea rcx, [rip + l_anon.[ID].2] + lea r8, [rip + l_anon.[ID].27] + lea rdx, [rbp - 16] + xor esi, esi + call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + jmp LBB9_2 +LBB9_4: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].27] + mov esi, 43 + call SYM(core::panicking::panic::GENERATED_ID, 0) + + .globl _access_forgetable_ivars + .p2align 4, 0x90 +_access_forgetable_ivars: + push rbp + mov rbp, rsp + push r14 + push rbx + mov rbx, rdi + lea rsi, [rip + L_anon.[ID].20] + mov edx, 4 + call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + mov rdi, rax + call _ivar_getOffset + movzx r14d, byte ptr [rbx + rax] + lea rsi, [rip + L_anon.[ID].19] + mov edx, 4 + mov rdi, rbx + call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + mov rdi, rax + call _ivar_getOffset + mov edx, dword ptr [rbx + rax] + mov eax, r14d + pop rbx + pop r14 + pop rbp + ret + + .globl SYM(::drop, 0) + .p2align 4, 0x90 +SYM(::drop, 0): + push rbp + mov rbp, rsp + ## InlineAsm Start + ## InlineAsm End + pop rbp + ret + + .globl _access_drop_ivars_class + .p2align 4, 0x90 +_access_drop_ivars_class: + push rbp + mov rbp, rsp + sub rsp, 16 + mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] + cmp rax, 3 + jne LBB12_1 +LBB12_2: + lea rdi, [rip + l_anon.[ID].16] + mov esi, 9 + call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + test rax, rax + je LBB12_4 + add rsp, 16 + pop rbp + ret +LBB12_1: + mov byte ptr [rbp - 1], 1 + lea rax, [rbp - 1] + mov qword ptr [rbp - 16], rax + lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] + lea rcx, [rip + l_anon.[ID].1] + lea r8, [rip + l_anon.[ID].28] + lea rdx, [rbp - 16] + xor esi, esi + call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + jmp LBB12_2 +LBB12_4: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].28] + mov esi, 43 + call SYM(core::panicking::panic::GENERATED_ID, 0) + + .globl _access_drop_ivars + .p2align 4, 0x90 +_access_drop_ivars: + push rbp + mov rbp, rsp + push rbx + push rax + mov rbx, rdi + lea rsi, [rip + L_anon.[ID].18] + mov edx, 4 + call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) + mov rdi, rax + call _ivar_getOffset + mov rax, qword ptr [rbx + rax] + add rsp, 8 + pop rbx + pop rbp + ret + + .globl SYM(::class, 0) + .p2align 4, 0x90 +SYM(::class, 0): + push rbp + mov rbp, rsp + sub rsp, 16 + mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] + cmp rax, 3 + jne LBB14_1 +LBB14_2: + lea rdi, [rip + l_anon.[ID].15] + mov esi, 7 + call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + test rax, rax + je LBB14_4 + add rsp, 16 + pop rbp + ret +LBB14_1: + mov byte ptr [rbp - 1], 1 + lea rax, [rbp - 1] + mov qword ptr [rbp - 16], rax + lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] + lea rcx, [rip + l_anon.[ID].0] + lea r8, [rip + l_anon.[ID].22] + lea rdx, [rbp - 16] + xor esi, esi + call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + jmp LBB14_2 +LBB14_4: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].22] + mov esi, 43 + call SYM(core::panicking::panic::GENERATED_ID, 0) + + .globl _get_class + .p2align 4, 0x90 +_get_class: + push rbp + mov rbp, rsp + sub rsp, 16 + mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] + cmp rax, 3 + jne LBB15_1 +LBB15_2: + lea rdi, [rip + l_anon.[ID].15] + mov esi, 7 + call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + test rax, rax + je LBB15_4 + add rsp, 16 + pop rbp + ret +LBB15_1: + mov byte ptr [rbp - 1], 1 + lea rax, [rbp - 1] + mov qword ptr [rbp - 16], rax + lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] + lea rcx, [rip + l_anon.[ID].0] + lea r8, [rip + l_anon.[ID].22] + lea rdx, [rbp - 16] + xor esi, esi + call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + jmp LBB15_2 +LBB15_4: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].22] + mov esi, 43 + call SYM(core::panicking::panic::GENERATED_ID, 0) + + .globl _method_simple + .p2align 4, 0x90 +_method_simple: + push rbp + mov rbp, rsp + pop rbp + ret + + .globl _method_bool + .p2align 4, 0x90 +_method_bool: + push rbp + mov rbp, rsp + xor eax, eax + test dl, dl + sete al + pop rbp + ret + + .globl _method_id + .p2align 4, 0x90 +_method_id: + push rbp + mov rbp, rsp + sub rsp, 16 + mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] + cmp rax, 3 + jne LBB18_1 +LBB18_2: + lea rdi, [rip + l_anon.[ID].15] + mov esi, 7 + call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + test rax, rax + je LBB18_4 + mov rcx, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_new@GOTPCREL] + mov rsi, qword ptr [rcx] + mov rdi, rax + call _objc_msgSend + mov rdi, rax + call _objc_autoreleaseReturnValue + add rsp, 16 + pop rbp + ret +LBB18_1: + mov byte ptr [rbp - 1], 1 + lea rax, [rbp - 1] + mov qword ptr [rbp - 16], rax + lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] + lea rcx, [rip + l_anon.[ID].0] + lea r8, [rip + l_anon.[ID].22] + lea rdx, [rbp - 16] + xor esi, esi + call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + jmp LBB18_2 +LBB18_4: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].22] + mov esi, 43 + call SYM(core::panicking::panic::GENERATED_ID, 0) + + .globl _method_id_with_param + .p2align 4, 0x90 +_method_id_with_param: + push rbp + mov rbp, rsp + push r14 + push rbx + mov r14d, edx + call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) + mov rbx, rax + test r14b, r14b + je LBB19_2 + call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) + mov r14, rax + mov rdi, rbx + call _objc_release + mov rbx, r14 +LBB19_2: + mov rdi, rbx + pop rbx + pop r14 + pop rbp + jmp _objc_autoreleaseReturnValue - .globl _get_class + .globl _copyWithZone .p2align 4, 0x90 -_get_class: +_copyWithZone: push rbp mov rbp, rsp sub rsp, 16 - mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] + mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB3_1 -LBB3_2: - lea rdi, [rip + l_anon.[ID].11] - mov esi, 15 + jne LBB20_1 +LBB20_2: + lea rdi, [rip + l_anon.[ID].15] + mov esi, 7 call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) test rax, rax - je LBB3_4 + je LBB20_4 + mov rcx, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_new@GOTPCREL] + mov rsi, qword ptr [rcx] + mov rdi, rax + call _objc_msgSend add rsp, 16 pop rbp ret -LBB3_1: +LBB20_1: mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax - lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] + lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].16] + lea r8, [rip + l_anon.[ID].22] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB3_2 -LBB3_4: - lea rdi, [rip + l_anon.[ID].8] - lea rdx, [rip + l_anon.[ID].16] + jmp LBB20_2 +LBB20_4: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].22] mov esi, 43 call SYM(core::panicking::panic::GENERATED_ID, 0) - .globl _get_obj - .p2align 4, 0x90 -_get_obj: - push rbp - mov rbp, rsp - call _get_class - mov rcx, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_new@GOTPCREL] - mov rsi, qword ptr [rcx] - mov rdi, rax - pop rbp - jmp _objc_msgSend - - .globl _access_ivars - .p2align 4, 0x90 -_access_ivars: - push rbp - mov rbp, rsp - push r15 - push r14 - push rbx - push rax - call _get_obj - mov rbx, rax - lea rsi, [rip + L_anon.[ID].12] - mov edx, 4 - mov rdi, rax - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - movzx r14d, byte ptr [rbx + rax] - lea rsi, [rip + L_anon.[ID].13] - mov edx, 4 - mov rdi, rbx - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov r15, qword ptr [rbx + rax] - mov rdi, rbx - call _objc_release - mov eax, r14d - mov rdx, r15 - add rsp, 8 - pop rbx - pop r14 - pop r15 - pop rbp - ret - - .globl SYM(::class, 0) + .globl SYM(::class, 0) .p2align 4, 0x90 -SYM(::class, 0): +SYM(::class, 0): push rbp mov rbp, rsp sub rsp, 16 - mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] + mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB6_1 -LBB6_2: - lea rdi, [rip + l_anon.[ID].11] + jne LBB21_1 +LBB21_2: + lea rdi, [rip + l_anon.[ID].14] mov esi, 15 call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) test rax, rax - je LBB6_4 + je LBB21_4 add rsp, 16 pop rbp ret -LBB6_1: +LBB21_1: mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax - lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] - lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].16] + lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] + lea rcx, [rip + l_anon.[ID].2] + lea r8, [rip + l_anon.[ID].27] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB6_2 -LBB6_4: - lea rdi, [rip + l_anon.[ID].8] - lea rdx, [rip + l_anon.[ID].16] + jmp LBB21_2 +LBB21_4: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].27] mov esi, 43 call SYM(core::panicking::panic::GENERATED_ID, 0) .p2align 4, 0x90 -SYM(::class::{closure#0}::__objc2_dealloc, 0): +SYM(::class::{closure#0}::__objc2_dealloc, 0): push rbp mov rbp, rsp - push r14 - push rbx sub rsp, 16 - mov rbx, rsi - mov r14, rdi - lea rsi, [rip + L_anon.[ID].13] - mov edx, 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov rdi, qword ptr [r14 + rax] - test rdi, rdi - je LBB7_2 - call _objc_release -LBB7_2: mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] mov rax, qword ptr [rax] - mov qword ptr [rbp - 32], r14 - mov qword ptr [rbp - 24], rax - lea rdi, [rbp - 32] - mov rsi, rbx + mov qword ptr [rbp - 16], rdi + mov qword ptr [rbp - 8], rax + lea rdi, [rbp - 16] call _objc_msgSendSuper add rsp, 16 - pop rbx - pop r14 pop rbp ret - .globl _init + .globl _init_forgetable_ivars .p2align 4, 0x90 -_init: +_init_forgetable_ivars: push rbp mov rbp, rsp push rbx @@ -314,378 +692,399 @@ _init: call _objc_msgSendSuper mov rbx, rax test rax, rax - je LBB8_2 - lea rsi, [rip + L_anon.[ID].12] + je LBB23_2 + lea rsi, [rip + L_anon.[ID].20] mov edx, 4 mov rdi, rbx call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) mov rdi, rax call _ivar_getOffset mov byte ptr [rbx + rax], 42 - lea rsi, [rip + L_anon.[ID].13] + lea rsi, [rip + L_anon.[ID].19] mov edx, 4 mov rdi, rbx call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) mov rdi, rax call _ivar_getOffset - mov qword ptr [rbx + rax], 0 -LBB8_2: + mov dword ptr [rbx + rax], 43 +LBB23_2: mov rax, rbx add rsp, 24 pop rbx pop rbp ret - .globl _class_method - .p2align 4, 0x90 -_class_method: - push rbp - mov rbp, rsp - pop rbp - ret - - .globl _method - .p2align 4, 0x90 -_method: - push rbp - mov rbp, rsp - pop rbp - ret - - .globl _method_bool + .globl SYM(::class, 0) .p2align 4, 0x90 -_method_bool: +SYM(::class, 0): push rbp mov rbp, rsp - xor eax, eax - test dl, dl - sete al + sub rsp, 16 + mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] + cmp rax, 3 + jne LBB24_1 +LBB24_2: + lea rdi, [rip + l_anon.[ID].16] + mov esi, 9 + call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) + test rax, rax + je LBB24_4 + add rsp, 16 pop rbp ret +LBB24_1: + mov byte ptr [rbp - 1], 1 + lea rax, [rbp - 1] + mov qword ptr [rbp - 16], rax + lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] + lea rcx, [rip + l_anon.[ID].1] + lea r8, [rip + l_anon.[ID].28] + lea rdx, [rbp - 16] + xor esi, esi + call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + jmp LBB24_2 +LBB24_4: + lea rdi, [rip + l_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].28] + mov esi, 43 + call SYM(core::panicking::panic::GENERATED_ID, 0) - .globl _method_id .p2align 4, 0x90 -_method_id: +SYM(::class::{closure#0}::__objc2_dealloc, 0): push rbp mov rbp, rsp + push r14 push rbx - push rax - mov rbx, rdi - lea rsi, [rip + L_anon.[ID].13] + sub rsp, 16 + mov rbx, rsi + mov r14, rdi + call SYM(::drop, 0) + lea rsi, [rip + L_anon.[ID].18] mov edx, 4 + mov rdi, r14 call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) mov rdi, rax call _ivar_getOffset - mov rdi, qword ptr [rbx + rax] + mov rdi, qword ptr [r14 + rax] test rdi, rdi - je LBB12_1 - call _objc_retain - mov rdi, rax - add rsp, 8 - pop rbx - pop rbp - jmp _objc_autoreleaseReturnValue -LBB12_1: - xor edi, edi - add rsp, 8 - pop rbx - pop rbp - jmp _objc_autoreleaseReturnValue - - .globl _method_id_with_param - .p2align 4, 0x90 -_method_id_with_param: - push rbp - mov rbp, rsp - push r15 - push r14 - push rbx - push rax - mov r15d, edx - mov r14, rdi - call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) - mov rbx, rax - test r15b, r15b - je LBB13_5 - lea rsi, [rip + L_anon.[ID].13] - mov edx, 4 + je LBB25_2 + call _objc_release +LBB25_2: + lea rsi, [rip + l_anon.[ID].17] + mov edx, 11 mov rdi, r14 call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) mov rdi, rax call _ivar_getOffset mov rdi, qword ptr [r14 + rax] test rdi, rdi - je LBB13_2 - call _objc_retain - mov r14, rax - jmp LBB13_4 -LBB13_2: - xor r14d, r14d -LBB13_4: - mov rdi, rbx + je LBB25_4 call _objc_release - mov rbx, r14 -LBB13_5: - mov rdi, rbx - add rsp, 8 +LBB25_4: + mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] + mov rax, qword ptr [rax] + mov qword ptr [rbp - 32], r14 + mov qword ptr [rbp - 24], rax + lea rdi, [rbp - 32] + mov rsi, rbx + call _objc_msgSendSuper + add rsp, 16 pop rbx pop r14 - pop r15 pop rbp - jmp _objc_autoreleaseReturnValue + ret - .globl _copyWithZone + .globl _init_drop_ivars .p2align 4, 0x90 -_copyWithZone: +_init_drop_ivars: push rbp mov rbp, rsp - push r15 push r14 - push r12 push rbx - mov r14, rdi - call _get_obj + sub rsp, 16 + mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] + mov rsi, qword ptr [rax] + mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] + mov rax, qword ptr [rax] + mov qword ptr [rbp - 32], rdi + mov qword ptr [rbp - 24], rax + lea rdi, [rbp - 32] + call _objc_msgSendSuper mov rbx, rax test rax, rax - je LBB14_5 - lea r15, [rip + L_anon.[ID].12] - mov edx, 4 - mov rdi, r14 - mov rsi, r15 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - movzx r12d, byte ptr [r14 + rax] + je LBB26_2 + call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) + mov r14, rax + lea rsi, [rip + L_anon.[ID].18] mov edx, 4 mov rdi, rbx - mov rsi, r15 call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) mov rdi, rax call _ivar_getOffset - mov byte ptr [rbx + rax], r12b - lea rsi, [rip + L_anon.[ID].13] - mov edx, 4 - mov rdi, r14 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov rdi, qword ptr [r14 + rax] - test rdi, rdi - je LBB14_2 - call _objc_retain + mov qword ptr [rbx + rax], r14 + call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) mov r14, rax - jmp LBB14_4 -LBB14_2: - xor r14d, r14d -LBB14_4: - lea rsi, [rip + L_anon.[ID].13] - mov edx, 4 + lea rsi, [rip + l_anon.[ID].17] + mov edx, 11 mov rdi, rbx call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) mov rdi, rax call _ivar_getOffset mov qword ptr [rbx + rax], r14 -LBB14_5: +LBB26_2: mov rax, rbx + add rsp, 16 pop rbx - pop r12 pop r14 - pop r15 pop rbp ret .section __DATA,__const .p2align 3, 0x0 l_anon.[ID].0: - .quad SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) + .quad SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) .asciz "\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000" - .quad SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) - .quad SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + .quad SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) + .quad SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - .section __TEXT,__const .p2align 3, 0x0 l_anon.[ID].1: - .byte 0 + .quad SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) + .asciz "\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000" + .quad SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) + .quad SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) .p2align 3, 0x0 l_anon.[ID].2: + .quad SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0) + .asciz "\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000" + .quad SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0) + .quad SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + + .section __TEXT,__const + .p2align 3, 0x0 +l_anon.[ID].3: + .byte 0 + + .p2align 3, 0x0 +l_anon.[ID].4: .byte 19 .space 39 .p2align 3, 0x0 -l_anon.[ID].3: +l_anon.[ID].5: .byte 17 .space 39 .p2align 3, 0x0 -l_anon.[ID].4: +l_anon.[ID].6: .space 1 .space 39 -l_anon.[ID].5: +l_anon.[ID].7: .ascii "_NSZone" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].6: +l_anon.[ID].8: .byte 28 .space 7 - .quad l_anon.[ID].5 + .quad l_anon.[ID].7 .asciz "\007\000\000\000\000\000\000" - .quad l_anon.[ID].1 + .quad l_anon.[ID].3 .space 8 .p2align 3, 0x0 -l_anon.[ID].7: +l_anon.[ID].9: .byte 25 .space 7 - .quad l_anon.[ID].6 + .quad l_anon.[ID].8 .space 24 .section __TEXT,__const -l_anon.[ID].8: + .p2align 3, 0x0 +l_anon.[ID].10: + .byte 21 + .space 39 + +l_anon.[ID].11: .ascii "called `Option::unwrap()` on a `None` value" -l_anon.[ID].9: +l_anon.[ID].12: .ascii "$RUSTC/library/std/src/sync/once.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].10: - .quad l_anon.[ID].9 +l_anon.[ID].13: + .quad l_anon.[ID].12 .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" .section __TEXT,__const -l_anon.[ID].11: - .ascii "CustomClassName" +l_anon.[ID].14: + .ascii "ForgetableIvars" - .section __TEXT,__literal4,4byte_literals -L_anon.[ID].12: - .ascii "_foo" +l_anon.[ID].15: + .ascii "NoIvars" + +l_anon.[ID].16: + .ascii "DropIvars" -L_anon.[ID].13: +l_anon.[ID].17: + .ascii "_obj_option" + + .section __TEXT,__literal4,4byte_literals +L_anon.[ID].18: .ascii "_obj" +L_anon.[ID].19: + .ascii "_bar" + +L_anon.[ID].20: + .ascii "_foo" + .section __TEXT,__const -l_anon.[ID].14: +l_anon.[ID].21: .ascii "crates/$DIR/lib.rs" - .p2align 3, 0x0 -l_anon.[ID].15: - .byte 5 - .space 39 - .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].16: - .quad l_anon.[ID].14 - .asciz "5\000\000\000\000\000\000\000\f\000\000\000\001\000\000" +l_anon.[ID].22: + .quad l_anon.[ID].21 + .asciz "5\000\000\000\000\000\000\000\017\000\000\000\001\000\000" + +.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 + .section __TEXT,__literal8,8byte_literals +L_anon.[ID].23: + .ascii "NSObject" -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .section __TEXT,__const -l_anon.[ID].17: +l_anon.[ID].24: .ascii "NSCopying" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_d874ee9262978be2 -L_OBJC_METH_VAR_NAME_d874ee9262978be2: + .globl L_OBJC_METH_VAR_NAME_f249b8b52b9a1205 +L_OBJC_METH_VAR_NAME_f249b8b52b9a1205: .asciz "classMethod" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2 + .globl L_OBJC_SELECTOR_REFERENCES_f249b8b52b9a1205 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_d874ee9262978be2: - .quad L_OBJC_METH_VAR_NAME_d874ee9262978be2 +L_OBJC_SELECTOR_REFERENCES_f249b8b52b9a1205: + .quad L_OBJC_METH_VAR_NAME_f249b8b52b9a1205 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_d874ee9262978be2 + .globl L_OBJC_IMAGE_INFO_f249b8b52b9a1205 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_d874ee9262978be2: +L_OBJC_IMAGE_INFO_f249b8b52b9a1205: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc -L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc: + .globl L_OBJC_METH_VAR_NAME_2607fe9c3979c381 +L_OBJC_METH_VAR_NAME_2607fe9c3979c381: .asciz "method" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc + .globl L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_4539fd1dbda0cddc: - .quad L_OBJC_METH_VAR_NAME_4539fd1dbda0cddc +L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381: + .quad L_OBJC_METH_VAR_NAME_2607fe9c3979c381 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_4539fd1dbda0cddc + .globl L_OBJC_IMAGE_INFO_2607fe9c3979c381 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4539fd1dbda0cddc: +L_OBJC_IMAGE_INFO_2607fe9c3979c381: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 -L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5: + .globl L_OBJC_METH_VAR_NAME_5a4952192b00de7f +L_OBJC_METH_VAR_NAME_5a4952192b00de7f: .asciz "methodBool:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5 + .globl L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_2b1b3a94e0ece2e5: - .quad L_OBJC_METH_VAR_NAME_2b1b3a94e0ece2e5 +L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f: + .quad L_OBJC_METH_VAR_NAME_5a4952192b00de7f .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5 + .globl L_OBJC_IMAGE_INFO_5a4952192b00de7f .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_2b1b3a94e0ece2e5: +L_OBJC_IMAGE_INFO_5a4952192b00de7f: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_f7f521670860b0ce -L_OBJC_METH_VAR_NAME_f7f521670860b0ce: + .globl L_OBJC_METH_VAR_NAME_bf0386bc74a73c00 +L_OBJC_METH_VAR_NAME_bf0386bc74a73c00: .asciz "methodId" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce + .globl L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_f7f521670860b0ce: - .quad L_OBJC_METH_VAR_NAME_f7f521670860b0ce +L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00: + .quad L_OBJC_METH_VAR_NAME_bf0386bc74a73c00 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_f7f521670860b0ce + .globl L_OBJC_IMAGE_INFO_bf0386bc74a73c00 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_f7f521670860b0ce: +L_OBJC_IMAGE_INFO_bf0386bc74a73c00: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6addfcf634c6232f -L_OBJC_METH_VAR_NAME_6addfcf634c6232f: + .globl L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09 +L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09: .asciz "methodIdWithParam:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f + .globl L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_6addfcf634c6232f: - .quad L_OBJC_METH_VAR_NAME_6addfcf634c6232f +L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09: + .quad L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_6addfcf634c6232f + .globl L_OBJC_IMAGE_INFO_6f0ab2a047fe4a09 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6addfcf634c6232f: +L_OBJC_IMAGE_INFO_6f0ab2a047fe4a09: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 -L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166: + .globl L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571 +L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571: .asciz "copyWithZone:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166 + .globl L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_4a8c690dbc9d8166: - .quad L_OBJC_METH_VAR_NAME_4a8c690dbc9d8166 +L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571: + .quad L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_4a8c690dbc9d8166 + .globl L_OBJC_IMAGE_INFO_062e7a5fdd2d2571 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_4a8c690dbc9d8166: +L_OBJC_IMAGE_INFO_062e7a5fdd2d2571: .asciz "\000\000\000\000@\000\000" + .section __TEXT,__const + .p2align 3, 0x0 +l_anon.[ID].25: + .byte 5 + .space 39 + + .p2align 3, 0x0 +l_anon.[ID].26: + .byte 7 + .space 39 + + .section __DATA,__const + .p2align 3, 0x0 +l_anon.[ID].27: + .quad l_anon.[ID].21 + .asciz "5\000\000\000\000\000\000\000I\000\000\000\001\000\000" + +.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 + .p2align 3, 0x0 +l_anon.[ID].28: + .quad l_anon.[ID].21 + .asciz "5\000\000\000\000\000\000\000u\000\000\000\001\000\000" + +.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .subsections_via_symbols diff --git a/crates/test-assembly/crates/test_declare_class/lib.rs b/crates/test-assembly/crates/test_declare_class/lib.rs index ea181ca05..5db61d5b4 100644 --- a/crates/test-assembly/crates/test_declare_class/lib.rs +++ b/crates/test-assembly/crates/test_declare_class/lib.rs @@ -1,51 +1,37 @@ //! Test assembly output of `declare_class!`. #![deny(unsafe_op_in_unsafe_fn)] +// Limit to Apple targets only, since we don't particularly care about GNUStep code-size for now. #![cfg(feature = "apple")] -use core::ptr::{self}; +// Limit to 64-bit since we don't do anything special on other targets, and the assembly files are _huge_. +#![cfg(target_pointer_width = "64")] +use core::ptr; -use icrate::Foundation::{NSCopying, NSObject}; +use icrate::Foundation::{NSCopying, NSObject, NSObjectProtocol, NSZone}; use objc2::declare::{Ivar, IvarDrop, IvarEncode}; use objc2::rc::Id; -use objc2::runtime::{AnyClass, NSZone}; +use objc2::runtime::AnyClass; use objc2::{declare_class, msg_send, msg_send_id, mutability, ClassType}; declare_class!( #[no_mangle] - pub struct Custom { - foo: IvarEncode, - obj: IvarDrop>, "_obj">, - } - - mod ivars; + pub struct NoIvars; - unsafe impl ClassType for Custom { + unsafe impl ClassType for NoIvars { type Super = NSObject; type Mutability = mutability::InteriorMutable; - const NAME: &'static str = "CustomClassName"; + const NAME: &'static str = "NoIvars"; } - unsafe impl Custom { - #[no_mangle] - #[method(init)] - unsafe fn init(this: *mut Self) -> *mut Self { - let this: Option<&mut Self> = unsafe { msg_send![super(this), init] }; - - this.map(|this| { - Ivar::write(&mut this.foo, 42); - Ivar::write(&mut this.obj, None); - let this: *mut Self = this; - this - }) - .unwrap_or_else(ptr::null_mut) - } - + unsafe impl NoIvars { #[no_mangle] #[method(classMethod)] - fn class_method() {} + fn get_class() -> &'static AnyClass { + Self::class() + } #[no_mangle] #[method(method)] - fn method(&self) {} + fn method_simple(&self) {} #[no_mangle] #[method(methodBool:)] @@ -56,60 +42,125 @@ declare_class!( #[no_mangle] #[method_id(methodId)] fn method_id(&self) -> Option> { - self.obj.clone() + unsafe { msg_send_id![Self::class(), new] } } // Test that `objc_autoreleaseReturnValue` is tail-called #[no_mangle] #[method_id(methodIdWithParam:)] fn method_id_with_param(&self, param: bool) -> Option> { - // Explicitly create outside condition + // Intentionally create this outside condition let obj = NSObject::new(); if param { - self.obj.clone() + Some(NSObject::new()) } else { Some(obj) } } } - unsafe impl NSCopying for Custom { + unsafe impl NSObjectProtocol for NoIvars {} + + unsafe impl NSCopying for NoIvars { #[no_mangle] #[method_id(copyWithZone:)] fn copyWithZone(&self, _zone: *const NSZone) -> Option> { - get_obj().map(|new| { - let hack = Id::as_ptr(&new) as *mut Self; - let hack = unsafe { &mut *hack }; + unsafe { msg_send_id![Self::class(), new] } + } + } +); + +declare_class!( + #[no_mangle] + pub struct ForgetableIvars { + foo: IvarEncode, + bar: IvarEncode, + } + + mod forgetable_ivars; + + unsafe impl ClassType for ForgetableIvars { + type Super = NSObject; + type Mutability = mutability::InteriorMutable; + const NAME: &'static str = "ForgetableIvars"; + } - Ivar::write(&mut hack.foo, *self.foo); - Ivar::write(&mut hack.obj, self.obj.clone()); - new + unsafe impl ForgetableIvars { + #[no_mangle] + #[method(init)] + unsafe fn init_forgetable_ivars(this: *mut Self) -> *mut Self { + let this: Option<&mut Self> = unsafe { msg_send![super(this), init] }; + + this.map(|this| { + Ivar::write(&mut this.foo, 42); + Ivar::write(&mut this.bar, 43); + let this: *mut Self = this; + this }) + .unwrap_or_else(ptr::null_mut) } } ); -#[no_mangle] -#[inline(never)] -pub fn get_class() -> &'static AnyClass { - Custom::class() +impl ForgetableIvars { + #[no_mangle] + pub fn access_forgetable_ivars_class() -> &'static AnyClass { + Self::class() + } + + #[no_mangle] + pub fn access_forgetable_ivars(&self) -> (u8, u32) { + (*self.foo, *self.bar) + } } -#[no_mangle] -#[inline(never)] -pub fn get_obj() -> Option> { - unsafe { msg_send_id![get_class(), new] } +declare_class!( + #[no_mangle] + pub struct DropIvars { + obj: IvarDrop, "_obj">, + obj_option: IvarDrop>, "_obj_option">, + } + + mod drop_ivars; + + unsafe impl ClassType for DropIvars { + type Super = NSObject; + type Mutability = mutability::InteriorMutable; + const NAME: &'static str = "DropIvars"; + } + + unsafe impl DropIvars { + #[no_mangle] + #[method(init)] + unsafe fn init_drop_ivars(this: *mut Self) -> *mut Self { + let this: Option<&mut Self> = unsafe { msg_send![super(this), init] }; + + this.map(|this| { + Ivar::write(&mut this.obj, NSObject::new()); + Ivar::write(&mut this.obj_option, Some(NSObject::new())); + let this: *mut Self = this; + this + }) + .unwrap_or_else(ptr::null_mut) + } + } +); + +impl Drop for DropIvars { + #[inline(never)] + fn drop(&mut self) { + std::hint::black_box(()); + } } -#[no_mangle] -#[inline(never)] -pub fn access_ivars() -> (u8, *const NSObject) { - let obj = unsafe { get_obj().unwrap_unchecked() }; - ( - *obj.foo, - (*obj.obj) - .as_ref() - .map(|obj| Id::as_ptr(&obj)) - .unwrap_or_else(ptr::null), - ) +impl DropIvars { + #[no_mangle] + pub fn access_drop_ivars_class() -> &'static AnyClass { + Self::class() + } + + #[no_mangle] + pub fn access_drop_ivars(&self) -> *const NSObject { + Id::as_ptr(&*self.obj) + } } From fef8b5b26c4e20bfc025c4c9880d274752143820 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 3 Dec 2023 04:12:43 +0100 Subject: [PATCH 3/6] Redo how instance variables work in `declare_class!` At the same time, add support for `msg_send_id![super(...)]`. Also relax `T: IsMutable` bound on `Allocated::as_mut_ptr`. --- crates/icrate/examples/browser.rs | 52 +- crates/icrate/examples/delegate.rs | 70 +- crates/icrate/examples/metal.rs | 67 +- crates/icrate/tests/array.rs | 4 +- crates/icrate/tests/auto_traits.rs | 4 +- crates/icrate/tests/mutable_array.rs | 2 +- crates/icrate/tests/mutable_dictionary.rs | 6 +- crates/icrate/tests/mutable_set.rs | 2 +- crates/icrate/tests/set.rs | 4 +- crates/objc2/CHANGELOG.md | 102 + .../src/__macro_helpers/common_selectors.rs | 87 + .../src/__macro_helpers/declare_class.rs | 32 +- .../src/__macro_helpers/declared_ivars.rs | 919 ++++++++ crates/objc2/src/__macro_helpers/mod.rs | 9 +- .../objc2/src/__macro_helpers/msg_send_id.rs | 573 ++++- crates/objc2/src/__macro_helpers/writeback.rs | 10 +- crates/objc2/src/declare/ivar.rs | 388 ---- crates/objc2/src/declare/ivar_bool.rs | 50 - crates/objc2/src/declare/ivar_drop.rs | 378 --- crates/objc2/src/declare/ivar_encode.rs | 75 - .../src/declare/ivar_forwarding_impls.rs | 340 --- crates/objc2/src/declare/mod.rs | 37 +- crates/objc2/src/lib.rs | 2 +- crates/objc2/src/macros/__field_helpers.rs | 355 --- crates/objc2/src/macros/__method_msg_send.rs | 3 + crates/objc2/src/macros/__msg_send_parse.rs | 30 +- crates/objc2/src/macros/declare_class.rs | 475 ++-- crates/objc2/src/macros/extern_class.rs | 5 +- crates/objc2/src/macros/extern_methods.rs | 14 +- crates/objc2/src/macros/mod.rs | 83 +- crates/objc2/src/rc/allocated.rs | 211 +- crates/objc2/src/rc/id.rs | 10 +- crates/objc2/src/rc/id_traits.rs | 4 +- crates/objc2/src/rc/mod.rs | 2 +- crates/objc2/src/rc/test_object.rs | 40 +- crates/objc2/src/rc/weak_id.rs | 2 +- crates/objc2/src/runtime/bool.rs | 4 +- crates/objc2/src/runtime/message_receiver.rs | 4 +- crates/objc2/src/runtime/protocol_object.rs | 6 +- crates/objc2/src/top_level_traits.rs | 67 + crates/objc2/tests/declare_class.rs | 41 +- crates/objc2/tests/declare_class_self.rs | 4 +- crates/objc2/tests/macros_mainthreadmarker.rs | 7 +- crates/objc2/tests/no_prelude.rs | 16 +- crates/objc2/tests/track_caller.rs | 4 +- crates/objc2/tests/use_macros.rs | 4 +- .../expected/apple-aarch64.s | 2021 ++++++++--------- .../expected/apple-x86_64.s | 929 ++++---- .../crates/test_declare_class/lib.rs | 85 +- crates/test-assembly/src/lib.rs | 1 + .../ui/declare_class_classtype_imported.rs | 2 + .../declare_class_classtype_imported.stderr | 2 +- ...clare_class_delegate_not_mainthreadonly.rs | 4 +- .../ui/declare_class_invalid_receiver.rs | 4 +- .../ui/declare_class_invalid_syntax.rs | 57 +- .../ui/declare_class_invalid_syntax.stderr | 64 +- .../test-ui/ui/declare_class_invalid_type.rs | 4 +- .../test-ui/ui/declare_class_invalid_type2.rs | 4 +- .../test-ui/ui/declare_class_invalid_type3.rs | 19 - .../ui/declare_class_invalid_type3.stderr | 29 - .../ui/declare_class_mut_self_not_mutable.rs | 4 +- .../ui/implement_protocol_missing_super.rs | 4 +- .../ui/main_thread_only_not_allocable.rs | 4 +- crates/test-ui/ui/msg_send_missing_comma.rs | 2 + .../test-ui/ui/msg_send_missing_comma.stderr | 18 + .../ui/mutability_traits_unimplementable.rs | 4 +- crates/test-ui/ui/wrong_optional.rs | 6 +- .../tests/src/test_declare_class_protocol.rs | 16 +- 68 files changed, 3896 insertions(+), 3991 deletions(-) create mode 100644 crates/objc2/src/__macro_helpers/declared_ivars.rs delete mode 100644 crates/objc2/src/declare/ivar.rs delete mode 100644 crates/objc2/src/declare/ivar_bool.rs delete mode 100644 crates/objc2/src/declare/ivar_drop.rs delete mode 100644 crates/objc2/src/declare/ivar_encode.rs delete mode 100644 crates/objc2/src/declare/ivar_forwarding_impls.rs delete mode 100644 crates/objc2/src/macros/__field_helpers.rs delete mode 100644 crates/test-ui/ui/declare_class_invalid_type3.rs delete mode 100644 crates/test-ui/ui/declare_class_invalid_type3.stderr diff --git a/crates/icrate/examples/browser.rs b/crates/icrate/examples/browser.rs index c56c32468..f3fcf0a40 100644 --- a/crates/icrate/examples/browser.rs +++ b/crates/icrate/examples/browser.rs @@ -1,5 +1,5 @@ #![deny(unsafe_op_in_unsafe_fn)] -use core::{cell::OnceCell, ptr::NonNull}; +use core::cell::OnceCell; #[allow(deprecated)] use icrate::{ @@ -19,26 +19,23 @@ use icrate::{ WebKit::{WKNavigation, WKNavigationDelegate, WKWebView}, }; use objc2::{ - declare::{Ivar, IvarDrop}, - declare_class, msg_send, msg_send_id, + declare_class, msg_send_id, mutability::MainThreadOnly, rc::Id, runtime::{AnyObject, ProtocolObject, Sel}, - sel, ClassType, + sel, ClassType, DeclaredClass, }; -type IdCell = Box>>; - macro_rules! idcell { ($name:ident => $this:expr) => { - $this.$name.set($name).expect(&format!( + $this.ivars().$name.set($name).expect(&format!( "ivar should not already be initialized: `{}`", stringify!($name) )); }; ($name:ident <= $this:expr) => { #[rustfmt::skip] - let Some($name) = $this.$name.get() else { + let Some($name) = $this.ivars().$name.get() else { unreachable!( "ivar should be initialized: `{}`", stringify!($name) @@ -47,31 +44,28 @@ macro_rules! idcell { }; } +#[derive(Default)] +struct Ivars { + nav_url: OnceCell>, + web_view: OnceCell>, + window: OnceCell>, +} + declare_class!( - struct Delegate { - nav_url: IvarDrop, "_nav_url">, - web_view: IvarDrop, "_web_view">, - window: IvarDrop, "_window">, - } - mod ivars; + struct Delegate; + // SAFETY: + // - The superclass NSObject does not have any subclassing requirements. + // - Main thread only mutability is correct, since this is an application delegate. + // - `Delegate` does not implement `Drop`. unsafe impl ClassType for Delegate { type Super = NSObject; type Mutability = MainThreadOnly; const NAME: &'static str = "Delegate"; } - unsafe impl Delegate { - #[method(init)] - unsafe fn init(this: *mut Self) -> Option> { - let this: Option<&mut Self> = msg_send![super(this), init]; - this.map(|this| { - Ivar::write(&mut this.nav_url, IdCell::default()); - Ivar::write(&mut this.web_view, IdCell::default()); - Ivar::write(&mut this.window, IdCell::default()); - NonNull::from(this) - }) - } + impl DeclaredClass for Delegate { + type Ivars = Ivars; } unsafe impl NSObjectProtocol for Delegate {} @@ -298,7 +292,9 @@ declare_class!( impl Delegate { pub fn new(mtm: MainThreadMarker) -> Id { - unsafe { msg_send_id![mtm.alloc(), init] } + let this = mtm.alloc(); + let this = this.set_ivars(Ivars::default()); + unsafe { msg_send_id![super(this), init] } } } @@ -307,10 +303,8 @@ fn main() { let app = NSApplication::sharedApplication(mtm); app.setActivationPolicy(NSApplicationActivationPolicyRegular); - // initialize the delegate - let delegate = Delegate::new(mtm); - // configure the application delegate + let delegate = Delegate::new(mtm); let object = ProtocolObject::from_ref(&*delegate); app.setDelegate(Some(object)); diff --git a/crates/icrate/examples/delegate.rs b/crates/icrate/examples/delegate.rs index 5d4e44457..b2453b89c 100644 --- a/crates/icrate/examples/delegate.rs +++ b/crates/icrate/examples/delegate.rs @@ -1,53 +1,38 @@ #![deny(unsafe_op_in_unsafe_fn)] -use std::ptr::NonNull; - use icrate::AppKit::{NSApplication, NSApplicationActivationPolicyRegular, NSApplicationDelegate}; use icrate::Foundation::{ ns_string, MainThreadMarker, NSCopying, NSNotification, NSObject, NSObjectProtocol, NSString, }; -use objc2::declare::{Ivar, IvarBool, IvarDrop, IvarEncode}; use objc2::rc::Id; use objc2::runtime::ProtocolObject; -use objc2::{declare_class, msg_send, msg_send_id, mutability, ClassType}; +use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass}; + +#[derive(Debug)] +#[allow(unused)] +struct Ivars { + ivar: u8, + another_ivar: bool, + box_ivar: Box, + maybe_box_ivar: Option>, + id_ivar: Id, + maybe_id_ivar: Option>, +} declare_class!( - #[derive(Debug)] - struct AppDelegate { - ivar: IvarEncode, - another_ivar: IvarBool<"_another_ivar">, - box_ivar: IvarDrop, "_box_ivar">, - maybe_box_ivar: IvarDrop>, "_maybe_box_ivar">, - id_ivar: IvarDrop, "_id_ivar">, - maybe_id_ivar: IvarDrop>, "_maybe_id_ivar">, - } - - mod ivars; + struct AppDelegate; + // SAFETY: + // - The superclass NSObject does not have any subclassing requirements. + // - Main thread only mutability is correct, since this is an application delegate. + // - `AppDelegate` does not implement `Drop`. unsafe impl ClassType for AppDelegate { type Super = NSObject; type Mutability = mutability::MainThreadOnly; const NAME: &'static str = "MyAppDelegate"; } - unsafe impl AppDelegate { - #[method(initWith:another:)] - unsafe fn init_with( - this: *mut Self, - ivar: u8, - another_ivar: bool, - ) -> Option> { - let this: Option<&mut Self> = unsafe { msg_send![super(this), init] }; - - this.map(|this| { - Ivar::write(&mut this.ivar, ivar); - Ivar::write(&mut this.another_ivar, another_ivar); - Ivar::write(&mut this.maybe_box_ivar, None); - Ivar::write(&mut this.maybe_id_ivar, Some(ns_string!("def").copy())); - Ivar::write(&mut this.box_ivar, Box::new(2)); - Ivar::write(&mut this.id_ivar, NSString::from_str("abc")); - NonNull::from(this) - }) - } + impl DeclaredClass for AppDelegate { + type Ivars = Ivars; } unsafe impl NSObjectProtocol for AppDelegate {} @@ -69,7 +54,16 @@ declare_class!( impl AppDelegate { pub fn new(ivar: u8, another_ivar: bool, mtm: MainThreadMarker) -> Id { - unsafe { msg_send_id![mtm.alloc(), initWith: ivar, another: another_ivar] } + let this = mtm.alloc(); + let this = this.set_ivars(Ivars { + ivar, + another_ivar, + box_ivar: Box::new(2), + maybe_box_ivar: None, + id_ivar: NSString::from_str("abc"), + maybe_id_ivar: Some(ns_string!("def").copy()), + }); + unsafe { msg_send_id![super(this), init] } } } @@ -79,12 +73,8 @@ fn main() { let app = NSApplication::sharedApplication(mtm); app.setActivationPolicy(NSApplicationActivationPolicyRegular); - // initialize the delegate - let delegate = AppDelegate::new(42, true, mtm); - - println!("{delegate:?}"); - // configure the application delegate + let delegate = AppDelegate::new(42, true, mtm); let object = ProtocolObject::from_ref(&*delegate); app.setDelegate(Some(object)); diff --git a/crates/icrate/examples/metal.rs b/crates/icrate/examples/metal.rs index 7b31d439e..b2b2d19f9 100644 --- a/crates/icrate/examples/metal.rs +++ b/crates/icrate/examples/metal.rs @@ -20,12 +20,8 @@ use icrate::{ MetalKit::{MTKView, MTKViewDelegate}, }; use objc2::{ - declare::{Ivar, IvarDrop}, - declare_class, msg_send, msg_send_id, - mutability::MainThreadOnly, - rc::Id, - runtime::ProtocolObject, - ClassType, + declare_class, msg_send_id, mutability::MainThreadOnly, rc::Id, runtime::ProtocolObject, + ClassType, DeclaredClass, }; #[rustfmt::skip] @@ -101,18 +97,16 @@ pub struct Color { pub b: f32, } -type IdCell = Box>>; - macro_rules! idcell { ($name:ident => $this:expr) => { - $this.$name.set($name).expect(&format!( + $this.ivars().$name.set($name).expect(&format!( "ivar should not already be initialized: `{}`", stringify!($name) )); }; ($name:ident <= $this:expr) => { #[rustfmt::skip] - let Some($name) = $this.$name.get() else { + let Some($name) = $this.ivars().$name.get() else { unreachable!( "ivar should be initialized: `{}`", stringify!($name) @@ -121,38 +115,30 @@ macro_rules! idcell { }; } +// declare the desired instance variables +struct Ivars { + start_date: Id, + command_queue: OnceCell>>, + pipeline_state: OnceCell>>, + window: OnceCell>, +} + // declare the Objective-C class machinery declare_class!( - // declare the delegate class with our instance variables - #[rustfmt::skip] // FIXME: rustfmt breaks the macro parsing apparently - struct Delegate { - start_date: IvarDrop, "_start_date">, - command_queue: IvarDrop>, "_command_queue">, - pipeline_state: IvarDrop>, "_pipeline_state">, - window: IvarDrop, "_window">, - } - mod ivars; + struct Delegate; - // declare the class type + // SAFETY: + // - The superclass NSObject does not have any subclassing requirements. + // - Main thread only mutability is correct, since this is an application delegate. + // - `Delegate` does not implement `Drop`. unsafe impl ClassType for Delegate { type Super = NSObject; type Mutability = MainThreadOnly; const NAME: &'static str = "Delegate"; } - // define the Delegate methods (e.g., initializer) - unsafe impl Delegate { - #[method(init)] - unsafe fn init(this: *mut Self) -> Option> { - let this: Option<&mut Self> = msg_send![super(this), init]; - this.map(|this| { - Ivar::write(&mut this.start_date, unsafe { NSDate::now() }); - Ivar::write(&mut this.command_queue, IdCell::default()); - Ivar::write(&mut this.pipeline_state, IdCell::default()); - Ivar::write(&mut this.window, IdCell::default()); - NonNull::from(this) - }) - } + impl DeclaredClass for Delegate { + type Ivars = Ivars; } unsafe impl NSObjectProtocol for Delegate {} @@ -277,7 +263,7 @@ declare_class!( // compute the scene properties let scene_properties_data = &SceneProperties { - time: unsafe { self.start_date.timeIntervalSinceNow() } as f32, + time: unsafe { self.ivars().start_date.timeIntervalSinceNow() } as f32, }; // write the scene properties to the vertex shader argument buffer at index 0 let scene_properties_bytes = NonNull::from(scene_properties_data); @@ -360,7 +346,14 @@ declare_class!( impl Delegate { pub fn new(mtm: MainThreadMarker) -> Id { - unsafe { msg_send_id![mtm.alloc(), init] } + let this = mtm.alloc(); + let this = this.set_ivars(Ivars { + start_date: unsafe { NSDate::now() }, + command_queue: OnceCell::default(), + pipeline_state: OnceCell::default(), + window: OnceCell::default(), + }); + unsafe { msg_send_id![super(this), init] } } } @@ -370,10 +363,8 @@ fn main() { let app = NSApplication::sharedApplication(mtm); app.setActivationPolicy(NSApplicationActivationPolicyRegular); - // initialize the delegate - let delegate = Delegate::new(mtm); - // configure the application delegate + let delegate = Delegate::new(mtm); let object = ProtocolObject::from_ref(&*delegate); app.setDelegate(Some(object)); diff --git a/crates/icrate/tests/array.rs b/crates/icrate/tests/array.rs index 04fb17adf..398c894c6 100644 --- a/crates/icrate/tests/array.rs +++ b/crates/icrate/tests/array.rs @@ -122,7 +122,7 @@ fn test_retains_stored() { drop(obj); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } @@ -187,7 +187,7 @@ fn test_iter_minimal_retains() { assert_eq!(iter.count(), 0); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } diff --git a/crates/icrate/tests/auto_traits.rs b/crates/icrate/tests/auto_traits.rs index 807f1a492..5f0fa8169 100644 --- a/crates/icrate/tests/auto_traits.rs +++ b/crates/icrate/tests/auto_traits.rs @@ -7,7 +7,7 @@ use icrate::Foundation::*; use objc2::mutability::{Immutable, Mutable}; use objc2::rc::Id; use objc2::runtime::AnyObject; -use objc2::{declare_class, ClassType}; +use objc2::{declare_class, ClassType, DeclaredClass}; // We expect most Foundation types to be UnwindSafe and RefUnwindSafe, // since they follow Rust's usual mutability rules (&T = immutable). @@ -40,6 +40,8 @@ macro_rules! helper { type Mutability = $mutability; const NAME: &'static str = concat!(stringify!($name), "Test"); } + + impl DeclaredClass for $name {} ); }; } diff --git a/crates/icrate/tests/mutable_array.rs b/crates/icrate/tests/mutable_array.rs index a6597ed0b..b3501064e 100644 --- a/crates/icrate/tests/mutable_array.rs +++ b/crates/icrate/tests/mutable_array.rs @@ -151,7 +151,7 @@ fn test_remove() { array.removeAllObjects(); expected.release += 2; - expected.dealloc += 2; + expected.drop += 2; expected.assert_current(); assert_eq!(array.len(), 0); } diff --git a/crates/icrate/tests/mutable_dictionary.rs b/crates/icrate/tests/mutable_dictionary.rs index 61db87512..6d3933079 100644 --- a/crates/icrate/tests/mutable_dictionary.rs +++ b/crates/icrate/tests/mutable_dictionary.rs @@ -102,7 +102,7 @@ fn test_insert_key_copies() { dict.removeAllObjects(); // Release key expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } @@ -137,7 +137,7 @@ fn test_insert_value_retain_release() { drop(old); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } @@ -183,7 +183,7 @@ fn test_remove_clear_release_dealloc() { dict.removeAllObjects(); expected.release += 2; - expected.dealloc += 2; + expected.drop += 2; expected.assert_current(); assert_eq!(dict.len(), 0); } diff --git a/crates/icrate/tests/mutable_set.rs b/crates/icrate/tests/mutable_set.rs index da18d0266..d997449b9 100644 --- a/crates/icrate/tests/mutable_set.rs +++ b/crates/icrate/tests/mutable_set.rs @@ -113,7 +113,7 @@ fn test_clear_release_dealloc() { set.removeAllObjects(); expected.release += 4; - expected.dealloc += 4; + expected.drop += 4; expected.assert_current(); assert_eq!(set.len(), 0); } diff --git a/crates/icrate/tests/set.rs b/crates/icrate/tests/set.rs index fe4a5fbd4..ec96addbd 100644 --- a/crates/icrate/tests/set.rs +++ b/crates/icrate/tests/set.rs @@ -227,7 +227,7 @@ fn test_retains_stored() { drop(obj); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } @@ -291,7 +291,7 @@ fn test_iter_minimal_retains() { assert_eq!(iter.count(), 0); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } diff --git a/crates/objc2/CHANGELOG.md b/crates/objc2/CHANGELOG.md index c3ab4498d..0826dd68b 100644 --- a/crates/objc2/CHANGELOG.md +++ b/crates/objc2/CHANGELOG.md @@ -18,8 +18,104 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Added methods `as_ptr` and `as_mut_ptr` to `Allocated`. * Added optimization for converting `msg_send_id![cls, alloc]` to a call to the faster runtime function `objc_alloc`. +* Added `DeclaredClass`, which represents classes that are declared in Rust. +* Added `Allocated::set_ivars`, which sets the instance variables of an + object, and returns the new `rc::PartialInit`. +* Added the ability for `msg_send_id!` to call `super` methods. ### Changed +* **BREAKING**: Changed how instance variables work in `declare_class!`. + + Previously, instance variables had to implement `Encode`, and you had to + initialize them properly, which was difficult to ensure. + + Now, you implement the new `DeclaredClass` trait instead, which helps to + ensure all of this for you. + + ```rust + // Before + declare_class!( + struct MyObject { + object: IvarDrop, "_object">, + data: IvarDrop>, "_data">, + } + + mod ivars; + + unsafe impl ClassType for MyObject { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "MyObject"; + } + + unsafe impl MyObject { + #[method(init)] + unsafe fn init(this: *mut Self) -> Option> { + let this: Option<&mut Self> = msg_send![super(this), init]; + this.map(|this| { + Ivar::write(&mut this.object, NSObject::new()); + Ivar::write(&mut this.data, Box::new(MyData::new())); + NonNull::from(this) + }) + } + } + ); + + extern_methods!( + unsafe impl MyObject { + #[method_id(new)] + pub fn new() -> Id; + } + ); + + fn main() { + let obj = MyObject::new(); + println!("{:?}", obj.object); + } + + // After + struct MyIvars { + object: Id, + data: Option>, + } + + declare_class!( + struct MyObject; + + unsafe impl ClassType for MyObject { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "MyObject"; + } + + impl DeclaredClass for MyObject { + type Ivars = MyIvars; + } + + unsafe impl MyObject { + #[method_id(init)] + pub fn init(this: Allocated) -> Option> { + let this = this.set_ivars(MyIvars { + object: NSObject::new(), + data: MyData::new(), + }); + unsafe { msg_send_id![super(this), init] } + } + } + ); + + extern_methods!( + unsafe impl MyObject { + #[method_id(new)] + pub fn new() -> Id; + } + ); + + fn main() { + let obj = MyObject::new(); + println!("{:?}", obj.ivars().object); + } + ``` * **BREAKING**: `AnyClass::verify_sel` now take more well-defined types `EncodeArguments` and `EncodeReturn`. * **BREAKING**: Changed how the `mutability` traits work; these no longer have @@ -110,6 +206,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * **BREAKING**: Removed `ProtocolType` implementation for `NSObject`. Use the more precise `NSObjectProtocol` trait instead! * **BREAKING**: Removed the `MessageArguments` trait. +* **BREAKING**: Removed the following items from the `declare` module: `Ivar`, + `IvarEncode`, `IvarBool`, `IvarDrop`, `IvarType` and `InnerIvarType`. + + Ivar functionality is available in a different form now, see above under + "Changed". +* **BREAKING**: Removed `ClassBuilder::add_static_ivar`. ## 0.4.1 - 2023-07-31 diff --git a/crates/objc2/src/__macro_helpers/common_selectors.rs b/crates/objc2/src/__macro_helpers/common_selectors.rs index 508a2f3c1..05ab9308e 100644 --- a/crates/objc2/src/__macro_helpers/common_selectors.rs +++ b/crates/objc2/src/__macro_helpers/common_selectors.rs @@ -28,3 +28,90 @@ pub fn new_sel() -> Sel { pub fn dealloc_sel() -> Sel { __sel_inner!(__sel_data!(dealloc), "dealloc") } + +/// An undocumented selector called by the Objective-C runtime when +/// initalizing instance variables. +#[inline] +#[allow(dead_code)] // May be useful in the future +fn cxx_construct_sel() -> Sel { + __sel_inner!(".cxx_construct\0", ".cxx_construct") +} + +/// Objective-C runtimes call `.cxx_destruct` as part of the final `dealloc` +/// call inside `NSObject` (and has done so since macOS 10.4). +/// +/// While [GCC does document it somewhat][gcc-docs], this is still severely +/// undocumented in clang - but since the selector is emitted into the final +/// binary, it is fine to rely on it being used. +/// +/// Unfortunately though, this only works if the class has been declared +/// statically, since in that case a flag is set to inform the runtime that it +/// needs to run destructors. So unfortunately we can't use this on +/// dynamically declared classes. +/// +/// +/// # ABI +/// +/// The ABI of `.cxx_destruct` in Apple's runtime is actually that it does NOT +/// take a selector, unlike every other Objective-C method, see: +/// +/// +/// So the signature is `extern "C" fn(*mut AnyObject)`. +/// +/// This is likely because it's not a real Objective-C method that can be +/// called from userspace / objc_msgSend, and it's more efficient to not pass +/// the selector. +/// +/// Note that even if Apple decides to suddenly add the selector one day, +/// ignoring it will still be sound, since the function uses the C calling +/// convention, where such an ignored parameter would be allowed on all +/// relevant architectures. +/// +/// TODO: Unsure whether "C-unwind" is allowed? +/// +/// [gcc-docs]: https://gcc.gnu.org/onlinedocs/gcc/Objective-C-and-Objective-C_002b_002b-Dialect-Options.html#index-fobjc-call-cxx-cdtors +#[inline] +#[allow(dead_code)] // May be useful in the future +fn cxx_destruct_sel() -> Sel { + __sel_inner!(".cxx_destruct\0", ".cxx_destruct") +} + +#[cfg(test)] +mod tests { + use core::sync::atomic::{AtomicBool, Ordering}; + + use crate::declare::ClassBuilder; + use crate::rc::Id; + use crate::runtime::NSObject; + use crate::{msg_send_id, ClassType}; + + use super::*; + + /// Test the unfortunate fact that we can't use .cxx_destruct on dynamic classes. + #[test] + fn test_destruct_dynamic() { + static HAS_RUN: AtomicBool = AtomicBool::new(false); + + let mut builder = ClassBuilder::new("TestCxxDestruct", NSObject::class()).unwrap(); + + unsafe extern "C" fn destruct(_: *mut NSObject, _: Sel) { + HAS_RUN.store(true, Ordering::Relaxed); + } + + // Note: The ABI is not upheld here, but its fine for this test + unsafe { builder.add_method(cxx_destruct_sel(), destruct as unsafe extern "C" fn(_, _)) }; + + let cls = builder.register(); + + let obj: Id = unsafe { msg_send_id![cls, new] }; + drop(obj); + let has_run_destruct = HAS_RUN.load(Ordering::Relaxed); + + // This does work on GNUStep, but unfortunately not in Apple's objc4 + if cfg!(feature = "gnustep-1-7") { + assert!(has_run_destruct); + } else { + assert!(!has_run_destruct); + } + } +} diff --git a/crates/objc2/src/__macro_helpers/declare_class.rs b/crates/objc2/src/__macro_helpers/declare_class.rs index 38eaba628..b1dbd67ed 100644 --- a/crates/objc2/src/__macro_helpers/declare_class.rs +++ b/crates/objc2/src/__macro_helpers/declare_class.rs @@ -4,18 +4,15 @@ use core::marker::PhantomData; #[cfg(all(debug_assertions, feature = "verify"))] use std::collections::HashSet; +use crate::declare::ClassBuilder; +use crate::encode::{Encode, Encoding}; +use crate::rc::{Allocated, Id}; +use crate::runtime::{AnyClass, AnyObject, MessageReceiver, MethodImplementation, Sel}; #[cfg(all(debug_assertions, feature = "verify"))] use crate::runtime::{AnyProtocol, MethodDescription}; +use crate::{ClassType, DeclaredClass, Message, ProtocolType}; -use objc2_encode::Encoding; - -use crate::declare::{ClassBuilder, IvarType}; -use crate::encode::Encode; -use crate::rc::{Allocated, Id}; -use crate::runtime::{AnyClass, MethodImplementation, Sel}; -use crate::runtime::{AnyObject, MessageReceiver}; -use crate::{ClassType, Message, ProtocolType}; - +use super::declared_ivars::{register_with_ivars, setup_dealloc}; use super::{CopyOrMutCopy, Init, MaybeUnwrap, New, Other}; use crate::mutability; @@ -213,7 +210,7 @@ fn failed_declaring_class(name: &str) -> ! { panic!("could not create new class {name}. Perhaps a class with that name already exists?") } -impl ClassBuilderHelper { +impl ClassBuilderHelper { #[inline] #[track_caller] #[allow(clippy::new_without_default)] @@ -221,11 +218,13 @@ impl ClassBuilderHelper { where T::Super: ClassType, { - let builder = match ClassBuilder::new(T::NAME, ::class()) { + let mut builder = match ClassBuilder::new(T::NAME, ::class()) { Some(builder) => builder, None => failed_declaring_class(T::NAME), }; + setup_dealloc::(&mut builder); + Self { builder, p: PhantomData, @@ -291,13 +290,8 @@ impl ClassBuilderHelper { } #[inline] - pub fn add_static_ivar(&mut self) { - self.builder.add_static_ivar::() - } - - #[inline] - pub fn register(self) -> &'static AnyClass { - self.builder.register() + pub fn register(self) -> (&'static AnyClass, isize, isize) { + register_with_ivars::(self.builder) } } @@ -324,7 +318,7 @@ pub struct ClassProtocolMethodsBuilder<'a, T: ?Sized> { registered_class_methods: HashSet, } -impl ClassProtocolMethodsBuilder<'_, T> { +impl ClassProtocolMethodsBuilder<'_, T> { // Addition: This restricts to callee `T` #[inline] pub unsafe fn add_method(&mut self, sel: Sel, func: F) diff --git a/crates/objc2/src/__macro_helpers/declared_ivars.rs b/crates/objc2/src/__macro_helpers/declared_ivars.rs new file mode 100644 index 000000000..784e2e6c6 --- /dev/null +++ b/crates/objc2/src/__macro_helpers/declared_ivars.rs @@ -0,0 +1,919 @@ +//! # Supporting code for instance variables on declared classes. +//! +//! Adding instance variables to Objective-C classes is fairly simple, it can +//! be done using `ClassBuilder::add_ivar`. +//! +//! However, things become more complicated once we have to handle `Drop`, +//! deallocation and unwind safety; remember, `dealloc` may be called even on +//! newly, non-initialized instances. +//! +//! Note that Swift [doesn't handle this][swift-deinit-unsound], but that +//! doesn't mean we can simply stick our heads in the sand. +//! +//! Basically, instead of storing the ivars directly, we store it as the +//! following tagged enum: +//! ``` +//! #[repr(u8)] +//! enum ActualIvar { +//! Allocated = 0, +//! PartialInit(T::Ivars), +//! Finalized(T::Ivars), +//! } +//! ``` +//! +//! For performance reasons, we unfortunately can't write it that cleanly: we +//! want the data and the drop flag as two separate ivars instead of combining +//! them into one, since that will give the layout algorithm in the +//! Objective-C runtime more information to work with, and it allows us to +//! selectively omit the drop flag or the data storage when either is not +//! needed. +//! +//! Ideally, we'd be able to somehow statically detect when the ivars have a +//! zero niche, which would allow us to know if the type is safe to drop when +//! zero-initialized: +//! ```ignore +//! None::.is_all_zeroes_bitpattern() +//! ``` +//! +//! However, detecting if the `None` is all zeroes requires reading the bytes, +//! which is [unsound for types that may have padding][unsound-read-padding], +//! since that padding is uninitialized. +//! +//! So this is an optimization that we don't yet do, but that may be possible +//! in the future using something like `bytemuck::ZeroableInOption`. +//! +//! [swift-deinit-unsound]: https://github.com/apple/swift/issues/68734 +//! [unsound-read-padding]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ea068e8d9e55801aa9520ea914eb2822 + +use alloc::borrow::Cow; +use alloc::format; +use core::mem; +use core::ptr::{self, NonNull}; + +use crate::declare::ClassBuilder; +use crate::encode::{Encode, Encoding}; +use crate::runtime::{AnyClass, AnyObject, MessageReceiver, Sel}; +use crate::{sel, ClassType, DeclaredClass}; + +/// A type representing the drop flags that may be set for a type. +#[repr(u8)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) enum DropFlag { + /// Set to zero to ensure that this is the default when created by the + /// Objective-C runtime. + /// + /// Ivars are [documented][obj-init-zeroed] to be zero-initialized after + /// allocation, and that has been true since at least [the Objective-C + /// version shipped with Mac OS X 10.0][objc4-208-init]. + /// + /// [obj-init-zeroed]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW7 + /// [objc4-208-init]: https://github.com/apple-oss-distributions/objc4/blob/objc4-208/runtime/objc-class.m#L367 + #[allow(dead_code)] + Allocated = 0x00, + /// Used when `mem::needs_drop::()`, or with debug assertions enabled. + InitializedIvars = 0x0f, + /// Used when `mem::needs_drop::()`, or with debug assertions enabled. + Finalized = 0xff, +} + +// SAFETY: The DropFlag is #[repr(u8)] +unsafe impl Encode for DropFlag { + const ENCODING: Encoding = u8::ENCODING; +} + +pub trait DeclaredIvarsHelper { + const HAS_IVARS: bool; + const HAS_DROP_FLAG: bool; +} + +impl DeclaredIvarsHelper for T { + /// Only add ivar if we need the runtime to allocate memory for it. + /// + /// We can avoid doing so if the type is a zero-sized type (ZST), and the + /// required alignment is less than the alignment of a pointer (objects + /// are guaranteed to have at least that alignment themselves). + const HAS_IVARS: bool = { + mem::size_of::() > 0 + || mem::align_of::() > mem::align_of::<*mut AnyObject>() + }; + /// Only add drop flag if the type or the ivars need it. + /// + /// `needs_drop::` can reliably detect a direct implementation of + /// `Drop`, since the type only includes `ManuallyDrop` or `PhantomData` + /// fields. + const HAS_DROP_FLAG: bool = mem::needs_drop::() || mem::needs_drop::(); +} + +/// Helper function for getting a pointer to the instance variable. +/// +/// # Safety +/// +/// The pointer must be valid, and the instance variable offset (if it has +/// any) must have been initialized. +#[inline] +unsafe fn ptr_to_ivar(ptr: NonNull) -> NonNull { + // This is called even when there is no ivars, but that's fine, since in + // that case the ivar is zero-sized, and the offset will be zero, so we + // can still compute a valid pointer to the ivar. + // + // debug_assert!(T::HAS_IVARS); + + // SAFETY: That an instance variable with the given type exists at the + // specified offset is ensured by `DeclaredClass` trait implementor. + unsafe { AnyObject::ivar_at_offset::(ptr.cast(), T::__ivars_offset()) } +} + +/// Helper function for getting a pointer to the drop flag. +/// +/// # Safety +/// +/// The pointer must be valid and have an initialized drop flag. +#[inline] +unsafe fn ptr_to_drop_flag(ptr: NonNull) -> *mut DropFlag { + debug_assert!(T::HAS_DROP_FLAG, "type did not have drop flag"); + // SAFETY: That a drop flag exists at the specified offset is ensured + // by caller. + unsafe { AnyObject::ivar_at_offset::(ptr.cast(), T::__drop_flag_offset()).as_ptr() } +} + +pub(crate) fn setup_dealloc(builder: &mut ClassBuilder) +where + T::Super: ClassType, +{ + // Add dealloc if the class or the ivars need dropping. + if mem::needs_drop::() || mem::needs_drop::() { + let func: unsafe extern "C" fn(_, _) = dealloc::; + // SAFETY: The function signature is correct, and method contract is + // upheld inside `dealloc`. + unsafe { builder.add_method(sel!(dealloc), func) }; + } else { + // Users should not rely on this ommision, it is only an optimization. + } +} + +/// The `dealloc` Objective-C method. +/// +/// See the following links for more details about `dealloc`: +/// - +/// - +/// - +/// +/// TODO: Change this to `extern "C-unwind"`, unwinding in dealloc is allowed. +unsafe extern "C" fn dealloc(this: NonNull, cmd: Sel) +where + T::Super: ClassType, +{ + /// Helper function for marking the cold path when branching. + #[inline] + #[cold] + fn cold_path() {} + + // SAFETY: `dealloc` is only registered when there is a need for dropping, + // and hence a need for a drop flag. + let drop_flag = unsafe { *ptr_to_drop_flag(this) }; + + if mem::needs_drop::() { + match drop_flag { + // Don't deallocate the current instance if it has not been fully + // initialized. + // + // Note that we still run the superclass deinitializer below. + DropFlag::Allocated | DropFlag::InitializedIvars => cold_path(), + // SAFETY: This is the `dealloc` method, so we know that the type + // never needs to be deallocated again. + // + // Additionally, we know that the type was fully initialized, since + // that's what the drop flag says. + // + // TODO: This can unwind, is it correct to just let that + // propagate? + DropFlag::Finalized => unsafe { ptr::drop_in_place(this.as_ptr()) }, + } + } + + // TODO: Debug assertions that the retain count is still 1 here. + + // Note: This should be done inside `.cxx_destruct`, since if a superclass + // calls an overwritten method in its `dealloc`, it can access + // deinitialized instance variables; but we can't do that without + // generating statics, so we have to do it in `dealloc` for now. + // + // It is very important that we do this after the `Drop` of the class + // itself above, though. + // + // Another possibility would be to read the contents of the ivars onto the + // stack here, and only deinitialize after the superclass' `dealloc`, but + // that would break the pinning guarantee that ivars otherwise have. + if mem::needs_drop::() { + match drop_flag { + // Do nothing if the ivars have not been initialized. + DropFlag::Allocated => cold_path(), + DropFlag::InitializedIvars | DropFlag::Finalized => { + // SAFETY: The instance variable is initialized, so it is + // valid to drop here. + // + // TODO: This can unwind, is it correct to just let that + // propagate? + unsafe { ptr::drop_in_place(ptr_to_ivar(this).as_ptr()) }; + } + } + } + + // The superclass' "marker" that this stores is wrapped in `ManuallyDrop`, + // we drop it by calling the superclass' `dealloc` method instead. + // + // Note: ARC does this automatically, which means most Objective-C code in + // the wild don't contain this call; but we _are_ ARC, so we must do this. + // + // SAFETY: The argument and return types are correct, and we make sure to + // only call this once. + unsafe { + MessageReceiver::send_super_message( + this, + ::Super::class(), + cmd, // Reuse the selector + (), // No arguments + ) + } +} + +/// Register the class, and get the ivar offsets. +#[inline] +pub(crate) fn register_with_ivars( + mut builder: ClassBuilder, +) -> (&'static AnyClass, isize, isize) { + let (ivar_name, drop_flag_name): (Cow<'static, str>, Cow<'static, str>) = { + if cfg!(feature = "gnustep-1-7") { + // GNUStep does not support a subclass having an ivar with the + // same name as a superclass, so let's use the class name as the + // ivar name to ensure uniqueness. + ( + format!("{}_ivars", T::NAME).into(), + format!("{}_drop_flag", T::NAME).into(), + ) + } else { + ("ivars".into(), "drop_flag".into()) + } + }; + + if T::HAS_IVARS { + // TODO: Consider not adding a encoding - Swift doesn't do it. + let ivar_encoding = Encoding::Array( + mem::size_of::() as u64, + match mem::align_of::() { + 1 => &u8::ENCODING, + 2 => &u16::ENCODING, + 4 => &u32::ENCODING, + // The alignment of `u64` may not be 8 on all architectures + 8 if mem::align_of::() == 8 => &u64::ENCODING, + alignment => panic!("unsupported alignment {alignment} for `{}::Ivars`", T::NAME), + }, + ); + unsafe { builder.add_ivar_inner::(&ivar_name, &ivar_encoding) }; + } + + if T::HAS_DROP_FLAG { + // TODO: Maybe we can reuse the drop flag when subclassing an already + // declared class? + builder.add_ivar::(&drop_flag_name); + } + + let cls = builder.register(); + + let ivars_offset = if T::HAS_IVARS { + cls.instance_variable(&ivar_name) + .expect("failed retrieving instance variable on newly declared class") + .offset() + } else { + // Fallback to an offset of zero. + // + // This is fine, since any reads here will only be via. zero-sized + // ivars, where the actual pointer doesn't matter. + 0 + }; + + let drop_flag_offset = if T::HAS_DROP_FLAG { + cls.instance_variable(&drop_flag_name) + .expect("failed retrieving drop flag instance variable on newly declared class") + .offset() + } else { + // Fall back to an offset of zero. + // + // This is fine, since the drop flag is never actually used in the + // cases where it was not added. + 0 + }; + + (cls, ivars_offset, drop_flag_offset) +} + +/// # Safety +/// +/// The pointer must be a valid, newly allocated instance. +#[inline] +#[track_caller] +pub(crate) unsafe fn initialize_ivars(ptr: NonNull, val: T::Ivars) { + // Debug assert the state of the drop flag + if T::HAS_DROP_FLAG && cfg!(debug_assertions) { + // SAFETY: Just checked that the drop flag is available. + match unsafe { *ptr_to_drop_flag(ptr) } { + DropFlag::Allocated => { + // Allow initialization after allocation + } + DropFlag::InitializedIvars => { + panic!("tried to initialize ivars after they were already initialized") + } + DropFlag::Finalized => { + panic!("tried to initialize ivars on an already initialized object") + } + } + } + + // SAFETY: + // - Caller ensures the pointer is valid. + // - The location is properly aligned by `ClassBuilder::add_ivar`. + // - This write is done as part of initialization, so we know that the + // pointer is not shared elsewhere. + unsafe { ptr_to_ivar(ptr).as_ptr().write(val) }; + + // Write to drop flag that we've initialized the instance variables. + // + // Note: We intentionally only do this _after_ writing to the ivars, + // for better unwind safety. + if T::HAS_DROP_FLAG && (mem::needs_drop::() || cfg!(debug_assertions)) { + // SAFETY: Just checked that the drop flag is available. + unsafe { ptr_to_drop_flag(ptr).write(DropFlag::InitializedIvars) } + } +} + +/// # Safety +/// +/// The pointer must be valid and finalized (i.e. all super initializers must +/// have been run). +#[inline] +#[track_caller] +pub(crate) unsafe fn set_finalized(ptr: NonNull) { + // Debug assert the state of the drop flag + if T::HAS_DROP_FLAG && cfg!(debug_assertions) { + // SAFETY: Just checked that the drop flag is available. + match unsafe { *ptr_to_drop_flag(ptr) } { + DropFlag::Allocated => { + panic!("tried to finalize an object that was not yet fully initialized") + } + DropFlag::InitializedIvars => { + // Allow finalizing after initialization + } + DropFlag::Finalized => { + panic!("tried to finalize an already finalized object") + } + } + } + + // Write to drop flag that we've fully initialized the class. + if T::HAS_DROP_FLAG && (mem::needs_drop::() || cfg!(debug_assertions)) { + // SAFETY: Just checked that the drop flag is available. + unsafe { ptr_to_drop_flag(ptr).write(DropFlag::Finalized) } + } +} + +/// # Safety +/// +/// The pointer must be valid and the instance variables must be initialized. +#[inline] +#[track_caller] +pub(crate) unsafe fn get_initialized_ivar_ptr( + ptr: NonNull, +) -> NonNull { + // Debug assert the state of the drop flag + if T::HAS_DROP_FLAG && cfg!(debug_assertions) { + // SAFETY: Just checked that the drop flag is available. + match unsafe { *ptr_to_drop_flag(ptr) } { + DropFlag::Allocated => { + panic!("tried to access uninitialized instance variable") + } + DropFlag::InitializedIvars => { + // Allow accessing even if not finalized, since we only set + // that state _after_ it actually happens, while accesses may + // be done by the superclass initializer in e.g. an + // overwritten method. + } + DropFlag::Finalized => { + // Allow accessing if finalized + } + } + } + + // SAFETY: That the pointer is valid is ensured by caller. + unsafe { ptr_to_ivar(ptr) } +} + +#[cfg(test)] +mod tests { + use std::println; + use std::sync::Mutex; + + use alloc::vec::Vec; + + use super::*; + use crate::mutability::{InteriorMutable, Mutable}; + use crate::rc::{Allocated, Id, PartialInit, __RcTestObject, __ThreadTestData}; + use crate::runtime::NSObject; + use crate::{declare_class, msg_send, msg_send_id, ClassType, DeclaredClass}; + + /// Initialize superclasses, but not own class. + unsafe fn init_only_superclasses(obj: Allocated) -> Id + where + T::Super: ClassType, + { + unsafe { Id::new(msg_send![super(Allocated::into_ptr(obj)), init]) }.unwrap() + } + + /// Initialize, but fail to finalize (which is only done by `msg_send_id!`). + unsafe fn init_no_finalize(obj: Allocated) -> Id + where + T::Super: ClassType, + T::Ivars: Default, + { + let obj = obj.set_ivars(Default::default()); + unsafe { Id::new(msg_send![super(PartialInit::into_ptr(obj)), init]) }.unwrap() + } + + /// Initialize properly. + unsafe fn init(obj: Allocated) -> Id { + unsafe { msg_send_id![obj, init] } + } + + #[test] + fn assert_size() { + assert_eq!(mem::size_of::(), 1); + } + + #[test] + fn test_dealloc_and_dealloc_subclasses() { + #[derive(Debug, PartialEq)] + enum Operation { + DropIvar, + DropClass, + } + + static OPERATIONS: Mutex> = Mutex::new(Vec::new()); + + #[derive(Default)] + struct IvarThatImplsDrop; + + impl Drop for IvarThatImplsDrop { + fn drop(&mut self) { + OPERATIONS.lock().unwrap().push(Operation::DropIvar); + } + } + + #[track_caller] + fn check(expected: [Operation; N]) { + let mut operations = OPERATIONS.lock().unwrap(); + assert_eq!(&**operations, expected); + operations.clear(); + } + + // First class + + declare_class!( + struct ImplsDrop; + + unsafe impl ClassType for ImplsDrop { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "ImplsDrop"; + } + + impl DeclaredClass for ImplsDrop { + type Ivars = (); + } + + unsafe impl ImplsDrop { + #[method_id(init)] + fn init(this: Allocated) -> Option> { + unsafe { msg_send_id![super(this.set_ivars(())), init] } + } + } + ); + + impl Drop for ImplsDrop { + fn drop(&mut self) { + OPERATIONS.lock().unwrap().push(Operation::DropClass); + } + } + + let _ = ImplsDrop::alloc(); + check([]); + + let _ = unsafe { init_only_superclasses(ImplsDrop::alloc()) }; + check([]); + + let _ = unsafe { init_no_finalize(ImplsDrop::alloc()) }; + check([]); + + let _ = unsafe { init(ImplsDrop::alloc()) }; + check([Operation::DropClass]); + + // Subclass + + declare_class!( + struct IvarsImplDrop; + + unsafe impl ClassType for IvarsImplDrop { + type Super = ImplsDrop; + type Mutability = InteriorMutable; + const NAME: &'static str = "IvarsImplDrop"; + } + + impl DeclaredClass for IvarsImplDrop { + type Ivars = IvarThatImplsDrop; + } + + unsafe impl IvarsImplDrop { + #[method_id(init)] + fn init(this: Allocated) -> Option> { + unsafe { msg_send_id![super(this.set_ivars(IvarThatImplsDrop)), init] } + } + } + ); + + let _ = IvarsImplDrop::alloc(); + check([]); + + let _ = unsafe { init_only_superclasses(IvarsImplDrop::alloc()) }; + check([Operation::DropClass]); + + let _ = unsafe { init_no_finalize(IvarsImplDrop::alloc()) }; + check([Operation::DropIvar, Operation::DropClass]); + + let _ = unsafe { init(IvarsImplDrop::alloc()) }; + check([Operation::DropIvar, Operation::DropClass]); + + // Further subclass + + declare_class!( + struct BothIvarsAndTypeImplsDrop; + + unsafe impl ClassType for BothIvarsAndTypeImplsDrop { + type Super = IvarsImplDrop; + type Mutability = InteriorMutable; + const NAME: &'static str = "BothIvarsAndTypeImplsDrop"; + } + + impl DeclaredClass for BothIvarsAndTypeImplsDrop { + type Ivars = IvarThatImplsDrop; + } + + unsafe impl BothIvarsAndTypeImplsDrop { + #[method_id(init)] + fn init(this: Allocated) -> Option> { + unsafe { msg_send_id![super(this.set_ivars(IvarThatImplsDrop)), init] } + } + } + ); + + impl Drop for BothIvarsAndTypeImplsDrop { + fn drop(&mut self) { + OPERATIONS.lock().unwrap().push(Operation::DropClass); + } + } + + let _ = BothIvarsAndTypeImplsDrop::alloc(); + check([]); + + let _ = unsafe { init_only_superclasses(BothIvarsAndTypeImplsDrop::alloc()) }; + check([Operation::DropIvar, Operation::DropClass]); + + let _ = unsafe { init_no_finalize(BothIvarsAndTypeImplsDrop::alloc()) }; + check([ + Operation::DropIvar, + Operation::DropIvar, + Operation::DropClass, + ]); + + let _ = unsafe { init(BothIvarsAndTypeImplsDrop::alloc()) }; + check([ + Operation::DropClass, + Operation::DropIvar, + Operation::DropIvar, + Operation::DropClass, + ]); + } + + #[test] + fn test_no_generated_dealloc_if_not_needed() { + #[allow(unused)] + struct Ivar { + field1: u8, + field2: bool, + } + + declare_class!( + struct IvarsNoDrop; + + unsafe impl ClassType for IvarsNoDrop { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "IvarsNoDrop"; + } + + impl DeclaredClass for IvarsNoDrop { + type Ivars = Ivar; + } + ); + + assert!(!mem::needs_drop::()); + assert!(!mem::needs_drop::()); + assert_eq!( + IvarsNoDrop::class().instance_method(sel!(dealloc)), + NSObject::class().instance_method(sel!(dealloc)), + ); + } + + #[test] + fn zst_ivar() { + #[derive(Default, Debug)] + struct Ivar; + + declare_class!( + struct IvarZst; + + unsafe impl ClassType for IvarZst { + type Super = NSObject; + type Mutability = Mutable; + const NAME: &'static str = "IvarZst"; + } + + impl DeclaredClass for IvarZst { + type Ivars = Ivar; + } + + unsafe impl IvarZst { + #[method_id(init)] + fn init(this: Allocated) -> Option> { + unsafe { msg_send_id![super(this.set_ivars(Ivar)), init] } + } + } + ); + + assert_eq!( + IvarZst::class().instance_size(), + NSObject::class().instance_size(), + ); + let ivar_name = if cfg!(feature = "gnustep-1-7") { + "IvarZst_ivars" + } else { + "ivars" + }; + assert!(IvarZst::class().instance_variable(ivar_name).is_none()); + + let mut obj = unsafe { init(IvarZst::alloc()) }; + println!("{:?}", obj.ivars()); + *obj.ivars_mut() = Ivar; + } + + #[test] + #[should_panic = "unsupported alignment 16 for `HasIvarWithHighAlignment::Ivars`"] + fn test_generate_ivar_high_alignment() { + #[repr(align(16))] + struct HighAlignment; + + declare_class!( + struct HasIvarWithHighAlignment; + + unsafe impl ClassType for HasIvarWithHighAlignment { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "HasIvarWithHighAlignment"; + } + + impl DeclaredClass for HasIvarWithHighAlignment { + type Ivars = HighAlignment; + } + ); + + // Have to allocate up to the desired alignment, but no need to go + // further, since the object is zero-sized. + assert_eq!(HasIvarWithHighAlignment::class().instance_size(), 16); + + let ivar_name = if cfg!(feature = "gnustep-1-7") { + "IvarZst_ivars" + } else { + "ivars" + }; + let ivar = HasIvarWithHighAlignment::class() + .instance_variable(ivar_name) + .unwrap(); + assert_eq!(ivar.offset(), 16); + } + + #[test] + fn test_ivar_access() { + declare_class!( + struct RcIvar; + + unsafe impl ClassType for RcIvar { + type Super = NSObject; + type Mutability = Mutable; + const NAME: &'static str = "RcIvar"; + } + + impl DeclaredClass for RcIvar { + type Ivars = Option>; + } + + unsafe impl RcIvar { + #[method_id(init)] + fn init(this: Allocated) -> Option> { + let this = this.set_ivars(Some(__RcTestObject::new())); + unsafe { msg_send_id![super(this), init] } + } + } + ); + + let mut expected = __ThreadTestData::current(); + + let _ = RcIvar::alloc(); + expected.assert_current(); + + let _ = unsafe { init_only_superclasses(RcIvar::alloc()) }; + expected.assert_current(); + + // Ivar access is valid even if the class is not finalized. + let mut obj = unsafe { init_no_finalize(RcIvar::alloc()) }; + expected.assert_current(); + + *obj.ivars_mut() = Some(__RcTestObject::new()); + expected.alloc += 1; + expected.init += 1; + expected.assert_current(); + + drop(obj); + expected.release += 1; + expected.drop += 1; + expected.assert_current(); + + let mut obj = unsafe { init(RcIvar::alloc()) }; + expected.alloc += 1; + expected.init += 1; + expected.assert_current(); + + *obj.ivars_mut() = obj.ivars().clone(); + expected.retain += 1; + expected.release += 1; + expected.assert_current(); + + drop(obj); + expected.release += 1; + expected.drop += 1; + expected.assert_current(); + + #[derive(Default, Debug, PartialEq, Eq)] + struct RcIvarSubclassIvars { + int: i32, + obj: Id<__RcTestObject>, + } + + declare_class!( + struct RcIvarSubclass; + + unsafe impl ClassType for RcIvarSubclass { + type Super = RcIvar; + type Mutability = Mutable; + const NAME: &'static str = "RcIvarSubclass"; + } + + impl DeclaredClass for RcIvarSubclass { + type Ivars = RcIvarSubclassIvars; + } + + unsafe impl RcIvarSubclass { + #[method_id(init)] + fn init(this: Allocated) -> Option> { + let this = this.set_ivars(RcIvarSubclassIvars { + int: 42, + obj: __RcTestObject::new(), + }); + unsafe { msg_send_id![super(this), init] } + } + } + ); + + let mut obj = unsafe { init(RcIvarSubclass::alloc()) }; + expected.alloc += 2; + expected.init += 2; + expected.assert_current(); + assert_eq!(obj.ivars().int, 42); + + obj.ivars_mut().int += 1; + assert_eq!(obj.ivars().int, 43); + + obj.ivars_mut().obj = (**obj).ivars().clone().unwrap(); + expected.retain += 1; + expected.release += 1; + expected.drop += 1; + expected.assert_current(); + + *(**obj).ivars_mut() = None; + expected.release += 1; + expected.assert_current(); + + drop(obj); + expected.release += 1; + expected.drop += 1; + expected.assert_current(); + + let obj = unsafe { init_only_superclasses(RcIvarSubclass::alloc()) }; + expected.alloc += 1; + expected.init += 1; + expected.assert_current(); + + // Accessing superclass ivars is valid + println!("{:?}", (**obj).ivars()); + + drop(obj); + expected.release += 1; + expected.drop += 1; + expected.assert_current(); + } + + #[test] + #[cfg_attr(not(debug_assertions), ignore = "only panics with debug assertions")] + #[should_panic = "tried to access uninitialized instance variable"] + fn access_invalid() { + declare_class!( + struct InvalidAccess; + + unsafe impl ClassType for InvalidAccess { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "InvalidAccess"; + } + + impl DeclaredClass for InvalidAccess { + // Type has to have a drop flag to detect invalid access + type Ivars = Id; + } + ); + + let obj = unsafe { init_only_superclasses(InvalidAccess::alloc()) }; + println!("{:?}", obj.ivars()); + } + + #[test] + #[should_panic = "panic in drop"] + fn test_panic_in_drop() { + declare_class!( + struct DropPanics; + + unsafe impl ClassType for DropPanics { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "DropPanics"; + } + + impl DeclaredClass for DropPanics {} + ); + + impl Drop for DropPanics { + fn drop(&mut self) { + panic!("panic in drop"); + } + } + + let obj = DropPanics::alloc().set_ivars(()); + let obj: Id = unsafe { msg_send_id![super(obj), init] }; + drop(obj); + } + + #[test] + #[should_panic = "panic in ivar drop"] + fn test_panic_in_ivar_drop() { + struct DropPanics; + + impl Drop for DropPanics { + fn drop(&mut self) { + panic!("panic in ivar drop"); + } + } + + declare_class!( + struct IvarDropPanics; + + unsafe impl ClassType for IvarDropPanics { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "IvarDropPanics"; + } + + impl DeclaredClass for IvarDropPanics { + type Ivars = DropPanics; + } + ); + + let obj = IvarDropPanics::alloc().set_ivars(DropPanics); + let obj: Id = unsafe { msg_send_id![super(obj), init] }; + drop(obj); + } +} diff --git a/crates/objc2/src/__macro_helpers/mod.rs b/crates/objc2/src/__macro_helpers/mod.rs index b7cffdbf7..3df738817 100644 --- a/crates/objc2/src/__macro_helpers/mod.rs +++ b/crates/objc2/src/__macro_helpers/mod.rs @@ -2,11 +2,10 @@ pub use core::borrow::{Borrow, BorrowMut}; pub use core::cell::UnsafeCell; pub use core::convert::{AsMut, AsRef}; pub use core::marker::{PhantomData, Sized}; -pub use core::mem::{needs_drop, size_of, ManuallyDrop}; +pub use core::mem::{size_of, ManuallyDrop, MaybeUninit}; pub use core::ops::{Deref, DerefMut}; pub use core::option::Option::{self, None, Some}; -pub use core::primitive::{bool, str, u8}; -pub use core::ptr::drop_in_place; +pub use core::primitive::{bool, isize, str, u8}; pub use core::{compile_error, concat, panic, stringify}; // TODO: Use `core::cell::LazyCell` pub use std::sync::Once; @@ -15,6 +14,7 @@ mod cache; mod common_selectors; mod convert; mod declare_class; +pub(crate) mod declared_ivars; mod method_family; mod msg_send; mod msg_send_id; @@ -28,11 +28,12 @@ pub use self::declare_class::{ ClassProtocolMethodsBuilder, IdReturnValue, MaybeOptionId, MessageRecieveId, ValidSubclassMutability, }; +pub use self::declared_ivars::DeclaredIvarsHelper; pub use self::method_family::{ retain_semantics, Alloc, CopyOrMutCopy, Init, New, Other, RetainSemantics, }; pub use self::msg_send::MsgSend; -pub use self::msg_send_id::{MaybeUnwrap, MsgSendId}; +pub use self::msg_send_id::{MaybeUnwrap, MsgSendId, MsgSendSuperId}; /// Helper struct for emitting the module info that macOS 32-bit requires. /// diff --git a/crates/objc2/src/__macro_helpers/msg_send_id.rs b/crates/objc2/src/__macro_helpers/msg_send_id.rs index 9cb02d96b..11112b552 100644 --- a/crates/objc2/src/__macro_helpers/msg_send_id.rs +++ b/crates/objc2/src/__macro_helpers/msg_send_id.rs @@ -1,10 +1,11 @@ -use core::ptr; +use core::ptr::{self, NonNull}; -use crate::encode::Encode; -use crate::rc::{Allocated, Id}; +use crate::encode::{Encode, RefEncode}; +use crate::rc::{Allocated, Id, PartialInit}; use crate::runtime::{AnyClass, AnyObject, Sel}; -use crate::{sel, Message}; +use crate::{sel, ClassType, DeclaredClass, Message}; +use super::declared_ivars::set_finalized; use super::{Alloc, ConvertArguments, CopyOrMutCopy, Init, MsgSend, New, Other, TupleExtender}; pub trait MsgSendId { @@ -57,6 +58,94 @@ pub trait MsgSendId { } } +/// new: T -> Option> +/// alloc: &AnyClass -> Allocated +/// init: PartialInit -> Option> // Changed +/// copy/mutableCopy: T -> Option> +/// others: T -> Option> +#[doc(hidden)] +pub trait MsgSendSuperId { + type Inner: ?Sized + RefEncode; + + unsafe fn send_super_message_id>( + obj: T, + superclass: &AnyClass, + sel: Sel, + args: A, + ) -> R; + + #[inline] + #[track_caller] + unsafe fn send_super_message_id_static>( + obj: T, + sel: Sel, + args: A, + ) -> R + where + Self::Inner: ClassType, + ::Super: ClassType, + { + unsafe { + Self::send_super_message_id(obj, ::Super::class(), sel, args) + } + } + + #[inline] + #[track_caller] + unsafe fn send_super_message_id_error( + obj: T, + superclass: &AnyClass, + sel: Sel, + args: A, + ) -> Result> + where + *mut *mut E: Encode, + A: TupleExtender<*mut *mut E>, + >::PlusOneArgument: ConvertArguments, + E: Message, + Option: MaybeUnwrap, + { + let mut err: *mut E = ptr::null_mut(); + let args = args.add_argument(&mut err); + // SAFETY: See `send_message_id_error` + let res: Option = unsafe { Self::send_super_message_id(obj, superclass, sel, args) }; + if let Some(res) = res { + Ok(res) + } else { + // SAFETY: See `send_message_id_error` + Err(unsafe { encountered_error(err) }) + } + } + + #[inline] + #[track_caller] + unsafe fn send_super_message_id_static_error( + obj: T, + sel: Sel, + args: A, + ) -> Result> + where + Self::Inner: ClassType, + ::Super: ClassType, + *mut *mut E: Encode, + A: TupleExtender<*mut *mut E>, + >::PlusOneArgument: ConvertArguments, + E: Message, + Option: MaybeUnwrap, + { + let mut err: *mut E = ptr::null_mut(); + let args = args.add_argument(&mut err); + // SAFETY: See `send_message_id_error` + let res: Option = unsafe { Self::send_super_message_id_static(obj, sel, args) }; + if let Some(res) = res { + Ok(res) + } else { + // SAFETY: See `send_message_id_error` + Err(unsafe { encountered_error(err) }) + } + } +} + // Marked `cold` to tell the optimizer that errors are comparatively rare. // And intentionally not inlined, for much the same reason. #[cold] @@ -85,6 +174,26 @@ impl MsgSendId>> for New { } } +impl MsgSendSuperId>> for New { + type Inner = T::Inner; + + #[inline] + unsafe fn send_super_message_id>>>( + obj: T, + superclass: &AnyClass, + sel: Sel, + args: A, + ) -> R { + let ptr = obj.into_raw_receiver(); + // SAFETY: Same as in `send_message_id` + let obj = unsafe { MsgSend::send_super_message(ptr, superclass, sel, args) }; + // SAFETY: Same as in `send_message_id` + let obj = unsafe { Id::new(obj) }; + // SAFETY: Same as in `send_message_id` + R::maybe_unwrap::(obj, (unsafe { ptr.as_ref() }, sel)) + } +} + impl MsgSendId<&'_ AnyClass, Allocated> for Alloc { #[inline] unsafe fn send_message_id>>( @@ -100,6 +209,24 @@ impl MsgSendId<&'_ AnyClass, Allocated> for Alloc { } } +impl MsgSendSuperId<&'_ AnyClass, Allocated> for Alloc { + type Inner = AnyClass; + + #[inline] + unsafe fn send_super_message_id>>( + cls: &AnyClass, + superclass: &AnyClass, + sel: Sel, + args: A, + ) -> R { + // SAFETY: Same as in `send_message_id` + let obj = unsafe { MsgSend::send_super_message(cls, superclass, sel, args) }; + // SAFETY: Same as in `send_message_id` + let obj = unsafe { Allocated::new(obj) }; + R::maybe_unwrap::(obj, ()) + } +} + impl Alloc { /// Fast path optimization for `msg_send_id![cls, alloc]`. #[inline] @@ -144,6 +271,32 @@ impl MsgSendId, Option>> for Init { } } +impl MsgSendSuperId, Option>> for Init { + type Inner = T; + + #[inline] + unsafe fn send_super_message_id>>>( + obj: PartialInit, + superclass: &AnyClass, + sel: Sel, + args: A, + ) -> R { + let ptr = PartialInit::into_ptr(obj); + // SAFETY: Same as `send_message_id`. + let ptr = unsafe { MsgSend::send_super_message(ptr, superclass, sel, args) }; + // SAFETY: The returned pointer is the same as the one we passed in. + // + // TODO: If this is not the case, a lot will have gone wrong anyhow, + // so unsure if we can do anything better than just ignore the issue? + if let Some(ptr) = NonNull::new(ptr) { + unsafe { set_finalized(ptr) }; + } + // SAFETY: Same as `send_message_id` + let obj = unsafe { Id::new(ptr) }; + R::maybe_unwrap::(obj, (ptr.cast(), sel)) + } +} + impl MsgSendId>> for CopyOrMutCopy { #[inline] unsafe fn send_message_id>>>( @@ -160,6 +313,24 @@ impl MsgSendId>> for CopyOrMutC } } +impl MsgSendSuperId>> for CopyOrMutCopy { + type Inner = T::Inner; + + #[inline] + unsafe fn send_super_message_id>>>( + obj: T, + superclass: &AnyClass, + sel: Sel, + args: A, + ) -> R { + // SAFETY: Same as in `send_message_id` + let obj = unsafe { MsgSend::send_super_message(obj, superclass, sel, args) }; + // SAFETY: Same as in `send_message_id` + let obj = unsafe { Id::new(obj) }; + R::maybe_unwrap::(obj, ()) + } +} + impl MsgSendId>> for Other { #[inline] unsafe fn send_message_id>>>( @@ -183,6 +354,26 @@ impl MsgSendId>> for Other { } } +impl MsgSendSuperId>> for Other { + type Inner = T::Inner; + + #[inline] + unsafe fn send_super_message_id>>>( + obj: T, + superclass: &AnyClass, + sel: Sel, + args: A, + ) -> R { + let ptr = obj.into_raw_receiver(); + // SAFETY: Same as `send_message_id` + let obj = unsafe { MsgSend::send_super_message(ptr, superclass, sel, args) }; + // SAFETY: Same as `send_message_id` + let obj = unsafe { Id::retain_autoreleased(obj) }; + // SAFETY: Same as `send_message_id` + R::maybe_unwrap::(obj, (unsafe { ptr.as_ref() }, sel)) + } +} + pub trait MaybeUnwrap { type Input; #[track_caller] @@ -318,21 +509,60 @@ mod tests { use crate::runtime::{AnyObject, NSObject, NSZone}; use crate::{class, msg_send_id, ClassType}; + mod test_trait_disambugated { + use super::*; + + trait Abc { + fn send_message_id(&self) {} + } + + impl Abc for T {} + + #[test] + fn test_macro_still_works() { + let _: Id = unsafe { msg_send_id![NSObject::class(), new] }; + } + } + + // `new` family + #[test] fn test_new() { - let _obj: Id = unsafe { msg_send_id![NSObject::class(), new] }; - let _obj: Option> = unsafe { msg_send_id![NSObject::class(), new] }; + let mut expected = __ThreadTestData::current(); + let cls = __RcTestObject::class(); + + let _obj: Id = unsafe { msg_send_id![cls, new] }; + let _obj: Option> = unsafe { msg_send_id![cls, new] }; + // This is just a roundabout way of calling `[__RcTestObject new]`. + let _obj: Id = unsafe { msg_send_id![super(cls, cls.metaclass()), new] }; + let _obj: Option> = unsafe { msg_send_id![super(cls, cls.metaclass()), new] }; + + // `__RcTestObject` does not override `new`, so this just ends up + // calling `[[__RcTestObject alloc] init]` as usual. + let _obj: Id<__RcTestObject> = + unsafe { msg_send_id![super(cls, NSObject::class().metaclass()), new] }; + + expected.alloc += 5; + expected.init += 5; + expected.assert_current(); } #[test] fn test_new_not_on_class() { let mut expected = __ThreadTestData::current(); let obj = __RcTestObject::new(); + expected.alloc += 1; + expected.init += 1; + expected.assert_current(); let _obj: Id = unsafe { msg_send_id![&obj, newMethodOnInstance] }; let _obj: Option> = unsafe { msg_send_id![&obj, newMethodOnInstance] }; - expected.alloc += 3; - expected.init += 3; + let _obj: Id = + unsafe { msg_send_id![super(&obj, __RcTestObject::class()), newMethodOnInstance] }; + let _obj: Option> = + unsafe { msg_send_id![super(&obj, __RcTestObject::class()), newMethodOnInstance] }; + expected.alloc += 4; + expected.init += 4; expected.assert_current(); } @@ -362,7 +592,82 @@ mod tests { } #[test] - fn test_macro_alloc() { + #[should_panic = "failed creating new instance of NSValue"] + // GNUStep instead returns an invalid instance that panics on accesses + #[cfg_attr(feature = "gnustep-1-7", ignore)] + fn new_nsvalue_fails() { + let _val: Id = unsafe { msg_send_id![class!(NSValue), new] }; + } + + #[test] + #[should_panic = "failed creating new instance using +[__RcTestObject newReturningNull]"] + fn test_new_with_null() { + let _obj: Id<__RcTestObject> = + unsafe { msg_send_id![__RcTestObject::class(), newReturningNull] }; + } + + #[test] + #[should_panic = "failed creating new instance using +[__RcTestObject newReturningNull]"] + fn test_super_new_with_null() { + let _: Id<__RcTestObject> = unsafe { + msg_send_id![ + super(__RcTestObject::class(), __RcTestObject::class().metaclass()), + newReturningNull + ] + }; + } + + #[test] + #[should_panic = "unexpected NULL returned from -[__RcTestObject newMethodOnInstanceNull]"] + fn test_new_any_with_null() { + let obj = __RcTestObject::new(); + let _obj: Id = unsafe { msg_send_id![&obj, newMethodOnInstanceNull] }; + } + + #[test] + #[should_panic = "unexpected NULL returned from -[__RcTestObject newMethodOnInstanceNull]"] + fn test_super_new_any_with_null() { + let obj = __RcTestObject::new(); + let _obj: Id = unsafe { + msg_send_id![ + super(&obj, __RcTestObject::class()), + newMethodOnInstanceNull + ] + }; + } + + #[test] + #[cfg_attr( + debug_assertions, + should_panic = "messsaging newMethodOnInstance to nil" + )] + #[cfg_attr( + not(debug_assertions), + ignore = "unexpected NULL newMethodOnInstance; receiver was NULL" + )] + fn test_new_any_with_null_receiver() { + let obj: *const NSObject = ptr::null(); + let _obj: Id = unsafe { msg_send_id![obj, newMethodOnInstance] }; + } + + #[test] + #[cfg_attr( + debug_assertions, + should_panic = "messsaging newMethodOnInstance to nil" + )] + #[cfg_attr( + not(debug_assertions), + ignore = "unexpected NULL newMethodOnInstance; receiver was NULL" + )] + fn test_super_new_any_with_null_receiver() { + let obj: *const __RcTestObject = ptr::null(); + let _obj: Id = unsafe { msg_send_id![super(obj), newMethodOnInstance] }; + } + + // `alloc` family + + #[test] + fn test_alloc() { let mut expected = __ThreadTestData::current(); let cls = __RcTestObject::class(); @@ -372,7 +677,18 @@ mod tests { drop(obj); expected.release += 1; - expected.dealloc += 1; + // Drop flag ensures uninitialized do not Drop + // expected.drop += 1; + expected.assert_current(); + + // `+[NSObject alloc]` forwards to `allocWithZone:`, so this still + // allocates a `__RcTestObject`. + let _: Allocated = + unsafe { msg_send_id![super(cls, NSObject::class().metaclass()), alloc] }; + expected.alloc += 1; + expected.release += 1; + // Drop flag ensures uninitialized do not Drop + // expected.drop += 1; expected.assert_current(); } @@ -380,138 +696,184 @@ mod tests { fn test_alloc_with_zone() { let mut expected = __ThreadTestData::current(); let cls = __RcTestObject::class(); - let zone: *const NSZone = ptr::null(); + let _obj: Allocated<__RcTestObject> = unsafe { msg_send_id![cls, allocWithZone: zone] }; expected.alloc += 1; expected.assert_current(); + + let _obj: Allocated<__RcTestObject> = + unsafe { msg_send_id![super(cls, cls.metaclass()), allocWithZone: zone] }; + expected.alloc += 1; + expected.assert_current(); + + let _obj: Allocated = + unsafe { msg_send_id![super(cls, NSObject::class().metaclass()), allocWithZone: zone] }; + expected.assert_current(); } #[test] - fn test_macro_init() { + fn test_alloc_with_null() { + let obj: Allocated<__RcTestObject> = + unsafe { msg_send_id![__RcTestObject::class(), allocReturningNull] }; + assert!(Allocated::as_ptr(&obj).is_null()); + } + + // `init` family + + #[test] + fn test_init() { let mut expected = __ThreadTestData::current(); - let cls = __RcTestObject::class(); - let obj: Allocated<__RcTestObject> = unsafe { msg_send_id![cls, alloc] }; + let _: Id<__RcTestObject> = unsafe { msg_send_id![__RcTestObject::alloc(), init] }; expected.alloc += 1; - expected.assert_current(); - - // Don't check allocation error - let _obj: Id<__RcTestObject> = unsafe { msg_send_id![obj, init] }; expected.init += 1; + expected.release += 1; + expected.drop += 1; expected.assert_current(); - let obj: Allocated<__RcTestObject> = unsafe { msg_send_id![cls, alloc] }; + let obj = __RcTestObject::alloc().set_ivars(()); + let _: Id<__RcTestObject> = unsafe { msg_send_id![super(obj), init] }; expected.alloc += 1; + expected.release += 1; + expected.drop += 1; expected.assert_current(); // Check allocation error before init + let obj = __RcTestObject::alloc(); + expected.alloc += 1; assert!(!Allocated::as_ptr(&obj).is_null()); - let _obj: Id<__RcTestObject> = unsafe { msg_send_id![obj, init] }; + let _: Id<__RcTestObject> = unsafe { msg_send_id![obj, init] }; expected.init += 1; + expected.release += 1; + expected.drop += 1; expected.assert_current(); } #[test] - fn test_macro() { - let mut expected = __ThreadTestData::current(); - let cls = __RcTestObject::class(); - crate::rc::autoreleasepool(|_| { - let _obj: Id<__RcTestObject> = unsafe { msg_send_id![cls, new] }; - expected.alloc += 1; - expected.init += 1; - expected.assert_current(); - - let obj = unsafe { msg_send_id![cls, alloc] }; - expected.alloc += 1; - expected.assert_current(); - - let obj: Id<__RcTestObject> = unsafe { msg_send_id![obj, init] }; - expected.init += 1; - expected.assert_current(); - - let _copy: Id<__RcTestObject> = unsafe { msg_send_id![&obj, copy] }; - expected.copy += 1; - expected.alloc += 1; - expected.init += 1; - expected.assert_current(); - - let _mutable_copy: Id<__RcTestObject> = unsafe { msg_send_id![&obj, mutableCopy] }; - expected.mutable_copy += 1; - expected.alloc += 1; - expected.init += 1; - expected.assert_current(); - - let _self: Id<__RcTestObject> = unsafe { msg_send_id![&obj, self] }; - expected.retain += 1; - expected.assert_current(); - - let _desc: Option> = unsafe { msg_send_id![&obj, description] }; - expected.assert_current(); - }); - expected.release += 5; - expected.dealloc += 4; - expected.assert_current(); + #[should_panic = "failed initializing object with -initReturningNull"] + fn test_init_with_null() { + let obj: Allocated<__RcTestObject> = + unsafe { msg_send_id![__RcTestObject::class(), alloc] }; + let _obj: Id<__RcTestObject> = unsafe { msg_send_id![obj, initReturningNull] }; } #[test] - #[should_panic = "failed creating new instance of NSValue"] - // GNUStep instead returns an invalid instance that panics on accesses - #[cfg_attr(feature = "gnustep-1-7", ignore)] - fn new_nsvalue_fails() { - let _val: Id = unsafe { msg_send_id![class!(NSValue), new] }; + #[cfg_attr(debug_assertions, should_panic = "messsaging init to nil")] + #[cfg_attr(not(debug_assertions), ignore = "failed allocating object")] + fn test_init_with_null_receiver() { + let obj: Allocated<__RcTestObject> = + unsafe { msg_send_id![__RcTestObject::class(), allocReturningNull] }; + let _obj: Id<__RcTestObject> = unsafe { msg_send_id![obj, init] }; } #[test] - #[should_panic = "failed creating new instance using +[__RcTestObject newReturningNull]"] - fn test_new_with_null() { - let _obj: Id<__RcTestObject> = - unsafe { msg_send_id![__RcTestObject::class(), newReturningNull] }; + #[should_panic = "tried to initialize ivars after they were already initialized"] + #[cfg_attr(not(debug_assertions), ignore = "only checked with debug assertions")] + fn test_super_init_not_initialized() { + let obj = __RcTestObject::alloc().set_ivars(()); + let _: Id<__RcTestObject> = + unsafe { msg_send_id![super(obj, __RcTestObject::class()), init] }; } #[test] - #[should_panic = "unexpected NULL returned from -[__RcTestObject newMethodOnInstanceNull]"] - fn test_new_any_with_null() { - let obj = __RcTestObject::new(); - let _obj: Id = unsafe { msg_send_id![&obj, newMethodOnInstanceNull] }; + #[should_panic = "tried to finalize an already finalized object"] + #[cfg_attr(not(debug_assertions), ignore = "only checked with debug assertions")] + fn test_super_init_not_finalized() { + let obj = unsafe { PartialInit::new(Allocated::into_ptr(__RcTestObject::alloc())) }; + let _: Id<__RcTestObject> = + unsafe { msg_send_id![super(obj, __RcTestObject::class()), init] }; } + // `copy` family + #[test] - #[should_panic = "unexpected NULL newMethodOnInstance; receiver was NULL"] - #[cfg(not(debug_assertions))] // Does NULL receiver checks - fn test_new_any_with_null_receiver() { - let obj: *const NSObject = ptr::null(); - let _obj: Id = unsafe { msg_send_id![obj, newMethodOnInstance] }; + fn test_copy() { + let obj = __RcTestObject::new(); + let mut expected = __ThreadTestData::current(); + + let _: Id<__RcTestObject> = unsafe { msg_send_id![&obj, copy] }; + expected.copy += 1; + expected.alloc += 1; + expected.init += 1; + expected.release += 1; + expected.drop += 1; + expected.assert_current(); + + // `+[NSObject copy]` forwards to `copyWithZone:`, so this still + // creates a `__RcTestObject`. + let _: Id = unsafe { msg_send_id![super(&obj), copy] }; + expected.copy += 1; + expected.alloc += 1; + expected.init += 1; + expected.release += 1; + expected.drop += 1; + expected.assert_current(); } #[test] - fn test_alloc_with_null() { - let _obj: Allocated<__RcTestObject> = - unsafe { msg_send_id![__RcTestObject::class(), allocReturningNull] }; + #[should_panic = "failed copying object"] + fn test_copy_with_null() { + let obj = __RcTestObject::new(); + let _obj: Id<__RcTestObject> = unsafe { msg_send_id![&obj, copyReturningNull] }; } #[test] - #[should_panic = "failed initializing object with -initReturningNull"] - fn test_init_with_null() { - let obj: Allocated<__RcTestObject> = - unsafe { msg_send_id![__RcTestObject::class(), alloc] }; - let _obj: Id<__RcTestObject> = unsafe { msg_send_id![obj, initReturningNull] }; + #[should_panic = "failed copying object"] + fn test_super_copy_with_null() { + let obj = __RcTestObject::new(); + let _obj: Id<__RcTestObject> = + unsafe { msg_send_id![super(&obj, __RcTestObject::class()), copyReturningNull] }; } + // `mutableCopy` family + #[test] - #[should_panic = "failed allocating object"] - #[cfg(not(debug_assertions))] // Does NULL receiver checks - fn test_init_with_null_receiver() { - let obj: Allocated<__RcTestObject> = - unsafe { msg_send_id![__RcTestObject::class(), allocReturningNull] }; - let _obj: Id<__RcTestObject> = unsafe { msg_send_id![obj, init] }; + fn test_mutable_copy() { + let obj = __RcTestObject::new(); + let mut expected = __ThreadTestData::current(); + + let _: Id<__RcTestObject> = unsafe { msg_send_id![&obj, mutableCopy] }; + expected.mutable_copy += 1; + expected.alloc += 1; + expected.init += 1; + expected.release += 1; + expected.drop += 1; + expected.assert_current(); + + // `+[NSObject mutableCopy]` forwards to `mutableCopyWithZone:`, so + // this still creates a `__RcTestObject`. + let _: Id = unsafe { msg_send_id![super(&obj), mutableCopy] }; + expected.mutable_copy += 1; + expected.alloc += 1; + expected.init += 1; + expected.release += 1; + expected.drop += 1; + expected.assert_current(); } + // No method family + #[test] - #[should_panic = "failed copying object"] - fn test_copy_with_null() { + fn test_normal() { let obj = __RcTestObject::new(); - let _obj: Id<__RcTestObject> = unsafe { msg_send_id![&obj, copyReturningNull] }; + let mut expected = __ThreadTestData::current(); + + let _: Id<__RcTestObject> = unsafe { msg_send_id![&obj, self] }; + expected.retain += 1; + expected.release += 1; + expected.assert_current(); + + let _: Id<__RcTestObject> = unsafe { msg_send_id![super(&obj), self] }; + expected.retain += 1; + expected.release += 1; + expected.assert_current(); + + let _: Option> = unsafe { msg_send_id![&obj, description] }; + expected.assert_current(); + + let _: Option> = unsafe { msg_send_id![super(&obj), description] }; + expected.assert_current(); } #[test] @@ -529,26 +891,13 @@ mod tests { } #[test] - #[should_panic = "unexpected NULL description; receiver was NULL"] - #[cfg(not(debug_assertions))] // Does NULL receiver checks + #[cfg_attr(debug_assertions, should_panic = "messsaging description to nil")] + #[cfg_attr( + not(debug_assertions), + ignore = "unexpected NULL description; receiver was NULL" + )] fn test_normal_with_null_receiver() { let obj: *const NSObject = ptr::null(); let _obj: Id = unsafe { msg_send_id![obj, description] }; } - - mod test_trait_disambugated { - use super::*; - - trait Abc { - fn send_message_id() {} - } - - impl Abc for T {} - - #[test] - fn test_macro_still_works() { - let cls = class!(NSObject); - let _obj: Id = unsafe { msg_send_id![cls, new] }; - } - } } diff --git a/crates/objc2/src/__macro_helpers/writeback.rs b/crates/objc2/src/__macro_helpers/writeback.rs index 3b4e78f77..aaf2a3fd7 100644 --- a/crates/objc2/src/__macro_helpers/writeback.rs +++ b/crates/objc2/src/__macro_helpers/writeback.rs @@ -258,7 +258,7 @@ mod tests { if error.is_some() { expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; } drop(error); expected.assert_current(); @@ -279,7 +279,7 @@ mod tests { expected.init += 1; expected.retain += 1; expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; helper(&mut expected, true, Some(__RcTestObject::new())); } @@ -328,19 +328,19 @@ mod tests { drop(obj); expected.release += 1; if AUTORELEASE_SKIPPED { - expected.dealloc += 1; + expected.drop += 1; } expected.assert_current(); }); if !AUTORELEASE_SKIPPED { expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; } expected.assert_current(); drop(err); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } } diff --git a/crates/objc2/src/declare/ivar.rs b/crates/objc2/src/declare/ivar.rs deleted file mode 100644 index d89b32a6e..000000000 --- a/crates/objc2/src/declare/ivar.rs +++ /dev/null @@ -1,388 +0,0 @@ -use core::fmt; -use core::marker::PhantomData; -use core::mem::{self, MaybeUninit}; -use core::ops::{Deref, DerefMut}; -use core::ptr::{self, NonNull}; - -use crate::encode::Encode; -use crate::runtime::AnyObject; - -pub(crate) mod private { - pub trait Sealed {} -} - -/// Types that may be used in ivars. -/// -/// This may be either: -/// - [`IvarBool`][super::IvarBool]. -/// - [`IvarDrop`][super::IvarDrop]. -/// - [`IvarEncode`][super::IvarEncode]. -/// -/// This is a sealed trait, and should not need to be implemented. Open an -/// issue if you know a use-case where this restrition should be lifted! -/// -/// -/// # Safety -/// -/// You cannot rely on any safety guarantees from this. -// -// The type must have the same memory layout as the output type. -// -// Additionally, the type must be safe to drop even if zero-initialized. -// -// Ivars are documented to be zero-initialized in [this section of the -// Objective-C manual][obj-dynamically-created], and that has been true since -// at least [the Objective-C version shipped with Mac OS X 10.0][objc4-208]. -// -// [obj-dynamically-created]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW7 -// [objc4-208]: https://github.com/apple-oss-distributions/objc4/blob/objc4-208/runtime/objc-class.m#L367 -pub unsafe trait InnerIvarType: private::Sealed + Encode { - /// The type that an `Ivar` containing this will dereference to. - /// - /// E.g. `Ivar>>` will deref to `Box`. - type Output; - - /// # Safety - /// - /// The instance variable must have been initialized. - #[doc(hidden)] - unsafe fn __deref(&self) -> &Self::Output; - - /// # Safety - /// - /// The instance variable must have been initialized. - #[doc(hidden)] - unsafe fn __deref_mut(&mut self) -> &mut Self::Output; -} - -/// Helper trait for defining instance variables. -/// -/// This should be implemented for an empty marker type, which can then be -/// used within [`Ivar`] to refer to the instance variable. -/// -/// -/// # Safety -/// -/// Really, [`Ivar`] should be marked as `unsafe`, but since we can't do that -/// we'll mark this trait as `unsafe` instead. See [`Ivar`] for safety -/// requirements. -/// -/// -/// # Examples -/// -/// Create an instance variable `myCustomIvar` with type `i32`. -/// -/// ``` -/// use objc2::declare::{IvarEncode, IvarType}; -/// -/// // Helper type -/// struct MyCustomIvar; -/// -/// unsafe impl IvarType for MyCustomIvar { -/// type Type = IvarEncode; -/// const NAME: &'static str = "myCustomIvar"; -/// } -/// -/// // `Ivar` can now be used -/// ``` -pub unsafe trait IvarType { - /// The type of the instance variable. - type Type: InnerIvarType; - /// The name of the instance variable. - const NAME: &'static str; - - #[doc(hidden)] - unsafe fn __ivar_ptr(ptr: NonNull) -> NonNull { - // FIXME: This is currently unsound! Looking up the instance variable - // dynamically will return the wrong variable if two variables with - // the same name exist. - let ivar = unsafe { ptr.as_ref() }.lookup_instance_variable_dynamically(Self::NAME); - ivar.debug_assert_encoding(&Self::Type::ENCODING); - unsafe { AnyObject::ivar_at_offset(ptr, ivar.offset()) } - } -} - -/// A wrapper type over a custom instance variable. -/// -/// This type is not meant to be constructed by itself, it must reside within -/// another struct meant to represent an Objective-C object. -/// -/// On [`Deref`] it then uses the [`IvarType::NAME`] string to access the ivar -/// of the containing object. -/// -/// Note that this is not ([currently][zst-hack]) allowed by [stacked -/// borrows][sb], but due to objects being zero-sized types, we don't have -/// provenance over the ivars anyhow, this should be just as sound as normal -/// instance variable access. -/// -/// [sb]: https://github.com/rust-lang/unsafe-code-guidelines/blob/e21202c60c7be03dd2ab016ada92fb5305d40438/wip/stacked-borrows.md -/// [zst-hack]: https://github.com/rust-lang/unsafe-code-guidelines/issues/305 -/// -/// -/// # `bool` handling -/// -/// This does _not_ perform a conversion step between [`bool`] and the -/// Objective-C `BOOL`; use [`runtime::Bool`][crate::runtime::Bool] when you -/// want your instance variable to be accessible from other Objective-C code. -/// -/// -/// # Safety -/// -/// This must be used within a type that act as an Objective-C object. In -/// particular, this is never safe to have on the stack by itself. -/// -/// Additionally, the instance variable described by `T` must be available on -/// the specific instance, and be of the exact same type. When declaring the -/// object yourself, you can ensure this using -/// [`ClassBuilder::add_static_ivar`]. -/// -/// Finally, two ivars with the same name must not be used on the same object. -/// -/// [`ClassBuilder::add_static_ivar`]: crate::declare::ClassBuilder::add_static_ivar -/// -/// -/// # Examples -/// -/// ``` -/// use objc2::declare::{Ivar, IvarEncode, IvarType}; -/// use objc2::runtime::NSObject; -/// -/// // Declare ivar with given type and name -/// struct MyCustomIvar; -/// unsafe impl IvarType for MyCustomIvar { -/// type Type = IvarEncode; -/// const NAME: &'static str = "myCustomIvar"; -/// } -/// -/// // Custom object -/// #[repr(C)] -/// pub struct MyObject { -/// inner: NSObject, -/// // SAFETY: The instance variable is used within an object, and it is -/// // properly declared below. -/// my_ivar: Ivar, -/// } -/// -/// # use objc2::ClassType; -/// # use objc2::declare::ClassBuilder; -/// # let mut builder = ClassBuilder::new("MyObject", NSObject::class()).unwrap(); -/// // Declare the class and add the instance variable to it -/// builder.add_static_ivar::(); -/// # let _cls = builder.register(); -/// -/// let obj: MyObject; -/// // You can now access `obj.my_ivar` -/// ``` -/// -/// See also the `declare_ivar.rs` example. -#[repr(C)] -// Must not be `Copy` nor `Clone`! -pub struct Ivar { - /// Make this type allowed in `repr(C)` - inner: [u8; 0], - /// For proper variance and auto traits - item: PhantomData, -} - -impl Drop for Ivar { - #[inline] - fn drop(&mut self) { - if mem::needs_drop::() { - unsafe { ptr::drop_in_place(self.as_inner_mut_ptr().as_ptr()) } - } - } -} - -impl Ivar { - /// Get a pointer to the instance variable. - /// - /// Note that if the ivar has already been initialized, you can use the - /// `Deref` implementation to get a reference. - /// - /// This is similar to [`MaybeUninit::as_ptr`], see that for usage - /// instructions. - pub fn as_ptr(this: &Self) -> *const ::Target { - this.as_inner_ptr().as_ptr().cast() - } - - fn as_inner_ptr(&self) -> NonNull { - let ptr: NonNull = NonNull::from(self).cast(); - - // SAFETY: The user ensures that this is placed in a struct that can - // be reinterpreted as an `AnyObject`. Since `Ivar` can never be - // constructed by itself (and is neither Copy nor Clone), we know that - // it is guaranteed to _stay_ in said struct. - // - // Even if the user were to do `mem::swap`, the `Ivar` has a unique - // type (and does not hold any data), so that wouldn't break anything. - // - // Note: We technically don't have provenance over the object, nor the - // ivar, but the object doesn't have provenance over the ivar either, - // so that is fine. - unsafe { T::__ivar_ptr(ptr) } - } - - /// Get a mutable pointer to the instance variable. - /// - /// This is useful when you want to initialize the ivar inside an `init` - /// method (where it may otherwise not have been safely initialized yet). - /// - /// Note that if the ivar has already been initialized, you can use the - /// `DerefMut` implementation to get a mutable reference. - /// - /// This is similar to [`MaybeUninit::as_mut_ptr`], see that for usage - /// instructions. - pub fn as_mut_ptr(this: &mut Self) -> *mut ::Target { - this.as_inner_mut_ptr().as_ptr().cast() - } - - fn as_inner_mut_ptr(&mut self) -> NonNull { - let ptr: NonNull = NonNull::from(self).cast(); - - // SAFETY: Same as `as_inner_ptr` - unsafe { T::__ivar_ptr(ptr) } - } - - /// Sets the value of the instance variable. - /// - /// This is useful when you want to initialize the ivar inside an `init` - /// method (where it may otherwise not have been safely initialized yet). - /// - /// This is similar to [`MaybeUninit::write`], see that for usage - /// instructions. - pub fn write(this: &mut Self, val: ::Target) -> &mut ::Target { - let ptr: *mut ::Output = Self::as_mut_ptr(this); - let ptr: *mut MaybeUninit<::Output> = ptr.cast(); - let ivar = unsafe { ptr.as_mut().unwrap_unchecked() }; - ivar.write(val) - } -} - -impl Deref for Ivar { - type Target = ::Output; - - #[inline] - fn deref(&self) -> &Self::Target { - // SAFETY: User ensures that the `Ivar` is only used when the ivar - // exists, has the correct type, and has been properly initialized. - // - // Since all accesses to a particular ivar only goes through one - // `Ivar`, if we have `&Ivar` we know that `&T` is safe. - unsafe { self.as_inner_ptr().as_ref().__deref() } - } -} - -impl DerefMut for Ivar { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - // SAFETY: User ensures that the `Ivar` is only used when the ivar - // exists, has the correct type, and has been properly initialized. - // - // Safe as mutable because there is only one access to a - // particular ivar at a time (since we have `&mut self`). - - // Note: We're careful not to create `&mut AnyObject` because the user - // might have two mutable references to different ivars, as such: - // - // ``` - // #[repr(C)] - // struct X { - // inner: AnyObject, - // ivar1: Ivar, - // ivar2: Ivar, - // } - // - // let mut x: X; - // let ivar1: &mut Ivar = &mut x.ivar1; - // let ivar2: &mut Ivar = &mut x.ivar2; - // ``` - // - // And using `mut` would create aliasing mutable reference to the - // object. - unsafe { self.as_inner_mut_ptr().as_mut().__deref_mut() } - } -} - -/// Format as a pointer to the instance variable. -impl fmt::Pointer for Ivar { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&Self::as_ptr(self), f) - } -} - -#[cfg(test)] -mod tests { - use core::mem; - use core::panic::{RefUnwindSafe, UnwindSafe}; - use std::sync::atomic::{AtomicBool, Ordering}; - - use super::*; - use crate::declare::{IvarBool, IvarEncode}; - use crate::mutability::Mutable; - use crate::rc::Id; - use crate::runtime::NSObject; - use crate::{declare_class, msg_send, msg_send_id, test_utils, ClassType}; - - struct TestIvar; - - unsafe impl IvarType for TestIvar { - type Type = IvarEncode; - const NAME: &'static str = "_foo"; - } - - #[repr(C)] - struct IvarTestObject { - inner: NSObject, - foo: Ivar, - } - - #[test] - fn auto_traits() { - fn assert_auto_traits() {} - assert_auto_traits::>(); - - // Ensure that `Ivar` is zero-sized - assert_eq!(mem::size_of::>(), 0); - assert_eq!(mem::align_of::>(), 1); - } - - #[test] - fn access_ivar() { - let mut obj = test_utils::custom_object(); - let _: () = unsafe { msg_send![&mut obj, setFoo: 42u32] }; - - let obj = unsafe { Id::as_ptr(&obj).cast::().as_ref().unwrap() }; - assert_eq!(*obj.foo, 42); - } - - #[test] - fn ensure_custom_drop_is_possible() { - static HAS_RUN_DEALLOC: AtomicBool = AtomicBool::new(false); - - declare_class!( - #[derive(Debug, PartialEq, Eq)] - struct CustomDrop { - ivar: IvarEncode, - ivar_bool: IvarBool<"_ivar_bool">, - } - - mod customdrop; - - unsafe impl ClassType for CustomDrop { - type Super = NSObject; - type Mutability = Mutable; - const NAME: &'static str = "CustomDrop"; - } - ); - - impl Drop for CustomDrop { - fn drop(&mut self) { - HAS_RUN_DEALLOC.store(true, Ordering::Relaxed); - } - } - - let _: Id = unsafe { msg_send_id![CustomDrop::class(), new] }; - - assert!(HAS_RUN_DEALLOC.load(Ordering::Relaxed)); - } -} diff --git a/crates/objc2/src/declare/ivar_bool.rs b/crates/objc2/src/declare/ivar_bool.rs deleted file mode 100644 index f7e1930a5..000000000 --- a/crates/objc2/src/declare/ivar_bool.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::encode::{Encode, Encoding}; - -use super::InnerIvarType; - -/// Ivar of [`bool`]. -/// -/// This is used to work around the fact that `bool` is not [`Encode`]. -/// -/// If you want to access this instance variable to Objective-C, you must do -/// so using C99 `_Bool`; if you want to use `BOOL` in Objective-C, you should -/// use `IvarEncode`. -#[repr(transparent)] -#[allow(missing_copy_implementations)] -#[allow(missing_debug_implementations)] -pub struct IvarBool(bool); - -unsafe impl Encode for IvarBool { - const ENCODING: Encoding = Encoding::Bool; -} - -impl super::ivar::private::Sealed for IvarBool {} - -// SAFETY: IvarBool is `#[repr(transparent)]`, and `bool` is safe to -// zero-initialize -unsafe impl InnerIvarType for IvarBool { - type Output = bool; - - #[inline] - unsafe fn __deref(&self) -> &Self::Output { - &self.0 - } - - #[inline] - unsafe fn __deref_mut(&mut self) -> &mut Self::Output { - &mut self.0 - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use core::mem; - - #[test] - fn needs_drop() { - assert!(!mem::needs_drop::()); - assert_eq!(mem::size_of::(), mem::size_of::()); - } -} diff --git a/crates/objc2/src/declare/ivar_drop.rs b/crates/objc2/src/declare/ivar_drop.rs deleted file mode 100644 index 0fa488608..000000000 --- a/crates/objc2/src/declare/ivar_drop.rs +++ /dev/null @@ -1,378 +0,0 @@ -use alloc::boxed::Box; -use core::ffi::c_void; - -use crate::encode::{Encode, Encoding}; -use crate::rc::Id; -use crate::Message; - -use super::InnerIvarType; - -mod private { - /// # Safety - /// - /// The inner type must be safe to zero-initialize. - pub unsafe trait IvarDropHelper { - type Inner; - } -} - -/// Ivar types that may drop. -/// -/// This currently works with the following types: -/// - `Box` -/// - `Option>` -/// - `Id` -/// - `Option>` -/// -/// Further may be added when the standard library guarantee their layout. -#[repr(transparent)] -#[allow(missing_debug_implementations)] -pub struct IvarDrop(::Inner); - -impl super::ivar::private::Sealed for IvarDrop {} - -// Note that we use `*const c_void` and not `*const T` to allow _any_ type, -// not just types that can be encoded by Objective-C -unsafe impl Encode for IvarDrop> { - const ENCODING: Encoding = <*const c_void>::ENCODING; -} - -// SAFETY: `Option>` is safe to zero-initialize -unsafe impl private::IvarDropHelper for Box { - type Inner = Option>; -} - -// SAFETY: The memory layout of `Box` is guaranteed to be a pointer: -// -// -// The user ensures that the Box has been initialized in an `init` method -// before being used. -unsafe impl InnerIvarType for IvarDrop> { - type Output = Box; - - #[inline] - unsafe fn __deref(&self) -> &Self::Output { - match &self.0 { - Some(inner) => inner, - None => unsafe { box_unreachable() }, - } - } - - #[inline] - unsafe fn __deref_mut(&mut self) -> &mut Self::Output { - match &mut self.0 { - Some(inner) => inner, - None => unsafe { box_unreachable() }, - } - } -} - -unsafe impl Encode for IvarDrop>> { - const ENCODING: Encoding = <*const c_void>::ENCODING; -} - -// SAFETY: `Option>` is safe to zero-initialize -unsafe impl private::IvarDropHelper for Option> { - type Inner = Option>; -} - -// SAFETY: `Option>` guarantees the null-pointer optimization, so for -// `T: Sized` the layout is just a pointer: -// -// -// This is valid to initialize as all-zeroes, so the user doesn't have to do -// anything to initialize it. -unsafe impl InnerIvarType for IvarDrop>> { - type Output = Option>; - - #[inline] - unsafe fn __deref(&self) -> &Self::Output { - &self.0 - } - - #[inline] - unsafe fn __deref_mut(&mut self) -> &mut Self::Output { - &mut self.0 - } -} - -unsafe impl Encode for IvarDrop> { - const ENCODING: Encoding = <*const T>::ENCODING; -} - -// SAFETY: `Option>` is safe to zero-initialize -unsafe impl private::IvarDropHelper for Id { - type Inner = Option>; -} - -// SAFETY: `Id` is `NonNull`, and hence safe to store as a pointer. -// -// The user ensures that the Id has been initialized in an `init` method -// before being used. -// -// Note: We could technically do `impl InnerIvarType for Ivar>` -// directly today, but since we can't do so for `Box` (because that is -// `#[fundamental]`), I think it makes sense to handle them similarly. -unsafe impl InnerIvarType for IvarDrop> { - type Output = Id; - - #[inline] - unsafe fn __deref(&self) -> &Self::Output { - match &self.0 { - Some(inner) => inner, - None => unsafe { id_unreachable() }, - } - } - - #[inline] - unsafe fn __deref_mut(&mut self) -> &mut Self::Output { - match &mut self.0 { - Some(inner) => inner, - None => unsafe { id_unreachable() }, - } - } -} - -unsafe impl Encode for IvarDrop>> { - const ENCODING: Encoding = <*const T>::ENCODING; -} - -// SAFETY: `Option>` is safe to zero-initialize -unsafe impl private::IvarDropHelper for Option> { - type Inner = Option>; -} - -// SAFETY: `Id` guarantees the null-pointer optimization. -// -// This is valid to initialize as all-zeroes, so the user doesn't have to do -// anything to initialize it. -unsafe impl InnerIvarType for IvarDrop>> { - type Output = Option>; - - #[inline] - unsafe fn __deref(&self) -> &Self::Output { - &self.0 - } - - #[inline] - unsafe fn __deref_mut(&mut self) -> &mut Self::Output { - &mut self.0 - } -} - -// TODO: Allow the following once their layout is guaranteed by `std`: -// - Arc -// - Option> -// - sync::Weak -// - Rc -// - Option> -// - rc::Weak -// - Vec -// - String - -// TODO: Allow `WeakId` once we figure out how to allow it being initialized -// by default. - -#[inline] -#[track_caller] -unsafe fn id_unreachable() -> ! { - #[cfg(debug_assertions)] - { - unreachable!("an Id in instance variables must always be initialized before use!") - } - // SAFETY: Checked by caller - #[cfg(not(debug_assertions))] - unsafe { - core::hint::unreachable_unchecked() - } -} - -#[inline] -#[track_caller] -unsafe fn box_unreachable() -> ! { - #[cfg(debug_assertions)] - { - unreachable!("a Box in instance variables must always be initialized before use!") - } - // SAFETY: Checked by caller - #[cfg(not(debug_assertions))] - unsafe { - core::hint::unreachable_unchecked() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::declare::{Ivar, IvarType}; - use crate::mutability::Mutable; - use crate::rc::{Allocated, __RcTestObject, __ThreadTestData}; - use crate::runtime::NSObject; - use crate::{declare_class, msg_send, msg_send_id, ClassType}; - - struct TestIvar1; - unsafe impl IvarType for TestIvar1 { - type Type = IvarDrop>; - const NAME: &'static str = "_abc"; - } - - struct TestIvar2; - unsafe impl IvarType for TestIvar2 { - type Type = IvarDrop>>; - const NAME: &'static str = "_abc"; - } - - struct TestIvar3; - unsafe impl IvarType for TestIvar3 { - type Type = IvarDrop>; - const NAME: &'static str = "_abc"; - } - - struct TestIvar4; - unsafe impl IvarType for TestIvar4 { - type Type = IvarDrop>>; - const NAME: &'static str = "_abc"; - } - - declare_class!( - #[derive(Debug, PartialEq, Eq)] - struct IvarTester { - ivar1: IvarDrop, "_ivar1">, - ivar2: IvarDrop>, "_ivar2">, - ivar3: IvarDrop>, "_ivar3">, - ivar4: IvarDrop>>, "_ivar4">, - } - - mod ivartester; - - unsafe impl ClassType for IvarTester { - type Super = NSObject; - type Mutability = Mutable; - const NAME: &'static str = "IvarTester"; - } - - unsafe impl IvarTester { - #[method(init)] - fn init(&mut self) -> Option<&mut Self> { - let this: Option<&mut Self> = unsafe { msg_send![super(self), init] }; - this.map(|this| { - Ivar::write(&mut this.ivar1, __RcTestObject::new()); - *this.ivar2 = Some(__RcTestObject::new()); - Ivar::write(&mut this.ivar3, Box::new(__RcTestObject::new())); - *this.ivar4 = Some(Box::new(__RcTestObject::new())); - this - }) - } - - #[method(initInvalid)] - fn init_invalid(&mut self) -> Option<&mut Self> { - // Don't actually initialize anything here; this creates an - // invalid instance, where accessing the two ivars `ivar1` - // and `ivar3` is UB - unsafe { msg_send![super(self), init] } - } - } - ); - - declare_class!( - #[derive(Debug, PartialEq, Eq)] - struct IvarTesterSubclass { - ivar5: IvarDrop, "_ivar5">, - } - - mod ivartestersubclass; - - unsafe impl ClassType for IvarTesterSubclass { - type Super = IvarTester; - type Mutability = Mutable; - const NAME: &'static str = "IvarTesterSubclass"; - } - - unsafe impl IvarTesterSubclass { - #[method(init)] - fn init(&mut self) -> Option<&mut Self> { - let this: Option<&mut Self> = unsafe { msg_send![super(self), init] }; - this.map(|this| { - Ivar::write(&mut this.ivar5, __RcTestObject::new()); - this - }) - } - } - ); - - #[test] - fn test_alloc_dealloc() { - let expected = __ThreadTestData::current(); - - let obj: Allocated = unsafe { msg_send_id![IvarTester::class(), alloc] }; - expected.assert_current(); - - drop(obj); - expected.assert_current(); - } - - #[test] - fn test_init_drop() { - let mut expected = __ThreadTestData::current(); - - let mut obj: Id = unsafe { msg_send_id![IvarTester::class(), new] }; - expected.alloc += 4; - expected.init += 4; - expected.assert_current(); - - *obj.ivar1 = (*obj.ivar1).clone(); - expected.retain += 1; - expected.release += 1; - expected.assert_current(); - - *obj.ivar2 = None; - expected.release += 1; - expected.dealloc += 1; - expected.assert_current(); - - drop(obj); - expected.release += 3; - expected.dealloc += 3; - expected.assert_current(); - } - - #[test] - fn test_subclass() { - let mut expected = __ThreadTestData::current(); - - let mut obj: Id = - unsafe { msg_send_id![IvarTesterSubclass::class(), new] }; - expected.alloc += 5; - expected.init += 5; - expected.assert_current(); - - *obj.ivar5 = (*obj.ivar1).clone(); - expected.retain += 1; - expected.release += 1; - expected.dealloc += 1; - expected.assert_current(); - - drop(obj); - expected.release += 5; - expected.dealloc += 4; - expected.assert_current(); - } - - #[test] - #[cfg_attr(not(debug_assertions), ignore = "only panics in debug mode")] - #[should_panic = "an Id in instance variables must always be initialized before use"] - fn test_init_invalid_ref() { - let obj: Id = unsafe { msg_send_id![IvarTester::alloc(), initInvalid] }; - - std::println!("{:?}", obj.ivar1); - } - - #[test] - #[cfg_attr(not(debug_assertions), ignore = "only panics in debug mode")] - #[should_panic = "an Id in instance variables must always be initialized before use"] - fn test_init_invalid_mut() { - let mut obj: Id = unsafe { msg_send_id![IvarTester::alloc(), initInvalid] }; - - *obj.ivar1 = __RcTestObject::new(); - } -} diff --git a/crates/objc2/src/declare/ivar_encode.rs b/crates/objc2/src/declare/ivar_encode.rs deleted file mode 100644 index 3a4300059..000000000 --- a/crates/objc2/src/declare/ivar_encode.rs +++ /dev/null @@ -1,75 +0,0 @@ -use core::mem::MaybeUninit; - -use crate::encode::{Encode, Encoding}; - -use super::InnerIvarType; - -/// Ivar types that are [`Encode`]. -// -// Note: We put the inner type in a `MaybeUninit`, since we may need to access -// this type before the inner type has been properly initialized. -#[repr(transparent)] -#[allow(missing_debug_implementations)] -pub struct IvarEncode(MaybeUninit); - -// We intentionally don't implement `Drop`, since that may happen before the -// ivar has been initialized. -// -// For example in the case of `NonNull`, it would be zero-initialized, -// which is an invalid state for that to have. - -// SAFETY: `IvarEncode` is `#[repr(transparent)]`, and the layout of -// `MaybeUninit` is the same as `T`. -unsafe impl Encode for IvarEncode { - const ENCODING: Encoding = T::ENCODING; -} - -impl super::ivar::private::Sealed for IvarEncode {} - -// SAFETY: `IvarEncode` has the same memory layout as T, and -// `MaybeUninit` is safe to zero-initialize. -unsafe impl InnerIvarType for IvarEncode { - type Output = T; - - #[inline] - unsafe fn __deref(&self) -> &Self::Output { - // SAFETY: Checked by caller - unsafe { self.0.assume_init_ref() } - } - - #[inline] - unsafe fn __deref_mut(&mut self) -> &mut Self::Output { - // SAFETY: Checked by caller - unsafe { self.0.assume_init_mut() } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use core::mem; - - #[test] - fn needs_drop() { - assert!(!mem::needs_drop::>()); - assert!(!mem::needs_drop::>()); - - // You wouldn't do this, but let's make sure it works as expected - #[repr(transparent)] - struct DropAndEncode(i32); - - unsafe impl Encode for DropAndEncode { - const ENCODING: Encoding = i32::ENCODING; - } - - impl Drop for DropAndEncode { - fn drop(&mut self) {} - } - - assert!(mem::needs_drop::()); - assert!(!mem::needs_drop::>()); - - assert_eq!(mem::size_of::>(), mem::size_of::()); - } -} diff --git a/crates/objc2/src/declare/ivar_forwarding_impls.rs b/crates/objc2/src/declare/ivar_forwarding_impls.rs deleted file mode 100644 index 3b80f25c7..000000000 --- a/crates/objc2/src/declare/ivar_forwarding_impls.rs +++ /dev/null @@ -1,340 +0,0 @@ -//! Trivial forwarding impls on `Ivar`. -//! -//! Kept here to keep `ivar.rs` free from this boilerplate. -//! -//! `#[inline]` is used where the standard library `Box` uses it. - -#![forbid(unsafe_code)] - -// use alloc::borrow; -use alloc::string::String; -use alloc::vec::Vec; -use core::cmp::Ordering; -use core::fmt; -use core::future::Future; -use core::hash; -use core::iter::FusedIterator; -use core::ops::Deref; -use core::pin::Pin; -use core::task::{Context, Poll}; -use std::error::Error; -use std::io; - -use super::{Ivar, IvarType}; - -impl PartialEq for Ivar -where - ::Target: PartialEq, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - (**self).eq(&**other) - } - - #[inline] - #[allow(clippy::partialeq_ne_impl)] - fn ne(&self, other: &Self) -> bool { - (**self).ne(&**other) - } -} - -impl Eq for Ivar where ::Target: Eq {} - -impl PartialOrd for Ivar -where - ::Target: PartialOrd, -{ - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - (**self).partial_cmp(&**other) - } - #[inline] - fn lt(&self, other: &Self) -> bool { - (**self).lt(&**other) - } - #[inline] - fn le(&self, other: &Self) -> bool { - (**self).le(&**other) - } - #[inline] - fn ge(&self, other: &Self) -> bool { - (**self).ge(&**other) - } - #[inline] - fn gt(&self, other: &Self) -> bool { - (**self).gt(&**other) - } -} - -impl Ord for Ivar -where - ::Target: Ord, -{ - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - (**self).cmp(&**other) - } -} - -impl hash::Hash for Ivar -where - ::Target: hash::Hash, -{ - fn hash(&self, state: &mut H) { - (**self).hash(state) - } -} - -impl hash::Hasher for Ivar -where - ::Target: hash::Hasher, -{ - fn finish(&self) -> u64 { - (**self).finish() - } - fn write(&mut self, bytes: &[u8]) { - (**self).write(bytes) - } - fn write_u8(&mut self, i: u8) { - (**self).write_u8(i) - } - fn write_u16(&mut self, i: u16) { - (**self).write_u16(i) - } - fn write_u32(&mut self, i: u32) { - (**self).write_u32(i) - } - fn write_u64(&mut self, i: u64) { - (**self).write_u64(i) - } - fn write_u128(&mut self, i: u128) { - (**self).write_u128(i) - } - fn write_usize(&mut self, i: usize) { - (**self).write_usize(i) - } - fn write_i8(&mut self, i: i8) { - (**self).write_i8(i) - } - fn write_i16(&mut self, i: i16) { - (**self).write_i16(i) - } - fn write_i32(&mut self, i: i32) { - (**self).write_i32(i) - } - fn write_i64(&mut self, i: i64) { - (**self).write_i64(i) - } - fn write_i128(&mut self, i: i128) { - (**self).write_i128(i) - } - fn write_isize(&mut self, i: isize) { - (**self).write_isize(i) - } -} - -impl fmt::Display for Ivar -where - ::Target: fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -impl fmt::Debug for Ivar -where - ::Target: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -impl Iterator for Ivar -where - ::Target: Iterator, -{ - type Item = <::Target as Iterator>::Item; - fn next(&mut self) -> Option<<::Target as Iterator>::Item> { - (**self).next() - } - fn size_hint(&self) -> (usize, Option) { - (**self).size_hint() - } - fn nth(&mut self, n: usize) -> Option<<::Target as Iterator>::Item> { - (**self).nth(n) - } -} - -impl DoubleEndedIterator for Ivar -where - ::Target: DoubleEndedIterator, -{ - fn next_back(&mut self) -> Option<<::Target as Iterator>::Item> { - (**self).next_back() - } - fn nth_back(&mut self, n: usize) -> Option<<::Target as Iterator>::Item> { - (**self).nth_back(n) - } -} - -impl ExactSizeIterator for Ivar -where - ::Target: ExactSizeIterator, -{ - fn len(&self) -> usize { - (**self).len() - } -} - -impl FusedIterator for Ivar where ::Target: FusedIterator {} - -// impl borrow::Borrow<::Target> for Ivar { -// fn borrow(&self) -> &::Target { -// self -// } -// } -// -// impl borrow::BorrowMut<::Target> for Ivar { -// fn borrow_mut(&mut self) -> &mut ::Target { -// self -// } -// } - -impl AsRef<::Target> for Ivar { - fn as_ref(&self) -> &::Target { - // Auto-derefs - self - } -} - -impl AsMut<::Target> for Ivar { - fn as_mut(&mut self) -> &mut ::Target { - // Auto-derefs - self - } -} - -impl Error for Ivar -where - ::Target: Error, -{ - fn source(&self) -> Option<&(dyn Error + 'static)> { - (**self).source() - } -} - -impl io::Read for Ivar -where - ::Target: io::Read, -{ - #[inline] - fn read(&mut self, buf: &mut [u8]) -> io::Result { - (**self).read(buf) - } - - #[inline] - fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { - (**self).read_vectored(bufs) - } - - #[inline] - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - (**self).read_to_end(buf) - } - - #[inline] - fn read_to_string(&mut self, buf: &mut String) -> io::Result { - (**self).read_to_string(buf) - } - - #[inline] - fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { - (**self).read_exact(buf) - } -} - -impl io::Write for Ivar -where - ::Target: io::Write, -{ - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result { - (**self).write(buf) - } - - #[inline] - fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { - (**self).write_vectored(bufs) - } - - #[inline] - fn flush(&mut self) -> io::Result<()> { - (**self).flush() - } - - #[inline] - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - (**self).write_all(buf) - } - - #[inline] - fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { - (**self).write_fmt(fmt) - } -} - -impl io::Seek for Ivar -where - ::Target: io::Seek, -{ - #[inline] - fn seek(&mut self, pos: io::SeekFrom) -> io::Result { - (**self).seek(pos) - } - - #[inline] - fn stream_position(&mut self) -> io::Result { - (**self).stream_position() - } -} - -impl io::BufRead for Ivar -where - ::Target: io::BufRead, -{ - #[inline] - fn fill_buf(&mut self) -> io::Result<&[u8]> { - (**self).fill_buf() - } - - #[inline] - fn consume(&mut self, amt: usize) { - (**self).consume(amt) - } - - #[inline] - fn read_until(&mut self, byte: u8, buf: &mut Vec) -> io::Result { - (**self).read_until(byte, buf) - } - - #[inline] - fn read_line(&mut self, buf: &mut String) -> io::Result { - (**self).read_line(buf) - } -} - -impl Future for Ivar -where - Self: Unpin, - ::Target: Future + Unpin, -{ - type Output = <::Target as Future>::Output; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - <::Target as Future>::poll(Pin::new(&mut *self), cx) - } -} - -// TODO: impl Fn traits, CoerceUnsized, Stream and so on when stabilized diff --git a/crates/objc2/src/declare/mod.rs b/crates/objc2/src/declare/mod.rs index 44c6adefe..d2e3226ff 100644 --- a/crates/objc2/src/declare/mod.rs +++ b/crates/objc2/src/declare/mod.rs @@ -4,12 +4,6 @@ //! variables and methods can then be added before the class is ultimately //! registered. -mod ivar; -mod ivar_bool; -mod ivar_drop; -mod ivar_encode; -mod ivar_forwarding_impls; - use alloc::format; use alloc::string::ToString; use core::mem; @@ -24,11 +18,6 @@ use crate::runtime::{AnyClass, AnyObject, AnyProtocol, Bool, Imp, MethodImplemen use crate::sel; use crate::Message; -pub use ivar::{InnerIvarType, Ivar, IvarType}; -pub use ivar_bool::IvarBool; -pub use ivar_drop::IvarDrop; -pub use ivar_encode::IvarEncode; - fn method_type_encoding(ret: &Encoding, args: &[Encoding]) -> CString { // First two arguments are always self and the selector let mut types = format!("{ret}{}{}", <*mut AnyObject>::ENCODING, Sel::ENCODING); @@ -399,6 +388,10 @@ impl ClassBuilder { unsafe { self.add_ivar_inner::(name, &T::ENCODING) } } + pub(crate) unsafe fn add_ivar_inner(&mut self, name: &str, encoding: &Encoding) { + unsafe { self.add_ivar_inner_mono(name, mem::size_of::(), T::LOG2_ALIGNMENT, encoding) } + } + // Monomorphized version unsafe fn add_ivar_inner_mono( &mut self, @@ -430,21 +423,6 @@ impl ClassBuilder { assert!(success.as_bool(), "failed to add ivar {name}"); } - unsafe fn add_ivar_inner(&mut self, name: &str, encoding: &Encoding) { - unsafe { self.add_ivar_inner_mono(name, mem::size_of::(), T::LOG2_ALIGNMENT, encoding) } - } - - /// Adds an instance variable from an [`IvarType`]. - /// - /// - /// # Panics - /// - /// Same as [`ClassBuilder::add_ivar`]. - pub fn add_static_ivar(&mut self) { - // SAFETY: The encoding is correct - unsafe { self.add_ivar_inner::(T::NAME, &T::Type::ENCODING) } - } - /// Adds the given protocol to self. /// /// # Panics @@ -617,7 +595,8 @@ mod tests { use crate::rc::Id; use crate::runtime::{NSObject, NSObjectProtocol}; use crate::{ - declare_class, extern_methods, msg_send, msg_send_id, test_utils, ClassType, ProtocolType, + declare_class, extern_methods, msg_send, msg_send_id, test_utils, ClassType, DeclaredClass, + ProtocolType, }; #[test] @@ -905,6 +884,8 @@ mod tests { type Mutability = Immutable; const NAME: &'static str = "TestInheritedNSObjectMethodsWork"; } + + impl DeclaredClass for Custom {} ); extern_methods!( @@ -923,7 +904,7 @@ mod tests { // description let expected = - format!("Custom {{ __superclass: ManuallyDrop {{ value: }} }}"); + format!("Custom {{ __superclass: ManuallyDrop {{ value: }}, __ivars: PhantomData<()> }}"); assert_eq!(format!("{obj1:?}"), expected); // hash diff --git a/crates/objc2/src/lib.rs b/crates/objc2/src/lib.rs index 1dbaeb38e..c6cec5447 100644 --- a/crates/objc2/src/lib.rs +++ b/crates/objc2/src/lib.rs @@ -190,7 +190,7 @@ pub use objc_sys as ffi; #[doc(no_inline)] pub use self::encode::{Encode, Encoding, RefEncode}; -pub use self::top_level_traits::{ClassType, Message, ProtocolType}; +pub use self::top_level_traits::{ClassType, DeclaredClass, Message, ProtocolType}; #[cfg(feature = "objc2-proc-macros")] #[doc(hidden)] diff --git a/crates/objc2/src/macros/__field_helpers.rs b/crates/objc2/src/macros/__field_helpers.rs deleted file mode 100644 index b545f17c6..000000000 --- a/crates/objc2/src/macros/__field_helpers.rs +++ /dev/null @@ -1,355 +0,0 @@ -#[doc(hidden)] -#[macro_export] -macro_rules! __emit_struct_and_ivars { - ( - ($(#[$m:meta])*) - ($v:vis) - ($($struct:tt)*) - ($($ivar_helper_module_v:vis mod $ivar_helper_module:ident)?) - ($($fields:tt)*) - ($($parsed_fields:tt)*) - ) => { - $crate::__parse_fields! { - ($($fields)*) - ($($ivar_helper_module_v mod $ivar_helper_module)?) - () () // No parsed ivars - ($($parsed_fields)*) - - ($crate::__emit_struct) - ($(#[$m])*) - ($v) - ($($struct)*) - } - } -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __emit_struct { - ( - ($(#[$m:meta])*) - ($v:vis) - ($($struct:tt)*) - - ($($fields:tt)*) - ) => { - $(#[$m])* - #[repr(C)] - $v struct $($struct)* { - // These are at this point all zero-sized. - $($fields)* - } - } -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __parse_fields { - // Base-case, no ivars, no module - ( - () // No more fields left - () // No module - () () // No ivars - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $out_macro! { - $($macro_args)* - - ($($parsed_fields)*) - } - }; - - // Base-case, has ivars, no module - ( - () // No more fields left - () // No module - ($($ivar_output:tt)+) ($($ivar_type_name:tt)+) - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $crate::__macro_helpers::compile_error!( - "must specify an ivar module when the type has ivars" - ); - - $($ivar_output)+ - - $out_macro! { - $($macro_args)* - - ($($parsed_fields)*) - } - }; - - // Base-case, no ivars, has module - ( - () // No more fields left - ($ivar_helper_module_v:vis mod $ivar_helper_module:ident) - () () // No ivars - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $ivar_helper_module_v mod $ivar_helper_module { - $crate::__macro_helpers::compile_error!( - "no need to specify an ivar module when the type has no ivars" - ); - - pub(super) fn __objc2_declare_ivars( - __objc2_builder: &mut $crate::__macro_helpers::ClassBuilderHelper, - ) {} - } - - $out_macro! { - $($macro_args)* - - ($($parsed_fields)*) - } - }; - - // Base-case, has ivars, has module - ( - () // No more fields left - ($ivar_helper_module_v:vis mod $ivar_helper_module:ident) - ($($ivar_output:tt)+) ($($ivar_type_name:ident)+) - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $ivar_helper_module_v mod $ivar_helper_module { - use super::*; - - $($ivar_output)+ - - pub(super) fn __objc2_declare_ivars( - __objc2_builder: &mut $crate::__macro_helpers::ClassBuilderHelper, - ) { - // Ivars - $( - __objc2_builder.add_static_ivar::<$ivar_type_name>(); - )+ - } - } - - $out_macro! { - $($macro_args)* - - ($($parsed_fields)*) - } - }; - - // PhantomData - ( - ( - $(#[$m:meta])* - $vis:vis $field_name:ident: PhantomData<$ty:ty> - $(, $($rest_fields:tt)*)? - ) - ($($ivar_helper_module_v:vis mod $ivar_helper_module:ident)?) - ($($ivar_output:tt)*) ($($ivar_type_name:ident)*) - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $crate::__parse_fields! { - ($($($rest_fields)*)?) - ($($ivar_helper_module_v mod $ivar_helper_module)?) - ($($ivar_output)*) ($($ivar_type_name)*) - ( - $($parsed_fields)* - - // A user could have defined their own PhantomData-like, type, - // and then tried to use it here, which we would accept, but - // which wouldn't necessarily be zero-sized! - // - // Hence we wrap it in an extra PhantomData, to ensure it is - // (while still not generating "unused imports" for the user). - $(#[$m])* - $vis $field_name: $crate::__macro_helpers::PhantomData>, - ) - - ($out_macro) - $($macro_args)* - } - }; - - // IvarDrop - ( - ( - $(#[$m:meta])* - $vis:vis $field_name:ident: IvarDrop<$ty:ty, $ivar_name:literal> - $(, $($rest_fields:tt)*)? - ) - ($($ivar_helper_module_v:vis mod $ivar_helper_module:ident)?) - ($($ivar_output:tt)*) ($($ivar_type_name:ident)*) - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $crate::__parse_fields! { - ($($($rest_fields)*)?) - ($($ivar_helper_module_v mod $ivar_helper_module)?) - ( - $($ivar_output)* - - #[allow(non_camel_case_types)] - #[allow(unreachable_pub)] - pub struct $field_name { - __priv: (), - } - - // SAFETY: - // - The ivars are in a type used as an Objective-C object. - // - The ivar is added to the class in `__objc2_declare_ivars`. - // - Caller upholds that the ivars are properly initialized. - unsafe impl $crate::declare::IvarType for $field_name { - type Type = IvarDrop<$ty>; - const NAME: &'static $crate::__macro_helpers::str = $ivar_name; - } - ) ($($ivar_type_name)* $field_name) - ( - $($parsed_fields)* - - $(#[$m])* - $vis $field_name: $crate::declare::Ivar<$($ivar_helper_module ::)? $field_name>, - ) - - ($out_macro) - $($macro_args)* - } - }; - - // IvarEncode - ( - ( - $(#[$m:meta])* - $vis:vis $field_name:ident: IvarEncode<$ty:ty, $ivar_name:literal> - $(, $($rest_fields:tt)*)? - ) - ($($ivar_helper_module_v:vis mod $ivar_helper_module:ident)?) - ($($ivar_output:tt)*) ($($ivar_type_name:ident)*) - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $crate::__parse_fields! { - ($($($rest_fields)*)?) - ($($ivar_helper_module_v mod $ivar_helper_module)?) - ( - $($ivar_output)* - - #[allow(non_camel_case_types)] - #[allow(unreachable_pub)] - pub struct $field_name { - __priv: (), - } - - // SAFETY: See above - unsafe impl $crate::declare::IvarType for $field_name { - type Type = IvarEncode<$ty>; - const NAME: &'static $crate::__macro_helpers::str = $ivar_name; - } - ) ($($ivar_type_name)* $field_name) - ( - $($parsed_fields)* - - $(#[$m])* - $vis $field_name: $crate::declare::Ivar<$($ivar_helper_module ::)? $field_name>, - ) - - ($out_macro) - $($macro_args)* - } - }; - - // IvarBool - ( - ( - $(#[$m:meta])* - $vis:vis $field_name:ident: IvarBool<$ivar_name:literal> - $(, $($rest_fields:tt)*)? - ) - ($($ivar_helper_module_v:vis mod $ivar_helper_module:ident)?) - ($($ivar_output:tt)*) ($($ivar_type_name:ident)*) - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $crate::__parse_fields! { - ($($($rest_fields)*)?) - ($($ivar_helper_module_v mod $ivar_helper_module)?) - ( - $($ivar_output)* - - #[allow(non_camel_case_types)] - #[allow(unreachable_pub)] - pub struct $field_name { - __priv: (), - } - - // SAFETY: See above - unsafe impl $crate::declare::IvarType for $field_name { - type Type = IvarBool; - const NAME: &'static $crate::__macro_helpers::str = $ivar_name; - } - ) ($($ivar_type_name)* $field_name) - ( - $($parsed_fields)* - - $(#[$m])* - $vis $field_name: $crate::declare::Ivar<$($ivar_helper_module ::)? $field_name>, - ) - - ($out_macro) - $($macro_args)* - } - }; - - // Invalid type - ( - ( - $(#[$m:meta])* - $vis:vis $field_name:ident: $ty:ty - $(, $($rest_fields:tt)*)? - ) - ($($ivar_helper_module_v:vis mod $ivar_helper_module:ident)?) - ($($ivar_output:tt)*) ($($ivar_type_name:ident)*) - ($($parsed_fields:tt)*) - - ($out_macro:path) - $($macro_args:tt)* - ) => { - $crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!( - "invalid type ", - $crate::__macro_helpers::stringify!($ty), - " in field ", - $crate::__macro_helpers::stringify!($field_name), - ". Type must be either `PhantomData`, `IvarDrop`, `IvarBool` or `IvarEncode`." - )); - - $crate::__parse_fields! { - ($($($rest_fields)*)?) - ($($ivar_helper_module_v mod $ivar_helper_module)?) - ($($ivar_output)*) ($($ivar_type_name)*) - ( - $($parsed_fields)* - - $(#[$m])* - $vis $field_name: $ty, - ) - - ($out_macro) - $($macro_args)* - } - } -} diff --git a/crates/objc2/src/macros/__method_msg_send.rs b/crates/objc2/src/macros/__method_msg_send.rs index fbcccf9b8..3dfe8a238 100644 --- a/crates/objc2/src/macros/__method_msg_send.rs +++ b/crates/objc2/src/macros/__method_msg_send.rs @@ -167,6 +167,7 @@ macro_rules! __method_msg_send_id { $crate::__msg_send_id_helper! { ($receiver) ($($retain_semantics)?) + (MsgSendId) (send_message_id) ($sel) () @@ -255,6 +256,7 @@ macro_rules! __method_msg_send_id { $crate::__msg_send_id_helper! { ($receiver) ($($retain_semantics)?) + (MsgSendId) (send_message_id) ($($sel_parsed)*) ($($arg_parsed)*) @@ -275,6 +277,7 @@ macro_rules! __method_msg_send_id { $crate::__msg_send_id_helper! { ($receiver) ($($retain_semantics)?) + (MsgSendId) // Use error method (send_message_id_error) ($($sel_parsed)* $sel :) diff --git a/crates/objc2/src/macros/__msg_send_parse.rs b/crates/objc2/src/macros/__msg_send_parse.rs index e6ee0c5fa..31f25fce9 100644 --- a/crates/objc2/src/macros/__msg_send_parse.rs +++ b/crates/objc2/src/macros/__msg_send_parse.rs @@ -139,6 +139,7 @@ macro_rules! __comma_between_args { #[macro_export] #[cfg(feature = "unstable-msg-send-always-comma")] macro_rules! __comma_between_args { + // msg_send! ( (send_super_message_static) ($($args:tt)*) @@ -169,12 +170,37 @@ macro_rules! __comma_between_args { ($crate::__macro_helpers::stringify!($obj), $($args)*) } }; - // Catch-all for msg_send_id! + // msg_send_id! ( - ($fn:ident) + (send_super_message_id_static) + ($($args:tt)*) + ($obj:expr) + () + (MsgSendSuperId) + ) => { + $crate::__comma_between_args_inner! { + ("msg_send_id") + ($crate::__macro_helpers::stringify!(super($obj)), $($args)*) + } + }; + ( + (send_super_message_id) + ($($args:tt)*) + ($obj:expr, $superclass:expr) + () + (MsgSendSuperId) + ) => { + $crate::__comma_between_args_inner! { + ("msg_send_id") + ($crate::__macro_helpers::stringify!(super($obj, $superclass)), $($args)*) + } + }; + ( + (send_message_id) ($($args:tt)*) ($obj:expr) () + (MsgSendId) ) => { $crate::__comma_between_args_inner! { ("msg_send_id") diff --git a/crates/objc2/src/macros/declare_class.rs b/crates/objc2/src/macros/declare_class.rs index 2b710477c..abacd8904 100644 --- a/crates/objc2/src/macros/declare_class.rs +++ b/crates/objc2/src/macros/declare_class.rs @@ -16,62 +16,74 @@ /// /// # Specification /// -/// This macro consists of roughly four parts: -/// - The type and ivar definition. +/// This macro consists of the following parts (the first three are required): +/// - The type declaration. /// - The [`ClassType`] implementation. -/// - Any number of method definitions. +/// - The [`DeclaredClass`] implementation. +/// - Any number of inherent implementations. /// - Any number of protocol implementations. /// /// With the syntax generally resembling a combination of that in /// [`extern_class!`] and [`extern_methods!`]. /// /// [`ClassType`]: crate::ClassType +/// [`DeclaredClass`]: crate::DeclaredClass /// [`extern_class!`]: crate::extern_class /// [`extern_methods!`]: crate::extern_methods /// /// -/// ## Ivar definition +/// ## Type declaration /// -/// The type definition works a lot like [`extern_class!`] (including the -/// allowed attributes), with the added capability that struct fields are -/// automatically defined as custom instance variables, which are then -/// accessible on instances of the class. (E.g. you can use `self.my_ivar` as -/// if the class was a normal Rust struct). +/// The type declaration works a lot like in [`extern_class!`], an opaque +/// struct is created and a lot of traits is implemented for that struct. /// -/// The instance variables are specified as such: -/// - [`IvarEncode`](crate::declare::IvarEncode) -/// - [`IvarBool<"my_crate_ivar">`](crate::declare::IvarBool) -/// - [`IvarDrop`](crate::declare::IvarDrop) +/// You are allowed to add most common attributes to the declaration, +/// including `#[cfg(...)]` and doc comments. ABI-modifying attributes like +/// `#[repr(...)]` are not allowed. /// -/// This is special syntax that will be used to generate helper types that -/// implement [`declare::IvarType`], which is then used inside the new struct. +/// `#[derive(...)]` attributes are allowed, but heavily discouraged, as they +/// are likely to not work as you'd expect them to. This is being worked on in +/// [#267]. /// -/// Instance variable names must be unique, and must not conflict with any -/// superclass' instance variables - this means is is good practice to name -/// them with a prefix of your crate name, or similar. +/// If the type implements [`Drop`], the macro will generate a `dealloc` +/// method for you, which will call `drop` automatically. /// -/// [`declare::IvarType`]: crate::declare::IvarType +/// [#267]: https://github.com/madsmtm/objc2/issues/267 /// /// /// ## `ClassType` implementation /// -/// This also resembles that in [`extern_class!`], except that +/// This also resembles the syntax in [`extern_class!`], except that /// [`ClassType::NAME`] must be specified, and it must be unique across the -/// entire application. Good practice here is to include your crate name in -/// the prefix. +/// entire application. +/// +/// If you're developing a library, good practice here would be to include +/// your crate name in the prefix (something like `"MyLibrary_MyClass"`). /// /// The class is guaranteed to have been created and registered with the /// Objective-C runtime after the [`ClassType::class`] function has been /// called. /// -/// The macro will generate a `dealloc` method for you, which will call any -/// [`Drop`] impl you may have defined on the type. -/// /// [`ClassType::NAME`]: crate::ClassType::NAME /// [`ClassType::class`]: crate::ClassType::class /// /// -/// ## Method definitions +/// ## `DeclaredClass` implementation +/// +/// The syntax here is as if you were implementing the trait yourself. +/// +/// You may optionally specify the associated type [`Ivars`]; this is the +/// intended way to specify the data your class stores. If you don't specify +/// any ivars, the macro will default to [`()`][unit]. +/// +/// Beware that if you want to use the class' inherited initializers (such as +/// `init`), you must override the subclass' designated initializers, and +/// initialize your ivars properly in there. +/// +/// [`Ivars`]: crate::DeclaredClass::Ivars +/// +/// +/// ## Inherent method definitions /// /// Within the `impl` block you can define two types of functions; /// ["associated functions"] and ["methods"]. These are then mapped to the @@ -142,12 +154,12 @@ /// The implemented `ClassType::class` method may panic in a few cases, such /// as if: /// - A class with the specified name already exists. -/// - One of the class' instance variables already exist on a superclass. /// - Debug assertions are enabled, and an overriden method's signature is not /// equal to the one on the superclass. /// - The `verify` feature and debug assertions are enabled, and the required /// protocol methods are not implemented. -/// - And possibly more similar cases. +/// +/// And possibly more similar cases. /// /// /// # Safety @@ -155,12 +167,16 @@ /// Using this macro requires writing a few `unsafe` markers: /// /// `unsafe impl ClassType for T` has the following safety requirements: -/// - Any invariants that the overridden class [`ClassType::Super`] may have -/// must be upheld. +/// - Any invariants that the superclass [`ClassType::Super`] may have must be +/// upheld. /// - [`ClassType::Mutability`] must be correct. -/// - Any instance variables you specify under the struct definition must -/// either be able to be created using [`MaybeUninit::zeroed`], or be -/// properly initialized in an `init` method. +/// - If your type implements `Drop`, the implementation must abide by the +/// following rules: +/// - It must not call any overridden methods. +/// - It must not `retain` the object past the lifetime of the drop. +/// - It must not `retain` in the same scope that `&mut self` is active. +/// - TODO: And probably a few more. [Open an issue] if you would like +/// guidance on whether your implementation is correct. /// /// `unsafe impl T { ... }` asserts that the types match those that are /// expected when the method is invoked from Objective-C. Note that unlike @@ -175,7 +191,7 @@ /// /// [`ClassType::Super`]: crate::ClassType::Super /// [`ClassType::Mutability`]: crate::ClassType::Mutability -/// [`MaybeUninit::zeroed`]: core::mem::MaybeUninit::zeroed +/// [Open an issue]: https://github.com/madsmtm/objc2/issues/new /// /// /// # Examples @@ -189,61 +205,55 @@ /// # use objc2::runtime::{NSObject, NSObjectProtocol, NSZone}; /// # #[cfg(available_in_icrate)] /// use icrate::Foundation::{NSCopying, NSObject, NSObjectProtocol, NSZone}; -/// use objc2::declare::{Ivar, IvarDrop, IvarEncode}; -/// use objc2::rc::Id; +/// use objc2::rc::{Allocated, Id}; /// use objc2::{ -/// declare_class, extern_protocol, msg_send, msg_send_id, mutability, ClassType, ProtocolType, +/// declare_class, extern_protocol, msg_send, msg_send_id, mutability, ClassType, +/// DeclaredClass, ProtocolType, /// }; /// -/// declare_class!( -/// struct MyCustomObject { -/// foo: IvarEncode, -/// pub bar: IvarEncode, -/// object: IvarDrop, "_object">, -/// } +/// #[derive(Clone)] +/// struct Ivars { +/// foo: u8, +/// bar: c_int, +/// object: Id, +/// } /// -/// mod ivars; +/// declare_class!( +/// struct MyCustomObject; /// +/// // SAFETY: +/// // - The superclass NSObject does not have any subclassing requirements. +/// // - Interior mutability is a safe default. +/// // - `MyCustomObject` does not implement `Drop`. /// unsafe impl ClassType for MyCustomObject { /// type Super = NSObject; -/// type Mutability = mutability::Mutable; +/// type Mutability = mutability::InteriorMutable; /// const NAME: &'static str = "MyCustomObject"; /// } /// +/// impl DeclaredClass for MyCustomObject { +/// type Ivars = Ivars; +/// } +/// /// unsafe impl MyCustomObject { -/// #[method(initWithFoo:)] -/// fn init_with(this: &mut Self, foo: u8) -> Option<&mut Self> { -/// let this: Option<&mut Self> = unsafe { -/// msg_send![super(this), init] -/// }; -/// -/// this.map(|this| { -/// // Initialize instance variables -/// -/// // Some types like `u8`, `bool`, `Option>` and -/// // `Option>` are safe to zero-initialize, and we can -/// // write to the variable as normal: -/// *this.foo = foo; -/// *this.bar = 42; -/// -/// // For others like `&u8`, `Box` or `Id`, we have to -/// // initialize them with `Ivar::write`: -/// Ivar::write(&mut this.object, NSObject::new()); -/// -/// // All the instance variables have been initialized; our -/// // initializer is sound -/// this -/// }) +/// #[method_id(initWithFoo:)] +/// fn init_with(this: Allocated, foo: u8) -> Option> { +/// let this = this.set_ivars(Ivars { +/// foo, +/// bar: 42, +/// object: NSObject::new(), +/// }); +/// unsafe { msg_send_id![super(this), init] } /// } /// /// #[method(foo)] /// fn __get_foo(&self) -> u8 { -/// *self.foo +/// self.ivars().foo /// } /// /// #[method_id(object)] /// fn __get_object(&self) -> Id { -/// self.object.clone() +/// self.ivars().object.clone() /// } /// /// #[method(myClassMethod)] @@ -253,9 +263,8 @@ /// # /// # #[method_id(copyWithZone:)] /// # fn copyWithZone(&self, _zone: *const NSZone) -> Id { -/// # let mut obj = Self::new(*self.foo); -/// # *obj.bar = *self.bar; -/// # obj +/// # let new = Self::alloc().set_ivars(self.ivars().clone()); +/// # unsafe { msg_send_id![super(new), init] } /// # } /// } /// @@ -265,9 +274,8 @@ /// unsafe impl NSCopying for MyCustomObject { /// #[method_id(copyWithZone:)] /// fn copyWithZone(&self, _zone: *const NSZone) -> Id { -/// let mut obj = Self::new(*self.foo); -/// *obj.bar = *self.bar; -/// obj +/// let new = Self::alloc().set_ivars(self.ivars().clone()); +/// unsafe { msg_send_id![super(new), init] } /// } /// /// // If we have tried to add other methods here, or had forgotten @@ -296,9 +304,9 @@ /// /// fn main() { /// let obj = MyCustomObject::new(3); -/// assert_eq!(*obj.foo, 3); -/// assert_eq!(*obj.bar, 42); -/// assert!(obj.object.is_kind_of::()); +/// assert_eq!(obj.ivars().foo, 3); +/// assert_eq!(obj.ivars().bar, 42); +/// assert!(obj.ivars().object.is_kind_of::()); /// /// # let obj: Id = unsafe { msg_send_id![&obj, copy] }; /// # #[cfg(available_in_icrate)] @@ -316,22 +324,18 @@ /// ```text /// #import /// -/// @interface MyCustomObject: NSObject { -/// // Public ivar -/// int bar; -/// } -/// +/// @interface MyCustomObject: NSObject /// - (instancetype)initWithFoo:(uint8_t)foo; /// - (uint8_t)foo; /// - (NSObject*)object; /// + (BOOL)myClassMethod; -/// /// @end /// /// /// @implementation MyCustomObject { -/// // Private ivar +/// // Instance variables /// uint8_t foo; +/// int bar; /// NSObject* _Nonnull object; /// } /// @@ -360,9 +364,10 @@ /// // NSCopying /// /// - (id)copyWithZone:(NSZone *)_zone { -/// MyCustomObject* obj = [[MyCustomObject alloc] initWithFoo: self->foo]; -/// obj->bar = self->bar; -/// return obj; +/// MyCustomObject* new = [[MyCustomObject alloc] initWithFoo: self->foo]; +/// new->bar = self->bar; +/// new->obj = self->obj; +/// return new; /// } /// /// @end @@ -371,16 +376,11 @@ #[doc(alias = "@implementation")] #[macro_export] macro_rules! declare_class { - // With ivar helper { $(#[$m:meta])* - $v:vis struct $name:ident { - $($fields:tt)* - } - - $ivar_helper_module_v:vis mod $ivar_helper_module:ident; + $v:vis struct $name:ident; - unsafe impl ClassType for $for:ty { + unsafe impl ClassType for $for_class:ty { $(#[inherits($($inheritance_rest:ty),+)])? type Super = $superclass:ty; @@ -389,238 +389,109 @@ macro_rules! declare_class { const NAME: &'static str = $name_const:expr; } - $($impls:tt)* - } => { - $crate::__emit_struct_and_ivars! { - ($(#[$m])*) - ($v) - ($name) - ($ivar_helper_module_v mod $ivar_helper_module) - ($($fields)*) - ( - // Superclasses are deallocated by calling `[super dealloc]`. - __superclass: $crate::__macro_helpers::ManuallyDrop<$superclass>, - ) - } - - $crate::__declare_class_inner! { - ($ivar_helper_module) - - unsafe impl ClassType for $for { - $(#[inherits($($inheritance_rest),+)])? - type Super = $superclass; - - type Mutability = $mutability; - - const NAME: &'static str = $name_const; - } - - $($impls)* - } - }; - - // No ivar helper - { - $(#[$m:meta])* - $v:vis struct $name:ident { - $($fields:tt)* - } - - unsafe impl ClassType for $for:ty { - $(#[inherits($($inheritance_rest:ty),+)])? - type Super = $superclass:ty; - - type Mutability = $mutability:ty; - - const NAME: &'static str = $name_const:expr; + impl DeclaredClass for $for_declared:ty { + $(type Ivars = $ivars:ty;)? } $($impls:tt)* } => { - $crate::__emit_struct_and_ivars! { - ($(#[$m])*) - ($v) - ($name) - () - ($($fields)*) - ( - // Superclasses are deallocated by calling `[super dealloc]`. - __superclass: $crate::__macro_helpers::ManuallyDrop<$superclass>, - ) + $(#[$m])* + #[repr(C)] + $v struct $name { + // Superclasses are deallocated by calling `[super dealloc]`. + __superclass: $crate::__macro_helpers::ManuallyDrop<$superclass>, + // Include ivars for proper auto traits. + __ivars: $crate::__macro_helpers::PhantomData<::Ivars>, } - $crate::__declare_class_inner! { - () - - unsafe impl ClassType for $for { - $(#[inherits($($inheritance_rest),+)])? - type Super = $superclass; + $crate::__extern_class_impl_traits! { + // SAFETY: Upheld by caller + unsafe impl () for $for_class { + INHERITS = [$superclass, $($($inheritance_rest,)+)? $crate::runtime::AnyObject]; - type Mutability = $mutability; + fn as_super(&self) { + &*self.__superclass + } - const NAME: &'static str = $name_const; + fn as_super_mut(&mut self) { + &mut *self.__superclass + } } - - $($impls)* } - }; - // Allow declaring class with no instance variables - { - $(#[$m:meta])* - $v:vis struct $name:ident; - - unsafe impl ClassType for $for:ty { - $(#[inherits($($inheritance_rest:ty),+)])? - type Super = $superclass:ty; - - type Mutability = $mutability:ty; - - const NAME: &'static str = $name_const:expr; - } - - $($impls:tt)* - } => { - $crate::__emit_struct_and_ivars! { - ($(#[$m])*) - ($v) - ($name) - () - () - ( - // Superclasses are deallocated by calling `[super dealloc]`. - __superclass: $crate::__macro_helpers::ManuallyDrop<$superclass>, - ) - } + // Anonymous block to hide the shared statics + const _: () = { + static mut __OBJC2_CLASS: $crate::__macro_helpers::MaybeUninit<&'static $crate::runtime::AnyClass> = $crate::__macro_helpers::MaybeUninit::uninit(); + static mut __OBJC2_IVAR_OFFSET: $crate::__macro_helpers::MaybeUninit<$crate::__macro_helpers::isize> = $crate::__macro_helpers::MaybeUninit::uninit(); + static mut __OBJC2_DROP_FLAG_OFFSET: $crate::__macro_helpers::MaybeUninit<$crate::__macro_helpers::isize> = $crate::__macro_helpers::MaybeUninit::uninit(); - $crate::__declare_class_inner! { - () - - unsafe impl ClassType for $for { - $(#[inherits($($inheritance_rest),+)])? + // Creation + unsafe impl ClassType for $for_class { type Super = $superclass; - type Mutability = $mutability; + const NAME: &'static $crate::__macro_helpers::str = $name_const; - const NAME: &'static str = $name_const; - } + fn class() -> &'static $crate::runtime::AnyClass { + $crate::__macro_helpers::assert_mutability_matches_superclass_mutability::(); - $($impls)* - } - }; -} + // TODO: Use `std::sync::OnceLock` + static REGISTER_CLASS: $crate::__macro_helpers::Once = $crate::__macro_helpers::Once::new(); -#[doc(hidden)] -#[macro_export] -macro_rules! __declare_class_inner { - { - ($($ivar_helper_module:ident)?) + REGISTER_CLASS.call_once(|| { + let mut __objc2_builder = $crate::__macro_helpers::ClassBuilderHelper::::new(); - unsafe impl ClassType for $for:ty { - $(#[inherits($($inheritance_rest:ty),+)])? - type Super = $superclass:ty; + // Implement protocols and methods + $crate::__declare_class_register_impls! { + (__objc2_builder) + $($impls)* + } - type Mutability = $mutability:ty; + let (__objc2_cls, __objc2_ivar_offset, __objc2_drop_flag_offset) = __objc2_builder.register(); - const NAME: &'static str = $name_const:expr; - } + // SAFETY: Modification is ensured by `Once` to happen + // before any access to the variables. + unsafe { + __OBJC2_CLASS.write(__objc2_cls); + __OBJC2_IVAR_OFFSET.write(__objc2_ivar_offset); + __OBJC2_DROP_FLAG_OFFSET.write(__objc2_drop_flag_offset); + } + }); - $($impls:tt)* - } => { - $crate::__extern_class_impl_traits! { - // SAFETY: Upheld by caller - unsafe impl () for $for { - INHERITS = [$superclass, $($($inheritance_rest,)+)? $crate::runtime::AnyObject]; + // SAFETY: We just registered the class, so is now available + unsafe { __OBJC2_CLASS.assume_init() } + } - fn as_super(&self) { + #[inline] + fn as_super(&self) -> &Self::Super { &*self.__superclass } - fn as_super_mut(&mut self) { + #[inline] + fn as_super_mut(&mut self) -> &mut Self::Super { &mut *self.__superclass } } - } - // Creation - unsafe impl ClassType for $for { - type Super = $superclass; - type Mutability = $mutability; - const NAME: &'static $crate::__macro_helpers::str = $name_const; - - fn class() -> &'static $crate::runtime::AnyClass { - $crate::__macro_helpers::assert_mutability_matches_superclass_mutability::(); - - // TODO: Use `core::cell::LazyCell` - static REGISTER_CLASS: $crate::__macro_helpers::Once = $crate::__macro_helpers::Once::new(); - - REGISTER_CLASS.call_once(|| { - let mut __objc2_builder = $crate::__macro_helpers::ClassBuilderHelper::::new(); - - $($ivar_helper_module::__objc2_declare_ivars(&mut __objc2_builder);)? - - // See the following links for more details: - // - - // - - // - - unsafe extern "C" fn __objc2_dealloc(__objc2_self: *mut $for, __objc2_cmd: $crate::runtime::Sel) { - // SAFETY: Ivars are explicitly designed to always - // be valid to drop, and since this is the - // `dealloc` method, we know the ivars are never - // going to be touched again. - // - // This also runs any `Drop` impl that the type may - // have. - unsafe { $crate::__macro_helpers::drop_in_place(__objc2_self) }; - - // The superclass' "marker" that this stores is - // wrapped in `ManuallyDrop`, instead we drop it by - // calling the superclass' `dealloc` method. - // - // Note: ARC does this automatically, which means - // most Objective-C code in the wild don't contain - // this; but we _are_ ARC, so we must do this. - unsafe { - $crate::__macro_helpers::MsgSend::send_super_message_static( - __objc2_self, - __objc2_cmd, // Reuse the selector - (), // No arguments - ) - } - } + impl DeclaredClass for $for_declared { + type Ivars = $crate::__select_ivars!($($ivars)?); - if $crate::__macro_helpers::needs_drop::() { - unsafe { - __objc2_builder.add_method( - $crate::sel!(dealloc), - __objc2_dealloc as unsafe extern "C" fn(_, _), - ); - } - } - - // Implement protocols and methods - $crate::__declare_class_register_impls! { - (__objc2_builder) - $($impls)* - } - - let _cls = __objc2_builder.register(); - }); - - // We just registered the class, so it should be available - $crate::runtime::AnyClass::get(::NAME).unwrap() - } + #[inline] + fn __ivars_offset() -> $crate::__macro_helpers::isize { + // SAFETY: Accessing the offset is guaranteed to only be + // done after the class has been initialized. + unsafe { __OBJC2_IVAR_OFFSET.assume_init() } + } - #[inline] - fn as_super(&self) -> &Self::Super { - &*self.__superclass - } + #[inline] + fn __drop_flag_offset() -> $crate::__macro_helpers::isize { + // SAFETY: Same as above. + unsafe { __OBJC2_DROP_FLAG_OFFSET.assume_init() } + } - #[inline] - fn as_super_mut(&mut self) -> &mut Self::Super { - &mut *self.__superclass + // SAFETY: The offsets are implemented correctly + const __UNSAFE_OFFSETS_CORRECT: () = (); } - } + }; // Methods $crate::__declare_class_output_impls! { @@ -640,6 +511,18 @@ macro_rules! __select_name { }; } +#[doc(hidden)] +#[macro_export] +macro_rules! __select_ivars { + ($ivars:ty) => { + $ivars + }; + () => { + // Default ivars to unit + () + }; +} + #[doc(hidden)] #[macro_export] macro_rules! __declare_class_output_impls { @@ -1106,6 +989,8 @@ macro_rules! __declare_class_method_out_inner { $($params_prefix)* $($params_converted)* ) -> $crate::__macro_helpers::IdReturnValue { + // TODO: Somehow tell the compiler that `this: Allocated` is non-null. + $($body_prefix)* let __objc2_result = $body; diff --git a/crates/objc2/src/macros/extern_class.rs b/crates/objc2/src/macros/extern_class.rs index 1907a9d2e..93edafd1e 100644 --- a/crates/objc2/src/macros/extern_class.rs +++ b/crates/objc2/src/macros/extern_class.rs @@ -28,8 +28,8 @@ /// - [`Borrow<$inheritance_chain>`][core::borrow::Borrow] /// - [`BorrowMut<$inheritance_chain>`][core::borrow::BorrowMut] /// -/// The macro allows specifying fields on the struct, but _only_ zero-sized -/// types like [`PhantomData`] and [`declare::Ivar`] are allowed here. +/// The macro allows specifying zero-sized fields like [`PhantomData`] on the +/// struct. /// /// You can add most attributes to the class, including `#[cfg(...)]`, /// `#[derive(...)]` and doc comments (but not ABI-modifying attributes like @@ -37,7 +37,6 @@ /// /// [rustfmt-macros]: https://github.com/rust-lang/rustfmt/discussions/5437 /// [`PhantomData`]: core::marker::PhantomData -/// [`declare::Ivar`]: crate::declare::Ivar /// /// /// ## `ClassType` implementation diff --git a/crates/objc2/src/macros/extern_methods.rs b/crates/objc2/src/macros/extern_methods.rs index 3fe32b354..ae4f2c5c9 100644 --- a/crates/objc2/src/macros/extern_methods.rs +++ b/crates/objc2/src/macros/extern_methods.rs @@ -69,7 +69,7 @@ /// use objc2::ffi::NSUInteger; /// use objc2::rc::{Allocated, Id}; /// use objc2::runtime::NSObject; -/// use objc2::{declare_class, extern_methods, mutability, ClassType}; +/// use objc2::{declare_class, extern_methods, mutability, ClassType, DeclaredClass}; /// /// // Shim /// type NSError = NSObject; @@ -77,12 +77,18 @@ /// declare_class!( /// pub struct MyObject; /// +/// // SAFETY: +/// // - The superclass NSObject does not have any subclassing requirements. +/// // - Interior mutability is a safe default. +/// // - `MyObject` does not implement `Drop`. /// unsafe impl ClassType for MyObject { /// type Super = NSObject; -/// type Mutability = mutability::Immutable; +/// type Mutability = mutability::InteriorMutable; /// const NAME: &'static str = "MyObject"; /// } /// +/// impl DeclaredClass for MyObject {} +/// /// unsafe impl MyObject { /// // ... Assume we've implemented all the methods used below /// } @@ -123,7 +129,7 @@ /// # use objc2::ffi::NSUInteger; /// # use objc2::rc::{Allocated, Id}; /// # use objc2::runtime::NSObject; -/// # use objc2::{declare_class, extern_methods, mutability, ClassType}; +/// # use objc2::{declare_class, extern_methods, mutability, ClassType, DeclaredClass}; /// # /// # // Shim /// # type NSError = NSObject; @@ -137,6 +143,8 @@ /// # const NAME: &'static str = "MyObject2"; /// # } /// # +/// # impl DeclaredClass for MyObject {} +/// # /// # unsafe impl MyObject { /// # // ... Assume we've implemented all the methods used below /// # } diff --git a/crates/objc2/src/macros/mod.rs b/crates/objc2/src/macros/mod.rs index da02ac8e2..b82a19052 100644 --- a/crates/objc2/src/macros/mod.rs +++ b/crates/objc2/src/macros/mod.rs @@ -1,5 +1,4 @@ mod __attribute_helpers; -mod __field_helpers; mod __method_msg_send; mod __msg_send_parse; mod __rewrite_self_param; @@ -872,7 +871,7 @@ macro_rules! __class_inner { /// use objc2::msg_send; /// # /// # use objc2::runtime::NSObject; -/// # use objc2::{declare_class, mutability, ClassType}; +/// # use objc2::{declare_class, mutability, ClassType, DeclaredClass}; /// # /// # declare_class!( /// # struct MyObject; @@ -882,6 +881,8 @@ macro_rules! __class_inner { /// # type Mutability = mutability::InteriorMutable; /// # const NAME: &'static str = "MyObject"; /// # } +/// # +/// # impl DeclaredClass for MyObject {} /// # ); /// /// let obj: &MyObject; // Some object that implements ClassType @@ -1084,7 +1085,10 @@ macro_rules! msg_send_bool { /// type is a generic `Allocated`. /// /// - The `init` family: The receiver must be `Allocated` as returned from -/// `alloc`. The receiver is consumed, and a the now-initialized `Id` or +/// `alloc`, or if sending messages to the superclass, it must be +/// `PartialInit`. +/// +/// The receiver is consumed, and a the now-initialized `Id` or /// `Option>` (with the same `T`) is returned. /// /// - The `copy` family: The receiver may be anything that implements @@ -1102,17 +1106,16 @@ macro_rules! msg_send_bool { /// See [the clang documentation][arc-retainable] for the precise /// specification of Objective-C's ownership rules. /// -/// As you may have noticed, the return type is always either `Id / Allocated` -/// or `Option`. Internally, the return type is always -/// `Option` (for example: almost all `new` methods can fail -/// if the allocation failed), but for convenience, if the return type is -/// `Id / Allocated` this macro will automatically unwrap the object, or panic -/// with an error message if it couldn't be retrieved. +/// As you may have noticed, the return type is usually either `Id` or +/// `Option`. Internally, the return type is always `Option` (for +/// example: almost all `new` methods can fail if the allocation failed), but +/// for convenience, if the return type is `Id`, this macro will +/// automatically unwrap the object, or panic with an error message if it +/// couldn't be retrieved. /// -/// Though as a special case, if the last argument is the marker `_`, the -/// macro will return a `Result, Id>`, see below. +/// As a special case, if the last argument is the marker `_`, the macro will +/// return a `Result, Id>`, see below. /// -/// This macro doesn't support super methods yet, see [#173]. /// The `retain`, `release` and `autorelease` selectors are not supported, use /// [`Id::retain`], [`Id::drop`] and [`Id::autorelease`] for that. /// @@ -1120,7 +1123,6 @@ macro_rules! msg_send_bool { /// [`MessageReceiver`]: crate::runtime::MessageReceiver /// [`Id::retain_autoreleased`]: crate::rc::Id::retain_autoreleased /// [arc-retainable]: https://clang.llvm.org/docs/AutomaticReferenceCounting.html#retainable-object-pointers-as-operands-and-arguments -/// [#173]: https://github.com/madsmtm/objc2/pull/173 /// [`Id::retain`]: crate::rc::Id::retain /// [`Id::drop`]: crate::rc::Id::drop /// [`Id::autorelease`]: crate::rc::Id::autorelease @@ -1187,6 +1189,34 @@ macro_rules! msg_send_bool { /// ``` #[macro_export] macro_rules! msg_send_id { + [super($obj:expr), $($selector_and_arguments:tt)+] => { + $crate::__msg_send_parse! { + (send_super_message_id_static_error) + () + () + ($($selector_and_arguments)+) + (send_super_message_id_static) + + ($crate::__msg_send_id_helper) + ($obj) + () // No retain semantics + (MsgSendSuperId) + } + }; + [super($obj:expr, $superclass:expr), $($selector_and_arguments:tt)+] => { + $crate::__msg_send_parse! { + (send_super_message_id_error) + () + () + ($($selector_and_arguments)+) + (send_super_message_id) + + ($crate::__msg_send_id_helper) + ($obj, $superclass) + () // No retain semantics + (MsgSendSuperId) + } + }; [$obj:expr, new $(,)?] => ({ let result; result = <$crate::__macro_helpers::New as $crate::__macro_helpers::MsgSendId<_, _>>::send_message_id( @@ -1221,6 +1251,7 @@ macro_rules! msg_send_id { ($crate::__msg_send_id_helper) ($obj) () // No retain semantics + (MsgSendId) } }; } @@ -1230,8 +1261,9 @@ macro_rules! msg_send_id { #[macro_export] macro_rules! __msg_send_id_helper { { - ($obj:expr) + ($($fn_args:tt)+) ($($retain_semantics:ident)?) + ($trait:ident) ($fn:ident) (retain) () @@ -1241,8 +1273,9 @@ macro_rules! __msg_send_id_helper { ) }}; { - ($obj:expr) + ($($fn_args:tt)+) ($($retain_semantics:ident)?) + ($trait:ident) ($fn:ident) (release) () @@ -1252,8 +1285,9 @@ macro_rules! __msg_send_id_helper { ) }}; { - ($obj:expr) + ($($fn_args:tt)+) ($($retain_semantics:ident)?) + ($trait:ident) ($fn:ident) (autorelease) () @@ -1263,8 +1297,9 @@ macro_rules! __msg_send_id_helper { ) }}; { - ($obj:expr) + ($($fn_args:tt)+) ($($retain_semantics:ident)?) + ($trait:ident) ($fn:ident) (dealloc) () @@ -1274,21 +1309,23 @@ macro_rules! __msg_send_id_helper { ) }}; { - ($obj:expr) + ($($fn_args:tt)+) ($retain_semantics:ident) + ($trait:ident) ($fn:ident) ($($selector:tt)*) ($($argument:expr,)*) } => ({ - <$crate::__macro_helpers::$retain_semantics as $crate::__macro_helpers::MsgSendId<_, _>>::$fn( - $obj, + <$crate::__macro_helpers::$retain_semantics as $crate::__macro_helpers::$trait<_, _>>::$fn( + $($fn_args)+, $crate::sel!($($selector)*), ($($argument,)*), ) }); { - ($obj:expr) + ($($fn_args:tt)+) () + ($trait:ident) ($fn:ident) ($($selector:tt)*) ($($argument:expr,)*) @@ -1300,8 +1337,8 @@ macro_rules! __msg_send_id_helper { let result; result = <$crate::__macro_helpers::RetainSemantics<{ $crate::__macro_helpers::retain_semantics(__SELECTOR_DATA) - }> as $crate::__macro_helpers::MsgSendId<_, _>>::$fn( - $obj, + }> as $crate::__macro_helpers::$trait<_, _>>::$fn( + $($fn_args)+, $crate::__sel_inner!( __SELECTOR_DATA, $crate::__hash_idents!($($selector)*) diff --git a/crates/objc2/src/rc/allocated.rs b/crates/objc2/src/rc/allocated.rs index fee507913..a616c1864 100644 --- a/crates/objc2/src/rc/allocated.rs +++ b/crates/objc2/src/rc/allocated.rs @@ -1,10 +1,11 @@ -use core::fmt; use core::marker::PhantomData; use core::mem::ManuallyDrop; +use core::ptr::NonNull; +use core::{fmt, ptr}; -use crate::mutability::IsMutable; +use crate::__macro_helpers::declared_ivars::initialize_ivars; use crate::runtime::{objc_release_fast, AnyObject}; -use crate::Message; +use crate::{DeclaredClass, Message}; /// An Objective-C object that has been allocated, but not initialized. /// @@ -38,7 +39,7 @@ pub struct Allocated { /// The yet-to-be initialized object. /// /// We don't use `Id` here, since that has different auto-trait impls, and - /// requires in it's safety contract that the object is initialized (which + /// requires in its safety contract that the object is initialized (which /// makes it difficult to ensure correctness if such things are split /// across different files). Additionally, we want to have fine control /// over NULL-ness. @@ -48,20 +49,20 @@ pub struct Allocated { /// Necessary for dropck, as with `Id`. p: PhantomData, /// Necessary for restricting auto traits. + /// + /// We _could_ probably implement auto traits `Send` and `Sync` here, but to be + /// safe, we won't for now. p_auto_traits: PhantomData, } -// We _could_ probably implement auto traits `Send` and `Sync` here, but to be -// safe, we won't for now. -// -// Explicitly don't implement `Deref`, `Message` nor `RefEncode`, though! +// Explicitly don't implement `Deref`, `Message` nor `RefEncode`. impl Allocated { /// # Safety /// - /// The caller must ensure the given object has +1 retain count, and that - /// the object behind the pointer has been allocated (but not yet - /// initialized), or that the pointer is NULL. + /// The caller must ensure the pointer is NULL, or that the given object + /// has +1 retain count, and that the object behind the pointer has been + /// allocated (but not yet initialized). #[inline] pub(crate) unsafe fn new(ptr: *mut T) -> Self { Self { @@ -111,10 +112,10 @@ impl Allocated { #[inline] #[allow(unknown_lints)] // New lint below #[allow(clippy::needless_pass_by_ref_mut)] - pub fn as_mut_ptr(this: &mut Self) -> *mut T - where - T: IsMutable, - { + pub fn as_mut_ptr(this: &mut Self) -> *mut T { + // Note: Not bound by `T: IsMutable`, since mutable pointers _can_ be + // safe for non-mutable classes, especially right when they're being + // allocated / initialized. this.ptr as *mut T } @@ -123,6 +124,61 @@ impl Allocated { let this = ManuallyDrop::new(this); this.ptr as *mut T } + + /// Initialize the instance variables for this object. + /// + /// This consumes the allocated instance, and returns the now partially + /// initialized instance instead, which can be further used in + /// [`msg_send_id!`] `super` calls. + /// + /// This works very similarly to [Swift's two-phase initialization + /// scheme][two-phase-init], see that for details. + /// + /// [`msg_send_id!`]: crate::msg_send_id + /// [two-phase-init]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization/#Two-Phase-Initialization + /// + /// + /// # Panics + /// + /// If debug assertions are enabled, this function will panic if the + /// allocated instance is `NULL`, which usually only happens in Out of + /// Memory situations. + /// + /// If debug assertions are disabled, this will return a `NULL` instance + /// and the ivars will be dropped. The NULL instance cannot cause + /// unsoundness and will likely lead to an initialization failure later on + /// instead, but not panicking here is done as a code-size optimization. + // + // Note: This is intentionally _not_ an associated method, even though + // `Allocated` will become `MethodReceiver` in the future. + #[inline] + #[track_caller] + pub fn set_ivars(self, ivars: T::Ivars) -> PartialInit + where + T: DeclaredClass + Sized, + { + if let Some(ptr) = NonNull::new(ManuallyDrop::new(self).ptr as *mut T) { + // SAFETY: The pointer came from `self`, so it is valid. + unsafe { initialize_ivars::(ptr, ivars) }; + + // SAFETY: + // - The pointer came from a `ManuallyDrop>`, which means + // that we've now transfered ownership over +1 retain count. + // - The instance variables for this class have been intialized above. + unsafe { PartialInit::new(ptr.as_ptr()) } + } else if cfg!(debug_assertions) { + panic!("tried to initialize instance variables on a NULL allocated object") + } else { + // Explicitly drop the ivars in this branch + drop(ivars); + + // Create a new NULL PartialInit, which will likely be checked for + // NULL-ness later on, after initialization of it has failed. + // + // SAFETY: The pointer is NULL. + unsafe { PartialInit::new(ptr::null_mut()) } + } + } } impl Drop for Allocated { @@ -146,6 +202,108 @@ impl fmt::Pointer for Allocated { } } +/// An Objective-C object that has been allocated and initialized in the +/// current class, but not yet initialized in the superclass. +/// +/// This is returned by [`Allocated::set_ivars`], and is intended to be used +/// further in [`msg_send_id!`] `super` calls. +/// +/// [`msg_send_id!`]: crate::msg_send_id +/// +/// +/// # Memory layout +/// +/// The memory layout of this struct is NOT currently guaranteed, as we may +/// want to be able to move a drop flag to the stack in the future. +// +// Internally, this is very similar to `Allocated`, except that we have +// different guarantees on the validity of the object. +#[repr(transparent)] +#[derive(Debug)] +pub struct PartialInit { + /// The partially initialized object. + /// + /// Variance is same as `Id`. + ptr: *const T, // Intentionally not NonNull + /// Necessary for dropck, as with `Id`. + p: PhantomData, + /// Restrict auto traits, same as `Allocated`. + p_auto_traits: PhantomData, +} + +impl PartialInit { + /// # Safety + /// + /// The caller must ensure the pointer is NULL, or that the given object + /// is allocated, has +1 retain count, and that the class' instance + /// variables have been initialized. + #[inline] + pub(crate) unsafe fn new(ptr: *mut T) -> Self { + Self { + ptr, + p: PhantomData, + p_auto_traits: PhantomData, + } + } + + /// Returns a raw pointer to the object. + /// + /// The pointer is valid for at least as long as the `PartialInit` is + /// held. + /// + /// See [`PartialInit::as_mut_ptr`] for the mutable equivalent. + /// + /// This is an associated method, and must be called as + /// `PartialInit::as_ptr(obj)`. + #[inline] + pub fn as_ptr(this: &Self) -> *const T { + this.ptr + } + + /// Returns a raw mutable pointer to the object. + /// + /// The pointer is valid for at least as long as the `PartialInit` is + /// held. + /// + /// See [`PartialInit::as_ptr`] for the immutable equivalent. + /// + /// This is an associated method, and must be called as + /// `PartialInit::as_mut_ptr(obj)`. + #[inline] + #[allow(unknown_lints)] // New lint below + #[allow(clippy::needless_pass_by_ref_mut)] + pub fn as_mut_ptr(this: &mut Self) -> *mut T { + this.ptr as *mut T + } + + #[inline] + pub(crate) fn into_ptr(this: Self) -> *mut T { + let this = ManuallyDrop::new(this); + this.ptr as *mut T + } +} + +impl Drop for PartialInit { + #[inline] + fn drop(&mut self) { + // SAFETY: Partially initialized objects can always safely be + // released, since destructors are written to take into account that + // the object may not have been fully initialized. + // + // This is also safe in the case where the object is NULL, + // since `objc_release` allows NULL pointers. + // + // Rest is same as `Id`. + unsafe { objc_release_fast(self.ptr as *mut _) }; + } +} + +impl fmt::Pointer for PartialInit { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.ptr, f) + } +} + #[cfg(test)] mod tests { use core::panic::{RefUnwindSafe, UnwindSafe}; @@ -153,11 +311,13 @@ mod tests { use static_assertions::assert_not_impl_any; use super::*; + use crate::rc::__RcTestObject; use crate::runtime::NSObject; #[test] fn auto_traits() { assert_not_impl_any!(Allocated<()>: Send, Sync, UnwindSafe, RefUnwindSafe, Unpin); + assert_not_impl_any!(PartialInit<()>: Send, Sync, UnwindSafe, RefUnwindSafe, Unpin); } #[repr(C)] @@ -168,7 +328,26 @@ mod tests { /// Test that `Allocated` is covariant over `T`. #[allow(unused)] - fn assert_variance<'b>(obj: Allocated>) -> Allocated> { + fn assert_allocated_variance<'b>(obj: Allocated>) -> Allocated> { obj } + + /// Test that `PartialInit` is covariant over `T`. + #[allow(unused)] + fn assert_partialinit_variance<'b>( + obj: PartialInit>, + ) -> PartialInit> { + obj + } + + #[test] + #[cfg_attr( + debug_assertions, + should_panic = "tried to initialize instance variables on a NULL allocated object" + )] + fn test_set_ivars_null() { + // SAFETY: The pointer is NULL + let obj: Allocated<__RcTestObject> = unsafe { Allocated::new(ptr::null_mut()) }; + let _ = obj.set_ivars(()); + } } diff --git a/crates/objc2/src/rc/id.rs b/crates/objc2/src/rc/id.rs index 7398c9c2d..3714462de 100644 --- a/crates/objc2/src/rc/id.rs +++ b/crates/objc2/src/rc/id.rs @@ -837,7 +837,7 @@ mod tests { use crate::mutability::{Immutable, Mutable}; use crate::rc::{__RcTestObject, __ThreadTestData, autoreleasepool}; use crate::runtime::{AnyObject, NSObject}; - use crate::{declare_class, msg_send}; + use crate::{declare_class, msg_send, DeclaredClass}; #[test] fn auto_traits() { @@ -851,6 +851,8 @@ mod tests { type Mutability = $mutability; const NAME: &'static str = concat!(stringify!($name), "Test"); } + + impl DeclaredClass for $name {} ); }; } @@ -906,7 +908,7 @@ mod tests { drop(obj); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } @@ -932,7 +934,7 @@ mod tests { expected.assert_current(); }); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } @@ -970,7 +972,7 @@ mod tests { drop(cloned); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } diff --git a/crates/objc2/src/rc/id_traits.rs b/crates/objc2/src/rc/id_traits.rs index 4ab267273..2bef09a79 100644 --- a/crates/objc2/src/rc/id_traits.rs +++ b/crates/objc2/src/rc/id_traits.rs @@ -130,7 +130,7 @@ mod tests { use super::*; use crate::mutability::Mutable; use crate::runtime::NSObject; - use crate::{declare_class, msg_send_id, ClassType}; + use crate::{declare_class, msg_send_id, ClassType, DeclaredClass}; declare_class!( #[derive(PartialEq, Eq, Hash, Debug)] @@ -141,6 +141,8 @@ mod tests { type Mutability = Mutable; const NAME: &'static str = "MyCustomCollection"; } + + impl DeclaredClass for Collection {} ); impl DefaultId for Collection { diff --git a/crates/objc2/src/rc/mod.rs b/crates/objc2/src/rc/mod.rs index 4c6dc0953..968707987 100644 --- a/crates/objc2/src/rc/mod.rs +++ b/crates/objc2/src/rc/mod.rs @@ -56,7 +56,7 @@ mod id_traits; mod test_object; mod weak_id; -pub use self::allocated::Allocated; +pub use self::allocated::{Allocated, PartialInit}; pub use self::autorelease::{ autoreleasepool, autoreleasepool_leaking, AutoreleasePool, AutoreleaseSafe, }; diff --git a/crates/objc2/src/rc/test_object.rs b/crates/objc2/src/rc/test_object.rs index 202de9997..f86953842 100644 --- a/crates/objc2/src/rc/test_object.rs +++ b/crates/objc2/src/rc/test_object.rs @@ -1,10 +1,10 @@ use core::cell::RefCell; use core::ptr; -use super::{Allocated, Id}; +use super::{Allocated, DefaultId, Id}; use crate::mutability::Immutable; use crate::runtime::{NSObject, NSZone}; -use crate::{declare_class, msg_send, msg_send_id, ClassType}; +use crate::{declare_class, msg_send, msg_send_id, ClassType, DeclaredClass}; // TODO: Put tests that use this in another crate #[derive(Debug, Clone, Default, PartialEq, Eq)] @@ -12,7 +12,7 @@ use crate::{declare_class, msg_send, msg_send_id, ClassType}; #[doc(hidden)] pub struct __ThreadTestData { pub alloc: usize, - pub dealloc: usize, + pub drop: usize, pub init: usize, pub retain: usize, pub copy: usize, @@ -70,6 +70,8 @@ declare_class!( const NAME: &'static str = "__RcTestObject"; } + impl DeclaredClass for __RcTestObject {} + unsafe impl __RcTestObject { #[method_id(newReturningNull)] fn new_returning_null() -> Option> { @@ -106,10 +108,11 @@ declare_class!( ptr::null_mut() } - #[method(init)] - unsafe fn init(this: *mut Self) -> *mut Self { + #[method_id(init)] + unsafe fn init(this: Allocated) -> Id { TEST_DATA.with(|data| data.borrow_mut().init += 1); - unsafe { msg_send![super(this), init] } + let this = this.set_ivars(()); + unsafe { msg_send_id![super(this), init] } } #[method_id(initReturningNull)] @@ -286,7 +289,13 @@ declare_class!( impl Drop for __RcTestObject { fn drop(&mut self) { - TEST_DATA.with(|data| data.borrow_mut().dealloc += 1); + TEST_DATA.with(|data| data.borrow_mut().drop += 1); + } +} + +impl DefaultId for __RcTestObject { + fn default_id() -> Id { + Self::new() } } @@ -311,6 +320,8 @@ declare_class!( type Mutability = Immutable; const NAME: &'static str = "RcTestObjectSubclass"; } + + impl DeclaredClass for RcTestObjectSubclass {} ); #[cfg_attr(not(test), allow(unused))] @@ -357,7 +368,7 @@ mod tests { drop(res); $expected.release += 1; - $expected.dealloc += 1; + $expected.drop += 1; $expected.assert_current(); } } @@ -429,7 +440,7 @@ mod tests { drop(res); $expected.release += 1; - $expected.dealloc += 1; + $expected.drop += 1; $expected.assert_current(); // Errors @@ -449,7 +460,7 @@ mod tests { drop(res); $expected.release += 1; - $expected.dealloc += 1; + $expected.drop += 1; $expected.assert_current(); } } @@ -474,11 +485,11 @@ mod tests { expected.alloc -= 1; expected.release -= 1; - expected.dealloc -= 1; test_error_id!(expected, 0, initAndShouldError, { expected.alloc += 1; expected.release += 1; - expected.dealloc += 1; + // Drop flag ensures newly allocated objects do not drop + // expected.drop += 1; __RcTestObject::alloc() }); } @@ -499,7 +510,8 @@ mod tests { drop(res); expected.release += 1; - expected.dealloc += 1; + // Drop flag ensures uninitialized do not drop + // expected.drop += 1; expected.assert_current(); // Errors @@ -521,7 +533,7 @@ mod tests { drop(res); expected.release += 1; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); } diff --git a/crates/objc2/src/rc/weak_id.rs b/crates/objc2/src/rc/weak_id.rs index 9f13e1211..48bd5f42f 100644 --- a/crates/objc2/src/rc/weak_id.rs +++ b/crates/objc2/src/rc/weak_id.rs @@ -210,7 +210,7 @@ mod tests { drop(obj); drop(strong); expected.release += 2; - expected.dealloc += 1; + expected.drop += 1; expected.assert_current(); if cfg!(not(feature = "gnustep-1-7")) { diff --git a/crates/objc2/src/runtime/bool.rs b/crates/objc2/src/runtime/bool.rs index 74b4bf9c0..e97a3b355 100644 --- a/crates/objc2/src/runtime/bool.rs +++ b/crates/objc2/src/runtime/bool.rs @@ -10,7 +10,9 @@ use crate::ffi; /// soon as possible. /// /// This is FFI-safe and can be used directly with `msg_send!` and `extern` -/// functions. +/// functions as a substitute for `BOOL` in Objective-C. If your Objective-C +/// code uses C99 `_Bool`, you should use a `#[repr(transparent)]` wrapper +/// around `bool` instead. /// /// Note that this is able to contain more states than `bool` on some /// platforms, but these cases should not be relied on! diff --git a/crates/objc2/src/runtime/message_receiver.rs b/crates/objc2/src/runtime/message_receiver.rs index bc1dc6b4e..d2cce6a72 100644 --- a/crates/objc2/src/runtime/message_receiver.rs +++ b/crates/objc2/src/runtime/message_receiver.rs @@ -510,7 +510,7 @@ mod tests { use crate::rc::{Allocated, Id}; use crate::runtime::NSObject; use crate::test_utils; - use crate::{declare_class, msg_send, msg_send_id, ClassType}; + use crate::{declare_class, msg_send, msg_send_id, ClassType, DeclaredClass}; declare_class!( struct MutableObject; @@ -520,6 +520,8 @@ mod tests { type Mutability = mutability::Mutable; const NAME: &'static str = "TestMutableObject"; } + + impl DeclaredClass for MutableObject {} ); #[allow(unused)] diff --git a/crates/objc2/src/runtime/protocol_object.rs b/crates/objc2/src/runtime/protocol_object.rs index ae8c8d085..46ff46c29 100644 --- a/crates/objc2/src/runtime/protocol_object.rs +++ b/crates/objc2/src/runtime/protocol_object.rs @@ -194,7 +194,7 @@ mod tests { use super::*; use crate::mutability::Mutable; use crate::runtime::{NSObject, NSObjectProtocol}; - use crate::{declare_class, extern_methods, extern_protocol, ClassType}; + use crate::{declare_class, extern_methods, extern_protocol, ClassType, DeclaredClass}; extern_protocol!( unsafe trait Foo { @@ -254,6 +254,8 @@ mod tests { const NAME: &'static str = "ProtocolTestsDummyClass"; } + impl DeclaredClass for DummyClass {} + unsafe impl NSObjectProtocol for DummyClass {} ); @@ -350,7 +352,7 @@ mod tests { assert_eq!( format!("{obj:?}"), format!( - "DummyClass {{ __superclass: {:?} }}", + "DummyClass {{ __superclass: {:?}, __ivars: PhantomData<()> }}", ManuallyDrop::new(foobar) ), ); diff --git a/crates/objc2/src/top_level_traits.rs b/crates/objc2/src/top_level_traits.rs index b852fb182..d8ddecb3d 100644 --- a/crates/objc2/src/top_level_traits.rs +++ b/crates/objc2/src/top_level_traits.rs @@ -1,3 +1,6 @@ +use core::ptr::NonNull; + +use crate::__macro_helpers::declared_ivars::get_initialized_ivar_ptr; use crate::encode::RefEncode; use crate::msg_send_id; use crate::mutability::{IsAllocableAnyThread, IsRetainable, Mutability}; @@ -307,6 +310,70 @@ pub unsafe trait ClassType: Message { // TODO: `fn mtm(&self) -> MainThreadMarker where T::Mutability: MainThreadOnly` } +/// Marks types whose implementation is defined in Rust. +/// +/// This is used in [`declare_class!`], and allows access to the instance +/// variables that a given type declares, see that macro for details. +/// +/// [`declare_class!`]: crate::declare_class +// +// Note: We mark this trait as not `unsafe` for better documentation, since +// implementing it inside `declare_class!` is not `unsafe`. +// +// Safety is ensured by `__UNSAFE_OFFSETS_CORRECT`. +pub trait DeclaredClass: ClassType { + /// A type representing the instance variables that this class carries. + type Ivars: Sized; + + // TODO: Add `ivars_ptr(this: NonNull) -> NonNull`? + + /// Get a reference to the instance variable data that this object + /// carries. + #[inline] + #[track_caller] + fn ivars(&self) -> &Self::Ivars + where + Self: Sized, // Required because of MSRV + { + let ptr: NonNull = NonNull::from(self); + // SAFETY: The pointer is valid and initialized. + let ivars = unsafe { get_initialized_ivar_ptr(ptr) }; + // SAFETY: The lifetime of the instance variable is tied to the object. + unsafe { ivars.as_ref() } + } + + /// Get a mutable reference to the instance variable data that this object + /// carries. + #[inline] + #[track_caller] + fn ivars_mut(&mut self) -> &mut Self::Ivars + where + Self: Sized, // Required because of MSRV + { + let ptr: NonNull = NonNull::from(self); + // SAFETY: The pointer is valid and initialized. + let mut ivars = unsafe { get_initialized_ivar_ptr(ptr) }; + // SAFETY: The lifetime of the instance variable is tied to the object. + // + // Mutability is safe since the object itself is mutable. See + // `ClassType::as_super_mut` for why this is safe without + // `Self: IsMutable`. + unsafe { ivars.as_mut() } + } + + #[doc(hidden)] + fn __ivars_offset() -> isize; + + #[doc(hidden)] + fn __drop_flag_offset() -> isize; + + /// # Safety + /// + /// The ivar offset and drop flag offsets must be implemented correctly. + #[doc(hidden)] + const __UNSAFE_OFFSETS_CORRECT: (); +} + /// Marks types that represent specific protocols. /// /// This is the protocol equivalent of [`ClassType`]. diff --git a/crates/objc2/tests/declare_class.rs b/crates/objc2/tests/declare_class.rs index 08a9d0622..c5933d8b2 100644 --- a/crates/objc2/tests/declare_class.rs +++ b/crates/objc2/tests/declare_class.rs @@ -1,17 +1,15 @@ #![deny(deprecated, unreachable_code)] use core::ptr::{self, NonNull}; -use objc2::declare::IvarEncode; use objc2::mutability::Immutable; use objc2::rc::Id; use objc2::runtime::NSObject; -use objc2::{declare_class, extern_methods, sel, ClassType}; +use objc2::{declare_class, extern_methods, sel, ClassType, DeclaredClass}; // Test that adding the `deprecated` attribute does not mean that warnings // when using the method internally are output. declare_class!( - // Also ensure that empty fields still work - struct DeclareClassDepreactedMethod {} + struct DeclareClassDepreactedMethod; unsafe impl ClassType for DeclareClassDepreactedMethod { type Super = NSObject; @@ -19,6 +17,8 @@ declare_class!( const NAME: &'static str = "DeclareClassDepreactedMethod"; } + impl DeclaredClass for DeclareClassDepreactedMethod {} + #[deprecated] unsafe impl DeclareClassDepreactedMethod { #[method(deprecatedOnImpl)] @@ -50,6 +50,8 @@ declare_class!( const NAME: &'static str = "DeclareClassCfg"; } + impl DeclaredClass for DeclareClassCfg {} + unsafe impl DeclareClassCfg { #[cfg(debug_assertions)] #[method(changesOnCfg1)] @@ -192,6 +194,8 @@ declare_class!( const NAME: &'static str = "TestMultipleColonSelector"; } + impl DeclaredClass for TestMultipleColonSelector {} + unsafe impl TestMultipleColonSelector { #[method(test::arg3:)] fn _test_class(arg1: i32, arg2: i32, arg3: i32) -> i32 { @@ -265,6 +269,8 @@ declare_class!( const NAME: &'static str = "DeclareClassAllTheBool"; } + impl DeclaredClass for DeclareClassAllTheBool {} + unsafe impl DeclareClassAllTheBool { #[method(returnsBool)] fn returns_bool() -> bool { @@ -328,6 +334,8 @@ declare_class!( const NAME: &'static str = "DeclareClassUnreachable"; } + impl DeclaredClass for DeclareClassUnreachable {} + // Ensure none of these warn unsafe impl DeclareClassUnreachable { #[method(unreachable)] @@ -367,27 +375,6 @@ fn test_unreachable() { let _ = DeclareClassUnreachable::class(); } -#[test] -#[should_panic = "failed to add ivar _ivar"] -fn test_duplicate_ivar() { - declare_class!( - struct DeclareClassDuplicateIvar { - ivar1: IvarEncode, - ivar2: IvarEncode, - } - - mod ivars; - - unsafe impl ClassType for DeclareClassDuplicateIvar { - type Super = NSObject; - type Mutability = Immutable; - const NAME: &'static str = "DeclareClassDuplicateIvar"; - } - ); - - let _ = DeclareClassDuplicateIvar::class(); -} - declare_class!( #[derive(Debug)] struct OutParam; @@ -398,6 +385,8 @@ declare_class!( const NAME: &'static str = "OutParam"; } + impl DeclaredClass for OutParam {} + unsafe impl OutParam { #[method(unsupported1:)] fn _unsupported1(_param: &mut Id) {} @@ -486,6 +475,8 @@ fn test_pointer_receiver_allowed() { const NAME: &'static str = "PointerReceiver"; } + impl DeclaredClass for PointerReceiver {} + unsafe impl PointerReceiver { #[method(constPtr)] fn const_ptr(_this: *const Self) {} diff --git a/crates/objc2/tests/declare_class_self.rs b/crates/objc2/tests/declare_class_self.rs index 6915e5f0f..6355e8429 100644 --- a/crates/objc2/tests/declare_class_self.rs +++ b/crates/objc2/tests/declare_class_self.rs @@ -3,7 +3,7 @@ //! do it in a context where `Self` works. use objc2::rc::{Allocated, Id}; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; trait GetSameType { type SameType: ?Sized; @@ -37,6 +37,8 @@ declare_class!( const NAME: &'static str = "MyTestObject"; } + impl DeclaredClass for MyTestObject {} + unsafe impl MyTestObject { #[method_id(initWith:)] fn init( diff --git a/crates/objc2/tests/macros_mainthreadmarker.rs b/crates/objc2/tests/macros_mainthreadmarker.rs index dff31e4c4..bf67b8614 100644 --- a/crates/objc2/tests/macros_mainthreadmarker.rs +++ b/crates/objc2/tests/macros_mainthreadmarker.rs @@ -1,6 +1,9 @@ use objc2::rc::Id; use objc2::runtime::{NSObject, NSObjectProtocol}; -use objc2::{declare_class, extern_methods, extern_protocol, mutability, ClassType, ProtocolType}; +use objc2::{ + declare_class, extern_methods, extern_protocol, mutability, ClassType, DeclaredClass, + ProtocolType, +}; extern_protocol!( #[allow(clippy::missing_safety_doc)] @@ -27,6 +30,8 @@ declare_class!( const NAME: &'static str = "MainThreadMarkerTest"; } + impl DeclaredClass for Cls {} + unsafe impl Proto for Cls { #[method(myMethod:)] fn _my_mainthreadonly_method(arg: i32) -> i32 { diff --git a/crates/objc2/tests/no_prelude.rs b/crates/objc2/tests/no_prelude.rs index cf79c10f5..c09ab224d 100644 --- a/crates/objc2/tests/no_prelude.rs +++ b/crates/objc2/tests/no_prelude.rs @@ -9,7 +9,7 @@ extern crate objc2 as new_objc2; -use new_objc2::{ClassType, ProtocolType}; +use new_objc2::{ClassType, DeclaredClass, ProtocolType}; mod core {} mod std {} @@ -82,14 +82,16 @@ type ExactSizeIterator = BogusType; type SliceConcatExt = BogusType; type ToString = BogusType; +type PhantomData = BogusType; + // Test begin below this line -type PhantomData = T; +pub struct MyCustomIvars { + ivars: i32, +} new_objc2::declare_class!( - pub struct CustomObject { - field1: PhantomData, - } + pub struct CustomObject; unsafe impl ClassType for CustomObject { type Super = new_objc2::runtime::NSObject; @@ -97,6 +99,10 @@ new_objc2::declare_class!( const NAME: &'static str = "CustomObject"; } + impl DeclaredClass for CustomObject { + type Ivars = MyCustomIvars; + } + unsafe impl CustomObject { #[method(a)] fn _a() {} diff --git a/crates/objc2/tests/track_caller.rs b/crates/objc2/tests/track_caller.rs index f50b32984..29bc8a47c 100644 --- a/crates/objc2/tests/track_caller.rs +++ b/crates/objc2/tests/track_caller.rs @@ -9,7 +9,7 @@ use std::sync::Mutex; use objc2::encode::Encode; use objc2::rc::{Allocated, Id, __RcTestObject}; use objc2::runtime::NSObject; -use objc2::{class, declare_class, msg_send, msg_send_id, mutability, ClassType}; +use objc2::{class, declare_class, msg_send, msg_send_id, mutability, ClassType, DeclaredClass}; static EXPECTED_MESSAGE: Mutex = Mutex::new(String::new()); static EXPECTED_LINE: Mutex = Mutex::new(0); @@ -202,6 +202,8 @@ declare_class!( const NAME: &'static str = "PanickingClass"; } + impl DeclaredClass for PanickingClass {} + unsafe impl PanickingClass { #[method(panic)] fn _panic() -> *mut Self { diff --git a/crates/objc2/tests/use_macros.rs b/crates/objc2/tests/use_macros.rs index 081b1e9f7..ce2ffe197 100644 --- a/crates/objc2/tests/use_macros.rs +++ b/crates/objc2/tests/use_macros.rs @@ -1,6 +1,6 @@ use objc2::mutability::Immutable; use objc2::runtime::{AnyClass, NSObject}; -use objc2::{class, declare_class, msg_send, sel, ClassType}; +use objc2::{class, declare_class, msg_send, sel, ClassType, DeclaredClass}; declare_class!( pub struct MyObject; @@ -10,6 +10,8 @@ declare_class!( type Mutability = Immutable; const NAME: &'static str = "MyObject"; } + + impl DeclaredClass for MyObject {} ); #[test] diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s index 8e8074c7c..9a27ca44c 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s @@ -11,6 +11,55 @@ SYM(core[CRATE_ID]::ptr::drop_in_place::<::call SYM(core[CRATE_ID]::ptr::drop_in_place::<::call_once<::class::{closure#0}>::{closure#0}>, 0): ret + .p2align 2 +SYM(objc2[CRATE_ID]::__macro_helpers::declared_ivars::dealloc::, 0): + sub sp, sp, #64 + stp x22, x21, [sp, #16] + stp x20, x19, [sp, #32] + stp x29, x30, [sp, #48] + add x29, sp, #48 + mov x19, x1 + mov x20, x0 +Lloh0: + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGE +Lloh1: + ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGEOFF] + ldrb w8, [x0, x8] + cbz w8, LBB3_5 + cmp w8, #255 + b.ne LBB3_3 + bl SYM(::drop, 0) +LBB3_3: +Lloh2: + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE +Lloh3: + ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] + add x8, x20, x8 + ldp x0, x21, [x8] + bl _objc_release + cbz x21, LBB3_5 + mov x0, x21 + bl _objc_release +LBB3_5: +Lloh4: + adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE +Lloh5: + ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] +Lloh6: + ldr x8, [x8] + stp x20, x8, [sp] + mov x0, sp + mov x1, x19 + bl _objc_msgSendSuper + ldp x29, x30, [sp, #48] + ldp x20, x19, [sp, #32] + ldp x22, x21, [sp, #16] + add sp, sp, #64 + ret + .loh AdrpLdr Lloh0, Lloh1 + .loh AdrpLdr Lloh2, Lloh3 + .loh AdrpLdrGotLdr Lloh4, Lloh5, Lloh6 + .p2align 2 SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): sub sp, sp, #64 @@ -21,847 +70,828 @@ SYM(::call_once::<::call_once::<::class::{closure#0}>::{closure#0}, 0): - sub sp, sp, #48 - stp x20, x19, [sp, #16] - stp x29, x30, [sp, #32] - add x29, sp, #32 + sub sp, sp, #96 + stp x20, x19, [sp, #64] + stp x29, x30, [sp, #80] + add x29, sp, #80 ldr x8, [x0] ldrb w9, [x8] strb wzr, [x8] - cbz w9, LBB4_3 -Lloh55: - adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh56: - ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh57: - ldr x2, [x8] -Lloh58: - adrp x0, l_anon.[ID].16@PAGE -Lloh59: - add x0, x0, l_anon.[ID].16@PAGEOFF - mov w1, #9 - bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) - cbz x0, LBB4_4 - str x0, [sp, #8] -Lloh60: - adrp x1, l_anon.[ID].18@PAGE -Lloh61: - add x1, x1, l_anon.[ID].18@PAGEOFF -Lloh62: - adrp x19, l_anon.[ID].4@PAGE -Lloh63: - add x19, x19, l_anon.[ID].4@PAGEOFF - add x0, sp, #8 - mov w2, #4 - mov w3, #8 - mov w4, #3 - mov x5, x19 - bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) -Lloh64: - adrp x1, l_anon.[ID].17@PAGE + cbz w9, LBB5_5 Lloh65: - add x1, x1, l_anon.[ID].17@PAGEOFF - add x0, sp, #8 - mov w2, #11 - mov w3, #8 - mov w4, #3 - mov x5, x19 - bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE Lloh66: - adrp x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGE + ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] Lloh67: - ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGEOFF] + ldr x2, [x8] Lloh68: - ldr x1, [x8] + adrp x0, l_anon.[ID].23@PAGE Lloh69: - adrp x20, l_anon.[ID].3@PAGE + add x0, x0, l_anon.[ID].23@PAGEOFF + mov w1, #9 + bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) + cbz x0, LBB5_6 + str x0, [sp, #24] Lloh70: - add x20, x20, l_anon.[ID].3@PAGEOFF + adrp x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGE Lloh71: - adrp x4, l_anon.[ID].5@PAGE + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGEOFF] Lloh72: - add x4, x4, l_anon.[ID].5@PAGEOFF + ldr x1, [x8] Lloh73: - adrp x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGE + adrp x19, l_anon.[ID].3@PAGE Lloh74: - add x5, x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGEOFF - add x0, sp, #8 - mov x2, x20 - mov x3, #0 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + add x19, x19, l_anon.[ID].3@PAGEOFF Lloh75: - adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE + adrp x4, l_anon.[ID].5@PAGE Lloh76: - ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] + add x4, x4, l_anon.[ID].5@PAGEOFF Lloh77: - ldr x1, [x8] + adrp x5, SYM(objc2[CRATE_ID]::__macro_helpers::declared_ivars::dealloc::, 0)@PAGE Lloh78: - adrp x5, _init_drop_ivars@PAGE -Lloh79: - add x5, x5, _init_drop_ivars@PAGEOFF - add x0, sp, #8 - mov x2, x20 + add x5, x5, SYM(objc2[CRATE_ID]::__macro_helpers::declared_ivars::dealloc::, 0)@PAGEOFF + add x0, sp, #24 + mov x2, x19 mov x3, #0 - mov x4, x19 bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - ldr x0, [sp, #8] - bl SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) - ldp x29, x30, [sp, #32] - ldp x20, x19, [sp, #16] - add sp, sp, #48 - ret -LBB4_3: + ldr x8, [sp, #24] + str x8, [sp, #8] +Lloh79: + adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE Lloh80: - adrp x0, l_anon.[ID].11@PAGE + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] Lloh81: - add x0, x0, l_anon.[ID].11@PAGEOFF + ldr x1, [x8] Lloh82: - adrp x2, l_anon.[ID].13@PAGE + adrp x4, l_anon.[ID].4@PAGE Lloh83: - add x2, x2, l_anon.[ID].13@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) -LBB4_4: + add x4, x4, l_anon.[ID].4@PAGEOFF Lloh84: - adrp x0, l_anon.[ID].16@PAGE + adrp x5, _init_drop_ivars@PAGE Lloh85: - add x0, x0, l_anon.[ID].16@PAGEOFF + add x5, x5, _init_drop_ivars@PAGEOFF + add x0, sp, #8 + mov x2, x19 + mov x3, #0 + bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + ldr x8, [sp, #8] + str x8, [sp, #16] + mov w8, #16 Lloh86: - adrp x2, l_anon.[ID].28@PAGE + adrp x9, l_anon.[ID].15@PAGE Lloh87: - add x2, x2, l_anon.[ID].28@PAGEOFF - mov w1, #9 - bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) - .loh AdrpAdd Lloh58, Lloh59 - .loh AdrpLdrGotLdr Lloh55, Lloh56, Lloh57 - .loh AdrpAdd Lloh78, Lloh79 - .loh AdrpLdrGotLdr Lloh75, Lloh76, Lloh77 - .loh AdrpAdd Lloh73, Lloh74 - .loh AdrpAdd Lloh71, Lloh72 - .loh AdrpAdd Lloh69, Lloh70 - .loh AdrpLdrGotLdr Lloh66, Lloh67, Lloh68 - .loh AdrpAdd Lloh64, Lloh65 - .loh AdrpAdd Lloh62, Lloh63 - .loh AdrpAdd Lloh60, Lloh61 - .loh AdrpAdd Lloh82, Lloh83 - .loh AdrpAdd Lloh80, Lloh81 - .loh AdrpAdd Lloh86, Lloh87 - .loh AdrpAdd Lloh84, Lloh85 - - .p2align 2 -SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): - sub sp, sp, #48 - stp x20, x19, [sp, #16] - stp x29, x30, [sp, #32] - add x29, sp, #32 - ldr x8, [x0] - ldrb w9, [x8] - strb wzr, [x8] - cbz w9, LBB5_3 + add x9, x9, l_anon.[ID].15@PAGEOFF + stp x8, x9, [sp, #32] + mov w8, #27 + strb w8, [sp, #24] Lloh88: - adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE + adrp x20, l_anon.[ID].11@PAGE Lloh89: - ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] + add x20, x20, l_anon.[ID].11@PAGEOFF + add x0, sp, #16 + add x5, sp, #24 + mov x1, x20 + mov w2, #5 + mov w3, #16 + mov w4, #3 + bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) Lloh90: - ldr x2, [x8] + adrp x1, l_anon.[ID].12@PAGE Lloh91: - adrp x0, l_anon.[ID].14@PAGE + add x1, x1, l_anon.[ID].12@PAGEOFF Lloh92: - add x0, x0, l_anon.[ID].14@PAGEOFF - mov w1, #15 - bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) - cbz x0, LBB5_4 - str x0, [sp, #8] + adrp x5, l_anon.[ID].13@PAGE Lloh93: - adrp x1, l_anon.[ID].20@PAGE -Lloh94: - add x1, x1, l_anon.[ID].20@PAGEOFF -Lloh95: - adrp x5, l_anon.[ID].25@PAGE -Lloh96: - add x5, x5, l_anon.[ID].25@PAGEOFF - add x0, sp, #8 - mov w2, #4 + add x5, x5, l_anon.[ID].13@PAGEOFF + add x0, sp, #16 + mov w2, #9 mov w3, #1 mov w4, #0 bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + ldr x0, [sp, #16] + bl SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) + mov x19, x0 + mov x1, x20 + mov w2, #5 + bl SYM(objc2::runtime::AnyClass::instance_variable::GENERATED_ID, 0) + cbz x0, LBB5_7 + bl _ivar_getOffset + mov x20, x0 +Lloh94: + adrp x1, l_anon.[ID].12@PAGE +Lloh95: + add x1, x1, l_anon.[ID].12@PAGEOFF + mov x0, x19 + mov w2, #9 + bl SYM(objc2::runtime::AnyClass::instance_variable::GENERATED_ID, 0) + cbz x0, LBB5_8 + bl _ivar_getOffset +Lloh96: + adrp x8, __MergedGlobals@PAGE+32 + str x19, [x8, __MergedGlobals@PAGEOFF+32] Lloh97: - adrp x1, l_anon.[ID].19@PAGE + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE + str x20, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] Lloh98: - add x1, x1, l_anon.[ID].19@PAGEOFF + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGE + str x0, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGEOFF] + ldp x29, x30, [sp, #80] + ldp x20, x19, [sp, #64] + add sp, sp, #96 + ret +LBB5_5: Lloh99: - adrp x5, l_anon.[ID].26@PAGE + adrp x0, l_anon.[ID].24@PAGE Lloh100: - add x5, x5, l_anon.[ID].26@PAGEOFF - add x0, sp, #8 - mov w2, #4 - mov w3, #4 - mov w4, #2 - bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + add x0, x0, l_anon.[ID].24@PAGEOFF Lloh101: - adrp x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGE + adrp x2, l_anon.[ID].26@PAGE Lloh102: - ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPAGEOFF] + add x2, x2, l_anon.[ID].26@PAGEOFF + mov w1, #43 + bl SYM(core::panicking::panic::GENERATED_ID, 0) +LBB5_6: Lloh103: - ldr x1, [x8] + adrp x0, l_anon.[ID].23@PAGE Lloh104: - adrp x19, l_anon.[ID].3@PAGE + add x0, x0, l_anon.[ID].23@PAGEOFF Lloh105: - add x19, x19, l_anon.[ID].3@PAGEOFF + adrp x2, l_anon.[ID].32@PAGE Lloh106: - adrp x4, l_anon.[ID].5@PAGE + add x2, x2, l_anon.[ID].32@PAGEOFF + mov w1, #9 + bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) +LBB5_7: Lloh107: - add x4, x4, l_anon.[ID].5@PAGEOFF + adrp x0, l_anon.[ID].16@PAGE Lloh108: - adrp x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGE + add x0, x0, l_anon.[ID].16@PAGEOFF Lloh109: - add x5, x5, SYM(::class::{closure#0}::__objc2_dealloc, 0)@PAGEOFF - add x0, sp, #8 - mov x2, x19 - mov x3, #0 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + adrp x2, l_anon.[ID].18@PAGE Lloh110: - adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE + add x2, x2, l_anon.[ID].18@PAGEOFF + mov w1, #59 + bl SYM(core::option::expect_failed::GENERATED_ID, 0) +LBB5_8: Lloh111: - ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] + adrp x0, l_anon.[ID].19@PAGE Lloh112: - ldr x1, [x8] + add x0, x0, l_anon.[ID].19@PAGEOFF Lloh113: - adrp x4, l_anon.[ID].4@PAGE + adrp x2, l_anon.[ID].20@PAGE Lloh114: - add x4, x4, l_anon.[ID].4@PAGEOFF + add x2, x2, l_anon.[ID].20@PAGEOFF + mov w1, #69 + bl SYM(core::option::expect_failed::GENERATED_ID, 0) + .loh AdrpAdd Lloh68, Lloh69 + .loh AdrpLdrGotLdr Lloh65, Lloh66, Lloh67 + .loh AdrpAdd Lloh92, Lloh93 + .loh AdrpAdd Lloh90, Lloh91 + .loh AdrpAdd Lloh88, Lloh89 + .loh AdrpAdd Lloh86, Lloh87 + .loh AdrpAdd Lloh84, Lloh85 + .loh AdrpAdd Lloh82, Lloh83 + .loh AdrpLdrGotLdr Lloh79, Lloh80, Lloh81 + .loh AdrpAdd Lloh77, Lloh78 + .loh AdrpAdd Lloh75, Lloh76 + .loh AdrpAdd Lloh73, Lloh74 + .loh AdrpLdrGotLdr Lloh70, Lloh71, Lloh72 + .loh AdrpAdd Lloh94, Lloh95 + .loh AdrpAdrp Lloh97, Lloh98 + .loh AdrpAdrp Lloh96, Lloh97 + .loh AdrpAdd Lloh101, Lloh102 + .loh AdrpAdd Lloh99, Lloh100 + .loh AdrpAdd Lloh105, Lloh106 + .loh AdrpAdd Lloh103, Lloh104 + .loh AdrpAdd Lloh109, Lloh110 + .loh AdrpAdd Lloh107, Lloh108 + .loh AdrpAdd Lloh113, Lloh114 + .loh AdrpAdd Lloh111, Lloh112 + + .p2align 2 +SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): + sub sp, sp, #96 + stp x20, x19, [sp, #64] + stp x29, x30, [sp, #80] + add x29, sp, #80 + ldr x8, [x0] + ldrb w9, [x8] + strb wzr, [x8] + cbz w9, LBB6_4 Lloh115: - adrp x5, _init_forgetable_ivars@PAGE + adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE Lloh116: - add x5, x5, _init_forgetable_ivars@PAGEOFF - add x0, sp, #8 - mov x2, x19 - mov x3, #0 - bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - ldr x0, [sp, #8] - bl SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) - ldp x29, x30, [sp, #32] - ldp x20, x19, [sp, #16] - add sp, sp, #48 - ret -LBB5_3: + ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] Lloh117: - adrp x0, l_anon.[ID].11@PAGE + ldr x2, [x8] Lloh118: - add x0, x0, l_anon.[ID].11@PAGEOFF + adrp x0, l_anon.[ID].21@PAGE Lloh119: - adrp x2, l_anon.[ID].13@PAGE + add x0, x0, l_anon.[ID].21@PAGEOFF + mov w1, #15 + bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) + cbz x0, LBB6_5 + str x0, [sp, #8] Lloh120: - add x2, x2, l_anon.[ID].13@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) -LBB5_4: + adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE Lloh121: - adrp x0, l_anon.[ID].14@PAGE + ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] Lloh122: - add x0, x0, l_anon.[ID].14@PAGEOFF + ldr x1, [x8] Lloh123: - adrp x2, l_anon.[ID].27@PAGE + adrp x2, l_anon.[ID].3@PAGE Lloh124: - add x2, x2, l_anon.[ID].27@PAGEOFF - mov w1, #15 - bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) - .loh AdrpAdd Lloh91, Lloh92 - .loh AdrpLdrGotLdr Lloh88, Lloh89, Lloh90 - .loh AdrpAdd Lloh115, Lloh116 - .loh AdrpAdd Lloh113, Lloh114 - .loh AdrpLdrGotLdr Lloh110, Lloh111, Lloh112 - .loh AdrpAdd Lloh108, Lloh109 - .loh AdrpAdd Lloh106, Lloh107 - .loh AdrpAdd Lloh104, Lloh105 - .loh AdrpLdrGotLdr Lloh101, Lloh102, Lloh103 - .loh AdrpAdd Lloh99, Lloh100 - .loh AdrpAdd Lloh97, Lloh98 - .loh AdrpAdd Lloh95, Lloh96 - .loh AdrpAdd Lloh93, Lloh94 - .loh AdrpAdd Lloh119, Lloh120 - .loh AdrpAdd Lloh117, Lloh118 - .loh AdrpAdd Lloh123, Lloh124 - .loh AdrpAdd Lloh121, Lloh122 - - .p2align 2 -SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 - ldr x8, [x0] - str x8, [sp, #8] - add x0, sp, #8 - bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - ldp x29, x30, [sp, #16] - add sp, sp, #32 - ret - - .p2align 2 -SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 - ldr x8, [x0] - str x8, [sp, #8] - add x0, sp, #8 - bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - ldp x29, x30, [sp, #16] - add sp, sp, #32 - ret - - .p2align 2 -SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 - ldr x8, [x0] - str x8, [sp, #8] - add x0, sp, #8 - bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) - ldp x29, x30, [sp, #16] - add sp, sp, #32 - ret - - .globl _access_forgetable_ivars_class - .p2align 2 -_access_forgetable_ivars_class: - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 + add x2, x2, l_anon.[ID].3@PAGEOFF Lloh125: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE + adrp x4, l_anon.[ID].4@PAGE Lloh126: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF - ldapr x8, [x8] - cmp x8, #3 - b.ne LBB9_3 + add x4, x4, l_anon.[ID].4@PAGEOFF Lloh127: - adrp x0, l_anon.[ID].14@PAGE + adrp x5, _init_forgetable_ivars@PAGE Lloh128: - add x0, x0, l_anon.[ID].14@PAGEOFF - mov w1, #15 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB9_4 -LBB9_2: - ldp x29, x30, [sp, #16] - add sp, sp, #32 - ret -LBB9_3: - mov w8, #1 - strb w8, [sp, #7] - add x8, sp, #7 - str x8, [sp, #8] + add x5, x5, _init_forgetable_ivars@PAGEOFF + add x0, sp, #8 + mov x3, #0 + bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + ldr x8, [sp, #8] + str x8, [sp, #16] + mov w8, #8 Lloh129: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE + adrp x9, l_anon.[ID].14@PAGE Lloh130: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + add x9, x9, l_anon.[ID].14@PAGEOFF + stp x8, x9, [sp, #32] + mov w8, #27 + strb w8, [sp, #24] Lloh131: - adrp x3, l_anon.[ID].2@PAGE + adrp x20, l_anon.[ID].11@PAGE Lloh132: - add x3, x3, l_anon.[ID].2@PAGEOFF + add x20, x20, l_anon.[ID].11@PAGEOFF + add x0, sp, #16 + add x5, sp, #24 + mov x1, x20 + mov w2, #5 + mov w3, #8 + mov w4, #2 + bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + ldr x0, [sp, #16] + bl SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) + mov x19, x0 + mov x1, x20 + mov w2, #5 + bl SYM(objc2::runtime::AnyClass::instance_variable::GENERATED_ID, 0) + cbz x0, LBB6_6 + bl _ivar_getOffset Lloh133: - adrp x4, l_anon.[ID].27@PAGE + adrp x8, __MergedGlobals@PAGE+16 + str x19, [x8, __MergedGlobals@PAGEOFF+16] Lloh134: - add x4, x4, l_anon.[ID].27@PAGEOFF - add x2, sp, #8 - mov w1, #0 - bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)@PAGE + str x0, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)@PAGEOFF] Lloh135: - adrp x0, l_anon.[ID].14@PAGE + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2)@PAGE + str xzr, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2)@PAGEOFF] + ldp x29, x30, [sp, #80] + ldp x20, x19, [sp, #64] + add sp, sp, #96 + ret +LBB6_4: Lloh136: - add x0, x0, l_anon.[ID].14@PAGEOFF - mov w1, #15 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB9_2 -LBB9_4: + adrp x0, l_anon.[ID].24@PAGE Lloh137: - adrp x0, l_anon.[ID].11@PAGE + add x0, x0, l_anon.[ID].24@PAGEOFF Lloh138: - add x0, x0, l_anon.[ID].11@PAGEOFF + adrp x2, l_anon.[ID].26@PAGE Lloh139: - adrp x2, l_anon.[ID].27@PAGE -Lloh140: - add x2, x2, l_anon.[ID].27@PAGEOFF + add x2, x2, l_anon.[ID].26@PAGEOFF mov w1, #43 bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh125, Lloh126 - .loh AdrpAdd Lloh127, Lloh128 - .loh AdrpAdd Lloh135, Lloh136 - .loh AdrpAdd Lloh133, Lloh134 +LBB6_5: +Lloh140: + adrp x0, l_anon.[ID].21@PAGE +Lloh141: + add x0, x0, l_anon.[ID].21@PAGEOFF +Lloh142: + adrp x2, l_anon.[ID].31@PAGE +Lloh143: + add x2, x2, l_anon.[ID].31@PAGEOFF + mov w1, #15 + bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) +LBB6_6: +Lloh144: + adrp x0, l_anon.[ID].16@PAGE +Lloh145: + add x0, x0, l_anon.[ID].16@PAGEOFF +Lloh146: + adrp x2, l_anon.[ID].18@PAGE +Lloh147: + add x2, x2, l_anon.[ID].18@PAGEOFF + mov w1, #59 + bl SYM(core::option::expect_failed::GENERATED_ID, 0) + .loh AdrpAdd Lloh118, Lloh119 + .loh AdrpLdrGotLdr Lloh115, Lloh116, Lloh117 .loh AdrpAdd Lloh131, Lloh132 .loh AdrpAdd Lloh129, Lloh130 - .loh AdrpAdd Lloh139, Lloh140 - .loh AdrpAdd Lloh137, Lloh138 + .loh AdrpAdd Lloh127, Lloh128 + .loh AdrpAdd Lloh125, Lloh126 + .loh AdrpAdd Lloh123, Lloh124 + .loh AdrpLdrGotLdr Lloh120, Lloh121, Lloh122 + .loh AdrpAdrp Lloh134, Lloh135 + .loh AdrpAdrp Lloh133, Lloh134 + .loh AdrpAdd Lloh138, Lloh139 + .loh AdrpAdd Lloh136, Lloh137 + .loh AdrpAdd Lloh142, Lloh143 + .loh AdrpAdd Lloh140, Lloh141 + .loh AdrpAdd Lloh146, Lloh147 + .loh AdrpAdd Lloh144, Lloh145 - .globl _access_forgetable_ivars .p2align 2 -_access_forgetable_ivars: - stp x20, x19, [sp, #-32]! +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): + sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 - mov x19, x0 -Lloh141: - adrp x1, l_anon.[ID].20@PAGE -Lloh142: - add x1, x1, l_anon.[ID].20@PAGEOFF - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldrb w20, [x19, x0] -Lloh143: - adrp x1, l_anon.[ID].19@PAGE -Lloh144: - add x1, x1, l_anon.[ID].19@PAGEOFF - mov x0, x19 - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr w1, [x19, x0] - mov x0, x20 + ldr x8, [x0] + str x8, [sp, #8] + add x0, sp, #8 + bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) ldp x29, x30, [sp, #16] - ldp x20, x19, [sp], #32 + add sp, sp, #32 ret - .loh AdrpAdd Lloh143, Lloh144 - .loh AdrpAdd Lloh141, Lloh142 - .globl SYM(::drop, 0) .p2align 2 -SYM(::drop, 0): - ; InlineAsm Start - ; InlineAsm End +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 + ldr x8, [x0] + str x8, [sp, #8] + add x0, sp, #8 + bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) + ldp x29, x30, [sp, #16] + add sp, sp, #32 ret - .globl _access_drop_ivars_class .p2align 2 -_access_drop_ivars_class: +SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh145: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh146: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF - ldapr x8, [x8] - cmp x8, #3 - b.ne LBB12_3 -Lloh147: - adrp x0, l_anon.[ID].16@PAGE -Lloh148: - add x0, x0, l_anon.[ID].16@PAGEOFF - mov w1, #9 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB12_4 -LBB12_2: + ldr x8, [x0] + str x8, [sp, #8] + add x0, sp, #8 + bl SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 ret -LBB12_3: + + .globl _access_forgetable_ivars_class + .p2align 2 +_access_forgetable_ivars_class: +Lloh148: + adrp x8, __MergedGlobals@PAGE+24 +Lloh149: + add x8, x8, __MergedGlobals@PAGEOFF+24 + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB10_2 +Lloh150: + adrp x8, __MergedGlobals@PAGE+16 +Lloh151: + ldr x0, [x8, __MergedGlobals@PAGEOFF+16] + ret +LBB10_2: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 mov w8, #1 strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh149: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh150: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF -Lloh151: - adrp x3, l_anon.[ID].1@PAGE Lloh152: - add x3, x3, l_anon.[ID].1@PAGEOFF + adrp x0, __MergedGlobals@PAGE+24 Lloh153: - adrp x4, l_anon.[ID].28@PAGE + add x0, x0, __MergedGlobals@PAGEOFF+24 Lloh154: - add x4, x4, l_anon.[ID].28@PAGEOFF - add x2, sp, #8 - mov w1, #0 - bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + adrp x3, l_anon.[ID].2@PAGE Lloh155: - adrp x0, l_anon.[ID].16@PAGE + add x3, x3, l_anon.[ID].2@PAGEOFF Lloh156: - add x0, x0, l_anon.[ID].16@PAGEOFF - mov w1, #9 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB12_2 -LBB12_4: + adrp x4, l_anon.[ID].31@PAGE Lloh157: - adrp x0, l_anon.[ID].11@PAGE + add x4, x4, l_anon.[ID].31@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + ldp x29, x30, [sp, #16] + add sp, sp, #32 Lloh158: - add x0, x0, l_anon.[ID].11@PAGEOFF + adrp x8, __MergedGlobals@PAGE+16 Lloh159: - adrp x2, l_anon.[ID].28@PAGE -Lloh160: - add x2, x2, l_anon.[ID].28@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh145, Lloh146 - .loh AdrpAdd Lloh147, Lloh148 - .loh AdrpAdd Lloh155, Lloh156 - .loh AdrpAdd Lloh153, Lloh154 - .loh AdrpAdd Lloh151, Lloh152 - .loh AdrpAdd Lloh149, Lloh150 - .loh AdrpAdd Lloh159, Lloh160 - .loh AdrpAdd Lloh157, Lloh158 + ldr x0, [x8, __MergedGlobals@PAGEOFF+16] + ret + .loh AdrpAdd Lloh148, Lloh149 + .loh AdrpLdr Lloh150, Lloh151 + .loh AdrpLdr Lloh158, Lloh159 + .loh AdrpAdd Lloh156, Lloh157 + .loh AdrpAdd Lloh154, Lloh155 + .loh AdrpAdd Lloh152, Lloh153 - .globl _access_drop_ivars + .globl _access_forgetable_ivars .p2align 2 -_access_drop_ivars: - stp x20, x19, [sp, #-32]! - stp x29, x30, [sp, #16] - add x29, sp, #16 - mov x19, x0 +_access_forgetable_ivars: +Lloh160: + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)@PAGE Lloh161: - adrp x1, l_anon.[ID].18@PAGE -Lloh162: - add x1, x1, l_anon.[ID].18@PAGEOFF - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr x0, [x19, x0] - ldp x29, x30, [sp, #16] - ldp x20, x19, [sp], #32 + ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)@PAGEOFF] + add x8, x0, x8 + ldr w1, [x8] + ldrb w0, [x8, #4] ret - .loh AdrpAdd Lloh161, Lloh162 + .loh AdrpLdr Lloh160, Lloh161 - .globl SYM(::class, 0) + .globl SYM(::drop, 0) .p2align 2 -SYM(::class, 0): - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 +SYM(::drop, 0): + ; InlineAsm Start + ; InlineAsm End + ret + + .globl _access_drop_ivars_class + .p2align 2 +_access_drop_ivars_class: +Lloh162: + adrp x8, __MergedGlobals@PAGE+40 Lloh163: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh164: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + add x8, x8, __MergedGlobals@PAGEOFF+40 ldapr x8, [x8] cmp x8, #3 - b.ne LBB14_3 + b.ne LBB13_2 +Lloh164: + adrp x8, __MergedGlobals@PAGE+32 Lloh165: - adrp x0, l_anon.[ID].15@PAGE -Lloh166: - add x0, x0, l_anon.[ID].15@PAGEOFF - mov w1, #7 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB14_4 -LBB14_2: - ldp x29, x30, [sp, #16] - add sp, sp, #32 + ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret -LBB14_3: +LBB13_2: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 mov w8, #1 strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] +Lloh166: + adrp x0, __MergedGlobals@PAGE+40 Lloh167: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE + add x0, x0, __MergedGlobals@PAGEOFF+40 Lloh168: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + adrp x3, l_anon.[ID].1@PAGE Lloh169: - adrp x3, l_anon.[ID].0@PAGE + add x3, x3, l_anon.[ID].1@PAGEOFF Lloh170: - add x3, x3, l_anon.[ID].0@PAGEOFF + adrp x4, l_anon.[ID].32@PAGE Lloh171: - adrp x4, l_anon.[ID].22@PAGE -Lloh172: - add x4, x4, l_anon.[ID].22@PAGEOFF + add x4, x4, l_anon.[ID].32@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + ldp x29, x30, [sp, #16] + add sp, sp, #32 +Lloh172: + adrp x8, __MergedGlobals@PAGE+32 Lloh173: - adrp x0, l_anon.[ID].15@PAGE + ldr x0, [x8, __MergedGlobals@PAGEOFF+32] + ret + .loh AdrpAdd Lloh162, Lloh163 + .loh AdrpLdr Lloh164, Lloh165 + .loh AdrpLdr Lloh172, Lloh173 + .loh AdrpAdd Lloh170, Lloh171 + .loh AdrpAdd Lloh168, Lloh169 + .loh AdrpAdd Lloh166, Lloh167 + + .globl _access_drop_ivars + .p2align 2 +_access_drop_ivars: Lloh174: - add x0, x0, l_anon.[ID].15@PAGEOFF - mov w1, #7 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB14_2 -LBB14_4: + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE Lloh175: - adrp x0, l_anon.[ID].11@PAGE + ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] + add x8, x0, x8 + ldp x0, x1, [x8] + ret + .loh AdrpLdr Lloh174, Lloh175 + + .globl SYM(::class, 0) + .p2align 2 +SYM(::class, 0): Lloh176: - add x0, x0, l_anon.[ID].11@PAGEOFF + adrp x8, __MergedGlobals@PAGE+8 Lloh177: - adrp x2, l_anon.[ID].22@PAGE + add x8, x8, __MergedGlobals@PAGEOFF+8 + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB15_2 Lloh178: - add x2, x2, l_anon.[ID].22@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh163, Lloh164 - .loh AdrpAdd Lloh165, Lloh166 - .loh AdrpAdd Lloh173, Lloh174 - .loh AdrpAdd Lloh171, Lloh172 - .loh AdrpAdd Lloh169, Lloh170 - .loh AdrpAdd Lloh167, Lloh168 - .loh AdrpAdd Lloh177, Lloh178 - .loh AdrpAdd Lloh175, Lloh176 - - .globl _get_class - .p2align 2 -_get_class: + adrp x8, __MergedGlobals@PAGE +Lloh179: + ldr x0, [x8, __MergedGlobals@PAGEOFF] + ret +LBB15_2: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh179: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh180: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF - ldapr x8, [x8] - cmp x8, #3 - b.ne LBB15_3 -Lloh181: - adrp x0, l_anon.[ID].15@PAGE -Lloh182: - add x0, x0, l_anon.[ID].15@PAGEOFF - mov w1, #7 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB15_4 -LBB15_2: - ldp x29, x30, [sp, #16] - add sp, sp, #32 - ret -LBB15_3: mov w8, #1 strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] +Lloh180: + adrp x0, __MergedGlobals@PAGE+8 +Lloh181: + add x0, x0, __MergedGlobals@PAGEOFF+8 +Lloh182: + adrp x3, l_anon.[ID].0@PAGE Lloh183: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE + add x3, x3, l_anon.[ID].0@PAGEOFF Lloh184: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + adrp x4, l_anon.[ID].28@PAGE Lloh185: - adrp x3, l_anon.[ID].0@PAGE -Lloh186: - add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh187: - adrp x4, l_anon.[ID].22@PAGE -Lloh188: - add x4, x4, l_anon.[ID].22@PAGEOFF + add x4, x4, l_anon.[ID].28@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + ldp x29, x30, [sp, #16] + add sp, sp, #32 +Lloh186: + adrp x8, __MergedGlobals@PAGE +Lloh187: + ldr x0, [x8, __MergedGlobals@PAGEOFF] + ret + .loh AdrpAdd Lloh176, Lloh177 + .loh AdrpLdr Lloh178, Lloh179 + .loh AdrpLdr Lloh186, Lloh187 + .loh AdrpAdd Lloh184, Lloh185 + .loh AdrpAdd Lloh182, Lloh183 + .loh AdrpAdd Lloh180, Lloh181 + + .globl _get_class + .p2align 2 +_get_class: +Lloh188: + adrp x8, __MergedGlobals@PAGE+8 Lloh189: - adrp x0, l_anon.[ID].15@PAGE + add x8, x8, __MergedGlobals@PAGEOFF+8 + ldapr x8, [x8] + cmp x8, #3 + b.ne LBB16_2 Lloh190: - add x0, x0, l_anon.[ID].15@PAGEOFF - mov w1, #7 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB15_2 -LBB15_4: + adrp x8, __MergedGlobals@PAGE Lloh191: - adrp x0, l_anon.[ID].11@PAGE + ldr x0, [x8, __MergedGlobals@PAGEOFF] + ret +LBB16_2: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 + mov w8, #1 + strb w8, [sp, #7] + add x8, sp, #7 + str x8, [sp, #8] Lloh192: - add x0, x0, l_anon.[ID].11@PAGEOFF + adrp x0, __MergedGlobals@PAGE+8 Lloh193: - adrp x2, l_anon.[ID].22@PAGE + add x0, x0, __MergedGlobals@PAGEOFF+8 Lloh194: - add x2, x2, l_anon.[ID].22@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh179, Lloh180 - .loh AdrpAdd Lloh181, Lloh182 - .loh AdrpAdd Lloh189, Lloh190 - .loh AdrpAdd Lloh187, Lloh188 - .loh AdrpAdd Lloh185, Lloh186 - .loh AdrpAdd Lloh183, Lloh184 - .loh AdrpAdd Lloh193, Lloh194 - .loh AdrpAdd Lloh191, Lloh192 + adrp x3, l_anon.[ID].0@PAGE +Lloh195: + add x3, x3, l_anon.[ID].0@PAGEOFF +Lloh196: + adrp x4, l_anon.[ID].28@PAGE +Lloh197: + add x4, x4, l_anon.[ID].28@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + ldp x29, x30, [sp, #16] + add sp, sp, #32 +Lloh198: + adrp x8, __MergedGlobals@PAGE +Lloh199: + ldr x0, [x8, __MergedGlobals@PAGEOFF] + ret + .loh AdrpAdd Lloh188, Lloh189 + .loh AdrpLdr Lloh190, Lloh191 + .loh AdrpLdr Lloh198, Lloh199 + .loh AdrpAdd Lloh196, Lloh197 + .loh AdrpAdd Lloh194, Lloh195 + .loh AdrpAdd Lloh192, Lloh193 .globl _method_simple .p2align 2 @@ -880,79 +910,57 @@ _method_id: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh195: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh196: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh200: + adrp x8, __MergedGlobals@PAGE+8 +Lloh201: + add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 - b.ne LBB18_3 -Lloh197: - adrp x0, l_anon.[ID].15@PAGE -Lloh198: - add x0, x0, l_anon.[ID].15@PAGEOFF - mov w1, #7 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB18_4 -LBB18_2: -Lloh199: + b.ne LBB19_2 +LBB19_1: +Lloh202: + adrp x8, __MergedGlobals@PAGE +Lloh203: + ldr x0, [x8, __MergedGlobals@PAGEOFF] +Lloh204: adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE -Lloh200: +Lloh205: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] -Lloh201: +Lloh206: ldr x1, [x8] bl _objc_msgSend bl _objc_autoreleaseReturnValue ldp x29, x30, [sp, #16] add sp, sp, #32 ret -LBB18_3: +LBB19_2: mov w8, #1 strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh202: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh203: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF -Lloh204: - adrp x3, l_anon.[ID].0@PAGE -Lloh205: - add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh206: - adrp x4, l_anon.[ID].22@PAGE Lloh207: - add x4, x4, l_anon.[ID].22@PAGEOFF - add x2, sp, #8 - mov w1, #0 - bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + adrp x0, __MergedGlobals@PAGE+8 Lloh208: - adrp x0, l_anon.[ID].15@PAGE + add x0, x0, __MergedGlobals@PAGEOFF+8 Lloh209: - add x0, x0, l_anon.[ID].15@PAGEOFF - mov w1, #7 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB18_2 -LBB18_4: + adrp x3, l_anon.[ID].0@PAGE Lloh210: - adrp x0, l_anon.[ID].11@PAGE + add x3, x3, l_anon.[ID].0@PAGEOFF Lloh211: - add x0, x0, l_anon.[ID].11@PAGEOFF + adrp x4, l_anon.[ID].28@PAGE Lloh212: - adrp x2, l_anon.[ID].22@PAGE -Lloh213: - add x2, x2, l_anon.[ID].22@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh195, Lloh196 - .loh AdrpAdd Lloh197, Lloh198 - .loh AdrpLdrGotLdr Lloh199, Lloh200, Lloh201 - .loh AdrpAdd Lloh208, Lloh209 - .loh AdrpAdd Lloh206, Lloh207 - .loh AdrpAdd Lloh204, Lloh205 - .loh AdrpAdd Lloh202, Lloh203 - .loh AdrpAdd Lloh212, Lloh213 - .loh AdrpAdd Lloh210, Lloh211 + add x4, x4, l_anon.[ID].28@PAGEOFF + add x2, sp, #8 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + b LBB19_1 + .loh AdrpAdd Lloh200, Lloh201 + .loh AdrpLdrGotLdr Lloh204, Lloh205, Lloh206 + .loh AdrpAdrp Lloh202, Lloh204 + .loh AdrpLdr Lloh202, Lloh203 + .loh AdrpAdd Lloh211, Lloh212 + .loh AdrpAdd Lloh209, Lloh210 + .loh AdrpAdd Lloh207, Lloh208 .globl _method_id_with_param .p2align 2 @@ -963,13 +971,13 @@ _method_id_with_param: mov x20, x2 bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) mov x19, x0 - tbz w20, #0, LBB19_2 + tbz w20, #0, LBB20_2 bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) mov x20, x0 mov x0, x19 bl _objc_release mov x19, x20 -LBB19_2: +LBB20_2: mov x0, x19 ldp x29, x30, [sp, #16] ldp x20, x19, [sp], #32 @@ -981,402 +989,257 @@ _copyWithZone: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 +Lloh213: + adrp x8, __MergedGlobals@PAGE+8 Lloh214: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh215: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF + add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 - b.ne LBB20_3 + b.ne LBB21_2 +LBB21_1: +Lloh215: + adrp x8, __MergedGlobals@PAGE Lloh216: - adrp x0, l_anon.[ID].15@PAGE + ldr x0, [x8, __MergedGlobals@PAGEOFF] Lloh217: - add x0, x0, l_anon.[ID].15@PAGEOFF - mov w1, #7 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB20_4 -LBB20_2: -Lloh218: adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE -Lloh219: +Lloh218: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] -Lloh220: +Lloh219: ldr x1, [x8] bl _objc_msgSend ldp x29, x30, [sp, #16] add sp, sp, #32 ret -LBB20_3: +LBB21_2: mov w8, #1 strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] +Lloh220: + adrp x0, __MergedGlobals@PAGE+8 Lloh221: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE + add x0, x0, __MergedGlobals@PAGEOFF+8 Lloh222: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF -Lloh223: adrp x3, l_anon.[ID].0@PAGE -Lloh224: +Lloh223: add x3, x3, l_anon.[ID].0@PAGEOFF +Lloh224: + adrp x4, l_anon.[ID].28@PAGE Lloh225: - adrp x4, l_anon.[ID].22@PAGE -Lloh226: - add x4, x4, l_anon.[ID].22@PAGEOFF + add x4, x4, l_anon.[ID].28@PAGEOFF add x2, sp, #8 - mov w1, #0 - bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) -Lloh227: - adrp x0, l_anon.[ID].15@PAGE -Lloh228: - add x0, x0, l_anon.[ID].15@PAGEOFF - mov w1, #7 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB20_2 -LBB20_4: -Lloh229: - adrp x0, l_anon.[ID].11@PAGE -Lloh230: - add x0, x0, l_anon.[ID].11@PAGEOFF -Lloh231: - adrp x2, l_anon.[ID].22@PAGE -Lloh232: - add x2, x2, l_anon.[ID].22@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh214, Lloh215 - .loh AdrpAdd Lloh216, Lloh217 - .loh AdrpLdrGotLdr Lloh218, Lloh219, Lloh220 - .loh AdrpAdd Lloh227, Lloh228 - .loh AdrpAdd Lloh225, Lloh226 - .loh AdrpAdd Lloh223, Lloh224 - .loh AdrpAdd Lloh221, Lloh222 - .loh AdrpAdd Lloh231, Lloh232 - .loh AdrpAdd Lloh229, Lloh230 + mov w1, #0 + bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) + b LBB21_1 + .loh AdrpAdd Lloh213, Lloh214 + .loh AdrpLdrGotLdr Lloh217, Lloh218, Lloh219 + .loh AdrpAdrp Lloh215, Lloh217 + .loh AdrpLdr Lloh215, Lloh216 + .loh AdrpAdd Lloh224, Lloh225 + .loh AdrpAdd Lloh222, Lloh223 + .loh AdrpAdd Lloh220, Lloh221 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 -Lloh233: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh234: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh226: + adrp x8, __MergedGlobals@PAGE+24 +Lloh227: + add x8, x8, __MergedGlobals@PAGEOFF+24 ldapr x8, [x8] cmp x8, #3 - b.ne LBB21_3 -Lloh235: - adrp x0, l_anon.[ID].14@PAGE -Lloh236: - add x0, x0, l_anon.[ID].14@PAGEOFF - mov w1, #15 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB21_4 -LBB21_2: - ldp x29, x30, [sp, #16] - add sp, sp, #32 + b.ne LBB22_2 +Lloh228: + adrp x8, __MergedGlobals@PAGE+16 +Lloh229: + ldr x0, [x8, __MergedGlobals@PAGEOFF+16] ret -LBB21_3: +LBB22_2: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 mov w8, #1 strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh237: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh238: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF -Lloh239: +Lloh230: + adrp x0, __MergedGlobals@PAGE+24 +Lloh231: + add x0, x0, __MergedGlobals@PAGEOFF+24 +Lloh232: adrp x3, l_anon.[ID].2@PAGE -Lloh240: +Lloh233: add x3, x3, l_anon.[ID].2@PAGEOFF -Lloh241: - adrp x4, l_anon.[ID].27@PAGE -Lloh242: - add x4, x4, l_anon.[ID].27@PAGEOFF +Lloh234: + adrp x4, l_anon.[ID].31@PAGE +Lloh235: + add x4, x4, l_anon.[ID].31@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) -Lloh243: - adrp x0, l_anon.[ID].14@PAGE -Lloh244: - add x0, x0, l_anon.[ID].14@PAGEOFF - mov w1, #15 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB21_2 -LBB21_4: -Lloh245: - adrp x0, l_anon.[ID].11@PAGE -Lloh246: - add x0, x0, l_anon.[ID].11@PAGEOFF -Lloh247: - adrp x2, l_anon.[ID].27@PAGE -Lloh248: - add x2, x2, l_anon.[ID].27@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh233, Lloh234 - .loh AdrpAdd Lloh235, Lloh236 - .loh AdrpAdd Lloh243, Lloh244 - .loh AdrpAdd Lloh241, Lloh242 - .loh AdrpAdd Lloh239, Lloh240 - .loh AdrpAdd Lloh237, Lloh238 - .loh AdrpAdd Lloh247, Lloh248 - .loh AdrpAdd Lloh245, Lloh246 - - .p2align 2 -SYM(::class::{closure#0}::__objc2_dealloc, 0): - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 -Lloh249: - adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh250: - ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh251: - ldr x8, [x8] - stp x0, x8, [sp] - mov x0, sp - bl _objc_msgSendSuper ldp x29, x30, [sp, #16] add sp, sp, #32 +Lloh236: + adrp x8, __MergedGlobals@PAGE+16 +Lloh237: + ldr x0, [x8, __MergedGlobals@PAGEOFF+16] ret - .loh AdrpLdrGotLdr Lloh249, Lloh250, Lloh251 + .loh AdrpAdd Lloh226, Lloh227 + .loh AdrpLdr Lloh228, Lloh229 + .loh AdrpLdr Lloh236, Lloh237 + .loh AdrpAdd Lloh234, Lloh235 + .loh AdrpAdd Lloh232, Lloh233 + .loh AdrpAdd Lloh230, Lloh231 .globl _init_forgetable_ivars .p2align 2 _init_forgetable_ivars: - sub sp, sp, #48 - stp x20, x19, [sp, #16] - stp x29, x30, [sp, #32] - add x29, sp, #32 -Lloh252: - adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE -Lloh253: - ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] -Lloh254: - ldr x1, [x8] -Lloh255: + cbz x0, LBB23_2 +Lloh238: + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)@PAGE +Lloh239: + ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)@PAGEOFF] + add x8, x0, x8 + mov w9, #43 + str w9, [x8] + mov w9, #42 + strb w9, [x8, #4] +LBB23_2: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 +Lloh240: + adrp x8, L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c@PAGE +Lloh241: + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c@PAGEOFF] +Lloh242: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh256: +Lloh243: ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh257: +Lloh244: ldr x8, [x8] stp x0, x8, [sp] mov x0, sp bl _objc_msgSendSuper - mov x19, x0 - cbz x0, LBB23_2 -Lloh258: - adrp x1, l_anon.[ID].20@PAGE -Lloh259: - add x1, x1, l_anon.[ID].20@PAGEOFF - mov x0, x19 - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - mov w8, #42 - strb w8, [x19, x0] -Lloh260: - adrp x1, l_anon.[ID].19@PAGE -Lloh261: - add x1, x1, l_anon.[ID].19@PAGEOFF - mov x0, x19 - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - mov w8, #43 - str w8, [x19, x0] -LBB23_2: - mov x0, x19 - ldp x29, x30, [sp, #32] - ldp x20, x19, [sp, #16] - add sp, sp, #48 + ldp x29, x30, [sp, #16] + add sp, sp, #32 ret - .loh AdrpLdrGotLdr Lloh255, Lloh256, Lloh257 - .loh AdrpLdrGotLdr Lloh252, Lloh253, Lloh254 - .loh AdrpAdd Lloh260, Lloh261 - .loh AdrpAdd Lloh258, Lloh259 + .loh AdrpLdr Lloh238, Lloh239 + .loh AdrpLdrGotLdr Lloh242, Lloh243, Lloh244 + .loh AdrpAdrp Lloh240, Lloh242 + .loh AdrpLdr Lloh240, Lloh241 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): - sub sp, sp, #32 - stp x29, x30, [sp, #16] - add x29, sp, #16 -Lloh262: - adrp x8, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh263: - add x8, x8, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF +Lloh245: + adrp x8, __MergedGlobals@PAGE+40 +Lloh246: + add x8, x8, __MergedGlobals@PAGEOFF+40 ldapr x8, [x8] cmp x8, #3 - b.ne LBB24_3 -Lloh264: - adrp x0, l_anon.[ID].16@PAGE -Lloh265: - add x0, x0, l_anon.[ID].16@PAGEOFF - mov w1, #9 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbz x0, LBB24_4 -LBB24_2: - ldp x29, x30, [sp, #16] - add sp, sp, #32 + b.ne LBB24_2 +Lloh247: + adrp x8, __MergedGlobals@PAGE+32 +Lloh248: + ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret -LBB24_3: +LBB24_2: + sub sp, sp, #32 + stp x29, x30, [sp, #16] + add x29, sp, #16 mov w8, #1 strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh266: - adrp x0, SYM(::class::REGISTER_CLASS, 0)@PAGE -Lloh267: - add x0, x0, SYM(::class::REGISTER_CLASS, 0)@PAGEOFF -Lloh268: +Lloh249: + adrp x0, __MergedGlobals@PAGE+40 +Lloh250: + add x0, x0, __MergedGlobals@PAGEOFF+40 +Lloh251: adrp x3, l_anon.[ID].1@PAGE -Lloh269: +Lloh252: add x3, x3, l_anon.[ID].1@PAGEOFF -Lloh270: - adrp x4, l_anon.[ID].28@PAGE -Lloh271: - add x4, x4, l_anon.[ID].28@PAGEOFF +Lloh253: + adrp x4, l_anon.[ID].32@PAGE +Lloh254: + add x4, x4, l_anon.[ID].32@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) -Lloh272: - adrp x0, l_anon.[ID].16@PAGE -Lloh273: - add x0, x0, l_anon.[ID].16@PAGEOFF - mov w1, #9 - bl SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - cbnz x0, LBB24_2 -LBB24_4: -Lloh274: - adrp x0, l_anon.[ID].11@PAGE -Lloh275: - add x0, x0, l_anon.[ID].11@PAGEOFF -Lloh276: - adrp x2, l_anon.[ID].28@PAGE -Lloh277: - add x2, x2, l_anon.[ID].28@PAGEOFF - mov w1, #43 - bl SYM(core::panicking::panic::GENERATED_ID, 0) - .loh AdrpAdd Lloh262, Lloh263 - .loh AdrpAdd Lloh264, Lloh265 - .loh AdrpAdd Lloh272, Lloh273 - .loh AdrpAdd Lloh270, Lloh271 - .loh AdrpAdd Lloh268, Lloh269 - .loh AdrpAdd Lloh266, Lloh267 - .loh AdrpAdd Lloh276, Lloh277 - .loh AdrpAdd Lloh274, Lloh275 + ldp x29, x30, [sp, #16] + add sp, sp, #32 +Lloh255: + adrp x8, __MergedGlobals@PAGE+32 +Lloh256: + ldr x0, [x8, __MergedGlobals@PAGEOFF+32] + ret + .loh AdrpAdd Lloh245, Lloh246 + .loh AdrpLdr Lloh247, Lloh248 + .loh AdrpLdr Lloh255, Lloh256 + .loh AdrpAdd Lloh253, Lloh254 + .loh AdrpAdd Lloh251, Lloh252 + .loh AdrpAdd Lloh249, Lloh250 + .globl _init_drop_ivars .p2align 2 -SYM(::class::{closure#0}::__objc2_dealloc, 0): - sub sp, sp, #48 - stp x20, x19, [sp, #16] - stp x29, x30, [sp, #32] - add x29, sp, #32 - mov x19, x1 +_init_drop_ivars: + sub sp, sp, #64 + stp x22, x21, [sp, #16] + stp x20, x19, [sp, #32] + stp x29, x30, [sp, #48] + add x29, sp, #48 + mov x19, x0 + bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) mov x20, x0 - bl SYM(::drop, 0) -Lloh278: - adrp x1, l_anon.[ID].18@PAGE -Lloh279: - add x1, x1, l_anon.[ID].18@PAGEOFF - mov x0, x20 - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr x0, [x20, x0] - cbz x0, LBB25_2 - bl _objc_release + bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) + mov x21, x0 + adrp x22, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGE + cbz x19, LBB25_2 +Lloh257: + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE +Lloh258: + ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] + add x8, x19, x8 + stp x20, x21, [x8] + ldr x8, [x22, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGEOFF] + mov w9, #15 + strb w9, [x19, x8] + b LBB25_3 LBB25_2: -Lloh280: - adrp x1, l_anon.[ID].17@PAGE -Lloh281: - add x1, x1, l_anon.[ID].17@PAGEOFF mov x0, x20 - mov w2, #11 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - ldr x0, [x20, x0] - cbz x0, LBB25_4 bl _objc_release -LBB25_4: -Lloh282: - adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh283: - ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh284: - ldr x8, [x8] - stp x20, x8, [sp] - mov x0, sp - mov x1, x19 - bl _objc_msgSendSuper - ldp x29, x30, [sp, #32] - ldp x20, x19, [sp, #16] - add sp, sp, #48 - ret - .loh AdrpAdd Lloh278, Lloh279 - .loh AdrpAdd Lloh280, Lloh281 - .loh AdrpLdrGotLdr Lloh282, Lloh283, Lloh284 - - .globl _init_drop_ivars - .p2align 2 -_init_drop_ivars: - sub sp, sp, #48 - stp x20, x19, [sp, #16] - stp x29, x30, [sp, #32] - add x29, sp, #32 -Lloh285: - adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE -Lloh286: - ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] -Lloh287: - ldr x1, [x8] -Lloh288: + mov x0, x21 + bl _objc_release +LBB25_3: +Lloh259: + adrp x8, L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32@PAGE +Lloh260: + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32@PAGEOFF] +Lloh261: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh289: +Lloh262: ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh290: +Lloh263: ldr x8, [x8] - stp x0, x8, [sp] + stp x19, x8, [sp] mov x0, sp bl _objc_msgSendSuper - mov x19, x0 - cbz x0, LBB26_2 - bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) - mov x20, x0 -Lloh291: - adrp x1, l_anon.[ID].18@PAGE -Lloh292: - add x1, x1, l_anon.[ID].18@PAGEOFF - mov x0, x19 - mov w2, #4 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - str x20, [x19, x0] - bl SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) - mov x20, x0 -Lloh293: - adrp x1, l_anon.[ID].17@PAGE -Lloh294: - add x1, x1, l_anon.[ID].17@PAGEOFF - mov x0, x19 - mov w2, #11 - bl SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - bl _ivar_getOffset - str x20, [x19, x0] -LBB26_2: - mov x0, x19 - ldp x29, x30, [sp, #32] - ldp x20, x19, [sp, #16] - add sp, sp, #48 + cbz x0, LBB25_5 + ldr x8, [x22, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGEOFF] + mov w9, #255 + strb w9, [x0, x8] +LBB25_5: + ldp x29, x30, [sp, #48] + ldp x20, x19, [sp, #32] + ldp x22, x21, [sp, #16] + add sp, sp, #64 ret - .loh AdrpLdrGotLdr Lloh288, Lloh289, Lloh290 - .loh AdrpLdrGotLdr Lloh285, Lloh286, Lloh287 - .loh AdrpAdd Lloh293, Lloh294 - .loh AdrpAdd Lloh291, Lloh292 + .loh AdrpLdr Lloh257, Lloh258 + .loh AdrpLdrGotLdr Lloh261, Lloh262, Lloh263 + .loh AdrpAdrp Lloh259, Lloh261 + .loh AdrpLdr Lloh259, Lloh260 .section __DATA,__const .p2align 3, 0x0 @@ -1447,183 +1310,247 @@ l_anon.[ID].10: .space 39 l_anon.[ID].11: - .ascii "called `Option::unwrap()` on a `None` value" + .ascii "ivars" l_anon.[ID].12: - .ascii "$RUSTC/library/std/src/sync/once.rs" + .ascii "drop_flag" - .section __DATA,__const .p2align 3, 0x0 l_anon.[ID].13: - .quad l_anon.[ID].12 - .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" + .byte 5 + .space 39 - .section __TEXT,__const + .p2align 3, 0x0 l_anon.[ID].14: - .ascii "ForgetableIvars" + .byte 7 + .space 39 + .p2align 3, 0x0 l_anon.[ID].15: - .ascii "NoIvars" + .byte 9 + .space 39 l_anon.[ID].16: - .ascii "DropIvars" + .ascii "failed retrieving instance variable on newly declared class" l_anon.[ID].17: - .ascii "_obj_option" + .ascii "$WORKSPACE/objc2/src/__macro_helpers/declared_ivars.rs" - .section __TEXT,__literal4,4byte_literals + .section __DATA,__const + .p2align 3, 0x0 l_anon.[ID].18: - .ascii "_obj" + .quad l_anon.[ID].17 + .asciz "P\000\000\000\000\000\000\000\035\001\000\000\016\000\000" + .section __TEXT,__const l_anon.[ID].19: - .ascii "_bar" + .ascii "failed retrieving drop flag instance variable on newly declared class" + .section __DATA,__const + .p2align 3, 0x0 l_anon.[ID].20: - .ascii "_foo" + .quad l_anon.[ID].17 + .asciz "P\000\000\000\000\000\000\000)\001\000\000\016\000\000" .section __TEXT,__const l_anon.[ID].21: + .ascii "ForgetableIvars" + +l_anon.[ID].22: + .ascii "NoIvars" + +l_anon.[ID].23: + .ascii "DropIvars" + +l_anon.[ID].24: + .ascii "called `Option::unwrap()` on a `None` value" + +l_anon.[ID].25: + .ascii "$RUSTC/library/std/src/sync/once.rs" + + .section __DATA,__const + .p2align 3, 0x0 +l_anon.[ID].26: + .quad l_anon.[ID].25 + .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" + + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1),8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1),8,3 + .section __TEXT,__const +l_anon.[ID].27: .ascii "crates/$DIR/lib.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].22: - .quad l_anon.[ID].21 - .asciz "5\000\000\000\000\000\000\000\017\000\000\000\001\000\000" +l_anon.[ID].28: + .quad l_anon.[ID].27 + .asciz "5\000\000\000\000\000\000\000\016\000\000\000\001\000\000" -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .section __TEXT,__literal8,8byte_literals -l_anon.[ID].23: +l_anon.[ID].29: .ascii "NSObject" .section __TEXT,__const -l_anon.[ID].24: +l_anon.[ID].30: .ascii "NSCopying" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_f249b8b52b9a1205 -L_OBJC_METH_VAR_NAME_f249b8b52b9a1205: + .globl L_OBJC_METH_VAR_NAME_03fd85b0462f54e9 +L_OBJC_METH_VAR_NAME_03fd85b0462f54e9: .asciz "classMethod" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_f249b8b52b9a1205 + .globl L_OBJC_SELECTOR_REFERENCES_03fd85b0462f54e9 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_f249b8b52b9a1205: - .quad L_OBJC_METH_VAR_NAME_f249b8b52b9a1205 +L_OBJC_SELECTOR_REFERENCES_03fd85b0462f54e9: + .quad L_OBJC_METH_VAR_NAME_03fd85b0462f54e9 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_f249b8b52b9a1205 + .globl L_OBJC_IMAGE_INFO_03fd85b0462f54e9 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_f249b8b52b9a1205: +L_OBJC_IMAGE_INFO_03fd85b0462f54e9: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_2607fe9c3979c381 -L_OBJC_METH_VAR_NAME_2607fe9c3979c381: + .globl L_OBJC_METH_VAR_NAME_cf773331f3cfba54 +L_OBJC_METH_VAR_NAME_cf773331f3cfba54: .asciz "method" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381 + .globl L_OBJC_SELECTOR_REFERENCES_cf773331f3cfba54 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381: - .quad L_OBJC_METH_VAR_NAME_2607fe9c3979c381 +L_OBJC_SELECTOR_REFERENCES_cf773331f3cfba54: + .quad L_OBJC_METH_VAR_NAME_cf773331f3cfba54 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_2607fe9c3979c381 + .globl L_OBJC_IMAGE_INFO_cf773331f3cfba54 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_2607fe9c3979c381: +L_OBJC_IMAGE_INFO_cf773331f3cfba54: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_5a4952192b00de7f -L_OBJC_METH_VAR_NAME_5a4952192b00de7f: + .globl L_OBJC_METH_VAR_NAME_abdcbb85641cd990 +L_OBJC_METH_VAR_NAME_abdcbb85641cd990: .asciz "methodBool:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f + .globl L_OBJC_SELECTOR_REFERENCES_abdcbb85641cd990 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f: - .quad L_OBJC_METH_VAR_NAME_5a4952192b00de7f +L_OBJC_SELECTOR_REFERENCES_abdcbb85641cd990: + .quad L_OBJC_METH_VAR_NAME_abdcbb85641cd990 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_5a4952192b00de7f + .globl L_OBJC_IMAGE_INFO_abdcbb85641cd990 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_5a4952192b00de7f: +L_OBJC_IMAGE_INFO_abdcbb85641cd990: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_bf0386bc74a73c00 -L_OBJC_METH_VAR_NAME_bf0386bc74a73c00: + .globl L_OBJC_METH_VAR_NAME_ef8de92414f2d9c8 +L_OBJC_METH_VAR_NAME_ef8de92414f2d9c8: .asciz "methodId" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00 + .globl L_OBJC_SELECTOR_REFERENCES_ef8de92414f2d9c8 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00: - .quad L_OBJC_METH_VAR_NAME_bf0386bc74a73c00 +L_OBJC_SELECTOR_REFERENCES_ef8de92414f2d9c8: + .quad L_OBJC_METH_VAR_NAME_ef8de92414f2d9c8 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_bf0386bc74a73c00 + .globl L_OBJC_IMAGE_INFO_ef8de92414f2d9c8 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_bf0386bc74a73c00: +L_OBJC_IMAGE_INFO_ef8de92414f2d9c8: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09 -L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09: + .globl L_OBJC_METH_VAR_NAME_4a611090161f3fae +L_OBJC_METH_VAR_NAME_4a611090161f3fae: .asciz "methodIdWithParam:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09 + .globl L_OBJC_SELECTOR_REFERENCES_4a611090161f3fae .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09: - .quad L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09 +L_OBJC_SELECTOR_REFERENCES_4a611090161f3fae: + .quad L_OBJC_METH_VAR_NAME_4a611090161f3fae .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_6f0ab2a047fe4a09 + .globl L_OBJC_IMAGE_INFO_4a611090161f3fae .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6f0ab2a047fe4a09: +L_OBJC_IMAGE_INFO_4a611090161f3fae: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571 -L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571: + .globl L_OBJC_METH_VAR_NAME_2837f061c311eb14 +L_OBJC_METH_VAR_NAME_2837f061c311eb14: .asciz "copyWithZone:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571 + .globl L_OBJC_SELECTOR_REFERENCES_2837f061c311eb14 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571: - .quad L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571 +L_OBJC_SELECTOR_REFERENCES_2837f061c311eb14: + .quad L_OBJC_METH_VAR_NAME_2837f061c311eb14 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_062e7a5fdd2d2571 + .globl L_OBJC_IMAGE_INFO_2837f061c311eb14 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_062e7a5fdd2d2571: +L_OBJC_IMAGE_INFO_2837f061c311eb14: .asciz "\000\000\000\000@\000\000" - .section __TEXT,__const + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2),8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2),8,3 + .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].25: - .byte 5 - .space 39 +l_anon.[ID].31: + .quad l_anon.[ID].27 + .asciz "5\000\000\000\000\000\000\000O\000\000\000\001\000\000" + + .section __TEXT,__objc_methname,cstring_literals + .globl L_OBJC_METH_VAR_NAME_af8966656b8b2b6c +L_OBJC_METH_VAR_NAME_af8966656b8b2b6c: + .asciz "init" + .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip + .globl L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c .p2align 3, 0x0 -l_anon.[ID].26: - .byte 7 - .space 39 +L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c: + .quad L_OBJC_METH_VAR_NAME_af8966656b8b2b6c + + .section __DATA,__objc_imageinfo,regular,no_dead_strip + .globl L_OBJC_IMAGE_INFO_af8966656b8b2b6c + .p2align 2, 0x0 +L_OBJC_IMAGE_INFO_af8966656b8b2b6c: + .asciz "\000\000\000\000@\000\000" + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0),8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0),8,3 .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].27: - .quad l_anon.[ID].21 - .asciz "5\000\000\000\000\000\000\000I\000\000\000\001\000\000" +l_anon.[ID].32: + .quad l_anon.[ID].27 + .asciz "5\000\000\000\000\000\000\000x\000\000\000\001\000\000" -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 + .section __TEXT,__objc_methname,cstring_literals + .globl L_OBJC_METH_VAR_NAME_6edddcebbded8f32 +L_OBJC_METH_VAR_NAME_6edddcebbded8f32: + .asciz "init" + + .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip + .globl L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32 .p2align 3, 0x0 -l_anon.[ID].28: - .quad l_anon.[ID].21 - .asciz "5\000\000\000\000\000\000\000u\000\000\000\001\000\000" +L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32: + .quad L_OBJC_METH_VAR_NAME_6edddcebbded8f32 + + .section __DATA,__objc_imageinfo,regular,no_dead_strip + .globl L_OBJC_IMAGE_INFO_6edddcebbded8f32 + .p2align 2, 0x0 +L_OBJC_IMAGE_INFO_6edddcebbded8f32: + .asciz "\000\000\000\000@\000\000" -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 +.zerofill __DATA,__bss,__MergedGlobals,48,3 .subsections_via_symbols diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s index 4716eb56e..c3ae77b08 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s @@ -21,6 +21,47 @@ SYM(core[CRATE_ID]::ptr::drop_in_place::<::call pop rbp ret + .p2align 4, 0x90 +SYM(objc2[CRATE_ID]::__macro_helpers::declared_ivars::dealloc::, 0): + push rbp + mov rbp, rsp + push r15 + push r14 + push rbx + sub rsp, 24 + mov rbx, rsi + mov r14, rdi + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)] + movzx eax, byte ptr [rdi + rax] + test eax, eax + je LBB3_5 + cmp eax, 255 + jne LBB3_3 + call SYM(::drop, 0) +LBB3_3: + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)] + mov rdi, qword ptr [r14 + rax] + mov r15, qword ptr [r14 + rax + 8] + call _objc_release + test r15, r15 + je LBB3_5 + mov rdi, r15 + call _objc_release +LBB3_5: + mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] + mov rax, qword ptr [rax] + mov qword ptr [rbp - 40], r14 + mov qword ptr [rbp - 32], rax + lea rdi, [rbp - 40] + mov rsi, rbx + call _objc_msgSendSuper + add rsp, 24 + pop rbx + pop r14 + pop r15 + pop rbp + ret + .p2align 4, 0x90 SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): push rbp @@ -33,16 +74,16 @@ SYM(::call_once::<::call_once::<::call_once::<::call_once::<::call_once::<::class::{closure#0}>::{closure#0}, 0): push rbp mov rbp, rsp - push r15 push r14 push rbx - push rax + sub rsp, 64 mov rax, qword ptr [rdi] cmp byte ptr [rax], 0 mov byte ptr [rax], 0 - je LBB4_3 + je LBB5_5 mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] mov rdx, qword ptr [rax] - lea rdi, [rip + l_anon.[ID].16] + lea rdi, [rip + l_anon.[ID].23] mov esi, 9 call SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) test rax, rax - je LBB4_4 - mov qword ptr [rbp - 32], rax - lea rsi, [rip + L_anon.[ID].18] - lea rbx, [rip + l_anon.[ID].4] - lea r14, [rbp - 32] - mov edx, 4 - mov ecx, 8 - mov rdi, r14 - mov r8d, 3 - mov r9, rbx - call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) - lea rsi, [rip + l_anon.[ID].17] - mov edx, 11 - mov ecx, 8 - mov rdi, r14 - mov r8d, 3 - mov r9, rbx - call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + je LBB5_6 + mov qword ptr [rbp - 72], rax mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPCREL] mov rsi, qword ptr [rax] - lea r15, [rip + l_anon.[ID].3] + lea rbx, [rip + l_anon.[ID].3] lea r8, [rip + l_anon.[ID].5] - lea r9, [rip + SYM(::class::{closure#0}::__objc2_dealloc, 0)] - mov rdi, r14 - mov rdx, r15 + lea r9, [rip + SYM(objc2[CRATE_ID]::__macro_helpers::declared_ivars::dealloc::, 0)] + lea rdi, [rbp - 72] + mov rdx, rbx xor ecx, ecx call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + mov rax, qword ptr [rbp - 72] + mov qword ptr [rbp - 24], rax mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] mov rsi, qword ptr [rax] + lea r8, [rip + l_anon.[ID].4] lea r9, [rip + _init_drop_ivars] - mov rdi, r14 - mov rdx, r15 + lea rdi, [rbp - 24] + mov rdx, rbx xor ecx, ecx - mov r8, rbx call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) + mov rax, qword ptr [rbp - 24] + mov qword ptr [rbp - 32], rax + mov qword ptr [rbp - 64], 16 + lea rax, [rip + l_anon.[ID].15] + mov qword ptr [rbp - 56], rax + mov byte ptr [rbp - 72], 27 + lea r14, [rip + l_anon.[ID].11] + lea rbx, [rbp - 32] + lea r9, [rbp - 72] + mov edx, 5 + mov ecx, 16 + mov rdi, rbx + mov rsi, r14 + mov r8d, 3 + call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + lea rsi, [rip + l_anon.[ID].12] + lea r9, [rip + l_anon.[ID].13] + mov edx, 9 + mov ecx, 1 + mov rdi, rbx + xor r8d, r8d + call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) mov rdi, qword ptr [rbp - 32] call SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) - add rsp, 8 + mov rbx, rax + mov edx, 5 + mov rdi, rax + mov rsi, r14 + call SYM(objc2::runtime::AnyClass::instance_variable::GENERATED_ID, 0) + test rax, rax + je LBB5_7 + mov rdi, rax + call _ivar_getOffset + mov r14, rax + lea rsi, [rip + l_anon.[ID].12] + mov edx, 9 + mov rdi, rbx + call SYM(objc2::runtime::AnyClass::instance_variable::GENERATED_ID, 0) + test rax, rax + je LBB5_8 + mov rdi, rax + call _ivar_getOffset + mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 1).0], rbx + mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)], r14 + mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)], rax + add rsp, 64 pop rbx pop r14 - pop r15 pop rbp ret -LBB4_3: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].13] +LBB5_5: + lea rdi, [rip + l_anon.[ID].24] + lea rdx, [rip + l_anon.[ID].26] mov esi, 43 call SYM(core::panicking::panic::GENERATED_ID, 0) -LBB4_4: - lea rdi, [rip + l_anon.[ID].16] - lea rdx, [rip + l_anon.[ID].28] +LBB5_6: + lea rdi, [rip + l_anon.[ID].23] + lea rdx, [rip + l_anon.[ID].32] mov esi, 9 call SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) +LBB5_7: + lea rdi, [rip + l_anon.[ID].16] + lea rdx, [rip + l_anon.[ID].18] + mov esi, 59 + call SYM(core::option::expect_failed::GENERATED_ID, 0) +LBB5_8: + lea rdi, [rip + l_anon.[ID].19] + lea rdx, [rip + l_anon.[ID].20] + mov esi, 69 + call SYM(core::option::expect_failed::GENERATED_ID, 0) .p2align 4, 0x90 SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): @@ -204,68 +285,75 @@ SYM(::call_once::<::class::{closure#0}::__objc2_dealloc, 0)] - mov rdi, rbx - mov rdx, r14 - xor ecx, ecx - call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] mov rsi, qword ptr [rax] + lea rdx, [rip + l_anon.[ID].3] lea r8, [rip + l_anon.[ID].4] lea r9, [rip + _init_forgetable_ivars] - mov rdi, rbx - mov rdx, r14 + lea rdi, [rbp - 24] xor ecx, ecx call SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) - mov rdi, qword ptr [rbp - 24] + mov rax, qword ptr [rbp - 24] + mov qword ptr [rbp - 32], rax + mov qword ptr [rbp - 64], 8 + lea rax, [rip + l_anon.[ID].14] + mov qword ptr [rbp - 56], rax + mov byte ptr [rbp - 72], 27 + lea r14, [rip + l_anon.[ID].11] + lea rdi, [rbp - 32] + lea r9, [rbp - 72] + mov edx, 5 + mov ecx, 8 + mov rsi, r14 + mov r8d, 2 + call SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) + mov rdi, qword ptr [rbp - 32] call SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) - add rsp, 16 + mov rbx, rax + mov edx, 5 + mov rdi, rax + mov rsi, r14 + call SYM(objc2::runtime::AnyClass::instance_variable::GENERATED_ID, 0) + test rax, rax + je LBB6_6 + mov rdi, rax + call _ivar_getOffset + mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 2).0], rbx + mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)], rax + mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2)], 0 + add rsp, 64 pop rbx pop r14 pop rbp ret -LBB5_3: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].13] +LBB6_4: + lea rdi, [rip + l_anon.[ID].24] + lea rdx, [rip + l_anon.[ID].26] mov esi, 43 call SYM(core::panicking::panic::GENERATED_ID, 0) -LBB5_4: - lea rdi, [rip + l_anon.[ID].14] - lea rdx, [rip + l_anon.[ID].27] +LBB6_5: + lea rdi, [rip + l_anon.[ID].21] + lea rdx, [rip + l_anon.[ID].31] mov esi, 15 call SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) +LBB6_6: + lea rdi, [rip + l_anon.[ID].16] + lea rdx, [rip + l_anon.[ID].18] + mov esi, 59 + call SYM(core::option::expect_failed::GENERATED_ID, 0) .p2align 4, 0x90 SYM(<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): @@ -309,62 +397,37 @@ SYM(<::call_once<::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB9_1 -LBB9_2: - lea rdi, [rip + l_anon.[ID].14] - mov esi, 15 - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - test rax, rax - je LBB9_4 - add rsp, 16 - pop rbp + jne LBB10_1 + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 2).0] ret -LBB9_1: +LBB10_1: + push rbp + mov rbp, rsp + sub rsp, 16 mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].2] - lea r8, [rip + l_anon.[ID].27] + lea r8, [rip + l_anon.[ID].31] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB9_2 -LBB9_4: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].27] - mov esi, 43 - call SYM(core::panicking::panic::GENERATED_ID, 0) + add rsp, 16 + pop rbp + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 2).0] + ret .globl _access_forgetable_ivars .p2align 4, 0x90 _access_forgetable_ivars: push rbp mov rbp, rsp - push r14 - push rbx - mov rbx, rdi - lea rsi, [rip + L_anon.[ID].20] - mov edx, 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - movzx r14d, byte ptr [rbx + rax] - lea rsi, [rip + L_anon.[ID].19] - mov edx, 4 - mov rdi, rbx - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov edx, dword ptr [rbx + rax] - mov eax, r14d - pop rbx - pop r14 + mov rcx, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)] + movzx eax, byte ptr [rdi + rcx + 4] + mov edx, dword ptr [rdi + rcx] pop rbp ret @@ -381,126 +444,91 @@ SYM( .globl _access_drop_ivars_class .p2align 4, 0x90 _access_drop_ivars_class: - push rbp - mov rbp, rsp - sub rsp, 16 mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB12_1 -LBB12_2: - lea rdi, [rip + l_anon.[ID].16] - mov esi, 9 - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - test rax, rax - je LBB12_4 - add rsp, 16 - pop rbp + jne LBB13_1 + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 1).0] ret -LBB12_1: +LBB13_1: + push rbp + mov rbp, rsp + sub rsp, 16 mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].1] - lea r8, [rip + l_anon.[ID].28] + lea r8, [rip + l_anon.[ID].32] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB12_2 -LBB12_4: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].28] - mov esi, 43 - call SYM(core::panicking::panic::GENERATED_ID, 0) + add rsp, 16 + pop rbp + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 1).0] + ret .globl _access_drop_ivars .p2align 4, 0x90 _access_drop_ivars: push rbp mov rbp, rsp - push rbx - push rax - mov rbx, rdi - lea rsi, [rip + L_anon.[ID].18] - mov edx, 4 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov rax, qword ptr [rbx + rax] - add rsp, 8 - pop rbx + mov rcx, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)] + mov rax, qword ptr [rdi + rcx] + mov rdx, qword ptr [rdi + rcx + 8] pop rbp ret .globl SYM(::class, 0) .p2align 4, 0x90 SYM(::class, 0): - push rbp - mov rbp, rsp - sub rsp, 16 mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB14_1 -LBB14_2: - lea rdi, [rip + l_anon.[ID].15] - mov esi, 7 - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - test rax, rax - je LBB14_4 - add rsp, 16 - pop rbp + jne LBB15_1 + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0] ret -LBB14_1: +LBB15_1: + push rbp + mov rbp, rsp + sub rsp, 16 mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].22] + lea r8, [rip + l_anon.[ID].28] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB14_2 -LBB14_4: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].22] - mov esi, 43 - call SYM(core::panicking::panic::GENERATED_ID, 0) + add rsp, 16 + pop rbp + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0] + ret .globl _get_class .p2align 4, 0x90 _get_class: - push rbp - mov rbp, rsp - sub rsp, 16 mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB15_1 -LBB15_2: - lea rdi, [rip + l_anon.[ID].15] - mov esi, 7 - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - test rax, rax - je LBB15_4 - add rsp, 16 - pop rbp + jne LBB16_1 + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0] ret -LBB15_1: +LBB16_1: + push rbp + mov rbp, rsp + sub rsp, 16 mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].22] + lea r8, [rip + l_anon.[ID].28] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB15_2 -LBB15_4: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].22] - mov esi, 43 - call SYM(core::panicking::panic::GENERATED_ID, 0) + add rsp, 16 + pop rbp + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0] + ret .globl _method_simple .p2align 4, 0x90 @@ -529,38 +557,28 @@ _method_id: sub rsp, 16 mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB18_1 -LBB18_2: - lea rdi, [rip + l_anon.[ID].15] - mov esi, 7 - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - test rax, rax - je LBB18_4 - mov rcx, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_new@GOTPCREL] - mov rsi, qword ptr [rcx] - mov rdi, rax + jne LBB19_1 +LBB19_2: + mov rdi, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0] + mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_new@GOTPCREL] + mov rsi, qword ptr [rax] call _objc_msgSend mov rdi, rax call _objc_autoreleaseReturnValue add rsp, 16 pop rbp ret -LBB18_1: +LBB19_1: mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].22] + lea r8, [rip + l_anon.[ID].28] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB18_2 -LBB18_4: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].22] - mov esi, 43 - call SYM(core::panicking::panic::GENERATED_ID, 0) + jmp LBB19_2 .globl _method_id_with_param .p2align 4, 0x90 @@ -573,13 +591,13 @@ _method_id_with_param: call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) mov rbx, rax test r14b, r14b - je LBB19_2 + je LBB20_2 call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) mov r14, rax mov rdi, rbx call _objc_release mov rbx, r14 -LBB19_2: +LBB20_2: mov rdi, rbx pop rbx pop r14 @@ -594,204 +612,100 @@ _copyWithZone: sub rsp, 16 mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB20_1 -LBB20_2: - lea rdi, [rip + l_anon.[ID].15] - mov esi, 7 - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - test rax, rax - je LBB20_4 - mov rcx, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_new@GOTPCREL] - mov rsi, qword ptr [rcx] - mov rdi, rax + jne LBB21_1 +LBB21_2: + mov rdi, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0] + mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_new@GOTPCREL] + mov rsi, qword ptr [rax] call _objc_msgSend add rsp, 16 pop rbp ret -LBB20_1: +LBB21_1: mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].22] + lea r8, [rip + l_anon.[ID].28] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB20_2 -LBB20_4: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].22] - mov esi, 43 - call SYM(core::panicking::panic::GENERATED_ID, 0) + jmp LBB21_2 .globl SYM(::class, 0) .p2align 4, 0x90 SYM(::class, 0): - push rbp - mov rbp, rsp - sub rsp, 16 mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 - jne LBB21_1 -LBB21_2: - lea rdi, [rip + l_anon.[ID].14] - mov esi, 15 - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - test rax, rax - je LBB21_4 - add rsp, 16 - pop rbp + jne LBB22_1 + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 2).0] ret -LBB21_1: +LBB22_1: + push rbp + mov rbp, rsp + sub rsp, 16 mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].2] - lea r8, [rip + l_anon.[ID].27] + lea r8, [rip + l_anon.[ID].31] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB21_2 -LBB21_4: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].27] - mov esi, 43 - call SYM(core::panicking::panic::GENERATED_ID, 0) - - .p2align 4, 0x90 -SYM(::class::{closure#0}::__objc2_dealloc, 0): - push rbp - mov rbp, rsp - sub rsp, 16 - mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] - mov rax, qword ptr [rax] - mov qword ptr [rbp - 16], rdi - mov qword ptr [rbp - 8], rax - lea rdi, [rbp - 16] - call _objc_msgSendSuper add rsp, 16 pop rbp + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 2).0] ret .globl _init_forgetable_ivars .p2align 4, 0x90 _init_forgetable_ivars: + test rdi, rdi + je LBB23_2 + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)] + mov dword ptr [rdi + rax], 43 + mov byte ptr [rdi + rax + 4], 42 +LBB23_2: push rbp mov rbp, rsp - push rbx - sub rsp, 24 - mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] - mov rsi, qword ptr [rax] + sub rsp, 16 + mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c] mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] mov rax, qword ptr [rax] - mov qword ptr [rbp - 24], rdi - mov qword ptr [rbp - 16], rax - lea rdi, [rbp - 24] + mov qword ptr [rbp - 16], rdi + mov qword ptr [rbp - 8], rax + lea rdi, [rbp - 16] call _objc_msgSendSuper - mov rbx, rax - test rax, rax - je LBB23_2 - lea rsi, [rip + L_anon.[ID].20] - mov edx, 4 - mov rdi, rbx - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov byte ptr [rbx + rax], 42 - lea rsi, [rip + L_anon.[ID].19] - mov edx, 4 - mov rdi, rbx - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov dword ptr [rbx + rax], 43 -LBB23_2: - mov rax, rbx - add rsp, 24 - pop rbx + add rsp, 16 pop rbp ret .globl SYM(::class, 0) .p2align 4, 0x90 SYM(::class, 0): - push rbp - mov rbp, rsp - sub rsp, 16 mov rax, qword ptr [rip + SYM(::class::REGISTER_CLASS, 0)] cmp rax, 3 jne LBB24_1 -LBB24_2: - lea rdi, [rip + l_anon.[ID].16] - mov esi, 9 - call SYM(objc2::runtime::AnyClass::get::GENERATED_ID, 0) - test rax, rax - je LBB24_4 - add rsp, 16 - pop rbp + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 1).0] ret LBB24_1: + push rbp + mov rbp, rsp + sub rsp, 16 mov byte ptr [rbp - 1], 1 lea rax, [rbp - 1] mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].1] - lea r8, [rip + l_anon.[ID].28] + lea r8, [rip + l_anon.[ID].32] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) - jmp LBB24_2 -LBB24_4: - lea rdi, [rip + l_anon.[ID].11] - lea rdx, [rip + l_anon.[ID].28] - mov esi, 43 - call SYM(core::panicking::panic::GENERATED_ID, 0) - - .p2align 4, 0x90 -SYM(::class::{closure#0}::__objc2_dealloc, 0): - push rbp - mov rbp, rsp - push r14 - push rbx - sub rsp, 16 - mov rbx, rsi - mov r14, rdi - call SYM(::drop, 0) - lea rsi, [rip + L_anon.[ID].18] - mov edx, 4 - mov rdi, r14 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov rdi, qword ptr [r14 + rax] - test rdi, rdi - je LBB25_2 - call _objc_release -LBB25_2: - lea rsi, [rip + l_anon.[ID].17] - mov edx, 11 - mov rdi, r14 - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov rdi, qword ptr [r14 + rax] - test rdi, rdi - je LBB25_4 - call _objc_release -LBB25_4: - mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] - mov rax, qword ptr [rax] - mov qword ptr [rbp - 32], r14 - mov qword ptr [rbp - 24], rax - lea rdi, [rbp - 32] - mov rsi, rbx - call _objc_msgSendSuper add rsp, 16 - pop rbx - pop r14 pop rbp + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 1).0] ret .globl _init_drop_ivars @@ -799,43 +713,45 @@ LBB25_4: _init_drop_ivars: push rbp mov rbp, rsp + push r15 push r14 push rbx - sub rsp, 16 - mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] - mov rsi, qword ptr [rax] - mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] - mov rax, qword ptr [rax] - mov qword ptr [rbp - 32], rdi - mov qword ptr [rbp - 24], rax - lea rdi, [rbp - 32] - call _objc_msgSendSuper - mov rbx, rax - test rax, rax - je LBB26_2 + sub rsp, 24 + mov rbx, rdi call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) mov r14, rax - lea rsi, [rip + L_anon.[ID].18] - mov edx, 4 - mov rdi, rbx - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset - mov qword ptr [rbx + rax], r14 call SYM(objc2::runtime::nsobject::NSObject::new::GENERATED_ID, 0) - mov r14, rax - lea rsi, [rip + l_anon.[ID].17] - mov edx, 11 - mov rdi, rbx - call SYM(objc2::runtime::AnyObject::lookup_instance_variable_dynamically::GENERATED_ID, 0) - mov rdi, rax - call _ivar_getOffset + mov r15, rax + test rbx, rbx + je LBB25_2 + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)] mov qword ptr [rbx + rax], r14 -LBB26_2: - mov rax, rbx - add rsp, 16 + mov qword ptr [rbx + rax + 8], r15 + mov rax, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)] + mov byte ptr [rbx + rax], 15 + jmp LBB25_3 +LBB25_2: + mov rdi, r14 + call _objc_release + mov rdi, r15 + call _objc_release +LBB25_3: + mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32] + mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] + mov rax, qword ptr [rax] + mov qword ptr [rbp - 40], rbx + mov qword ptr [rbp - 32], rax + lea rdi, [rbp - 40] + call _objc_msgSendSuper + test rax, rax + je LBB25_5 + mov rcx, qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)] + mov byte ptr [rax + rcx], -1 +LBB25_5: + add rsp, 24 pop rbx pop r14 + pop r15 pop rbp ret @@ -908,183 +824,252 @@ l_anon.[ID].10: .space 39 l_anon.[ID].11: - .ascii "called `Option::unwrap()` on a `None` value" + .ascii "ivars" l_anon.[ID].12: - .ascii "$RUSTC/library/std/src/sync/once.rs" + .ascii "drop_flag" - .section __DATA,__const .p2align 3, 0x0 l_anon.[ID].13: - .quad l_anon.[ID].12 - .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" + .byte 5 + .space 39 - .section __TEXT,__const + .p2align 3, 0x0 l_anon.[ID].14: - .ascii "ForgetableIvars" + .byte 7 + .space 39 + .p2align 3, 0x0 l_anon.[ID].15: - .ascii "NoIvars" + .byte 9 + .space 39 l_anon.[ID].16: - .ascii "DropIvars" + .ascii "failed retrieving instance variable on newly declared class" l_anon.[ID].17: - .ascii "_obj_option" + .ascii "$WORKSPACE/objc2/src/__macro_helpers/declared_ivars.rs" - .section __TEXT,__literal4,4byte_literals -L_anon.[ID].18: - .ascii "_obj" + .section __DATA,__const + .p2align 3, 0x0 +l_anon.[ID].18: + .quad l_anon.[ID].17 + .asciz "P\000\000\000\000\000\000\000\035\001\000\000\016\000\000" -L_anon.[ID].19: - .ascii "_bar" + .section __TEXT,__const +l_anon.[ID].19: + .ascii "failed retrieving drop flag instance variable on newly declared class" -L_anon.[ID].20: - .ascii "_foo" + .section __DATA,__const + .p2align 3, 0x0 +l_anon.[ID].20: + .quad l_anon.[ID].17 + .asciz "P\000\000\000\000\000\000\000)\001\000\000\016\000\000" .section __TEXT,__const l_anon.[ID].21: + .ascii "ForgetableIvars" + +l_anon.[ID].22: + .ascii "NoIvars" + +l_anon.[ID].23: + .ascii "DropIvars" + +l_anon.[ID].24: + .ascii "called `Option::unwrap()` on a `None` value" + +l_anon.[ID].25: + .ascii "$RUSTC/library/std/src/sync/once.rs" + + .section __DATA,__const + .p2align 3, 0x0 +l_anon.[ID].26: + .quad l_anon.[ID].25 + .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" + +.zerofill __DATA,__bss,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0,8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1),8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1),8,3 + .section __TEXT,__const +l_anon.[ID].27: .ascii "crates/$DIR/lib.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].22: - .quad l_anon.[ID].21 - .asciz "5\000\000\000\000\000\000\000\017\000\000\000\001\000\000" +l_anon.[ID].28: + .quad l_anon.[ID].27 + .asciz "5\000\000\000\000\000\000\000\016\000\000\000\001\000\000" .zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .section __TEXT,__literal8,8byte_literals -L_anon.[ID].23: +L_anon.[ID].29: .ascii "NSObject" .section __TEXT,__const -l_anon.[ID].24: +l_anon.[ID].30: .ascii "NSCopying" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_f249b8b52b9a1205 -L_OBJC_METH_VAR_NAME_f249b8b52b9a1205: + .globl L_OBJC_METH_VAR_NAME_03fd85b0462f54e9 +L_OBJC_METH_VAR_NAME_03fd85b0462f54e9: .asciz "classMethod" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_f249b8b52b9a1205 + .globl L_OBJC_SELECTOR_REFERENCES_03fd85b0462f54e9 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_f249b8b52b9a1205: - .quad L_OBJC_METH_VAR_NAME_f249b8b52b9a1205 +L_OBJC_SELECTOR_REFERENCES_03fd85b0462f54e9: + .quad L_OBJC_METH_VAR_NAME_03fd85b0462f54e9 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_f249b8b52b9a1205 + .globl L_OBJC_IMAGE_INFO_03fd85b0462f54e9 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_f249b8b52b9a1205: +L_OBJC_IMAGE_INFO_03fd85b0462f54e9: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_2607fe9c3979c381 -L_OBJC_METH_VAR_NAME_2607fe9c3979c381: + .globl L_OBJC_METH_VAR_NAME_cf773331f3cfba54 +L_OBJC_METH_VAR_NAME_cf773331f3cfba54: .asciz "method" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381 + .globl L_OBJC_SELECTOR_REFERENCES_cf773331f3cfba54 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_2607fe9c3979c381: - .quad L_OBJC_METH_VAR_NAME_2607fe9c3979c381 +L_OBJC_SELECTOR_REFERENCES_cf773331f3cfba54: + .quad L_OBJC_METH_VAR_NAME_cf773331f3cfba54 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_2607fe9c3979c381 + .globl L_OBJC_IMAGE_INFO_cf773331f3cfba54 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_2607fe9c3979c381: +L_OBJC_IMAGE_INFO_cf773331f3cfba54: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_5a4952192b00de7f -L_OBJC_METH_VAR_NAME_5a4952192b00de7f: + .globl L_OBJC_METH_VAR_NAME_abdcbb85641cd990 +L_OBJC_METH_VAR_NAME_abdcbb85641cd990: .asciz "methodBool:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f + .globl L_OBJC_SELECTOR_REFERENCES_abdcbb85641cd990 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_5a4952192b00de7f: - .quad L_OBJC_METH_VAR_NAME_5a4952192b00de7f +L_OBJC_SELECTOR_REFERENCES_abdcbb85641cd990: + .quad L_OBJC_METH_VAR_NAME_abdcbb85641cd990 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_5a4952192b00de7f + .globl L_OBJC_IMAGE_INFO_abdcbb85641cd990 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_5a4952192b00de7f: +L_OBJC_IMAGE_INFO_abdcbb85641cd990: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_bf0386bc74a73c00 -L_OBJC_METH_VAR_NAME_bf0386bc74a73c00: + .globl L_OBJC_METH_VAR_NAME_ef8de92414f2d9c8 +L_OBJC_METH_VAR_NAME_ef8de92414f2d9c8: .asciz "methodId" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00 + .globl L_OBJC_SELECTOR_REFERENCES_ef8de92414f2d9c8 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_bf0386bc74a73c00: - .quad L_OBJC_METH_VAR_NAME_bf0386bc74a73c00 +L_OBJC_SELECTOR_REFERENCES_ef8de92414f2d9c8: + .quad L_OBJC_METH_VAR_NAME_ef8de92414f2d9c8 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_bf0386bc74a73c00 + .globl L_OBJC_IMAGE_INFO_ef8de92414f2d9c8 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_bf0386bc74a73c00: +L_OBJC_IMAGE_INFO_ef8de92414f2d9c8: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09 -L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09: + .globl L_OBJC_METH_VAR_NAME_4a611090161f3fae +L_OBJC_METH_VAR_NAME_4a611090161f3fae: .asciz "methodIdWithParam:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09 + .globl L_OBJC_SELECTOR_REFERENCES_4a611090161f3fae .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_6f0ab2a047fe4a09: - .quad L_OBJC_METH_VAR_NAME_6f0ab2a047fe4a09 +L_OBJC_SELECTOR_REFERENCES_4a611090161f3fae: + .quad L_OBJC_METH_VAR_NAME_4a611090161f3fae .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_6f0ab2a047fe4a09 + .globl L_OBJC_IMAGE_INFO_4a611090161f3fae .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6f0ab2a047fe4a09: +L_OBJC_IMAGE_INFO_4a611090161f3fae: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571 -L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571: + .globl L_OBJC_METH_VAR_NAME_2837f061c311eb14 +L_OBJC_METH_VAR_NAME_2837f061c311eb14: .asciz "copyWithZone:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571 + .globl L_OBJC_SELECTOR_REFERENCES_2837f061c311eb14 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_062e7a5fdd2d2571: - .quad L_OBJC_METH_VAR_NAME_062e7a5fdd2d2571 +L_OBJC_SELECTOR_REFERENCES_2837f061c311eb14: + .quad L_OBJC_METH_VAR_NAME_2837f061c311eb14 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_062e7a5fdd2d2571 + .globl L_OBJC_IMAGE_INFO_2837f061c311eb14 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_062e7a5fdd2d2571: +L_OBJC_IMAGE_INFO_2837f061c311eb14: .asciz "\000\000\000\000@\000\000" - .section __TEXT,__const +.zerofill __DATA,__bss,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 2).0,8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2),8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2),8,3 + .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].25: - .byte 5 - .space 39 +l_anon.[ID].31: + .quad l_anon.[ID].27 + .asciz "5\000\000\000\000\000\000\000O\000\000\000\001\000\000" +.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 + .section __TEXT,__objc_methname,cstring_literals + .globl L_OBJC_METH_VAR_NAME_af8966656b8b2b6c +L_OBJC_METH_VAR_NAME_af8966656b8b2b6c: + .asciz "init" + + .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip + .globl L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c .p2align 3, 0x0 -l_anon.[ID].26: - .byte 7 - .space 39 +L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c: + .quad L_OBJC_METH_VAR_NAME_af8966656b8b2b6c + + .section __DATA,__objc_imageinfo,regular,no_dead_strip + .globl L_OBJC_IMAGE_INFO_af8966656b8b2b6c + .p2align 2, 0x0 +L_OBJC_IMAGE_INFO_af8966656b8b2b6c: + .asciz "\000\000\000\000@\000\000" +.zerofill __DATA,__bss,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 1).0,8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0),8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0),8,3 .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].27: - .quad l_anon.[ID].21 - .asciz "5\000\000\000\000\000\000\000I\000\000\000\001\000\000" +l_anon.[ID].32: + .quad l_anon.[ID].27 + .asciz "5\000\000\000\000\000\000\000x\000\000\000\001\000\000" -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 +.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 + .section __TEXT,__objc_methname,cstring_literals + .globl L_OBJC_METH_VAR_NAME_6edddcebbded8f32 +L_OBJC_METH_VAR_NAME_6edddcebbded8f32: + .asciz "init" + + .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip + .globl L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32 .p2align 3, 0x0 -l_anon.[ID].28: - .quad l_anon.[ID].21 - .asciz "5\000\000\000\000\000\000\000u\000\000\000\001\000\000" +L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32: + .quad L_OBJC_METH_VAR_NAME_6edddcebbded8f32 + + .section __DATA,__objc_imageinfo,regular,no_dead_strip + .globl L_OBJC_IMAGE_INFO_6edddcebbded8f32 + .p2align 2, 0x0 +L_OBJC_IMAGE_INFO_6edddcebbded8f32: + .asciz "\000\000\000\000@\000\000" -.zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .subsections_via_symbols diff --git a/crates/test-assembly/crates/test_declare_class/lib.rs b/crates/test-assembly/crates/test_declare_class/lib.rs index 5db61d5b4..e65c67d18 100644 --- a/crates/test-assembly/crates/test_declare_class/lib.rs +++ b/crates/test-assembly/crates/test_declare_class/lib.rs @@ -7,10 +7,9 @@ use core::ptr; use icrate::Foundation::{NSCopying, NSObject, NSObjectProtocol, NSZone}; -use objc2::declare::{Ivar, IvarDrop, IvarEncode}; -use objc2::rc::Id; +use objc2::rc::{Allocated, Id}; use objc2::runtime::AnyClass; -use objc2::{declare_class, msg_send, msg_send_id, mutability, ClassType}; +use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass}; declare_class!( #[no_mangle] @@ -22,6 +21,8 @@ declare_class!( const NAME: &'static str = "NoIvars"; } + impl DeclaredClass for NoIvars {} + unsafe impl NoIvars { #[no_mangle] #[method(classMethod)] @@ -70,14 +71,14 @@ declare_class!( } ); +pub struct ForgetableIvarsIvars { + foo: u8, + bar: u32, +} + declare_class!( #[no_mangle] - pub struct ForgetableIvars { - foo: IvarEncode, - bar: IvarEncode, - } - - mod forgetable_ivars; + pub struct ForgetableIvars; unsafe impl ClassType for ForgetableIvars { type Super = NSObject; @@ -85,19 +86,16 @@ declare_class!( const NAME: &'static str = "ForgetableIvars"; } + impl DeclaredClass for ForgetableIvars { + type Ivars = ForgetableIvarsIvars; + } + unsafe impl ForgetableIvars { #[no_mangle] - #[method(init)] - unsafe fn init_forgetable_ivars(this: *mut Self) -> *mut Self { - let this: Option<&mut Self> = unsafe { msg_send![super(this), init] }; - - this.map(|this| { - Ivar::write(&mut this.foo, 42); - Ivar::write(&mut this.bar, 43); - let this: *mut Self = this; - this - }) - .unwrap_or_else(ptr::null_mut) + #[method_id(init)] + fn init_forgetable_ivars(this: Allocated) -> Option> { + let this = this.set_ivars(ForgetableIvarsIvars { foo: 42, bar: 43 }); + unsafe { msg_send_id![super(this), init] } } } ); @@ -110,18 +108,18 @@ impl ForgetableIvars { #[no_mangle] pub fn access_forgetable_ivars(&self) -> (u8, u32) { - (*self.foo, *self.bar) + (self.ivars().foo, self.ivars().bar) } } +pub struct DropIvarsIvars { + obj: Id, + obj_option: Option>, +} + declare_class!( #[no_mangle] - pub struct DropIvars { - obj: IvarDrop, "_obj">, - obj_option: IvarDrop>, "_obj_option">, - } - - mod drop_ivars; + pub struct DropIvars; unsafe impl ClassType for DropIvars { type Super = NSObject; @@ -129,19 +127,19 @@ declare_class!( const NAME: &'static str = "DropIvars"; } + impl DeclaredClass for DropIvars { + type Ivars = DropIvarsIvars; + } + unsafe impl DropIvars { #[no_mangle] - #[method(init)] - unsafe fn init_drop_ivars(this: *mut Self) -> *mut Self { - let this: Option<&mut Self> = unsafe { msg_send![super(this), init] }; - - this.map(|this| { - Ivar::write(&mut this.obj, NSObject::new()); - Ivar::write(&mut this.obj_option, Some(NSObject::new())); - let this: *mut Self = this; - this - }) - .unwrap_or_else(ptr::null_mut) + #[method_id(init)] + fn init_drop_ivars(this: Allocated) -> Option> { + let this = this.set_ivars(DropIvarsIvars { + obj: NSObject::new(), + obj_option: Some(NSObject::new()), + }); + unsafe { msg_send_id![super(this), init] } } } ); @@ -160,7 +158,14 @@ impl DropIvars { } #[no_mangle] - pub fn access_drop_ivars(&self) -> *const NSObject { - Id::as_ptr(&*self.obj) + pub fn access_drop_ivars(&self) -> (*const NSObject, *const NSObject) { + ( + Id::as_ptr(&self.ivars().obj), + self.ivars() + .obj_option + .as_ref() + .map(Id::as_ptr) + .unwrap_or_else(ptr::null), + ) } } diff --git a/crates/test-assembly/src/lib.rs b/crates/test-assembly/src/lib.rs index 23464ceaa..f5acef128 100644 --- a/crates/test-assembly/src/lib.rs +++ b/crates/test-assembly/src/lib.rs @@ -90,6 +90,7 @@ pub fn read_assembly>(path: P, package_path: &Path) -> io::Result let s = s.replace(".asciz\t\"}\\000", ".asciz\t\"p\\000"); let s = s.replace(".asciz\t\"L\\000", ".asciz\t\"p\\000"); let s = s.replace(".asciz\t\"t\\000", ".asciz\t\"p\\000"); + let s = s.replace(".asciz\t\"T\\000", ".asciz\t\"P\\000"); // HACK: Replace Objective-C image info for simulator targets let s = s.replace( diff --git a/crates/test-ui/ui/declare_class_classtype_imported.rs b/crates/test-ui/ui/declare_class_classtype_imported.rs index 7ab550cd2..6fc85f270 100644 --- a/crates/test-ui/ui/declare_class_classtype_imported.rs +++ b/crates/test-ui/ui/declare_class_classtype_imported.rs @@ -10,6 +10,8 @@ declare_class!( type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject"; } + + impl objc2::DeclaredClass for CustomObject {} ); fn main() {} diff --git a/crates/test-ui/ui/declare_class_classtype_imported.stderr b/crates/test-ui/ui/declare_class_classtype_imported.stderr index 38a59afb6..a60443068 100644 --- a/crates/test-ui/ui/declare_class_classtype_imported.stderr +++ b/crates/test-ui/ui/declare_class_classtype_imported.stderr @@ -7,5 +7,5 @@ error: no rules expected the token `objc2` note: while trying to match `ClassType` --> $WORKSPACE/crates/objc2/src/macros/declare_class.rs | - | unsafe impl ClassType for $for:ty { + | unsafe impl ClassType for $for_class:ty { | ^^^^^^^^^ diff --git a/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.rs b/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.rs index af10f877b..cb43b051e 100644 --- a/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.rs +++ b/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.rs @@ -4,7 +4,7 @@ use icrate::AppKit::{NSApplication, NSApplicationDelegate}; use icrate::Foundation::{MainThreadMarker, NSNotification, NSObject, NSObjectProtocol}; use objc2::rc::Id; use objc2::runtime::ProtocolObject; -use objc2::{declare_class, extern_methods, mutability, ClassType}; +use objc2::{declare_class, extern_methods, mutability, ClassType, DeclaredClass}; declare_class!( struct CustomObject; @@ -15,6 +15,8 @@ declare_class!( const NAME: &'static str = "CustomObject"; } + impl DeclaredClass for CustomObject {} + unsafe impl NSObjectProtocol for CustomObject {} unsafe impl NSApplicationDelegate for CustomObject { diff --git a/crates/test-ui/ui/declare_class_invalid_receiver.rs b/crates/test-ui/ui/declare_class_invalid_receiver.rs index 63ff3f45c..5cfb493f9 100644 --- a/crates/test-ui/ui/declare_class_invalid_receiver.rs +++ b/crates/test-ui/ui/declare_class_invalid_receiver.rs @@ -1,6 +1,6 @@ use objc2::rc::{Allocated, Id}; use objc2::runtime::{AnyClass, NSObject}; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; declare_class!( struct CustomObject; @@ -11,6 +11,8 @@ declare_class!( const NAME: &'static str = "CustomObject"; } + impl DeclaredClass for CustomObject {} + unsafe impl CustomObject { #[method(testBox)] fn test_box(self: Box) { diff --git a/crates/test-ui/ui/declare_class_invalid_syntax.rs b/crates/test-ui/ui/declare_class_invalid_syntax.rs index d7e38b188..e0757b960 100644 --- a/crates/test-ui/ui/declare_class_invalid_syntax.rs +++ b/crates/test-ui/ui/declare_class_invalid_syntax.rs @@ -1,9 +1,6 @@ -use std::marker::PhantomData; - -use objc2::declare::IvarEncode; use objc2::rc::Id; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; declare_class!( struct InvalidMethodDeclarations; @@ -14,6 +11,8 @@ declare_class!( const NAME: &'static str = "InvalidMethodDeclarations"; } + impl DeclaredClass for InvalidMethodDeclarations {} + unsafe impl InvalidMethodDeclarations { fn test_no_attribute() { unimplemented!() @@ -140,63 +139,27 @@ declare_class!( type Super = NSObject; type Mutability = mutability::InteriorMutable; } -); - -declare_class!( - struct InvalidField { - field: i32, - } - unsafe impl ClassType for InvalidField { - type Super = NSObject; - type Mutability = mutability::InteriorMutable; - const NAME: &'static str = "InvalidField"; - } + impl DeclaredClass for MissingName {} ); declare_class!( - struct UnnecessaryIvarModule; - - mod ivars; + struct MissingMutability; - unsafe impl ClassType for UnnecessaryIvarModule { + unsafe impl ClassType for MissingMutability { type Super = NSObject; - type Mutability = mutability::InteriorMutable; - const NAME: &'static str = "UnnecessaryIvarModule"; - } -); - -declare_class!( - struct UnnecessaryIvarModuleWithFields { - p: PhantomData, } - mod ivars; - - unsafe impl ClassType for UnnecessaryIvarModuleWithFields { - type Super = NSObject; - type Mutability = mutability::InteriorMutable; - const NAME: &'static str = "UnnecessaryIvarModuleWithFields"; - } + impl DeclaredClass for MissingMutability {} ); declare_class!( - struct MissingIvarModule { - field: IvarEncode, - } + struct MissingDeclaredClass; - unsafe impl ClassType for MissingIvarModule { + unsafe impl ClassType for MissingDeclaredClass { type Super = NSObject; type Mutability = mutability::InteriorMutable; - const NAME: &'static str = "MissingIvarModule"; - } -); - -declare_class!( - struct MissingMutability; - - unsafe impl ClassType for MissingMutability { - type Super = NSObject; + const NAME: &'static str = "MissingDeclaredClass"; } ); diff --git a/crates/test-ui/ui/declare_class_invalid_syntax.stderr b/crates/test-ui/ui/declare_class_invalid_syntax.stderr index faa2b6cee..add5de7c8 100644 --- a/crates/test-ui/ui/declare_class_invalid_syntax.stderr +++ b/crates/test-ui/ui/declare_class_invalid_syntax.stderr @@ -457,71 +457,29 @@ note: while trying to match `const` | const NAME: &'static str = $name_const:expr; | ^^^^^ -error: invalid type i32 in field field. Type must be either `PhantomData`, `IvarDrop`, `IvarBool` or `IvarEncode`. - --> ui/declare_class_invalid_syntax.rs - | - | / declare_class!( - | | struct InvalidField { - | | field: i32, - | | } -... | - | | } - | | ); - | |_^ - | - = note: this error originates in the macro `$crate::__parse_fields` which comes from the expansion of the macro `declare_class` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: no rules expected the token `mod` +error: no rules expected the token `}` --> ui/declare_class_invalid_syntax.rs | - | mod ivars; - | ^^^ no rules expected this token in macro call + | } + | ^ no rules expected this token in macro call | -note: while trying to match `unsafe` +note: while trying to match `type` --> $WORKSPACE/crates/objc2/src/macros/declare_class.rs | - | unsafe impl ClassType for $for:ty { - | ^^^^^^ - -error: no need to specify an ivar module when the type has no ivars - --> ui/declare_class_invalid_syntax.rs - | - | / declare_class!( - | | struct UnnecessaryIvarModuleWithFields { - | | p: PhantomData, - | | } -... | - | | } - | | ); - | |_^ - | - = note: this error originates in the macro `$crate::__parse_fields` which comes from the expansion of the macro `declare_class` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: must specify an ivar module when the type has ivars - --> ui/declare_class_invalid_syntax.rs - | - | / declare_class!( - | | struct MissingIvarModule { - | | field: IvarEncode, - | | } -... | - | | } - | | ); - | |_^ - | - = note: this error originates in the macro `$crate::__parse_fields` which comes from the expansion of the macro `declare_class` (in Nightly builds, run with -Z macro-backtrace for more info) + | type Mutability = $mutability:ty; + | ^^^^ -error: no rules expected the token `}` +error: unexpected end of macro invocation --> ui/declare_class_invalid_syntax.rs | | } - | ^ no rules expected this token in macro call + | ^ missing tokens in macro arguments | -note: while trying to match `type` +note: while trying to match `impl` --> $WORKSPACE/crates/objc2/src/macros/declare_class.rs | - | type Mutability = $mutability:ty; - | ^^^^ + | impl DeclaredClass for $for_declared:ty { + | ^^^^ error[E0599]: no function or associated item named `test_pattern` found for struct `InvalidMethodDeclarations` in the current scope --> ui/declare_class_invalid_syntax.rs diff --git a/crates/test-ui/ui/declare_class_invalid_type.rs b/crates/test-ui/ui/declare_class_invalid_type.rs index a34b00e1b..ce8c704bf 100644 --- a/crates/test-ui/ui/declare_class_invalid_type.rs +++ b/crates/test-ui/ui/declare_class_invalid_type.rs @@ -1,6 +1,6 @@ use objc2::rc::Id; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; declare_class!( struct CustomObject; @@ -11,6 +11,8 @@ declare_class!( const NAME: &'static str = "CustomObject"; } + impl DeclaredClass for CustomObject {} + unsafe impl CustomObject { #[method(test1)] fn test1() -> Id { diff --git a/crates/test-ui/ui/declare_class_invalid_type2.rs b/crates/test-ui/ui/declare_class_invalid_type2.rs index 18dcf5da3..fb1129632 100644 --- a/crates/test-ui/ui/declare_class_invalid_type2.rs +++ b/crates/test-ui/ui/declare_class_invalid_type2.rs @@ -1,6 +1,6 @@ use objc2::rc::{Allocated, Id}; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; declare_class!( struct CustomObject; @@ -11,6 +11,8 @@ declare_class!( const NAME: &'static str = "CustomObject"; } + impl DeclaredClass for CustomObject {} + unsafe impl CustomObject { #[method_id(initNotSameGenerics)] fn test_init_not_same_generics(this: Allocated) -> Id { diff --git a/crates/test-ui/ui/declare_class_invalid_type3.rs b/crates/test-ui/ui/declare_class_invalid_type3.rs deleted file mode 100644 index 99480de84..000000000 --- a/crates/test-ui/ui/declare_class_invalid_type3.rs +++ /dev/null @@ -1,19 +0,0 @@ -use objc2::declare::IvarEncode; -use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType}; - -declare_class!( - struct CustomObject { - field: IvarEncode<(), "_field">, - } - - mod ivars; - - unsafe impl ClassType for CustomObject { - type Super = NSObject; - type Mutability = mutability::InteriorMutable; - const NAME: &'static str = "CustomObject"; - } -); - -fn main() {} diff --git a/crates/test-ui/ui/declare_class_invalid_type3.stderr b/crates/test-ui/ui/declare_class_invalid_type3.stderr deleted file mode 100644 index 9e0f48a51..000000000 --- a/crates/test-ui/ui/declare_class_invalid_type3.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0277]: the trait bound `(): Encode` is not satisfied - --> ui/declare_class_invalid_type3.rs - | - | / declare_class!( - | | struct CustomObject { - | | field: IvarEncode<(), "_field">, - | | } -... | - | | } - | | ); - | |_^ the trait `Encode` is not implemented for `()` - | - = help: the following other types implement trait `Encode`: - isize - i8 - i16 - i32 - i64 - usize - u8 - u16 - and $N others - = note: required for `objc2::declare::IvarEncode<()>` to implement `InnerIvarType` -note: required by a bound in `objc2::declare::IvarType::Type` - --> $WORKSPACE/crates/objc2/src/declare/ivar.rs - | - | type Type: InnerIvarType; - | ^^^^^^^^^^^^^ required by this bound in `IvarType::Type` - = note: this error originates in the macro `$crate::__parse_fields` which comes from the expansion of the macro `declare_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/declare_class_mut_self_not_mutable.rs b/crates/test-ui/ui/declare_class_mut_self_not_mutable.rs index 96d865f7d..9505f8775 100644 --- a/crates/test-ui/ui/declare_class_mut_self_not_mutable.rs +++ b/crates/test-ui/ui/declare_class_mut_self_not_mutable.rs @@ -1,6 +1,6 @@ use objc2::rc::Id; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; declare_class!( struct CustomObject; @@ -11,6 +11,8 @@ declare_class!( const NAME: &'static str = "CustomObject"; } + impl DeclaredClass for CustomObject {} + unsafe impl CustomObject { #[method(initTest)] fn init_test(&mut self) -> &mut Self { diff --git a/crates/test-ui/ui/implement_protocol_missing_super.rs b/crates/test-ui/ui/implement_protocol_missing_super.rs index 7e2fd36ad..dbb131610 100644 --- a/crates/test-ui/ui/implement_protocol_missing_super.rs +++ b/crates/test-ui/ui/implement_protocol_missing_super.rs @@ -2,7 +2,7 @@ //! protocols like `NSObjectProtocol` to also be implemented. use icrate::AppKit::NSApplicationDelegate; use icrate::Foundation::NSObject; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; declare_class!( struct CustomObject; @@ -13,6 +13,8 @@ declare_class!( const NAME: &'static str = "CustomObject"; } + impl DeclaredClass for CustomObject {} + unsafe impl NSApplicationDelegate for CustomObject {} ); diff --git a/crates/test-ui/ui/main_thread_only_not_allocable.rs b/crates/test-ui/ui/main_thread_only_not_allocable.rs index 2b67f131a..b5b2a6f58 100644 --- a/crates/test-ui/ui/main_thread_only_not_allocable.rs +++ b/crates/test-ui/ui/main_thread_only_not_allocable.rs @@ -1,5 +1,5 @@ use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; declare_class!( struct MyMainThreadOnlyClass; @@ -9,6 +9,8 @@ declare_class!( type Mutability = mutability::MainThreadOnly; const NAME: &'static str = "MyMainThreadOnlyClass"; } + + impl DeclaredClass for MyMainThreadOnlyClass {} ); fn main() { diff --git a/crates/test-ui/ui/msg_send_missing_comma.rs b/crates/test-ui/ui/msg_send_missing_comma.rs index e23c4fe87..7e7d2a0c9 100644 --- a/crates/test-ui/ui/msg_send_missing_comma.rs +++ b/crates/test-ui/ui/msg_send_missing_comma.rs @@ -12,5 +12,7 @@ fn main() { unsafe { msg_send_bool![obj, c:obj d:obj] }; + let _: Id = unsafe { msg_send_id![super(obj), e:obj f:obj] }; + let _: Id = unsafe { msg_send_id![super(obj, NSString::class()), e:obj f:obj] }; let _: Id = unsafe { msg_send_id![obj, e:obj f:obj] }; } diff --git a/crates/test-ui/ui/msg_send_missing_comma.stderr b/crates/test-ui/ui/msg_send_missing_comma.stderr index 0b1c55abb..c49284a9f 100644 --- a/crates/test-ui/ui/msg_send_missing_comma.stderr +++ b/crates/test-ui/ui/msg_send_missing_comma.stderr @@ -49,6 +49,24 @@ error: use of deprecated function `main::__msg_send_missing_comma`: using msg_se | = note: this error originates in the macro `$crate::__comma_between_args_inner` which comes from the expansion of the macro `msg_send_bool` (in Nightly builds, run with -Z macro-backtrace for more info) +error: use of deprecated function `main::__msg_send_missing_comma`: using msg_send_id! without a comma between arguments is technically not valid macro syntax, and may break in a future version of Rust. You should use the following instead: + msg_send_id![super(obj), e: obj, f: obj] + --> ui/msg_send_missing_comma.rs + | + | let _: Id = unsafe { msg_send_id![super(obj), e:obj f:obj] }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::__comma_between_args_inner` which comes from the expansion of the macro `msg_send_id` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of deprecated function `main::__msg_send_missing_comma`: using msg_send_id! without a comma between arguments is technically not valid macro syntax, and may break in a future version of Rust. You should use the following instead: + msg_send_id![super(obj, NSString::class()), e: obj, f: obj] + --> ui/msg_send_missing_comma.rs + | + | let _: Id = unsafe { msg_send_id![super(obj, NSString::class()), e:obj f:obj] }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::__comma_between_args_inner` which comes from the expansion of the macro `msg_send_id` (in Nightly builds, run with -Z macro-backtrace for more info) + error: use of deprecated function `main::__msg_send_missing_comma`: using msg_send_id! without a comma between arguments is technically not valid macro syntax, and may break in a future version of Rust. You should use the following instead: msg_send_id![obj, e: obj, f: obj] --> ui/msg_send_missing_comma.rs diff --git a/crates/test-ui/ui/mutability_traits_unimplementable.rs b/crates/test-ui/ui/mutability_traits_unimplementable.rs index 96fe63505..8eedc6be9 100644 --- a/crates/test-ui/ui/mutability_traits_unimplementable.rs +++ b/crates/test-ui/ui/mutability_traits_unimplementable.rs @@ -1,6 +1,6 @@ //! Check that `mutability` traits are not implementable manually. use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType}; +use objc2::{declare_class, mutability, ClassType, DeclaredClass}; declare_class!( struct CustomObject; @@ -10,6 +10,8 @@ declare_class!( type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject"; } + + impl DeclaredClass for CustomObject {} ); unsafe impl mutability::IsMutable for CustomObject {} diff --git a/crates/test-ui/ui/wrong_optional.rs b/crates/test-ui/ui/wrong_optional.rs index 78203d187..721a430aa 100644 --- a/crates/test-ui/ui/wrong_optional.rs +++ b/crates/test-ui/ui/wrong_optional.rs @@ -1,6 +1,6 @@ use objc2::rc::Id; use objc2::runtime::NSObject; -use objc2::{declare_class, extern_class, extern_methods, mutability, ClassType}; +use objc2::{declare_class, extern_class, extern_methods, mutability, ClassType, DeclaredClass}; extern_class!( pub struct MyObject; @@ -38,6 +38,8 @@ declare_class!( const NAME: &'static str = "CustomObject1"; } + impl DeclaredClass for CustomObject1 {} + unsafe impl CustomObject1 { #[method(c)] #[optional] @@ -55,6 +57,8 @@ declare_class!( const NAME: &'static str = "CustomObject2"; } + impl DeclaredClass for CustomObject2 {} + unsafe impl CustomObject2 { #[optional] /// Doc comment diff --git a/crates/tests/src/test_declare_class_protocol.rs b/crates/tests/src/test_declare_class_protocol.rs index e408e296a..1a1c9cd67 100644 --- a/crates/tests/src/test_declare_class_protocol.rs +++ b/crates/tests/src/test_declare_class_protocol.rs @@ -3,7 +3,7 @@ use icrate::Foundation::NSCopying; use objc2::mutability::Immutable; use objc2::rc::Id; use objc2::runtime::{NSObject, NSZone}; -use objc2::{declare_class, ClassType, ProtocolType}; +use objc2::{declare_class, ClassType, DeclaredClass, ProtocolType}; #[test] #[should_panic = "could not create new class TestDeclareClassDuplicate. Perhaps a class with that name already exists?"] @@ -16,6 +16,8 @@ fn test_declare_class_duplicate() { type Mutability = Immutable; const NAME: &'static str = "TestDeclareClassDuplicate"; } + + impl DeclaredClass for Custom1 {} ); declare_class!( @@ -26,6 +28,8 @@ fn test_declare_class_duplicate() { type Mutability = Immutable; const NAME: &'static str = "TestDeclareClassDuplicate"; } + + impl DeclaredClass for Custom2 {} ); let _cls = Custom1::class(); @@ -44,6 +48,8 @@ fn test_declare_class_protocol() { const NAME: &'static str = "TestDeclareClassProtocolNotFound"; } + impl DeclaredClass for Custom {} + unsafe impl NSCopying for Custom { #[method_id(copyWithZone:)] fn copy_with_zone(&self, _zone: *const NSZone) -> Id { @@ -71,6 +77,8 @@ fn test_declare_class_invalid_method() { const NAME: &'static str = "TestDeclareClassInvalidMethod"; } + impl DeclaredClass for Custom {} + unsafe impl Custom { // Override `description` with a bad return type #[method(description)] @@ -96,6 +104,8 @@ fn test_declare_class_missing_protocol_method() { const NAME: &'static str = "TestDeclareClassMissingProtocolMethod"; } + impl DeclaredClass for Custom {} + unsafe impl NSCopying for Custom { // Missing required method } @@ -116,6 +126,8 @@ fn test_declare_class_invalid_protocol_method() { const NAME: &'static str = "TestDeclareClassInvalidProtocolMethod"; } + impl DeclaredClass for Custom {} + unsafe impl NSCopying for Custom { // Override with a bad return type #[method(copyWithZone:)] @@ -143,6 +155,8 @@ fn test_declare_class_extra_protocol_method() { const NAME: &'static str = "TestDeclareClassExtraProtocolMethod"; } + impl DeclaredClass for Custom {} + unsafe impl NSCopying for Custom { #[method_id(copyWithZone:)] fn copy_with_zone(&self, _zone: *const NSZone) -> Id { From d3e76f64492b1096f47c2153a6ea8f3bafe292b3 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 27 Oct 2023 01:28:56 +0200 Subject: [PATCH 4/6] Refactor how existence of ivars is stored --- crates/objc2/src/macros/declare_class.rs | 38 +- .../expected/apple-aarch64.s | 627 +++++++++--------- .../expected/apple-x86_64.s | 17 +- 3 files changed, 345 insertions(+), 337 deletions(-) diff --git a/crates/objc2/src/macros/declare_class.rs b/crates/objc2/src/macros/declare_class.rs index abacd8904..db9d073a2 100644 --- a/crates/objc2/src/macros/declare_class.rs +++ b/crates/objc2/src/macros/declare_class.rs @@ -452,8 +452,12 @@ macro_rules! declare_class { // before any access to the variables. unsafe { __OBJC2_CLASS.write(__objc2_cls); - __OBJC2_IVAR_OFFSET.write(__objc2_ivar_offset); - __OBJC2_DROP_FLAG_OFFSET.write(__objc2_drop_flag_offset); + if ::HAS_IVARS { + __OBJC2_IVAR_OFFSET.write(__objc2_ivar_offset); + } + if ::HAS_DROP_FLAG { + __OBJC2_DROP_FLAG_OFFSET.write(__objc2_drop_flag_offset); + } } }); @@ -477,15 +481,35 @@ macro_rules! declare_class { #[inline] fn __ivars_offset() -> $crate::__macro_helpers::isize { - // SAFETY: Accessing the offset is guaranteed to only be - // done after the class has been initialized. - unsafe { __OBJC2_IVAR_OFFSET.assume_init() } + // Only access ivar offset if we have an ivar. + // + // This makes the offset not be included in the final + // executable if it's not needed. + if ::HAS_IVARS { + // SAFETY: Accessing the offset is guaranteed to only be + // done after the class has been initialized. + unsafe { __OBJC2_IVAR_OFFSET.assume_init() } + } else { + // Fall back to an offset of zero. + // + // This is fine, since any reads here will only be via. zero-sized + // ivars, where the actual pointer doesn't matter. + 0 + } } #[inline] fn __drop_flag_offset() -> $crate::__macro_helpers::isize { - // SAFETY: Same as above. - unsafe { __OBJC2_DROP_FLAG_OFFSET.assume_init() } + if ::HAS_DROP_FLAG { + // SAFETY: Same as above. + unsafe { __OBJC2_DROP_FLAG_OFFSET.assume_init() } + } else { + // Fall back to an offset of zero. + // + // This is fine, since the drop flag is never actually used in the + // cases where it was not added. + 0 + } } // SAFETY: The offsets are implemented correctly diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s index 9a27ca44c..073ed1d6f 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s @@ -211,39 +211,32 @@ Lloh53: bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) ldr x0, [sp, #8] bl SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) -Lloh54: adrp x8, __MergedGlobals@PAGE str x0, [x8, __MergedGlobals@PAGEOFF] -Lloh55: - adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1)@PAGE - str xzr, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1)@PAGEOFF] -Lloh56: - adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1)@PAGE - str xzr, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1)@PAGEOFF] ldp x29, x30, [sp, #48] ldp x20, x19, [sp, #32] ldp x22, x21, [sp, #16] add sp, sp, #64 ret LBB4_7: -Lloh57: +Lloh54: adrp x0, l_anon.[ID].24@PAGE -Lloh58: +Lloh55: add x0, x0, l_anon.[ID].24@PAGEOFF -Lloh59: +Lloh56: adrp x2, l_anon.[ID].26@PAGE -Lloh60: +Lloh57: add x2, x2, l_anon.[ID].26@PAGEOFF mov w1, #43 bl SYM(core::panicking::panic::GENERATED_ID, 0) LBB4_8: -Lloh61: +Lloh58: adrp x0, l_anon.[ID].22@PAGE -Lloh62: +Lloh59: add x0, x0, l_anon.[ID].22@PAGEOFF -Lloh63: +Lloh60: adrp x2, l_anon.[ID].28@PAGE -Lloh64: +Lloh61: add x2, x2, l_anon.[ID].28@PAGEOFF mov w1, #7 bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) @@ -266,16 +259,14 @@ Lloh64: .loh AdrpAdd Lloh14, Lloh15 .loh AdrpLdr Lloh12, Lloh13 .loh AdrpAdd Lloh44, Lloh45 - .loh AdrpAdrp Lloh55, Lloh56 - .loh AdrpAdrp Lloh54, Lloh55 .loh AdrpAdd Lloh52, Lloh53 .loh AdrpAdd Lloh50, Lloh51 .loh AdrpAdd Lloh48, Lloh49 .loh AdrpLdr Lloh46, Lloh47 - .loh AdrpAdd Lloh59, Lloh60 - .loh AdrpAdd Lloh57, Lloh58 - .loh AdrpAdd Lloh63, Lloh64 - .loh AdrpAdd Lloh61, Lloh62 + .loh AdrpAdd Lloh56, Lloh57 + .loh AdrpAdd Lloh54, Lloh55 + .loh AdrpAdd Lloh60, Lloh61 + .loh AdrpAdd Lloh58, Lloh59 .p2align 2 SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): @@ -287,37 +278,37 @@ SYM(::call_once::<, 0)@PAGE -Lloh78: +Lloh75: add x5, x5, SYM(objc2[CRATE_ID]::__macro_helpers::declared_ivars::dealloc::, 0)@PAGEOFF add x0, sp, #24 mov x2, x19 @@ -325,19 +316,19 @@ Lloh78: bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) ldr x8, [sp, #24] str x8, [sp, #8] -Lloh79: +Lloh76: adrp x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGE -Lloh80: +Lloh77: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_init@GOTPAGEOFF] -Lloh81: +Lloh78: ldr x1, [x8] -Lloh82: +Lloh79: adrp x4, l_anon.[ID].4@PAGE -Lloh83: +Lloh80: add x4, x4, l_anon.[ID].4@PAGEOFF -Lloh84: +Lloh81: adrp x5, _init_drop_ivars@PAGE -Lloh85: +Lloh82: add x5, x5, _init_drop_ivars@PAGEOFF add x0, sp, #8 mov x2, x19 @@ -346,16 +337,16 @@ Lloh85: ldr x8, [sp, #8] str x8, [sp, #16] mov w8, #16 -Lloh86: +Lloh83: adrp x9, l_anon.[ID].15@PAGE -Lloh87: +Lloh84: add x9, x9, l_anon.[ID].15@PAGEOFF stp x8, x9, [sp, #32] mov w8, #27 strb w8, [sp, #24] -Lloh88: +Lloh85: adrp x20, l_anon.[ID].11@PAGE -Lloh89: +Lloh86: add x20, x20, l_anon.[ID].11@PAGEOFF add x0, sp, #16 add x5, sp, #24 @@ -364,13 +355,13 @@ Lloh89: mov w3, #16 mov w4, #3 bl SYM(objc2::declare::ClassBuilder::add_ivar_inner_mono::GENERATED_ID, 0) -Lloh90: +Lloh87: adrp x1, l_anon.[ID].12@PAGE -Lloh91: +Lloh88: add x1, x1, l_anon.[ID].12@PAGEOFF -Lloh92: +Lloh89: adrp x5, l_anon.[ID].13@PAGE -Lloh93: +Lloh90: add x5, x5, l_anon.[ID].13@PAGEOFF add x0, sp, #16 mov w2, #9 @@ -386,22 +377,22 @@ Lloh93: cbz x0, LBB5_7 bl _ivar_getOffset mov x20, x0 -Lloh94: +Lloh91: adrp x1, l_anon.[ID].12@PAGE -Lloh95: +Lloh92: add x1, x1, l_anon.[ID].12@PAGEOFF mov x0, x19 mov w2, #9 bl SYM(objc2::runtime::AnyClass::instance_variable::GENERATED_ID, 0) cbz x0, LBB5_8 bl _ivar_getOffset -Lloh96: +Lloh93: adrp x8, __MergedGlobals@PAGE+32 str x19, [x8, __MergedGlobals@PAGEOFF+32] -Lloh97: +Lloh94: adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE str x20, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] -Lloh98: +Lloh95: adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGE str x0, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGEOFF] ldp x29, x30, [sp, #80] @@ -409,73 +400,73 @@ Lloh98: add sp, sp, #96 ret LBB5_5: -Lloh99: +Lloh96: adrp x0, l_anon.[ID].24@PAGE -Lloh100: +Lloh97: add x0, x0, l_anon.[ID].24@PAGEOFF -Lloh101: +Lloh98: adrp x2, l_anon.[ID].26@PAGE -Lloh102: +Lloh99: add x2, x2, l_anon.[ID].26@PAGEOFF mov w1, #43 bl SYM(core::panicking::panic::GENERATED_ID, 0) LBB5_6: -Lloh103: +Lloh100: adrp x0, l_anon.[ID].23@PAGE -Lloh104: +Lloh101: add x0, x0, l_anon.[ID].23@PAGEOFF -Lloh105: +Lloh102: adrp x2, l_anon.[ID].32@PAGE -Lloh106: +Lloh103: add x2, x2, l_anon.[ID].32@PAGEOFF mov w1, #9 bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) LBB5_7: -Lloh107: +Lloh104: adrp x0, l_anon.[ID].16@PAGE -Lloh108: +Lloh105: add x0, x0, l_anon.[ID].16@PAGEOFF -Lloh109: +Lloh106: adrp x2, l_anon.[ID].18@PAGE -Lloh110: +Lloh107: add x2, x2, l_anon.[ID].18@PAGEOFF mov w1, #59 bl SYM(core::option::expect_failed::GENERATED_ID, 0) LBB5_8: -Lloh111: +Lloh108: adrp x0, l_anon.[ID].19@PAGE -Lloh112: +Lloh109: add x0, x0, l_anon.[ID].19@PAGEOFF -Lloh113: +Lloh110: adrp x2, l_anon.[ID].20@PAGE -Lloh114: +Lloh111: add x2, x2, l_anon.[ID].20@PAGEOFF mov w1, #69 bl SYM(core::option::expect_failed::GENERATED_ID, 0) - .loh AdrpAdd Lloh68, Lloh69 - .loh AdrpLdrGotLdr Lloh65, Lloh66, Lloh67 - .loh AdrpAdd Lloh92, Lloh93 - .loh AdrpAdd Lloh90, Lloh91 - .loh AdrpAdd Lloh88, Lloh89 - .loh AdrpAdd Lloh86, Lloh87 - .loh AdrpAdd Lloh84, Lloh85 - .loh AdrpAdd Lloh82, Lloh83 - .loh AdrpLdrGotLdr Lloh79, Lloh80, Lloh81 - .loh AdrpAdd Lloh77, Lloh78 - .loh AdrpAdd Lloh75, Lloh76 - .loh AdrpAdd Lloh73, Lloh74 - .loh AdrpLdrGotLdr Lloh70, Lloh71, Lloh72 - .loh AdrpAdd Lloh94, Lloh95 - .loh AdrpAdrp Lloh97, Lloh98 - .loh AdrpAdrp Lloh96, Lloh97 - .loh AdrpAdd Lloh101, Lloh102 - .loh AdrpAdd Lloh99, Lloh100 - .loh AdrpAdd Lloh105, Lloh106 - .loh AdrpAdd Lloh103, Lloh104 - .loh AdrpAdd Lloh109, Lloh110 - .loh AdrpAdd Lloh107, Lloh108 - .loh AdrpAdd Lloh113, Lloh114 - .loh AdrpAdd Lloh111, Lloh112 + .loh AdrpAdd Lloh65, Lloh66 + .loh AdrpLdrGotLdr Lloh62, Lloh63, Lloh64 + .loh AdrpAdd Lloh89, Lloh90 + .loh AdrpAdd Lloh87, Lloh88 + .loh AdrpAdd Lloh85, Lloh86 + .loh AdrpAdd Lloh83, Lloh84 + .loh AdrpAdd Lloh81, Lloh82 + .loh AdrpAdd Lloh79, Lloh80 + .loh AdrpLdrGotLdr Lloh76, Lloh77, Lloh78 + .loh AdrpAdd Lloh74, Lloh75 + .loh AdrpAdd Lloh72, Lloh73 + .loh AdrpAdd Lloh70, Lloh71 + .loh AdrpLdrGotLdr Lloh67, Lloh68, Lloh69 + .loh AdrpAdd Lloh91, Lloh92 + .loh AdrpAdrp Lloh94, Lloh95 + .loh AdrpAdrp Lloh93, Lloh94 + .loh AdrpAdd Lloh98, Lloh99 + .loh AdrpAdd Lloh96, Lloh97 + .loh AdrpAdd Lloh102, Lloh103 + .loh AdrpAdd Lloh100, Lloh101 + .loh AdrpAdd Lloh106, Lloh107 + .loh AdrpAdd Lloh104, Lloh105 + .loh AdrpAdd Lloh110, Lloh111 + .loh AdrpAdd Lloh108, Lloh109 .p2align 2 SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): @@ -487,37 +478,37 @@ SYM(::call_once::<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): @@ -656,16 +643,16 @@ SYM(<::call_once<::drop, 0) .p2align 2 @@ -728,16 +715,16 @@ SYM( .globl _access_drop_ivars_class .p2align 2 _access_drop_ivars_class: -Lloh162: +Lloh158: adrp x8, __MergedGlobals@PAGE+40 -Lloh163: +Lloh159: add x8, x8, __MergedGlobals@PAGEOFF+40 ldapr x8, [x8] cmp x8, #3 b.ne LBB13_2 -Lloh164: +Lloh160: adrp x8, __MergedGlobals@PAGE+32 -Lloh165: +Lloh161: ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret LBB13_2: @@ -748,60 +735,60 @@ LBB13_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh166: +Lloh162: adrp x0, __MergedGlobals@PAGE+40 -Lloh167: +Lloh163: add x0, x0, __MergedGlobals@PAGEOFF+40 -Lloh168: +Lloh164: adrp x3, l_anon.[ID].1@PAGE -Lloh169: +Lloh165: add x3, x3, l_anon.[ID].1@PAGEOFF -Lloh170: +Lloh166: adrp x4, l_anon.[ID].32@PAGE -Lloh171: +Lloh167: add x4, x4, l_anon.[ID].32@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh172: +Lloh168: adrp x8, __MergedGlobals@PAGE+32 -Lloh173: +Lloh169: ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret - .loh AdrpAdd Lloh162, Lloh163 - .loh AdrpLdr Lloh164, Lloh165 - .loh AdrpLdr Lloh172, Lloh173 - .loh AdrpAdd Lloh170, Lloh171 - .loh AdrpAdd Lloh168, Lloh169 + .loh AdrpAdd Lloh158, Lloh159 + .loh AdrpLdr Lloh160, Lloh161 + .loh AdrpLdr Lloh168, Lloh169 .loh AdrpAdd Lloh166, Lloh167 + .loh AdrpAdd Lloh164, Lloh165 + .loh AdrpAdd Lloh162, Lloh163 .globl _access_drop_ivars .p2align 2 _access_drop_ivars: -Lloh174: +Lloh170: adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE -Lloh175: +Lloh171: ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] add x8, x0, x8 ldp x0, x1, [x8] ret - .loh AdrpLdr Lloh174, Lloh175 + .loh AdrpLdr Lloh170, Lloh171 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): -Lloh176: +Lloh172: adrp x8, __MergedGlobals@PAGE+8 -Lloh177: +Lloh173: add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 b.ne LBB15_2 -Lloh178: +Lloh174: adrp x8, __MergedGlobals@PAGE -Lloh179: +Lloh175: ldr x0, [x8, __MergedGlobals@PAGEOFF] ret LBB15_2: @@ -812,48 +799,48 @@ LBB15_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh180: +Lloh176: adrp x0, __MergedGlobals@PAGE+8 -Lloh181: +Lloh177: add x0, x0, __MergedGlobals@PAGEOFF+8 -Lloh182: +Lloh178: adrp x3, l_anon.[ID].0@PAGE -Lloh183: +Lloh179: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh184: +Lloh180: adrp x4, l_anon.[ID].28@PAGE -Lloh185: +Lloh181: add x4, x4, l_anon.[ID].28@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh186: +Lloh182: adrp x8, __MergedGlobals@PAGE -Lloh187: +Lloh183: ldr x0, [x8, __MergedGlobals@PAGEOFF] ret - .loh AdrpAdd Lloh176, Lloh177 - .loh AdrpLdr Lloh178, Lloh179 - .loh AdrpLdr Lloh186, Lloh187 - .loh AdrpAdd Lloh184, Lloh185 - .loh AdrpAdd Lloh182, Lloh183 + .loh AdrpAdd Lloh172, Lloh173 + .loh AdrpLdr Lloh174, Lloh175 + .loh AdrpLdr Lloh182, Lloh183 .loh AdrpAdd Lloh180, Lloh181 + .loh AdrpAdd Lloh178, Lloh179 + .loh AdrpAdd Lloh176, Lloh177 .globl _get_class .p2align 2 _get_class: -Lloh188: +Lloh184: adrp x8, __MergedGlobals@PAGE+8 -Lloh189: +Lloh185: add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 b.ne LBB16_2 -Lloh190: +Lloh186: adrp x8, __MergedGlobals@PAGE -Lloh191: +Lloh187: ldr x0, [x8, __MergedGlobals@PAGEOFF] ret LBB16_2: @@ -864,34 +851,34 @@ LBB16_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh192: +Lloh188: adrp x0, __MergedGlobals@PAGE+8 -Lloh193: +Lloh189: add x0, x0, __MergedGlobals@PAGEOFF+8 -Lloh194: +Lloh190: adrp x3, l_anon.[ID].0@PAGE -Lloh195: +Lloh191: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh196: +Lloh192: adrp x4, l_anon.[ID].28@PAGE -Lloh197: +Lloh193: add x4, x4, l_anon.[ID].28@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh198: +Lloh194: adrp x8, __MergedGlobals@PAGE -Lloh199: +Lloh195: ldr x0, [x8, __MergedGlobals@PAGEOFF] ret - .loh AdrpAdd Lloh188, Lloh189 - .loh AdrpLdr Lloh190, Lloh191 - .loh AdrpLdr Lloh198, Lloh199 - .loh AdrpAdd Lloh196, Lloh197 - .loh AdrpAdd Lloh194, Lloh195 + .loh AdrpAdd Lloh184, Lloh185 + .loh AdrpLdr Lloh186, Lloh187 + .loh AdrpLdr Lloh194, Lloh195 .loh AdrpAdd Lloh192, Lloh193 + .loh AdrpAdd Lloh190, Lloh191 + .loh AdrpAdd Lloh188, Lloh189 .globl _method_simple .p2align 2 @@ -910,23 +897,23 @@ _method_id: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh200: +Lloh196: adrp x8, __MergedGlobals@PAGE+8 -Lloh201: +Lloh197: add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 b.ne LBB19_2 LBB19_1: -Lloh202: +Lloh198: adrp x8, __MergedGlobals@PAGE -Lloh203: +Lloh199: ldr x0, [x8, __MergedGlobals@PAGEOFF] -Lloh204: +Lloh200: adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE -Lloh205: +Lloh201: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] -Lloh206: +Lloh202: ldr x1, [x8] bl _objc_msgSend bl _objc_autoreleaseReturnValue @@ -938,29 +925,29 @@ LBB19_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh207: +Lloh203: adrp x0, __MergedGlobals@PAGE+8 -Lloh208: +Lloh204: add x0, x0, __MergedGlobals@PAGEOFF+8 -Lloh209: +Lloh205: adrp x3, l_anon.[ID].0@PAGE -Lloh210: +Lloh206: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh211: +Lloh207: adrp x4, l_anon.[ID].28@PAGE -Lloh212: +Lloh208: add x4, x4, l_anon.[ID].28@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) b LBB19_1 - .loh AdrpAdd Lloh200, Lloh201 - .loh AdrpLdrGotLdr Lloh204, Lloh205, Lloh206 - .loh AdrpAdrp Lloh202, Lloh204 - .loh AdrpLdr Lloh202, Lloh203 - .loh AdrpAdd Lloh211, Lloh212 - .loh AdrpAdd Lloh209, Lloh210 + .loh AdrpAdd Lloh196, Lloh197 + .loh AdrpLdrGotLdr Lloh200, Lloh201, Lloh202 + .loh AdrpAdrp Lloh198, Lloh200 + .loh AdrpLdr Lloh198, Lloh199 .loh AdrpAdd Lloh207, Lloh208 + .loh AdrpAdd Lloh205, Lloh206 + .loh AdrpAdd Lloh203, Lloh204 .globl _method_id_with_param .p2align 2 @@ -989,23 +976,23 @@ _copyWithZone: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh213: +Lloh209: adrp x8, __MergedGlobals@PAGE+8 -Lloh214: +Lloh210: add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 b.ne LBB21_2 LBB21_1: -Lloh215: +Lloh211: adrp x8, __MergedGlobals@PAGE -Lloh216: +Lloh212: ldr x0, [x8, __MergedGlobals@PAGEOFF] -Lloh217: +Lloh213: adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE -Lloh218: +Lloh214: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] -Lloh219: +Lloh215: ldr x1, [x8] bl _objc_msgSend ldp x29, x30, [sp, #16] @@ -1016,43 +1003,43 @@ LBB21_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh220: +Lloh216: adrp x0, __MergedGlobals@PAGE+8 -Lloh221: +Lloh217: add x0, x0, __MergedGlobals@PAGEOFF+8 -Lloh222: +Lloh218: adrp x3, l_anon.[ID].0@PAGE -Lloh223: +Lloh219: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh224: +Lloh220: adrp x4, l_anon.[ID].28@PAGE -Lloh225: +Lloh221: add x4, x4, l_anon.[ID].28@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) b LBB21_1 - .loh AdrpAdd Lloh213, Lloh214 - .loh AdrpLdrGotLdr Lloh217, Lloh218, Lloh219 - .loh AdrpAdrp Lloh215, Lloh217 - .loh AdrpLdr Lloh215, Lloh216 - .loh AdrpAdd Lloh224, Lloh225 - .loh AdrpAdd Lloh222, Lloh223 + .loh AdrpAdd Lloh209, Lloh210 + .loh AdrpLdrGotLdr Lloh213, Lloh214, Lloh215 + .loh AdrpAdrp Lloh211, Lloh213 + .loh AdrpLdr Lloh211, Lloh212 .loh AdrpAdd Lloh220, Lloh221 + .loh AdrpAdd Lloh218, Lloh219 + .loh AdrpAdd Lloh216, Lloh217 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): -Lloh226: +Lloh222: adrp x8, __MergedGlobals@PAGE+24 -Lloh227: +Lloh223: add x8, x8, __MergedGlobals@PAGEOFF+24 ldapr x8, [x8] cmp x8, #3 b.ne LBB22_2 -Lloh228: +Lloh224: adrp x8, __MergedGlobals@PAGE+16 -Lloh229: +Lloh225: ldr x0, [x8, __MergedGlobals@PAGEOFF+16] ret LBB22_2: @@ -1063,43 +1050,43 @@ LBB22_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh230: +Lloh226: adrp x0, __MergedGlobals@PAGE+24 -Lloh231: +Lloh227: add x0, x0, __MergedGlobals@PAGEOFF+24 -Lloh232: +Lloh228: adrp x3, l_anon.[ID].2@PAGE -Lloh233: +Lloh229: add x3, x3, l_anon.[ID].2@PAGEOFF -Lloh234: +Lloh230: adrp x4, l_anon.[ID].31@PAGE -Lloh235: +Lloh231: add x4, x4, l_anon.[ID].31@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh236: +Lloh232: adrp x8, __MergedGlobals@PAGE+16 -Lloh237: +Lloh233: ldr x0, [x8, __MergedGlobals@PAGEOFF+16] ret - .loh AdrpAdd Lloh226, Lloh227 - .loh AdrpLdr Lloh228, Lloh229 - .loh AdrpLdr Lloh236, Lloh237 - .loh AdrpAdd Lloh234, Lloh235 - .loh AdrpAdd Lloh232, Lloh233 + .loh AdrpAdd Lloh222, Lloh223 + .loh AdrpLdr Lloh224, Lloh225 + .loh AdrpLdr Lloh232, Lloh233 .loh AdrpAdd Lloh230, Lloh231 + .loh AdrpAdd Lloh228, Lloh229 + .loh AdrpAdd Lloh226, Lloh227 .globl _init_forgetable_ivars .p2align 2 _init_forgetable_ivars: cbz x0, LBB23_2 -Lloh238: - adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)@PAGE -Lloh239: - ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2)@PAGEOFF] +Lloh234: + adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1)@PAGE +Lloh235: + ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1)@PAGEOFF] add x8, x0, x8 mov w9, #43 str w9, [x8] @@ -1109,15 +1096,15 @@ LBB23_2: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh240: +Lloh236: adrp x8, L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c@PAGE -Lloh241: +Lloh237: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c@PAGEOFF] -Lloh242: +Lloh238: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh243: +Lloh239: ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh244: +Lloh240: ldr x8, [x8] stp x0, x8, [sp] mov x0, sp @@ -1125,24 +1112,24 @@ Lloh244: ldp x29, x30, [sp, #16] add sp, sp, #32 ret - .loh AdrpLdr Lloh238, Lloh239 - .loh AdrpLdrGotLdr Lloh242, Lloh243, Lloh244 - .loh AdrpAdrp Lloh240, Lloh242 - .loh AdrpLdr Lloh240, Lloh241 + .loh AdrpLdr Lloh234, Lloh235 + .loh AdrpLdrGotLdr Lloh238, Lloh239, Lloh240 + .loh AdrpAdrp Lloh236, Lloh238 + .loh AdrpLdr Lloh236, Lloh237 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): -Lloh245: +Lloh241: adrp x8, __MergedGlobals@PAGE+40 -Lloh246: +Lloh242: add x8, x8, __MergedGlobals@PAGEOFF+40 ldapr x8, [x8] cmp x8, #3 b.ne LBB24_2 -Lloh247: +Lloh243: adrp x8, __MergedGlobals@PAGE+32 -Lloh248: +Lloh244: ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret LBB24_2: @@ -1153,34 +1140,34 @@ LBB24_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh249: +Lloh245: adrp x0, __MergedGlobals@PAGE+40 -Lloh250: +Lloh246: add x0, x0, __MergedGlobals@PAGEOFF+40 -Lloh251: +Lloh247: adrp x3, l_anon.[ID].1@PAGE -Lloh252: +Lloh248: add x3, x3, l_anon.[ID].1@PAGEOFF -Lloh253: +Lloh249: adrp x4, l_anon.[ID].32@PAGE -Lloh254: +Lloh250: add x4, x4, l_anon.[ID].32@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh255: +Lloh251: adrp x8, __MergedGlobals@PAGE+32 -Lloh256: +Lloh252: ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret - .loh AdrpAdd Lloh245, Lloh246 - .loh AdrpLdr Lloh247, Lloh248 - .loh AdrpLdr Lloh255, Lloh256 - .loh AdrpAdd Lloh253, Lloh254 - .loh AdrpAdd Lloh251, Lloh252 + .loh AdrpAdd Lloh241, Lloh242 + .loh AdrpLdr Lloh243, Lloh244 + .loh AdrpLdr Lloh251, Lloh252 .loh AdrpAdd Lloh249, Lloh250 + .loh AdrpAdd Lloh247, Lloh248 + .loh AdrpAdd Lloh245, Lloh246 .globl _init_drop_ivars .p2align 2 @@ -1197,9 +1184,9 @@ _init_drop_ivars: mov x21, x0 adrp x22, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGE cbz x19, LBB25_2 -Lloh257: +Lloh253: adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE -Lloh258: +Lloh254: ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] add x8, x19, x8 stp x20, x21, [x8] @@ -1213,15 +1200,15 @@ LBB25_2: mov x0, x21 bl _objc_release LBB25_3: -Lloh259: +Lloh255: adrp x8, L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32@PAGE -Lloh260: +Lloh256: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32@PAGEOFF] -Lloh261: +Lloh257: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh262: +Lloh258: ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh263: +Lloh259: ldr x8, [x8] stp x19, x8, [sp] mov x0, sp @@ -1236,10 +1223,10 @@ LBB25_5: ldp x22, x21, [sp, #16] add sp, sp, #64 ret - .loh AdrpLdr Lloh257, Lloh258 - .loh AdrpLdrGotLdr Lloh261, Lloh262, Lloh263 - .loh AdrpAdrp Lloh259, Lloh261 - .loh AdrpLdr Lloh259, Lloh260 + .loh AdrpLdr Lloh253, Lloh254 + .loh AdrpLdrGotLdr Lloh257, Lloh258, Lloh259 + .loh AdrpAdrp Lloh255, Lloh257 + .loh AdrpLdr Lloh255, Lloh256 .section __DATA,__const .p2align 3, 0x0 @@ -1374,8 +1361,8 @@ l_anon.[ID].26: .quad l_anon.[ID].25 .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" - .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1) -.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1),8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2),8,3 .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1) .zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1),8,3 .section __TEXT,__const @@ -1498,8 +1485,8 @@ L_OBJC_SELECTOR_REFERENCES_2837f061c311eb14: L_OBJC_IMAGE_INFO_2837f061c311eb14: .asciz "\000\000\000\000@\000\000" - .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2) -.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2),8,3 + .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1) +.zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1),8,3 .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2) .zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2),8,3 .section __DATA,__const diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s index c3ae77b08..8ba5011ac 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s @@ -150,8 +150,6 @@ LBB4_6: mov rdi, qword ptr [rbp - 40] call SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0) mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0], rax - mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1)], 0 - mov qword ptr [rip + SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1)], 0 add rsp, 16 pop rbx pop r12 @@ -332,8 +330,7 @@ SYM(::call_once::< Date: Tue, 28 Nov 2023 02:28:43 +0100 Subject: [PATCH 5/6] Rename allocated.rs --- .../objc2/src/rc/{allocated.rs => allocated_partial_init.rs} | 0 crates/objc2/src/rc/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename crates/objc2/src/rc/{allocated.rs => allocated_partial_init.rs} (100%) diff --git a/crates/objc2/src/rc/allocated.rs b/crates/objc2/src/rc/allocated_partial_init.rs similarity index 100% rename from crates/objc2/src/rc/allocated.rs rename to crates/objc2/src/rc/allocated_partial_init.rs diff --git a/crates/objc2/src/rc/mod.rs b/crates/objc2/src/rc/mod.rs index 968707987..da9c80fb3 100644 --- a/crates/objc2/src/rc/mod.rs +++ b/crates/objc2/src/rc/mod.rs @@ -48,7 +48,7 @@ //! assert!(weak.load().is_none()); //! ``` -mod allocated; +mod allocated_partial_init; mod autorelease; mod id; mod id_forwarding_impls; @@ -56,7 +56,7 @@ mod id_traits; mod test_object; mod weak_id; -pub use self::allocated::{Allocated, PartialInit}; +pub use self::allocated_partial_init::{Allocated, PartialInit}; pub use self::autorelease::{ autoreleasepool, autoreleasepool_leaking, AutoreleasePool, AutoreleaseSafe, }; From 2d188cb215427f56e791b7710788b205c7306f6c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 3 Dec 2023 04:16:40 +0100 Subject: [PATCH 6/6] Monomorphize a bit of error handling in declare_class! Mostly to make the assembly tests more stable --- .../src/__macro_helpers/declared_ivars.rs | 16 +- .../expected/apple-aarch64.s | 622 ++++++++---------- .../expected/apple-x86_64.s | 118 ++-- 3 files changed, 340 insertions(+), 416 deletions(-) diff --git a/crates/objc2/src/__macro_helpers/declared_ivars.rs b/crates/objc2/src/__macro_helpers/declared_ivars.rs index 784e2e6c6..d3ae34a35 100644 --- a/crates/objc2/src/__macro_helpers/declared_ivars.rs +++ b/crates/objc2/src/__macro_helpers/declared_ivars.rs @@ -281,8 +281,14 @@ pub(crate) fn register_with_ivars( let cls = builder.register(); let ivars_offset = if T::HAS_IVARS { + // Monomorphized error handling + // Intentionally not #[track_caller], we expect this error to never occur + fn get_ivar_failed() -> ! { + unreachable!("failed retrieving instance variable on newly declared class") + } + cls.instance_variable(&ivar_name) - .expect("failed retrieving instance variable on newly declared class") + .unwrap_or_else(|| get_ivar_failed()) .offset() } else { // Fallback to an offset of zero. @@ -293,8 +299,14 @@ pub(crate) fn register_with_ivars( }; let drop_flag_offset = if T::HAS_DROP_FLAG { + // Monomorphized error handling + // Intentionally not #[track_caller], we expect this error to never occur + fn get_drop_flag_failed() -> ! { + unreachable!("failed retrieving drop flag instance variable on newly declared class") + } + cls.instance_variable(&drop_flag_name) - .expect("failed retrieving drop flag instance variable on newly declared class") + .unwrap_or_else(|| get_drop_flag_failed()) .offset() } else { // Fall back to an offset of zero. diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s index 073ed1d6f..2ea0c3e1a 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s @@ -78,9 +78,9 @@ Lloh8: Lloh9: ldr x2, [x8] Lloh10: - adrp x0, l_anon.[ID].22@PAGE + adrp x0, l_anon.[ID].17@PAGE Lloh11: - add x0, x0, l_anon.[ID].22@PAGEOFF + add x0, x0, l_anon.[ID].17@PAGEOFF mov w1, #7 bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) cbz x0, LBB4_8 @@ -169,9 +169,9 @@ Lloh41: mov x4, x21 bl SYM(objc2::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) Lloh42: - adrp x0, l_anon.[ID].29@PAGE + adrp x0, l_anon.[ID].24@PAGE Lloh43: - add x0, x0, l_anon.[ID].29@PAGEOFF + add x0, x0, l_anon.[ID].24@PAGEOFF mov w1, #8 bl SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) cbz x0, LBB4_4 @@ -180,9 +180,9 @@ Lloh43: bl SYM(objc2::declare::ClassBuilder::add_protocol::GENERATED_ID, 0) LBB4_4: Lloh44: - adrp x0, l_anon.[ID].30@PAGE + adrp x0, l_anon.[ID].25@PAGE Lloh45: - add x0, x0, l_anon.[ID].30@PAGEOFF + add x0, x0, l_anon.[ID].25@PAGEOFF mov w1, #9 bl SYM(objc2::runtime::AnyProtocol::get::GENERATED_ID, 0) cbz x0, LBB4_6 @@ -220,24 +220,24 @@ Lloh53: ret LBB4_7: Lloh54: - adrp x0, l_anon.[ID].24@PAGE + adrp x0, l_anon.[ID].19@PAGE Lloh55: - add x0, x0, l_anon.[ID].24@PAGEOFF + add x0, x0, l_anon.[ID].19@PAGEOFF Lloh56: - adrp x2, l_anon.[ID].26@PAGE + adrp x2, l_anon.[ID].21@PAGE Lloh57: - add x2, x2, l_anon.[ID].26@PAGEOFF + add x2, x2, l_anon.[ID].21@PAGEOFF mov w1, #43 bl SYM(core::panicking::panic::GENERATED_ID, 0) LBB4_8: Lloh58: - adrp x0, l_anon.[ID].22@PAGE + adrp x0, l_anon.[ID].17@PAGE Lloh59: - add x0, x0, l_anon.[ID].22@PAGEOFF + add x0, x0, l_anon.[ID].17@PAGEOFF Lloh60: - adrp x2, l_anon.[ID].28@PAGE + adrp x2, l_anon.[ID].23@PAGE Lloh61: - add x2, x2, l_anon.[ID].28@PAGEOFF + add x2, x2, l_anon.[ID].23@PAGEOFF mov w1, #7 bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) .loh AdrpAdd Lloh10, Lloh11 @@ -285,9 +285,9 @@ Lloh63: Lloh64: ldr x2, [x8] Lloh65: - adrp x0, l_anon.[ID].23@PAGE + adrp x0, l_anon.[ID].18@PAGE Lloh66: - add x0, x0, l_anon.[ID].23@PAGEOFF + add x0, x0, l_anon.[ID].18@PAGEOFF mov w1, #9 bl SYM(objc2::declare::ClassBuilder::new::GENERATED_ID, 0) cbz x0, LBB5_6 @@ -401,48 +401,30 @@ Lloh95: ret LBB5_5: Lloh96: - adrp x0, l_anon.[ID].24@PAGE + adrp x0, l_anon.[ID].19@PAGE Lloh97: - add x0, x0, l_anon.[ID].24@PAGEOFF + add x0, x0, l_anon.[ID].19@PAGEOFF Lloh98: - adrp x2, l_anon.[ID].26@PAGE + adrp x2, l_anon.[ID].21@PAGE Lloh99: - add x2, x2, l_anon.[ID].26@PAGEOFF + add x2, x2, l_anon.[ID].21@PAGEOFF mov w1, #43 bl SYM(core::panicking::panic::GENERATED_ID, 0) LBB5_6: Lloh100: - adrp x0, l_anon.[ID].23@PAGE + adrp x0, l_anon.[ID].18@PAGE Lloh101: - add x0, x0, l_anon.[ID].23@PAGEOFF + add x0, x0, l_anon.[ID].18@PAGEOFF Lloh102: - adrp x2, l_anon.[ID].32@PAGE + adrp x2, l_anon.[ID].27@PAGE Lloh103: - add x2, x2, l_anon.[ID].32@PAGEOFF + add x2, x2, l_anon.[ID].27@PAGEOFF mov w1, #9 bl SYM(objc2::__macro_helpers::declare_class::failed_declaring_class::GENERATED_ID, 0) LBB5_7: -Lloh104: - adrp x0, l_anon.[ID].16@PAGE -Lloh105: - add x0, x0, l_anon.[ID].16@PAGEOFF -Lloh106: - adrp x2, l_anon.[ID].18@PAGE -Lloh107: - add x2, x2, l_anon.[ID].18@PAGEOFF - mov w1, #59 - bl SYM(core::option::expect_failed::GENERATED_ID, 0) + bl SYM(objc2::__macro_helpers::declared_ivars::register_with_ivars::get_ivar_failed::GENERATED_ID, 0) LBB5_8: -Lloh108: - adrp x0, l_anon.[ID].19@PAGE -Lloh109: - add x0, x0, l_anon.[ID].19@PAGEOFF -Lloh110: - adrp x2, l_anon.[ID].20@PAGE -Lloh111: - add x2, x2, l_anon.[ID].20@PAGEOFF - mov w1, #69 - bl SYM(core::option::expect_failed::GENERATED_ID, 0) + bl SYM(objc2::__macro_helpers::declared_ivars::register_with_ivars::get_drop_flag_failed::GENERATED_ID, 0) .loh AdrpAdd Lloh65, Lloh66 .loh AdrpLdrGotLdr Lloh62, Lloh63, Lloh64 .loh AdrpAdd Lloh89, Lloh90 @@ -463,10 +445,6 @@ Lloh111: .loh AdrpAdd Lloh96, Lloh97 .loh AdrpAdd Lloh102, Lloh103 .loh AdrpAdd Lloh100, Lloh101 - .loh AdrpAdd Lloh106, Lloh107 - .loh AdrpAdd Lloh104, Lloh105 - .loh AdrpAdd Lloh110, Lloh111 - .loh AdrpAdd Lloh108, Lloh109 .p2align 2 SYM(::call_once::<::class::{closure#0}>::{closure#0}, 0): @@ -478,37 +456,37 @@ SYM(::call_once::<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): @@ -643,16 +610,16 @@ SYM(<::call_once<::drop, 0) .p2align 2 @@ -715,16 +682,16 @@ SYM( .globl _access_drop_ivars_class .p2align 2 _access_drop_ivars_class: -Lloh158: +Lloh146: adrp x8, __MergedGlobals@PAGE+40 -Lloh159: +Lloh147: add x8, x8, __MergedGlobals@PAGEOFF+40 ldapr x8, [x8] cmp x8, #3 b.ne LBB13_2 -Lloh160: +Lloh148: adrp x8, __MergedGlobals@PAGE+32 -Lloh161: +Lloh149: ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret LBB13_2: @@ -735,60 +702,60 @@ LBB13_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh162: +Lloh150: adrp x0, __MergedGlobals@PAGE+40 -Lloh163: +Lloh151: add x0, x0, __MergedGlobals@PAGEOFF+40 -Lloh164: +Lloh152: adrp x3, l_anon.[ID].1@PAGE -Lloh165: +Lloh153: add x3, x3, l_anon.[ID].1@PAGEOFF -Lloh166: - adrp x4, l_anon.[ID].32@PAGE -Lloh167: - add x4, x4, l_anon.[ID].32@PAGEOFF +Lloh154: + adrp x4, l_anon.[ID].27@PAGE +Lloh155: + add x4, x4, l_anon.[ID].27@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh168: +Lloh156: adrp x8, __MergedGlobals@PAGE+32 -Lloh169: +Lloh157: ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret - .loh AdrpAdd Lloh158, Lloh159 - .loh AdrpLdr Lloh160, Lloh161 - .loh AdrpLdr Lloh168, Lloh169 - .loh AdrpAdd Lloh166, Lloh167 - .loh AdrpAdd Lloh164, Lloh165 - .loh AdrpAdd Lloh162, Lloh163 + .loh AdrpAdd Lloh146, Lloh147 + .loh AdrpLdr Lloh148, Lloh149 + .loh AdrpLdr Lloh156, Lloh157 + .loh AdrpAdd Lloh154, Lloh155 + .loh AdrpAdd Lloh152, Lloh153 + .loh AdrpAdd Lloh150, Lloh151 .globl _access_drop_ivars .p2align 2 _access_drop_ivars: -Lloh170: +Lloh158: adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE -Lloh171: +Lloh159: ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] add x8, x0, x8 ldp x0, x1, [x8] ret - .loh AdrpLdr Lloh170, Lloh171 + .loh AdrpLdr Lloh158, Lloh159 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): -Lloh172: +Lloh160: adrp x8, __MergedGlobals@PAGE+8 -Lloh173: +Lloh161: add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 b.ne LBB15_2 -Lloh174: +Lloh162: adrp x8, __MergedGlobals@PAGE -Lloh175: +Lloh163: ldr x0, [x8, __MergedGlobals@PAGEOFF] ret LBB15_2: @@ -799,48 +766,48 @@ LBB15_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh176: +Lloh164: adrp x0, __MergedGlobals@PAGE+8 -Lloh177: +Lloh165: add x0, x0, __MergedGlobals@PAGEOFF+8 -Lloh178: +Lloh166: adrp x3, l_anon.[ID].0@PAGE -Lloh179: +Lloh167: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh180: - adrp x4, l_anon.[ID].28@PAGE -Lloh181: - add x4, x4, l_anon.[ID].28@PAGEOFF +Lloh168: + adrp x4, l_anon.[ID].23@PAGE +Lloh169: + add x4, x4, l_anon.[ID].23@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh182: +Lloh170: adrp x8, __MergedGlobals@PAGE -Lloh183: +Lloh171: ldr x0, [x8, __MergedGlobals@PAGEOFF] ret - .loh AdrpAdd Lloh172, Lloh173 - .loh AdrpLdr Lloh174, Lloh175 - .loh AdrpLdr Lloh182, Lloh183 - .loh AdrpAdd Lloh180, Lloh181 - .loh AdrpAdd Lloh178, Lloh179 - .loh AdrpAdd Lloh176, Lloh177 + .loh AdrpAdd Lloh160, Lloh161 + .loh AdrpLdr Lloh162, Lloh163 + .loh AdrpLdr Lloh170, Lloh171 + .loh AdrpAdd Lloh168, Lloh169 + .loh AdrpAdd Lloh166, Lloh167 + .loh AdrpAdd Lloh164, Lloh165 .globl _get_class .p2align 2 _get_class: -Lloh184: +Lloh172: adrp x8, __MergedGlobals@PAGE+8 -Lloh185: +Lloh173: add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 b.ne LBB16_2 -Lloh186: +Lloh174: adrp x8, __MergedGlobals@PAGE -Lloh187: +Lloh175: ldr x0, [x8, __MergedGlobals@PAGEOFF] ret LBB16_2: @@ -851,34 +818,34 @@ LBB16_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh188: +Lloh176: adrp x0, __MergedGlobals@PAGE+8 -Lloh189: +Lloh177: add x0, x0, __MergedGlobals@PAGEOFF+8 -Lloh190: +Lloh178: adrp x3, l_anon.[ID].0@PAGE -Lloh191: +Lloh179: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh192: - adrp x4, l_anon.[ID].28@PAGE -Lloh193: - add x4, x4, l_anon.[ID].28@PAGEOFF +Lloh180: + adrp x4, l_anon.[ID].23@PAGE +Lloh181: + add x4, x4, l_anon.[ID].23@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh194: +Lloh182: adrp x8, __MergedGlobals@PAGE -Lloh195: +Lloh183: ldr x0, [x8, __MergedGlobals@PAGEOFF] ret - .loh AdrpAdd Lloh184, Lloh185 - .loh AdrpLdr Lloh186, Lloh187 - .loh AdrpLdr Lloh194, Lloh195 - .loh AdrpAdd Lloh192, Lloh193 - .loh AdrpAdd Lloh190, Lloh191 - .loh AdrpAdd Lloh188, Lloh189 + .loh AdrpAdd Lloh172, Lloh173 + .loh AdrpLdr Lloh174, Lloh175 + .loh AdrpLdr Lloh182, Lloh183 + .loh AdrpAdd Lloh180, Lloh181 + .loh AdrpAdd Lloh178, Lloh179 + .loh AdrpAdd Lloh176, Lloh177 .globl _method_simple .p2align 2 @@ -897,23 +864,23 @@ _method_id: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh196: +Lloh184: adrp x8, __MergedGlobals@PAGE+8 -Lloh197: +Lloh185: add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 b.ne LBB19_2 LBB19_1: -Lloh198: +Lloh186: adrp x8, __MergedGlobals@PAGE -Lloh199: +Lloh187: ldr x0, [x8, __MergedGlobals@PAGEOFF] -Lloh200: +Lloh188: adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE -Lloh201: +Lloh189: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] -Lloh202: +Lloh190: ldr x1, [x8] bl _objc_msgSend bl _objc_autoreleaseReturnValue @@ -925,29 +892,29 @@ LBB19_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh203: +Lloh191: adrp x0, __MergedGlobals@PAGE+8 -Lloh204: +Lloh192: add x0, x0, __MergedGlobals@PAGEOFF+8 -Lloh205: +Lloh193: adrp x3, l_anon.[ID].0@PAGE -Lloh206: +Lloh194: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh207: - adrp x4, l_anon.[ID].28@PAGE -Lloh208: - add x4, x4, l_anon.[ID].28@PAGEOFF +Lloh195: + adrp x4, l_anon.[ID].23@PAGE +Lloh196: + add x4, x4, l_anon.[ID].23@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) b LBB19_1 - .loh AdrpAdd Lloh196, Lloh197 - .loh AdrpLdrGotLdr Lloh200, Lloh201, Lloh202 - .loh AdrpAdrp Lloh198, Lloh200 - .loh AdrpLdr Lloh198, Lloh199 - .loh AdrpAdd Lloh207, Lloh208 - .loh AdrpAdd Lloh205, Lloh206 - .loh AdrpAdd Lloh203, Lloh204 + .loh AdrpAdd Lloh184, Lloh185 + .loh AdrpLdrGotLdr Lloh188, Lloh189, Lloh190 + .loh AdrpAdrp Lloh186, Lloh188 + .loh AdrpLdr Lloh186, Lloh187 + .loh AdrpAdd Lloh195, Lloh196 + .loh AdrpAdd Lloh193, Lloh194 + .loh AdrpAdd Lloh191, Lloh192 .globl _method_id_with_param .p2align 2 @@ -976,23 +943,23 @@ _copyWithZone: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh209: +Lloh197: adrp x8, __MergedGlobals@PAGE+8 -Lloh210: +Lloh198: add x8, x8, __MergedGlobals@PAGEOFF+8 ldapr x8, [x8] cmp x8, #3 b.ne LBB21_2 LBB21_1: -Lloh211: +Lloh199: adrp x8, __MergedGlobals@PAGE -Lloh212: +Lloh200: ldr x0, [x8, __MergedGlobals@PAGEOFF] -Lloh213: +Lloh201: adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE -Lloh214: +Lloh202: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] -Lloh215: +Lloh203: ldr x1, [x8] bl _objc_msgSend ldp x29, x30, [sp, #16] @@ -1003,43 +970,43 @@ LBB21_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh216: +Lloh204: adrp x0, __MergedGlobals@PAGE+8 -Lloh217: +Lloh205: add x0, x0, __MergedGlobals@PAGEOFF+8 -Lloh218: +Lloh206: adrp x3, l_anon.[ID].0@PAGE -Lloh219: +Lloh207: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh220: - adrp x4, l_anon.[ID].28@PAGE -Lloh221: - add x4, x4, l_anon.[ID].28@PAGEOFF +Lloh208: + adrp x4, l_anon.[ID].23@PAGE +Lloh209: + add x4, x4, l_anon.[ID].23@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) b LBB21_1 - .loh AdrpAdd Lloh209, Lloh210 - .loh AdrpLdrGotLdr Lloh213, Lloh214, Lloh215 - .loh AdrpAdrp Lloh211, Lloh213 - .loh AdrpLdr Lloh211, Lloh212 - .loh AdrpAdd Lloh220, Lloh221 - .loh AdrpAdd Lloh218, Lloh219 - .loh AdrpAdd Lloh216, Lloh217 + .loh AdrpAdd Lloh197, Lloh198 + .loh AdrpLdrGotLdr Lloh201, Lloh202, Lloh203 + .loh AdrpAdrp Lloh199, Lloh201 + .loh AdrpLdr Lloh199, Lloh200 + .loh AdrpAdd Lloh208, Lloh209 + .loh AdrpAdd Lloh206, Lloh207 + .loh AdrpAdd Lloh204, Lloh205 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): -Lloh222: +Lloh210: adrp x8, __MergedGlobals@PAGE+24 -Lloh223: +Lloh211: add x8, x8, __MergedGlobals@PAGEOFF+24 ldapr x8, [x8] cmp x8, #3 b.ne LBB22_2 -Lloh224: +Lloh212: adrp x8, __MergedGlobals@PAGE+16 -Lloh225: +Lloh213: ldr x0, [x8, __MergedGlobals@PAGEOFF+16] ret LBB22_2: @@ -1050,42 +1017,42 @@ LBB22_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh226: +Lloh214: adrp x0, __MergedGlobals@PAGE+24 -Lloh227: +Lloh215: add x0, x0, __MergedGlobals@PAGEOFF+24 -Lloh228: +Lloh216: adrp x3, l_anon.[ID].2@PAGE -Lloh229: +Lloh217: add x3, x3, l_anon.[ID].2@PAGEOFF -Lloh230: - adrp x4, l_anon.[ID].31@PAGE -Lloh231: - add x4, x4, l_anon.[ID].31@PAGEOFF +Lloh218: + adrp x4, l_anon.[ID].26@PAGE +Lloh219: + add x4, x4, l_anon.[ID].26@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh232: +Lloh220: adrp x8, __MergedGlobals@PAGE+16 -Lloh233: +Lloh221: ldr x0, [x8, __MergedGlobals@PAGEOFF+16] ret - .loh AdrpAdd Lloh222, Lloh223 - .loh AdrpLdr Lloh224, Lloh225 - .loh AdrpLdr Lloh232, Lloh233 - .loh AdrpAdd Lloh230, Lloh231 - .loh AdrpAdd Lloh228, Lloh229 - .loh AdrpAdd Lloh226, Lloh227 + .loh AdrpAdd Lloh210, Lloh211 + .loh AdrpLdr Lloh212, Lloh213 + .loh AdrpLdr Lloh220, Lloh221 + .loh AdrpAdd Lloh218, Lloh219 + .loh AdrpAdd Lloh216, Lloh217 + .loh AdrpAdd Lloh214, Lloh215 .globl _init_forgetable_ivars .p2align 2 _init_forgetable_ivars: cbz x0, LBB23_2 -Lloh234: +Lloh222: adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1)@PAGE -Lloh235: +Lloh223: ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1)@PAGEOFF] add x8, x0, x8 mov w9, #43 @@ -1096,15 +1063,15 @@ LBB23_2: sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh236: +Lloh224: adrp x8, L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c@PAGE -Lloh237: +Lloh225: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_af8966656b8b2b6c@PAGEOFF] -Lloh238: +Lloh226: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh239: +Lloh227: ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh240: +Lloh228: ldr x8, [x8] stp x0, x8, [sp] mov x0, sp @@ -1112,24 +1079,24 @@ Lloh240: ldp x29, x30, [sp, #16] add sp, sp, #32 ret - .loh AdrpLdr Lloh234, Lloh235 - .loh AdrpLdrGotLdr Lloh238, Lloh239, Lloh240 - .loh AdrpAdrp Lloh236, Lloh238 - .loh AdrpLdr Lloh236, Lloh237 + .loh AdrpLdr Lloh222, Lloh223 + .loh AdrpLdrGotLdr Lloh226, Lloh227, Lloh228 + .loh AdrpAdrp Lloh224, Lloh226 + .loh AdrpLdr Lloh224, Lloh225 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): -Lloh241: +Lloh229: adrp x8, __MergedGlobals@PAGE+40 -Lloh242: +Lloh230: add x8, x8, __MergedGlobals@PAGEOFF+40 ldapr x8, [x8] cmp x8, #3 b.ne LBB24_2 -Lloh243: +Lloh231: adrp x8, __MergedGlobals@PAGE+32 -Lloh244: +Lloh232: ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret LBB24_2: @@ -1140,34 +1107,34 @@ LBB24_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh245: +Lloh233: adrp x0, __MergedGlobals@PAGE+40 -Lloh246: +Lloh234: add x0, x0, __MergedGlobals@PAGEOFF+40 -Lloh247: +Lloh235: adrp x3, l_anon.[ID].1@PAGE -Lloh248: +Lloh236: add x3, x3, l_anon.[ID].1@PAGEOFF -Lloh249: - adrp x4, l_anon.[ID].32@PAGE -Lloh250: - add x4, x4, l_anon.[ID].32@PAGEOFF +Lloh237: + adrp x4, l_anon.[ID].27@PAGE +Lloh238: + add x4, x4, l_anon.[ID].27@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh251: +Lloh239: adrp x8, __MergedGlobals@PAGE+32 -Lloh252: +Lloh240: ldr x0, [x8, __MergedGlobals@PAGEOFF+32] ret - .loh AdrpAdd Lloh241, Lloh242 - .loh AdrpLdr Lloh243, Lloh244 - .loh AdrpLdr Lloh251, Lloh252 - .loh AdrpAdd Lloh249, Lloh250 - .loh AdrpAdd Lloh247, Lloh248 - .loh AdrpAdd Lloh245, Lloh246 + .loh AdrpAdd Lloh229, Lloh230 + .loh AdrpLdr Lloh231, Lloh232 + .loh AdrpLdr Lloh239, Lloh240 + .loh AdrpAdd Lloh237, Lloh238 + .loh AdrpAdd Lloh235, Lloh236 + .loh AdrpAdd Lloh233, Lloh234 .globl _init_drop_ivars .p2align 2 @@ -1184,9 +1151,9 @@ _init_drop_ivars: mov x21, x0 adrp x22, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0)@PAGE cbz x19, LBB25_2 -Lloh253: +Lloh241: adrp x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGE -Lloh254: +Lloh242: ldr x8, [x8, SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0)@PAGEOFF] add x8, x19, x8 stp x20, x21, [x8] @@ -1200,15 +1167,15 @@ LBB25_2: mov x0, x21 bl _objc_release LBB25_3: -Lloh255: +Lloh243: adrp x8, L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32@PAGE -Lloh256: +Lloh244: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_6edddcebbded8f32@PAGEOFF] -Lloh257: +Lloh245: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE -Lloh258: +Lloh246: ldr x8, [x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGEOFF] -Lloh259: +Lloh247: ldr x8, [x8] stp x19, x8, [sp] mov x0, sp @@ -1223,10 +1190,10 @@ LBB25_5: ldp x22, x21, [sp, #16] add sp, sp, #64 ret - .loh AdrpLdr Lloh253, Lloh254 - .loh AdrpLdrGotLdr Lloh257, Lloh258, Lloh259 - .loh AdrpAdrp Lloh255, Lloh257 - .loh AdrpLdr Lloh255, Lloh256 + .loh AdrpLdr Lloh241, Lloh242 + .loh AdrpLdrGotLdr Lloh245, Lloh246, Lloh247 + .loh AdrpAdrp Lloh243, Lloh245 + .loh AdrpLdr Lloh243, Lloh244 .section __DATA,__const .p2align 3, 0x0 @@ -1318,47 +1285,24 @@ l_anon.[ID].15: .space 39 l_anon.[ID].16: - .ascii "failed retrieving instance variable on newly declared class" - -l_anon.[ID].17: - .ascii "$WORKSPACE/objc2/src/__macro_helpers/declared_ivars.rs" - - .section __DATA,__const - .p2align 3, 0x0 -l_anon.[ID].18: - .quad l_anon.[ID].17 - .asciz "P\000\000\000\000\000\000\000\035\001\000\000\016\000\000" - - .section __TEXT,__const -l_anon.[ID].19: - .ascii "failed retrieving drop flag instance variable on newly declared class" - - .section __DATA,__const - .p2align 3, 0x0 -l_anon.[ID].20: - .quad l_anon.[ID].17 - .asciz "P\000\000\000\000\000\000\000)\001\000\000\016\000\000" - - .section __TEXT,__const -l_anon.[ID].21: .ascii "ForgetableIvars" -l_anon.[ID].22: +l_anon.[ID].17: .ascii "NoIvars" -l_anon.[ID].23: +l_anon.[ID].18: .ascii "DropIvars" -l_anon.[ID].24: +l_anon.[ID].19: .ascii "called `Option::unwrap()` on a `None` value" -l_anon.[ID].25: +l_anon.[ID].20: .ascii "$RUSTC/library/std/src/sync/once.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].26: - .quad l_anon.[ID].25 +l_anon.[ID].21: + .quad l_anon.[ID].20 .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 2) @@ -1366,21 +1310,21 @@ l_anon.[ID].26: .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1) .zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1),8,3 .section __TEXT,__const -l_anon.[ID].27: +l_anon.[ID].22: .ascii "crates/$DIR/lib.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].28: - .quad l_anon.[ID].27 +l_anon.[ID].23: + .quad l_anon.[ID].22 .asciz "5\000\000\000\000\000\000\000\016\000\000\000\001\000\000" .section __TEXT,__literal8,8byte_literals -l_anon.[ID].29: +l_anon.[ID].24: .ascii "NSObject" .section __TEXT,__const -l_anon.[ID].30: +l_anon.[ID].25: .ascii "NSCopying" .section __TEXT,__objc_methname,cstring_literals @@ -1491,8 +1435,8 @@ L_OBJC_IMAGE_INFO_2837f061c311eb14: .zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2),8,3 .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].31: - .quad l_anon.[ID].27 +l_anon.[ID].26: + .quad l_anon.[ID].22 .asciz "5\000\000\000\000\000\000\000O\000\000\000\001\000\000" .section __TEXT,__objc_methname,cstring_literals @@ -1518,8 +1462,8 @@ L_OBJC_IMAGE_INFO_af8966656b8b2b6c: .zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0),8,3 .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].32: - .quad l_anon.[ID].27 +l_anon.[ID].27: + .quad l_anon.[ID].22 .asciz "5\000\000\000\000\000\000\000x\000\000\000\001\000\000" .section __TEXT,__objc_methname,cstring_literals diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s index 8ba5011ac..20519bd6d 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s @@ -77,7 +77,7 @@ SYM(::call_once::<::call_once::<::call_once::<::call_once::<::call_once::<::call_once::<::class::{closure#0}>::{closure#0}, 0): @@ -290,7 +284,7 @@ SYM(::call_once::<::call_once::<::call_once<::class::{closure#0}>::{closure#0} as core[CRATE_ID]::ops::function::FnOnce<(&std[CRATE_ID]::sync::once::OnceState,)>>::call_once::{shim:vtable#0}, 0): @@ -408,7 +399,7 @@ LBB10_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].2] - lea r8, [rip + l_anon.[ID].31] + lea r8, [rip + l_anon.[ID].26] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) @@ -455,7 +446,7 @@ LBB13_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].1] - lea r8, [rip + l_anon.[ID].32] + lea r8, [rip + l_anon.[ID].27] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) @@ -492,7 +483,7 @@ LBB15_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].28] + lea r8, [rip + l_anon.[ID].23] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) @@ -518,7 +509,7 @@ LBB16_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].28] + lea r8, [rip + l_anon.[ID].23] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) @@ -571,7 +562,7 @@ LBB19_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].28] + lea r8, [rip + l_anon.[ID].23] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) @@ -624,7 +615,7 @@ LBB21_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].28] + lea r8, [rip + l_anon.[ID].23] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) @@ -647,7 +638,7 @@ LBB22_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].2] - lea r8, [rip + l_anon.[ID].31] + lea r8, [rip + l_anon.[ID].26] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) @@ -696,7 +687,7 @@ LBB24_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + SYM(::class::REGISTER_CLASS, 0)] lea rcx, [rip + l_anon.[ID].1] - lea r8, [rip + l_anon.[ID].32] + lea r8, [rip + l_anon.[ID].27] lea rdx, [rbp - 16] xor esi, esi call SYM(std::sys_common::once::queue::Once::call::GENERATED_ID, 0) @@ -842,47 +833,24 @@ l_anon.[ID].15: .space 39 l_anon.[ID].16: - .ascii "failed retrieving instance variable on newly declared class" - -l_anon.[ID].17: - .ascii "$WORKSPACE/objc2/src/__macro_helpers/declared_ivars.rs" - - .section __DATA,__const - .p2align 3, 0x0 -l_anon.[ID].18: - .quad l_anon.[ID].17 - .asciz "P\000\000\000\000\000\000\000\035\001\000\000\016\000\000" - - .section __TEXT,__const -l_anon.[ID].19: - .ascii "failed retrieving drop flag instance variable on newly declared class" - - .section __DATA,__const - .p2align 3, 0x0 -l_anon.[ID].20: - .quad l_anon.[ID].17 - .asciz "P\000\000\000\000\000\000\000)\001\000\000\016\000\000" - - .section __TEXT,__const -l_anon.[ID].21: .ascii "ForgetableIvars" -l_anon.[ID].22: +l_anon.[ID].17: .ascii "NoIvars" -l_anon.[ID].23: +l_anon.[ID].18: .ascii "DropIvars" -l_anon.[ID].24: +l_anon.[ID].19: .ascii "called `Option::unwrap()` on a `None` value" -l_anon.[ID].25: +l_anon.[ID].20: .ascii "$RUSTC/library/std/src/sync/once.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].26: - .quad l_anon.[ID].25 +l_anon.[ID].21: + .quad l_anon.[ID].20 .asciz "p\000\000\000\000\000\000\000\225\000\000\0002\000\000" .zerofill __DATA,__bss,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 0).0,8,3 @@ -891,22 +859,22 @@ l_anon.[ID].26: .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1) .zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 1),8,3 .section __TEXT,__const -l_anon.[ID].27: +l_anon.[ID].22: .ascii "crates/$DIR/lib.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].28: - .quad l_anon.[ID].27 +l_anon.[ID].23: + .quad l_anon.[ID].22 .asciz "5\000\000\000\000\000\000\000\016\000\000\000\001\000\000" .zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .section __TEXT,__literal8,8byte_literals -L_anon.[ID].29: +L_anon.[ID].24: .ascii "NSObject" .section __TEXT,__const -l_anon.[ID].30: +l_anon.[ID].25: .ascii "NSCopying" .section __TEXT,__objc_methname,cstring_literals @@ -1018,8 +986,8 @@ L_OBJC_IMAGE_INFO_2837f061c311eb14: .zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 2),8,3 .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].31: - .quad l_anon.[ID].27 +l_anon.[ID].26: + .quad l_anon.[ID].22 .asciz "5\000\000\000\000\000\000\000O\000\000\000\001\000\000" .zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 @@ -1047,8 +1015,8 @@ L_OBJC_IMAGE_INFO_af8966656b8b2b6c: .zerofill __DATA,__common,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_DROP_FLAG_OFFSET, 0),8,3 .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].32: - .quad l_anon.[ID].27 +l_anon.[ID].27: + .quad l_anon.[ID].22 .asciz "5\000\000\000\000\000\000\000x\000\000\000\001\000\000" .zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3