Ejemplo n.º 1
0
// visitCallInst - This converts all LLVM call instructions into invoke
// instructions. The except part of the invoke goes to the "LongJmpBlkPre"
// that grabs the exception and proceeds to determine if it's a longjmp
// exception or not.
void LowerSetJmp::visitCallInst(CallInst& CI)
{
  if (CI.getCalledFunction())
    if (!IsTransformableFunction(CI.getCalledFunction()->getName()) ||
        CI.getCalledFunction()->isIntrinsic()) return;

  BasicBlock* OldBB = CI.getParent();

  // If not reachable from a setjmp call, don't transform.
  if (!DFSBlocks.count(OldBB)) return;

  BasicBlock* NewBB = OldBB->splitBasicBlock(CI);
  assert(NewBB && "Couldn't split BB of \"call\" instruction!!");
  DFSBlocks.insert(NewBB);
  NewBB->setName("Call2Invoke");

  Function* Func = OldBB->getParent();

  // Construct the new "invoke" instruction.
  TerminatorInst* Term = OldBB->getTerminator();
  std::vector<Value*> Params(CI.op_begin() + 1, CI.op_end());
  InvokeInst* II =
    InvokeInst::Create(CI.getCalledValue(), NewBB, PrelimBBMap[Func],
                       Params.begin(), Params.end(), CI.getName(), Term);
  II->setCallingConv(CI.getCallingConv());
  II->setParamAttrs(CI.getParamAttrs());

  // Replace the old call inst with the invoke inst and remove the call.
  CI.replaceAllUsesWith(II);
  CI.getParent()->getInstList().erase(&CI);

  // The old terminator is useless now that we have the invoke inst.
  Term->getParent()->getInstList().erase(Term);
  ++CallsTransformed;
}
Ejemplo n.º 2
0
bool CallLowering::lowerCall(
    MachineIRBuilder &MIRBuilder, const CallInst &CI, unsigned ResReg,
    ArrayRef<unsigned> ArgRegs, std::function<unsigned()> GetCalleeReg) const {
  auto &DL = CI.getParent()->getParent()->getParent()->getDataLayout();

  // First step is to marshall all the function's parameters into the correct
  // physregs and memory locations. Gather the sequence of argument types that
  // we'll pass to the assigner function.
  SmallVector<ArgInfo, 8> OrigArgs;
  unsigned i = 0;
  for (auto &Arg : CI.arg_operands()) {
    ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}};
    setArgFlags(OrigArg, i + 1, DL, CI);
    OrigArgs.push_back(OrigArg);
    ++i;
  }

  MachineOperand Callee = MachineOperand::CreateImm(0);
  if (Function *F = CI.getCalledFunction())
    Callee = MachineOperand::CreateGA(F, 0);
  else
    Callee = MachineOperand::CreateReg(GetCalleeReg(), false);

  ArgInfo OrigRet{ResReg, CI.getType(), ISD::ArgFlagsTy{}};
  if (!OrigRet.Ty->isVoidTy())
    setArgFlags(OrigRet, AttributeSet::ReturnIndex, DL, CI);

  return lowerCall(MIRBuilder, Callee, OrigRet, OrigArgs);
}
Ejemplo n.º 3
0
void SelectionDAGBuilder::visitGCResult(const CallInst &CI) {
  // The result value of the gc_result is simply the result of the actual
  // call.  We've already emitted this, so just grab the value.
  Instruction *I = cast<Instruction>(CI.getArgOperand(0));
  assert(isStatepoint(I) && "first argument must be a statepoint token");

  if (I->getParent() != CI.getParent()) {
    // Statepoint is in different basic block so we should have stored call
    // result in a virtual register.
    // We can not use default getValue() functionality to copy value from this
    // register because statepoint and actuall call return types can be
    // different, and getValue() will use CopyFromReg of the wrong type,
    // which is always i32 in our case.
    PointerType *CalleeType = cast<PointerType>(
        ImmutableStatepoint(I).getCalledValue()->getType());
    Type *RetTy =
        cast<FunctionType>(CalleeType->getElementType())->getReturnType();
    SDValue CopyFromReg = getCopyFromRegs(I, RetTy);

    assert(CopyFromReg.getNode());
    setValue(&CI, CopyFromReg);
  } else {
    setValue(&CI, getValue(I));
  }
}
Ejemplo n.º 4
0
/// Extract in a new basic block the omp fork call
int SplitOMPCall(Module *mod, Function *F, Pass *P, std::string RegionName) {
  std::string functionCall;
  int t = 0;

  CallInst *iFirst;
  Instruction *iSecond;

  // XXX To optimize with a single run trough the instructions
  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
    if (t) {
      Instruction *instru = dyn_cast<Instruction>(&*I);
      iSecond = instru;
      break;
    }
    if (CallInst *callInst = dyn_cast<CallInst>(&*I)) {
      if (callInst->getCalledFunction()) {
        functionCall = callInst->getCalledFunction()->getName();
        if (ChooseExtract(functionCall, RegionName, callInst, F)) {
          t = 1;
          iFirst = callInst;
        }
      }
    }
  }
  if (t) {
    SplitBlock(iFirst->getParent(), iFirst, P);
    SplitBlock(iSecond->getParent(), iSecond, P);
  }

  return t;
}
Ejemplo n.º 5
0
//
// Function: makeFSParameterCallsComplete()
//
// Description:
//  Finds calls to sc.fsparameter and fills in the completeness byte which
//  is the last argument to such call. The second argument to the function
//  is the one which is analyzed for completeness.
//
// Inputs:
//  M      - Reference to the the module to analyze
//
void
CompleteChecks::makeFSParameterCallsComplete(Module &M)
{
  Function *sc_fsparameter = M.getFunction("sc.fsparameter");

  if (sc_fsparameter == NULL)
    return;

  std::set<CallInst *> toComplete;

  //
  // Iterate over all uses of sc.fsparameter and discover which have a complete
  // pointer argument.
  //
  for (Function::use_iterator i = sc_fsparameter->use_begin();
       i != sc_fsparameter->use_end(); ++i) {
    CallInst *CI;
    CI = dyn_cast<CallInst>(*i);
    if (CI == 0 || CI->getCalledFunction() != sc_fsparameter)
      continue;

    //
    // Get the parent function to which this call belongs.
    //
    Function *P = CI->getParent()->getParent();
    Value *PtrOperand = CI->getOperand(2);
    
    DSNode *N = getDSNodeHandle(PtrOperand, P).getNode();

    if (N == 0                ||
        N->isExternalNode()   ||
        N->isIncompleteNode() ||
        N->isUnknownNode()    ||
        N->isPtrToIntNode()   ||
        N->isIntToPtrNode()) {
      continue;
    }

    toComplete.insert(CI);
  }

  //
  // Fill in a 1 for each call instruction that has a complete pointer
  // argument.
  //
  Type *int8      = Type::getInt8Ty(M.getContext());
  Constant *complete = ConstantInt::get(int8, 1);

  for (std::set<CallInst *>::iterator i = toComplete.begin();
       i != toComplete.end();
       ++i) {
    CallInst *CI = *i;
    CI->setOperand(4, complete);
  }

  return;
}
void
PoolRegisterElimination::removeTypeSafeRegistrations (const char * name) {
  //
  // Scan through all uses of the registration function and see if it can be
  // safely removed.  If so, schedule it for removal.
  //
  std::vector<CallInst*> toBeRemoved;
  Function * F = intrinsic->getIntrinsic(name).F;

  //
  // Look for and record all registrations that can be deleted.
  //
  for (Value::use_iterator UI=F->use_begin(), UE=F->use_end();
       UI != UE;
       ++UI) {
    //
    // Get the pointer to the registered object.
    //
    CallInst * CI = cast<CallInst>(*UI);
    Value * Ptr = intrinsic->getValuePointer(CI);
    // Lookup the DSNode for the value in the function's DSGraph.
    //
    DSGraph * TDG = dsaPass->getDSGraph(*(CI->getParent()->getParent()));
    DSNodeHandle DSH = TDG->getNodeForValue(Ptr);
    assert ((!(DSH.isNull())) && "No DSNode for Value!\n");

    //
    // If the DSNode is type-safe and is never used as an array, then there
    // will never be a need to look it up in a splay tree, so remove its
    // registration.
    //
    DSNode * N = DSH.getNode();
    if(!N->isArrayNode() && 
       TS->isTypeSafe(Ptr, F)){
      toBeRemoved.push_back(CI);
    }
  }

  //
  // Update the statistics.
  //
  if (toBeRemoved.size()) {
    RemovedRegistration += toBeRemoved.size();
    TypeSafeRegistrations += toBeRemoved.size();
  }

  //
  // Remove the unnecesary registrations.
  //
  std::vector<CallInst*>::iterator it, end;
  for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) {
    (*it)->eraseFromParent();
  }
}
Ejemplo n.º 7
0
/// rewriteExpensiveInvoke - Insert code and hack the function to replace the
/// specified invoke instruction with a call.
void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo,
                                         AllocaInst *InvokeNum,
                                         AllocaInst *StackPtr,
                                         SwitchInst *CatchSwitch) {
  ConstantInt *InvokeNoC = ConstantInt::get(Type::getInt32Ty(II->getContext()),
                                            InvokeNo);

  // If the unwind edge has phi nodes, split the edge.
  if (isa<PHINode>(II->getUnwindDest()->begin())) {
    SplitCriticalEdge(II, 1, this);

    // If there are any phi nodes left, they must have a single predecessor.
    while (PHINode *PN = dyn_cast<PHINode>(II->getUnwindDest()->begin())) {
      PN->replaceAllUsesWith(PN->getIncomingValue(0));
      PN->eraseFromParent();
    }
  }

  // Insert a store of the invoke num before the invoke and store zero into the
  // location afterward.
  new StoreInst(InvokeNoC, InvokeNum, true, II);  // volatile
  
  // Insert a store of the stack ptr before the invoke, so we can restore it
  // later in the exception case.
  CallInst* StackSaveRet = CallInst::Create(StackSaveFn, "ssret", II);
  new StoreInst(StackSaveRet, StackPtr, true, II); // volatile

  BasicBlock::iterator NI = II->getNormalDest()->getFirstInsertionPt();
  // nonvolatile.
  new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())), 
                InvokeNum, false, NI);

  Instruction* StackPtrLoad =
    new LoadInst(StackPtr, "stackptr.restore", true,
                 II->getUnwindDest()->getFirstInsertionPt());
  CallInst::Create(StackRestoreFn, StackPtrLoad, "")->insertAfter(StackPtrLoad);
    
  // Add a switch case to our unwind block.
  CatchSwitch->addCase(InvokeNoC, II->getUnwindDest());

  // Insert a normal call instruction.
  SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3);
  CallInst *NewCall = CallInst::Create(II->getCalledValue(),
                                       CallArgs, "", II);
  NewCall->takeName(II);
  NewCall->setCallingConv(II->getCallingConv());
  NewCall->setAttributes(II->getAttributes());
  NewCall->setDebugLoc(II->getDebugLoc());
  II->replaceAllUsesWith(NewCall);

  // Replace the invoke with an uncond branch.
  BranchInst::Create(II->getNormalDest(), NewCall->getParent());
  II->eraseFromParent();
}
Ejemplo n.º 8
0
void AMDGPUAnnotateKernelFeatures::addAttrToCallers(Function *Intrin,
                                                    StringRef AttrName) {
  SmallPtrSet<Function *, 4> SeenFuncs;

  for (User *U : Intrin->users()) {
    // CallInst is the only valid user for an intrinsic.
    CallInst *CI = cast<CallInst>(U);

    Function *CallingFunction = CI->getParent()->getParent();
    if (SeenFuncs.insert(CallingFunction).second)
      CallingFunction->addFnAttr(AttrName);
  }
}
Ejemplo n.º 9
0
void ExtractContracts::visitCallInst(CallInst &I) {
  if (auto F = I.getCalledFunction()) {
    auto name = F->getName();
    if (name == Naming::CONTRACT_REQUIRES ||
        name == Naming::CONTRACT_ENSURES ||
        name == Naming::CONTRACT_INVARIANT) {

      validateAnnotation(I);

      if (auto J = dyn_cast<CallInst>(I.getArgOperand(0)))
        if (auto G = J->getCalledFunction())
          if (G->getName().find(Naming::CONTRACT_EXPR) != std::string::npos)
            return;

      Function* EF;
      std::vector<Value*> Args;
      tie(EF, Args) = extractExpression(I.getArgOperand(0), I.getParent());
      I.setArgOperand(0, CallInst::Create(EF, Args, "", &I));
      modified = true;

      // TODO can we somehow force LLVM to consider calls to the obsoleted
      // forall, exists, etc., to be dead code?

    } else if (name == Naming::CONTRACT_FORALL ||
               name == Naming::CONTRACT_EXISTS) {

      if (auto J = dyn_cast<CallInst>(I.getArgOperand(1)))
        if (auto G = J->getCalledFunction())
          if (G->getName().find(Naming::CONTRACT_EXPR) != std::string::npos)
            return;

      Function* EF;
      std::vector<Value*> Args;
      tie(EF, Args) = extractExpression(I.getArgOperand(1), I.getParent());
      I.setArgOperand(1, CallInst::Create(EF, Args, "", &I));
      modified = true;
    }
  }
}
Ejemplo n.º 10
0
bool DINOTaskBoundaries::getTaskBoundariesFromCall (CallInst &CI, DINOGlobal::BasicBlockSet &TBs) {

    /*TBs Collects the Task Boundaries for this store instruction*/
    IsTaskBoundaryPredicate collect = IsTaskBoundaryPredicate();
    IsTaskBoundaryOrFunctionEntryPredicate stop = IsTaskBoundaryOrFunctionEntryPredicate();
    BasicBlock *CB = CI.getParent();

    DINOGlobal::BasicBlockList visited = DINOGlobal::BasicBlockList();

    DINOGlobal::CollectBBsPredicated(*CB, visited, TBs,
                         collect, /*Collection Predicate*/
                         stop);/*Traversal Stop Predicate*/

    return !stop.hitTaskBoundary;

}
Ejemplo n.º 11
0
void LLSTDebuggingPass::insertSelfInSendMessageCheck(Function& F)
{
    Value* BrokenSelfMessage = m_builder->CreateGlobalStringPtr("\nself is broken\n");

    InstructionVector Calls;
    for (Function::iterator BB = F.begin(); BB != F.end(); ++BB)
    {
        for(BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II)
        {
            if (CallInst* Call = dyn_cast<CallInst>(II)) {
                if (Call->getCalledFunction()->getName() == "sendMessage")
                    Calls.push_back(Call);
            }
        }
    }

    for(std::size_t i = 0; i < Calls.size(); i++)
    {
        CallInst* Call = dyn_cast<CallInst>(Calls[i]);

        BasicBlock* PointerIsOkBB = Call->getParent()->splitBasicBlock( static_cast<BasicBlock::iterator>(Call) );
        BasicBlock* PointerIsBrokenBB = BasicBlock::Create(m_module->getContext(), "", &F, PointerIsOkBB);
        BasicBlock* PointerIsNotSmallIntBB = BasicBlock::Create(m_module->getContext(), "", &F, PointerIsBrokenBB);

        Instruction* branchToPointerIsOkBB = & PointerIsOkBB->getSinglePredecessor()->back();
        m_builder->SetInsertPoint(branchToPointerIsOkBB);


        Value* argsPtr = m_builder->CreateBitCast( Call->getArgOperand(2), m_baseTypes.object->getPointerTo());
        Value* self = m_builder->CreateCall2(getObjectField, argsPtr, m_builder->getInt32(0));

        Value* isSmallInt = m_builder->CreateCall(isSmallInteger, self);
        m_builder->CreateCondBr(isSmallInt, PointerIsOkBB, PointerIsNotSmallIntBB);


        m_builder->SetInsertPoint(PointerIsNotSmallIntBB);
        Value* klassPtr = m_builder->CreateCall(getObjectClass, self);
        Value* pointerIsNull = m_builder->CreateICmpEQ(klassPtr, ConstantPointerNull::get(m_baseTypes.klass->getPointerTo()) );
        m_builder->CreateCondBr(pointerIsNull, PointerIsBrokenBB, PointerIsOkBB);
        branchToPointerIsOkBB->eraseFromParent();

        m_builder->SetInsertPoint(PointerIsBrokenBB);
        m_builder->CreateCall(_printf, BrokenSelfMessage);
        m_builder->CreateBr(PointerIsOkBB);
    }
}
Ejemplo n.º 12
0
Value *
StringAllocatorInfo::getOrCreateAllocSize (Value * AllocSite) const {
  //
  // See if this is a call to the allocator.  If not, return NULL.
  //
  CallInst * CI = dyn_cast<CallInst>(AllocSite);
  if (!CI)
    return NULL;

  Function * F  = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts());
  if (!F || F->getName() != allocCallName) 
    return NULL;

  //
  // See if this call has an argument.  If not, ignore it.  We do this because
  // autoconf configure scripts will create calls to string functions with zero
  // arguments just to see if the function exists.
  //
  CallSite CS(CI);
  if (CS.arg_size() == 0)
    return NULL;

  //
  // Insert a call to strlen() to determine the length of the string that was
  // allocated.  Use a version of strlen() in the SAFECode library that can
  // handle NULL pointers.
  //
  Module * M = CI->getParent()->getParent()->getParent();
  Function * Strlen = M->getFunction ("nullstrlen");
  assert (Strlen && "No nullstrlen function in the module");
  BasicBlock::iterator InsertPt = CI;
  ++InsertPt;
  Instruction * Length =
    CallInst::Create (Strlen, CS.getInstruction(), "", InsertPt);

  //
  // The size of the allocation is the string length plus one.
  //
  IntegerType * LengthType = dyn_cast<IntegerType>(Length->getType());
  assert (LengthType && "nullstrlen doesn't return an integer?");
  Value * One = ConstantInt::get (LengthType, 1);
  Instruction * Size = BinaryOperator::Create (Instruction::Add, Length, One);
  Size->insertAfter (Length);
  return Size;
}
Ejemplo n.º 13
0
/// rewriteExpensiveInvoke - Insert code and hack the function to replace the
/// specified invoke instruction with a call.
void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo,
                                         AllocaInst *InvokeNum,
                                         SwitchInst *CatchSwitch) {
  ConstantInt *InvokeNoC = ConstantInt::get(Type::getInt32Ty(II->getContext()),
                                            InvokeNo);

  // If the unwind edge has phi nodes, split the edge.
  if (isa<PHINode>(II->getUnwindDest()->begin())) {
    SplitCriticalEdge(II, 1, this);

    // If there are any phi nodes left, they must have a single predecessor.
    while (PHINode *PN = dyn_cast<PHINode>(II->getUnwindDest()->begin())) {
      PN->replaceAllUsesWith(PN->getIncomingValue(0));
      PN->eraseFromParent();
    }
  }

  // Insert a store of the invoke num before the invoke and store zero into the
  // location afterward.
  new StoreInst(InvokeNoC, InvokeNum, true, II);  // volatile

  BasicBlock::iterator NI = II->getNormalDest()->getFirstNonPHI();
  // nonvolatile.
  new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())), 
                InvokeNum, false, NI);

  // Add a switch case to our unwind block.
  CatchSwitch->addCase(InvokeNoC, II->getUnwindDest());

  // Insert a normal call instruction.
  std::vector<Value*> CallArgs(II->op_begin()+3, II->op_end());
  CallInst *NewCall = CallInst::Create(II->getCalledValue(),
                                       CallArgs.begin(), CallArgs.end(), "",
                                       II);
  NewCall->takeName(II);
  NewCall->setCallingConv(II->getCallingConv());
  NewCall->setAttributes(II->getAttributes());
  II->replaceAllUsesWith(NewCall);

  // Replace the invoke with an uncond branch.
  BranchInst::Create(II->getNormalDest(), NewCall->getParent());
  II->eraseFromParent();
}
Ejemplo n.º 14
0
void ArgumentRecovery::fixCallSites(Function& base, Function& newTarget, const CallInformation& ci)
{
	auto targetInfo = TargetInfo::getTargetInfo(*base.getParent());
	
	// loop over callers and transform call sites.
	while (!base.use_empty())
	{
		CallInst* call = cast<CallInst>(base.user_back());
		Function* caller = call->getParent()->getParent();
		auto registers = getRegisterPtr(*caller);
		auto newCall = createCallSite(*targetInfo, ci, newTarget, *registers, *call);
		
		// replace call
		newCall->takeName(call);
		call->eraseFromParent();
		
		md::incrementFunctionVersion(*caller);
	}
}
Ejemplo n.º 15
0
void ExtractContracts::validateAnnotation(CallInst &I) {
  assert(I.getCalledFunction() && "Unexpected virtual function.");
  assert(I.getNumArgOperands() == 1 && "Unexpected operands.");
  auto B = I.getParent();
  auto F = B->getParent();
  auto& DT = getAnalysis<DominatorTreeWrapperPass>(*F).getDomTree();
  auto& LI = getAnalysis<LoopInfoWrapperPass>(*F).getLoopInfo();
  if (I.getCalledFunction()->getName() == Naming::CONTRACT_INVARIANT) {
    auto L = LI[B];
    if (!L) {
      llvm_unreachable("Loop invariants must occur inside loops.");
    }
  } else {
    for (auto L : LI) {
      auto& J = L->getHeader()->getInstList().front();
      if (DT.dominates(&J, &I)) {
        llvm_unreachable("Procedure specifications must occur before loops.");
      }
    }
  }
}
Ejemplo n.º 16
0
void insertCallToAccessFunctionSequential(Function *F, Function *cF) {
  CallInst *I;
  BasicBlock *b;

  Value::user_iterator i = F->user_begin(), e = F->user_end();
  while (i != e) {
    if (isa<CallInst>(*i)) {

      I = dyn_cast<CallInst>(*i);
      b = I->getParent();
      BasicBlock::iterator helper(I);
      CallInst *ci = dyn_cast<CallInst>(I->clone());
      ci->setCalledFunction(cF);
      b->getInstList().insertAfter(helper, ci);

      i++;
      I->replaceAllUsesWith(ci);

      insertCallToPAPI(I, ci);
    }
  }
}
void
PoolRegisterElimination::removeSingletonRegistrations (const char * name) {
  //
  // Scan through all uses of the registration function and see if it can be
  // safely removed.  If so, schedule it for removal.
  //
  std::vector<CallInst*> toBeRemoved;
  Function * F = intrinsic->getIntrinsic(name).F;

  //
  // Look for and record all registrations that can be deleted.
  //
  for (Value::use_iterator UI=F->use_begin(), UE=F->use_end();
       UI != UE;
       ++UI) {
    //
    // Get the pointer to the registered object.
    //
    CallInst * CI = cast<CallInst>(*UI);
    Value * Ptr = intrinsic->getValuePointer(CI);

    //
    // Lookup the DSNode for the value in the function's DSGraph.
    //
    DSGraph * TDG = dsaPass->getDSGraph(*(CI->getParent()->getParent()));
    DSNodeHandle DSH = TDG->getNodeForValue(Ptr);
    assert ((!(DSH.isNull())) && "No DSNode for Value!\n");

    //
    // If the object being registered is the same size as that found in the
    // DSNode, then we know it's a singleton object.  The run-time doesn't need
    // such objects registered in the splay trees, so we can remove the
    // registration function.
    //
    DSNode * N = DSH.getNode();
    Value * Size = intrinsic->getObjectSize (Ptr->stripPointerCasts());
    if (Size) {
      if (ConstantInt * C = dyn_cast<ConstantInt>(Size)) {
        unsigned long size = C->getZExtValue();
        if (size == N->getSize()) {
          toBeRemoved.push_back(CI);
          continue;
        }
      }
    }
  }

  //
  // Update the statistics.
  //
  if (toBeRemoved.size()) {
    RemovedRegistration += toBeRemoved.size();
    SingletonRegistrations += toBeRemoved.size();
  }

  //
  // Remove the unnecesary registrations.
  //
  std::vector<CallInst*>::iterator it, end;
  for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) {
    (*it)->eraseFromParent();
  }
}
Ejemplo n.º 18
0
bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
  SmallVector<ReturnInst*,16> Returns;
  SmallVector<UnwindInst*,16> Unwinds;
  SmallVector<InvokeInst*,16> Invokes;

  // Look through the terminators of the basic blocks to find invokes, returns
  // and unwinds.
  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
    if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
      // Remember all return instructions in case we insert an invoke into this
      // function.
      Returns.push_back(RI);
    } else if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
      Invokes.push_back(II);
    } else if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
      Unwinds.push_back(UI);
    }
  }

  NumInvokes += Invokes.size();
  NumUnwinds += Unwinds.size();

  // If we don't have any invokes, there's nothing to do.
  if (Invokes.empty()) return false;

  // Find the eh.selector.*, eh.exception and alloca calls.
  //
  // Remember any allocas() that aren't in the entry block, as the
  // jmpbuf saved SP will need to be updated for them.
  //
  // We'll use the first eh.selector to determine the right personality
  // function to use. For SJLJ, we always use the same personality for the
  // whole function, not on a per-selector basis.
  // FIXME: That's a bit ugly. Better way?
  SmallVector<CallInst*,16> EH_Selectors;
  SmallVector<CallInst*,16> EH_Exceptions;
  SmallVector<Instruction*,16> JmpbufUpdatePoints;

  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
    // Note: Skip the entry block since there's nothing there that interests
    // us. eh.selector and eh.exception shouldn't ever be there, and we
    // want to disregard any allocas that are there.
    // 
    // FIXME: This is awkward. The new EH scheme won't need to skip the entry
    //        block.
    if (BB == F.begin()) {
      if (InvokeInst *II = dyn_cast<InvokeInst>(F.begin()->getTerminator())) {
        // FIXME: This will be always non-NULL in the new EH.
        if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst())
          if (!PersonalityFn) PersonalityFn = LPI->getPersonalityFn();
      }

      continue;
    }

    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
      if (CallInst *CI = dyn_cast<CallInst>(I)) {
        if (CI->getCalledFunction() == SelectorFn) {
          if (!PersonalityFn) PersonalityFn = CI->getArgOperand(1);
          EH_Selectors.push_back(CI);
        } else if (CI->getCalledFunction() == ExceptionFn) {
          EH_Exceptions.push_back(CI);
        } else if (CI->getCalledFunction() == StackRestoreFn) {
          JmpbufUpdatePoints.push_back(CI);
        }
      } else if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
        JmpbufUpdatePoints.push_back(AI);
      } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
        // FIXME: This will be always non-NULL in the new EH.
        if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst())
          if (!PersonalityFn) PersonalityFn = LPI->getPersonalityFn();
      }
    }
  }

  // If we don't have any eh.selector calls, we can't determine the personality
  // function. Without a personality function, we can't process exceptions.
  if (!PersonalityFn) return false;

  // We have invokes, so we need to add register/unregister calls to get this
  // function onto the global unwind stack.
  //
  // First thing we need to do is scan the whole function for values that are
  // live across unwind edges.  Each value that is live across an unwind edge we
  // spill into a stack location, guaranteeing that there is nothing live across
  // the unwind edge.  This process also splits all critical edges coming out of
  // invoke's.
  splitLiveRangesAcrossInvokes(Invokes);


  SmallVector<LandingPadInst*, 16> LandingPads;
  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
    if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
      // FIXME: This will be always non-NULL in the new EH.
      if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst())
        LandingPads.push_back(LPI);
  }


  BasicBlock *EntryBB = F.begin();
  // Create an alloca for the incoming jump buffer ptr and the new jump buffer
  // that needs to be restored on all exits from the function.  This is an
  // alloca because the value needs to be added to the global context list.
  unsigned Align = 4; // FIXME: Should be a TLI check?
  AllocaInst *FunctionContext =
    new AllocaInst(FunctionContextTy, 0, Align,
                   "fcn_context", F.begin()->begin());

  Value *Idxs[2];
  Type *Int32Ty = Type::getInt32Ty(F.getContext());
  Value *Zero = ConstantInt::get(Int32Ty, 0);
  // We need to also keep around a reference to the call_site field
  Idxs[0] = Zero;
  Idxs[1] = ConstantInt::get(Int32Ty, 1);
  CallSite = GetElementPtrInst::Create(FunctionContext, Idxs, "call_site",
                                       EntryBB->getTerminator());

  // The exception selector comes back in context->data[1]
  Idxs[1] = ConstantInt::get(Int32Ty, 2);
  Value *FCData = GetElementPtrInst::Create(FunctionContext, Idxs, "fc_data",
                                            EntryBB->getTerminator());
  Idxs[1] = ConstantInt::get(Int32Ty, 1);
  Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs,
                                                  "exc_selector_gep",
                                                  EntryBB->getTerminator());
  // The exception value comes back in context->data[0]
  Idxs[1] = Zero;
  Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs,
                                                   "exception_gep",
                                                   EntryBB->getTerminator());

  // The result of the eh.selector call will be replaced with a a reference to
  // the selector value returned in the function context. We leave the selector
  // itself so the EH analysis later can use it.
  for (int i = 0, e = EH_Selectors.size(); i < e; ++i) {
    CallInst *I = EH_Selectors[i];
    Value *SelectorVal = new LoadInst(SelectorAddr, "select_val", true, I);
    I->replaceAllUsesWith(SelectorVal);
  }

  // eh.exception calls are replaced with references to the proper location in
  // the context. Unlike eh.selector, the eh.exception calls are removed
  // entirely.
  for (int i = 0, e = EH_Exceptions.size(); i < e; ++i) {
    CallInst *I = EH_Exceptions[i];
    // Possible for there to be duplicates, so check to make sure the
    // instruction hasn't already been removed.
    if (!I->getParent()) continue;
    Value *Val = new LoadInst(ExceptionAddr, "exception", true, I);
    Type *Ty = Type::getInt8PtrTy(F.getContext());
    Val = CastInst::Create(Instruction::IntToPtr, Val, Ty, "", I);

    I->replaceAllUsesWith(Val);
    I->eraseFromParent();
  }

  for (unsigned i = 0, e = LandingPads.size(); i != e; ++i)
    ReplaceLandingPadVal(F, LandingPads[i], ExceptionAddr, SelectorAddr);

  // The entry block changes to have the eh.sjlj.setjmp, with a conditional
  // branch to a dispatch block for non-zero returns. If we return normally,
  // we're not handling an exception and just register the function context and
  // continue.

  // Create the dispatch block.  The dispatch block is basically a big switch
  // statement that goes to all of the invoke landing pads.
  BasicBlock *DispatchBlock =
    BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F);

  // Insert a load of the callsite in the dispatch block, and a switch on its
  // value. By default, we issue a trap statement.
  BasicBlock *TrapBlock =
    BasicBlock::Create(F.getContext(), "trapbb", &F);
  CallInst::Create(Intrinsic::getDeclaration(F.getParent(), Intrinsic::trap),
                   "", TrapBlock);
  new UnreachableInst(F.getContext(), TrapBlock);

  Value *DispatchLoad = new LoadInst(CallSite, "invoke.num", true,
                                     DispatchBlock);
  SwitchInst *DispatchSwitch =
    SwitchInst::Create(DispatchLoad, TrapBlock, Invokes.size(),
                       DispatchBlock);
  // Split the entry block to insert the conditional branch for the setjmp.
  BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(),
                                                   "eh.sjlj.setjmp.cont");

  // Populate the Function Context
  //   1. LSDA address
  //   2. Personality function address
  //   3. jmpbuf (save SP, FP and call eh.sjlj.setjmp)

  // LSDA address
  Idxs[0] = Zero;
  Idxs[1] = ConstantInt::get(Int32Ty, 4);
  Value *LSDAFieldPtr =
    GetElementPtrInst::Create(FunctionContext, Idxs, "lsda_gep",
                              EntryBB->getTerminator());
  Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr",
                                 EntryBB->getTerminator());
  new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator());

  Idxs[1] = ConstantInt::get(Int32Ty, 3);
  Value *PersonalityFieldPtr =
    GetElementPtrInst::Create(FunctionContext, Idxs, "lsda_gep",
                              EntryBB->getTerminator());
  new StoreInst(PersonalityFn, PersonalityFieldPtr, true,
                EntryBB->getTerminator());

  // Save the frame pointer.
  Idxs[1] = ConstantInt::get(Int32Ty, 5);
  Value *JBufPtr
    = GetElementPtrInst::Create(FunctionContext, Idxs, "jbuf_gep",
                                EntryBB->getTerminator());
  Idxs[1] = ConstantInt::get(Int32Ty, 0);
  Value *FramePtr =
    GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_fp_gep",
                              EntryBB->getTerminator());

  Value *Val = CallInst::Create(FrameAddrFn,
                                ConstantInt::get(Int32Ty, 0),
                                "fp",
                                EntryBB->getTerminator());
  new StoreInst(Val, FramePtr, true, EntryBB->getTerminator());

  // Save the stack pointer.
  Idxs[1] = ConstantInt::get(Int32Ty, 2);
  Value *StackPtr =
    GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_sp_gep",
                              EntryBB->getTerminator());

  Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator());
  new StoreInst(Val, StackPtr, true, EntryBB->getTerminator());

  // Call the setjmp instrinsic. It fills in the rest of the jmpbuf.
  Value *SetjmpArg =
    CastInst::Create(Instruction::BitCast, JBufPtr,
                     Type::getInt8PtrTy(F.getContext()), "",
                     EntryBB->getTerminator());
  Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg,
                                        "dispatch",
                                        EntryBB->getTerminator());

  // Add a call to dispatch_setup after the setjmp call. This is expanded to any
  // target-specific setup that needs to be done.
  CallInst::Create(DispatchSetupFn, DispatchVal, "", EntryBB->getTerminator());

  // check the return value of the setjmp. non-zero goes to dispatcher.
  Value *IsNormal = new ICmpInst(EntryBB->getTerminator(),
                                 ICmpInst::ICMP_EQ, DispatchVal, Zero,
                                 "notunwind");
  // Nuke the uncond branch.
  EntryBB->getTerminator()->eraseFromParent();

  // Put in a new condbranch in its place.
  BranchInst::Create(ContBlock, DispatchBlock, IsNormal, EntryBB);

  // Register the function context and make sure it's known to not throw
  CallInst *Register =
    CallInst::Create(RegisterFn, FunctionContext, "",
                     ContBlock->getTerminator());
  Register->setDoesNotThrow();

  // At this point, we are all set up, update the invoke instructions to mark
  // their call_site values, and fill in the dispatch switch accordingly.
  for (unsigned i = 0, e = Invokes.size(); i != e; ++i)
    markInvokeCallSite(Invokes[i], i+1, CallSite, DispatchSwitch);

  // Mark call instructions that aren't nounwind as no-action (call_site ==
  // -1). Skip the entry block, as prior to then, no function context has been
  // created for this function and any unexpected exceptions thrown will go
  // directly to the caller's context, which is what we want anyway, so no need
  // to do anything here.
  for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) {
    for (BasicBlock::iterator I = BB->begin(), end = BB->end(); I != end; ++I)
      if (CallInst *CI = dyn_cast<CallInst>(I)) {
        // Ignore calls to the EH builtins (eh.selector, eh.exception)
        Constant *Callee = CI->getCalledFunction();
        if (Callee != SelectorFn && Callee != ExceptionFn
            && !CI->doesNotThrow())
          insertCallSiteStore(CI, -1, CallSite);
      } else if (ResumeInst *RI = dyn_cast<ResumeInst>(I)) {
        insertCallSiteStore(RI, -1, CallSite);
      }
  }

  // Replace all unwinds with a branch to the unwind handler.
  // ??? Should this ever happen with sjlj exceptions?
  for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) {
    BranchInst::Create(TrapBlock, Unwinds[i]);
    Unwinds[i]->eraseFromParent();
  }

  // Following any allocas not in the entry block, update the saved SP in the
  // jmpbuf to the new value.
  for (unsigned i = 0, e = JmpbufUpdatePoints.size(); i != e; ++i) {
    Instruction *AI = JmpbufUpdatePoints[i];
    Instruction *StackAddr = CallInst::Create(StackAddrFn, "sp");
    StackAddr->insertAfter(AI);
    Instruction *StoreStackAddr = new StoreInst(StackAddr, StackPtr, true);
    StoreStackAddr->insertAfter(StackAddr);
  }

  // Finally, for any returns from this function, if this function contains an
  // invoke, add a call to unregister the function context.
  for (unsigned i = 0, e = Returns.size(); i != e; ++i)
    CallInst::Create(UnregisterFn, FunctionContext, "", Returns[i]);

  return true;
}
Ejemplo n.º 19
0
//
// Function: makeCStdLibCallsComplete()
//
// Description:
//  Fills in completeness information for all calls of a given CStdLib function
//  assumed to be of the form:
//
//   pool_X(POOL *p1, ..., POOL *pN, void *a1, ..., void *aN, ..., uint8_t c);
//
//  Specifically, this function assumes that there are as many pointer arguments
//  to check as there are initial pool arguments, and the pointer arguments
//  follow the pool arguments in corresponding order. Also, it is assumed that
//  the final argument to the function is a byte sized bit vector.
//
//  This function fills in this final byte with a constant value whose ith
//  bit is set exactly when the ith pointer argument is complete.
//
// Inputs:
//
//  F            - A pointer to the CStdLib function appearing in the module
//                 (non-null).
//  PoolArgs     - The number of initial pool arguments for which a
//                 corresponding pointer value requires a completeness check
//                 (required to be at most 8).
//
void
CompleteChecks::makeCStdLibCallsComplete(Function *F, unsigned PoolArgs) {
  assert(F != 0 && "Null function argument!");

  assert(PoolArgs <= 8 && \
    "Only up to 8 arguments are supported by CStdLib completeness checks!");

  Value::use_iterator U = F->use_begin();
  Value::use_iterator E = F->use_end();

  //
  // Hold the call instructions that need changing.
  //
  typedef std::pair<CallInst *, uint8_t> VectorReplacement;
  std::set<VectorReplacement> callsToChange;

  Type *int8ty = Type::getInt8Ty(F->getContext());
  FunctionType *F_type = F->getFunctionType();

  //
  // Verify the type of the function is as expected.
  //
  // There should be as many pointer parameters to check for completeness
  // as there are pool parameters. The last parameter should be a byte.
  //
  assert(F_type->getNumParams() >= PoolArgs * 2 && \
    "Not enough arguments to transformed CStdLib function call!");
  for (unsigned arg = PoolArgs; arg < PoolArgs * 2; ++arg)
    assert(isa<PointerType>(F_type->getParamType(arg)) && \
      "Expected pointer argument to function!");

  //
  // This is the position of the vector operand in the call.
  //
  unsigned vect_position = F_type->getNumParams();

  assert(F_type->getParamType(vect_position - 1) == int8ty && \
    "Last parameter to the function should be a byte!");

  //
  // Iterate over all calls of the function in the module, computing the
  // vectors for each call as it is found.
  //
  for (; U != E; ++U) {
    CallInst *CI;
    if ((CI = dyn_cast<CallInst>(*U)) && \
      CI->getCalledValue()->stripPointerCasts() == F) {

      uint8_t vector = 0x0;

      //
      // Get the parent function to which this instruction belongs.
      //
      Function *P = CI->getParent()->getParent();

      //
      // Iterate over the pointer arguments that need completeness checking
      // and build the completeness vector.
      //
      for (unsigned arg = 0; arg < PoolArgs; ++arg) {
        bool complete = true;
        //
        // Go past all the pool arguments to get the pointer to check.
        //
        Value *V = CI->getOperand(1 + PoolArgs + arg);

        //
        // Check for completeness of the pointer using DSA and 
        // set the bit in the vector accordingly.
        //
        DSNode *N;
        if ((N = getDSNodeHandle(V, P).getNode()) &&
              (N->isExternalNode() || N->isIncompleteNode() ||
               N->isUnknownNode()  || N->isIntToPtrNode()   ||
               N->isPtrToIntNode()) ) {
            complete = false;
        }

        if (complete)
          vector |= (1 << arg);
      }

      //
      // Add the instruction and vector to the set of instructions to change.
      //
      callsToChange.insert(VectorReplacement(CI, vector));
    }
  }


  //
  // Iterate over all call instructions that need changing, modifying the
  // final operand of the call to hold the bit vector value.
  //
  std::set<VectorReplacement>::iterator change = callsToChange.begin();
  std::set<VectorReplacement>::iterator change_end = callsToChange.end();

  while (change != change_end) {
    Constant *vect_value = ConstantInt::get(int8ty, change->second);
    change->first->setOperand(vect_position, vect_value);
    ++change;
  }

  return;

}
bool RangedAddressSanitizer::runOnFunction(Function &F) {
    if (getenv("FASAN_DISABLE")) {
      SPM_DEBUG( dbgs() << "FASan : disabled\n" );
      return false;
    }

    DL_  = &getAnalysis<DataLayout>();
    DT_  = &getAnalysis<DominatorTree>();
    LI_  = &getAnalysis<LoopInfo>();
    RI_  = &getAnalysis<ReduceIndexation>();
#ifdef ENABLE_REUSE
    RE_  = &getAnalysis<RelativeExecutions>();
#endif
    RMM_ = &getAnalysis<RelativeMinMax>();

    Module_  = F.getParent();
    Context_ = &Module_->getContext();

    Type        *VoidTy    = Type::getVoidTy(*Context_);
    IntegerType *IntTy     = IntegerType::getInt64Ty(*Context_);
    IntegerType *BoolTy     = IntegerType::getInt1Ty(*Context_);
    PointerType *IntPtrTy  = PointerType::getUnqual(IntTy);
    PointerType *VoidPtrTy = PointerType::getInt8PtrTy(*Context_);

    SPM_DEBUG( F.dump() );
    outs() << "[IterationInfo]\n";
    for (Loop * loop : *LI_) {
            ii_visitLoop(loop);
    }
    outs() << "[EndOfIterationInfo]\n";
    
#if 0 // disabled initialization,shutdown sequence for FASan
  if (F.getName() == "main") {
    SPM_DEBUG(dbgs() << "RangedAddressSanitizer: inserting hwloc calls into "
                        "main function\n");

    FunctionType *FnType = FunctionType::get(VoidTy, ArrayRef<Type*>(), false);
    IRBuilder<> IRB(&(*F.getEntryBlock().begin()));

    Constant *Init = Module_->getOrInsertFunction("__spm_init", FnType);
    IRB.CreateCall(Init);

    Constant *End = Module_->getOrInsertFunction("__spm_end", FnType);
    for (auto &BB : F) {
      TerminatorInst *TI = BB.getTerminator();
      if (isa<ReturnInst>(TI)) {
        IRB.SetInsertPoint(TI);
        IRB.CreateCall(End);
      }
    }
  }
#endif

  if (!ClFunc.empty() && F.getName() != ClFunc) {
    SPM_DEBUG(dbgs() << "RangedAddressSanitizer: skipping function "
                     << F.getName() << "\n");
    return false;
  }

  Calls_.clear();

  SPM_DEBUG(dbgs() << "RangedAddressSanitizer: processing function "
                   << F.getName() << "\n");

  std::vector<Type*> ReuseFnFormals = { VoidPtrTy, IntTy, IntTy, IntTy };
  FunctionType *ReuseFnType = FunctionType::get(BoolTy, ReuseFnFormals, false);
  ReuseFn_ =
    F.getParent()->getOrInsertFunction("__fasan_check", ReuseFnType);
  ReuseFnDestroy_ =
    F.getParent()->getOrInsertFunction("__spm_give", ReuseFnType);

// Visit all loops in bottom-up order (innter-most loops first)
  std::set<BasicBlock*> Processed;
  auto Entry = DT_->getRootNode();
  for (auto ET = po_begin(Entry), EE = po_end(Entry); ET != EE; ++ET) {
    BasicBlock *Header = (*ET)->getBlock();

    if (LI_->isLoopHeader(Header)) {
      SPM_DEBUG(dbgs() << "RangedAddressSanitizer: processing loop at "
                       << Header->getName() << "\n");
      Loop *L = LI_->getLoopFor(Header);

      if (L->getNumBackEdges() != 1 ||
          std::distance(pred_begin(Header), pred_end(Header)) != 2) {
        SPM_DEBUG(dbgs() << "RangedAddressSanitizer: loop has multiple "
                         << "backedges or multiple incoming outer blocks\n");
        continue;
      }

      SPM_DEBUG(dbgs() << "RangedAddressSanitizer: processing loop at "
                       << Header->getName() << "\n");

    // visit all memory acccesses in this loop
      for (auto BB = L->block_begin(), BE = L->block_end(); BB != BE; ++BB) {
        if (!Processed.count(*BB)) {
          Processed.insert(*BB);
          for (auto &I : *(*BB))
            generateCallFor(L, &I);
        }
      }
    }
  }

  // FAsan logic goes here

  std::map<const BasicBlock*,BasicBlock*> clonedBlockMap; // keeps track of cloned regions to avoid redundant cloning

  std::vector<CallInst*> ToInline;

  for (auto &CI : Calls_) {
    BasicBlock * Preheader = CI.Preheader;
    
  // TODO decide whether it is worthwhile to optimize for this case

  // insert range check
    IRBuilder<> IRB(Preheader->getTerminator());
    Value *VoidArray = IRB.CreateBitCast(CI.Array, VoidPtrTy);
    std::vector<Value*> Args = { VoidArray, CI.Min, CI.Max, CI.Reuse };
    CallInst *CR = IRB.CreateCall(ReuseFn_, Args);
    ToInline.push_back(CR);
    
 // verify if this loop was already instrumented
    TerminatorInst * preHeaderTerm = CR->getParent()->getTerminator();
    BranchInst * preHeaderBranch = dyn_cast<BranchInst>(preHeaderTerm);

    if (preHeaderBranch && preHeaderBranch->isConditional()) {

    // discover the structure of the instrumented code (safe and default region)
    // abort, if this does not look like instrumented code
    	BasicBlock * firstTarget = preHeaderBranch->getSuccessor(0);
    	BasicBlock * secondTarget = preHeaderBranch->getSuccessor(1);
    	BasicBlock * safeHeader, * defHeader;
    	if (clonedBlockMap.count(firstTarget)) {
    		defHeader = firstTarget;
    		safeHeader = clonedBlockMap[firstTarget];
    		assert(safeHeader == secondTarget);
    	} else {
    		assert(clonedBlockMap.count(secondTarget));
    		defHeader = secondTarget;
			safeHeader = clonedBlockMap[secondTarget];
			assert(safeHeader == firstTarget);
    	}

    	SPM_DEBUG( dbgs() << "FASan: (Unsupported) second array in safe region controlled by " << * preHeaderBranch << "\n" );
    	Loop * defLoop = LI_->getLoopFor(defHeader);
    	assert(defLoop && "default region is not a loop!");

		Loop::block_iterator itBodyBlock,S,E;
		S = defLoop->block_begin();
		E = defLoop->block_end();

	// mark accesses in cloned region as safe
    	for (itBodyBlock = S;itBodyBlock != E; ++itBodyBlock) {
    		BasicBlock * defBodyBlock = *itBodyBlock;
    		BasicBlock * safeBodyBlock = clonedBlockMap[defBodyBlock];

    		for(auto & inst : *safeBodyBlock) {
				markSafeArrayUse(&inst, CI.Array);
			}
    	}

    // add conjunctive test
    	Value * oldCond = preHeaderBranch->getCondition();
    	Value * joinedCond = IRB.CreateAnd(oldCond, CR, "allsafe");
    	preHeaderBranch->setCondition(joinedCond);

    } else {

	  // get loop
		Loop* finalLoop = CI.FinalLoop;
		Loop::block_iterator itBodyBlock,S,E;
		S = finalLoop->block_begin();
		E = finalLoop->block_end();

	  // clone loop body (cloned loop will run unchecked)
		ValueToValueMapTy cloneMap;

		BasicBlock * clonedHeader = 0;
		std::vector<BasicBlock*> clonedBlocks;

		for (itBodyBlock = S;itBodyBlock != E; ++itBodyBlock) {

			const BasicBlock * bodyBlock = *itBodyBlock;
			BasicBlock * clonedBlock = CloneBasicBlock(bodyBlock, cloneMap, "_checked", &F, 0);

			cloneMap[bodyBlock] = clonedBlock;
			clonedBlockMap[bodyBlock] = clonedBlock;
			clonedBlocks.push_back(clonedBlock);

			if (bodyBlock == finalLoop->getHeader()) {
				clonedHeader = clonedBlock;
				SPM_DEBUG( dbgs() << "FASan: loop header case at " << bodyBlock->getName() << "\n" );
			} else {
				SPM_DEBUG( dbgs() << "FASan: non-header block at " << bodyBlock->getName() << "\n" );
			}
		}

		if (!clonedHeader) {
			// TODO run clean-up code
			SPM_DEBUG( dbgs() << "FASan: could not find header!\n");
			abort();
		}

	  // Remap uses inside cloned region (mark pointers in the region as unguarded)
		for (BasicBlock * block : clonedBlocks) {
			for(auto & inst : *block) {
				RemapInstruction(&inst, cloneMap, RF_IgnoreMissingEntries);
				markSafeArrayUse(&inst, CI.Array);
			}
		}

	   // TODO fix PHI-nodes in exit blocks

	   // Rewire terminator of the range check to branch to the cloned region
		TerminatorInst * checkTermInst = CR->getParent()->getTerminator();

		if (BranchInst * checkBranchInst = dyn_cast<BranchInst>(checkTermInst)) {
			if (checkBranchInst->isUnconditional()) {
				BasicBlock * defTarget = checkBranchInst->getSuccessor(0);
				BranchInst * modifiedBranchInst = BranchInst::Create(clonedHeader, defTarget, CR, checkBranchInst);
				checkBranchInst->replaceAllUsesWith(modifiedBranchInst);
				checkBranchInst->eraseFromParent();
			} else {
				SPM_DEBUG( dbgs() << "FASan: Unexpected conditional branch (preheader should branch unconditional, other array checks will introduce conditional branches) " << * checkTermInst << "\n" );
				abort();
			}
		} else {
			SPM_DEBUG( dbgs() << "FASan: unsupported terminator type " << * checkTermInst << "\n" );
			abort();
		}
    }
    
#if 0
    IRB.SetInsertPoint(&(*CI.Final->begin()));
    IRB.CreateCall(ReuseFnDestroy_, Args);
#endif
    SPM_DEBUG(dbgs() << "RangedAddressSanitizer: call instruction: " << *CR
                     << "\n");
  }


  // inline calls
#ifdef FASAN_INLINE_RUNTIME
  for (CallInst * call : ToInline) {
	assert(call);
	InlineFunctionInfo IFI;
	InlineFunction(call, IFI, false);
  }
#endif

  SPM_DEBUG( F.dump() );
  return true;
}
//
// Function: insertPoolFrees()
//
// Description:
//  This function takes a list of alloca instructions and inserts code to
//  unregister them at every unwind and return instruction.
//
// Inputs:
//  PoolRegisters - The list of calls to poolregister() inserted for stack
//                  objects.
//  ExitPoints    - The list of instructions that can cause the function to
//                  return.
//  Context       - The LLVM Context in which to insert instructions.
//
void
RegisterStackObjPass::insertPoolFrees
  (const std::vector<CallInst *> & PoolRegisters,
   const std::vector<Instruction *> & ExitPoints,
   LLVMContext * Context) {
  // List of alloca instructions we create to store the pointers to be
  // deregistered.
  std::vector<AllocaInst *> PtrList;

  // List of pool handles; this is a parallel array to PtrList
  std::vector<Value *> PHList;

  // The infamous void pointer type
  PointerType * VoidPtrTy = getVoidPtrType(*Context);

  //
  // Create alloca instructions for every registered alloca.  These will hold
  // a pointer to the registered stack objects and will be referenced by
  // poolunregister().
  //
  for (unsigned index = 0; index < PoolRegisters.size(); ++index) {
    //
    // Take the first element off of the worklist.
    //
    CallInst * CI = PoolRegisters[index];
    CallSite CS(CI);

    //
    // Get the pool handle and allocated pointer from the poolregister() call.
    //
    Value * PH  = CS.getArgument(0);
    Value * Ptr = CS.getArgument(1);

    //
    // Create a place to store the pointer returned from alloca.  Initialize it
    // with a null pointer.
    //
    BasicBlock & EntryBB = CI->getParent()->getParent()->getEntryBlock();
    Instruction * InsertPt = &(EntryBB.front());
    AllocaInst * PtrLoc = new AllocaInst (VoidPtrTy,
                                          Ptr->getName() + ".st",
                                          InsertPt);
    Value * NullPointer = ConstantPointerNull::get(VoidPtrTy);
    new StoreInst (NullPointer, PtrLoc, InsertPt);

    //
    // Store the registered pointer into the memory we allocated in the entry
    // block.
    //
    new StoreInst (Ptr, PtrLoc, CI);

    //
    // Record the alloca that stores the pointer to deregister.
    // Record the pool handle with it.
    //
    PtrList.push_back (PtrLoc);
    PHList.push_back (PH);
  }

  //
  // For each point where the function can exit, insert code to deregister all
  // stack objects.
  //
  for (unsigned index = 0; index < ExitPoints.size(); ++index) {
    //
    // Take the first element off of the worklist.
    //
    Instruction * Return = ExitPoints[index];

    //
    // Deregister each registered stack object.
    //
    for (unsigned i = 0; i < PtrList.size(); ++i) {
      //
      // Get the location holding the pointer and the pool handle associated
      // with it.
      //
      AllocaInst * PtrLoc = PtrList[i];
      Value * PH = PHList[i];

      //
      // Generate a load instruction to get the registered pointer.
      //
      LoadInst * Ptr = new LoadInst (PtrLoc, "", Return);

      //
      // Create the call to poolunregister().
      //
      std::vector<Value *> args;
      args.push_back (PH);
      args.push_back (Ptr);
      CallInst::Create (StackFree, args, "", Return);
    }
  }

  //
  // Lastly, promote the allocas we created into LLVM virtual registers.
  //
  PromoteMemToReg(PtrList, *DT);
}
Ejemplo n.º 22
0
static void
InsertSafepointPoll(DominatorTree &DT, Instruction *term,
                    std::vector<CallSite> &ParsePointsNeeded /*rval*/) {
  Module *M = term->getParent()->getParent()->getParent();
  assert(M);

  // Inline the safepoint poll implementation - this will get all the branch,
  // control flow, etc..  Most importantly, it will introduce the actual slow
  // path call - where we need to insert a safepoint (parsepoint).
  FunctionType *ftype =
      FunctionType::get(Type::getVoidTy(M->getContext()), false);
  assert(ftype && "null?");
  // Note: This cast can fail if there's a function of the same name with a
  // different type inserted previously
  Function *F =
      dyn_cast<Function>(M->getOrInsertFunction("gc.safepoint_poll", ftype));
  assert(F && !F->empty() && "definition must exist");
  CallInst *poll = CallInst::Create(F, "", term);

  // Record some information about the call site we're replacing
  BasicBlock *OrigBB = term->getParent();
  BasicBlock::iterator before(poll), after(poll);
  bool isBegin(false);
  if (before == term->getParent()->begin()) {
    isBegin = true;
  } else {
    before--;
  }
  after++;
  assert(after != poll->getParent()->end() && "must have successor");
  assert(DT.dominates(before, after) && "trivially true");

  // do the actual inlining
  InlineFunctionInfo IFI;
  bool inlineStatus = InlineFunction(poll, IFI);
  assert(inlineStatus && "inline must succeed");
  (void)inlineStatus; // suppress warning in release-asserts

  // Check post conditions
  assert(IFI.StaticAllocas.empty() && "can't have allocs");

  std::vector<CallInst *> calls; // new calls
  std::set<BasicBlock *> BBs;    // new BBs + insertee
  // Include only the newly inserted instructions, Note: begin may not be valid
  // if we inserted to the beginning of the basic block
  BasicBlock::iterator start;
  if (isBegin) {
    start = OrigBB->begin();
  } else {
    start = before;
    start++;
  }

  // If your poll function includes an unreachable at the end, that's not
  // valid.  Bugpoint likes to create this, so check for it.
  assert(isPotentiallyReachable(&*start, &*after, nullptr, nullptr) &&
         "malformed poll function");

  scanInlinedCode(&*(start), &*(after), calls, BBs);

  // Recompute since we've invalidated cached data.  Conceptually we
  // shouldn't need to do this, but implementation wise we appear to.  Needed
  // so we can insert safepoints correctly.
  // TODO: update more cheaply
  DT.recalculate(*after->getParent()->getParent());

  assert(!calls.empty() && "slow path not found for safepoint poll");

  // Record the fact we need a parsable state at the runtime call contained in
  // the poll function.  This is required so that the runtime knows how to
  // parse the last frame when we actually take  the safepoint (i.e. execute
  // the slow path)
  assert(ParsePointsNeeded.empty());
  for (size_t i = 0; i < calls.size(); i++) {

    // No safepoint needed or wanted
    if (!needsStatepoint(calls[i])) {
      continue;
    }

    // These are likely runtime calls.  Should we assert that via calling
    // convention or something?
    ParsePointsNeeded.push_back(CallSite(calls[i]));
  }
  assert(ParsePointsNeeded.size() <= calls.size());
}
Ejemplo n.º 23
0
/// DupRetToEnableTailCallOpts - Look for opportunities to duplicate return
/// instructions to the predecessor to enable tail call optimizations. The
/// case it is currently looking for is:
/// bb0:
///   %tmp0 = tail call i32 @f0()
///   br label %return
/// bb1:
///   %tmp1 = tail call i32 @f1()
///   br label %return
/// bb2:
///   %tmp2 = tail call i32 @f2()
///   br label %return
/// return:
///   %retval = phi i32 [ %tmp0, %bb0 ], [ %tmp1, %bb1 ], [ %tmp2, %bb2 ]
///   ret i32 %retval
///
/// =>
///
/// bb0:
///   %tmp0 = tail call i32 @f0()
///   ret i32 %tmp0
/// bb1:
///   %tmp1 = tail call i32 @f1()
///   ret i32 %tmp1
/// bb2:
///   %tmp2 = tail call i32 @f2()
///   ret i32 %tmp2
///
bool CodeGenPrepare::DupRetToEnableTailCallOpts(ReturnInst *RI) {
    if (!TLI)
        return false;

    Value *V = RI->getReturnValue();
    PHINode *PN = V ? dyn_cast<PHINode>(V) : NULL;
    if (V && !PN)
        return false;

    BasicBlock *BB = RI->getParent();
    if (PN && PN->getParent() != BB)
        return false;

    // It's not safe to eliminate the sign / zero extension of the return value.
    // See llvm::isInTailCallPosition().
    const Function *F = BB->getParent();
    Attributes CallerRetAttr = F->getAttributes().getRetAttributes();
    if ((CallerRetAttr & Attribute::ZExt) || (CallerRetAttr & Attribute::SExt))
        return false;

    // Make sure there are no instructions between the PHI and return, or that the
    // return is the first instruction in the block.
    if (PN) {
        BasicBlock::iterator BI = BB->begin();
        do {
            ++BI;
        }
        while (isa<DbgInfoIntrinsic>(BI));
        if (&*BI != RI)
            return false;
    } else {
        BasicBlock::iterator BI = BB->begin();
        while (isa<DbgInfoIntrinsic>(BI)) ++BI;
        if (&*BI != RI)
            return false;
    }

    /// Only dup the ReturnInst if the CallInst is likely to be emitted as a tail
    /// call.
    SmallVector<CallInst*, 4> TailCalls;
    if (PN) {
        for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) {
            CallInst *CI = dyn_cast<CallInst>(PN->getIncomingValue(I));
            // Make sure the phi value is indeed produced by the tail call.
            if (CI && CI->hasOneUse() && CI->getParent() == PN->getIncomingBlock(I) &&
                    TLI->mayBeEmittedAsTailCall(CI))
                TailCalls.push_back(CI);
        }
    } else {
        SmallPtrSet<BasicBlock*, 4> VisitedBBs;
        for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) {
            if (!VisitedBBs.insert(*PI))
                continue;

            BasicBlock::InstListType &InstList = (*PI)->getInstList();
            BasicBlock::InstListType::reverse_iterator RI = InstList.rbegin();
            BasicBlock::InstListType::reverse_iterator RE = InstList.rend();
            do {
                ++RI;
            }
            while (RI != RE && isa<DbgInfoIntrinsic>(&*RI));
            if (RI == RE)
                continue;

            CallInst *CI = dyn_cast<CallInst>(&*RI);
            if (CI && CI->use_empty() && TLI->mayBeEmittedAsTailCall(CI))
                TailCalls.push_back(CI);
        }
    }

    bool Changed = false;
    for (unsigned i = 0, e = TailCalls.size(); i != e; ++i) {
        CallInst *CI = TailCalls[i];
        CallSite CS(CI);

        // Conservatively require the attributes of the call to match those of the
        // return. Ignore noalias because it doesn't affect the call sequence.
        Attributes CalleeRetAttr = CS.getAttributes().getRetAttributes();
        if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias)
            continue;

        // Make sure the call instruction is followed by an unconditional branch to
        // the return block.
        BasicBlock *CallBB = CI->getParent();
        BranchInst *BI = dyn_cast<BranchInst>(CallBB->getTerminator());
        if (!BI || !BI->isUnconditional() || BI->getSuccessor(0) != BB)
            continue;

        // Duplicate the return into CallBB.
        (void)FoldReturnIntoUncondBranch(RI, BB, CallBB);
        ModifiedDT = Changed = true;
        ++NumRetsDup;
    }

    // If we eliminated all predecessors of the block, delete the block now.
    if (Changed && pred_begin(BB) == pred_end(BB))
        BB->eraseFromParent();

    return Changed;
}
Ejemplo n.º 24
0
bool TypeChecksOpt::runOnModule(Module &M) {
  TS = &getAnalysis<dsa::TypeSafety<TDDataStructures> >();

  // Create the necessary prototypes
  VoidTy = IntegerType::getVoidTy(M.getContext());
  Int8Ty = IntegerType::getInt8Ty(M.getContext());
  Int32Ty = IntegerType::getInt32Ty(M.getContext());
  Int64Ty = IntegerType::getInt64Ty(M.getContext());
  VoidPtrTy = PointerType::getUnqual(Int8Ty);
  TypeTagTy = Int8Ty;
  TypeTagPtrTy = PointerType::getUnqual(TypeTagTy);

  Constant *memsetF = M.getOrInsertFunction ("llvm.memset.i64", VoidTy,
                                             VoidPtrTy,
                                             Int8Ty,
                                             Int64Ty,
                                             Int32Ty,
                                             NULL);
  trackGlobal = M.getOrInsertFunction("trackGlobal",
                                      VoidTy,
                                      VoidPtrTy,/*ptr*/
                                      TypeTagTy,/*type*/
                                      Int64Ty,/*size*/
                                      Int32Ty,/*tag*/
                                      NULL);
  trackInitInst = M.getOrInsertFunction("trackInitInst",
                                        VoidTy,
                                        VoidPtrTy,/*ptr*/
                                        Int64Ty,/*size*/
                                        Int32Ty,/*tag*/
                                        NULL);
  trackUnInitInst = M.getOrInsertFunction("trackUnInitInst",
                                          VoidTy,
                                          VoidPtrTy,/*ptr*/
                                          Int64Ty,/*size*/
                                          Int32Ty,/*tag*/
                                          NULL);
  trackStoreInst = M.getOrInsertFunction("trackStoreInst",
                                         VoidTy,
                                         VoidPtrTy,/*ptr*/
                                         TypeTagTy,/*type*/
                                         Int64Ty,/*size*/
                                         Int32Ty,/*tag*/
                                         NULL);
  checkTypeInst = M.getOrInsertFunction("checkType",
                                        VoidTy,
                                        TypeTagTy,/*type*/
                                        Int64Ty,/*size*/
                                        TypeTagPtrTy,
                                        VoidPtrTy,/*ptr*/
                                        Int32Ty,/*tag*/
                                        NULL);
  copyTypeInfo = M.getOrInsertFunction("copyTypeInfo",
                                       VoidTy,
                                       VoidPtrTy,/*dest ptr*/
                                       VoidPtrTy,/*src ptr*/
                                       Int64Ty,/*size*/
                                       Int32Ty,/*tag*/
                                       NULL);
  setTypeInfo = M.getOrInsertFunction("setTypeInfo",
                                      VoidTy,
                                      VoidPtrTy,/*dest ptr*/
                                      TypeTagPtrTy,/*metadata*/
                                      Int64Ty,/*size*/
                                      TypeTagTy,
                                      VoidPtrTy,
                                      Int32Ty,/*tag*/
                                      NULL);
  trackStringInput = M.getOrInsertFunction("trackStringInput",
                                           VoidTy,
                                           VoidPtrTy,
                                           Int32Ty,
                                           NULL);
  getTypeTag = M.getOrInsertFunction("getTypeTag",
                                     VoidTy,
                                     VoidPtrTy, /*ptr*/
                                     Int64Ty, /*size*/
                                     TypeTagPtrTy, /*dest for type tag*/
                                     Int32Ty, /*tag*/
                                     NULL);
  MallocFunc = M.getFunction("malloc");

  for(Value::use_iterator User = trackGlobal->use_begin(); User != trackGlobal->use_end(); ++User) {
    CallInst *CI = dyn_cast<CallInst>(*User);
    assert(CI);
    if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) {
      std::vector<Value*>Args;
      Args.push_back(CI->getOperand(1));
      Args.push_back(CI->getOperand(3));
      Args.push_back(CI->getOperand(4));
      CallInst::Create(trackInitInst, Args, "", CI);
      toDelete.push_back(CI);
    }
  }

  for(Value::use_iterator User = checkTypeInst->use_begin(); User != checkTypeInst->use_end(); ++User) {
    CallInst *CI = dyn_cast<CallInst>(*User);
    assert(CI);

    if(TS->isTypeSafe(CI->getOperand(4)->stripPointerCasts(), CI->getParent()->getParent())) {
      toDelete.push_back(CI);
    }
  }

  for(Value::use_iterator User = trackStoreInst->use_begin(); User != trackStoreInst->use_end(); ++User) {
    CallInst *CI = dyn_cast<CallInst>(*User);
    assert(CI);

    if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) {
      toDelete.push_back(CI);
    }
  }

  // for alloca's if they are type known
  // assume initialized with TOP
  for(Value::use_iterator User = trackUnInitInst->use_begin(); User != trackUnInitInst->use_end(); ) {
    CallInst *CI = dyn_cast<CallInst>(*(User++));
    assert(CI);

    // check if operand is an alloca inst.
    if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) {
      CI->setCalledFunction(trackInitInst);

      if(AllocaInst *AI = dyn_cast<AllocaInst>(CI->getOperand(1)->stripPointerCasts())) {
        // Initialize the allocation to NULL
        std::vector<Value *> Args2;
        Args2.push_back(CI->getOperand(1));
        Args2.push_back(ConstantInt::get(Int8Ty, 0));
        Args2.push_back(CI->getOperand(2));
        Args2.push_back(ConstantInt::get(Int32Ty, AI->getAlignment()));
        CallInst::Create(memsetF, Args2, "", CI);
      }
    }
  }

  if(MallocFunc) {
    for(Value::use_iterator User = MallocFunc->use_begin(); User != MallocFunc->use_end(); User ++) {
      CallInst *CI = dyn_cast<CallInst>(*User);
      if(!CI)
        continue;
      if(TS->isTypeSafe(CI, CI->getParent()->getParent())){
        CastInst *BCI = BitCastInst::CreatePointerCast(CI, VoidPtrTy);
        CastInst *Size = CastInst::CreateSExtOrBitCast(CI->getOperand(1), Int64Ty);
        Size->insertAfter(CI);
        BCI->insertAfter(Size);
        std::vector<Value *>Args;
        Args.push_back(BCI);
        Args.push_back(Size);
        Args.push_back(ConstantInt::get(Int32Ty, 0));
        CallInst *CINew = CallInst::Create(trackInitInst, Args);
        CINew->insertAfter(BCI);
      }
    }
  }

  // also do for mallocs/calloc/other allocators???
  // other allocators??

  for(Value::use_iterator User = copyTypeInfo->use_begin(); User != copyTypeInfo->use_end(); ++User) {
    CallInst *CI = dyn_cast<CallInst>(*User);
    assert(CI);

    if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) {
      std::vector<Value*> Args;
      Args.push_back(CI->getOperand(1));
      Args.push_back(CI->getOperand(3)); // size
      Args.push_back(CI->getOperand(4));
      CallInst::Create(trackInitInst, Args, "", CI);
      toDelete.push_back(CI);
    }
  }
  for(Value::use_iterator User = setTypeInfo->use_begin(); User != setTypeInfo->use_end(); ++User) {
    CallInst *CI = dyn_cast<CallInst>(*User);
    assert(CI);

    if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) {
      std::vector<Value*> Args;
      Args.push_back(CI->getOperand(1));
      Args.push_back(CI->getOperand(3)); // size
      Args.push_back(CI->getOperand(6));
      CallInst::Create(trackInitInst, Args, "", CI);
      toDelete.push_back(CI);
    }
  }

  for(Value::use_iterator User = getTypeTag->use_begin(); User != getTypeTag->use_end(); ++User) {
    CallInst *CI = dyn_cast<CallInst>(*User);
    assert(CI);
    if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) {
      AllocaInst *AI = dyn_cast<AllocaInst>(CI->getOperand(3)->stripPointerCasts());
      assert(AI);
      std::vector<Value*>Args;
      Args.push_back(CI->getOperand(3));
      Args.push_back(ConstantInt::get(Int8Ty, 255));
      Args.push_back(CI->getOperand(2));
      Args.push_back(ConstantInt::get(Int32Ty, AI->getAlignment()));
      CallInst::Create(memsetF, Args, "", CI);
      toDelete.push_back(CI);
    }
  }

  numSafe += toDelete.size();

  while(!toDelete.empty()) {
    Instruction *I = toDelete.back();
    toDelete.pop_back();
    I->eraseFromParent();
  }

  return (numSafe > 0);
}