зеркало из https://github.com/microsoft/clang-1.git
revert r149184
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149205 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
52f127297c
Коммит
4e1524babb
|
@ -136,7 +136,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
|
|||
bool isDelegateInit = E->isDelegateInitCall();
|
||||
|
||||
const ObjCMethodDecl *method = E->getMethodDecl();
|
||||
|
||||
|
||||
// We don't retain the receiver in delegate init calls, and this is
|
||||
// safe because the receiver value is always loaded from 'self',
|
||||
// which we zero out. We don't want to Block_copy block receivers,
|
||||
|
@ -191,19 +191,6 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
|
|||
break;
|
||||
}
|
||||
|
||||
// Check to see if receiver must be null checked before method is sent
|
||||
// to the receiver.
|
||||
NullReturnState nullReturn;
|
||||
if (CGM.getLangOptions().ObjCAutoRefCount && method)
|
||||
for (ObjCMethodDecl::param_const_iterator i = method->param_begin(),
|
||||
e = method->param_end(); i != e; ++i) {
|
||||
const ParmVarDecl *ParamDecl = (*i);
|
||||
if (ParamDecl->hasAttr<NSConsumedAttr>()) {
|
||||
nullReturn.init(*this, Receiver);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retainSelf)
|
||||
Receiver = EmitARCRetainNonBlock(Receiver);
|
||||
|
||||
|
@ -275,8 +262,8 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
|
|||
|
||||
Builder.CreateStore(newSelf, selfAddr);
|
||||
}
|
||||
RValue rvalue = AdjustRelatedResultType(*this, E, method, result);
|
||||
return nullReturn.complete(*this, rvalue, ResultType);
|
||||
|
||||
return AdjustRelatedResultType(*this, E, method, result);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -305,7 +292,6 @@ struct FinishARCDealloc : EHScopeStack::Cleanup {
|
|||
method);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// StartObjCMethod - Begin emission of an ObjCMethod. This generates
|
||||
|
|
|
@ -1392,6 +1392,63 @@ public:
|
|||
const ObjCInterfaceDecl *Interface,
|
||||
const ObjCIvarDecl *Ivar);
|
||||
};
|
||||
|
||||
/// A helper class for performing the null-initialization of a return
|
||||
/// value.
|
||||
struct NullReturnState {
|
||||
llvm::BasicBlock *NullBB;
|
||||
llvm::BasicBlock *callBB;
|
||||
NullReturnState() : NullBB(0), callBB(0) {}
|
||||
|
||||
void init(CodeGenFunction &CGF, llvm::Value *receiver) {
|
||||
// Make blocks for the null-init and call edges.
|
||||
NullBB = CGF.createBasicBlock("msgSend.nullinit");
|
||||
callBB = CGF.createBasicBlock("msgSend.call");
|
||||
|
||||
// Check for a null receiver and, if there is one, jump to the
|
||||
// null-init test.
|
||||
llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
|
||||
CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
|
||||
|
||||
// Otherwise, start performing the call.
|
||||
CGF.EmitBlock(callBB);
|
||||
}
|
||||
|
||||
RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType) {
|
||||
if (!NullBB) return result;
|
||||
|
||||
// Finish the call path.
|
||||
llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
|
||||
if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
|
||||
|
||||
// Emit the null-init block and perform the null-initialization there.
|
||||
CGF.EmitBlock(NullBB);
|
||||
if (!resultType->isAnyComplexType()) {
|
||||
assert(result.isAggregate() && "null init of non-aggregate result?");
|
||||
CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
|
||||
// Jump to the continuation block.
|
||||
CGF.EmitBlock(contBB);
|
||||
return result;
|
||||
}
|
||||
|
||||
// _Complex type
|
||||
// FIXME. Now easy to handle any other scalar type whose result is returned
|
||||
// in memory due to ABI limitations.
|
||||
CGF.EmitBlock(contBB);
|
||||
CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
|
||||
llvm::Type *MemberType = CallCV.first->getType();
|
||||
llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
|
||||
// Create phi instruction for scalar complex value.
|
||||
llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
|
||||
PHIReal->addIncoming(ZeroCV, NullBB);
|
||||
PHIReal->addIncoming(CallCV.first, callBB);
|
||||
llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
|
||||
PHIImag->addIncoming(ZeroCV, NullBB);
|
||||
PHIImag->addIncoming(CallCV.second, callBB);
|
||||
return RValue::getComplex(PHIReal, PHIImag);
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/* *** Helper Functions *** */
|
||||
|
@ -1598,23 +1655,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
|
|||
|
||||
llvm::Constant *Fn = NULL;
|
||||
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
|
||||
if (!IsSuper) {
|
||||
bool nullCheckAlreadyDone = false;
|
||||
// We have already done this computation once and flag could have been
|
||||
// passed down. But such cases are extremely rare and we do this lazily,
|
||||
// instead of absorbing cost of passing down a flag for all cases.
|
||||
if (CGM.getLangOptions().ObjCAutoRefCount && Method)
|
||||
for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
|
||||
e = Method->param_end(); i != e; ++i) {
|
||||
if ((*i)->hasAttr<NSConsumedAttr>()) {
|
||||
nullCheckAlreadyDone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nullCheckAlreadyDone)
|
||||
nullReturn.init(CGF, Arg0);
|
||||
}
|
||||
|
||||
if (!IsSuper) nullReturn.init(CGF, Arg0);
|
||||
Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
|
||||
: ObjCTypes.getSendStretFn(IsSuper);
|
||||
} else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
|
||||
|
|
|
@ -2627,75 +2627,7 @@ template <> struct DominatingValue<RValue> {
|
|||
}
|
||||
};
|
||||
|
||||
/// A helper class for performing the null-initialization of a return
|
||||
/// value.
|
||||
struct NullReturnState {
|
||||
llvm::BasicBlock *NullBB;
|
||||
llvm::BasicBlock *callBB;
|
||||
NullReturnState() : NullBB(0), callBB(0) {}
|
||||
|
||||
void init(CodeGenFunction &CGF, llvm::Value *receiver) {
|
||||
// Make blocks for the null-init and call edges.
|
||||
NullBB = CGF.createBasicBlock("msgSend.nullinit");
|
||||
callBB = CGF.createBasicBlock("msgSend.call");
|
||||
|
||||
// Check for a null receiver and, if there is one, jump to the
|
||||
// null-init test.
|
||||
llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
|
||||
CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
|
||||
|
||||
// Otherwise, start performing the call.
|
||||
CGF.EmitBlock(callBB);
|
||||
}
|
||||
|
||||
RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType) {
|
||||
if (!NullBB) return result;
|
||||
|
||||
llvm::Value *NullInitPtr = 0;
|
||||
if (result.isScalar() && !resultType->isVoidType()) {
|
||||
NullInitPtr = CGF.CreateTempAlloca(result.getScalarVal()->getType());
|
||||
CGF.Builder.CreateStore(result.getScalarVal(), NullInitPtr);
|
||||
}
|
||||
// Finish the call path.
|
||||
llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
|
||||
if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
|
||||
|
||||
// Emit the null-init block and perform the null-initialization there.
|
||||
CGF.EmitBlock(NullBB);
|
||||
if (result.isScalar()) {
|
||||
if (NullInitPtr)
|
||||
CGF.EmitNullInitialization(NullInitPtr, resultType);
|
||||
// Jump to the continuation block.
|
||||
CGF.EmitBlock(contBB);
|
||||
return NullInitPtr ? RValue::get(CGF.Builder.CreateLoad(NullInitPtr))
|
||||
: result;
|
||||
}
|
||||
|
||||
if (!resultType->isAnyComplexType()) {
|
||||
assert(result.isAggregate() && "null init of non-aggregate result?");
|
||||
CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
|
||||
// Jump to the continuation block.
|
||||
CGF.EmitBlock(contBB);
|
||||
return result;
|
||||
}
|
||||
|
||||
// _Complex type
|
||||
// FIXME. Now easy to handle any other scalar type whose result is returned
|
||||
// in memory due to ABI limitations.
|
||||
CGF.EmitBlock(contBB);
|
||||
CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
|
||||
llvm::Type *MemberType = CallCV.first->getType();
|
||||
llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
|
||||
// Create phi instruction for scalar complex value.
|
||||
llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
|
||||
PHIReal->addIncoming(ZeroCV, NullBB);
|
||||
PHIReal->addIncoming(CallCV.first, callBB);
|
||||
llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
|
||||
PHIImag->addIncoming(ZeroCV, NullBB);
|
||||
PHIImag->addIncoming(CallCV.second, callBB);
|
||||
return RValue::getComplex(PHIReal, PHIImag);
|
||||
}
|
||||
};
|
||||
} // end namespace CodeGen
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1485,16 +1485,12 @@ void test66(void) {
|
|||
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST66]]* [[T0]] to i8*
|
||||
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST66]]*
|
||||
// CHECK-NEXT: [[THREE:%.*]] = icmp eq [[TEST23:%.*]]* [[T3]], null
|
||||
// CHECK-NEXT: br i1 [[THREE]], label [[NULINIT:%.*]], label [[MSGCALL:%.*]]
|
||||
// CHECK: [[T4:%.*]] = call i8* @test66_arg()
|
||||
// CHECK-NEXT: [[T4:%.*]] = call i8* @test66_arg()
|
||||
// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]])
|
||||
// CHECK-NEXT: [[T6:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
|
||||
// CHECK-NEXT: [[T7:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
|
||||
// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* [[T7]], i8* [[T6]], i8* [[T5]])
|
||||
// CHECK-NEXT: br label [[MSGCONT:%.*]]
|
||||
// CHECK: br label [[MSGCONT:%.*]]
|
||||
// CHECK: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
|
||||
// CHECK-NEXT: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
|
||||
// CHECK-NEXT: call void @objc_release(i8* [[T8]])
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче