aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-05-14 21:12:11 +0000
committerJohn McCall <rjmccall@apple.com>2011-05-14 21:12:11 +0000
commitcba681af356e24ec4335bcf2b6bb6515072ace99 (patch)
tree4a14349fc9fe3ffb93f5d932367adcef7d896063 /lib/CodeGen
parent02c5116db6a40e806534c416e0abb22b8840831e (diff)
Only perform the null-initialization of an aggregate result of a message
send if the receiver is null. Normally it's not worthwhile to check this, but avoiding the null-initialization is nice, and this also avoids nasty problems where the null-initialization is visible within the call because we use an aliased result buffer. rdar://problem/9402992 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131366 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGObjCMac.cpp66
1 files changed, 50 insertions, 16 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 137f724c99..7cb51e2611 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -43,18 +43,6 @@ using namespace clang;
using namespace CodeGen;
-static void EmitNullReturnInitialization(CodeGenFunction &CGF,
- ReturnValueSlot &returnSlot,
- QualType resultType) {
- // Force the return slot to exist.
- if (!returnSlot.getValue())
- returnSlot = ReturnValueSlot(CGF.CreateMemTemp(resultType), false);
- CGF.EmitNullInitialization(returnSlot.getValue(), resultType);
-}
-
-
-///
-
namespace {
typedef std::vector<llvm::Constant*> ConstantVector;
@@ -1351,6 +1339,46 @@ public:
const ObjCIvarDecl *Ivar);
};
+/// A helper class for performing the null-initialization of a return
+/// value.
+struct NullReturnState {
+ llvm::BasicBlock *NullBB;
+
+ NullReturnState() : NullBB(0) {}
+
+ void init(CodeGenFunction &CGF, llvm::Value *receiver) {
+ // Make blocks for the null-init and call edges.
+ NullBB = CGF.createBasicBlock("msgSend.nullinit");
+ llvm::BasicBlock *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);
+ assert(result.isAggregate() && "null init of non-aggregate result?");
+ CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
+
+ // Jump to the continuation block.
+ CGF.EmitBlock(contBB);
+
+ return result;
+ }
+};
+
} // end anonymous namespace
/* *** Helper Functions *** */
@@ -1541,9 +1569,11 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
CGM.getContext().getCanonicalType(ResultType) &&
"Result type mismatch!");
+ NullReturnState nullReturn;
+
llvm::Constant *Fn = NULL;
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
- EmitNullReturnInitialization(CGF, Return, ResultType);
+ if (!IsSuper) nullReturn.init(CGF, Arg0);
Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
: ObjCTypes.getSendStretFn(IsSuper);
} else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
@@ -1554,7 +1584,8 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
: ObjCTypes.getSendFn(IsSuper);
}
Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
- return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
+ RValue rvalue = CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
+ return nullReturn.complete(CGF, rvalue, ResultType);
}
static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
@@ -5590,6 +5621,8 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
CGM.getTypes().getFunctionInfo(resultType, args,
FunctionType::ExtInfo());
+ NullReturnState nullReturn;
+
// Find the function to call and the mangled name for the message
// ref structure. Using a different mangled name wouldn't actually
// be a problem; it would just be a waste.
@@ -5600,11 +5633,11 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
llvm::Constant *fn = 0;
std::string messageRefName("\01l_");
if (CGM.ReturnTypeUsesSRet(fnInfo)) {
- EmitNullReturnInitialization(CGF, returnSlot, resultType);
if (isSuper) {
fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
messageRefName += "objc_msgSendSuper2_stret_fixup";
} else {
+ nullReturn.init(CGF, arg0);
fn = ObjCTypes.getMessageSendStretFixupFn();
messageRefName += "objc_msgSend_stret_fixup";
}
@@ -5660,7 +5693,8 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
callee = CGF.Builder.CreateBitCast(callee,
llvm::PointerType::getUnqual(fnType));
- return CGF.EmitCall(fnInfo, callee, returnSlot, args);
+ RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
+ return nullReturn.complete(CGF, result, resultType);
}
/// Generate code for a message send expression in the nonfragile abi.