[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