1*9880d681SAndroid Build Coastguard Worker //===- ObjCARCExpand.cpp - ObjC ARC Optimization --------------------------===// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker /// \file 10*9880d681SAndroid Build Coastguard Worker /// This file defines ObjC ARC optimizations. ARC stands for Automatic 11*9880d681SAndroid Build Coastguard Worker /// Reference Counting and is a system for managing reference counts for objects 12*9880d681SAndroid Build Coastguard Worker /// in Objective C. 13*9880d681SAndroid Build Coastguard Worker /// 14*9880d681SAndroid Build Coastguard Worker /// This specific file deals with early optimizations which perform certain 15*9880d681SAndroid Build Coastguard Worker /// cleanup operations. 16*9880d681SAndroid Build Coastguard Worker /// 17*9880d681SAndroid Build Coastguard Worker /// WARNING: This file knows about certain library functions. It recognizes them 18*9880d681SAndroid Build Coastguard Worker /// by name, and hardwires knowledge of their semantics. 19*9880d681SAndroid Build Coastguard Worker /// 20*9880d681SAndroid Build Coastguard Worker /// WARNING: This file knows about how certain Objective-C library functions are 21*9880d681SAndroid Build Coastguard Worker /// used. Naive LLVM IR transformations which would otherwise be 22*9880d681SAndroid Build Coastguard Worker /// behavior-preserving may break these assumptions. 23*9880d681SAndroid Build Coastguard Worker /// 24*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 25*9880d681SAndroid Build Coastguard Worker 26*9880d681SAndroid Build Coastguard Worker #include "ObjCARC.h" 27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h" 28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstIterator.h" 29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instruction.h" 30*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h" 31*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Value.h" 32*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h" 33*9880d681SAndroid Build Coastguard Worker #include "llvm/PassAnalysisSupport.h" 34*9880d681SAndroid Build Coastguard Worker #include "llvm/PassRegistry.h" 35*9880d681SAndroid Build Coastguard Worker #include "llvm/PassSupport.h" 36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Casting.h" 37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h" 38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h" 39*9880d681SAndroid Build Coastguard Worker 40*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "objc-arc-expand" 41*9880d681SAndroid Build Coastguard Worker 42*9880d681SAndroid Build Coastguard Worker namespace llvm { 43*9880d681SAndroid Build Coastguard Worker class Module; 44*9880d681SAndroid Build Coastguard Worker } 45*9880d681SAndroid Build Coastguard Worker 46*9880d681SAndroid Build Coastguard Worker using namespace llvm; 47*9880d681SAndroid Build Coastguard Worker using namespace llvm::objcarc; 48*9880d681SAndroid Build Coastguard Worker 49*9880d681SAndroid Build Coastguard Worker namespace { 50*9880d681SAndroid Build Coastguard Worker /// \brief Early ARC transformations. 51*9880d681SAndroid Build Coastguard Worker class ObjCARCExpand : public FunctionPass { 52*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override; 53*9880d681SAndroid Build Coastguard Worker bool doInitialization(Module &M) override; 54*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override; 55*9880d681SAndroid Build Coastguard Worker 56*9880d681SAndroid Build Coastguard Worker /// A flag indicating whether this optimization pass should run. 57*9880d681SAndroid Build Coastguard Worker bool Run; 58*9880d681SAndroid Build Coastguard Worker 59*9880d681SAndroid Build Coastguard Worker public: 60*9880d681SAndroid Build Coastguard Worker static char ID; ObjCARCExpand()61*9880d681SAndroid Build Coastguard Worker ObjCARCExpand() : FunctionPass(ID) { 62*9880d681SAndroid Build Coastguard Worker initializeObjCARCExpandPass(*PassRegistry::getPassRegistry()); 63*9880d681SAndroid Build Coastguard Worker } 64*9880d681SAndroid Build Coastguard Worker }; 65*9880d681SAndroid Build Coastguard Worker } 66*9880d681SAndroid Build Coastguard Worker 67*9880d681SAndroid Build Coastguard Worker char ObjCARCExpand::ID = 0; 68*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(ObjCARCExpand, 69*9880d681SAndroid Build Coastguard Worker "objc-arc-expand", "ObjC ARC expansion", false, false) 70*9880d681SAndroid Build Coastguard Worker createObjCARCExpandPass()71*9880d681SAndroid Build Coastguard WorkerPass *llvm::createObjCARCExpandPass() { 72*9880d681SAndroid Build Coastguard Worker return new ObjCARCExpand(); 73*9880d681SAndroid Build Coastguard Worker } 74*9880d681SAndroid Build Coastguard Worker getAnalysisUsage(AnalysisUsage & AU) const75*9880d681SAndroid Build Coastguard Workervoid ObjCARCExpand::getAnalysisUsage(AnalysisUsage &AU) const { 76*9880d681SAndroid Build Coastguard Worker AU.setPreservesCFG(); 77*9880d681SAndroid Build Coastguard Worker } 78*9880d681SAndroid Build Coastguard Worker doInitialization(Module & M)79*9880d681SAndroid Build Coastguard Workerbool ObjCARCExpand::doInitialization(Module &M) { 80*9880d681SAndroid Build Coastguard Worker Run = ModuleHasARC(M); 81*9880d681SAndroid Build Coastguard Worker return false; 82*9880d681SAndroid Build Coastguard Worker } 83*9880d681SAndroid Build Coastguard Worker runOnFunction(Function & F)84*9880d681SAndroid Build Coastguard Workerbool ObjCARCExpand::runOnFunction(Function &F) { 85*9880d681SAndroid Build Coastguard Worker if (!EnableARCOpts) 86*9880d681SAndroid Build Coastguard Worker return false; 87*9880d681SAndroid Build Coastguard Worker 88*9880d681SAndroid Build Coastguard Worker // If nothing in the Module uses ARC, don't do anything. 89*9880d681SAndroid Build Coastguard Worker if (!Run) 90*9880d681SAndroid Build Coastguard Worker return false; 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker bool Changed = false; 93*9880d681SAndroid Build Coastguard Worker 94*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ObjCARCExpand: Visiting Function: " << F.getName() << "\n"); 95*9880d681SAndroid Build Coastguard Worker 96*9880d681SAndroid Build Coastguard Worker for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) { 97*9880d681SAndroid Build Coastguard Worker Instruction *Inst = &*I; 98*9880d681SAndroid Build Coastguard Worker 99*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ObjCARCExpand: Visiting: " << *Inst << "\n"); 100*9880d681SAndroid Build Coastguard Worker 101*9880d681SAndroid Build Coastguard Worker switch (GetBasicARCInstKind(Inst)) { 102*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Retain: 103*9880d681SAndroid Build Coastguard Worker case ARCInstKind::RetainRV: 104*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Autorelease: 105*9880d681SAndroid Build Coastguard Worker case ARCInstKind::AutoreleaseRV: 106*9880d681SAndroid Build Coastguard Worker case ARCInstKind::FusedRetainAutorelease: 107*9880d681SAndroid Build Coastguard Worker case ARCInstKind::FusedRetainAutoreleaseRV: { 108*9880d681SAndroid Build Coastguard Worker // These calls return their argument verbatim, as a low-level 109*9880d681SAndroid Build Coastguard Worker // optimization. However, this makes high-level optimizations 110*9880d681SAndroid Build Coastguard Worker // harder. Undo any uses of this optimization that the front-end 111*9880d681SAndroid Build Coastguard Worker // emitted here. We'll redo them in the contract pass. 112*9880d681SAndroid Build Coastguard Worker Changed = true; 113*9880d681SAndroid Build Coastguard Worker Value *Value = cast<CallInst>(Inst)->getArgOperand(0); 114*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ObjCARCExpand: Old = " << *Inst << "\n" 115*9880d681SAndroid Build Coastguard Worker " New = " << *Value << "\n"); 116*9880d681SAndroid Build Coastguard Worker Inst->replaceAllUsesWith(Value); 117*9880d681SAndroid Build Coastguard Worker break; 118*9880d681SAndroid Build Coastguard Worker } 119*9880d681SAndroid Build Coastguard Worker default: 120*9880d681SAndroid Build Coastguard Worker break; 121*9880d681SAndroid Build Coastguard Worker } 122*9880d681SAndroid Build Coastguard Worker } 123*9880d681SAndroid Build Coastguard Worker 124*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ObjCARCExpand: Finished List.\n\n"); 125*9880d681SAndroid Build Coastguard Worker 126*9880d681SAndroid Build Coastguard Worker return Changed; 127*9880d681SAndroid Build Coastguard Worker } 128