1221339Sdim//==- CGObjCRuntime.cpp - Interface to Shared Objective-C Runtime Features ==// 2221339Sdim// 3221339Sdim// The LLVM Compiler Infrastructure 4221339Sdim// 5221339Sdim// This file is distributed under the University of Illinois Open Source 6221339Sdim// License. See LICENSE.TXT for details. 7221339Sdim// 8221339Sdim//===----------------------------------------------------------------------===// 9221339Sdim// 10221339Sdim// This abstract class defines the interface for Objective-C runtime-specific 11221339Sdim// code generation. It provides some concrete helper methods for functionality 12221339Sdim// shared between all (or most) of the Objective-C runtimes supported by clang. 13221339Sdim// 14221339Sdim//===----------------------------------------------------------------------===// 15221339Sdim 16221339Sdim#include "CGObjCRuntime.h" 17249423Sdim#include "CGCleanup.h" 18221339Sdim#include "CGRecordLayout.h" 19249423Sdim#include "CodeGenFunction.h" 20221339Sdim#include "CodeGenModule.h" 21221339Sdim#include "clang/AST/RecordLayout.h" 22221339Sdim#include "clang/AST/StmtObjC.h" 23263508Sdim#include "clang/CodeGen/CGFunctionInfo.h" 24221339Sdim#include "llvm/Support/CallSite.h" 25221339Sdim 26221339Sdimusing namespace clang; 27221339Sdimusing namespace CodeGen; 28221339Sdim 29221339Sdimstatic uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, 30221339Sdim const ObjCInterfaceDecl *OID, 31221339Sdim const ObjCImplementationDecl *ID, 32221339Sdim const ObjCIvarDecl *Ivar) { 33221339Sdim const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); 34221339Sdim 35221339Sdim // FIXME: We should eliminate the need to have ObjCImplementationDecl passed 36221339Sdim // in here; it should never be necessary because that should be the lexical 37221339Sdim // decl context for the ivar. 38221339Sdim 39221339Sdim // If we know have an implementation (and the ivar is in it) then 40221339Sdim // look up in the implementation layout. 41221339Sdim const ASTRecordLayout *RL; 42234353Sdim if (ID && declaresSameEntity(ID->getClassInterface(), Container)) 43221339Sdim RL = &CGM.getContext().getASTObjCImplementationLayout(ID); 44221339Sdim else 45221339Sdim RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); 46221339Sdim 47221339Sdim // Compute field index. 48221339Sdim // 49221339Sdim // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is 50221339Sdim // implemented. This should be fixed to get the information from the layout 51221339Sdim // directly. 52221339Sdim unsigned Index = 0; 53224145Sdim 54226633Sdim for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin(); 55224145Sdim IVD; IVD = IVD->getNextIvar()) { 56224145Sdim if (Ivar == IVD) 57221339Sdim break; 58221339Sdim ++Index; 59221339Sdim } 60221339Sdim assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!"); 61221339Sdim 62221339Sdim return RL->getFieldOffset(Index); 63221339Sdim} 64221339Sdim 65221339Sdimuint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 66221339Sdim const ObjCInterfaceDecl *OID, 67221339Sdim const ObjCIvarDecl *Ivar) { 68221339Sdim return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 69221339Sdim CGM.getContext().getCharWidth(); 70221339Sdim} 71221339Sdim 72221339Sdimuint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 73221339Sdim const ObjCImplementationDecl *OID, 74221339Sdim const ObjCIvarDecl *Ivar) { 75221339Sdim return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 76221339Sdim CGM.getContext().getCharWidth(); 77221339Sdim} 78221339Sdim 79243830Sdimunsigned CGObjCRuntime::ComputeBitfieldBitOffset( 80243830Sdim CodeGen::CodeGenModule &CGM, 81243830Sdim const ObjCInterfaceDecl *ID, 82243830Sdim const ObjCIvarDecl *Ivar) { 83243830Sdim return LookupFieldBitOffset(CGM, ID, ID->getImplementation(), Ivar); 84243830Sdim} 85243830Sdim 86221339SdimLValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, 87221339Sdim const ObjCInterfaceDecl *OID, 88221339Sdim llvm::Value *BaseValue, 89221339Sdim const ObjCIvarDecl *Ivar, 90221339Sdim unsigned CVRQualifiers, 91221339Sdim llvm::Value *Offset) { 92221339Sdim // Compute (type*) ( (char *) BaseValue + Offset) 93221339Sdim QualType IvarTy = Ivar->getType(); 94226633Sdim llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); 95249423Sdim llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy); 96221339Sdim V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr"); 97221339Sdim 98221339Sdim if (!Ivar->isBitField()) { 99249423Sdim V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); 100234353Sdim LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); 101221339Sdim LV.getQuals().addCVRQualifiers(CVRQualifiers); 102221339Sdim return LV; 103221339Sdim } 104221339Sdim 105221339Sdim // We need to compute an access strategy for this bit-field. We are given the 106221339Sdim // offset to the first byte in the bit-field, the sub-byte offset is taken 107221339Sdim // from the original layout. We reuse the normal bit-field access strategy by 108221339Sdim // treating this as an access to a struct where the bit-field is in byte 0, 109221339Sdim // and adjust the containing type size as appropriate. 110221339Sdim // 111221339Sdim // FIXME: Note that currently we make a very conservative estimate of the 112221339Sdim // alignment of the bit-field, because (a) it is not clear what guarantees the 113221339Sdim // runtime makes us, and (b) we don't have a way to specify that the struct is 114221339Sdim // at an alignment plus offset. 115221339Sdim // 116221339Sdim // Note, there is a subtle invariant here: we can only call this routine on 117221339Sdim // non-synthesized ivars but we may be called for synthesized ivars. However, 118221339Sdim // a synthesized ivar can never be a bit-field, so this is safe. 119221339Sdim uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar); 120221339Sdim uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); 121251662Sdim uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign(); 122226633Sdim uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); 123249423Sdim CharUnits StorageSize = 124249423Sdim CGF.CGM.getContext().toCharUnitsFromBits( 125249423Sdim llvm::RoundUpToAlignment(BitOffset + BitFieldSize, AlignmentBits)); 126249423Sdim CharUnits Alignment = CGF.CGM.getContext().toCharUnitsFromBits(AlignmentBits); 127221339Sdim 128221339Sdim // Allocate a new CGBitFieldInfo object to describe this access. 129221339Sdim // 130221339Sdim // FIXME: This is incredibly wasteful, these should be uniqued or part of some 131221339Sdim // layout object. However, this is blocked on other cleanups to the 132221339Sdim // Objective-C code, so for now we just live with allocating a bunch of these 133221339Sdim // objects. 134221339Sdim CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo( 135221339Sdim CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize, 136249423Sdim CGF.CGM.getContext().toBits(StorageSize), 137249423Sdim Alignment.getQuantity())); 138221339Sdim 139249423Sdim V = CGF.Builder.CreateBitCast(V, 140249423Sdim llvm::Type::getIntNPtrTy(CGF.getLLVMContext(), 141249423Sdim Info->StorageSize)); 142221339Sdim return LValue::MakeBitfield(V, *Info, 143239462Sdim IvarTy.withCVRQualifiers(CVRQualifiers), 144249423Sdim Alignment); 145221339Sdim} 146221339Sdim 147221339Sdimnamespace { 148221339Sdim struct CatchHandler { 149221339Sdim const VarDecl *Variable; 150221339Sdim const Stmt *Body; 151221339Sdim llvm::BasicBlock *Block; 152221339Sdim llvm::Value *TypeInfo; 153221339Sdim }; 154221339Sdim 155221339Sdim struct CallObjCEndCatch : EHScopeStack::Cleanup { 156221339Sdim CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) : 157221339Sdim MightThrow(MightThrow), Fn(Fn) {} 158221339Sdim bool MightThrow; 159221339Sdim llvm::Value *Fn; 160221339Sdim 161224145Sdim void Emit(CodeGenFunction &CGF, Flags flags) { 162221339Sdim if (!MightThrow) { 163221339Sdim CGF.Builder.CreateCall(Fn)->setDoesNotThrow(); 164221339Sdim return; 165221339Sdim } 166221339Sdim 167249423Sdim CGF.EmitRuntimeCallOrInvoke(Fn); 168221339Sdim } 169221339Sdim }; 170221339Sdim} 171221339Sdim 172221339Sdim 173221339Sdimvoid CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, 174221339Sdim const ObjCAtTryStmt &S, 175223017Sdim llvm::Constant *beginCatchFn, 176223017Sdim llvm::Constant *endCatchFn, 177223017Sdim llvm::Constant *exceptionRethrowFn) { 178221339Sdim // Jump destination for falling out of catch bodies. 179221339Sdim CodeGenFunction::JumpDest Cont; 180221339Sdim if (S.getNumCatchStmts()) 181221339Sdim Cont = CGF.getJumpDestInCurrentScope("eh.cont"); 182221339Sdim 183221339Sdim CodeGenFunction::FinallyInfo FinallyInfo; 184221339Sdim if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) 185224145Sdim FinallyInfo.enter(CGF, Finally->getFinallyBody(), 186224145Sdim beginCatchFn, endCatchFn, exceptionRethrowFn); 187221339Sdim 188226633Sdim SmallVector<CatchHandler, 8> Handlers; 189221339Sdim 190221339Sdim // Enter the catch, if there is one. 191221339Sdim if (S.getNumCatchStmts()) { 192221339Sdim for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) { 193221339Sdim const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I); 194221339Sdim const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); 195221339Sdim 196221339Sdim Handlers.push_back(CatchHandler()); 197221339Sdim CatchHandler &Handler = Handlers.back(); 198221339Sdim Handler.Variable = CatchDecl; 199221339Sdim Handler.Body = CatchStmt->getCatchBody(); 200221339Sdim Handler.Block = CGF.createBasicBlock("catch"); 201221339Sdim 202221339Sdim // @catch(...) always matches. 203221339Sdim if (!CatchDecl) { 204221339Sdim Handler.TypeInfo = 0; // catch-all 205221339Sdim // Don't consider any other catches. 206221339Sdim break; 207221339Sdim } 208221339Sdim 209221339Sdim Handler.TypeInfo = GetEHType(CatchDecl->getType()); 210221339Sdim } 211221339Sdim 212221339Sdim EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); 213221339Sdim for (unsigned I = 0, E = Handlers.size(); I != E; ++I) 214221339Sdim Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block); 215221339Sdim } 216221339Sdim 217221339Sdim // Emit the try body. 218221339Sdim CGF.EmitStmt(S.getTryBody()); 219221339Sdim 220221339Sdim // Leave the try. 221221339Sdim if (S.getNumCatchStmts()) 222226633Sdim CGF.popCatchScope(); 223221339Sdim 224221339Sdim // Remember where we were. 225221339Sdim CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); 226221339Sdim 227221339Sdim // Emit the handlers. 228221339Sdim for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { 229221339Sdim CatchHandler &Handler = Handlers[I]; 230221339Sdim 231221339Sdim CGF.EmitBlock(Handler.Block); 232226633Sdim llvm::Value *RawExn = CGF.getExceptionFromSlot(); 233221339Sdim 234221339Sdim // Enter the catch. 235221339Sdim llvm::Value *Exn = RawExn; 236221339Sdim if (beginCatchFn) { 237221339Sdim Exn = CGF.Builder.CreateCall(beginCatchFn, RawExn, "exn.adjusted"); 238221339Sdim cast<llvm::CallInst>(Exn)->setDoesNotThrow(); 239221339Sdim } 240221339Sdim 241234353Sdim CodeGenFunction::LexicalScope cleanups(CGF, Handler.Body->getSourceRange()); 242223017Sdim 243221339Sdim if (endCatchFn) { 244221339Sdim // Add a cleanup to leave the catch. 245221339Sdim bool EndCatchMightThrow = (Handler.Variable == 0); 246221339Sdim 247221339Sdim CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup, 248221339Sdim EndCatchMightThrow, 249221339Sdim endCatchFn); 250221339Sdim } 251221339Sdim 252221339Sdim // Bind the catch parameter if it exists. 253221339Sdim if (const VarDecl *CatchParam = Handler.Variable) { 254226633Sdim llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType()); 255221339Sdim llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType); 256221339Sdim 257221339Sdim CGF.EmitAutoVarDecl(*CatchParam); 258234353Sdim 259234353Sdim llvm::Value *CatchParamAddr = CGF.GetAddrOfLocalVar(CatchParam); 260234353Sdim 261234353Sdim switch (CatchParam->getType().getQualifiers().getObjCLifetime()) { 262234353Sdim case Qualifiers::OCL_Strong: 263234353Sdim CastExn = CGF.EmitARCRetainNonBlock(CastExn); 264234353Sdim // fallthrough 265234353Sdim 266234353Sdim case Qualifiers::OCL_None: 267234353Sdim case Qualifiers::OCL_ExplicitNone: 268234353Sdim case Qualifiers::OCL_Autoreleasing: 269234353Sdim CGF.Builder.CreateStore(CastExn, CatchParamAddr); 270234353Sdim break; 271234353Sdim 272234353Sdim case Qualifiers::OCL_Weak: 273234353Sdim CGF.EmitARCInitWeak(CatchParamAddr, CastExn); 274234353Sdim break; 275234353Sdim } 276221339Sdim } 277221339Sdim 278221339Sdim CGF.ObjCEHValueStack.push_back(Exn); 279221339Sdim CGF.EmitStmt(Handler.Body); 280221339Sdim CGF.ObjCEHValueStack.pop_back(); 281221339Sdim 282223017Sdim // Leave any cleanups associated with the catch. 283223017Sdim cleanups.ForceCleanup(); 284221339Sdim 285221339Sdim CGF.EmitBranchThroughCleanup(Cont); 286221339Sdim } 287221339Sdim 288221339Sdim // Go back to the try-statement fallthrough. 289221339Sdim CGF.Builder.restoreIP(SavedIP); 290221339Sdim 291224145Sdim // Pop out of the finally. 292221339Sdim if (S.getFinallyStmt()) 293224145Sdim FinallyInfo.exit(CGF); 294221339Sdim 295221339Sdim if (Cont.isValid()) 296221339Sdim CGF.EmitBlock(Cont.getBlock()); 297221339Sdim} 298221339Sdim 299221339Sdimnamespace { 300221339Sdim struct CallSyncExit : EHScopeStack::Cleanup { 301221339Sdim llvm::Value *SyncExitFn; 302221339Sdim llvm::Value *SyncArg; 303221339Sdim CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg) 304221339Sdim : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} 305221339Sdim 306224145Sdim void Emit(CodeGenFunction &CGF, Flags flags) { 307221339Sdim CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow(); 308221339Sdim } 309221339Sdim }; 310221339Sdim} 311221339Sdim 312221339Sdimvoid CGObjCRuntime::EmitAtSynchronizedStmt(CodeGenFunction &CGF, 313221339Sdim const ObjCAtSynchronizedStmt &S, 314221339Sdim llvm::Function *syncEnterFn, 315221339Sdim llvm::Function *syncExitFn) { 316226633Sdim CodeGenFunction::RunCleanupsScope cleanups(CGF); 317221339Sdim 318226633Sdim // Evaluate the lock operand. This is guaranteed to dominate the 319226633Sdim // ARC release and lock-release cleanups. 320226633Sdim const Expr *lockExpr = S.getSynchExpr(); 321226633Sdim llvm::Value *lock; 322234353Sdim if (CGF.getLangOpts().ObjCAutoRefCount) { 323226633Sdim lock = CGF.EmitARCRetainScalarExpr(lockExpr); 324226633Sdim lock = CGF.EmitObjCConsumeObject(lockExpr->getType(), lock); 325226633Sdim } else { 326226633Sdim lock = CGF.EmitScalarExpr(lockExpr); 327226633Sdim } 328226633Sdim lock = CGF.Builder.CreateBitCast(lock, CGF.VoidPtrTy); 329226633Sdim 330221339Sdim // Acquire the lock. 331226633Sdim CGF.Builder.CreateCall(syncEnterFn, lock)->setDoesNotThrow(); 332221339Sdim 333221339Sdim // Register an all-paths cleanup to release the lock. 334226633Sdim CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup, syncExitFn, lock); 335221339Sdim 336221339Sdim // Emit the body of the statement. 337221339Sdim CGF.EmitStmt(S.getSynchBody()); 338221339Sdim} 339234353Sdim 340234353Sdim/// Compute the pointer-to-function type to which a message send 341234353Sdim/// should be casted in order to correctly call the given method 342234353Sdim/// with the given arguments. 343234353Sdim/// 344234353Sdim/// \param method - may be null 345234353Sdim/// \param resultType - the result type to use if there's no method 346239462Sdim/// \param callArgs - the actual arguments, including implicit ones 347234353SdimCGObjCRuntime::MessageSendInfo 348234353SdimCGObjCRuntime::getMessageSendInfo(const ObjCMethodDecl *method, 349234353Sdim QualType resultType, 350234353Sdim CallArgList &callArgs) { 351234353Sdim // If there's a method, use information from that. 352234353Sdim if (method) { 353234353Sdim const CGFunctionInfo &signature = 354234353Sdim CGM.getTypes().arrangeObjCMessageSendSignature(method, callArgs[0].Ty); 355234353Sdim 356234353Sdim llvm::PointerType *signatureType = 357234353Sdim CGM.getTypes().GetFunctionType(signature)->getPointerTo(); 358234353Sdim 359234353Sdim // If that's not variadic, there's no need to recompute the ABI 360234353Sdim // arrangement. 361234353Sdim if (!signature.isVariadic()) 362234353Sdim return MessageSendInfo(signature, signatureType); 363234353Sdim 364234353Sdim // Otherwise, there is. 365234353Sdim FunctionType::ExtInfo einfo = signature.getExtInfo(); 366234353Sdim const CGFunctionInfo &argsInfo = 367239462Sdim CGM.getTypes().arrangeFreeFunctionCall(resultType, callArgs, einfo, 368239462Sdim signature.getRequiredArgs()); 369234353Sdim 370234353Sdim return MessageSendInfo(argsInfo, signatureType); 371234353Sdim } 372234353Sdim 373234353Sdim // There's no method; just use a default CC. 374234353Sdim const CGFunctionInfo &argsInfo = 375239462Sdim CGM.getTypes().arrangeFreeFunctionCall(resultType, callArgs, 376239462Sdim FunctionType::ExtInfo(), 377239462Sdim RequiredArgs::All); 378234353Sdim 379234353Sdim // Derive the signature to call from that. 380234353Sdim llvm::PointerType *signatureType = 381234353Sdim CGM.getTypes().GetFunctionType(argsInfo)->getPointerTo(); 382234353Sdim return MessageSendInfo(argsInfo, signatureType); 383234353Sdim} 384