Exemple #1
0
// Replace a direct call to coro.resume or coro.destroy with an indirect call to
// an address returned by coro.subfn.addr intrinsic. This is done so that
// CGPassManager recognizes devirtualization when CoroElide pass replaces a call
// to coro.subfn.addr with an appropriate function address.
void Lowerer::lowerResumeOrDestroy(CallSite CS,
                                   CoroSubFnInst::ResumeKind Index) {
  Value *ResumeAddr =
      makeSubFnCall(CS.getArgOperand(0), Index, CS.getInstruction());
  CS.setCalledFunction(ResumeAddr);
  CS.setCallingConv(CallingConv::Fast);
}
Exemple #2
0
// Calls to setjmp(p) are lowered to _setjmp3(p, 0) by the frontend.
// The idea behind _setjmp3 is that it takes an optional number of personality
// specific parameters to indicate how to restore the personality-specific frame
// state when longjmp is initiated.  Typically, the current TryLevel is saved.
void WinEHStatePass::rewriteSetJmpCallSite(IRBuilder<> &Builder, Function &F,
                                           CallSite CS, Value *State) {
  // Don't rewrite calls with a weird number of arguments.
  if (CS.getNumArgOperands() != 2)
    return;

  Instruction *Inst = CS.getInstruction();

  SmallVector<OperandBundleDef, 1> OpBundles;
  CS.getOperandBundlesAsDefs(OpBundles);

  SmallVector<Value *, 3> OptionalArgs;
  if (Personality == EHPersonality::MSVC_CXX) {
    OptionalArgs.push_back(CxxLongjmpUnwind);
    OptionalArgs.push_back(State);
    OptionalArgs.push_back(emitEHLSDA(Builder, &F));
  } else if (Personality == EHPersonality::MSVC_X86SEH) {
    OptionalArgs.push_back(SehLongjmpUnwind);
    OptionalArgs.push_back(State);
    if (UseStackGuard)
      OptionalArgs.push_back(Cookie);
  } else {
    llvm_unreachable("unhandled personality!");
  }

  SmallVector<Value *, 5> Args;
  Args.push_back(
      Builder.CreateBitCast(CS.getArgOperand(0), Builder.getInt8PtrTy()));
  Args.push_back(Builder.getInt32(OptionalArgs.size()));
  Args.append(OptionalArgs.begin(), OptionalArgs.end());

  CallSite NewCS;
  if (CS.isCall()) {
    auto *CI = cast<CallInst>(Inst);
    CallInst *NewCI = Builder.CreateCall(SetJmp3, Args, OpBundles);
    NewCI->setTailCallKind(CI->getTailCallKind());
    NewCS = NewCI;
  } else {
    auto *II = cast<InvokeInst>(Inst);
    NewCS = Builder.CreateInvoke(
        SetJmp3, II->getNormalDest(), II->getUnwindDest(), Args, OpBundles);
  }
  NewCS.setCallingConv(CS.getCallingConv());
  NewCS.setAttributes(CS.getAttributes());
  NewCS->setDebugLoc(CS->getDebugLoc());

  Instruction *NewInst = NewCS.getInstruction();
  NewInst->takeName(Inst);
  Inst->replaceAllUsesWith(NewInst);
  Inst->eraseFromParent();
}
void OptimizeReturned::visitCallSite(CallSite CS) {
  for (unsigned i = 0, e = CS.getNumArgOperands(); i < e; ++i)
    if (CS.paramHasAttr(1 + i, Attribute::Returned)) {
      Instruction *Inst = CS.getInstruction();
      Value *Arg = CS.getArgOperand(i);
      // Ignore constants, globals, undef, etc.
      if (isa<Constant>(Arg))
        continue;
      // Like replaceDominatedUsesWith but using Instruction/Use dominance.
      for (auto UI = Arg->use_begin(), UE = Arg->use_end(); UI != UE;) {
        Use &U = *UI++;
        if (DT->dominates(Inst, U))
          U.set(Inst);
      }
    }
}
bool CSDataRando::processCallSite(CallSite CS, FuncInfo &FI, PointerEquivalenceAnalysis &P, DSGraph *G) {
  bool IndirectCall = !isa<Function>(CS.getCalledValue()->stripPointerCasts());
  if (IndirectCall) { NumIndirectCalls++; }

  CallSite OriginalCS = originalCallSite(FI, CS);
  if (!DSA->canEncryptCall(OriginalCS)) {
    if (IndirectCall) { NumIndirectCantEncrypt++; }
    return false;
  }

  DSCallSite DSCS = G->getDSCallSiteForCallSite(OriginalCS);
  const Function *Callee = getEffectiveCallee(DSCS, FI, G);
  if (!Callee) {
    if (IndirectCall) { NumIndirectCantEncrypt++; }
    return false;
  }

  FuncInfo &CalleeInfo = FunctionInfo[Callee];
  Value *Clone = getCloneCalledValue(CS, CalleeInfo);
  if (!Clone || CalleeInfo.ArgNodes.empty()) {
    if (IndirectCall) { NumIndirectCantEncrypt++; }
    return false;
  }

  // We create a mapping of the formal argument nodes in the callee function and
  // actual argument nodes in the caller function's graph.
  DSGraph::NodeMapTy NodeMap;
  DSGraph *CalleeG = DSA->getDSGraph(*Callee);

  // getArgNodesForCall places the return node and the vanode in the
  // first two slots of the vector, followed by the nodes for the regular
  // pointer arguments.
  std::vector<DSNodeHandle> ArgNodes;
  getArgNodesForCall(CalleeG, DSCS, ArgNodes);

  // First the return value
  DSNodeHandle CalleeRetNode = ArgNodes[0];
  DSGraph::computeNodeMapping(CalleeRetNode, DSCS.getRetVal(), NodeMap);

  // Then VarArgs
  DSNodeHandle CalleeVarArgNode = ArgNodes[1];
  DSGraph::computeNodeMapping(CalleeVarArgNode, DSCS.getVAVal(), NodeMap);

  // And last the regular arguments.
  for (unsigned int i = 0; i < DSCS.getNumPtrArgs() && i + 2 < ArgNodes.size(); i++) {
    DSGraph::computeNodeMapping(ArgNodes[i + 2], DSCS.getPtrArg(i), NodeMap);
  }

  // Collect the arguments and masks to pass to call
  SmallVector<Value*, 8> Args;
  unsigned int i = 0;
  for (unsigned int e = CS.getFunctionType()->getNumParams(); i < e; i++) {
    Args.push_back(CS.getArgOperand(i));
  }

  for (const DSNode *N : CalleeInfo.ArgNodes) {
    Value *Mask = P.getMaskForNode(NodeMap[N]);
    Args.push_back(Mask);
  }

  // VarArgs go after masks
  for (unsigned int e = CS.arg_size(); i < e; i++) {
    Args.push_back(CS.getArgOperand(i));
  }

  // Do replacement
  Instruction *CI = CS.getInstruction();
  Value *Call;
  if (CS.isCall()) {
    Call = CallInst::Create(Clone, Args, "", CI);
  } else {
    InvokeInst *II = cast<InvokeInst>(CI);
    Call = InvokeInst::Create(Clone, II->getNormalDest(), II->getUnwindDest(), Args, "", II);
  }
  CallSite NewCS(Call);
  NewCS.setCallingConv(CS.getCallingConv());

  CI->replaceAllUsesWith(Call);
  P.replace(CI, Call);
  CI->eraseFromParent();

  return true;
}