zcov: / lib/CodeGen/CGObjC.cpp


Files: 1 Branches Taken: 81.8% 72 / 88
Generated: 2010-02-10 01:31 Branches Executed: 95.5% 84 / 88
Line Coverage: 94.4% 289 / 306


Programs: 1 Runs 2897


       1                 : //===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : // This contains code to emit Objective-C code as LLVM code.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "CGObjCRuntime.h"
      15                 : #include "CodeGenFunction.h"
      16                 : #include "CodeGenModule.h"
      17                 : #include "clang/AST/ASTContext.h"
      18                 : #include "clang/AST/DeclObjC.h"
      19                 : #include "clang/AST/StmtObjC.h"
      20                 : #include "clang/Basic/Diagnostic.h"
      21                 : #include "llvm/ADT/STLExtras.h"
      22                 : #include "llvm/Target/TargetData.h"
      23                 : using namespace clang;
      24                 : using namespace CodeGen;
      25                 : 
      26                 : /// Emits an instance of NSConstantString representing the object.
      27               67: llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
      28                 : {
      29                 :   llvm::Constant *C = 
      30               67:       CGM.getObjCRuntime().GenerateConstantString(E->getString());
      31                 :   // FIXME: This bitcast should just be made an invariant on the Runtime.
      32               67:   return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
      33                 : }
      34                 : 
      35                 : /// Emit a selector.
      36                3: llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) {
      37                 :   // Untyped selector.
      38                 :   // Note that this implementation allows for non-constant strings to be passed
      39                 :   // as arguments to @selector().  Currently, the only thing preventing this
      40                 :   // behaviour is the type checking in the front end.
      41                3:   return CGM.getObjCRuntime().GetSelector(Builder, E->getSelector());
      42                 : }
      43                 : 
      44               12: llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
      45                 :   // FIXME: This should pass the Decl not the name.
      46               12:   return CGM.getObjCRuntime().GenerateProtocolRef(Builder, E->getProtocol());
      47                 : }
      48                 : 
      49                 : 
      50              138: RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
      51                 :   // Only the lookup mechanism and first two arguments of the method
      52                 :   // implementation vary between runtimes.  We can get the receiver and
      53                 :   // arguments in generic code.
      54                 : 
      55              138:   CGObjCRuntime &Runtime = CGM.getObjCRuntime();
      56              138:   const Expr *ReceiverExpr = E->getReceiver();
      57              138:   bool isSuperMessage = false;
      58              138:   bool isClassMessage = false;
      59                 :   // Find the receiver
      60                 :   llvm::Value *Receiver;
                       53: branch 0 taken
                       85: branch 1 taken
      61              138:   if (!ReceiverExpr) {
      62               53:     const ObjCInterfaceDecl *OID = E->getClassInfo().first;
      63                 : 
      64                 :     // Very special case, super send in class method. The receiver is
      65                 :     // self (the class object) and the send uses super semantics.
                       12: branch 0 taken
                       41: branch 1 taken
      66               53:     if (!OID) {
      67                 :       assert(E->getClassName()->isStr("super") &&
                       12: branch 2 taken
                        0: branch 3 not taken
      68               12:              "Unexpected missing class interface in message send.");
      69               12:       isSuperMessage = true;
      70               12:       Receiver = LoadObjCSelf();
      71                 :     } else {
      72               41:       Receiver = Runtime.GetClass(Builder, OID);
      73                 :     }
      74                 : 
      75               53:     isClassMessage = true;
                       17: branch 2 taken
                       68: branch 3 taken
      76               85:   } else if (isa<ObjCSuperExpr>(E->getReceiver())) {
      77               17:     isSuperMessage = true;
      78               17:     Receiver = LoadObjCSelf();
      79                 :   } else {
      80               68:     Receiver = EmitScalarExpr(E->getReceiver());
      81                 :   }
      82                 : 
      83              138:   CallArgList Args;
      84              138:   EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end());
      85                 : 
                       29: branch 0 taken
                      109: branch 1 taken
      86              138:   if (isSuperMessage) {
      87                 :     // super is only valid in an Objective-C method
      88               29:     const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
      89               29:     bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
      90                 :     return Runtime.GenerateMessageSendSuper(*this, E->getType(),
      91                 :                                             E->getSelector(),
      92                 :                                             OMD->getClassInterface(),
      93                 :                                             isCategoryImpl,
      94                 :                                             Receiver,
      95                 :                                             isClassMessage,
      96                 :                                             Args,
      97               29:                                             E->getMethodDecl());
      98                 :   }
      99                 : 
     100                 :   return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(),
     101                 :                                      Receiver, isClassMessage, Args,
     102              109:                                      E->getMethodDecl());
     103                 : }
     104                 : 
     105                 : /// StartObjCMethod - Begin emission of an ObjCMethod. This generates
     106                 : /// the LLVM function and sets the other context used by
     107                 : /// CodeGenFunction.
     108                 : void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
     109              291:                                       const ObjCContainerDecl *CD) {
     110              291:   FunctionArgList Args;
     111              291:   llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD);
     112                 : 
     113              291:   const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD);
     114              291:   CGM.SetInternalFunctionAttributes(OMD, Fn, FI);
     115                 : 
     116                 :   Args.push_back(std::make_pair(OMD->getSelfDecl(),
     117              291:                                 OMD->getSelfDecl()->getType()));
     118                 :   Args.push_back(std::make_pair(OMD->getCmdDecl(),
     119              291:                                 OMD->getCmdDecl()->getType()));
     120                 : 
                      124: branch 1 taken
                      291: branch 2 taken
     121              706:   for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
     122              291:        E = OMD->param_end(); PI != E; ++PI)
     123              124:     Args.push_back(std::make_pair(*PI, (*PI)->getType()));
     124                 : 
     125              291:   StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocEnd());
     126              291: }
     127                 : 
     128                 : /// Generate an Objective-C method.  An Objective-C method is a C function with
     129                 : /// its pointer, name, and types registered in the class struture.
     130              175: void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
     131                 :   // Check if we should generate debug info for this method.
                       10: branch 1 taken
                      165: branch 2 taken
                       10: branch 4 taken
                        0: branch 5 not taken
                       10: branch 6 taken
                      165: branch 7 taken
     132              175:   if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>())
     133               10:     DebugInfo = CGM.getDebugInfo();
     134              175:   StartObjCMethod(OMD, OMD->getClassInterface());
     135              175:   EmitStmt(OMD->getBody());
     136              175:   FinishFunction(OMD->getBodyRBrace());
     137              175: }
     138                 : 
     139                 : // FIXME: I wasn't sure about the synthesis approach. If we end up generating an
     140                 : // AST for the whole body we can just fall back to having a GenerateFunction
     141                 : // which takes the body Stmt.
     142                 : 
     143                 : /// GenerateObjCGetter - Generate an Objective-C property getter
     144                 : /// function. The given Decl must be an ObjCImplementationDecl. @synthesize
     145                 : /// is illegal within a category.
     146                 : void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
     147               59:                                          const ObjCPropertyImplDecl *PID) {
     148               59:   ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
     149               59:   const ObjCPropertyDecl *PD = PID->getPropertyDecl();
     150               59:   ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
                        0: branch 0 not taken
                       59: branch 1 taken
     151               59:   assert(OMD && "Invalid call to generate getter (empty method)");
     152                 :   // FIXME: This is rather murky, we create this here since they will not have
     153                 :   // been created by Sema for us.
     154               59:   OMD->createImplicitParams(getContext(), IMP->getClassInterface());
     155               59:   StartObjCMethod(OMD, IMP->getClassInterface());
     156                 : 
     157                 :   // Determine if we should use an objc_getProperty call for
     158                 :   // this. Non-atomic properties are directly evaluated.
     159                 :   // atomic 'copy' and 'retain' properties are also directly
     160                 :   // evaluated in gc-only mode.
                       58: branch 2 taken
                        1: branch 3 taken
                       53: branch 5 taken
                        5: branch 6 taken
                       50: branch 8 taken
                        3: branch 9 taken
                        5: branch 11 taken
                       45: branch 12 taken
                        8: branch 13 taken
                       51: branch 14 taken
     161               59:   if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly &&
     162                 :       !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
     163                 :       (PD->getSetterKind() == ObjCPropertyDecl::Copy ||
     164                 :        PD->getSetterKind() == ObjCPropertyDecl::Retain)) {
     165                 :     llvm::Value *GetPropertyFn =
     166                8:       CGM.getObjCRuntime().GetPropertyGetFunction();
     167                 : 
                        0: branch 0 not taken
                        8: branch 1 taken
     168                8:     if (!GetPropertyFn) {
     169                0:       CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy");
     170                0:       FinishFunction();
     171                0:       return;
     172                 :     }
     173                 : 
     174                 :     // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
     175                 :     // FIXME: Can't this be simpler? This might even be worse than the
     176                 :     // corresponding gcc code.
     177                8:     CodeGenTypes &Types = CGM.getTypes();
     178                8:     ValueDecl *Cmd = OMD->getCmdDecl();
     179                8:     llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd");
     180                8:     QualType IdTy = getContext().getObjCIdType();
     181                 :     llvm::Value *SelfAsId =
     182                8:       Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
     183                8:     llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar);
     184                 :     llvm::Value *True =
     185                8:       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
     186                8:     CallArgList Args;
     187                8:     Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy));
     188                8:     Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType()));
     189                8:     Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy));
     190                8:     Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
     191                 :     // FIXME: We shouldn't need to get the function info here, the
     192                 :     // runtime already should have computed it to build the function.
     193                 :     RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args,
     194                 :                                                CC_Default, false),
     195                8:                          GetPropertyFn, ReturnValueSlot(), Args);
     196                 :     // We need to fix the type here. Ivars with copy & retain are
     197                 :     // always objects so we don't need to worry about complex or
     198                 :     // aggregates.
     199                 :     RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
     200                8:                                            Types.ConvertType(PD->getType())));
     201                8:     EmitReturnOfRValue(RV, PD->getType());
     202                 :   } else {
     203               51:     LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0);
                        2: branch 2 taken
                       49: branch 3 taken
     204               51:     if (hasAggregateLLVMType(Ivar->getType())) {
     205                2:       EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType());
     206                 :     } else {
     207               49:       CodeGenTypes &Types = CGM.getTypes();
     208               49:       RValue RV = EmitLoadOfLValue(LV, Ivar->getType());
     209                 :       RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
     210               49:                        Types.ConvertType(PD->getType())));
     211               49:       EmitReturnOfRValue(RV, PD->getType());
     212                 :     }
     213                 :   }
     214                 : 
     215               59:   FinishFunction();
     216                 : }
     217                 : 
     218                 : /// GenerateObjCSetter - Generate an Objective-C property setter
     219                 : /// function. The given Decl must be an ObjCImplementationDecl. @synthesize
     220                 : /// is illegal within a category.
     221                 : void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
     222               57:                                          const ObjCPropertyImplDecl *PID) {
     223               57:   ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
     224               57:   const ObjCPropertyDecl *PD = PID->getPropertyDecl();
     225               57:   ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
                        0: branch 0 not taken
                       57: branch 1 taken
     226               57:   assert(OMD && "Invalid call to generate setter (empty method)");
     227                 :   // FIXME: This is rather murky, we create this here since they will not have
     228                 :   // been created by Sema for us.
     229               57:   OMD->createImplicitParams(getContext(), IMP->getClassInterface());
     230               57:   StartObjCMethod(OMD, IMP->getClassInterface());
     231                 : 
     232               57:   bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy;
     233                 :   bool IsAtomic =
     234               57:     !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic);
     235                 : 
     236                 :   // Determine if we should use an objc_setProperty call for
     237                 :   // this. Properties with 'copy' semantics always use it, as do
     238                 :   // non-atomic properties with 'release' semantics as long as we are
     239                 :   // not in gc-only mode.
                       53: branch 0 taken
                        4: branch 1 taken
                       52: branch 4 taken
                        1: branch 5 taken
                        6: branch 7 taken
                       46: branch 8 taken
                       10: branch 9 taken
                       47: branch 10 taken
     240               57:   if (IsCopy ||
     241                 :       (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly &&
     242                 :        PD->getSetterKind() == ObjCPropertyDecl::Retain)) {
     243                 :     llvm::Value *SetPropertyFn =
     244               10:       CGM.getObjCRuntime().GetPropertySetFunction();
     245                 : 
                        0: branch 0 not taken
                       10: branch 1 taken
     246               10:     if (!SetPropertyFn) {
     247                0:       CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy");
     248                0:       FinishFunction();
     249                0:       return;
     250                 :     }
     251                 : 
     252                 :     // Emit objc_setProperty((id) self, _cmd, offset, arg,
     253                 :     //                       <is-atomic>, <is-copy>).
     254                 :     // FIXME: Can't this be simpler? This might even be worse than the
     255                 :     // corresponding gcc code.
     256               10:     CodeGenTypes &Types = CGM.getTypes();
     257               10:     ValueDecl *Cmd = OMD->getCmdDecl();
     258               10:     llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd");
     259               10:     QualType IdTy = getContext().getObjCIdType();
     260                 :     llvm::Value *SelfAsId =
     261               10:       Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
     262               10:     llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar);
     263               10:     llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()];
     264                 :     llvm::Value *ArgAsId =
     265                 :       Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"),
     266               10:                             Types.ConvertType(IdTy));
     267                 :     llvm::Value *True =
     268               10:       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
     269                 :     llvm::Value *False =
     270               10:       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
     271               10:     CallArgList Args;
     272               10:     Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy));
     273               10:     Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType()));
     274               10:     Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy));
     275               10:     Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy));
     276                 :     Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False),
                        8: branch 1 taken
                        2: branch 2 taken
     277               10:                                   getContext().BoolTy));
     278                 :     Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False),
                        4: branch 1 taken
                        6: branch 2 taken
     279               10:                                   getContext().BoolTy));
     280                 :     // FIXME: We shouldn't need to get the function info here, the runtime
     281                 :     // already should have computed it to build the function.
     282                 :     EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
     283                 :                                    CC_Default, false), SetPropertyFn,
     284               10:              ReturnValueSlot(), Args);
     285                 :   } else {
     286                 :     // FIXME: Find a clean way to avoid AST node creation.
     287               47:     SourceLocation Loc = PD->getLocation();
     288               47:     ValueDecl *Self = OMD->getSelfDecl();
     289               47:     ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
     290               47:     DeclRefExpr Base(Self, Self->getType(), Loc);
     291               47:     ParmVarDecl *ArgDecl = *OMD->param_begin();
     292               47:     DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc);
     293               47:     ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
     294                 :     
     295                 :     // The property type can differ from the ivar type in some situations with
     296                 :     // Objective-C pointer types, we can always bit cast the RHS in these cases.
                        5: branch 7 taken
                       42: branch 8 taken
     297               47:     if (getContext().getCanonicalType(Ivar->getType()) !=
     298                 :         getContext().getCanonicalType(ArgDecl->getType())) {
     299                 :       ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg,
     300                5:                                  false);
     301                 :       BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign,
     302                5:                             Ivar->getType(), Loc);
     303                5:       EmitStmt(&Assign);
     304                 :     } else {
     305                 :       BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
     306               42:                             Ivar->getType(), Loc);
     307               42:       EmitStmt(&Assign);
     308               47:     }
     309                 :   }
     310                 : 
     311               57:   FinishFunction();
     312                 : }
     313                 : 
     314              107: llvm::Value *CodeGenFunction::LoadObjCSelf() {
     315              107:   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
     316                 :   // See if we need to lazily forward self inside a block literal.
     317              107:   BlockForwardSelf();
     318              107:   return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
     319                 : }
     320                 : 
     321               51: QualType CodeGenFunction::TypeOfSelfObject() {
     322               51:   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
     323               51:   ImplicitParamDecl *selfDecl = OMD->getSelfDecl();
     324                 :   const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>(
     325               51:     getContext().getCanonicalType(selfDecl->getType()));
     326               51:   return PTy->getPointeeType();
     327                 : }
     328                 : 
     329                 : RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp,
     330                6:                                                  const Selector &S) {
     331                6:   llvm::Value *Receiver = LoadObjCSelf();
     332                6:   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
     333                6:   bool isClassMessage = OMD->isClassMethod();
     334                6:   bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
     335                 :   return CGM.getObjCRuntime().GenerateMessageSendSuper(*this,
     336                 :                                                        Exp->getType(),
     337                 :                                                        S,
     338                 :                                                        OMD->getClassInterface(),
     339                 :                                                        isCategoryImpl,
     340                 :                                                        Receiver,
     341                 :                                                        isClassMessage,
     342                6:                                                        CallArgList());
     343                 : 
     344                 : }
     345                 : 
     346               42: RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) {
     347               42:   Exp = Exp->IgnoreParens();
     348                 :   // FIXME: Split it into two separate routines.
                       32: branch 1 taken
                       10: branch 2 taken
     349               42:   if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
     350               32:     Selector S = E->getProperty()->getGetterName();
                        4: branch 2 taken
                       28: branch 3 taken
     351               32:     if (isa<ObjCSuperExpr>(E->getBase()))
     352                4:       return EmitObjCSuperPropertyGet(E, S);
     353                 :     return CGM.getObjCRuntime().
     354                 :              GenerateMessageSend(*this, Exp->getType(), S,
     355                 :                                  EmitScalarExpr(E->getBase()),
     356               28:                                  false, CallArgList());
     357                 :   } else {
     358                 :     const ObjCImplicitSetterGetterRefExpr *KE =
     359               10:       cast<ObjCImplicitSetterGetterRefExpr>(Exp);
     360               10:     Selector S = KE->getGetterMethod()->getSelector();
     361                 :     llvm::Value *Receiver;
                        2: branch 1 taken
                        8: branch 2 taken
     362               10:     if (KE->getInterfaceDecl()) {
     363                2:       const ObjCInterfaceDecl *OID = KE->getInterfaceDecl();
     364                2:       Receiver = CGM.getObjCRuntime().GetClass(Builder, OID);
                        2: branch 2 taken
                        6: branch 3 taken
     365                8:     } else if (isa<ObjCSuperExpr>(KE->getBase()))
     366                2:       return EmitObjCSuperPropertyGet(KE, S);
     367                 :     else
     368                6:       Receiver = EmitScalarExpr(KE->getBase());
     369                 :     return CGM.getObjCRuntime().
     370                 :              GenerateMessageSend(*this, Exp->getType(), S,
     371                 :                                  Receiver,
     372                8:                                  KE->getInterfaceDecl() != 0, CallArgList());
     373                 :   }
     374                 : }
     375                 : 
     376                 : void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp,
     377                 :                                                const Selector &S,
     378                3:                                                RValue Src) {
     379                3:   CallArgList Args;
     380                3:   llvm::Value *Receiver = LoadObjCSelf();
     381                3:   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
     382                3:   bool isClassMessage = OMD->isClassMethod();
     383                3:   bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
     384                3:   Args.push_back(std::make_pair(Src, Exp->getType()));
     385                 :   CGM.getObjCRuntime().GenerateMessageSendSuper(*this,
     386                 :                                                 Exp->getType(),
     387                 :                                                 S,
     388                 :                                                 OMD->getClassInterface(),
     389                 :                                                 isCategoryImpl,
     390                 :                                                 Receiver,
     391                 :                                                 isClassMessage,
     392                3:                                                 Args);
     393                3:   return;
     394                 : }
     395                 : 
     396                 : void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp,
     397               44:                                           RValue Src) {
     398                 :   // FIXME: Split it into two separate routines.
                       38: branch 1 taken
                        6: branch 2 taken
     399               44:   if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
     400               38:     Selector S = E->getProperty()->getSetterName();
                        1: branch 2 taken
                       37: branch 3 taken
     401               38:     if (isa<ObjCSuperExpr>(E->getBase())) {
     402                1:       EmitObjCSuperPropertySet(E, S, Src);
     403                1:       return;
     404                 :     }
     405               37:     CallArgList Args;
     406               37:     Args.push_back(std::make_pair(Src, E->getType()));
     407                 :     CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S,
     408                 :                                              EmitScalarExpr(E->getBase()),
     409               37:                                              false, Args);
                        6: branch 0 taken
                        0: branch 1 not taken
     410                6:   } else if (const ObjCImplicitSetterGetterRefExpr *E =
     411                6:                dyn_cast<ObjCImplicitSetterGetterRefExpr>(Exp)) {
     412                6:     Selector S = E->getSetterMethod()->getSelector();
     413                6:     CallArgList Args;
     414                 :     llvm::Value *Receiver;
                        0: branch 1 not taken
                        6: branch 2 taken
     415                6:     if (E->getInterfaceDecl()) {
     416                0:       const ObjCInterfaceDecl *OID = E->getInterfaceDecl();
     417                0:       Receiver = CGM.getObjCRuntime().GetClass(Builder, OID);
                        2: branch 2 taken
                        4: branch 3 taken
     418                6:     } else if (isa<ObjCSuperExpr>(E->getBase())) {
     419                2:       EmitObjCSuperPropertySet(E, S, Src);
     420                2:       return;
     421                 :     } else
     422                4:       Receiver = EmitScalarExpr(E->getBase());
     423                4:     Args.push_back(std::make_pair(Src, E->getType()));
     424                 :     CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S,
     425                 :                                              Receiver,
                        4: branch 6 taken
                        2: branch 7 taken
     426                4:                                              E->getInterfaceDecl() != 0, Args);
     427                 :   } else
     428                0:     assert (0 && "bad expression node in EmitObjCPropertySet");
     429                 : }
     430                 : 
     431                5: void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
     432                 :   llvm::Constant *EnumerationMutationFn =
     433                5:     CGM.getObjCRuntime().EnumerationMutationFunction();
     434                 :   llvm::Value *DeclAddress;
     435                5:   QualType ElementTy;
     436                 : 
                        0: branch 0 not taken
                        5: branch 1 taken
     437                5:   if (!EnumerationMutationFn) {
     438                0:     CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime");
     439                0:     return;
     440                 :   }
     441                 : 
                        5: branch 2 taken
                        0: branch 3 not taken
     442                5:   if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
     443                5:     EmitStmt(SD);
                        5: branch 1 taken
                        0: branch 2 not taken
     444                5:     assert(HaveInsertPoint() && "DeclStmt destroyed insert point!");
     445                5:     const Decl* D = SD->getSingleDecl();
     446                5:     ElementTy = cast<ValueDecl>(D)->getType();
     447                5:     DeclAddress = LocalDeclMap[D];
     448                 :   } else {
     449                0:     ElementTy = cast<Expr>(S.getElement())->getType();
     450                0:     DeclAddress = 0;
     451                 :   }
     452                 : 
     453                 :   // Fast enumeration state.
     454                5:   QualType StateTy = getContext().getObjCFastEnumerationStateType();
     455                5:   llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
     456                5:   EmitMemSetToZero(StatePtr, StateTy);
     457                 : 
     458                 :   // Number of elements in the items array.
     459                 :   static const unsigned NumItems = 16;
     460                 : 
     461                 :   // Get selector
     462                5:   llvm::SmallVector<IdentifierInfo*, 3> II;
     463                5:   II.push_back(&CGM.getContext().Idents.get("countByEnumeratingWithState"));
     464                5:   II.push_back(&CGM.getContext().Idents.get("objects"));
     465                5:   II.push_back(&CGM.getContext().Idents.get("count"));
     466                 :   Selector FastEnumSel = CGM.getContext().Selectors.getSelector(II.size(),
     467                5:                                                                 &II[0]);
     468                 : 
     469                 :   QualType ItemsTy =
     470                 :     getContext().getConstantArrayType(getContext().getObjCIdType(),
     471                 :                                       llvm::APInt(32, NumItems),
     472                5:                                       ArrayType::Normal, 0);
     473                5:   llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
     474                 : 
     475                5:   llvm::Value *Collection = EmitScalarExpr(S.getCollection());
     476                 : 
     477                5:   CallArgList Args;
     478                 :   Args.push_back(std::make_pair(RValue::get(StatePtr),
     479                5:                                 getContext().getPointerType(StateTy)));
     480                 : 
     481                 :   Args.push_back(std::make_pair(RValue::get(ItemsPtr),
     482                5:                                 getContext().getPointerType(ItemsTy)));
     483                 : 
     484                5:   const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy);
     485                5:   llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems);
     486                 :   Args.push_back(std::make_pair(RValue::get(Count),
     487                5:                                 getContext().UnsignedLongTy));
     488                 : 
     489                 :   RValue CountRV =
     490                 :     CGM.getObjCRuntime().GenerateMessageSend(*this,
     491                 :                                              getContext().UnsignedLongTy,
     492                 :                                              FastEnumSel,
     493                5:                                              Collection, false, Args);
     494                 : 
     495                 :   llvm::Value *LimitPtr = CreateMemTemp(getContext().UnsignedLongTy,
     496                5:                                         "limit.ptr");
     497                5:   Builder.CreateStore(CountRV.getScalarVal(), LimitPtr);
     498                 : 
     499                5:   llvm::BasicBlock *NoElements = createBasicBlock("noelements");
     500                5:   llvm::BasicBlock *SetStartMutations = createBasicBlock("setstartmutations");
     501                 : 
     502                5:   llvm::Value *Limit = Builder.CreateLoad(LimitPtr);
     503                5:   llvm::Value *Zero = llvm::Constant::getNullValue(UnsignedLongLTy);
     504                 : 
     505                5:   llvm::Value *IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero");
     506                5:   Builder.CreateCondBr(IsZero, NoElements, SetStartMutations);
     507                 : 
     508                5:   EmitBlock(SetStartMutations);
     509                 : 
     510                5:   llvm::Value *StartMutationsPtr = CreateMemTemp(getContext().UnsignedLongTy);
     511                 : 
     512                 :   llvm::Value *StateMutationsPtrPtr =
     513                5:     Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr");
     514                 :   llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr,
     515                5:                                                       "mutationsptr");
     516                 : 
     517                 :   llvm::Value *StateMutations = Builder.CreateLoad(StateMutationsPtr,
     518                5:                                                    "mutations");
     519                 : 
     520                5:   Builder.CreateStore(StateMutations, StartMutationsPtr);
     521                 : 
     522                5:   llvm::BasicBlock *LoopStart = createBasicBlock("loopstart");
     523                5:   EmitBlock(LoopStart);
     524                 : 
     525                 :   llvm::Value *CounterPtr = CreateMemTemp(getContext().UnsignedLongTy,
     526                5:                                        "counter.ptr");
     527                5:   Builder.CreateStore(Zero, CounterPtr);
     528                 : 
     529                5:   llvm::BasicBlock *LoopBody = createBasicBlock("loopbody");
     530                5:   EmitBlock(LoopBody);
     531                 : 
     532                5:   StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr");
     533                5:   StateMutations = Builder.CreateLoad(StateMutationsPtr, "statemutations");
     534                 : 
     535                 :   llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr,
     536                5:                                                    "mutations");
     537                 :   llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations,
     538                 :                                                      StartMutations,
     539                5:                                                      "tobool");
     540                 : 
     541                 : 
     542                5:   llvm::BasicBlock *WasMutated = createBasicBlock("wasmutated");
     543                5:   llvm::BasicBlock *WasNotMutated = createBasicBlock("wasnotmutated");
     544                 : 
     545                5:   Builder.CreateCondBr(MutationsEqual, WasNotMutated, WasMutated);
     546                 : 
     547                5:   EmitBlock(WasMutated);
     548                 :   llvm::Value *V =
     549                 :     Builder.CreateBitCast(Collection,
     550                 :                           ConvertType(getContext().getObjCIdType()),
     551                5:                           "tmp");
     552                5:   CallArgList Args2;
     553                 :   Args2.push_back(std::make_pair(RValue::get(V),
     554                5:                                 getContext().getObjCIdType()));
     555                 :   // FIXME: We shouldn't need to get the function info here, the runtime already
     556                 :   // should have computed it to build the function.
     557                 :   EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2,
     558                 :                                           CC_Default, false),
     559                5:            EnumerationMutationFn, ReturnValueSlot(), Args2);
     560                 : 
     561                5:   EmitBlock(WasNotMutated);
     562                 : 
     563                 :   llvm::Value *StateItemsPtr =
     564                5:     Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr");
     565                 : 
     566                5:   llvm::Value *Counter = Builder.CreateLoad(CounterPtr, "counter");
     567                 : 
     568                 :   llvm::Value *EnumStateItems = Builder.CreateLoad(StateItemsPtr,
     569                5:                                                    "stateitems");
     570                 : 
     571                 :   llvm::Value *CurrentItemPtr =
     572                5:     Builder.CreateGEP(EnumStateItems, Counter, "currentitem.ptr");
     573                 : 
     574                5:   llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr, "currentitem");
     575                 : 
     576                 :   // Cast the item to the right type.
     577                 :   CurrentItem = Builder.CreateBitCast(CurrentItem,
     578                5:                                       ConvertType(ElementTy), "tmp");
     579                 : 
                        0: branch 0 not taken
                        5: branch 1 taken
     580                5:   if (!DeclAddress) {
     581                0:     LValue LV = EmitLValue(cast<Expr>(S.getElement()));
     582                 : 
     583                 :     // Set the value to null.
     584                0:     Builder.CreateStore(CurrentItem, LV.getAddress());
     585                 :   } else
     586                5:     Builder.CreateStore(CurrentItem, DeclAddress);
     587                 : 
     588                 :   // Increment the counter.
     589                 :   Counter = Builder.CreateAdd(Counter,
     590                5:                               llvm::ConstantInt::get(UnsignedLongLTy, 1));
     591                5:   Builder.CreateStore(Counter, CounterPtr);
     592                 : 
     593                5:   llvm::BasicBlock *LoopEnd = createBasicBlock("loopend");
     594                5:   llvm::BasicBlock *AfterBody = createBasicBlock("afterbody");
     595                 : 
     596                5:   BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
     597                 : 
     598                5:   EmitStmt(S.getBody());
     599                 : 
     600                5:   BreakContinueStack.pop_back();
     601                 : 
     602                5:   EmitBlock(AfterBody);
     603                 : 
     604                5:   llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore");
     605                 : 
     606                5:   Counter = Builder.CreateLoad(CounterPtr);
     607                5:   Limit = Builder.CreateLoad(LimitPtr);
     608                5:   llvm::Value *IsLess = Builder.CreateICmpULT(Counter, Limit, "isless");
     609                5:   Builder.CreateCondBr(IsLess, LoopBody, FetchMore);
     610                 : 
     611                 :   // Fetch more elements.
     612                5:   EmitBlock(FetchMore);
     613                 : 
     614                 :   CountRV =
     615                 :     CGM.getObjCRuntime().GenerateMessageSend(*this,
     616                 :                                              getContext().UnsignedLongTy,
     617                 :                                              FastEnumSel,
     618                5:                                              Collection, false, Args);
     619                5:   Builder.CreateStore(CountRV.getScalarVal(), LimitPtr);
     620                5:   Limit = Builder.CreateLoad(LimitPtr);
     621                 : 
     622                5:   IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero");
     623                5:   Builder.CreateCondBr(IsZero, NoElements, LoopStart);
     624                 : 
     625                 :   // No more elements.
     626                5:   EmitBlock(NoElements);
     627                 : 
                        0: branch 0 not taken
                        5: branch 1 taken
     628                5:   if (!DeclAddress) {
     629                 :     // If the element was not a declaration, set it to be null.
     630                 : 
     631                0:     LValue LV = EmitLValue(cast<Expr>(S.getElement()));
     632                 : 
     633                 :     // Set the value to null.
     634                 :     Builder.CreateStore(llvm::Constant::getNullValue(ConvertType(ElementTy)),
     635                0:                         LV.getAddress());
     636                 :   }
     637                 : 
     638                5:   EmitBlock(LoopEnd);
     639                 : }
     640                 : 
     641               11: void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) {
     642               11:   CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S);
     643               11: }
     644                 : 
     645                8: void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) {
     646                8:   CGM.getObjCRuntime().EmitThrowStmt(*this, S);
     647                8: }
     648                 : 
     649                 : void CodeGenFunction::EmitObjCAtSynchronizedStmt(
     650                8:                                               const ObjCAtSynchronizedStmt &S) {
     651                8:   CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S);
     652                8: }
     653                 : 
                      135: branch 0 taken
                      135: branch 1 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 6 not taken
                      135: branch 7 taken
     654              135: CGObjCRuntime::~CGObjCRuntime() {}

Generated: 2010-02-10 01:31 by zcov