Extracted pass ObjCARCExpand from ObjCARC.cpp => ObjCARCExpand.cpp.
[oota-llvm.git] / lib / Transforms / ObjCARC / ObjCARC.h
1 //===- ObjCARC.h - ObjC ARC Optimization --------------*- mode: c++ -*-----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file defines common definitions/declarations used by the ObjC ARC
11 /// Optimizer. ARC stands for Automatic Reference Counting and is a system for
12 /// managing reference counts for objects in Objective C.
13 ///
14 /// WARNING: This file knows about certain library functions. It recognizes them
15 /// by name, and hardwires knowledge of their semantics.
16 ///
17 /// WARNING: This file knows about how certain Objective-C library functions are
18 /// used. Naive LLVM IR transformations which would otherwise be
19 /// behavior-preserving may break these assumptions.
20 ///
21 //===----------------------------------------------------------------------===//
22
23 #ifndef LLVM_TRANSFORMS_SCALAR_OBJCARC_H
24 #define LLVM_TRANSFORMS_SCALAR_OBJCARC_H
25
26 #include "llvm/ADT/StringSwitch.h"
27 #include "llvm/Analysis/AliasAnalysis.h"
28 #include "llvm/Analysis/Passes.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/Pass.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/InstIterator.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include "llvm/Transforms/ObjCARC.h"
35
36 namespace llvm {
37 namespace objcarc {
38
39 /// \brief A handy option to enable/disable all ARC Optimizations.
40 extern bool EnableARCOpts;
41
42 /// \brief Test if the given module looks interesting to run ARC optimization
43 /// on.
44 static inline bool ModuleHasARC(const Module &M) {
45   return
46     M.getNamedValue("objc_retain") ||
47     M.getNamedValue("objc_release") ||
48     M.getNamedValue("objc_autorelease") ||
49     M.getNamedValue("objc_retainAutoreleasedReturnValue") ||
50     M.getNamedValue("objc_retainBlock") ||
51     M.getNamedValue("objc_autoreleaseReturnValue") ||
52     M.getNamedValue("objc_autoreleasePoolPush") ||
53     M.getNamedValue("objc_loadWeakRetained") ||
54     M.getNamedValue("objc_loadWeak") ||
55     M.getNamedValue("objc_destroyWeak") ||
56     M.getNamedValue("objc_storeWeak") ||
57     M.getNamedValue("objc_initWeak") ||
58     M.getNamedValue("objc_moveWeak") ||
59     M.getNamedValue("objc_copyWeak") ||
60     M.getNamedValue("objc_retainedObject") ||
61     M.getNamedValue("objc_unretainedObject") ||
62     M.getNamedValue("objc_unretainedPointer");
63 }
64
65 /// \enum InstructionClass
66 /// \brief A simple classification for instructions.
67 enum InstructionClass {
68   IC_Retain,              ///< objc_retain
69   IC_RetainRV,            ///< objc_retainAutoreleasedReturnValue
70   IC_RetainBlock,         ///< objc_retainBlock
71   IC_Release,             ///< objc_release
72   IC_Autorelease,         ///< objc_autorelease
73   IC_AutoreleaseRV,       ///< objc_autoreleaseReturnValue
74   IC_AutoreleasepoolPush, ///< objc_autoreleasePoolPush
75   IC_AutoreleasepoolPop,  ///< objc_autoreleasePoolPop
76   IC_NoopCast,            ///< objc_retainedObject, etc.
77   IC_FusedRetainAutorelease, ///< objc_retainAutorelease
78   IC_FusedRetainAutoreleaseRV, ///< objc_retainAutoreleaseReturnValue
79   IC_LoadWeakRetained,    ///< objc_loadWeakRetained (primitive)
80   IC_StoreWeak,           ///< objc_storeWeak (primitive)
81   IC_InitWeak,            ///< objc_initWeak (derived)
82   IC_LoadWeak,            ///< objc_loadWeak (derived)
83   IC_MoveWeak,            ///< objc_moveWeak (derived)
84   IC_CopyWeak,            ///< objc_copyWeak (derived)
85   IC_DestroyWeak,         ///< objc_destroyWeak (derived)
86   IC_StoreStrong,         ///< objc_storeStrong (derived)
87   IC_CallOrUser,          ///< could call objc_release and/or "use" pointers
88   IC_Call,                ///< could call objc_release
89   IC_User,                ///< could "use" a pointer
90   IC_None                 ///< anything else
91 };
92
93 static raw_ostream &operator<<(raw_ostream &OS, const InstructionClass Class)
94   LLVM_ATTRIBUTE_USED;
95
96 static raw_ostream &operator<<(raw_ostream &OS, const InstructionClass Class) {
97   switch (Class) {
98   case IC_Retain:
99     return OS << "IC_Retain";
100   case IC_RetainRV:
101     return OS << "IC_RetainRV";
102   case IC_RetainBlock:
103     return OS << "IC_RetainBlock";
104   case IC_Release:
105     return OS << "IC_Release";
106   case IC_Autorelease:
107     return OS << "IC_Autorelease";
108   case IC_AutoreleaseRV:
109     return OS << "IC_AutoreleaseRV";
110   case IC_AutoreleasepoolPush:
111     return OS << "IC_AutoreleasepoolPush";
112   case IC_AutoreleasepoolPop:
113     return OS << "IC_AutoreleasepoolPop";
114   case IC_NoopCast:
115     return OS << "IC_NoopCast";
116   case IC_FusedRetainAutorelease:
117     return OS << "IC_FusedRetainAutorelease";
118   case IC_FusedRetainAutoreleaseRV:
119     return OS << "IC_FusedRetainAutoreleaseRV";
120   case IC_LoadWeakRetained:
121     return OS << "IC_LoadWeakRetained";
122   case IC_StoreWeak:
123     return OS << "IC_StoreWeak";
124   case IC_InitWeak:
125     return OS << "IC_InitWeak";
126   case IC_LoadWeak:
127     return OS << "IC_LoadWeak";
128   case IC_MoveWeak:
129     return OS << "IC_MoveWeak";
130   case IC_CopyWeak:
131     return OS << "IC_CopyWeak";
132   case IC_DestroyWeak:
133     return OS << "IC_DestroyWeak";
134   case IC_StoreStrong:
135     return OS << "IC_StoreStrong";
136   case IC_CallOrUser:
137     return OS << "IC_CallOrUser";
138   case IC_Call:
139     return OS << "IC_Call";
140   case IC_User:
141     return OS << "IC_User";
142   case IC_None:
143     return OS << "IC_None";
144   }
145   llvm_unreachable("Unknown instruction class!");
146 }
147
148
149 /// \brief Determine if F is one of the special known Functions.  If it isn't,
150 /// return IC_CallOrUser.
151 static inline InstructionClass GetFunctionClass(const Function *F) {
152   Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
153
154   // No arguments.
155   if (AI == AE)
156     return StringSwitch<InstructionClass>(F->getName())
157       .Case("objc_autoreleasePoolPush",  IC_AutoreleasepoolPush)
158       .Default(IC_CallOrUser);
159
160   // One argument.
161   const Argument *A0 = AI++;
162   if (AI == AE)
163     // Argument is a pointer.
164     if (PointerType *PTy = dyn_cast<PointerType>(A0->getType())) {
165       Type *ETy = PTy->getElementType();
166       // Argument is i8*.
167       if (ETy->isIntegerTy(8))
168         return StringSwitch<InstructionClass>(F->getName())
169           .Case("objc_retain",                IC_Retain)
170           .Case("objc_retainAutoreleasedReturnValue", IC_RetainRV)
171           .Case("objc_retainBlock",           IC_RetainBlock)
172           .Case("objc_release",               IC_Release)
173           .Case("objc_autorelease",           IC_Autorelease)
174           .Case("objc_autoreleaseReturnValue", IC_AutoreleaseRV)
175           .Case("objc_autoreleasePoolPop",    IC_AutoreleasepoolPop)
176           .Case("objc_retainedObject",        IC_NoopCast)
177           .Case("objc_unretainedObject",      IC_NoopCast)
178           .Case("objc_unretainedPointer",     IC_NoopCast)
179           .Case("objc_retain_autorelease",    IC_FusedRetainAutorelease)
180           .Case("objc_retainAutorelease",     IC_FusedRetainAutorelease)
181           .Case("objc_retainAutoreleaseReturnValue",IC_FusedRetainAutoreleaseRV)
182           .Default(IC_CallOrUser);
183
184       // Argument is i8**
185       if (PointerType *Pte = dyn_cast<PointerType>(ETy))
186         if (Pte->getElementType()->isIntegerTy(8))
187           return StringSwitch<InstructionClass>(F->getName())
188             .Case("objc_loadWeakRetained",      IC_LoadWeakRetained)
189             .Case("objc_loadWeak",              IC_LoadWeak)
190             .Case("objc_destroyWeak",           IC_DestroyWeak)
191             .Default(IC_CallOrUser);
192     }
193
194   // Two arguments, first is i8**.
195   const Argument *A1 = AI++;
196   if (AI == AE)
197     if (PointerType *PTy = dyn_cast<PointerType>(A0->getType()))
198       if (PointerType *Pte = dyn_cast<PointerType>(PTy->getElementType()))
199         if (Pte->getElementType()->isIntegerTy(8))
200           if (PointerType *PTy1 = dyn_cast<PointerType>(A1->getType())) {
201             Type *ETy1 = PTy1->getElementType();
202             // Second argument is i8*
203             if (ETy1->isIntegerTy(8))
204               return StringSwitch<InstructionClass>(F->getName())
205                      .Case("objc_storeWeak",             IC_StoreWeak)
206                      .Case("objc_initWeak",              IC_InitWeak)
207                      .Case("objc_storeStrong",           IC_StoreStrong)
208                      .Default(IC_CallOrUser);
209             // Second argument is i8**.
210             if (PointerType *Pte1 = dyn_cast<PointerType>(ETy1))
211               if (Pte1->getElementType()->isIntegerTy(8))
212                 return StringSwitch<InstructionClass>(F->getName())
213                        .Case("objc_moveWeak",              IC_MoveWeak)
214                        .Case("objc_copyWeak",              IC_CopyWeak)
215                        .Default(IC_CallOrUser);
216           }
217
218   // Anything else.
219   return IC_CallOrUser;
220 }
221
222 /// \brief Determine which objc runtime call instruction class V belongs to.
223 ///
224 /// This is similar to GetInstructionClass except that it only detects objc
225 /// runtime calls. This allows it to be faster.
226 ///
227 static inline InstructionClass GetBasicInstructionClass(const Value *V) {
228   if (const CallInst *CI = dyn_cast<CallInst>(V)) {
229     if (const Function *F = CI->getCalledFunction())
230       return GetFunctionClass(F);
231     // Otherwise, be conservative.
232     return IC_CallOrUser;
233   }
234
235   // Otherwise, be conservative.
236   return isa<InvokeInst>(V) ? IC_CallOrUser : IC_User;
237 }
238
239 } // end namespace objcarc
240 } // end namespace llvm
241
242 #endif // LLVM_TRANSFORMS_SCALAR_OBJCARC_H