Ejemplo n.º 1
0
static bool isAddressTaken(Value* V) {
    //Find the users for the value to see if it was assigned.
  for (Value::const_use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
    User *U = I->getUser();
    if(isa<StoreInst>(U))
      return true;
    if (!isa<CallInst>(U) && !isa<InvokeInst>(U)) {
      if(U->use_empty())
        continue;
      if(isa<GlobalAlias>(U)) {
        if(isAddressTaken(U))
          return true;
      } else {
        if (Constant *C = dyn_cast<Constant>(U)) {
          if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
            if (CE->getOpcode() == Instruction::BitCast) {
              return isAddressTaken(CE);
            }
          }
        }
        return true;
      }

      // FIXME: Can be more robust here for weak aliases that
      // are never used
    } else {
      llvm::CallSite CS(cast<Instruction>(U));
      if (!CS.isCallee(&*I))
        return true;
    }
  }
  return false;
}
Ejemplo n.º 2
0
bool
SPEscapes(Function &F, const Argument *sp_arg) {
  // We monotonically accumulate the set of values that hold a pointer based on Sp
  // INVARIANT: an Instruction in the work list never defines a Value that is already in SpPointers
  std::set<const Value*> SpPointers;
  SpPointers.insert(sp_arg);

  // Initialize the worklist to all of the instructions using the Sp
  std::set<const Instruction*> WorkList;
  for (Value::const_use_iterator UI = sp_arg->use_begin(), UE = sp_arg->use_end(); UI != UE; ++UI)
    WorkList.insert(cast<Instruction>(UI->getUser()));
  
  while (!WorkList.empty()) {
    // Get an element from the worklist
    const Instruction *I = *WorkList.begin();
    WorkList.erase(WorkList.begin());

    // Switch on the kind of instruction to decide whether this instruction should add to SpPointers
    //
    // NB: it is safe to say "load" never adds to SpPointers, since we terminate the
    // fixed point process immediately if we ever detect that a SpPointer escapes.
    //
    // NB: The only calls we see in GHC-generated code will be unsafe foreign calls
    // or tail calls. In either case we can safely assume no escape.
    if (const StoreInst *SI = dyn_cast<StoreInst>(I)) {
      // Check for escape:
      if (SpPointers.find(SI->getValueOperand()) != SpPointers.end()) {
        return true;
      }
      continue;
#if 0
    } else if (AtomicCmpXchgInst *ACXI = dyn_cast<AtomicCmpXchgInst>(I)) {
      // Check for escape:
      if (SpPointers.find(ACXI->getNewValOperand()) != SpPointers.end()) {
        return true;
      }
      continue;
    } else if (AtomicRMWInst *ARMWI = dyn_cast<AtomicRMWInst>(I)) {
      // Check for escape:
      if (SpPointers.find(ARMWI->getValOperand()) != SpPointers.end()) {
        return true;
      }
      continue;
#endif
    } else if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
      if (SpPointers.find(GEPI->getPointerOperand()) == SpPointers.end()) {
        continue;
      }
    } else if (const SelectInst *SI = dyn_cast<SelectInst>(I)) {
      if ((SpPointers.find(SI->getTrueValue())  == SpPointers.end()) &&
          (SpPointers.find(SI->getFalseValue()) == SpPointers.end())) {
        continue;
      }
    } else if (isa<PHINode>(I)) {
      if (!SomeOperandIsSPPointer(SpPointers, I)) continue;
    } else if (isa<BinaryOperator>(I)) {
      if (!SomeOperandIsSPPointer(SpPointers, I)) continue;
    } else if (isa<CastInst>(I)) {
      if (!SomeOperandIsSPPointer(SpPointers, I)) continue;
    } else {
      // Assume all other instructions do not define new SpPointers or avenues for escape.
      continue;
    }

    // We fall through to here if this instruction defines a new SpPointer:
    // add all the use sites to the work list.
    SpPointers.insert(I);
    for (Value::const_use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE; ++UI) {
      // There is nothing more to do if we have already decided that this defines a SpPointer
      if (SpPointers.find(*UI) == SpPointers.end()) {
        WorkList.insert(cast<Instruction>(*UI));
      }
    }
  }

  return false;
}