void SelectionDAGBuilder::LowerCallSiteWithDeoptBundleImpl(
    ImmutableCallSite CS, SDValue Callee, const BasicBlock *EHPadBB,
    bool VarArgDisallowed, bool ForceVoidReturnTy) {
  StatepointLoweringInfo SI(DAG);
  unsigned ArgBeginIndex = CS.arg_begin() - CS.getInstruction()->op_begin();
  populateCallLoweringInfo(
      SI.CLI, CS, ArgBeginIndex, CS.getNumArgOperands(), Callee,
      ForceVoidReturnTy ? Type::getVoidTy(*DAG.getContext()) : CS.getType(),
      false);
  if (!VarArgDisallowed)
    SI.CLI.IsVarArg = CS.getFunctionType()->isVarArg();

  auto DeoptBundle = *CS.getOperandBundle(LLVMContext::OB_deopt);

  unsigned DefaultID = StatepointDirectives::DeoptBundleStatepointID;

  auto SD = parseStatepointDirectivesFromAttrs(CS.getAttributes());
  SI.ID = SD.StatepointID.getValueOr(DefaultID);
  SI.NumPatchBytes = SD.NumPatchBytes.getValueOr(0);

  SI.DeoptState =
      ArrayRef<const Use>(DeoptBundle.Inputs.begin(), DeoptBundle.Inputs.end());
  SI.StatepointFlags = static_cast<uint64_t>(StatepointFlags::None);
  SI.EHPadBB = EHPadBB;

  // NB! The GC arguments are deliberately left empty.

  if (SDValue ReturnVal = LowerAsSTATEPOINT(SI)) {
    const Instruction *Inst = CS.getInstruction();
    ReturnVal = lowerRangeToAssertZExt(DAG, *Inst, ReturnVal);
    setValue(Inst, ReturnVal);
  }
}
Example #2
0
bool CallLowering::lowerCall(
    MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, unsigned ResReg,
    ArrayRef<unsigned> ArgRegs, std::function<unsigned()> GetCalleeReg) const {
  auto &DL = CS.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;
  unsigned NumFixedArgs = CS.getFunctionType()->getNumParams();
  for (auto &Arg : CS.args()) {
    ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{},
                    i < NumFixedArgs};
    setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CS);
    // We don't currently support swifterror or swiftself args.
    if (OrigArg.Flags.isSwiftError() || OrigArg.Flags.isSwiftSelf())
      return false;
    OrigArgs.push_back(OrigArg);
    ++i;
  }

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

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

  return lowerCall(MIRBuilder, CS.getCallingConv(), Callee, OrigRet, OrigArgs);
}
Example #3
0
void SelectionDAGBuilder::LowerCallSiteWithDeoptBundle(
    ImmutableCallSite CS, SDValue Callee, const BasicBlock *EHPadBB) {
  StatepointLoweringInfo SI(DAG);
  unsigned ArgBeginIndex = CS.arg_begin() - CS.getInstruction()->op_begin();
  populateCallLoweringInfo(SI.CLI, CS, ArgBeginIndex, CS.getNumArgOperands(),
                           Callee, CS.getType(), false);

  auto DeoptBundle = *CS.getOperandBundle(LLVMContext::OB_deopt);

  unsigned DefaultID = StatepointDirectives::DeoptBundleStatepointID;

  auto SD = parseStatepointDirectivesFromAttrs(CS.getAttributes());
  SI.ID = SD.StatepointID.getValueOr(DefaultID);
  SI.NumPatchBytes = SD.NumPatchBytes.getValueOr(0);

  SI.DeoptState =
      ArrayRef<const Use>(DeoptBundle.Inputs.begin(), DeoptBundle.Inputs.end());
  SI.StatepointFlags = static_cast<uint64_t>(StatepointFlags::None);
  SI.EHPadBB = EHPadBB;

  if (SDValue ReturnVal = LowerAsSTATEPOINT(SI)) {
    const Instruction *Inst = CS.getInstruction();
    ReturnVal = lowerRangeToAssertZExt(DAG, *Inst, ReturnVal);
    setValue(Inst, ReturnVal);
  }
}
std::vector<FlowRecord>
TaintReachable::process(const ContextID ctxt, const ImmutableCallSite cs) const {
  DEBUG(errs() << "Using taint reachable signature for: " << *cs.getInstruction() << "\n");

  FlowRecord exp(false,ctxt,ctxt);
  FlowRecord imp(true,ctxt,ctxt);

  // implicit from the pc of the call site and the function pointer
  imp.addSourceValue(*cs->getParent());
  imp.addSourceValue(*cs.getCalledValue());

  // Sources and sinks of the args
  for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end();
       arg != end; ++arg) {
      // every argument's value is a source
      exp.addSourceValue(**arg);
      // if the argument is a pointer, everything it reaches is a source
      // and everything it reaches is a sink
      if ((*arg)->getType()->isPointerTy()) {
	exp.addSourceReachablePtr(**arg);
	imp.addSourceValue(**arg);

	exp.addSinkReachablePtr(**arg);
	imp.addSinkReachablePtr(**arg);
      }
  }

  // if the function has a return value it is a sink
  if (!cs->getType()->isVoidTy()) {
    imp.addSinkValue(*cs.getInstruction());
    exp.addSinkValue(*cs.getInstruction());
  }

  std::vector<FlowRecord> flows;
  flows.push_back(imp);
  flows.push_back(exp);
  return flows;
}
std::vector<FlowRecord>
ArgsToRet::process(const ContextID ctxt, const ImmutableCallSite cs) const {
  DEBUG(errs() << "Using ArgsToRet reachable signature for: " << *cs.getInstruction() << "\n");

  std::vector<FlowRecord> flows;

  if (!cs->getType()->isVoidTy()) {
    FlowRecord exp(false,ctxt,ctxt);

    // Sources and sinks of the args
    for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end();
	 arg != end; ++arg) {
      // every argument's value is a source
      exp.addSourceValue(**arg);
    }

    // if the function has a return value it is a sink
    exp.addSinkValue(*cs.getInstruction());

    flows.push_back(exp);
  }

  return flows;
}
std::vector<FlowRecord>
OverflowChecks::process(const ContextID ctxt, const ImmutableCallSite cs) const {
  DEBUG(errs() << "Using OverflowChecks signature...\n");

  FlowRecord exp(false,ctxt,ctxt);
  FlowRecord imp(true,ctxt,ctxt);

  imp.addSourceValue(*cs->getParent());

  // Add all argument values as sources
  for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end();
       arg != end; ++arg)
    exp.addSourceValue(**arg);
  assert(!cs->getType()->isVoidTy() && "Found 'void' overflow check?");

  // And the return value as a sink
  exp.addSinkValue(*cs.getInstruction());
  imp.addSinkValue(*cs.getInstruction());

  std::vector<FlowRecord> flows;
  flows.push_back(imp);
  flows.push_back(exp);
  return flows;
}
Example #7
0
// There are two types of constraints to add for a function call:
// - ValueNode(callsite) = ReturnNode(call target)
// - ValueNode(formal arg) = ValueNode(actual arg)
void Andersen::addConstraintForCall(ImmutableCallSite cs) {
  if (const Function *f = cs.getCalledFunction()) // Direct call
  {
    if (f->isDeclaration() || f->isIntrinsic()) // External library call
    {
      // Handle libraries separately
      if (addConstraintForExternalLibrary(cs, f))
        return;
      else // Unresolved library call: ruin everything!
      {
        errs() << "Unresolved ext function: " << f->getName() << "\n";
        if (cs.getType()->isPointerTy()) {
          NodeIndex retIndex = nodeFactory.getValueNodeFor(cs.getInstruction());
          assert(retIndex != AndersNodeFactory::InvalidIndex &&
                 "Failed to find ret node!");
          constraints.emplace_back(AndersConstraint::COPY, retIndex,
                                   nodeFactory.getUniversalPtrNode());
        }
        for (ImmutableCallSite::arg_iterator itr = cs.arg_begin(),
                                             ite = cs.arg_end();
             itr != ite; ++itr) {
          Value *argVal = *itr;
          if (argVal->getType()->isPointerTy()) {
            NodeIndex argIndex = nodeFactory.getValueNodeFor(argVal);
            assert(argIndex != AndersNodeFactory::InvalidIndex &&
                   "Failed to find arg node!");
            constraints.emplace_back(AndersConstraint::COPY, argIndex,
                                     nodeFactory.getUniversalPtrNode());
          }
        }
      }
    } else // Non-external function call
    {
      if (cs.getType()->isPointerTy()) {
        NodeIndex retIndex = nodeFactory.getValueNodeFor(cs.getInstruction());
        assert(retIndex != AndersNodeFactory::InvalidIndex &&
               "Failed to find ret node!");
        // errs() << f->getName() << "\n";
        NodeIndex fRetIndex = nodeFactory.getReturnNodeFor(f);
        assert(fRetIndex != AndersNodeFactory::InvalidIndex &&
               "Failed to find function ret node!");
        constraints.emplace_back(AndersConstraint::COPY, retIndex, fRetIndex);
      }
      // The argument constraints
      addArgumentConstraintForCall(cs, f);
    }
  } else // Indirect call
  {
    // We do the simplest thing here: just assume the returned value can be
    // anything :)
    if (cs.getType()->isPointerTy()) {
      NodeIndex retIndex = nodeFactory.getValueNodeFor(cs.getInstruction());
      assert(retIndex != AndersNodeFactory::InvalidIndex &&
             "Failed to find ret node!");
      constraints.emplace_back(AndersConstraint::COPY, retIndex,
                               nodeFactory.getUniversalPtrNode());
    }

    // For argument constraints, first search through all addr-taken functions:
    // any function that takes can take as many variables is a potential
    // candidate
    const Module *M =
        cs.getInstruction()->getParent()->getParent()->getParent();
    for (auto const &f : *M) {
      NodeIndex funPtrIndex = nodeFactory.getValueNodeFor(&f);
      if (funPtrIndex == AndersNodeFactory::InvalidIndex)
        // Not an addr-taken function
        continue;

      if (!f.getFunctionType()->isVarArg() && f.arg_size() != cs.arg_size())
        // #arg mismatch
        continue;

      if (f.isDeclaration() || f.isIntrinsic()) // External library call
      {
        if (addConstraintForExternalLibrary(cs, &f))
          continue;
        else {
          // Pollute everything
          for (ImmutableCallSite::arg_iterator itr = cs.arg_begin(),
                                               ite = cs.arg_end();
               itr != ite; ++itr) {
            Value *argVal = *itr;

            if (argVal->getType()->isPointerTy()) {
              NodeIndex argIndex = nodeFactory.getValueNodeFor(argVal);
              assert(argIndex != AndersNodeFactory::InvalidIndex &&
                     "Failed to find arg node!");
              constraints.emplace_back(AndersConstraint::COPY, argIndex,
                                       nodeFactory.getUniversalPtrNode());
            }
          }
        }
      } else
        addArgumentConstraintForCall(cs, &f);
    }
  }
}