예제 #1
0
/// \brief Returns the allocation data for the given value if it is a call to a
/// known allocation function, and NULL otherwise.
static const AllocFnsTy *getAllocationData(const Value *V, AllocType AllocTy,
                                           const TargetLibraryInfo *TLI,
                                           bool LookThroughBitCast = false) {
  // Skip all intrinsics but duetto.allocate
  if (const IntrinsicInst* II = dyn_cast<IntrinsicInst>(V))
  {
    if (II->getIntrinsicID() == Intrinsic::duetto_allocate)
      return &AllocationFnData[0];
    return 0;
  }

  Function *Callee = getCalledFunction(V, LookThroughBitCast);
  if (!Callee)
    return 0;

  // Make sure that the function is available.
  StringRef FnName = Callee->getName();
  LibFunc::Func TLIFn;
  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
    return 0;

  unsigned i = 0;
  bool found = false;
  for ( ; i < array_lengthof(AllocationFnData); ++i) {
    if (AllocationFnData[i].Func == TLIFn) {
      found = true;
      break;
    }
  }
  if (!found)
    return 0;

  const AllocFnsTy *FnData = &AllocationFnData[i];
  if ((FnData->AllocTy & AllocTy) != FnData->AllocTy)
    return 0;

  // Check function prototype.
  int FstParam = FnData->FstParam;
  int SndParam = FnData->SndParam;
  FunctionType *FTy = Callee->getFunctionType();

  if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) &&
      FTy->getNumParams() == FnData->NumParams &&
      (FstParam < 0 ||
       (FTy->getParamType(FstParam)->isIntegerTy(32) ||
        FTy->getParamType(FstParam)->isIntegerTy(64))) &&
      (SndParam < 0 ||
       FTy->getParamType(SndParam)->isIntegerTy(32) ||
       FTy->getParamType(SndParam)->isIntegerTy(64)))
    return FnData;
  return 0;
}
예제 #2
0
void Function::BuildLazyArguments() const {
  // Create the arguments vector, all arguments start out unnamed.
  FunctionType *FT = getFunctionType();
  for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
    assert(!FT->getParamType(i)->isVoidTy() &&
           "Cannot have void typed arguments!");
    ArgumentList.push_back(new Argument(FT->getParamType(i)));
  }
  
  // Clear the lazy arguments bit.
  unsigned SDC = getSubclassDataFromValue();
  const_cast<Function*>(this)->setValueSubclassData(SDC &= ~1);
}
예제 #3
0
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
  const CallInst *CI = dyn_cast<CallInst>(I);
  if (!CI || isa<IntrinsicInst>(CI))
    return 0;
  Function *Callee = CI->getCalledFunction();
  if (Callee == 0 || !Callee->isDeclaration())
    return 0;

  StringRef FnName = Callee->getName();
  LibFunc::Func TLIFn;
  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
    return 0;

  if (TLIFn != LibFunc::free &&
      TLIFn != LibFunc::ZdlPv && // operator delete(void*)
      TLIFn != LibFunc::ZdaPv)   // operator delete[](void*)
    return 0;

  // Check free prototype.
  // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
  // attribute will exist.
  FunctionType *FTy = Callee->getFunctionType();
  if (!FTy->getReturnType()->isVoidTy())
    return 0;
  if (FTy->getNumParams() != 1)
    return 0;
  if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext()))
    return 0;

  return CI;
}
예제 #4
0
static Instruction*
applyRewriteToCall(Module& M, const CallRewrite* const rw, CallSite cs)
{
    Function* target = cs.getCalledFunction();
    assert(target != NULL);

    Function* newTarget = M.getFunction(rw->function);
    if (newTarget == NULL) {
        // There isn't a function, we need to construct it
        FunctionType* newType = target->getFunctionType();
        std::vector<Type*> argTypes;
        for (std::vector<unsigned>::const_iterator i = rw->args.begin(), e =
                    rw->args.end(); i != e; ++i)
            argTypes.push_back(newType->getParamType(*i));
        ArrayRef<Type*> params(argTypes);
        newType = FunctionType::get(target->getReturnType(), params, target->isVarArg());

        newTarget = dyn_cast<Function> (M.getOrInsertFunction(rw->function,
                                        newType));
    }

    assert(newTarget != NULL);

    return specializeCallSite(cs.getInstruction(), newTarget, rw->args);
}
예제 #5
0
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
static const CallInst* isFreeCall(const Value* I) {
    const CallInst* CI = dyn_cast<CallInst>(I);
    if (!CI)
        return 0;
    Function* Callee = CI->getCalledFunction();
    if (Callee == 0 || !Callee->isDeclaration())
        return 0;

    if (Callee->getName() != "free" /*&&
            Callee->getName() != "my_free" &&
            Callee->getName() != "_ZdlPv" && // operator delete(void*)
            Callee->getName() != "_ZdaPv"*/) // operator delete[](void*)
        return 0;

    // Check free prototype.
    // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
    // attribute will exist.
    FunctionType* FTy = Callee->getFunctionType();
    if (!FTy->getReturnType()->isVoidTy())
        return 0;
    if (FTy->getNumParams() != 1)
        return 0;
    if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext()))
        return 0;

    return CI;
}
예제 #6
0
void TypeDuplicater::RemoveNonLocalTypes(Module &M){
  std::set<Function *> UndefinedFunctions;
  for(auto IF = M.begin(), EF = M.end(); IF != EF; ++IF){
    Function *F = &*IF;

    if(F->isDeclaration())
      UndefinedFunctions.insert(F);
  }

  for(auto F: UndefinedFunctions){
    FunctionType *FuncType = cast<FunctionType>(F->getFunctionType());
    for(int i=0; i<FuncType->getNumParams(); i++){
      Type *T =FuncType->getParamType(i);

      while(T->isPointerTy())
        T = T->getPointerElementType();
      if(auto *ST = dyn_cast<StructType>(T))
        RawStructs.erase(ST);
    }

    Type *T =FuncType->getReturnType();
    while(T->isPointerTy())
      T = T->getPointerElementType();
    if(auto *ST = dyn_cast<StructType>(T))
      RawStructs.erase(ST);
  }
}
예제 #7
0
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
  bool IsNoBuiltinCall;
  const Function *Callee =
      getCalledFunction(I, /*LookThroughBitCast=*/false, IsNoBuiltinCall);
  if (Callee == nullptr || IsNoBuiltinCall)
    return nullptr;

  StringRef FnName = Callee->getName();
  LibFunc TLIFn;
  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
    return nullptr;

  unsigned ExpectedNumParams;
  if (TLIFn == LibFunc_free ||
      TLIFn == LibFunc_ZdlPv || // operator delete(void*)
      TLIFn == LibFunc_ZdaPv || // operator delete[](void*)
      TLIFn == LibFunc_msvc_delete_ptr32 || // operator delete(void*)
      TLIFn == LibFunc_msvc_delete_ptr64 || // operator delete(void*)
      TLIFn == LibFunc_msvc_delete_array_ptr32 || // operator delete[](void*)
      TLIFn == LibFunc_msvc_delete_array_ptr64)   // operator delete[](void*)
    ExpectedNumParams = 1;
  else if (TLIFn == LibFunc_ZdlPvj ||              // delete(void*, uint)
           TLIFn == LibFunc_ZdlPvm ||              // delete(void*, ulong)
           TLIFn == LibFunc_ZdlPvRKSt9nothrow_t || // delete(void*, nothrow)
           TLIFn == LibFunc_ZdlPvSt11align_val_t || // delete(void*, align_val_t)
           TLIFn == LibFunc_ZdaPvj ||              // delete[](void*, uint)
           TLIFn == LibFunc_ZdaPvm ||              // delete[](void*, ulong)
           TLIFn == LibFunc_ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow)
           TLIFn == LibFunc_ZdaPvSt11align_val_t || // delete[](void*, align_val_t)
           TLIFn == LibFunc_msvc_delete_ptr32_int ||      // delete(void*, uint)
           TLIFn == LibFunc_msvc_delete_ptr64_longlong || // delete(void*, ulonglong)
           TLIFn == LibFunc_msvc_delete_ptr32_nothrow || // delete(void*, nothrow)
           TLIFn == LibFunc_msvc_delete_ptr64_nothrow || // delete(void*, nothrow)
           TLIFn == LibFunc_msvc_delete_array_ptr32_int ||      // delete[](void*, uint)
           TLIFn == LibFunc_msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong)
           TLIFn == LibFunc_msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow)
           TLIFn == LibFunc_msvc_delete_array_ptr64_nothrow)   // delete[](void*, nothrow)
    ExpectedNumParams = 2;
  else if (TLIFn == LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t || // delete(void*, align_val_t, nothrow)
           TLIFn == LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t) // delete[](void*, align_val_t, nothrow)
    ExpectedNumParams = 3;
  else
    return nullptr;

  // Check free prototype.
  // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
  // attribute will exist.
  FunctionType *FTy = Callee->getFunctionType();
  if (!FTy->getReturnType()->isVoidTy())
    return nullptr;
  if (FTy->getNumParams() != ExpectedNumParams)
    return nullptr;
  if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext()))
    return nullptr;

  return dyn_cast<CallInst>(I);
}
예제 #8
0
/// \brief Returns the allocation data for the given value if it is a call to a
/// known allocation function, and NULL otherwise.
static const AllocFnsTy *getAllocationData(const Value *V, AllocType AllocTy,
                                           const TargetLibraryInfo *TLI,
                                           bool LookThroughBitCast = false) {
  // Skip intrinsics
  if (isa<IntrinsicInst>(V))
    return nullptr;

  Function *Callee = getCalledFunction(V, LookThroughBitCast);
  if (!Callee)
    return nullptr;

  // Make sure that the function is available.
  StringRef FnName = Callee->getName();
  LibFunc::Func TLIFn;
  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
    return nullptr;

  const AllocFnsTy *FnData =
      std::find_if(std::begin(AllocationFnData), std::end(AllocationFnData),
                   [TLIFn](const AllocFnsTy &Fn) { return Fn.Func == TLIFn; });

  if (FnData == std::end(AllocationFnData))
    return nullptr;

  if ((FnData->AllocTy & AllocTy) != FnData->AllocTy)
    return nullptr;

  // Check function prototype.
  int FstParam = FnData->FstParam;
  int SndParam = FnData->SndParam;
  FunctionType *FTy = Callee->getFunctionType();

  if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) &&
      FTy->getNumParams() == FnData->NumParams &&
      (FstParam < 0 ||
       (FTy->getParamType(FstParam)->isIntegerTy(32) ||
        FTy->getParamType(FstParam)->isIntegerTy(64))) &&
      (SndParam < 0 ||
       FTy->getParamType(SndParam)->isIntegerTy(32) ||
       FTy->getParamType(SndParam)->isIntegerTy(64)))
    return FnData;
  return nullptr;
}
예제 #9
0
// We accept bswap for a limited set of types (i16, i32, i64).
// The various backends are able to generate instructions to
// implement the intrinsic.  Also, i16 and i64 are easy to
// implement as along as there is a way to do i32.
static bool isWhitelistedBswap(const Function *F) {
  FunctionType *FT = F->getFunctionType();
  if (FT->getNumParams() != 1)
    return false;
  Type *ParamType = FT->getParamType(0);
  LLVMContext &C = F->getContext();
  Type *AcceptableTypes[] = { Type::getInt16Ty(C),
                              Type::getInt32Ty(C),
                              Type::getInt64Ty(C) };
  return TypeAcceptable(ParamType, AcceptableTypes);
}
예제 #10
0
static void check(Value *Func, ArrayRef<Value *> Args) {
  FunctionType *FTy =
      cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());

  assert((Args.size() == FTy->getNumParams() ||
          (FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
         "XXCalling a function with bad signature!");

  for (unsigned i = 0; i != Args.size(); ++i) {
    if (!(FTy->getParamType(i) == Args[i]->getType())) {
      errs() << "types:\n  ";
      FTy->getParamType(i)->dump();
      errs() << "\n  ";
      Args[i]->getType()->dump();
      errs() << "\n";
    }
    assert((i >= FTy->getNumParams() ||
            FTy->getParamType(i) == Args[i]->getType()) &&
           "YYCalling a function with a bad signature!");
  }
}
예제 #11
0
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
  const CallInst *CI = dyn_cast<CallInst>(I);
  if (!CI || isa<IntrinsicInst>(CI))
    return nullptr;
  Function *Callee = CI->getCalledFunction();
  if (Callee == nullptr)
    return nullptr;

  StringRef FnName = Callee->getName();
  LibFunc::Func TLIFn;
  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
    return nullptr;

  unsigned ExpectedNumParams;
  if (TLIFn == LibFunc::free ||
      TLIFn == LibFunc::ZdlPv || // operator delete(void*)
      TLIFn == LibFunc::ZdaPv || // operator delete[](void*)
      TLIFn == LibFunc::msvc_delete_ptr32 || // operator delete(void*)
      TLIFn == LibFunc::msvc_delete_ptr64 || // operator delete(void*)
      TLIFn == LibFunc::msvc_delete_array_ptr32 || // operator delete[](void*)
      TLIFn == LibFunc::msvc_delete_array_ptr64)   // operator delete[](void*)
    ExpectedNumParams = 1;
  else if (TLIFn == LibFunc::ZdlPvj ||              // delete(void*, uint)
           TLIFn == LibFunc::ZdlPvm ||              // delete(void*, ulong)
           TLIFn == LibFunc::ZdlPvRKSt9nothrow_t || // delete(void*, nothrow)
           TLIFn == LibFunc::ZdaPvj ||              // delete[](void*, uint)
           TLIFn == LibFunc::ZdaPvm ||              // delete[](void*, ulong)
           TLIFn == LibFunc::ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow)
           TLIFn == LibFunc::msvc_delete_ptr32_int ||      // delete(void*, uint)
           TLIFn == LibFunc::msvc_delete_ptr64_longlong || // delete(void*, ulonglong)
           TLIFn == LibFunc::msvc_delete_ptr32_nothrow || // delete(void*, nothrow)
           TLIFn == LibFunc::msvc_delete_ptr64_nothrow || // delete(void*, nothrow)
           TLIFn == LibFunc::msvc_delete_array_ptr32_int ||      // delete[](void*, uint)
           TLIFn == LibFunc::msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong)
           TLIFn == LibFunc::msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow)
           TLIFn == LibFunc::msvc_delete_array_ptr64_nothrow)   // delete[](void*, nothrow)
    ExpectedNumParams = 2;
  else
    return nullptr;

  // Check free prototype.
  // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
  // attribute will exist.
  FunctionType *FTy = Callee->getFunctionType();
  if (!FTy->getReturnType()->isVoidTy())
    return nullptr;
  if (FTy->getNumParams() != ExpectedNumParams)
    return nullptr;
  if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext()))
    return nullptr;

  return CI;
}
예제 #12
0
static bool isCallocCall(const CallInst *CI) {
  if (!CI)
    return false;
  
  Function *Callee = CI->getCalledFunction();
  if (Callee == 0 || !Callee->isDeclaration())
    return false;
  if (Callee->getName() != "calloc")
    return false;
  
  // Check malloc prototype.
  // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin 
  // attribute exists.
  FunctionType *FTy = Callee->getFunctionType();
  return FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) &&
  FTy->getNumParams() == 2 &&
  ((FTy->getParamType(0)->isIntegerTy(32) &&
    FTy->getParamType(1)->isIntegerTy(32)) ||
   (FTy->getParamType(0)->isIntegerTy(64) &&
    FTy->getParamType(1)->isIntegerTy(64)));
}
예제 #13
0
// TODO Copy-paste
static bool isMallocCall(const CallInst* CI) {
    if (!CI)
        return false;

    Function* Callee = CI->getCalledFunction();
    if (Callee == 0 || !Callee->isDeclaration())
        return false;
    if (Callee->getName() != "malloc" /*&&
            Callee->getName() != "my_malloc" &&
            Callee->getName() != "_Znwj" && // operator new(unsigned int)
            Callee->getName() != "_Znwm" && // operator new(unsigned long)
            Callee->getName() != "_Znaj" && // operator new[](unsigned int)
            Callee->getName() != "_Znam"*/) // operator new[](unsigned long)
        return false;

    // Check malloc prototype.
    // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
    // attribute will exist.
    FunctionType* FTy = Callee->getFunctionType();
    return FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) && FTy->getNumParams() == 1
           && (FTy->getParamType(0)->isIntegerTy(32) || FTy->getParamType(0)->isIntegerTy(64));
}
예제 #14
0
/// Creates a hash-code for the function which is the same for any two
/// functions that will compare equal, without looking at the instructions
/// inside the function.
static unsigned profileFunction(const Function *F) {
  FunctionType *FTy = F->getFunctionType();

  FoldingSetNodeID ID;
  ID.AddInteger(F->size());
  ID.AddInteger(F->getCallingConv());
  ID.AddBoolean(F->hasGC());
  ID.AddBoolean(FTy->isVarArg());
  ID.AddInteger(getTypeIDForHash(FTy->getReturnType()));
  for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
    ID.AddInteger(getTypeIDForHash(FTy->getParamType(i)));
  return ID.ComputeHash();
}
예제 #15
0
/// Replace \p Thunk with a simple tail call to \p ToFunc. Also add parameters
/// to the call to \p ToFunc, which are defined by the FuncIdx's value in
/// \p Params.
void SwiftMergeFunctions::writeThunk(Function *ToFunc, Function *Thunk,
                                     const ParamInfos &Params,
                                     unsigned FuncIdx) {
  // Delete the existing content of Thunk.
  Thunk->dropAllReferences();
  
  BasicBlock *BB = BasicBlock::Create(Thunk->getContext(), "", Thunk);
  IRBuilder<> Builder(BB);

  SmallVector<Value *, 16> Args;
  unsigned ParamIdx = 0;
  FunctionType *ToFuncTy = ToFunc->getFunctionType();
  
  // Add arguments which are passed through Thunk.
  for (Argument & AI : Thunk->args()) {
    Args.push_back(createCast(Builder, &AI, ToFuncTy->getParamType(ParamIdx)));
    ++ParamIdx;
  }
  // Add new arguments defined by Params.
  for (const ParamInfo &PI : Params) {
    assert(ParamIdx < ToFuncTy->getNumParams());
    Args.push_back(createCast(Builder, PI.Values[FuncIdx],
                   ToFuncTy->getParamType(ParamIdx)));
    ++ParamIdx;
  }

  CallInst *CI = Builder.CreateCall(ToFunc, Args);
  CI->setTailCall();
  CI->setCallingConv(ToFunc->getCallingConv());
  CI->setAttributes(ToFunc->getAttributes());
  if (Thunk->getReturnType()->isVoidTy()) {
    Builder.CreateRetVoid();
  } else {
    Builder.CreateRet(createCast(Builder, CI, Thunk->getReturnType()));
  }

  LLVM_DEBUG(dbgs() << "    writeThunk: " << Thunk->getName() << '\n');
  ++NumSwiftThunksWritten;
}
예제 #16
0
/// \brief Returns the allocation data for the given value if it is a call to a
/// known allocation function, and NULL otherwise.
static const AllocFnsTy *getAllocationData(const Value *V, AllocType AllocTy,
                                           bool LookThroughBitCast = false) {
  Function *Callee = getCalledFunction(V, LookThroughBitCast);
  if (!Callee)
    return 0;

  unsigned i = 0;
  bool found = false;
  for ( ; i < array_lengthof(AllocationFnData); ++i) {
    if (Callee->getName() == AllocationFnData[i].Name) {
      found = true;
      break;
    }
  }
  if (!found)
    return 0;

  const AllocFnsTy *FnData = &AllocationFnData[i];
  if ((FnData->AllocTy & AllocTy) == 0)
    return 0;

  // Check function prototype.
  // FIXME: Check the nobuiltin metadata?? (PR5130)
  int FstParam = FnData->FstParam;
  int SndParam = FnData->SndParam;
  FunctionType *FTy = Callee->getFunctionType();

  if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) &&
      FTy->getNumParams() == FnData->NumParams &&
      (FstParam < 0 ||
       (FTy->getParamType(FstParam)->isIntegerTy(32) ||
        FTy->getParamType(FstParam)->isIntegerTy(64))) &&
      (SndParam < 0 ||
       FTy->getParamType(SndParam)->isIntegerTy(32) ||
       FTy->getParamType(SndParam)->isIntegerTy(64)))
    return FnData;
  return 0;
}
예제 #17
0
// a simple function 'prototype' printer
void printFuncProtoType(Function *F)
{
  F->getReturnType()->dump();
  errs() << " " << F->getName() << "(";
  FunctionType * FTY = F->getFunctionType();
  unsigned params = FTY->getNumParams();
  unsigned i;
  for (i = 0; i < params; i++) {
    FTY->getParamType(i)->dump();
    if (i != params - 1)
      errs() << ",";
  }
  errs() << ")";
}
예제 #18
0
/// Returns the allocation data for the given value if it's either a call to a
/// known allocation function, or a call to a function with the allocsize
/// attribute.
static Optional<AllocFnsTy>
getAllocationDataForFunction(const Function *Callee, AllocType AllocTy,
                             const TargetLibraryInfo *TLI) {
  // Make sure that the function is available.
  StringRef FnName = Callee->getName();
  LibFunc TLIFn;
  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
    return None;

  const auto *Iter = find_if(
      AllocationFnData, [TLIFn](const std::pair<LibFunc, AllocFnsTy> &P) {
        return P.first == TLIFn;
      });

  if (Iter == std::end(AllocationFnData))
    return None;

  const AllocFnsTy *FnData = &Iter->second;
  if ((FnData->AllocTy & AllocTy) != FnData->AllocTy)
    return None;

  // Check function prototype.
  int FstParam = FnData->FstParam;
  int SndParam = FnData->SndParam;
  FunctionType *FTy = Callee->getFunctionType();

  if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) &&
      FTy->getNumParams() == FnData->NumParams &&
      (FstParam < 0 ||
       (FTy->getParamType(FstParam)->isIntegerTy(32) ||
        FTy->getParamType(FstParam)->isIntegerTy(64))) &&
      (SndParam < 0 ||
       FTy->getParamType(SndParam)->isIntegerTy(32) ||
       FTy->getParamType(SndParam)->isIntegerTy(64)))
    return *FnData;
  return None;
}
예제 #19
0
// Replace G with a simple tail call to bitcast(F). Also replace direct uses
// of G with bitcast(F). Deletes G.
void MergeFunctions::writeThunk(Function *F, Function *G) {
  if (!G->mayBeOverridden()) {
    // Redirect direct callers of G to F.
    replaceDirectCallers(G, F);
  }

  // If G was internal then we may have replaced all uses of G with F. If so,
  // stop here and delete G. There's no need for a thunk.
  if (G->hasLocalLinkage() && G->use_empty()) {
    G->eraseFromParent();
    return;
  }

  Function *NewG = Function::Create(G->getFunctionType(), G->getLinkage(), "",
                                    G->getParent());
  BasicBlock *BB = BasicBlock::Create(F->getContext(), "", NewG);
  IRBuilder<false> Builder(BB);

  SmallVector<Value *, 16> Args;
  unsigned i = 0;
  FunctionType *FFTy = F->getFunctionType();
  for (Function::arg_iterator AI = NewG->arg_begin(), AE = NewG->arg_end();
       AI != AE; ++AI) {
    Args.push_back(createCast(Builder, (Value*)AI, FFTy->getParamType(i)));
    ++i;
  }

  CallInst *CI = Builder.CreateCall(F, Args);
  CI->setTailCall();
  CI->setCallingConv(F->getCallingConv());
  if (NewG->getReturnType()->isVoidTy()) {
    Builder.CreateRetVoid();
  } else {
    Builder.CreateRet(createCast(Builder, CI, NewG->getReturnType()));
  }

  NewG->copyAttributesFrom(G);
  NewG->takeName(G);
  removeUsers(G);
  G->replaceAllUsesWith(NewG);
  G->eraseFromParent();

  DEBUG(dbgs() << "writeThunk: " << NewG->getName() << '\n');
  ++NumThunksWritten;
}
bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const DataLayout *TD,
                                     const TargetLibraryInfo *TLI) {
  // We really need DataLayout for later.
  if (!TD) return false;
  
  this->CI = CI;
  Function *Callee = CI->getCalledFunction();
  StringRef Name = Callee->getName();
  FunctionType *FT = Callee->getFunctionType();
  LLVMContext &Context = CI->getParent()->getContext();
  IRBuilder<> B(CI);

  if (Name == "__memcpy_chk") {
    // Check if this has the right signature.
    if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) ||
        !FT->getParamType(0)->isPointerTy() ||
        !FT->getParamType(1)->isPointerTy() ||
        FT->getParamType(2) != TD->getIntPtrType(Context) ||
        FT->getParamType(3) != TD->getIntPtrType(Context))
      return false;

    if (isFoldable(3, 2, false)) {
      B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1),
                     CI->getArgOperand(2), 1);
      replaceCall(CI->getArgOperand(0));
      return true;
    }
    return false;
  }

  // Should be similar to memcpy.
  if (Name == "__mempcpy_chk") {
    return false;
  }

  if (Name == "__memmove_chk") {
    // Check if this has the right signature.
    if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) ||
        !FT->getParamType(0)->isPointerTy() ||
        !FT->getParamType(1)->isPointerTy() ||
        FT->getParamType(2) != TD->getIntPtrType(Context) ||
        FT->getParamType(3) != TD->getIntPtrType(Context))
      return false;

    if (isFoldable(3, 2, false)) {
      B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1),
                      CI->getArgOperand(2), 1);
      replaceCall(CI->getArgOperand(0));
      return true;
    }
    return false;
  }

  if (Name == "__memset_chk") {
    // Check if this has the right signature.
    if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) ||
        !FT->getParamType(0)->isPointerTy() ||
        !FT->getParamType(1)->isIntegerTy() ||
        FT->getParamType(2) != TD->getIntPtrType(Context) ||
        FT->getParamType(3) != TD->getIntPtrType(Context))
      return false;

    if (isFoldable(3, 2, false)) {
      Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(),
                                   false);
      B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1);
      replaceCall(CI->getArgOperand(0));
      return true;
    }
    return false;
  }

  if (Name == "__strcpy_chk" || Name == "__stpcpy_chk") {
    // Check if this has the right signature.
    if (FT->getNumParams() != 3 ||
        FT->getReturnType() != FT->getParamType(0) ||
        FT->getParamType(0) != FT->getParamType(1) ||
        FT->getParamType(0) != Type::getInt8PtrTy(Context) ||
        FT->getParamType(2) != TD->getIntPtrType(Context))
      return 0;
    
    
    // If a) we don't have any length information, or b) we know this will
    // fit then just lower to a plain st[rp]cpy. Otherwise we'll keep our
    // st[rp]cpy_chk call which may fail at runtime if the size is too long.
    // TODO: It might be nice to get a maximum length out of the possible
    // string lengths for varying.
    if (isFoldable(2, 1, true)) {
      Value *Ret = EmitStrCpy(CI->getArgOperand(0), CI->getArgOperand(1), B, TD,
                              TLI, Name.substr(2, 6));
      if (!Ret)
        return false;
      replaceCall(Ret);
      return true;
    }
    return false;
  }

  if (Name == "__strncpy_chk" || Name == "__stpncpy_chk") {
    // Check if this has the right signature.
    if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) ||
        FT->getParamType(0) != FT->getParamType(1) ||
        FT->getParamType(0) != Type::getInt8PtrTy(Context) ||
        !FT->getParamType(2)->isIntegerTy() ||
        FT->getParamType(3) != TD->getIntPtrType(Context))
      return false;

    if (isFoldable(3, 2, false)) {
      Value *Ret = EmitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1),
                               CI->getArgOperand(2), B, TD, TLI,
                               Name.substr(2, 7));
      if (!Ret)
        return false;
      replaceCall(Ret);
      return true;
    }
    return false;
  }

  if (Name == "__strcat_chk") {
    return false;
  }

  if (Name == "__strncat_chk") {
    return false;
  }

  return false;
}
예제 #21
0
bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
                                                   LibFunc::Func F,
                                                   const DataLayout *DL) const {
  LLVMContext &Ctx = FTy.getContext();
  Type *PCharTy = Type::getInt8PtrTy(Ctx);
  Type *SizeTTy = DL ? DL->getIntPtrType(Ctx, /*AS=*/0) : nullptr;
  auto IsSizeTTy = [SizeTTy](Type *Ty) {
    return SizeTTy ? Ty == SizeTTy : Ty->isIntegerTy();
  };
  unsigned NumParams = FTy.getNumParams();

  switch (F) {
  case LibFunc::strlen:
    return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getReturnType()->isIntegerTy());

  case LibFunc::strchr:
  case LibFunc::strrchr:
    return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0) == FTy.getReturnType() &&
            FTy.getParamType(1)->isIntegerTy());

  case LibFunc::strtol:
  case LibFunc::strtod:
  case LibFunc::strtof:
  case LibFunc::strtoul:
  case LibFunc::strtoll:
  case LibFunc::strtold:
  case LibFunc::strtoull:
    return ((NumParams == 2 || NumParams == 3) &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::strcat:
    return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0) == FTy.getReturnType() &&
            FTy.getParamType(1) == FTy.getReturnType());

  case LibFunc::strncat:
    return (NumParams == 3 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0) == FTy.getReturnType() &&
            FTy.getParamType(1) == FTy.getReturnType() &&
            FTy.getParamType(2)->isIntegerTy());

  case LibFunc::strcpy_chk:
  case LibFunc::stpcpy_chk:
    --NumParams;
    if (!IsSizeTTy(FTy.getParamType(NumParams)))
      return false;
  // fallthrough
  case LibFunc::strcpy:
  case LibFunc::stpcpy:
    return (NumParams == 2 && FTy.getReturnType() == FTy.getParamType(0) &&
            FTy.getParamType(0) == FTy.getParamType(1) &&
            FTy.getParamType(0) == PCharTy);

  case LibFunc::strncpy_chk:
  case LibFunc::stpncpy_chk:
    --NumParams;
    if (!IsSizeTTy(FTy.getParamType(NumParams)))
      return false;
  // fallthrough
  case LibFunc::strncpy:
  case LibFunc::stpncpy:
    return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) &&
            FTy.getParamType(0) == FTy.getParamType(1) &&
            FTy.getParamType(0) == PCharTy &&
            FTy.getParamType(2)->isIntegerTy());

  case LibFunc::strxfrm:
    return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());

  case LibFunc::strcmp:
    return (NumParams == 2 && FTy.getReturnType()->isIntegerTy(32) &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(0) == FTy.getParamType(1));

  case LibFunc::strncmp:
    return (NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(0) == FTy.getParamType(1) &&
            FTy.getParamType(2)->isIntegerTy());

  case LibFunc::strspn:
  case LibFunc::strcspn:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(0) == FTy.getParamType(1) &&
            FTy.getReturnType()->isIntegerTy());

  case LibFunc::strcoll:
  case LibFunc::strcasecmp:
  case LibFunc::strncasecmp:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());

  case LibFunc::strstr:
    return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());

  case LibFunc::strpbrk:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getReturnType() == FTy.getParamType(0) &&
            FTy.getParamType(0) == FTy.getParamType(1));

  case LibFunc::strtok:
  case LibFunc::strtok_r:
    return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::scanf:
  case LibFunc::setbuf:
  case LibFunc::setvbuf:
    return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::strdup:
  case LibFunc::strndup:
    return (NumParams >= 1 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0)->isPointerTy());
  case LibFunc::sscanf:
  case LibFunc::stat:
  case LibFunc::statvfs:
  case LibFunc::sprintf:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::snprintf:
    return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(2)->isPointerTy());
  case LibFunc::setitimer:
    return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() &&
            FTy.getParamType(2)->isPointerTy());
  case LibFunc::system:
    return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::malloc:
    return (NumParams == 1 && FTy.getReturnType()->isPointerTy());
  case LibFunc::memcmp:
    return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy() &&
            FTy.getReturnType()->isIntegerTy(32));

  case LibFunc::memchr:
  case LibFunc::memrchr:
    return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isIntegerTy(32) &&
            FTy.getParamType(2)->isIntegerTy() &&
            FTy.getReturnType()->isPointerTy());
  case LibFunc::modf:
  case LibFunc::modff:
  case LibFunc::modfl:
    return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy());

  case LibFunc::memcpy_chk:
  case LibFunc::memmove_chk:
    --NumParams;
    if (!IsSizeTTy(FTy.getParamType(NumParams)))
      return false;
  // fallthrough
  case LibFunc::memcpy:
  case LibFunc::mempcpy:
  case LibFunc::memmove:
    return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy() &&
            IsSizeTTy(FTy.getParamType(2)));

  case LibFunc::memset_chk:
    --NumParams;
    if (!IsSizeTTy(FTy.getParamType(NumParams)))
      return false;
  // fallthrough
  case LibFunc::memset:
    return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isIntegerTy() &&
            IsSizeTTy(FTy.getParamType(2)));

  case LibFunc::memccpy:
    return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::memalign:
    return (FTy.getReturnType()->isPointerTy());
  case LibFunc::realloc:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getReturnType()->isPointerTy());
  case LibFunc::read:
    return (NumParams == 3 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::rewind:
  case LibFunc::rmdir:
  case LibFunc::remove:
  case LibFunc::realpath:
    return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::rename:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::readlink:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::write:
    return (NumParams == 3 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::bcopy:
  case LibFunc::bcmp:
    return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::bzero:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::calloc:
    return (NumParams == 2 && FTy.getReturnType()->isPointerTy());

  case LibFunc::atof:
  case LibFunc::atoi:
  case LibFunc::atol:
  case LibFunc::atoll:
  case LibFunc::ferror:
  case LibFunc::getenv:
  case LibFunc::getpwnam:
  case LibFunc::pclose:
  case LibFunc::perror:
  case LibFunc::printf:
  case LibFunc::puts:
  case LibFunc::uname:
  case LibFunc::under_IO_getc:
  case LibFunc::unlink:
  case LibFunc::unsetenv:
    return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());

  case LibFunc::chmod:
  case LibFunc::chown:
  case LibFunc::clearerr:
  case LibFunc::closedir:
  case LibFunc::ctermid:
  case LibFunc::fclose:
  case LibFunc::feof:
  case LibFunc::fflush:
  case LibFunc::fgetc:
  case LibFunc::fileno:
  case LibFunc::flockfile:
  case LibFunc::free:
  case LibFunc::fseek:
  case LibFunc::fseeko64:
  case LibFunc::fseeko:
  case LibFunc::fsetpos:
  case LibFunc::ftell:
  case LibFunc::ftello64:
  case LibFunc::ftello:
  case LibFunc::ftrylockfile:
  case LibFunc::funlockfile:
  case LibFunc::getc:
  case LibFunc::getc_unlocked:
  case LibFunc::getlogin_r:
  case LibFunc::mkdir:
  case LibFunc::mktime:
  case LibFunc::times:
    return (NumParams != 0 && FTy.getParamType(0)->isPointerTy());

  case LibFunc::access:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::fopen:
    return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::fdopen:
    return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::fputc:
  case LibFunc::fstat:
  case LibFunc::frexp:
  case LibFunc::frexpf:
  case LibFunc::frexpl:
  case LibFunc::fstatvfs:
    return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::fgets:
    return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(2)->isPointerTy());
  case LibFunc::fread:
    return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(3)->isPointerTy());
  case LibFunc::fwrite:
    return (NumParams == 4 && FTy.getReturnType()->isIntegerTy() &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isIntegerTy() &&
            FTy.getParamType(2)->isIntegerTy() &&
            FTy.getParamType(3)->isPointerTy());
  case LibFunc::fputs:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::fscanf:
  case LibFunc::fprintf:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::fgetpos:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::gets:
  case LibFunc::getchar:
  case LibFunc::getitimer:
    return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::ungetc:
    return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::utime:
  case LibFunc::utimes:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::putc:
    return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::pread:
  case LibFunc::pwrite:
    return (NumParams == 4 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::popen:
    return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::vscanf:
    return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::vsscanf:
    return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() &&
            FTy.getParamType(2)->isPointerTy());
  case LibFunc::vfscanf:
    return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() &&
            FTy.getParamType(2)->isPointerTy());
  case LibFunc::valloc:
    return (FTy.getReturnType()->isPointerTy());
  case LibFunc::vprintf:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::vfprintf:
  case LibFunc::vsprintf:
    return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::vsnprintf:
    return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(2)->isPointerTy());
  case LibFunc::open:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::opendir:
    return (NumParams == 1 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0)->isPointerTy());
  case LibFunc::tmpfile:
    return (FTy.getReturnType()->isPointerTy());
  case LibFunc::htonl:
  case LibFunc::htons:
  case LibFunc::ntohl:
  case LibFunc::ntohs:
  case LibFunc::lstat:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::lchown:
    return (NumParams == 3 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::qsort:
    return (NumParams == 4 && FTy.getParamType(3)->isPointerTy());
  case LibFunc::dunder_strdup:
  case LibFunc::dunder_strndup:
    return (NumParams >= 1 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0)->isPointerTy());
  case LibFunc::dunder_strtok_r:
    return (NumParams == 3 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::under_IO_putc:
    return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::dunder_isoc99_scanf:
    return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::stat64:
  case LibFunc::lstat64:
  case LibFunc::statvfs64:
    return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::dunder_isoc99_sscanf:
    return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::fopen64:
    return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());
  case LibFunc::tmpfile64:
    return (FTy.getReturnType()->isPointerTy());
  case LibFunc::fstat64:
  case LibFunc::fstatvfs64:
    return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
  case LibFunc::open64:
    return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy());
  case LibFunc::gettimeofday:
    return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy());

  case LibFunc::Znwj:                    // new(unsigned int);
  case LibFunc::Znwm:                    // new(unsigned long);
  case LibFunc::Znaj:                    // new[](unsigned int);
  case LibFunc::Znam:                    // new[](unsigned long);
  case LibFunc::msvc_new_int:            // new(unsigned int);
  case LibFunc::msvc_new_longlong:       // new(unsigned long long);
  case LibFunc::msvc_new_array_int:      // new[](unsigned int);
  case LibFunc::msvc_new_array_longlong: // new[](unsigned long long);
    return (NumParams == 1);

  case LibFunc::memset_pattern16:
    return (!FTy.isVarArg() && NumParams == 3 &&
            isa<PointerType>(FTy.getParamType(0)) &&
            isa<PointerType>(FTy.getParamType(1)) &&
            isa<IntegerType>(FTy.getParamType(2)));

  // int __nvvm_reflect(const char *);
  case LibFunc::nvvm_reflect:
    return (NumParams == 1 && isa<PointerType>(FTy.getParamType(0)));

  case LibFunc::sin:
  case LibFunc::sinf:
  case LibFunc::sinl:
  case LibFunc::cos:
  case LibFunc::cosf:
  case LibFunc::cosl:
  case LibFunc::tan:
  case LibFunc::tanf:
  case LibFunc::tanl:
  case LibFunc::exp:
  case LibFunc::expf:
  case LibFunc::expl:
  case LibFunc::exp2:
  case LibFunc::exp2f:
  case LibFunc::exp2l:
  case LibFunc::log:
  case LibFunc::logf:
  case LibFunc::logl:
  case LibFunc::log10:
  case LibFunc::log10f:
  case LibFunc::log10l:
  case LibFunc::log2:
  case LibFunc::log2f:
  case LibFunc::log2l:
  case LibFunc::fabs:
  case LibFunc::fabsf:
  case LibFunc::fabsl:
  case LibFunc::floor:
  case LibFunc::floorf:
  case LibFunc::floorl:
  case LibFunc::ceil:
  case LibFunc::ceilf:
  case LibFunc::ceill:
  case LibFunc::trunc:
  case LibFunc::truncf:
  case LibFunc::truncl:
  case LibFunc::rint:
  case LibFunc::rintf:
  case LibFunc::rintl:
  case LibFunc::nearbyint:
  case LibFunc::nearbyintf:
  case LibFunc::nearbyintl:
  case LibFunc::round:
  case LibFunc::roundf:
  case LibFunc::roundl:
  case LibFunc::sqrt:
  case LibFunc::sqrtf:
  case LibFunc::sqrtl:
    return (NumParams == 1 && FTy.getReturnType()->isFloatingPointTy() &&
            FTy.getReturnType() == FTy.getParamType(0));

  case LibFunc::fmin:
  case LibFunc::fminf:
  case LibFunc::fminl:
  case LibFunc::fmax:
  case LibFunc::fmaxf:
  case LibFunc::fmaxl:
  case LibFunc::copysign:
  case LibFunc::copysignf:
  case LibFunc::copysignl:
  case LibFunc::pow:
  case LibFunc::powf:
  case LibFunc::powl:
    return (NumParams == 2 && FTy.getReturnType()->isFloatingPointTy() &&
            FTy.getReturnType() == FTy.getParamType(0) &&
            FTy.getReturnType() == FTy.getParamType(1));

  case LibFunc::ffs:
  case LibFunc::ffsl:
  case LibFunc::ffsll:
  case LibFunc::isdigit:
  case LibFunc::isascii:
  case LibFunc::toascii:
    return (NumParams == 1 && FTy.getReturnType()->isIntegerTy(32) &&
            FTy.getParamType(0)->isIntegerTy());

  case LibFunc::fls:
  case LibFunc::flsl:
  case LibFunc::flsll:
  case LibFunc::abs:
  case LibFunc::labs:
  case LibFunc::llabs:
    return (NumParams == 1 && FTy.getReturnType()->isIntegerTy() &&
            FTy.getReturnType() == FTy.getParamType(0));

  case LibFunc::cxa_atexit:
    return (NumParams == 3 && FTy.getReturnType()->isIntegerTy() &&
            FTy.getParamType(0)->isPointerTy() &&
            FTy.getParamType(1)->isPointerTy() &&
            FTy.getParamType(2)->isPointerTy());

  case LibFunc::sinpi:
  case LibFunc::cospi:
    return (NumParams == 1 && FTy.getReturnType()->isDoubleTy() &&
            FTy.getReturnType() == FTy.getParamType(0));

  case LibFunc::sinpif:
  case LibFunc::cospif:
    return (NumParams == 1 && FTy.getReturnType()->isFloatTy() &&
            FTy.getReturnType() == FTy.getParamType(0));

  default:
    // Assume the other functions are correct.
    // FIXME: It'd be really nice to cover them all.
    return true;
  }
}
bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
  LLVMContext &C = M.getContext();
  IRBuilder<> IRB(C);

  Function *SetjmpF = M.getFunction("setjmp");
  Function *LongjmpF = M.getFunction("longjmp");
  bool SetjmpUsed = SetjmpF && !SetjmpF->use_empty();
  bool LongjmpUsed = LongjmpF && !LongjmpF->use_empty();
  bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed);

  // Create global variables __THREW__, threwValue, and __tempRet0, which are
  // used in common for both exception handling and setjmp/longjmp handling
  ThrewGV = createGlobalVariableI32(M, IRB, "__THREW__");
  ThrewValueGV = createGlobalVariableI32(M, IRB, "__threwValue");
  TempRet0GV = createGlobalVariableI32(M, IRB, "__tempRet0");

  bool Changed = false;

  // Exception handling
  if (EnableEH) {
    // Register __resumeException function
    FunctionType *ResumeFTy =
        FunctionType::get(IRB.getVoidTy(), IRB.getInt8PtrTy(), false);
    ResumeF = Function::Create(ResumeFTy, GlobalValue::ExternalLinkage,
                               ResumeFName, &M);

    // Register llvm_eh_typeid_for function
    FunctionType *EHTypeIDTy =
        FunctionType::get(IRB.getInt32Ty(), IRB.getInt8PtrTy(), false);
    EHTypeIDF = Function::Create(EHTypeIDTy, GlobalValue::ExternalLinkage,
                                 EHTypeIDFName, &M);

    for (Function &F : M) {
      if (F.isDeclaration())
        continue;
      Changed |= runEHOnFunction(F);
    }
  }

  // Setjmp/longjmp handling
  if (DoSjLj) {
    Changed = true; // We have setjmp or longjmp somewhere

    // Register saveSetjmp function
    FunctionType *SetjmpFTy = SetjmpF->getFunctionType();
    SmallVector<Type *, 4> Params = {SetjmpFTy->getParamType(0),
                                     IRB.getInt32Ty(), Type::getInt32PtrTy(C),
                                     IRB.getInt32Ty()};
    FunctionType *FTy =
        FunctionType::get(Type::getInt32PtrTy(C), Params, false);
    SaveSetjmpF = Function::Create(FTy, GlobalValue::ExternalLinkage,
                                   SaveSetjmpFName, &M);

    // Register testSetjmp function
    Params = {IRB.getInt32Ty(), Type::getInt32PtrTy(C), IRB.getInt32Ty()};
    FTy = FunctionType::get(IRB.getInt32Ty(), Params, false);
    TestSetjmpF = Function::Create(FTy, GlobalValue::ExternalLinkage,
                                   TestSetjmpFName, &M);

    if (LongjmpF) {
      // Replace all uses of longjmp with emscripten_longjmp_jmpbuf, which is
      // defined in JS code
      EmLongjmpJmpbufF = Function::Create(LongjmpF->getFunctionType(),
                                          GlobalValue::ExternalLinkage,
                                          EmLongjmpJmpbufFName, &M);

      LongjmpF->replaceAllUsesWith(EmLongjmpJmpbufF);
    }
    FTy = FunctionType::get(IRB.getVoidTy(),
                            {IRB.getInt32Ty(), IRB.getInt32Ty()}, false);
    EmLongjmpF =
        Function::Create(FTy, GlobalValue::ExternalLinkage, EmLongjmpFName, &M);

    // Only traverse functions that uses setjmp in order not to insert
    // unnecessary prep / cleanup code in every function
    SmallPtrSet<Function *, 8> SetjmpUsers;
    for (User *U : SetjmpF->users()) {
      auto *UI = cast<Instruction>(U);
      SetjmpUsers.insert(UI->getFunction());
    }
    for (Function *F : SetjmpUsers)
      runSjLjOnFunction(*F);
  }

  if (!Changed) {
    // Delete unused global variables and functions
    ThrewGV->eraseFromParent();
    ThrewValueGV->eraseFromParent();
    TempRet0GV->eraseFromParent();
    if (ResumeF)
      ResumeF->eraseFromParent();
    if (EHTypeIDF)
      EHTypeIDF->eraseFromParent();
    if (EmLongjmpF)
      EmLongjmpF->eraseFromParent();
    if (SaveSetjmpF)
      SaveSetjmpF->eraseFromParent();
    if (TestSetjmpF)
      TestSetjmpF->eraseFromParent();
    return false;
  }

  // If we have made any changes while doing exception handling or
  // setjmp/longjmp handling, we have to create these functions for JavaScript
  // to call.
  createSetThrewFunction(M);
  createSetTempRet0Function(M);

  return true;
}
예제 #23
0
/// cmpType - compares two types,
/// defines total ordering among the types set.
/// See method declaration comments for more details.
int FunctionComparator::cmpType(Type *TyL, Type *TyR) const {

  PointerType *PTyL = dyn_cast<PointerType>(TyL);
  PointerType *PTyR = dyn_cast<PointerType>(TyR);

  if (DL) {
    if (PTyL && PTyL->getAddressSpace() == 0) TyL = DL->getIntPtrType(TyL);
    if (PTyR && PTyR->getAddressSpace() == 0) TyR = DL->getIntPtrType(TyR);
  }

  if (TyL == TyR)
    return 0;

  if (int Res = cmpNumbers(TyL->getTypeID(), TyR->getTypeID()))
    return Res;

  switch (TyL->getTypeID()) {
  default:
    llvm_unreachable("Unknown type!");
    // Fall through in Release mode.
  case Type::IntegerTyID:
  case Type::VectorTyID:
    // TyL == TyR would have returned true earlier.
    return cmpNumbers((uint64_t)TyL, (uint64_t)TyR);

  case Type::VoidTyID:
  case Type::FloatTyID:
  case Type::DoubleTyID:
  case Type::X86_FP80TyID:
  case Type::FP128TyID:
  case Type::PPC_FP128TyID:
  case Type::LabelTyID:
  case Type::MetadataTyID:
    return 0;

  case Type::PointerTyID: {
    assert(PTyL && PTyR && "Both types must be pointers here.");
    return cmpNumbers(PTyL->getAddressSpace(), PTyR->getAddressSpace());
  }

  case Type::StructTyID: {
    StructType *STyL = cast<StructType>(TyL);
    StructType *STyR = cast<StructType>(TyR);
    if (STyL->getNumElements() != STyR->getNumElements())
      return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());

    if (STyL->isPacked() != STyR->isPacked())
      return cmpNumbers(STyL->isPacked(), STyR->isPacked());

    for (unsigned i = 0, e = STyL->getNumElements(); i != e; ++i) {
      if (int Res = cmpType(STyL->getElementType(i),
                            STyR->getElementType(i)))
        return Res;
    }
    return 0;
  }

  case Type::FunctionTyID: {
    FunctionType *FTyL = cast<FunctionType>(TyL);
    FunctionType *FTyR = cast<FunctionType>(TyR);
    if (FTyL->getNumParams() != FTyR->getNumParams())
      return cmpNumbers(FTyL->getNumParams(), FTyR->getNumParams());

    if (FTyL->isVarArg() != FTyR->isVarArg())
      return cmpNumbers(FTyL->isVarArg(), FTyR->isVarArg());

    if (int Res = cmpType(FTyL->getReturnType(), FTyR->getReturnType()))
      return Res;

    for (unsigned i = 0, e = FTyL->getNumParams(); i != e; ++i) {
      if (int Res = cmpType(FTyL->getParamType(i), FTyR->getParamType(i)))
        return Res;
    }
    return 0;
  }

  case Type::ArrayTyID: {
    ArrayType *ATyL = cast<ArrayType>(TyL);
    ArrayType *ATyR = cast<ArrayType>(TyR);
    if (ATyL->getNumElements() != ATyR->getNumElements())
      return cmpNumbers(ATyL->getNumElements(), ATyR->getNumElements());
    return cmpType(ATyL->getElementType(), ATyR->getElementType());
  }
  }
}
예제 #24
0
/// cmpType - compares two types,
/// defines total ordering among the types set.
/// See method declaration comments for more details.
int FunctionComparator::cmpTypes(Type *TyL, Type *TyR) const {
  PointerType *PTyL = dyn_cast<PointerType>(TyL);
  PointerType *PTyR = dyn_cast<PointerType>(TyR);

  const DataLayout &DL = FnL->getParent()->getDataLayout();
  if (PTyL && PTyL->getAddressSpace() == 0)
    TyL = DL.getIntPtrType(TyL);
  if (PTyR && PTyR->getAddressSpace() == 0)
    TyR = DL.getIntPtrType(TyR);

  if (TyL == TyR)
    return 0;

  if (int Res = cmpNumbers(TyL->getTypeID(), TyR->getTypeID()))
    return Res;

  switch (TyL->getTypeID()) {
  default:
    llvm_unreachable("Unknown type!");
    // Fall through in Release mode.
    LLVM_FALLTHROUGH;
  case Type::IntegerTyID:
    return cmpNumbers(cast<IntegerType>(TyL)->getBitWidth(),
                      cast<IntegerType>(TyR)->getBitWidth());
  // TyL == TyR would have returned true earlier, because types are uniqued.
  case Type::VoidTyID:
  case Type::FloatTyID:
  case Type::DoubleTyID:
  case Type::X86_FP80TyID:
  case Type::FP128TyID:
  case Type::PPC_FP128TyID:
  case Type::LabelTyID:
  case Type::MetadataTyID:
  case Type::TokenTyID:
    return 0;

  case Type::PointerTyID: {
    assert(PTyL && PTyR && "Both types must be pointers here.");
    return cmpNumbers(PTyL->getAddressSpace(), PTyR->getAddressSpace());
  }

  case Type::StructTyID: {
    StructType *STyL = cast<StructType>(TyL);
    StructType *STyR = cast<StructType>(TyR);
    if (STyL->getNumElements() != STyR->getNumElements())
      return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());

    if (STyL->isPacked() != STyR->isPacked())
      return cmpNumbers(STyL->isPacked(), STyR->isPacked());

    for (unsigned i = 0, e = STyL->getNumElements(); i != e; ++i) {
      if (int Res = cmpTypes(STyL->getElementType(i), STyR->getElementType(i)))
        return Res;
    }
    return 0;
  }

  case Type::FunctionTyID: {
    FunctionType *FTyL = cast<FunctionType>(TyL);
    FunctionType *FTyR = cast<FunctionType>(TyR);
    if (FTyL->getNumParams() != FTyR->getNumParams())
      return cmpNumbers(FTyL->getNumParams(), FTyR->getNumParams());

    if (FTyL->isVarArg() != FTyR->isVarArg())
      return cmpNumbers(FTyL->isVarArg(), FTyR->isVarArg());

    if (int Res = cmpTypes(FTyL->getReturnType(), FTyR->getReturnType()))
      return Res;

    for (unsigned i = 0, e = FTyL->getNumParams(); i != e; ++i) {
      if (int Res = cmpTypes(FTyL->getParamType(i), FTyR->getParamType(i)))
        return Res;
    }
    return 0;
  }

  case Type::ArrayTyID:
  case Type::VectorTyID: {
    auto *STyL = cast<SequentialType>(TyL);
    auto *STyR = cast<SequentialType>(TyR);
    if (STyL->getNumElements() != STyR->getNumElements())
      return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
    return cmpTypes(STyL->getElementType(), STyR->getElementType());
  }
  }
}
예제 #25
0
GenericValue MCJIT::runFunction(Function *F,
                                const std::vector<GenericValue> &ArgValues) {
  assert(F && "Function *F was null at entry to run()");

  void *FPtr = getPointerToFunction(F);
  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
  FunctionType *FTy = F->getFunctionType();
  Type *RetTy = FTy->getReturnType();

  assert((FTy->getNumParams() == ArgValues.size() ||
          (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
         "Wrong number of arguments passed into function!");
  assert(FTy->getNumParams() == ArgValues.size() &&
         "This doesn't support passing arguments through varargs (yet)!");

  // Handle some common cases first.  These cases correspond to common `main'
  // prototypes.
  if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
    switch (ArgValues.size()) {
    case 3:
      if (FTy->getParamType(0)->isIntegerTy(32) &&
          FTy->getParamType(1)->isPointerTy() &&
          FTy->getParamType(2)->isPointerTy()) {
        int (*PF)(int, char **, const char **) =
          (int(*)(int, char **, const char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                 (char **)GVTOP(ArgValues[1]),
                                 (const char **)GVTOP(ArgValues[2])));
        return rv;
      }
      break;
    case 2:
      if (FTy->getParamType(0)->isIntegerTy(32) &&
          FTy->getParamType(1)->isPointerTy()) {
        int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                 (char **)GVTOP(ArgValues[1])));
        return rv;
      }
      break;
    case 1:
      if (FTy->getNumParams() == 1 &&
          FTy->getParamType(0)->isIntegerTy(32)) {
        GenericValue rv;
        int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
        return rv;
      }
      break;
    }
  }

  // Handle cases where no arguments are passed first.
  if (ArgValues.empty()) {
    GenericValue rv;
    switch (RetTy->getTypeID()) {
    default: llvm_unreachable("Unknown return type for function call!");
    case Type::IntegerTyID: {
      unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
      if (BitWidth == 1)
        rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 8)
        rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 16)
        rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 32)
        rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 64)
        rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
      else
        llvm_unreachable("Integer types > 64 bits not supported");
      return rv;
    }
    case Type::VoidTyID:
      rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
      return rv;
    case Type::FloatTyID:
      rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
      return rv;
    case Type::DoubleTyID:
      rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
      return rv;
    case Type::X86_FP80TyID:
    case Type::FP128TyID:
    case Type::PPC_FP128TyID:
      llvm_unreachable("long double not supported yet");
    case Type::PointerTyID:
      return PTOGV(((void*(*)())(intptr_t)FPtr)());
    }
  }

  llvm_unreachable("Full-featured argument passing not supported yet!");
}
예제 #26
0
/// PromotePrivates Implementation - Used to promote pointers from new/delete operations to global segment in HSA
///
bool PromotePrivates::runOnFunction(Function &F) {
  if (F.getName().find("cxxamp_trampoline") == StringRef::npos)
    return false;

  // Need refactor!
  Module *M = F.getParent();
  if ((M->getFunction(/*"_Znwj"*/ "_Znwm") == NULL) && (M->getFunction(/*"_Znaj"*/ "_Znam") == NULL))
    return false;

  //errs() << "Execute PromotePrivates::runOnFunction: " << F.getName() << "\n";

  LLVMContext& C = F.getContext();
  std::vector<Instruction*> NeedPromoted;

  for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
    NewedMemoryAnalyzer NMA(F);
    NMA.analyze(*I);
    
    if (NMA.isNewed())
      NeedPromoted.push_back(&*I);
  }

#if 0
  for (unsigned i = 0; i < NeedPromoted.size(); i++)
    errs () << *NeedPromoted[i] << "\n";
#endif

  while (!NeedPromoted.empty()) {
    Instruction *I = NeedPromoted.back();

#if 0
    llvm::errs() << "NeedPromoted:" << *I << "\n";
#endif

    if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
      IRBuilder<> Builder(SI);
      //Value *StoreAddr = Builder.CreatePointerCast(SI->getPointerOperand(), Type::getInt64PtrTy(C, 1));
      PointerType *DestTy = SI->getPointerOperand()->getType()->getPointerElementType()->getPointerTo(1);
      Value *StoreAddr = Builder.CreatePointerCast(SI->getPointerOperand(), DestTy);
      StoreInst* nSI = new StoreInst(SI->getValueOperand(), StoreAddr);

      ReplaceInstWithInst(SI, nSI);
    }

    if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
      IRBuilder<> Builder(LI);
      Value *LoadAddr = Builder.CreatePointerCast(LI->getPointerOperand(), Type::getInt32PtrTy(C, 1));
      LoadInst* nLI = new LoadInst(LoadAddr);

      ReplaceInstWithInst(LI, nLI);
    }

    if (CallInst *CI = dyn_cast<CallInst>(I)) {
      IRBuilder<> Builder(CI);

      PointerType *DestTy = CI->getArgOperand(0)->getType()->getPointerElementType()->getPointerTo(1);
      Value *MemsetAddr = Builder.CreatePointerCast(CI->getArgOperand(0), DestTy);
      std::vector<Value*> ArgsVec;
      ArgsVec.push_back(MemsetAddr);
      for (int i = 1, e = CI->getNumArgOperands(); i < e; i++) {
        ArgsVec.push_back(CI->getArgOperand(i));
      }
      ArrayRef<Value*> Args(ArgsVec);

      FunctionType *MemsetFuncType = CI->getCalledFunction()->getFunctionType();
      Type *MemsetRetType = MemsetFuncType->getReturnType();
      std::vector<Type*> ArgsTypeVec;
      ArgsTypeVec.push_back(DestTy);
      for (int i = 1, e = MemsetFuncType->getNumParams(); i < e; i++) {
        ArgsTypeVec.push_back(MemsetFuncType->getParamType(i));
      }
      ArrayRef<Type*> ArgsType(ArgsTypeVec);  
      FunctionType *nMemsetFuncType = FunctionType::get(MemsetRetType, ArgsType, false);
      M->getOrInsertFunction("llvm.memset.p1i8.i64", nMemsetFuncType);
      Function *MemsetFunc = M->getFunction("llvm.memset.p1i8.i64");

      CallInst* nCI = CallInst::Create(MemsetFunc, Args);

      ReplaceInstWithInst(CI, nCI);
    }

#if 0
    if (StoreInst *SI = dyn_cast<StoreInst>(NeedPromoted.back()) ) {
    IRBuilder<> Builder(SI);
    Value *StoreAddr = Builder.CreatePointerCast(SI->getPointerOperand(), Type::getInt32PtrTy(C, 1));
    StoreInst* nSI = new StoreInst(SI->getValueOperand(), StoreAddr);
    ReplaceInstWithInst(SI, nSI);
    }
    else if (LoadInst *LI = dyn_cast<LoadInst>(NeedPromoted.back()) ) {
    IRBuilder<> Builder(LI);
    Value *StoreAddr = Builder.CreatePointerCast(LI->getPointerOperand(), Type::getInt32PtrTy(C, 1));
    LoadInst* nLI = new LoadInst(/*SI->getValueOperand(), */StoreAddr);
    ReplaceInstWithInst(LI, nLI);
    }
#endif

    NeedPromoted.pop_back();
  }

  //F.dump();
  //errs() << "Finished PromotePrivates::runOnFunction\n";

  return true;
}
예제 #27
0
// =============================================================================
// andOOPIsGone (formerly: createProcess)
// 
// Formerly, OOP permitted the same SC_{METHOD,THREAD} functions to apply
// to each copy of a SC_MODULE. Aaaaand it's gone !
// (but OTOH we enable better optimizations)
// Creates a new C-style function that calls the old member function with the
// given sc_module. The call is then inlined.
// FIXME: assumes the method is non-virtual and that sc_module is the first
//        inherited class of the SC_MODULE
// =============================================================================
Function *TwetoPassImpl::andOOPIsGone(Function * oldProc,
				      sc_core::sc_module * initiatorMod)
{
	if (!oldProc)
		return NULL;

	// can't statically optimize if the address of the module isn't predictible
	// TODO: also handle already-static variables, which also have
	// fixed $pc-relative addresses
	if (staticopt == optlevel && !permalloc::is_from (initiatorMod))
		return NULL;

	LLVMContext & context = getGlobalContext();

	FunctionType *funType = oldProc->getFunctionType();
	Type *type = funType->getParamType(0);

	FunctionType *newProcType =
	    FunctionType::get(oldProc->getReturnType(),
			      ArrayRef < Type * >(), false);

	// Create the new function
	std::ostringstream id;
	id << proc_counter++;
	std::string name =
	    oldProc->getName().str() + std::string("_clone_") + id.str();
	Function *newProc =
	    Function::Create(newProcType, Function::ExternalLinkage, name,
			     this->llvmMod);
	assert(newProc->empty());
	newProc->addFnAttr(Attribute::InlineHint);

	// Create call to old function
	BasicBlock *bb = BasicBlock::Create(context, "entry", newProc);
	IRBuilder <> *irb = new IRBuilder <> (context);
	irb->SetInsertPoint(bb);

	Value* thisAddr = createRelocatablePointer (type, initiatorMod, irb);

	CallInst *ci = irb->CreateCall(oldProc,
				       ArrayRef < Value * >(std::vector<Value*>(1,thisAddr)));
	//bb->getInstList().insert(ci, thisAddr);
	if (ci->getType()->isVoidTy())
		irb->CreateRetVoid();
	else
		irb->CreateRet(ci);

	// The function should be valid now
	verifyFunction(*newProc);

	{			// Inline the call
		DataLayout *td = new DataLayout(this->llvmMod);
		InlineFunctionInfo i(NULL, td);
		bool success = InlineFunction(ci, i);
		assert(success);
		verifyFunction(*newProc);
	}

	// further optimize the function
	inlineBasicIO (initiatorMod, newProc);

	newProc->dump();
	return newProc;
}
예제 #28
0
// FIXME: This might have been relevant for the old JIT but the MCJIT
// has a completly different implementation so this comment below is
// likely irrelevant and misleading.
//
// For performance purposes we construct the stub in such a way that the
// arguments pointer is passed through the static global variable gTheArgsP in
// this file. This is done so that the stub function prototype trivially matches
// the special cases that the JIT knows how to directly call. If this is not
// done, then the jit will end up generating a nullary stub just to call our
// stub, for every single function call.
Function *ExternalDispatcherImpl::createDispatcher(Function *target,
                                                   Instruction *inst,
                                                   Module *module) {
  if (!resolveSymbol(target->getName()))
    return 0;

  CallSite cs;
  if (inst->getOpcode() == Instruction::Call) {
    cs = CallSite(cast<CallInst>(inst));
  } else {
    cs = CallSite(cast<InvokeInst>(inst));
  }

  Value **args = new Value *[cs.arg_size()];

  std::vector<Type *> nullary;

  // MCJIT functions need unique names, or wrong function can be called.
  // The module identifier is included because for the MCJIT we need
  // unique function names across all `llvm::Modules`s.
  std::string fnName =
      "dispatcher_" + target->getName().str() + module->getModuleIdentifier();
  Function *dispatcher =
      Function::Create(FunctionType::get(Type::getVoidTy(ctx), nullary, false),
                       GlobalVariable::ExternalLinkage, fnName, module);

  BasicBlock *dBB = BasicBlock::Create(ctx, "entry", dispatcher);

  // Get a Value* for &gTheArgsP, as an i64**.
  Instruction *argI64sp = new IntToPtrInst(
      ConstantInt::get(Type::getInt64Ty(ctx), (uintptr_t)(void *)&gTheArgsP),
      PointerType::getUnqual(PointerType::getUnqual(Type::getInt64Ty(ctx))),
      "argsp", dBB);
  Instruction *argI64s = new LoadInst(argI64sp, "args", dBB);

  // Get the target function type.
  FunctionType *FTy = cast<FunctionType>(
      cast<PointerType>(target->getType())->getElementType());

  // Each argument will be passed by writing it into gTheArgsP[i].
  unsigned i = 0, idx = 2;
  for (CallSite::arg_iterator ai = cs.arg_begin(), ae = cs.arg_end(); ai != ae;
       ++ai, ++i) {
    // Determine the type the argument will be passed as. This accomodates for
    // the corresponding code in Executor.cpp for handling calls to bitcasted
    // functions.
    Type *argTy =
        (i < FTy->getNumParams() ? FTy->getParamType(i) : (*ai)->getType());
    Instruction *argI64p = GetElementPtrInst::Create(
        KLEE_LLVM_GEP_TYPE(nullptr)
        argI64s, ConstantInt::get(Type::getInt32Ty(ctx), idx), "", dBB);

    Instruction *argp =
        new BitCastInst(argI64p, PointerType::getUnqual(argTy), "", dBB);
    args[i] = new LoadInst(argp, "", dBB);

    unsigned argSize = argTy->getPrimitiveSizeInBits();
    idx += ((!!argSize ? argSize : 64) + 63) / 64;
  }

  Constant *dispatchTarget = module->getOrInsertFunction(
      target->getName(), FTy, target->getAttributes());
  Instruction *result = CallInst::Create(
      dispatchTarget, llvm::ArrayRef<Value *>(args, args + i), "", dBB);
  if (result->getType() != Type::getVoidTy(ctx)) {
    Instruction *resp = new BitCastInst(
        argI64s, PointerType::getUnqual(result->getType()), "", dBB);
    new StoreInst(result, resp, dBB);
  }

  ReturnInst::Create(ctx, dBB);

  delete[] args;

  return dispatcher;
}
예제 #29
0
파일: JIT.cpp 프로젝트: agheorghiu/root
/// run - Start execution with the specified function and arguments.
///
GenericValue JIT::runFunction(Function *F,
                              const std::vector<GenericValue> &ArgValues) {
  assert(F && "Function *F was null at entry to run()");

  void *FPtr = getPointerToFunction(F);
  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
  FunctionType *FTy = F->getFunctionType();
  Type *RetTy = FTy->getReturnType();

  assert((FTy->getNumParams() == ArgValues.size() ||
          (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
         "Wrong number of arguments passed into function!");
  assert(FTy->getNumParams() == ArgValues.size() &&
         "This doesn't support passing arguments through varargs (yet)!");

  // Handle some common cases first.  These cases correspond to common `main'
  // prototypes.
  if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
    switch (ArgValues.size()) {
    case 3:
      if (FTy->getParamType(0)->isIntegerTy(32) &&
          FTy->getParamType(1)->isPointerTy() &&
          FTy->getParamType(2)->isPointerTy()) {
        int (*PF)(int, char **, const char **) =
          (int(*)(int, char **, const char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                 (char **)GVTOP(ArgValues[1]),
                                 (const char **)GVTOP(ArgValues[2])));
        return rv;
      }
      break;
    case 2:
      if (FTy->getParamType(0)->isIntegerTy(32) &&
          FTy->getParamType(1)->isPointerTy()) {
        int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;

        // Call the function.
        GenericValue rv;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
                                 (char **)GVTOP(ArgValues[1])));
        return rv;
      }
      break;
    case 1:
      if (FTy->getParamType(0)->isIntegerTy(32)) {
        GenericValue rv;
        int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
        return rv;
      }
      if (FTy->getParamType(0)->isPointerTy()) {
        GenericValue rv;
        int (*PF)(char *) = (int(*)(char *))(intptr_t)FPtr;
        rv.IntVal = APInt(32, PF((char*)GVTOP(ArgValues[0])));
        return rv;
      }
      break;
    }
  }

  // Handle cases where no arguments are passed first.
  if (ArgValues.empty()) {
    GenericValue rv;
    switch (RetTy->getTypeID()) {
    default: llvm_unreachable("Unknown return type for function call!");
    case Type::IntegerTyID: {
      unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
      if (BitWidth == 1)
        rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 8)
        rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 16)
        rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 32)
        rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
      else if (BitWidth <= 64)
        rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
      else
        llvm_unreachable("Integer types > 64 bits not supported");
      return rv;
    }
    case Type::VoidTyID:
      rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
      return rv;
    case Type::FloatTyID:
      rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
      return rv;
    case Type::DoubleTyID:
      rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
      return rv;
    case Type::X86_FP80TyID:
    case Type::FP128TyID:
    case Type::PPC_FP128TyID:
      llvm_unreachable("long double not supported yet");
    case Type::PointerTyID:
      return PTOGV(((void*(*)())(intptr_t)FPtr)());
    }
  }

  // Okay, this is not one of our quick and easy cases.  Because we don't have a
  // full FFI, we have to codegen a nullary stub function that just calls the
  // function we are interested in, passing in constants for all of the
  // arguments.  Make this function and return.

  // First, create the function.
  FunctionType *STy=FunctionType::get(RetTy, false);
  Function *Stub = Function::Create(STy, Function::InternalLinkage, "",
                                    F->getParent());

  // Insert a basic block.
  BasicBlock *StubBB = BasicBlock::Create(F->getContext(), "", Stub);

  // Convert all of the GenericValue arguments over to constants.  Note that we
  // currently don't support varargs.
  SmallVector<Value*, 8> Args;
  for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) {
    Constant *C = 0;
    Type *ArgTy = FTy->getParamType(i);
    const GenericValue &AV = ArgValues[i];
    switch (ArgTy->getTypeID()) {
    default: llvm_unreachable("Unknown argument type for function call!");
    case Type::IntegerTyID:
        C = ConstantInt::get(F->getContext(), AV.IntVal);
        break;
    case Type::FloatTyID:
        C = ConstantFP::get(F->getContext(), APFloat(AV.FloatVal));
        break;
    case Type::DoubleTyID:
        C = ConstantFP::get(F->getContext(), APFloat(AV.DoubleVal));
        break;
    case Type::PPC_FP128TyID:
    case Type::X86_FP80TyID:
    case Type::FP128TyID:
        C = ConstantFP::get(F->getContext(), APFloat(ArgTy->getFltSemantics(),
                                                     AV.IntVal));
        break;
    case Type::PointerTyID:
      void *ArgPtr = GVTOP(AV);
      if (sizeof(void*) == 4)
        C = ConstantInt::get(Type::getInt32Ty(F->getContext()),
                             (int)(intptr_t)ArgPtr);
      else
        C = ConstantInt::get(Type::getInt64Ty(F->getContext()),
                             (intptr_t)ArgPtr);
      // Cast the integer to pointer
      C = ConstantExpr::getIntToPtr(C, ArgTy);
      break;
    }
    Args.push_back(C);
  }

  CallInst *TheCall = CallInst::Create(F, Args, "", StubBB);
  TheCall->setCallingConv(F->getCallingConv());
  TheCall->setTailCall();
  if (!TheCall->getType()->isVoidTy())
    // Return result of the call.
    ReturnInst::Create(F->getContext(), TheCall, StubBB);
  else
    ReturnInst::Create(F->getContext(), StubBB);           // Just return void.

  // Finally, call our nullary stub function.
  GenericValue Result = runFunction(Stub, std::vector<GenericValue>());
  // Erase it, since no other function can have a reference to it.
  Stub->eraseFromParent();
  // And return the result.
  return Result;
}
예제 #30
0
static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
                      const DataLayout &TD, GenericValue &Result) {
  ffi_cif cif;
  FunctionType *FTy = F->getFunctionType();
  const unsigned NumArgs = F->arg_size();

  // TODO: We don't have type information about the remaining arguments, because
  // this information is never passed into ExecutionEngine::runFunction().
  if (ArgVals.size() > NumArgs && F->isVarArg()) {
    report_fatal_error("Calling external var arg function '" + F->getName()
                      + "' is not supported by the Interpreter.");
  }

  unsigned ArgBytes = 0;

  std::vector<ffi_type*> args(NumArgs);
  for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
       A != E; ++A) {
    const unsigned ArgNo = A->getArgNo();
    Type *ArgTy = FTy->getParamType(ArgNo);
    args[ArgNo] = ffiTypeFor(ArgTy);
    ArgBytes += TD.getTypeStoreSize(ArgTy);
  }

  SmallVector<uint8_t, 128> ArgData;
  ArgData.resize(ArgBytes);
  uint8_t *ArgDataPtr = ArgData.data();
  SmallVector<void*, 16> values(NumArgs);
  for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
       A != E; ++A) {
    const unsigned ArgNo = A->getArgNo();
    Type *ArgTy = FTy->getParamType(ArgNo);
    values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
    ArgDataPtr += TD.getTypeStoreSize(ArgTy);
  }

  Type *RetTy = FTy->getReturnType();
  ffi_type *rtype = ffiTypeFor(RetTy);

  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
      FFI_OK) {
    SmallVector<uint8_t, 128> ret;
    if (RetTy->getTypeID() != Type::VoidTyID)
      ret.resize(TD.getTypeStoreSize(RetTy));
    ffi_call(&cif, Fn, ret.data(), values.data());
    switch (RetTy->getTypeID()) {
      case Type::IntegerTyID:
        switch (cast<IntegerType>(RetTy)->getBitWidth()) {
          case 8:  Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
          case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
          case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
          case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
        }
        break;
      case Type::FloatTyID:   Result.FloatVal   = *(float *) ret.data(); break;
      case Type::DoubleTyID:  Result.DoubleVal  = *(double*) ret.data(); break;
      case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
      default: break;
    }
    return true;
  }

  return false;
}