Implement __attribute__((objc_direct)), __attribute__((objc_direct_members))
__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.
A `direct` property specifier is added (@property(direct) type name)
These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.
The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.
The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:
1) for instance methods, `self` is nil-checked. On arm64 backends this
typically adds a single instruction (cbz x0, <closest-ret>) to the
codegen, for the vast majority of the cases when the return type is a
scalar.
2) for class methods, because the class may not be realized/initialized
yet, a call to `[self self]` is emitted. When the proper deployment
target is used, this is optimized to `objc_opt_self(self)`.
However, long term we might want to emit something better that the
optimizer can reason about. When inlining kicks in, these calls
aren't optimized away as the optimizer has no idea that a single call
is really necessary.
3) the calling convention for the `_cmd` argument is changed: the caller
leaves the second argument to the call undefined, and the selector is
loaded inside the body when it's referenced only.
As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
interface isn't (the other way around is allowed, as the direct
attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.
As warnings:
- any inconsistency of direct-related calling convention when
@selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.
Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.
Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
2019-11-08 15:14:58 +08:00
|
|
|
// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
|
|
|
|
|
|
|
|
struct my_complex_struct {
|
|
|
|
int a, b;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct my_aggregate_struct {
|
|
|
|
int a, b;
|
|
|
|
char buf[128];
|
|
|
|
};
|
|
|
|
|
|
|
|
__attribute__((objc_root_class))
|
|
|
|
@interface Root
|
2019-12-07 06:24:37 +08:00
|
|
|
- (int)getInt __attribute__((objc_direct));
|
|
|
|
@property(direct, readonly) int intProperty;
|
|
|
|
@property(direct, readonly) int intProperty2;
|
Implement __attribute__((objc_direct)), __attribute__((objc_direct_members))
__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.
A `direct` property specifier is added (@property(direct) type name)
These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.
The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.
The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:
1) for instance methods, `self` is nil-checked. On arm64 backends this
typically adds a single instruction (cbz x0, <closest-ret>) to the
codegen, for the vast majority of the cases when the return type is a
scalar.
2) for class methods, because the class may not be realized/initialized
yet, a call to `[self self]` is emitted. When the proper deployment
target is used, this is optimized to `objc_opt_self(self)`.
However, long term we might want to emit something better that the
optimizer can reason about. When inlining kicks in, these calls
aren't optimized away as the optimizer has no idea that a single call
is really necessary.
3) the calling convention for the `_cmd` argument is changed: the caller
leaves the second argument to the call undefined, and the selector is
loaded inside the body when it's referenced only.
As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
interface isn't (the other way around is allowed, as the direct
attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.
As warnings:
- any inconsistency of direct-related calling convention when
@selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.
Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.
Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
2019-11-08 15:14:58 +08:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation Root
|
2019-12-07 06:24:37 +08:00
|
|
|
// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty2]"
|
|
|
|
- (int)intProperty2 {
|
|
|
|
return 42;
|
|
|
|
}
|
|
|
|
|
Implement __attribute__((objc_direct)), __attribute__((objc_direct_members))
__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.
A `direct` property specifier is added (@property(direct) type name)
These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.
The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.
The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:
1) for instance methods, `self` is nil-checked. On arm64 backends this
typically adds a single instruction (cbz x0, <closest-ret>) to the
codegen, for the vast majority of the cases when the return type is a
scalar.
2) for class methods, because the class may not be realized/initialized
yet, a call to `[self self]` is emitted. When the proper deployment
target is used, this is optimized to `objc_opt_self(self)`.
However, long term we might want to emit something better that the
optimizer can reason about. When inlining kicks in, these calls
aren't optimized away as the optimizer has no idea that a single call
is really necessary.
3) the calling convention for the `_cmd` argument is changed: the caller
leaves the second argument to the call undefined, and the selector is
loaded inside the body when it's referenced only.
As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
interface isn't (the other way around is allowed, as the direct
attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.
As warnings:
- any inconsistency of direct-related calling convention when
@selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.
Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.
Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
2019-11-08 15:14:58 +08:00
|
|
|
// CHECK-LABEL: define hidden i32 @"\01-[Root getInt]"(
|
|
|
|
- (int)getInt __attribute__((objc_direct)) {
|
|
|
|
// loading parameters
|
|
|
|
// CHECK-LABEL: entry:
|
|
|
|
// CHECK-NEXT: [[RETVAL:%.*]] = alloca
|
|
|
|
// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
|
|
|
|
// CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
|
|
|
|
// CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
|
|
|
|
// CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
|
|
|
|
|
|
|
|
// self nil-check
|
|
|
|
// CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
|
|
|
|
// CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
|
|
|
|
// CHECK-NEXT: br i1 [[NILCHECK]],
|
|
|
|
|
|
|
|
// setting return value to nil
|
|
|
|
// CHECK-LABEL: objc_direct_method.self_is_nil:
|
|
|
|
// CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
|
|
|
|
// CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
|
|
|
|
// CHECK-NEXT: br label
|
|
|
|
|
|
|
|
// set value
|
|
|
|
// CHECK-LABEL: objc_direct_method.cont:
|
|
|
|
// CHECK: store{{.*}}[[RETVAL]],
|
|
|
|
// CHECK-NEXT: br label
|
|
|
|
|
|
|
|
// return
|
|
|
|
// CHECK-LABEL: return:
|
|
|
|
// CHECK: {{%.*}} = load{{.*}}[[RETVAL]],
|
|
|
|
// CHECK-NEXT: ret
|
|
|
|
return 42;
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: define hidden i32 @"\01+[Root classGetInt]"(
|
|
|
|
+ (int)classGetInt __attribute__((objc_direct)) {
|
|
|
|
// loading parameters
|
|
|
|
// CHECK-LABEL: entry:
|
|
|
|
// CHECK-NEXT: [[SELFADDR:%.*]] = alloca i8*,
|
|
|
|
// CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
|
|
|
|
// CHECK-NEXT: store i8* %{{.*}}, i8** [[SELFADDR]],
|
|
|
|
// CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
|
|
|
|
|
|
|
|
// [self self]
|
|
|
|
// CHECK-NEXT: [[SELF:%.*]] = load i8*, i8** [[SELFADDR]],
|
|
|
|
// CHECK-NEXT: [[SELFSEL:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
|
|
|
|
// CHECK-NEXT: [[SELF0:%.*]] = call {{.*}} @objc_msgSend
|
|
|
|
// CHECK-NEXT: store i8* [[SELF0]], i8** [[SELFADDR]],
|
|
|
|
|
|
|
|
// return
|
|
|
|
// CHECK-NEXT: ret
|
|
|
|
return 42;
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: define hidden i64 @"\01-[Root getComplex]"(
|
|
|
|
- (struct my_complex_struct)getComplex __attribute__((objc_direct)) {
|
|
|
|
// loading parameters
|
|
|
|
// CHECK-LABEL: entry:
|
|
|
|
// CHECK-NEXT: [[RETVAL:%.*]] = alloca
|
|
|
|
// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
|
|
|
|
// CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
|
|
|
|
// CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
|
|
|
|
// CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
|
|
|
|
|
|
|
|
// self nil-check
|
|
|
|
// CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
|
|
|
|
// CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
|
|
|
|
// CHECK-NEXT: br i1 [[NILCHECK]],
|
|
|
|
|
|
|
|
// setting return value to nil
|
|
|
|
// CHECK-LABEL: objc_direct_method.self_is_nil:
|
|
|
|
// CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
|
|
|
|
// CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
|
|
|
|
// CHECK-NEXT: br label
|
|
|
|
|
|
|
|
// set value
|
|
|
|
// CHECK-LABEL: objc_direct_method.cont:
|
|
|
|
// CHECK: [[RET1:%.*]] = bitcast{{.*}}[[RETVAL]]
|
|
|
|
// CHECK-NEXT: call void @llvm.memcpy{{[^(]*}}({{[^,]*}}[[RET1]],
|
|
|
|
// CHECK-NEXT: br label
|
|
|
|
|
|
|
|
// return
|
|
|
|
// CHECK-LABEL: return:
|
|
|
|
// CHECK: [[RET2:%.*]] = bitcast{{.*}}[[RETVAL]]
|
|
|
|
// CHECK-NEXT: {{%.*}} = load{{.*}}[[RET2]],
|
|
|
|
// CHECK-NEXT: ret
|
|
|
|
struct my_complex_struct st = {.a = 42};
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: define hidden i64 @"\01+[Root classGetComplex]"(
|
|
|
|
+ (struct my_complex_struct)classGetComplex __attribute__((objc_direct)) {
|
|
|
|
struct my_complex_struct st = {.a = 42};
|
|
|
|
return st;
|
|
|
|
// CHECK: ret i64
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"(
|
|
|
|
- (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) {
|
2020-03-25 00:36:19 +08:00
|
|
|
// CHECK: %struct.my_aggregate_struct* noalias sret align 4 [[RETVAL:%[^,]*]],
|
Implement __attribute__((objc_direct)), __attribute__((objc_direct_members))
__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.
A `direct` property specifier is added (@property(direct) type name)
These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.
The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.
The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:
1) for instance methods, `self` is nil-checked. On arm64 backends this
typically adds a single instruction (cbz x0, <closest-ret>) to the
codegen, for the vast majority of the cases when the return type is a
scalar.
2) for class methods, because the class may not be realized/initialized
yet, a call to `[self self]` is emitted. When the proper deployment
target is used, this is optimized to `objc_opt_self(self)`.
However, long term we might want to emit something better that the
optimizer can reason about. When inlining kicks in, these calls
aren't optimized away as the optimizer has no idea that a single call
is really necessary.
3) the calling convention for the `_cmd` argument is changed: the caller
leaves the second argument to the call undefined, and the selector is
loaded inside the body when it's referenced only.
As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
interface isn't (the other way around is allowed, as the direct
attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.
As warnings:
- any inconsistency of direct-related calling convention when
@selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.
Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.
Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
2019-11-08 15:14:58 +08:00
|
|
|
|
|
|
|
// loading parameters
|
|
|
|
// CHECK-LABEL: entry:
|
|
|
|
// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
|
|
|
|
// CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
|
|
|
|
// CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
|
|
|
|
// CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
|
|
|
|
|
|
|
|
// self nil-check
|
|
|
|
// CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
|
|
|
|
// CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
|
|
|
|
// CHECK-NEXT: br i1 [[NILCHECK]],
|
|
|
|
|
|
|
|
// setting return value to nil
|
|
|
|
// CHECK-LABEL: objc_direct_method.self_is_nil:
|
|
|
|
// CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
|
|
|
|
// CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
|
|
|
|
// CHECK-NEXT: br label
|
|
|
|
|
|
|
|
// set value
|
|
|
|
// CHECK-LABEL: objc_direct_method.cont:
|
|
|
|
// CHECK: [[RET1:%.*]] = bitcast{{.*}}[[RETVAL]]
|
|
|
|
// CHECK: br label
|
|
|
|
|
|
|
|
// return
|
|
|
|
// CHECK-LABEL: return:
|
|
|
|
// CHECK: ret void
|
|
|
|
struct my_aggregate_struct st = {.a = 42};
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: define hidden void @"\01+[Root classGetAggregate]"(
|
|
|
|
+ (struct my_aggregate_struct)classGetAggregate __attribute__((objc_direct)) {
|
|
|
|
struct my_aggregate_struct st = {.a = 42};
|
|
|
|
return st;
|
|
|
|
// CHECK: ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
2019-12-07 06:24:37 +08:00
|
|
|
// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
|
Implement __attribute__((objc_direct)), __attribute__((objc_direct_members))
__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.
A `direct` property specifier is added (@property(direct) type name)
These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.
The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.
The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:
1) for instance methods, `self` is nil-checked. On arm64 backends this
typically adds a single instruction (cbz x0, <closest-ret>) to the
codegen, for the vast majority of the cases when the return type is a
scalar.
2) for class methods, because the class may not be realized/initialized
yet, a call to `[self self]` is emitted. When the proper deployment
target is used, this is optimized to `objc_opt_self(self)`.
However, long term we might want to emit something better that the
optimizer can reason about. When inlining kicks in, these calls
aren't optimized away as the optimizer has no idea that a single call
is really necessary.
3) the calling convention for the `_cmd` argument is changed: the caller
leaves the second argument to the call undefined, and the selector is
loaded inside the body when it's referenced only.
As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
interface isn't (the other way around is allowed, as the direct
attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.
As warnings:
- any inconsistency of direct-related calling convention when
@selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.
Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.
Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
2019-11-08 15:14:58 +08:00
|
|
|
|
|
|
|
@interface Foo : Root {
|
|
|
|
id __strong _cause_cxx_destruct;
|
|
|
|
}
|
|
|
|
@property(nonatomic, readonly, direct) int getDirect_setDynamic;
|
|
|
|
@property(nonatomic, readonly) int getDynamic_setDirect;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface Foo ()
|
|
|
|
@property(nonatomic, readwrite) int getDirect_setDynamic;
|
|
|
|
@property(nonatomic, readwrite, direct) int getDynamic_setDirect;
|
2019-12-19 17:25:03 +08:00
|
|
|
- (int)directMethodInExtension __attribute__((objc_direct));
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface Foo (Cat)
|
|
|
|
- (int)directMethodInCategory __attribute__((objc_direct));
|
Implement __attribute__((objc_direct)), __attribute__((objc_direct_members))
__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.
A `direct` property specifier is added (@property(direct) type name)
These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.
The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.
The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:
1) for instance methods, `self` is nil-checked. On arm64 backends this
typically adds a single instruction (cbz x0, <closest-ret>) to the
codegen, for the vast majority of the cases when the return type is a
scalar.
2) for class methods, because the class may not be realized/initialized
yet, a call to `[self self]` is emitted. When the proper deployment
target is used, this is optimized to `objc_opt_self(self)`.
However, long term we might want to emit something better that the
optimizer can reason about. When inlining kicks in, these calls
aren't optimized away as the optimizer has no idea that a single call
is really necessary.
3) the calling convention for the `_cmd` argument is changed: the caller
leaves the second argument to the call undefined, and the selector is
loaded inside the body when it's referenced only.
As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
interface isn't (the other way around is allowed, as the direct
attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.
As warnings:
- any inconsistency of direct-related calling convention when
@selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.
Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.
Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
2019-11-08 15:14:58 +08:00
|
|
|
@end
|
|
|
|
|
|
|
|
__attribute__((objc_direct_members))
|
|
|
|
@implementation Foo
|
2019-12-19 17:25:03 +08:00
|
|
|
// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInExtension]"(
|
|
|
|
- (int)directMethodInExtension {
|
|
|
|
return 42;
|
|
|
|
}
|
Implement __attribute__((objc_direct)), __attribute__((objc_direct_members))
__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.
A `direct` property specifier is added (@property(direct) type name)
These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.
The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.
The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:
1) for instance methods, `self` is nil-checked. On arm64 backends this
typically adds a single instruction (cbz x0, <closest-ret>) to the
codegen, for the vast majority of the cases when the return type is a
scalar.
2) for class methods, because the class may not be realized/initialized
yet, a call to `[self self]` is emitted. When the proper deployment
target is used, this is optimized to `objc_opt_self(self)`.
However, long term we might want to emit something better that the
optimizer can reason about. When inlining kicks in, these calls
aren't optimized away as the optimizer has no idea that a single call
is really necessary.
3) the calling convention for the `_cmd` argument is changed: the caller
leaves the second argument to the call undefined, and the selector is
loaded inside the body when it's referenced only.
As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
interface isn't (the other way around is allowed, as the direct
attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.
As warnings:
- any inconsistency of direct-related calling convention when
@selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.
Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.
Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
2019-11-08 15:14:58 +08:00
|
|
|
// CHECK-LABEL: define hidden i32 @"\01-[Foo getDirect_setDynamic]"(
|
|
|
|
// CHECK-LABEL: define internal void @"\01-[Foo setGetDirect_setDynamic:]"(
|
|
|
|
// CHECK-LABEL: define internal i32 @"\01-[Foo getDynamic_setDirect]"(
|
|
|
|
// CHECK-LABEL: define hidden void @"\01-[Foo setGetDynamic_setDirect:]"(
|
|
|
|
// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"(
|
|
|
|
@end
|
2019-12-07 06:24:37 +08:00
|
|
|
|
2019-12-19 17:25:03 +08:00
|
|
|
@implementation Foo (Cat)
|
|
|
|
// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategory]"(
|
|
|
|
- (int)directMethodInCategory {
|
|
|
|
return 42;
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategoryNoDecl]"(
|
|
|
|
- (int)directMethodInCategoryNoDecl __attribute__((objc_direct)) {
|
|
|
|
return 42;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2019-12-07 06:24:37 +08:00
|
|
|
int useRoot(Root *r) {
|
|
|
|
// CHECK-LABEL: define i32 @useRoot
|
|
|
|
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]"
|
|
|
|
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]"
|
|
|
|
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]"
|
|
|
|
return [r getInt] + [r intProperty] + [r intProperty2];
|
|
|
|
}
|
2019-12-10 06:27:57 +08:00
|
|
|
|
2019-12-18 03:06:17 +08:00
|
|
|
int useFoo(Foo *f) {
|
|
|
|
// CHECK-LABEL: define i32 @useFoo
|
|
|
|
// CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]"
|
|
|
|
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]"
|
2019-12-19 17:25:03 +08:00
|
|
|
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]"
|
|
|
|
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]"
|
|
|
|
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]"
|
2019-12-18 03:06:17 +08:00
|
|
|
[f setGetDynamic_setDirect:1];
|
2019-12-19 17:25:03 +08:00
|
|
|
return [f getDirect_setDynamic] +
|
|
|
|
[f directMethodInExtension] +
|
|
|
|
[f directMethodInCategory] +
|
|
|
|
[f directMethodInCategoryNoDecl];
|
2019-12-18 03:06:17 +08:00
|
|
|
}
|
|
|
|
|
2019-12-10 06:27:57 +08:00
|
|
|
__attribute__((objc_root_class))
|
|
|
|
@interface RootDeclOnly
|
|
|
|
@property(direct, readonly) int intProperty;
|
|
|
|
@end
|
|
|
|
|
|
|
|
int useRootDeclOnly(RootDeclOnly *r) {
|
|
|
|
// CHECK-LABEL: define i32 @useRootDeclOnly
|
|
|
|
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[RootDeclOnly intProperty]"
|
|
|
|
return [r intProperty];
|
|
|
|
}
|