IC_None ///< anything else
};
-static raw_ostream &operator<<(raw_ostream &OS, const InstructionClass Class)
- LLVM_ATTRIBUTE_USED;
-
-static raw_ostream &operator<<(raw_ostream &OS, const InstructionClass Class) {
- switch (Class) {
- case IC_Retain:
- return OS << "IC_Retain";
- case IC_RetainRV:
- return OS << "IC_RetainRV";
- case IC_RetainBlock:
- return OS << "IC_RetainBlock";
- case IC_Release:
- return OS << "IC_Release";
- case IC_Autorelease:
- return OS << "IC_Autorelease";
- case IC_AutoreleaseRV:
- return OS << "IC_AutoreleaseRV";
- case IC_AutoreleasepoolPush:
- return OS << "IC_AutoreleasepoolPush";
- case IC_AutoreleasepoolPop:
- return OS << "IC_AutoreleasepoolPop";
- case IC_NoopCast:
- return OS << "IC_NoopCast";
- case IC_FusedRetainAutorelease:
- return OS << "IC_FusedRetainAutorelease";
- case IC_FusedRetainAutoreleaseRV:
- return OS << "IC_FusedRetainAutoreleaseRV";
- case IC_LoadWeakRetained:
- return OS << "IC_LoadWeakRetained";
- case IC_StoreWeak:
- return OS << "IC_StoreWeak";
- case IC_InitWeak:
- return OS << "IC_InitWeak";
- case IC_LoadWeak:
- return OS << "IC_LoadWeak";
- case IC_MoveWeak:
- return OS << "IC_MoveWeak";
- case IC_CopyWeak:
- return OS << "IC_CopyWeak";
- case IC_DestroyWeak:
- return OS << "IC_DestroyWeak";
- case IC_StoreStrong:
- return OS << "IC_StoreStrong";
- case IC_CallOrUser:
- return OS << "IC_CallOrUser";
- case IC_Call:
- return OS << "IC_Call";
- case IC_User:
- return OS << "IC_User";
- case IC_None:
- return OS << "IC_None";
- }
- llvm_unreachable("Unknown instruction class!");
-}
+raw_ostream &operator<<(raw_ostream &OS, const InstructionClass Class);
/// \brief Test if the given class is objc_retain or equivalent.
static inline bool IsRetain(InstructionClass Class) {
/// \brief Determine if F is one of the special known Functions. If it isn't,
/// return IC_CallOrUser.
-static InstructionClass GetFunctionClass(const Function *F)
- LLVM_ATTRIBUTE_USED;
-static InstructionClass GetFunctionClass(const Function *F) {
- Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
-
- // No arguments.
- if (AI == AE)
- return StringSwitch<InstructionClass>(F->getName())
- .Case("objc_autoreleasePoolPush", IC_AutoreleasepoolPush)
- .Default(IC_CallOrUser);
-
- // One argument.
- const Argument *A0 = AI++;
- if (AI == AE)
- // Argument is a pointer.
- if (PointerType *PTy = dyn_cast<PointerType>(A0->getType())) {
- Type *ETy = PTy->getElementType();
- // Argument is i8*.
- if (ETy->isIntegerTy(8))
- return StringSwitch<InstructionClass>(F->getName())
- .Case("objc_retain", IC_Retain)
- .Case("objc_retainAutoreleasedReturnValue", IC_RetainRV)
- .Case("objc_retainBlock", IC_RetainBlock)
- .Case("objc_release", IC_Release)
- .Case("objc_autorelease", IC_Autorelease)
- .Case("objc_autoreleaseReturnValue", IC_AutoreleaseRV)
- .Case("objc_autoreleasePoolPop", IC_AutoreleasepoolPop)
- .Case("objc_retainedObject", IC_NoopCast)
- .Case("objc_unretainedObject", IC_NoopCast)
- .Case("objc_unretainedPointer", IC_NoopCast)
- .Case("objc_retain_autorelease", IC_FusedRetainAutorelease)
- .Case("objc_retainAutorelease", IC_FusedRetainAutorelease)
- .Case("objc_retainAutoreleaseReturnValue",IC_FusedRetainAutoreleaseRV)
- .Default(IC_CallOrUser);
-
- // Argument is i8**
- if (PointerType *Pte = dyn_cast<PointerType>(ETy))
- if (Pte->getElementType()->isIntegerTy(8))
- return StringSwitch<InstructionClass>(F->getName())
- .Case("objc_loadWeakRetained", IC_LoadWeakRetained)
- .Case("objc_loadWeak", IC_LoadWeak)
- .Case("objc_destroyWeak", IC_DestroyWeak)
- .Default(IC_CallOrUser);
- }
-
- // Two arguments, first is i8**.
- const Argument *A1 = AI++;
- if (AI == AE)
- if (PointerType *PTy = dyn_cast<PointerType>(A0->getType()))
- if (PointerType *Pte = dyn_cast<PointerType>(PTy->getElementType()))
- if (Pte->getElementType()->isIntegerTy(8))
- if (PointerType *PTy1 = dyn_cast<PointerType>(A1->getType())) {
- Type *ETy1 = PTy1->getElementType();
- // Second argument is i8*
- if (ETy1->isIntegerTy(8))
- return StringSwitch<InstructionClass>(F->getName())
- .Case("objc_storeWeak", IC_StoreWeak)
- .Case("objc_initWeak", IC_InitWeak)
- .Case("objc_storeStrong", IC_StoreStrong)
- .Default(IC_CallOrUser);
- // Second argument is i8**.
- if (PointerType *Pte1 = dyn_cast<PointerType>(ETy1))
- if (Pte1->getElementType()->isIntegerTy(8))
- return StringSwitch<InstructionClass>(F->getName())
- .Case("objc_moveWeak", IC_MoveWeak)
- .Case("objc_copyWeak", IC_CopyWeak)
- .Default(IC_CallOrUser);
- }
-
- // Anything else.
- return IC_CallOrUser;
-}
+InstructionClass GetFunctionClass(const Function *F);
/// \brief Determine which objc runtime call instruction class V belongs to.
///
--- /dev/null
+//===- ObjCARCUtil.h - ObjC ARC Optimization ----------*- mode: c++ -*-----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file defines several utility functions used by various ARC
+/// optimizations which are IMHO too big to be in a header file.
+///
+/// WARNING: This file knows about certain library functions. It recognizes them
+/// by name, and hardwires knowledge of their semantics.
+///
+/// WARNING: This file knows about how certain Objective-C library functions are
+/// used. Naive LLVM IR transformations which would otherwise be
+/// behavior-preserving may break these assumptions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ObjCARC.h"
+
+using namespace llvm;
+using namespace llvm::objcarc;
+
+raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS,
+ const InstructionClass Class) {
+ switch (Class) {
+ case IC_Retain:
+ return OS << "IC_Retain";
+ case IC_RetainRV:
+ return OS << "IC_RetainRV";
+ case IC_RetainBlock:
+ return OS << "IC_RetainBlock";
+ case IC_Release:
+ return OS << "IC_Release";
+ case IC_Autorelease:
+ return OS << "IC_Autorelease";
+ case IC_AutoreleaseRV:
+ return OS << "IC_AutoreleaseRV";
+ case IC_AutoreleasepoolPush:
+ return OS << "IC_AutoreleasepoolPush";
+ case IC_AutoreleasepoolPop:
+ return OS << "IC_AutoreleasepoolPop";
+ case IC_NoopCast:
+ return OS << "IC_NoopCast";
+ case IC_FusedRetainAutorelease:
+ return OS << "IC_FusedRetainAutorelease";
+ case IC_FusedRetainAutoreleaseRV:
+ return OS << "IC_FusedRetainAutoreleaseRV";
+ case IC_LoadWeakRetained:
+ return OS << "IC_LoadWeakRetained";
+ case IC_StoreWeak:
+ return OS << "IC_StoreWeak";
+ case IC_InitWeak:
+ return OS << "IC_InitWeak";
+ case IC_LoadWeak:
+ return OS << "IC_LoadWeak";
+ case IC_MoveWeak:
+ return OS << "IC_MoveWeak";
+ case IC_CopyWeak:
+ return OS << "IC_CopyWeak";
+ case IC_DestroyWeak:
+ return OS << "IC_DestroyWeak";
+ case IC_StoreStrong:
+ return OS << "IC_StoreStrong";
+ case IC_CallOrUser:
+ return OS << "IC_CallOrUser";
+ case IC_Call:
+ return OS << "IC_Call";
+ case IC_User:
+ return OS << "IC_User";
+ case IC_None:
+ return OS << "IC_None";
+ }
+ llvm_unreachable("Unknown instruction class!");
+}
+
+InstructionClass llvm::objcarc::GetFunctionClass(const Function *F) {
+ Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
+
+ // No arguments.
+ if (AI == AE)
+ return StringSwitch<InstructionClass>(F->getName())
+ .Case("objc_autoreleasePoolPush", IC_AutoreleasepoolPush)
+ .Default(IC_CallOrUser);
+
+ // One argument.
+ const Argument *A0 = AI++;
+ if (AI == AE)
+ // Argument is a pointer.
+ if (PointerType *PTy = dyn_cast<PointerType>(A0->getType())) {
+ Type *ETy = PTy->getElementType();
+ // Argument is i8*.
+ if (ETy->isIntegerTy(8))
+ return StringSwitch<InstructionClass>(F->getName())
+ .Case("objc_retain", IC_Retain)
+ .Case("objc_retainAutoreleasedReturnValue", IC_RetainRV)
+ .Case("objc_retainBlock", IC_RetainBlock)
+ .Case("objc_release", IC_Release)
+ .Case("objc_autorelease", IC_Autorelease)
+ .Case("objc_autoreleaseReturnValue", IC_AutoreleaseRV)
+ .Case("objc_autoreleasePoolPop", IC_AutoreleasepoolPop)
+ .Case("objc_retainedObject", IC_NoopCast)
+ .Case("objc_unretainedObject", IC_NoopCast)
+ .Case("objc_unretainedPointer", IC_NoopCast)
+ .Case("objc_retain_autorelease", IC_FusedRetainAutorelease)
+ .Case("objc_retainAutorelease", IC_FusedRetainAutorelease)
+ .Case("objc_retainAutoreleaseReturnValue",IC_FusedRetainAutoreleaseRV)
+ .Default(IC_CallOrUser);
+
+ // Argument is i8**
+ if (PointerType *Pte = dyn_cast<PointerType>(ETy))
+ if (Pte->getElementType()->isIntegerTy(8))
+ return StringSwitch<InstructionClass>(F->getName())
+ .Case("objc_loadWeakRetained", IC_LoadWeakRetained)
+ .Case("objc_loadWeak", IC_LoadWeak)
+ .Case("objc_destroyWeak", IC_DestroyWeak)
+ .Default(IC_CallOrUser);
+ }
+
+ // Two arguments, first is i8**.
+ const Argument *A1 = AI++;
+ if (AI == AE)
+ if (PointerType *PTy = dyn_cast<PointerType>(A0->getType()))
+ if (PointerType *Pte = dyn_cast<PointerType>(PTy->getElementType()))
+ if (Pte->getElementType()->isIntegerTy(8))
+ if (PointerType *PTy1 = dyn_cast<PointerType>(A1->getType())) {
+ Type *ETy1 = PTy1->getElementType();
+ // Second argument is i8*
+ if (ETy1->isIntegerTy(8))
+ return StringSwitch<InstructionClass>(F->getName())
+ .Case("objc_storeWeak", IC_StoreWeak)
+ .Case("objc_initWeak", IC_InitWeak)
+ .Case("objc_storeStrong", IC_StoreStrong)
+ .Default(IC_CallOrUser);
+ // Second argument is i8**.
+ if (PointerType *Pte1 = dyn_cast<PointerType>(ETy1))
+ if (Pte1->getElementType()->isIntegerTy(8))
+ return StringSwitch<InstructionClass>(F->getName())
+ .Case("objc_moveWeak", IC_MoveWeak)
+ .Case("objc_copyWeak", IC_CopyWeak)
+ .Default(IC_CallOrUser);
+ }
+
+ // Anything else.
+ return IC_CallOrUser;
+}