Esempio n. 1
0
static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
                                 ArgIt ArgBegin, ArgIt ArgEnd,
                                 Type *RetTy) {
  // If we haven't already looked up this function, check to see if the
  // program already contains a function with this name.
  Module *M = CI->getParent()->getParent()->getParent();
  // Get or insert the definition now.
  std::vector<Type *> ParamTys;
  for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
    ParamTys.push_back((*I)->getType());
  Constant* FCache = M->getOrInsertFunction(NewFn,
                                  FunctionType::get(RetTy, ParamTys, false));

  IRBuilder<> Builder(CI->getParent(), CI);
  SmallVector<Value *, 8> Args(ArgBegin, ArgEnd);
  CallInst *NewCI = Builder.CreateCall(FCache, Args);
  NewCI->setName(CI->getName());
  if (!CI->use_empty())
    CI->replaceAllUsesWith(NewCI);
  return NewCI;
}
void AtomicVisitor::replaceInstructionWithIntrinsicCall(
    Instruction &I, const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic,
    Type *DstType, Type *OverloadedType, ArrayRef<Value *> Args) {
  std::string Name(I.getName());
  Function *F = Intrinsic->getDeclaration(&M);
  CallInst *Call = CallInst::Create(F, Args, "", &I);
  Call->setDebugLoc(I.getDebugLoc());
  Instruction *Res = Call;

  assert((I.getType()->isStructTy() == isa<AtomicCmpXchgInst>(&I)) &&
         "cmpxchg returns a struct, and other instructions don't");
  if (auto S = dyn_cast<StructType>(I.getType())) {
    assert(S->getNumElements() == 2 &&
           "cmpxchg returns a struct with two elements");
    assert(S->getElementType(0) == DstType &&
           "cmpxchg struct's first member should be the value type");
    assert(S->getElementType(1) == Type::getInt1Ty(C) &&
           "cmpxchg struct's second member should be the success flag");
    // Recreate struct { T value, i1 success } after the call.
    auto Success = CmpInst::Create(
        Instruction::ICmp, CmpInst::ICMP_EQ, Res,
        cast<AtomicCmpXchgInst>(&I)->getCompareOperand(), "success", &I);
    Res = InsertValueInst::Create(
        InsertValueInst::Create(UndefValue::get(S), Res, 0,
                                Name + ".insert.value", &I),
        Success, 1, Name + ".insert.success", &I);
  } else if (!Call->getType()->isVoidTy() && DstType != OverloadedType) {
    // The call returns a value which needs to be cast to a non-integer.
    Res = createCast(I, Call, DstType, Name + ".cast");
    Res->setDebugLoc(I.getDebugLoc());
  }

  I.replaceAllUsesWith(Res);
  I.eraseFromParent();
  Call->setName(Name);
  ModifiedModule = true;
}
// Creates the helper function that will do the setjmp() call and
// function call for implementing Invoke.  Creates the call to the
// helper function.  Returns a Value which is zero on the normal
// execution path and non-zero if the landingpad block should be
// entered.
Value *FuncRewriter::createSetjmpWrappedCall(InvokeInst *Invoke) {
  Type *I32 = Type::getInt32Ty(Func->getContext());

  // Allocate space for storing the invoke's result temporarily (so
  // that the helper function can return multiple values).  We don't
  // need to do this if the result is unused, and we can't if its type
  // is void.
  Instruction *ResultAlloca = NULL;
  if (!Invoke->use_empty()) {
    ResultAlloca = new AllocaInst(Invoke->getType(), "invoke_result_ptr");
    Func->getEntryBlock().getInstList().push_front(ResultAlloca);
  }

  // Create type for the helper function.
  SmallVector<Type *, 10> ArgTypes;
  for (unsigned I = 0, E = Invoke->getNumArgOperands(); I < E; ++I)
    ArgTypes.push_back(Invoke->getArgOperand(I)->getType());
  ArgTypes.push_back(Invoke->getCalledValue()->getType());
  ArgTypes.push_back(FrameJmpBuf->getType());
  if (ResultAlloca)
    ArgTypes.push_back(Invoke->getType()->getPointerTo());
  FunctionType *FTy = FunctionType::get(I32, ArgTypes, false);

  // Create the helper function.
  Function *HelperFunc = Function::Create(
      FTy, GlobalValue::InternalLinkage, Func->getName() + "_setjmp_caller");
  Func->getParent()->getFunctionList().insertAfter(Func, HelperFunc);
  BasicBlock *EntryBB = BasicBlock::Create(Func->getContext(), "", HelperFunc);
  BasicBlock *NormalBB = BasicBlock::Create(Func->getContext(), "normal",
                                            HelperFunc);
  BasicBlock *ExceptionBB = BasicBlock::Create(Func->getContext(), "exception",
                                               HelperFunc);

  // Unpack the helper function's arguments.
  Function::arg_iterator ArgIter = HelperFunc->arg_begin();
  SmallVector<Value *, 10> InnerCallArgs;
  for (unsigned I = 0, E = Invoke->getNumArgOperands(); I < E; ++I) {
    ArgIter->setName("arg");
    InnerCallArgs.push_back(ArgIter++);
  }
  Argument *CalleeArg = ArgIter++;
  Argument *JmpBufArg = ArgIter++;
  CalleeArg->setName("func_ptr");
  JmpBufArg->setName("jmp_buf");

  // Create setjmp() call.
  Value *SetjmpArgs[] = { JmpBufArg };
  CallInst *SetjmpCall = CallInst::Create(SetjmpIntrinsic, SetjmpArgs,
                                          "invoke_sj", EntryBB);
  CopyDebug(SetjmpCall, Invoke);
  // Setting the "returns_twice" attribute here prevents optimization
  // passes from inlining HelperFunc into its caller.
  SetjmpCall->setCanReturnTwice();
  // Check setjmp()'s result.
  Value *IsZero = CopyDebug(new ICmpInst(*EntryBB, CmpInst::ICMP_EQ, SetjmpCall,
                                         ConstantInt::get(I32, 0),
                                         "invoke_sj_is_zero"), Invoke);
  CopyDebug(BranchInst::Create(NormalBB, ExceptionBB, IsZero, EntryBB), Invoke);
  // Handle the normal, non-exceptional code path.
  CallInst *InnerCall = CallInst::Create(CalleeArg, InnerCallArgs, "",
                                         NormalBB);
  CopyDebug(InnerCall, Invoke);
  InnerCall->setAttributes(Invoke->getAttributes());
  InnerCall->setCallingConv(Invoke->getCallingConv());
  if (ResultAlloca) {
    InnerCall->setName("result");
    Argument *ResultArg = ArgIter++;
    ResultArg->setName("result_ptr");
    CopyDebug(new StoreInst(InnerCall, ResultArg, NormalBB), Invoke);
  }
  ReturnInst::Create(Func->getContext(), ConstantInt::get(I32, 0), NormalBB);
  // Handle the exceptional code path.
  ReturnInst::Create(Func->getContext(), ConstantInt::get(I32, 1), ExceptionBB);

  // Create the outer call to the helper function.
  SmallVector<Value *, 10> OuterCallArgs;
  for (unsigned I = 0, E = Invoke->getNumArgOperands(); I < E; ++I)
    OuterCallArgs.push_back(Invoke->getArgOperand(I));
  OuterCallArgs.push_back(Invoke->getCalledValue());
  OuterCallArgs.push_back(FrameJmpBuf);
  if (ResultAlloca)
    OuterCallArgs.push_back(ResultAlloca);
  CallInst *OuterCall = CallInst::Create(HelperFunc, OuterCallArgs,
                                         "invoke_is_exc", Invoke);
  CopyDebug(OuterCall, Invoke);

  // Retrieve the function return value stored in the alloca.  We only
  // need to do this on the non-exceptional path, but we currently do
  // it unconditionally because that is simpler.
  if (ResultAlloca) {
    Value *Result = new LoadInst(ResultAlloca, "", Invoke);
    Result->takeName(Invoke);
    Invoke->replaceAllUsesWith(Result);
  }
  return OuterCall;
}