Home | History | Annotate | Line # | Download | only in CodeGen
      1 //==- CGObjCRuntime.cpp - Interface to Shared Objective-C Runtime Features ==//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This abstract class defines the interface for Objective-C runtime-specific
     10 // code generation.  It provides some concrete helper methods for functionality
     11 // shared between all (or most) of the Objective-C runtimes supported by clang.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "CGObjCRuntime.h"
     16 #include "CGCXXABI.h"
     17 #include "CGCleanup.h"
     18 #include "CGRecordLayout.h"
     19 #include "CodeGenFunction.h"
     20 #include "CodeGenModule.h"
     21 #include "clang/AST/RecordLayout.h"
     22 #include "clang/AST/StmtObjC.h"
     23 #include "clang/CodeGen/CGFunctionInfo.h"
     24 #include "clang/CodeGen/CodeGenABITypes.h"
     25 #include "llvm/Support/SaveAndRestore.h"
     26 
     27 using namespace clang;
     28 using namespace CodeGen;
     29 
     30 uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
     31                                               const ObjCInterfaceDecl *OID,
     32                                               const ObjCIvarDecl *Ivar) {
     33   return CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar) /
     34          CGM.getContext().getCharWidth();
     35 }
     36 
     37 uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
     38                                               const ObjCImplementationDecl *OID,
     39                                               const ObjCIvarDecl *Ivar) {
     40   return CGM.getContext().lookupFieldBitOffset(OID->getClassInterface(), OID,
     41                                                Ivar) /
     42          CGM.getContext().getCharWidth();
     43 }
     44 
     45 unsigned CGObjCRuntime::ComputeBitfieldBitOffset(
     46     CodeGen::CodeGenModule &CGM,
     47     const ObjCInterfaceDecl *ID,
     48     const ObjCIvarDecl *Ivar) {
     49   return CGM.getContext().lookupFieldBitOffset(ID, ID->getImplementation(),
     50                                                Ivar);
     51 }
     52 
     53 LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
     54                                                const ObjCInterfaceDecl *OID,
     55                                                llvm::Value *BaseValue,
     56                                                const ObjCIvarDecl *Ivar,
     57                                                unsigned CVRQualifiers,
     58                                                llvm::Value *Offset) {
     59   // Compute (type*) ( (char *) BaseValue + Offset)
     60   QualType InterfaceTy{OID->getTypeForDecl(), 0};
     61   QualType ObjectPtrTy =
     62       CGF.CGM.getContext().getObjCObjectPointerType(InterfaceTy);
     63   QualType IvarTy =
     64       Ivar->getUsageType(ObjectPtrTy).withCVRQualifiers(CVRQualifiers);
     65   llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
     66   llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy);
     67   V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, V, Offset, "add.ptr");
     68 
     69   if (!Ivar->isBitField()) {
     70     V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
     71     LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy);
     72     return LV;
     73   }
     74 
     75   // We need to compute an access strategy for this bit-field. We are given the
     76   // offset to the first byte in the bit-field, the sub-byte offset is taken
     77   // from the original layout. We reuse the normal bit-field access strategy by
     78   // treating this as an access to a struct where the bit-field is in byte 0,
     79   // and adjust the containing type size as appropriate.
     80   //
     81   // FIXME: Note that currently we make a very conservative estimate of the
     82   // alignment of the bit-field, because (a) it is not clear what guarantees the
     83   // runtime makes us, and (b) we don't have a way to specify that the struct is
     84   // at an alignment plus offset.
     85   //
     86   // Note, there is a subtle invariant here: we can only call this routine on
     87   // non-synthesized ivars but we may be called for synthesized ivars.  However,
     88   // a synthesized ivar can never be a bit-field, so this is safe.
     89   uint64_t FieldBitOffset =
     90       CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar);
     91   uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth();
     92   uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign();
     93   uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext());
     94   CharUnits StorageSize = CGF.CGM.getContext().toCharUnitsFromBits(
     95       llvm::alignTo(BitOffset + BitFieldSize, AlignmentBits));
     96   CharUnits Alignment = CGF.CGM.getContext().toCharUnitsFromBits(AlignmentBits);
     97 
     98   // Allocate a new CGBitFieldInfo object to describe this access.
     99   //
    100   // FIXME: This is incredibly wasteful, these should be uniqued or part of some
    101   // layout object. However, this is blocked on other cleanups to the
    102   // Objective-C code, so for now we just live with allocating a bunch of these
    103   // objects.
    104   CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo(
    105     CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize,
    106                              CGF.CGM.getContext().toBits(StorageSize),
    107                              CharUnits::fromQuantity(0)));
    108 
    109   Address Addr(V, Alignment);
    110   Addr = CGF.Builder.CreateElementBitCast(Addr,
    111                                    llvm::Type::getIntNTy(CGF.getLLVMContext(),
    112                                                          Info->StorageSize));
    113   return LValue::MakeBitfield(Addr, *Info, IvarTy,
    114                               LValueBaseInfo(AlignmentSource::Decl),
    115                               TBAAAccessInfo());
    116 }
    117 
    118 namespace {
    119   struct CatchHandler {
    120     const VarDecl *Variable;
    121     const Stmt *Body;
    122     llvm::BasicBlock *Block;
    123     llvm::Constant *TypeInfo;
    124     /// Flags used to differentiate cleanups and catchalls in Windows SEH
    125     unsigned Flags;
    126   };
    127 
    128   struct CallObjCEndCatch final : EHScopeStack::Cleanup {
    129     CallObjCEndCatch(bool MightThrow, llvm::FunctionCallee Fn)
    130         : MightThrow(MightThrow), Fn(Fn) {}
    131     bool MightThrow;
    132     llvm::FunctionCallee Fn;
    133 
    134     void Emit(CodeGenFunction &CGF, Flags flags) override {
    135       if (MightThrow)
    136         CGF.EmitRuntimeCallOrInvoke(Fn);
    137       else
    138         CGF.EmitNounwindRuntimeCall(Fn);
    139     }
    140   };
    141 }
    142 
    143 void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
    144                                      const ObjCAtTryStmt &S,
    145                                      llvm::FunctionCallee beginCatchFn,
    146                                      llvm::FunctionCallee endCatchFn,
    147                                      llvm::FunctionCallee exceptionRethrowFn) {
    148   // Jump destination for falling out of catch bodies.
    149   CodeGenFunction::JumpDest Cont;
    150   if (S.getNumCatchStmts())
    151     Cont = CGF.getJumpDestInCurrentScope("eh.cont");
    152 
    153   bool useFunclets = EHPersonality::get(CGF).usesFuncletPads();
    154 
    155   CodeGenFunction::FinallyInfo FinallyInfo;
    156   if (!useFunclets)
    157     if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
    158       FinallyInfo.enter(CGF, Finally->getFinallyBody(),
    159                         beginCatchFn, endCatchFn, exceptionRethrowFn);
    160 
    161   SmallVector<CatchHandler, 8> Handlers;
    162 
    163 
    164   // Enter the catch, if there is one.
    165   if (S.getNumCatchStmts()) {
    166     for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
    167       const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I);
    168       const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
    169 
    170       Handlers.push_back(CatchHandler());
    171       CatchHandler &Handler = Handlers.back();
    172       Handler.Variable = CatchDecl;
    173       Handler.Body = CatchStmt->getCatchBody();
    174       Handler.Block = CGF.createBasicBlock("catch");
    175       Handler.Flags = 0;
    176 
    177       // @catch(...) always matches.
    178       if (!CatchDecl) {
    179         auto catchAll = getCatchAllTypeInfo();
    180         Handler.TypeInfo = catchAll.RTTI;
    181         Handler.Flags = catchAll.Flags;
    182         // Don't consider any other catches.
    183         break;
    184       }
    185 
    186       Handler.TypeInfo = GetEHType(CatchDecl->getType());
    187     }
    188 
    189     EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
    190     for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
    191       Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags }, Handlers[I].Block);
    192   }
    193 
    194   if (useFunclets)
    195     if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) {
    196         CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
    197         if (!CGF.CurSEHParent)
    198             CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl);
    199         // Outline the finally block.
    200         const Stmt *FinallyBlock = Finally->getFinallyBody();
    201         HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock);
    202 
    203         // Emit the original filter expression, convert to i32, and return.
    204         HelperCGF.EmitStmt(FinallyBlock);
    205 
    206         HelperCGF.FinishFunction(FinallyBlock->getEndLoc());
    207 
    208         llvm::Function *FinallyFunc = HelperCGF.CurFn;
    209 
    210 
    211         // Push a cleanup for __finally blocks.
    212         CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc);
    213     }
    214 
    215 
    216   // Emit the try body.
    217   CGF.EmitStmt(S.getTryBody());
    218 
    219   // Leave the try.
    220   if (S.getNumCatchStmts())
    221     CGF.popCatchScope();
    222 
    223   // Remember where we were.
    224   CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
    225 
    226   // Emit the handlers.
    227   for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
    228     CatchHandler &Handler = Handlers[I];
    229 
    230     CGF.EmitBlock(Handler.Block);
    231     llvm::CatchPadInst *CPI = nullptr;
    232     SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(CGF.CurrentFuncletPad);
    233     if (useFunclets)
    234       if ((CPI = dyn_cast_or_null<llvm::CatchPadInst>(Handler.Block->getFirstNonPHI()))) {
    235         CGF.CurrentFuncletPad = CPI;
    236         CPI->setOperand(2, CGF.getExceptionSlot().getPointer());
    237       }
    238     llvm::Value *RawExn = CGF.getExceptionFromSlot();
    239 
    240     // Enter the catch.
    241     llvm::Value *Exn = RawExn;
    242     if (beginCatchFn)
    243       Exn = CGF.EmitNounwindRuntimeCall(beginCatchFn, RawExn, "exn.adjusted");
    244 
    245     CodeGenFunction::LexicalScope cleanups(CGF, Handler.Body->getSourceRange());
    246 
    247     if (endCatchFn) {
    248       // Add a cleanup to leave the catch.
    249       bool EndCatchMightThrow = (Handler.Variable == nullptr);
    250 
    251       CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
    252                                                 EndCatchMightThrow,
    253                                                 endCatchFn);
    254     }
    255 
    256     // Bind the catch parameter if it exists.
    257     if (const VarDecl *CatchParam = Handler.Variable) {
    258       llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType());
    259       llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);
    260 
    261       CGF.EmitAutoVarDecl(*CatchParam);
    262       EmitInitOfCatchParam(CGF, CastExn, CatchParam);
    263     }
    264     if (CPI)
    265         CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
    266 
    267     CGF.ObjCEHValueStack.push_back(Exn);
    268     CGF.EmitStmt(Handler.Body);
    269     CGF.ObjCEHValueStack.pop_back();
    270 
    271     // Leave any cleanups associated with the catch.
    272     cleanups.ForceCleanup();
    273 
    274     CGF.EmitBranchThroughCleanup(Cont);
    275   }
    276 
    277   // Go back to the try-statement fallthrough.
    278   CGF.Builder.restoreIP(SavedIP);
    279 
    280   // Pop out of the finally.
    281   if (!useFunclets && S.getFinallyStmt())
    282     FinallyInfo.exit(CGF);
    283 
    284   if (Cont.isValid())
    285     CGF.EmitBlock(Cont.getBlock());
    286 }
    287 
    288 void CGObjCRuntime::EmitInitOfCatchParam(CodeGenFunction &CGF,
    289                                          llvm::Value *exn,
    290                                          const VarDecl *paramDecl) {
    291 
    292   Address paramAddr = CGF.GetAddrOfLocalVar(paramDecl);
    293 
    294   switch (paramDecl->getType().getQualifiers().getObjCLifetime()) {
    295   case Qualifiers::OCL_Strong:
    296     exn = CGF.EmitARCRetainNonBlock(exn);
    297     LLVM_FALLTHROUGH;
    298 
    299   case Qualifiers::OCL_None:
    300   case Qualifiers::OCL_ExplicitNone:
    301   case Qualifiers::OCL_Autoreleasing:
    302     CGF.Builder.CreateStore(exn, paramAddr);
    303     return;
    304 
    305   case Qualifiers::OCL_Weak:
    306     CGF.EmitARCInitWeak(paramAddr, exn);
    307     return;
    308   }
    309   llvm_unreachable("invalid ownership qualifier");
    310 }
    311 
    312 namespace {
    313   struct CallSyncExit final : EHScopeStack::Cleanup {
    314     llvm::FunctionCallee SyncExitFn;
    315     llvm::Value *SyncArg;
    316     CallSyncExit(llvm::FunctionCallee SyncExitFn, llvm::Value *SyncArg)
    317         : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
    318 
    319     void Emit(CodeGenFunction &CGF, Flags flags) override {
    320       CGF.EmitNounwindRuntimeCall(SyncExitFn, SyncArg);
    321     }
    322   };
    323 }
    324 
    325 void CGObjCRuntime::EmitAtSynchronizedStmt(CodeGenFunction &CGF,
    326                                            const ObjCAtSynchronizedStmt &S,
    327                                            llvm::FunctionCallee syncEnterFn,
    328                                            llvm::FunctionCallee syncExitFn) {
    329   CodeGenFunction::RunCleanupsScope cleanups(CGF);
    330 
    331   // Evaluate the lock operand.  This is guaranteed to dominate the
    332   // ARC release and lock-release cleanups.
    333   const Expr *lockExpr = S.getSynchExpr();
    334   llvm::Value *lock;
    335   if (CGF.getLangOpts().ObjCAutoRefCount) {
    336     lock = CGF.EmitARCRetainScalarExpr(lockExpr);
    337     lock = CGF.EmitObjCConsumeObject(lockExpr->getType(), lock);
    338   } else {
    339     lock = CGF.EmitScalarExpr(lockExpr);
    340   }
    341   lock = CGF.Builder.CreateBitCast(lock, CGF.VoidPtrTy);
    342 
    343   // Acquire the lock.
    344   CGF.Builder.CreateCall(syncEnterFn, lock)->setDoesNotThrow();
    345 
    346   // Register an all-paths cleanup to release the lock.
    347   CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup, syncExitFn, lock);
    348 
    349   // Emit the body of the statement.
    350   CGF.EmitStmt(S.getSynchBody());
    351 }
    352 
    353 /// Compute the pointer-to-function type to which a message send
    354 /// should be casted in order to correctly call the given method
    355 /// with the given arguments.
    356 ///
    357 /// \param method - may be null
    358 /// \param resultType - the result type to use if there's no method
    359 /// \param callArgs - the actual arguments, including implicit ones
    360 CGObjCRuntime::MessageSendInfo
    361 CGObjCRuntime::getMessageSendInfo(const ObjCMethodDecl *method,
    362                                   QualType resultType,
    363                                   CallArgList &callArgs) {
    364   // If there's a method, use information from that.
    365   if (method) {
    366     const CGFunctionInfo &signature =
    367       CGM.getTypes().arrangeObjCMessageSendSignature(method, callArgs[0].Ty);
    368 
    369     llvm::PointerType *signatureType =
    370       CGM.getTypes().GetFunctionType(signature)->getPointerTo();
    371 
    372     const CGFunctionInfo &signatureForCall =
    373       CGM.getTypes().arrangeCall(signature, callArgs);
    374 
    375     return MessageSendInfo(signatureForCall, signatureType);
    376   }
    377 
    378   // There's no method;  just use a default CC.
    379   const CGFunctionInfo &argsInfo =
    380     CGM.getTypes().arrangeUnprototypedObjCMessageSend(resultType, callArgs);
    381 
    382   // Derive the signature to call from that.
    383   llvm::PointerType *signatureType =
    384     CGM.getTypes().GetFunctionType(argsInfo)->getPointerTo();
    385   return MessageSendInfo(argsInfo, signatureType);
    386 }
    387 
    388 llvm::Constant *
    389 clang::CodeGen::emitObjCProtocolObject(CodeGenModule &CGM,
    390                                        const ObjCProtocolDecl *protocol) {
    391   return CGM.getObjCRuntime().GetOrEmitProtocol(protocol);
    392 }
    393 
    394 std::string CGObjCRuntime::getSymbolNameForMethod(const ObjCMethodDecl *OMD,
    395                                                   bool includeCategoryName) {
    396   std::string buffer;
    397   llvm::raw_string_ostream out(buffer);
    398   CGM.getCXXABI().getMangleContext().mangleObjCMethodName(OMD, out,
    399                                        /*includePrefixByte=*/true,
    400                                        includeCategoryName);
    401   return buffer;
    402 }
    403