mwyman updated this revision to Diff 465857.
mwyman retitled this revision from "Load the `_cmd` selector for generated
getters/setters of `direct` Objective-C properties." to "Create storage for the
`_cmd` argument to the helper function for generated getters/setters of
`direct` Objective-C properties.".
mwyman edited the summary of this revision.
mwyman added a comment.
Updated to eliminate loading the selector, as the prior implementation didn't
pass a valid `_cmd` value (it just re-used the `_cmd` argument in the ABI,
which was unset by the caller and so undefined in value).
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D135091/new/
https://reviews.llvm.org/D135091
Files:
clang/lib/CodeGen/CGObjC.cpp
clang/test/CodeGenObjC/direct-method.m
Index: clang/test/CodeGenObjC/direct-method.m
===================================================================
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
- (int)getInt __attribute__((objc_direct));
@property(direct, readonly) int intProperty;
@property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
@end
@implementation Root
@@ -167,6 +168,18 @@
@end
// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method accesses _cmd (or rather loads the
+// selector, as it is an argument to objc_getProperty).
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: entry:
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca i8*,
+// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
+// CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK: [[CMD:%.*]] = load i8*, i8** [[CMDVAL]],
+// CHECK: call i8* @objc_getProperty({{.*}}, i8*{{.*}} [[CMD]], {{.*}})
+
@interface Foo : Root {
id __strong _cause_cxx_destruct;
}
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -1189,8 +1189,15 @@
// Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
// FIXME: Can't this be simpler? This might even be worse than the
// corresponding gcc code.
- llvm::Value *cmd =
- Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+ if (getterMethod->isDirectMethod()) {
+ // Direct methods no longer have a `_cmd` argument, so storage must be
+ // emitted for it to be passed to the property helper. Since the `_cmd`
+ // argument was never being initialized by the caller before, still pass
+ // an uninitialized/undefined value here.
+ EmitVarDecl(*getterMethod->getCmdDecl());
+ }
+ llvm::Value *cmd =
Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()),
+ "cmd");
llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,10 +1482,16 @@
// Emit objc_setProperty((id) self, _cmd, offset, arg,
// <is-atomic>, <is-copy>).
- llvm::Value *cmd =
- Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
- llvm::Value *self =
- Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
+ if (setterMethod->isDirectMethod()) {
+ // Direct methods no longer have a `_cmd` argument, so storage must be
+ // emitted for it to be passed to the property helper. Since the `_cmd`
+ // argument was never being initialized by the caller before, still pass
+ // an uninitialized/undefined value here.
+ EmitVarDecl(*setterMethod->getCmdDecl());
+ }
+ llvm::Value *cmd =
Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()),
+ "cmd");
+ llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
EmitIvarOffset(classImpl->getClassInterface(), ivar);
Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin());
Index: clang/test/CodeGenObjC/direct-method.m
===================================================================
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
- (int)getInt __attribute__((objc_direct));
@property(direct, readonly) int intProperty;
@property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
@end
@implementation Root
@@ -167,6 +168,18 @@
@end
// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method accesses _cmd (or rather loads the
+// selector, as it is an argument to objc_getProperty).
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: entry:
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca i8*,
+// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
+// CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK: [[CMD:%.*]] = load i8*, i8** [[CMDVAL]],
+// CHECK: call i8* @objc_getProperty({{.*}}, i8*{{.*}} [[CMD]], {{.*}})
+
@interface Foo : Root {
id __strong _cause_cxx_destruct;
}
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -1189,8 +1189,15 @@
// Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
// FIXME: Can't this be simpler? This might even be worse than the
// corresponding gcc code.
- llvm::Value *cmd =
- Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+ if (getterMethod->isDirectMethod()) {
+ // Direct methods no longer have a `_cmd` argument, so storage must be
+ // emitted for it to be passed to the property helper. Since the `_cmd`
+ // argument was never being initialized by the caller before, still pass
+ // an uninitialized/undefined value here.
+ EmitVarDecl(*getterMethod->getCmdDecl());
+ }
+ llvm::Value *cmd = Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()),
+ "cmd");
llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,10 +1482,16 @@
// Emit objc_setProperty((id) self, _cmd, offset, arg,
// <is-atomic>, <is-copy>).
- llvm::Value *cmd =
- Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
- llvm::Value *self =
- Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
+ if (setterMethod->isDirectMethod()) {
+ // Direct methods no longer have a `_cmd` argument, so storage must be
+ // emitted for it to be passed to the property helper. Since the `_cmd`
+ // argument was never being initialized by the caller before, still pass
+ // an uninitialized/undefined value here.
+ EmitVarDecl(*setterMethod->getCmdDecl());
+ }
+ llvm::Value *cmd = Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()),
+ "cmd");
+ llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
EmitIvarOffset(classImpl->getClassInterface(), ivar);
Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin());
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits