bool PAEval::runOnFunction(Function &F) {
    SetVector<Value *> Values;

    for (auto &Arg : F.args())
        insertIfNamed(Values, &Arg);

    for (auto I = inst_begin(F), E = inst_end(F); I != E; ++I) {
        insertIfNamed(Values, &*I);

        for (auto &Op : I->operands())
            insertIfNamed(Values, Op);
    }

    ProvenanceAnalysis PA;
    PA.setAA(&getAnalysis<AliasAnalysis>());
    const DataLayout &DL = F.getParent()->getDataLayout();

    for (Value *V1 : Values) {
        StringRef NameV1 = getName(V1);
        for (Value *V2 : Values) {
            StringRef NameV2 = getName(V2);
            if (NameV1 >= NameV2)
                continue;
            errs() << NameV1 << " and " << NameV2;
            if (PA.related(V1, V2, DL))
                errs() << " are related.\n";
            else
                errs() << " are not related.\n";
        }
    }

    return false;
}
Example #2
0
/// Test whether the given instruction can result in a reference count
/// modification (positive or negative) for the pointer's object.
bool
llvm::objcarc::CanAlterRefCount(const Instruction *Inst, const Value *Ptr,
                                ProvenanceAnalysis &PA,
                                InstructionClass Class) {
  switch (Class) {
  case IC_Autorelease:
  case IC_AutoreleaseRV:
  case IC_IntrinsicUser:
  case IC_User:
    // These operations never directly modify a reference count.
    return false;
  default: break;
  }

  ImmutableCallSite CS = static_cast<const Value *>(Inst);
  assert(CS && "Only calls can alter reference counts!");

  // See if AliasAnalysis can help us with the call.
  AliasAnalysis::ModRefBehavior MRB = PA.getAA()->getModRefBehavior(CS);
  if (AliasAnalysis::onlyReadsMemory(MRB))
    return false;
  if (AliasAnalysis::onlyAccessesArgPointees(MRB)) {
    for (ImmutableCallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
         I != E; ++I) {
      const Value *Op = *I;
      if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op))
        return true;
    }
    return false;
  }

  // Assume the worst.
  return true;
}
Example #3
0
/// Test whether the given instruction can "use" the given pointer's object in a
/// way that requires the reference count to be positive.
bool
llvm::objcarc::CanUse(const Instruction *Inst, const Value *Ptr,
                      ProvenanceAnalysis &PA, InstructionClass Class) {
  // IC_Call operations (as opposed to IC_CallOrUser) never "use" objc pointers.
  if (Class == IC_Call)
    return false;

  // Consider various instructions which may have pointer arguments which are
  // not "uses".
  if (const ICmpInst *ICI = dyn_cast<ICmpInst>(Inst)) {
    // Comparing a pointer with null, or any other constant, isn't really a use,
    // because we don't care what the pointer points to, or about the values
    // of any other dynamic reference-counted pointers.
    if (!IsPotentialRetainableObjPtr(ICI->getOperand(1), *PA.getAA()))
      return false;
  } else if (ImmutableCallSite CS = static_cast<const Value *>(Inst)) {
    // For calls, just check the arguments (and not the callee operand).
    for (ImmutableCallSite::arg_iterator OI = CS.arg_begin(),
         OE = CS.arg_end(); OI != OE; ++OI) {
      const Value *Op = *OI;
      if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op))
        return true;
    }
    return false;
  } else if (const StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
    // Special-case stores, because we don't care about the stored value, just
    // the store address.
    const Value *Op = GetUnderlyingObjCPtr(SI->getPointerOperand());
    // If we can't tell what the underlying object was, assume there is a
    // dependence.
    return IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Op, Ptr);
  }

  // Check each operand for a match.
  for (User::const_op_iterator OI = Inst->op_begin(), OE = Inst->op_end();
       OI != OE; ++OI) {
    const Value *Op = *OI;
    if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op))
      return true;
  }
  return false;
}