Skip to content
This repository has been archived by the owner on Jan 28, 2024. It is now read-only.

Commit

Permalink
Use stret and fpret variants of objc_msgSend where appropriate (#613)
Browse files Browse the repository at this point in the history
* Use stret and fpret variants of objc_msgSend where appropriate

* Changelog

* Daco's comment
  • Loading branch information
liamappelbe committed Sep 4, 2023
1 parent fd1fbce commit 97ea620
Show file tree
Hide file tree
Showing 10 changed files with 356 additions and 92 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

- Add support for ObjC Blocks that can be invoked from any thread, using
NativeCallable.listener.
- Fix invalid exceptional return value ObjCBlocks that return floats.
- Fix return_of_invalid_type analysis error for ObjCBlocks.
- Fix crash in ObjC methods and blocks that return structs by value.
- Bump min SDK version to 3.2.0-114.0.dev.

# 9.0.1
Expand Down
144 changes: 87 additions & 57 deletions example/swift/swift_api.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated by Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
// Generated by Apple Swift version 5.8.1 (swiftlang-5.8.0.124.5 clang-1403.0.22.11.100)
#ifndef SWIFT_MODULE_SWIFT_H
#define SWIFT_MODULE_SWIFT_H
#pragma clang diagnostic push
Expand All @@ -21,7 +21,6 @@
# include <swift/objc-prologue.h>
#endif

#pragma clang diagnostic ignored "-Wduplicate-method-match"
#pragma clang diagnostic ignored "-Wauto-import"
#if defined(__OBJC__)
#include <Foundation/Foundation.h>
Expand All @@ -30,10 +29,24 @@
#include <cstdint>
#include <cstddef>
#include <cstdbool>
#include <cstring>
#include <stdlib.h>
#include <new>
#include <type_traits>
#else
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#endif
#if defined(__cplusplus)
#if __has_include(<ptrauth.h>)
# include <ptrauth.h>
#else
# ifndef __ptrauth_swift_value_witness_function_pointer
# define __ptrauth_swift_value_witness_function_pointer(x)
# endif
#endif
#endif

#if !defined(SWIFT_TYPEDEFS)
Expand Down Expand Up @@ -69,53 +82,66 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
# if __has_feature(objc_class_property)
# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
# else
# define SWIFT_CLASS_PROPERTY(...)
# define SWIFT_CLASS_PROPERTY(...)
# endif
#endif

#if __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
#else
# define SWIFT_RUNTIME_NAME(X)
#if !defined(SWIFT_RUNTIME_NAME)
# if __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
# else
# define SWIFT_RUNTIME_NAME(X)
# endif
#endif
#if __has_attribute(swift_name)
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
#else
# define SWIFT_COMPILE_NAME(X)
#if !defined(SWIFT_COMPILE_NAME)
# if __has_attribute(swift_name)
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
# else
# define SWIFT_COMPILE_NAME(X)
# endif
#endif
#if __has_attribute(objc_method_family)
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
#else
# define SWIFT_METHOD_FAMILY(X)
#if !defined(SWIFT_METHOD_FAMILY)
# if __has_attribute(objc_method_family)
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
# else
# define SWIFT_METHOD_FAMILY(X)
# endif
#endif
#if __has_attribute(noescape)
# define SWIFT_NOESCAPE __attribute__((noescape))
#else
# define SWIFT_NOESCAPE
#if !defined(SWIFT_NOESCAPE)
# if __has_attribute(noescape)
# define SWIFT_NOESCAPE __attribute__((noescape))
# else
# define SWIFT_NOESCAPE
# endif
#endif
#if __has_attribute(ns_consumed)
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
#else
# define SWIFT_RELEASES_ARGUMENT
#if !defined(SWIFT_RELEASES_ARGUMENT)
# if __has_attribute(ns_consumed)
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
# else
# define SWIFT_RELEASES_ARGUMENT
# endif
#endif
#if __has_attribute(warn_unused_result)
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
# define SWIFT_WARN_UNUSED_RESULT
#if !defined(SWIFT_WARN_UNUSED_RESULT)
# if __has_attribute(warn_unused_result)
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
# else
# define SWIFT_WARN_UNUSED_RESULT
# endif
#endif
#if __has_attribute(noreturn)
# define SWIFT_NORETURN __attribute__((noreturn))
#else
# define SWIFT_NORETURN
#if !defined(SWIFT_NORETURN)
# if __has_attribute(noreturn)
# define SWIFT_NORETURN __attribute__((noreturn))
# else
# define SWIFT_NORETURN
# endif
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_ENUM_EXTRA)
# define SWIFT_ENUM_EXTRA
# define SWIFT_ENUM_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if __has_attribute(objc_subclassing_restricted)
Expand All @@ -135,28 +161,25 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
# endif
#endif

#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif

#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif

#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if __has_attribute(objc_designated_initializer)
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
# define OBJC_DESIGNATED_INITIALIZER
# define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#if !defined(SWIFT_ENUM_ATTR)
# if defined(__has_attribute) && __has_attribute(enum_extensibility)
# if __has_attribute(enum_extensibility)
# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
# else
# define SWIFT_ENUM_ATTR(_extensibility)
# define SWIFT_ENUM_ATTR(_extensibility)
# endif
#endif
#if !defined(SWIFT_ENUM)
Expand Down Expand Up @@ -185,14 +208,16 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
#if !defined(SWIFT_DEPRECATED_MSG)
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
#endif
#if __has_feature(attribute_diagnose_if_objc)
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
#else
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
#if !defined(SWIFT_DEPRECATED_OBJC)
# if __has_feature(attribute_diagnose_if_objc)
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
# else
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
# endif
#endif
#if defined(__OBJC__)
#if !defined(IBSegueAction)
# define IBSegueAction
# define IBSegueAction
#endif
#endif
#if !defined(SWIFT_EXTERN)
Expand All @@ -205,26 +230,31 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
#if !defined(SWIFT_CALL)
# define SWIFT_CALL __attribute__((swiftcall))
#endif
#if !defined(SWIFT_INDIRECT_RESULT)
# define SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result))
#endif
#if !defined(SWIFT_CONTEXT)
# define SWIFT_CONTEXT __attribute__((swift_context))
#endif
#if !defined(SWIFT_ERROR_RESULT)
# define SWIFT_ERROR_RESULT __attribute__((swift_error_result))
#endif
#if defined(__cplusplus)
#if !defined(SWIFT_NOEXCEPT)
# define SWIFT_NOEXCEPT noexcept
#endif
#else
#if !defined(SWIFT_NOEXCEPT)
# define SWIFT_NOEXCEPT
#endif
#if defined(_WIN32)
#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL)
# define SWIFT_IMPORT_STDLIB_SYMBOL __declspec(dllimport)
#endif
#if defined(__cplusplus)
#if !defined(SWIFT_CXX_INT_DEFINED)
#define SWIFT_CXX_INT_DEFINED
namespace swift {
using Int = ptrdiff_t;
using UInt = size_t;
}
#else
#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL)
# define SWIFT_IMPORT_STDLIB_SYMBOL
#endif
#endif
#if defined(__OBJC__)
#if __has_feature(modules)
#if __has_feature(objc_modules)
#if __has_warning("-Watimport-in-framework-header")
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
#endif
Expand Down
73 changes: 57 additions & 16 deletions lib/src/code_generator/objc_built_in_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,18 @@ $objType $name(String name) {
_blockReleaseFunc,
);

// We need to load a separate instance of objc_msgSend for each signature.
final _msgSendFuncs = <String, Func>{};
Func getMsgSendFunc(Type returnType, List<ObjCMethodParam> params) {
// We need to load a separate instance of objc_msgSend for each signature. If
// the return type is a struct, we need to use objc_msgSend_stret instead, and
// for float return types we need objc_msgSend_fpret.
final _msgSendFuncs = <String, ObjCMsgSendFunc>{};
ObjCMsgSendFunc getMsgSendFunc(
Type returnType, List<ObjCMethodParam> params) {
var key = returnType.cacheKey();
for (final p in params) {
key += ' ${p.type.cacheKey()}';
}
return _msgSendFuncs[key] ??= Func(
name: '_objc_msgSend_${_msgSendFuncs.length}',
originalName: 'objc_msgSend',
returnType: returnType,
parameters: [
Parameter(name: 'obj', type: PointerType(objCObjectType)),
Parameter(name: 'sel', type: PointerType(objCSelType)),
for (final p in params) Parameter(name: p.name, type: p.type),
],
isInternal: true,
);
return _msgSendFuncs[key] ??= ObjCMsgSendFunc(
'_objc_msgSend_${_msgSendFuncs.length}', returnType, params);
}

final _selObjects = <String, ObjCInternalGlobal>{};
Expand Down Expand Up @@ -285,8 +279,8 @@ class $name implements ${w.ffiLibraryPrefix}.Finalizable {
_retainFunc.addDependencies(dependencies);
_releaseFunc.addDependencies(dependencies);
_releaseFinalizer.addDependencies(dependencies);
for (final func in _msgSendFuncs.values) {
func.addDependencies(dependencies);
for (final msgSendFunc in _msgSendFuncs.values) {
msgSendFunc.func.addDependencies(dependencies);
}
for (final sel in _selObjects.values) {
sel.addDependencies(dependencies);
Expand Down Expand Up @@ -396,3 +390,50 @@ class ObjCInternalGlobal extends LookUpBinding {
binding?.addDependencies(dependencies);
}
}

enum ObjCMsgSendVariant {
normal('objc_msgSend'),
stret('objc_msgSend_stret'),
fpret('objc_msgSend_fpret');

final String name;
const ObjCMsgSendVariant(this.name);

static ObjCMsgSendVariant fromReturnType(Type returnType) {
if (returnType is Compound && returnType.isStruct) {
return ObjCMsgSendVariant.stret;
} else if (returnType == floatType || returnType == doubleType) {
return ObjCMsgSendVariant.fpret;
}
return ObjCMsgSendVariant.normal;
}
}

/// A wrapper around the objc_msgSend function, or the stret or fpret variants.
class ObjCMsgSendFunc {
final ObjCMsgSendVariant variant;
late final Func func;

ObjCMsgSendFunc(String name, Type returnType, List<ObjCMethodParam> params)
: variant = ObjCMsgSendVariant.fromReturnType(returnType) {
func = Func(
name: name,
originalName: variant.name,
returnType: isStret ? voidType : returnType,
parameters: [
if (isStret) Parameter(name: 'stret', type: PointerType(returnType)),
Parameter(name: 'obj', type: PointerType(objCObjectType)),
Parameter(name: 'sel', type: PointerType(objCSelType)),
for (final p in params) Parameter(name: p.name, type: p.type),
],
isInternal: true,
);
}

String get name => func.name;
bool get isStret => variant == ObjCMsgSendVariant.stret;

void addDependencies(Set<Binding> dependencies) {
func.addDependencies(dependencies);
}
}
Loading

0 comments on commit 97ea620

Please sign in to comment.