brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · 32e7092 Raw
140 lines · cpp
1//===-- ObjCARC.cpp -------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements common infrastructure for libLLVMObjCARCOpts.a, which10// implements several scalar transformations over the LLVM intermediate11// representation, including the C bindings for that library.12//13//===----------------------------------------------------------------------===//14 15#include "ObjCARC.h"16#include "llvm/Analysis/ObjCARCUtil.h"17#include "llvm/IR/IRBuilder.h"18#include "llvm/IR/Instructions.h"19#include "llvm/Transforms/Utils/BasicBlockUtils.h"20 21using namespace llvm;22using namespace llvm::objcarc;23 24CallInst *objcarc::createCallInstWithColors(25    FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr,26    BasicBlock::iterator InsertBefore,27    const DenseMap<BasicBlock *, ColorVector> &BlockColors) {28  FunctionType *FTy = Func.getFunctionType();29  Value *Callee = Func.getCallee();30  SmallVector<OperandBundleDef, 1> OpBundles;31 32  if (!BlockColors.empty()) {33    const ColorVector &CV = BlockColors.find(InsertBefore->getParent())->second;34    assert(CV.size() == 1 && "non-unique color for block!");35    BasicBlock::iterator EHPad = CV.front()->getFirstNonPHIIt();36    if (EHPad->isEHPad())37      OpBundles.emplace_back("funclet", &*EHPad);38  }39 40  return CallInst::Create(FTy, Callee, Args, OpBundles, NameStr, InsertBefore);41}42 43std::pair<bool, bool>44BundledRetainClaimRVs::insertAfterInvokes(Function &F, DominatorTree *DT) {45  bool Changed = false, CFGChanged = false;46 47  for (BasicBlock &BB : F) {48    auto *I = dyn_cast<InvokeInst>(BB.getTerminator());49 50    if (!I)51      continue;52 53    if (!objcarc::hasAttachedCallOpBundle(I))54      continue;55 56    BasicBlock *DestBB = I->getNormalDest();57 58    if (!DestBB->getSinglePredecessor()) {59      assert(I->getSuccessor(0) == DestBB &&60             "the normal dest is expected to be the first successor");61      DestBB = SplitCriticalEdge(I, 0, CriticalEdgeSplittingOptions(DT));62      CFGChanged = true;63    }64 65    // We don't have to call insertRVCallWithColors since DestBB is the normal66    // destination of the invoke.67    insertRVCall(DestBB->getFirstInsertionPt(), I);68    Changed = true;69  }70 71  return std::make_pair(Changed, CFGChanged);72}73 74CallInst *BundledRetainClaimRVs::insertRVCall(BasicBlock::iterator InsertPt,75                                              CallBase *AnnotatedCall) {76  DenseMap<BasicBlock *, ColorVector> BlockColors;77  return insertRVCallWithColors(InsertPt, AnnotatedCall, BlockColors);78}79 80CallInst *BundledRetainClaimRVs::insertRVCallWithColors(81    BasicBlock::iterator InsertPt, CallBase *AnnotatedCall,82    const DenseMap<BasicBlock *, ColorVector> &BlockColors) {83  IRBuilder<> Builder(InsertPt->getParent(), InsertPt);84  Function *Func = *objcarc::getAttachedARCFunction(AnnotatedCall);85  assert(Func && "operand isn't a Function");86  Type *ParamTy = Func->getArg(0)->getType();87  Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy);88  auto *Call =89      createCallInstWithColors(Func, CallArg, "", InsertPt, BlockColors);90  RVCalls[Call] = AnnotatedCall;91  return Call;92}93 94BundledRetainClaimRVs::~BundledRetainClaimRVs() {95  for (auto P : RVCalls) {96    if (ContractPass) {97      CallBase *CB = P.second;98      // At this point, we know that the annotated calls can't be tail calls99      // as they are followed by marker instructions and retainRV/claimRV100      // calls. Mark them as notail so that the backend knows these calls101      // can't be tail calls.102      if (auto *CI = dyn_cast<CallInst>(CB))103        CI->setTailCallKind(CallInst::TCK_NoTail);104 105      // We can also do one final optimization: modify the bundle in the106      // annotated call, to change the bundle operand from107      //   objc_retainAutoreleasedReturnValue108      // to:109      //   objc_claimAutoreleasedReturnValue110      // allowing the marker to be omitted from the bundle expansion later.111      //112      // Note that, confusingly, ClaimRV is semantically equivalent to RetainRV,113      // and only differs in that it doesn't require the marker.114      // The bundle provides the guarantee that we're emitting the ClaimRV call115      // adjacent to the original call, and providing that guarantee is the116      // only difference between ClaimRV and RetainRV.117      //118      // UnsafeClaimRV has a different RC contract entirely.119 120      // Find the clang.arc.attachedcall bundle, and rewrite its operand.121      if (UseClaimRV) {122        for (auto OBI : CB->bundle_op_infos()) {123          auto OBU = CB->operandBundleFromBundleOpInfo(OBI);124          if (OBU.getTagID() == LLVMContext::OB_clang_arc_attachedcall &&125              OBU.Inputs[0] == EP.get(ARCRuntimeEntryPointKind::RetainRV)) {126            CB->setOperand(OBI.Begin,127                           EP.get(ARCRuntimeEntryPointKind::ClaimRV));128            break;129          }130        }131      }132    }133 134    // Erase the RV call we emitted earlier: it's already in the bundle.135    EraseInstruction(P.first);136  }137 138  RVCalls.clear();139}140