-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ffigen] Only use objc_msgSend
variants on x64
#836
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @liamappelbe!
I think this code could use some simplification before landing.
@@ -35168,25 +35768,46 @@ class NSString extends NSObject { | |||
|
|||
void localizedStandardRangeOfString_( | |||
ffi.Pointer<_NSRange> stret, NSString str) { | |||
_lib._objc_msgSend_340( | |||
stret, _id, _lib._sel_localizedStandardRangeOfString_1, str._id); | |||
_lib._objc_msgSend_useVariants1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This will probs also need treatment in #216.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are @Native
annotations lazy loaded? If so this approach should work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, they are "dynamic loading" everywhere currently.
If we'd ever to static linking, it would be after TFA. @sstrickl has been working passing the OS in to TFA, when I get to static linking, I could extend that work to cover Abi
.
pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart
Outdated
Show resolved
Hide resolved
@@ -417,28 +427,81 @@ enum ObjCMsgSendVariant { | |||
/// A wrapper around the objc_msgSend function, or the stret or fpret variants. | |||
class ObjCMsgSendFunc { | |||
final ObjCMsgSendVariant variant; | |||
late final Func func; | |||
final ObjCInternalGlobal useVariants; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could use documentation. Ditto for the other fields, and maybe a larger explanation on ObjCMsgSendFunc
itself.
What I've been able to reverse engineer:
isStret
whether ifuseVariant
is true, thestret
variant is used. Requires a pointer to the struct as extra param.useVariant
whether at runtime the ABI is x64 on iOS or MacOS.variantFunc
thestret
orfpret
variants. null if only normal func.normalFunc
always the normal variant.
We emit both variant and normalFunc and branch at runtime based on ABI.
The same documentation should go on the PR description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
bool get isStret => variant == ObjCMsgSendVariant.stret; | ||
bool get isNormal => variant == ObjCMsgSendVariant.normal; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, maybe the code would be more readable if the call sites had switches over the enum. (e.g. !isNormal
would be both the stret and fpret cases.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
final stretCall = | ||
_invoke(variantFunc!.name, lib, target, sel, params, stret: stret); | ||
return '$lib.${useVariants.name} ? $stretCall : $stret.ref = $normalCall'; | ||
} else if (variantFunc != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not so readable: variantFunc != null if !isNormal. Since we already covered isStret, this is the fpret case.
Please convert this if else if else to a switch on variant
with the 3 cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @liamappelbe !
objc_msgSend_stret
andobjc_msgSend_fpret
are only available on x64, so just use the normalobjc_msgSend
on arm64.We can only check the ABI at runtime, so for the stret and fpret variants we need to emit both the variant and the normal
objc_msgSend
function. Then we can decide which to use when the method is invoked at runtime.This runtime check is complicated by the fact that
objc_msgSend_stret
has a different signature thanobjc_msgSend
has for the same method. This is becauseobjc_msgSend_stret
takes a pointer to the return type as its first arg. If it wasn't for this signature difference we could just change the function name string we pass toDynamicLibrary.lookup
.Fixes #829