#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
#include "llvm/Analysis/ObjCARCAnalysisUtils.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/IR/Function.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#define DEBUG_TYPE "objc-arc-aa"
using namespace llvm;
using namespace llvm::objcarc;
AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA,
const MemoryLocation &LocB,
AAQueryInfo &AAQI) {
if (!EnableARCOpts)
return AAResultBase::alias(LocA, LocB, AAQI);
const Value *SA = GetRCIdentityRoot(LocA.Ptr);
const Value *SB = GetRCIdentityRoot(LocB.Ptr);
AliasResult Result =
AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
MemoryLocation(SB, LocB.Size, LocB.AATags), AAQI);
if (Result != AliasResult::MayAlias)
return Result;
const Value *UA = GetUnderlyingObjCPtr(SA);
const Value *UB = GetUnderlyingObjCPtr(SB);
if (UA != SA || UB != SB) {
Result = AAResultBase::alias(MemoryLocation::getBeforeOrAfter(UA),
MemoryLocation::getBeforeOrAfter(UB), AAQI);
if (Result == AliasResult::NoAlias)
return AliasResult::NoAlias;
}
return AliasResult::MayAlias;
}
bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
AAQueryInfo &AAQI, bool OrLocal) {
if (!EnableARCOpts)
return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
const Value *S = GetRCIdentityRoot(Loc.Ptr);
if (AAResultBase::pointsToConstantMemory(
MemoryLocation(S, Loc.Size, Loc.AATags), AAQI, OrLocal))
return true;
const Value *U = GetUnderlyingObjCPtr(S);
if (U != S)
return AAResultBase::pointsToConstantMemory(
MemoryLocation::getBeforeOrAfter(U), AAQI, OrLocal);
return false;
}
FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) {
if (!EnableARCOpts)
return AAResultBase::getModRefBehavior(F);
switch (GetFunctionClass(F)) {
case ARCInstKind::NoopCast:
return FMRB_DoesNotAccessMemory;
default:
break;
}
return AAResultBase::getModRefBehavior(F);
}
ModRefInfo ObjCARCAAResult::getModRefInfo(const CallBase *Call,
const MemoryLocation &Loc,
AAQueryInfo &AAQI) {
if (!EnableARCOpts)
return AAResultBase::getModRefInfo(Call, Loc, AAQI);
switch (GetBasicARCInstKind(Call)) {
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
case ARCInstKind::Autorelease:
case ARCInstKind::AutoreleaseRV:
case ARCInstKind::NoopCast:
case ARCInstKind::AutoreleasepoolPush:
case ARCInstKind::FusedRetainAutorelease:
case ARCInstKind::FusedRetainAutoreleaseRV:
return ModRefInfo::NoModRef;
default:
break;
}
return AAResultBase::getModRefInfo(Call, Loc, AAQI);
}
AnalysisKey ObjCARCAA::Key;
ObjCARCAAResult ObjCARCAA::run(Function &F, FunctionAnalysisManager &AM) {
return ObjCARCAAResult(F.getParent()->getDataLayout());
}
char ObjCARCAAWrapperPass::ID = 0;
INITIALIZE_PASS(ObjCARCAAWrapperPass, "objc-arc-aa",
"ObjC-ARC-Based Alias Analysis", false, true)
ImmutablePass *llvm::createObjCARCAAWrapperPass() {
return new ObjCARCAAWrapperPass();
}
ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) {
initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry());
}
bool ObjCARCAAWrapperPass::doInitialization(Module &M) {
Result.reset(new ObjCARCAAResult(M.getDataLayout()));
return false;
}
bool ObjCARCAAWrapperPass::doFinalization(Module &M) {
Result.reset();
return false;
}
void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}