Created ObjCARCUtil.cpp for functions which in my humble opinion are too large to...
[oota-llvm.git] / lib / Transforms / ObjCARC / ObjCARCUtil.cpp
1 //===- ObjCARCUtil.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 several utility functions used by various ARC
11 /// optimizations which are IMHO too big to be in a header file.
12 ///
13 /// WARNING: This file knows about certain library functions. It recognizes them
14 /// by name, and hardwires knowledge of their semantics.
15 ///
16 /// WARNING: This file knows about how certain Objective-C library functions are
17 /// used. Naive LLVM IR transformations which would otherwise be
18 /// behavior-preserving may break these assumptions.
19 ///
20 //===----------------------------------------------------------------------===//
21
22 #include "ObjCARC.h"
23
24 using namespace llvm;
25 using namespace llvm::objcarc;
26
27 raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS,
28                                        const InstructionClass Class) {
29   switch (Class) {
30   case IC_Retain:
31     return OS << "IC_Retain";
32   case IC_RetainRV:
33     return OS << "IC_RetainRV";
34   case IC_RetainBlock:
35     return OS << "IC_RetainBlock";
36   case IC_Release:
37     return OS << "IC_Release";
38   case IC_Autorelease:
39     return OS << "IC_Autorelease";
40   case IC_AutoreleaseRV:
41     return OS << "IC_AutoreleaseRV";
42   case IC_AutoreleasepoolPush:
43     return OS << "IC_AutoreleasepoolPush";
44   case IC_AutoreleasepoolPop:
45     return OS << "IC_AutoreleasepoolPop";
46   case IC_NoopCast:
47     return OS << "IC_NoopCast";
48   case IC_FusedRetainAutorelease:
49     return OS << "IC_FusedRetainAutorelease";
50   case IC_FusedRetainAutoreleaseRV:
51     return OS << "IC_FusedRetainAutoreleaseRV";
52   case IC_LoadWeakRetained:
53     return OS << "IC_LoadWeakRetained";
54   case IC_StoreWeak:
55     return OS << "IC_StoreWeak";
56   case IC_InitWeak:
57     return OS << "IC_InitWeak";
58   case IC_LoadWeak:
59     return OS << "IC_LoadWeak";
60   case IC_MoveWeak:
61     return OS << "IC_MoveWeak";
62   case IC_CopyWeak:
63     return OS << "IC_CopyWeak";
64   case IC_DestroyWeak:
65     return OS << "IC_DestroyWeak";
66   case IC_StoreStrong:
67     return OS << "IC_StoreStrong";
68   case IC_CallOrUser:
69     return OS << "IC_CallOrUser";
70   case IC_Call:
71     return OS << "IC_Call";
72   case IC_User:
73     return OS << "IC_User";
74   case IC_None:
75     return OS << "IC_None";
76   }
77   llvm_unreachable("Unknown instruction class!");
78 }
79
80 InstructionClass llvm::objcarc::GetFunctionClass(const Function *F) {
81   Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
82
83   // No arguments.
84   if (AI == AE)
85     return StringSwitch<InstructionClass>(F->getName())
86       .Case("objc_autoreleasePoolPush",  IC_AutoreleasepoolPush)
87       .Default(IC_CallOrUser);
88
89   // One argument.
90   const Argument *A0 = AI++;
91   if (AI == AE)
92     // Argument is a pointer.
93     if (PointerType *PTy = dyn_cast<PointerType>(A0->getType())) {
94       Type *ETy = PTy->getElementType();
95       // Argument is i8*.
96       if (ETy->isIntegerTy(8))
97         return StringSwitch<InstructionClass>(F->getName())
98           .Case("objc_retain",                IC_Retain)
99           .Case("objc_retainAutoreleasedReturnValue", IC_RetainRV)
100           .Case("objc_retainBlock",           IC_RetainBlock)
101           .Case("objc_release",               IC_Release)
102           .Case("objc_autorelease",           IC_Autorelease)
103           .Case("objc_autoreleaseReturnValue", IC_AutoreleaseRV)
104           .Case("objc_autoreleasePoolPop",    IC_AutoreleasepoolPop)
105           .Case("objc_retainedObject",        IC_NoopCast)
106           .Case("objc_unretainedObject",      IC_NoopCast)
107           .Case("objc_unretainedPointer",     IC_NoopCast)
108           .Case("objc_retain_autorelease",    IC_FusedRetainAutorelease)
109           .Case("objc_retainAutorelease",     IC_FusedRetainAutorelease)
110           .Case("objc_retainAutoreleaseReturnValue",IC_FusedRetainAutoreleaseRV)
111           .Default(IC_CallOrUser);
112
113       // Argument is i8**
114       if (PointerType *Pte = dyn_cast<PointerType>(ETy))
115         if (Pte->getElementType()->isIntegerTy(8))
116           return StringSwitch<InstructionClass>(F->getName())
117             .Case("objc_loadWeakRetained",      IC_LoadWeakRetained)
118             .Case("objc_loadWeak",              IC_LoadWeak)
119             .Case("objc_destroyWeak",           IC_DestroyWeak)
120             .Default(IC_CallOrUser);
121     }
122
123   // Two arguments, first is i8**.
124   const Argument *A1 = AI++;
125   if (AI == AE)
126     if (PointerType *PTy = dyn_cast<PointerType>(A0->getType()))
127       if (PointerType *Pte = dyn_cast<PointerType>(PTy->getElementType()))
128         if (Pte->getElementType()->isIntegerTy(8))
129           if (PointerType *PTy1 = dyn_cast<PointerType>(A1->getType())) {
130             Type *ETy1 = PTy1->getElementType();
131             // Second argument is i8*
132             if (ETy1->isIntegerTy(8))
133               return StringSwitch<InstructionClass>(F->getName())
134                 .Case("objc_storeWeak",             IC_StoreWeak)
135                 .Case("objc_initWeak",              IC_InitWeak)
136                 .Case("objc_storeStrong",           IC_StoreStrong)
137                 .Default(IC_CallOrUser);
138             // Second argument is i8**.
139             if (PointerType *Pte1 = dyn_cast<PointerType>(ETy1))
140               if (Pte1->getElementType()->isIntegerTy(8))
141                 return StringSwitch<InstructionClass>(F->getName())
142                   .Case("objc_moveWeak",              IC_MoveWeak)
143                   .Case("objc_copyWeak",              IC_CopyWeak)
144                   .Default(IC_CallOrUser);
145           }
146
147   // Anything else.
148   return IC_CallOrUser;
149 }