forked from OSchip/llvm-project
Remove the unused/undefined `_cmd` parameter in `objc_direct` methods.
When `objc_direct` methods were implemented, the implicit `_cmd` parameter was left as an argument to the method implementation function, but was unset by callers; if the method body referenced the `_cmd` variable, a selector load would be emitted inside the body. However, this leaves an unused argument in the ABI, and is unnecessary. This change removes the empty/unset argument, and if `_cmd` is referenced inside an `objc_direct` method it will emit local storage for the implicit variable. From the ABI perspective, `objc_direct` methods will have the implicit `self` parameter, immediately followed by whatever explicit arguments are defined on the method, rather than having one unset/undefined register in the middle. Differential Revision: https://reviews.llvm.org/D131424
This commit is contained in:
parent
1d8a7adca6
commit
aa4bcaab96
|
@ -484,9 +484,11 @@ const CGFunctionInfo &
|
|||
CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
|
||||
QualType receiverType) {
|
||||
SmallVector<CanQualType, 16> argTys;
|
||||
SmallVector<FunctionProtoType::ExtParameterInfo, 4> extParamInfos(2);
|
||||
SmallVector<FunctionProtoType::ExtParameterInfo, 4> extParamInfos(
|
||||
MD->isDirectMethod() ? 1 : 2);
|
||||
argTys.push_back(Context.getCanonicalParamType(receiverType));
|
||||
argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
|
||||
if (!MD->isDirectMethod())
|
||||
argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
|
||||
// FIXME: Kill copy?
|
||||
for (const auto *I : MD->parameters()) {
|
||||
argTys.push_back(Context.getCanonicalParamType(I->getType()));
|
||||
|
|
|
@ -768,7 +768,8 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
|
|||
}
|
||||
|
||||
args.push_back(OMD->getSelfDecl());
|
||||
args.push_back(OMD->getCmdDecl());
|
||||
if (!OMD->isDirectMethod())
|
||||
args.push_back(OMD->getCmdDecl());
|
||||
|
||||
args.append(OMD->param_begin(), OMD->param_end());
|
||||
|
||||
|
|
|
@ -2145,7 +2145,8 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
|
|||
if (!IsSuper)
|
||||
Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
|
||||
ActualArgs.add(RValue::get(Arg0), Arg0Ty);
|
||||
ActualArgs.add(RValue::get(SelValue), selTy);
|
||||
if (!Method || !Method->isDirectMethod())
|
||||
ActualArgs.add(RValue::get(SelValue), selTy);
|
||||
ActualArgs.addFrom(CallArgs);
|
||||
|
||||
// If we're calling a method, use the formal signature.
|
||||
|
@ -4103,6 +4104,9 @@ void CGObjCCommonMac::GenerateDirectMethodPrologue(
|
|||
|
||||
// only synthesize _cmd if it's referenced
|
||||
if (OMD->getCmdDecl()->isUsed()) {
|
||||
// `_cmd` is not a parameter to direct methods, so storage must be
|
||||
// explicitly declared for it.
|
||||
CGF.EmitVarDecl(*OMD->getCmdDecl());
|
||||
Builder.CreateStore(GetSelector(CGF, OMD),
|
||||
CGF.GetAddrOfLocalVar(OMD->getCmdDecl()));
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@ __attribute__((objc_root_class))
|
|||
// 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]],
|
||||
|
@ -60,9 +58,7 @@ __attribute__((objc_root_class))
|
|||
// 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]],
|
||||
|
@ -81,9 +77,7 @@ __attribute__((objc_root_class))
|
|||
// 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]],
|
||||
|
@ -125,9 +119,7 @@ __attribute__((objc_root_class))
|
|||
// 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]],
|
||||
|
@ -159,6 +151,19 @@ __attribute__((objc_root_class))
|
|||
// CHECK: ret void
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define hidden void @"\01-[Root accessCmd]"(
|
||||
- (void)accessCmd __attribute__((objc_direct)) {
|
||||
// CHECK-LABEL: entry:
|
||||
// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
|
||||
// CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
|
||||
|
||||
// loading the _cmd selector
|
||||
// CHECK-LABEL: objc_direct_method.cont:
|
||||
// CHECK-NEXT: [[CMD1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
|
||||
// CHECK-NEXT: store i8* [[CMD1]], i8** [[CMDVAL]],
|
||||
SEL sel = _cmd;
|
||||
}
|
||||
|
||||
@end
|
||||
// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
|
||||
|
||||
|
@ -205,19 +210,19 @@ __attribute__((objc_direct_members))
|
|||
|
||||
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]"
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]" to i32 (i8*)
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]" to i32 (i8*)
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]" to i32 (i8*)
|
||||
return [r getInt] + [r intProperty] + [r intProperty2];
|
||||
}
|
||||
|
||||
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]"
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]"
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]"
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]"
|
||||
// CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]" to void (i8*, i32)
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]" to i32 (i8*)
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]" to i32 (i8*)
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]" to i32 (i8*)
|
||||
// CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]" to i32 (i8*)
|
||||
[f setGetDynamic_setDirect:1];
|
||||
return [f getDirect_setDynamic] +
|
||||
[f directMethodInExtension] +
|
||||
|
|
Loading…
Reference in New Issue