10b57cec5SDimitry Andric //==- CGObjCRuntime.cpp - Interface to Shared Objective-C Runtime Features ==// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This abstract class defines the interface for Objective-C runtime-specific 100b57cec5SDimitry Andric // code generation. It provides some concrete helper methods for functionality 110b57cec5SDimitry Andric // shared between all (or most) of the Objective-C runtimes supported by clang. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "CGObjCRuntime.h" 160b57cec5SDimitry Andric #include "CGCXXABI.h" 175ffd83dbSDimitry Andric #include "CGCleanup.h" 180b57cec5SDimitry Andric #include "CGRecordLayout.h" 190b57cec5SDimitry Andric #include "CodeGenFunction.h" 200b57cec5SDimitry Andric #include "CodeGenModule.h" 210b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h" 220b57cec5SDimitry Andric #include "clang/AST/StmtObjC.h" 230b57cec5SDimitry Andric #include "clang/CodeGen/CGFunctionInfo.h" 245ffd83dbSDimitry Andric #include "clang/CodeGen/CodeGenABITypes.h" 25bdd1243dSDimitry Andric #include "llvm/IR/Instruction.h" 260b57cec5SDimitry Andric #include "llvm/Support/SaveAndRestore.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric using namespace clang; 290b57cec5SDimitry Andric using namespace CodeGen; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 320b57cec5SDimitry Andric const ObjCInterfaceDecl *OID, 330b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) { 340b57cec5SDimitry Andric return CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar) / 350b57cec5SDimitry Andric CGM.getContext().getCharWidth(); 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 390b57cec5SDimitry Andric const ObjCImplementationDecl *OID, 400b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) { 410b57cec5SDimitry Andric return CGM.getContext().lookupFieldBitOffset(OID->getClassInterface(), OID, 420b57cec5SDimitry Andric Ivar) / 430b57cec5SDimitry Andric CGM.getContext().getCharWidth(); 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric unsigned CGObjCRuntime::ComputeBitfieldBitOffset( 470b57cec5SDimitry Andric CodeGen::CodeGenModule &CGM, 480b57cec5SDimitry Andric const ObjCInterfaceDecl *ID, 490b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) { 500b57cec5SDimitry Andric return CGM.getContext().lookupFieldBitOffset(ID, ID->getImplementation(), 510b57cec5SDimitry Andric Ivar); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, 550b57cec5SDimitry Andric const ObjCInterfaceDecl *OID, 560b57cec5SDimitry Andric llvm::Value *BaseValue, 570b57cec5SDimitry Andric const ObjCIvarDecl *Ivar, 580b57cec5SDimitry Andric unsigned CVRQualifiers, 590b57cec5SDimitry Andric llvm::Value *Offset) { 600b57cec5SDimitry Andric // Compute (type*) ( (char *) BaseValue + Offset) 610b57cec5SDimitry Andric QualType InterfaceTy{OID->getTypeForDecl(), 0}; 620b57cec5SDimitry Andric QualType ObjectPtrTy = 630b57cec5SDimitry Andric CGF.CGM.getContext().getObjCObjectPointerType(InterfaceTy); 640b57cec5SDimitry Andric QualType IvarTy = 650b57cec5SDimitry Andric Ivar->getUsageType(ObjectPtrTy).withCVRQualifiers(CVRQualifiers); 665f757f3fSDimitry Andric llvm::Value *V = BaseValue; 67fe6060f1SDimitry Andric V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, V, Offset, "add.ptr"); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric if (!Ivar->isBitField()) { 70*0fca6ea1SDimitry Andric LValue LV = CGF.MakeNaturalAlignRawAddrLValue(V, IvarTy); 710b57cec5SDimitry Andric return LV; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // We need to compute an access strategy for this bit-field. We are given the 750b57cec5SDimitry Andric // offset to the first byte in the bit-field, the sub-byte offset is taken 760b57cec5SDimitry Andric // from the original layout. We reuse the normal bit-field access strategy by 770b57cec5SDimitry Andric // treating this as an access to a struct where the bit-field is in byte 0, 780b57cec5SDimitry Andric // and adjust the containing type size as appropriate. 790b57cec5SDimitry Andric // 800b57cec5SDimitry Andric // FIXME: Note that currently we make a very conservative estimate of the 810b57cec5SDimitry Andric // alignment of the bit-field, because (a) it is not clear what guarantees the 820b57cec5SDimitry Andric // runtime makes us, and (b) we don't have a way to specify that the struct is 830b57cec5SDimitry Andric // at an alignment plus offset. 840b57cec5SDimitry Andric // 850b57cec5SDimitry Andric // Note, there is a subtle invariant here: we can only call this routine on 860b57cec5SDimitry Andric // non-synthesized ivars but we may be called for synthesized ivars. However, 870b57cec5SDimitry Andric // a synthesized ivar can never be a bit-field, so this is safe. 880b57cec5SDimitry Andric uint64_t FieldBitOffset = 890b57cec5SDimitry Andric CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar); 900b57cec5SDimitry Andric uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); 910b57cec5SDimitry Andric uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign(); 920b57cec5SDimitry Andric uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); 930b57cec5SDimitry Andric CharUnits StorageSize = CGF.CGM.getContext().toCharUnitsFromBits( 940b57cec5SDimitry Andric llvm::alignTo(BitOffset + BitFieldSize, AlignmentBits)); 950b57cec5SDimitry Andric CharUnits Alignment = CGF.CGM.getContext().toCharUnitsFromBits(AlignmentBits); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric // Allocate a new CGBitFieldInfo object to describe this access. 980b57cec5SDimitry Andric // 990b57cec5SDimitry Andric // FIXME: This is incredibly wasteful, these should be uniqued or part of some 1000b57cec5SDimitry Andric // layout object. However, this is blocked on other cleanups to the 1010b57cec5SDimitry Andric // Objective-C code, so for now we just live with allocating a bunch of these 1020b57cec5SDimitry Andric // objects. 1030b57cec5SDimitry Andric CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo( 1040b57cec5SDimitry Andric CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize, 1050b57cec5SDimitry Andric CGF.CGM.getContext().toBits(StorageSize), 1060b57cec5SDimitry Andric CharUnits::fromQuantity(0))); 1070b57cec5SDimitry Andric 10806c3fb27SDimitry Andric Address Addr = 10906c3fb27SDimitry Andric Address(V, llvm::Type::getIntNTy(CGF.getLLVMContext(), Info->StorageSize), 11006c3fb27SDimitry Andric Alignment); 11106c3fb27SDimitry Andric 1120b57cec5SDimitry Andric return LValue::MakeBitfield(Addr, *Info, IvarTy, 1130b57cec5SDimitry Andric LValueBaseInfo(AlignmentSource::Decl), 1140b57cec5SDimitry Andric TBAAAccessInfo()); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric namespace { 1180b57cec5SDimitry Andric struct CatchHandler { 1190b57cec5SDimitry Andric const VarDecl *Variable; 1200b57cec5SDimitry Andric const Stmt *Body; 1210b57cec5SDimitry Andric llvm::BasicBlock *Block; 1220b57cec5SDimitry Andric llvm::Constant *TypeInfo; 1230b57cec5SDimitry Andric /// Flags used to differentiate cleanups and catchalls in Windows SEH 1240b57cec5SDimitry Andric unsigned Flags; 1250b57cec5SDimitry Andric }; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric struct CallObjCEndCatch final : EHScopeStack::Cleanup { 1280b57cec5SDimitry Andric CallObjCEndCatch(bool MightThrow, llvm::FunctionCallee Fn) 1290b57cec5SDimitry Andric : MightThrow(MightThrow), Fn(Fn) {} 1300b57cec5SDimitry Andric bool MightThrow; 1310b57cec5SDimitry Andric llvm::FunctionCallee Fn; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override { 1340b57cec5SDimitry Andric if (MightThrow) 1350b57cec5SDimitry Andric CGF.EmitRuntimeCallOrInvoke(Fn); 1360b57cec5SDimitry Andric else 1370b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(Fn); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric }; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, 1430b57cec5SDimitry Andric const ObjCAtTryStmt &S, 1440b57cec5SDimitry Andric llvm::FunctionCallee beginCatchFn, 1450b57cec5SDimitry Andric llvm::FunctionCallee endCatchFn, 1460b57cec5SDimitry Andric llvm::FunctionCallee exceptionRethrowFn) { 1470b57cec5SDimitry Andric // Jump destination for falling out of catch bodies. 1480b57cec5SDimitry Andric CodeGenFunction::JumpDest Cont; 1490b57cec5SDimitry Andric if (S.getNumCatchStmts()) 1500b57cec5SDimitry Andric Cont = CGF.getJumpDestInCurrentScope("eh.cont"); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric bool useFunclets = EHPersonality::get(CGF).usesFuncletPads(); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric CodeGenFunction::FinallyInfo FinallyInfo; 1550b57cec5SDimitry Andric if (!useFunclets) 1560b57cec5SDimitry Andric if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) 1570b57cec5SDimitry Andric FinallyInfo.enter(CGF, Finally->getFinallyBody(), 1580b57cec5SDimitry Andric beginCatchFn, endCatchFn, exceptionRethrowFn); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric SmallVector<CatchHandler, 8> Handlers; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric // Enter the catch, if there is one. 1640b57cec5SDimitry Andric if (S.getNumCatchStmts()) { 165349cc55cSDimitry Andric for (const ObjCAtCatchStmt *CatchStmt : S.catch_stmts()) { 1660b57cec5SDimitry Andric const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric Handlers.push_back(CatchHandler()); 1690b57cec5SDimitry Andric CatchHandler &Handler = Handlers.back(); 1700b57cec5SDimitry Andric Handler.Variable = CatchDecl; 1710b57cec5SDimitry Andric Handler.Body = CatchStmt->getCatchBody(); 1720b57cec5SDimitry Andric Handler.Block = CGF.createBasicBlock("catch"); 1730b57cec5SDimitry Andric Handler.Flags = 0; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric // @catch(...) always matches. 1760b57cec5SDimitry Andric if (!CatchDecl) { 1770b57cec5SDimitry Andric auto catchAll = getCatchAllTypeInfo(); 1780b57cec5SDimitry Andric Handler.TypeInfo = catchAll.RTTI; 1790b57cec5SDimitry Andric Handler.Flags = catchAll.Flags; 1800b57cec5SDimitry Andric // Don't consider any other catches. 1810b57cec5SDimitry Andric break; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric Handler.TypeInfo = GetEHType(CatchDecl->getType()); 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); 1880b57cec5SDimitry Andric for (unsigned I = 0, E = Handlers.size(); I != E; ++I) 1890b57cec5SDimitry Andric Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags }, Handlers[I].Block); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric if (useFunclets) 1930b57cec5SDimitry Andric if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) { 1940b57cec5SDimitry Andric CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); 1950b57cec5SDimitry Andric if (!CGF.CurSEHParent) 1960b57cec5SDimitry Andric CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl); 1970b57cec5SDimitry Andric // Outline the finally block. 1980b57cec5SDimitry Andric const Stmt *FinallyBlock = Finally->getFinallyBody(); 1990b57cec5SDimitry Andric HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric // Emit the original filter expression, convert to i32, and return. 2020b57cec5SDimitry Andric HelperCGF.EmitStmt(FinallyBlock); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric HelperCGF.FinishFunction(FinallyBlock->getEndLoc()); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric llvm::Function *FinallyFunc = HelperCGF.CurFn; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric // Push a cleanup for __finally blocks. 2100b57cec5SDimitry Andric CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric // Emit the try body. 2150b57cec5SDimitry Andric CGF.EmitStmt(S.getTryBody()); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric // Leave the try. 2180b57cec5SDimitry Andric if (S.getNumCatchStmts()) 2190b57cec5SDimitry Andric CGF.popCatchScope(); 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric // Remember where we were. 2220b57cec5SDimitry Andric CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric // Emit the handlers. 2250b57cec5SDimitry Andric for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { 2260b57cec5SDimitry Andric CatchHandler &Handler = Handlers[I]; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric CGF.EmitBlock(Handler.Block); 229bdd1243dSDimitry Andric 230bdd1243dSDimitry Andric CodeGenFunction::LexicalScope Cleanups(CGF, Handler.Body->getSourceRange()); 231bdd1243dSDimitry Andric SaveAndRestore RevertAfterScope(CGF.CurrentFuncletPad); 232bdd1243dSDimitry Andric if (useFunclets) { 233bdd1243dSDimitry Andric llvm::Instruction *CPICandidate = Handler.Block->getFirstNonPHI(); 234bdd1243dSDimitry Andric if (auto *CPI = dyn_cast_or_null<llvm::CatchPadInst>(CPICandidate)) { 2350b57cec5SDimitry Andric CGF.CurrentFuncletPad = CPI; 236*0fca6ea1SDimitry Andric CPI->setOperand(2, CGF.getExceptionSlot().emitRawPointer(CGF)); 237bdd1243dSDimitry Andric CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); 2380b57cec5SDimitry Andric } 239bdd1243dSDimitry Andric } 240bdd1243dSDimitry Andric 2410b57cec5SDimitry Andric llvm::Value *RawExn = CGF.getExceptionFromSlot(); 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // Enter the catch. 2440b57cec5SDimitry Andric llvm::Value *Exn = RawExn; 2450b57cec5SDimitry Andric if (beginCatchFn) 2460b57cec5SDimitry Andric Exn = CGF.EmitNounwindRuntimeCall(beginCatchFn, RawExn, "exn.adjusted"); 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric if (endCatchFn) { 2490b57cec5SDimitry Andric // Add a cleanup to leave the catch. 2500b57cec5SDimitry Andric bool EndCatchMightThrow = (Handler.Variable == nullptr); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup, 2530b57cec5SDimitry Andric EndCatchMightThrow, 2540b57cec5SDimitry Andric endCatchFn); 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric // Bind the catch parameter if it exists. 2580b57cec5SDimitry Andric if (const VarDecl *CatchParam = Handler.Variable) { 2590b57cec5SDimitry Andric llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType()); 2600b57cec5SDimitry Andric llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric CGF.EmitAutoVarDecl(*CatchParam); 2630b57cec5SDimitry Andric EmitInitOfCatchParam(CGF, CastExn, CatchParam); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric CGF.ObjCEHValueStack.push_back(Exn); 2670b57cec5SDimitry Andric CGF.EmitStmt(Handler.Body); 2680b57cec5SDimitry Andric CGF.ObjCEHValueStack.pop_back(); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric // Leave any cleanups associated with the catch. 271bdd1243dSDimitry Andric Cleanups.ForceCleanup(); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric CGF.EmitBranchThroughCleanup(Cont); 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric // Go back to the try-statement fallthrough. 2770b57cec5SDimitry Andric CGF.Builder.restoreIP(SavedIP); 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // Pop out of the finally. 2800b57cec5SDimitry Andric if (!useFunclets && S.getFinallyStmt()) 2810b57cec5SDimitry Andric FinallyInfo.exit(CGF); 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric if (Cont.isValid()) 2840b57cec5SDimitry Andric CGF.EmitBlock(Cont.getBlock()); 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric void CGObjCRuntime::EmitInitOfCatchParam(CodeGenFunction &CGF, 2880b57cec5SDimitry Andric llvm::Value *exn, 2890b57cec5SDimitry Andric const VarDecl *paramDecl) { 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric Address paramAddr = CGF.GetAddrOfLocalVar(paramDecl); 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric switch (paramDecl->getType().getQualifiers().getObjCLifetime()) { 2940b57cec5SDimitry Andric case Qualifiers::OCL_Strong: 2950b57cec5SDimitry Andric exn = CGF.EmitARCRetainNonBlock(exn); 296bdd1243dSDimitry Andric [[fallthrough]]; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric case Qualifiers::OCL_None: 2990b57cec5SDimitry Andric case Qualifiers::OCL_ExplicitNone: 3000b57cec5SDimitry Andric case Qualifiers::OCL_Autoreleasing: 3010b57cec5SDimitry Andric CGF.Builder.CreateStore(exn, paramAddr); 3020b57cec5SDimitry Andric return; 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric case Qualifiers::OCL_Weak: 3050b57cec5SDimitry Andric CGF.EmitARCInitWeak(paramAddr, exn); 3060b57cec5SDimitry Andric return; 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric llvm_unreachable("invalid ownership qualifier"); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric namespace { 3120b57cec5SDimitry Andric struct CallSyncExit final : EHScopeStack::Cleanup { 3130b57cec5SDimitry Andric llvm::FunctionCallee SyncExitFn; 3140b57cec5SDimitry Andric llvm::Value *SyncArg; 3150b57cec5SDimitry Andric CallSyncExit(llvm::FunctionCallee SyncExitFn, llvm::Value *SyncArg) 3160b57cec5SDimitry Andric : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override { 3190b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(SyncExitFn, SyncArg); 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric }; 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric void CGObjCRuntime::EmitAtSynchronizedStmt(CodeGenFunction &CGF, 3250b57cec5SDimitry Andric const ObjCAtSynchronizedStmt &S, 3260b57cec5SDimitry Andric llvm::FunctionCallee syncEnterFn, 3270b57cec5SDimitry Andric llvm::FunctionCallee syncExitFn) { 3280b57cec5SDimitry Andric CodeGenFunction::RunCleanupsScope cleanups(CGF); 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Evaluate the lock operand. This is guaranteed to dominate the 3310b57cec5SDimitry Andric // ARC release and lock-release cleanups. 3320b57cec5SDimitry Andric const Expr *lockExpr = S.getSynchExpr(); 3330b57cec5SDimitry Andric llvm::Value *lock; 3340b57cec5SDimitry Andric if (CGF.getLangOpts().ObjCAutoRefCount) { 3350b57cec5SDimitry Andric lock = CGF.EmitARCRetainScalarExpr(lockExpr); 3360b57cec5SDimitry Andric lock = CGF.EmitObjCConsumeObject(lockExpr->getType(), lock); 3370b57cec5SDimitry Andric } else { 3380b57cec5SDimitry Andric lock = CGF.EmitScalarExpr(lockExpr); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric lock = CGF.Builder.CreateBitCast(lock, CGF.VoidPtrTy); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric // Acquire the lock. 3430b57cec5SDimitry Andric CGF.Builder.CreateCall(syncEnterFn, lock)->setDoesNotThrow(); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric // Register an all-paths cleanup to release the lock. 3460b57cec5SDimitry Andric CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup, syncExitFn, lock); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric // Emit the body of the statement. 3490b57cec5SDimitry Andric CGF.EmitStmt(S.getSynchBody()); 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric /// Compute the pointer-to-function type to which a message send 3530b57cec5SDimitry Andric /// should be casted in order to correctly call the given method 3540b57cec5SDimitry Andric /// with the given arguments. 3550b57cec5SDimitry Andric /// 3560b57cec5SDimitry Andric /// \param method - may be null 3570b57cec5SDimitry Andric /// \param resultType - the result type to use if there's no method 3580b57cec5SDimitry Andric /// \param callArgs - the actual arguments, including implicit ones 3590b57cec5SDimitry Andric CGObjCRuntime::MessageSendInfo 3600b57cec5SDimitry Andric CGObjCRuntime::getMessageSendInfo(const ObjCMethodDecl *method, 3610b57cec5SDimitry Andric QualType resultType, 3620b57cec5SDimitry Andric CallArgList &callArgs) { 363bdd1243dSDimitry Andric unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace(); 364bdd1243dSDimitry Andric 36506c3fb27SDimitry Andric llvm::PointerType *signatureType = 36606c3fb27SDimitry Andric llvm::PointerType::get(CGM.getLLVMContext(), ProgramAS); 36706c3fb27SDimitry Andric 3680b57cec5SDimitry Andric // If there's a method, use information from that. 3690b57cec5SDimitry Andric if (method) { 3700b57cec5SDimitry Andric const CGFunctionInfo &signature = 3710b57cec5SDimitry Andric CGM.getTypes().arrangeObjCMessageSendSignature(method, callArgs[0].Ty); 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric const CGFunctionInfo &signatureForCall = 3740b57cec5SDimitry Andric CGM.getTypes().arrangeCall(signature, callArgs); 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric return MessageSendInfo(signatureForCall, signatureType); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric // There's no method; just use a default CC. 3800b57cec5SDimitry Andric const CGFunctionInfo &argsInfo = 3810b57cec5SDimitry Andric CGM.getTypes().arrangeUnprototypedObjCMessageSend(resultType, callArgs); 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric return MessageSendInfo(argsInfo, signatureType); 3840b57cec5SDimitry Andric } 3855ffd83dbSDimitry Andric 386349cc55cSDimitry Andric bool CGObjCRuntime::canMessageReceiverBeNull(CodeGenFunction &CGF, 387349cc55cSDimitry Andric const ObjCMethodDecl *method, 388349cc55cSDimitry Andric bool isSuper, 389349cc55cSDimitry Andric const ObjCInterfaceDecl *classReceiver, 390349cc55cSDimitry Andric llvm::Value *receiver) { 391349cc55cSDimitry Andric // Super dispatch assumes that self is non-null; even the messenger 392349cc55cSDimitry Andric // doesn't have a null check internally. 393349cc55cSDimitry Andric if (isSuper) 394349cc55cSDimitry Andric return false; 395349cc55cSDimitry Andric 396349cc55cSDimitry Andric // If this is a direct dispatch of a class method, check whether the class, 397349cc55cSDimitry Andric // or anything in its hierarchy, was weak-linked. 398349cc55cSDimitry Andric if (classReceiver && method && method->isClassMethod()) 399349cc55cSDimitry Andric return isWeakLinkedClass(classReceiver); 400349cc55cSDimitry Andric 401349cc55cSDimitry Andric // If we're emitting a method, and self is const (meaning just ARC, for now), 402349cc55cSDimitry Andric // and the receiver is a load of self, then self is a valid object. 403349cc55cSDimitry Andric if (auto curMethod = 404349cc55cSDimitry Andric dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) { 405349cc55cSDimitry Andric auto self = curMethod->getSelfDecl(); 406349cc55cSDimitry Andric if (self->getType().isConstQualified()) { 407349cc55cSDimitry Andric if (auto LI = dyn_cast<llvm::LoadInst>(receiver->stripPointerCasts())) { 408*0fca6ea1SDimitry Andric llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).emitRawPointer(CGF); 409349cc55cSDimitry Andric if (selfAddr == LI->getPointerOperand()) { 410349cc55cSDimitry Andric return false; 411349cc55cSDimitry Andric } 412349cc55cSDimitry Andric } 413349cc55cSDimitry Andric } 414349cc55cSDimitry Andric } 415349cc55cSDimitry Andric 416349cc55cSDimitry Andric // Otherwise, assume it can be null. 417349cc55cSDimitry Andric return true; 418349cc55cSDimitry Andric } 419349cc55cSDimitry Andric 420349cc55cSDimitry Andric bool CGObjCRuntime::isWeakLinkedClass(const ObjCInterfaceDecl *ID) { 421349cc55cSDimitry Andric do { 422349cc55cSDimitry Andric if (ID->isWeakImported()) 423349cc55cSDimitry Andric return true; 424349cc55cSDimitry Andric } while ((ID = ID->getSuperClass())); 425349cc55cSDimitry Andric 426349cc55cSDimitry Andric return false; 427349cc55cSDimitry Andric } 428349cc55cSDimitry Andric 429349cc55cSDimitry Andric void CGObjCRuntime::destroyCalleeDestroyedArguments(CodeGenFunction &CGF, 430349cc55cSDimitry Andric const ObjCMethodDecl *method, 431349cc55cSDimitry Andric const CallArgList &callArgs) { 432349cc55cSDimitry Andric CallArgList::const_iterator I = callArgs.begin(); 433349cc55cSDimitry Andric for (auto i = method->param_begin(), e = method->param_end(); 434349cc55cSDimitry Andric i != e; ++i, ++I) { 435349cc55cSDimitry Andric const ParmVarDecl *param = (*i); 436349cc55cSDimitry Andric if (param->hasAttr<NSConsumedAttr>()) { 437349cc55cSDimitry Andric RValue RV = I->getRValue(CGF); 438349cc55cSDimitry Andric assert(RV.isScalar() && 439349cc55cSDimitry Andric "NullReturnState::complete - arg not on object"); 440349cc55cSDimitry Andric CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime); 441349cc55cSDimitry Andric } else { 442349cc55cSDimitry Andric QualType QT = param->getType(); 443349cc55cSDimitry Andric auto *RT = QT->getAs<RecordType>(); 444349cc55cSDimitry Andric if (RT && RT->getDecl()->isParamDestroyedInCallee()) { 445349cc55cSDimitry Andric RValue RV = I->getRValue(CGF); 446349cc55cSDimitry Andric QualType::DestructionKind DtorKind = QT.isDestructedType(); 447349cc55cSDimitry Andric switch (DtorKind) { 448349cc55cSDimitry Andric case QualType::DK_cxx_destructor: 449349cc55cSDimitry Andric CGF.destroyCXXObject(CGF, RV.getAggregateAddress(), QT); 450349cc55cSDimitry Andric break; 451349cc55cSDimitry Andric case QualType::DK_nontrivial_c_struct: 452349cc55cSDimitry Andric CGF.destroyNonTrivialCStruct(CGF, RV.getAggregateAddress(), QT); 453349cc55cSDimitry Andric break; 454349cc55cSDimitry Andric default: 455349cc55cSDimitry Andric llvm_unreachable("unexpected dtor kind"); 456349cc55cSDimitry Andric break; 457349cc55cSDimitry Andric } 458349cc55cSDimitry Andric } 459349cc55cSDimitry Andric } 460349cc55cSDimitry Andric } 461349cc55cSDimitry Andric } 462349cc55cSDimitry Andric 4635ffd83dbSDimitry Andric llvm::Constant * 4645ffd83dbSDimitry Andric clang::CodeGen::emitObjCProtocolObject(CodeGenModule &CGM, 4655ffd83dbSDimitry Andric const ObjCProtocolDecl *protocol) { 4665ffd83dbSDimitry Andric return CGM.getObjCRuntime().GetOrEmitProtocol(protocol); 4675ffd83dbSDimitry Andric } 468e8d8bef9SDimitry Andric 469e8d8bef9SDimitry Andric std::string CGObjCRuntime::getSymbolNameForMethod(const ObjCMethodDecl *OMD, 470e8d8bef9SDimitry Andric bool includeCategoryName) { 471e8d8bef9SDimitry Andric std::string buffer; 472e8d8bef9SDimitry Andric llvm::raw_string_ostream out(buffer); 473e8d8bef9SDimitry Andric CGM.getCXXABI().getMangleContext().mangleObjCMethodName(OMD, out, 474e8d8bef9SDimitry Andric /*includePrefixByte=*/true, 475e8d8bef9SDimitry Andric includeCategoryName); 476e8d8bef9SDimitry Andric return buffer; 477e8d8bef9SDimitry Andric } 478