[cfe-commits] r131366 - in /cfe/trunk: lib/CodeGen/CGObjCMac.cpp test/CodeGenObjC/messages-2.m
John McCall
rjmccall at apple.com
Sat May 14 14:12:11 PDT 2011
Author: rjmccall
Date: Sat May 14 16:12:11 2011
New Revision: 131366
URL: http://llvm.org/viewvc/llvm-project?rev=131366&view=rev
Log:
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
Modified:
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/test/CodeGenObjC/messages-2.m
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=131366&r1=131365&r2=131366&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Sat May 14 16:12:11 2011
@@ -43,18 +43,6 @@
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 @@
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 @@
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 @@
: 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 @@
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 @@
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 @@
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.
Modified: cfe/trunk/test/CodeGenObjC/messages-2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/messages-2.m?rev=131366&r1=131365&r2=131366&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/messages-2.m (original)
+++ cfe/trunk/test/CodeGenObjC/messages-2.m Sat May 14 16:12:11 2011
@@ -147,17 +147,29 @@
// rdar://problem/7854674
// CHECK: define void @test0([[A:%.*]]*
// CHECK-NF: define void @test0([[A:%.*]]*
-void test0(A *a) {
- // CHECK: alloca [[A]]*
+void test0(A *x) {
+ // CHECK: [[X:%.*]] = alloca [[A]]*
// CHECK-NEXT: [[POINT:%.*]] = alloca [[POINT_T:%.*]],
- // CHECK-NF: alloca [[A]]*
- // CHECK-NF-NEXT: [[POINT:%.*]] = alloca [[POINT_T:%.*]],
-
+ // CHECK: [[T0:%.*]] = load [[A]]** [[X]]
+ // CHECK: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
+ // CHECK-NEXT: icmp eq i8* [[T1]], null
+ // CHECK-NEXT: br i1
+ // CHECK: call {{.*}} @objc_msgSend_stret to
+ // CHECK-NEXT: br label
// CHECK: [[T0:%.*]] = bitcast [[POINT_T]]* [[POINT]] to i8*
// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 4, i1 false)
- // CHECK-NEXT: call {{.*}} @objc_msgSend_stret to
+ // CHECK-NEXT: br label
+
+ // CHECK-NF: [[X:%.*]] = alloca [[A]]*
+ // CHECK-NF-NEXT: [[POINT:%.*]] = alloca [[POINT_T:%.*]],
+ // CHECK-NF: [[T0:%.*]] = load [[A]]** [[X]]
+ // CHECK-NF: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
+ // CHECK-NF-NEXT: icmp eq i8* [[T1]], null
+ // CHECK-NF-NEXT: br i1
+ // CHECK-NF: call {{.*}} @objc_msgSend_stret to
+ // CHECK-NF-NEXT: br label
// CHECK-NF: [[T0:%.*]] = bitcast [[POINT_T]]* [[POINT]] to i8*
// CHECK-NF-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 4, i1 false)
- // CHECK-NF-NEXT: call {{.*}} @objc_msgSend_stret to
- MyPoint point = [a returnAPoint];
+ // CHECK-NF-NEXT: br label
+ MyPoint point = [x returnAPoint];
}
More information about the cfe-commits
mailing list