Skip to content
IntrinsicLowering.cpp 43.6 KiB
Newer Older
//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
//
// This file implements the IntrinsicLowering class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/Support/Streams.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;

template <class ArgIt>
static void EnsureFunctionExists(Module &M, const char *Name,
                                 ArgIt ArgBegin, ArgIt ArgEnd,
                                 const Type *RetTy) {
  // Insert a correctly-typed definition now.
  std::vector<const Type *> ParamTys;
  for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
    ParamTys.push_back(I->getType());
  M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
}

/// ReplaceCallWith - This function is used when we want to lower an intrinsic
/// call to a call of an external function.  This handles hard cases such as
/// when there was already a prototype for the external function, and if that
/// prototype doesn't match the arguments we expect to pass in.
template <class ArgIt>
static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
                                 ArgIt ArgBegin, ArgIt ArgEnd,
                                 const Type *RetTy, Constant *&FCache) {
  if (!FCache) {
    // 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<const Type *> ParamTys;
    for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
      ParamTys.push_back((*I)->getType());
    FCache = M->getOrInsertFunction(NewFn,
                                    FunctionType::get(RetTy, ParamTys, false));
David Greene's avatar
 
David Greene committed
  SmallVector<Value *, 8> Args(ArgBegin, ArgEnd);
  CallInst *NewCI = CallInst::Create(FCache, Args.begin(), Args.end(),
                                     CI->getName(), CI);
  if (!CI->use_empty())
    CI->replaceAllUsesWith(NewCI);
void IntrinsicLowering::AddPrototypes(Module &M) {
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (I->isDeclaration() && !I->use_empty())
      switch (I->getIntrinsicID()) {
      default: break;
      case Intrinsic::setjmp:
        EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(),
Reid Spencer's avatar
Reid Spencer committed
                             Type::Int32Ty);
        EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),
                             Type::VoidTy);
        EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(),
                             Type::VoidTy);
      case Intrinsic::memcpy_i32:
      case Intrinsic::memcpy_i64:
        M.getOrInsertFunction("memcpy", PointerType::getUnqual(Type::Int8Ty),
                              PointerType::getUnqual(Type::Int8Ty), 
                              PointerType::getUnqual(Type::Int8Ty), 
      case Intrinsic::memmove_i32:
      case Intrinsic::memmove_i64:
        M.getOrInsertFunction("memmove", PointerType::getUnqual(Type::Int8Ty),
                              PointerType::getUnqual(Type::Int8Ty), 
                              PointerType::getUnqual(Type::Int8Ty), 
      case Intrinsic::memset_i32:
      case Intrinsic::memset_i64:
        M.getOrInsertFunction("memset", PointerType::getUnqual(Type::Int8Ty),
                              PointerType::getUnqual(Type::Int8Ty), 
                              Type::Int32Ty, 
      case Intrinsic::sqrt:
        switch((int)I->arg_begin()->getType()->getTypeID()) {
        case Type::FloatTyID:
          EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(),
                               Type::FloatTy);
          EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(),
                               Type::DoubleTy);
        case Type::X86_FP80TyID:
        case Type::FP128TyID:
        case Type::PPC_FP128TyID:
          EnsureFunctionExists(M, "sqrtl", I->arg_begin(), I->arg_end(),
                               I->arg_begin()->getType());
        }
        break;
      case Intrinsic::sin:
        switch((int)I->arg_begin()->getType()->getTypeID()) {
        case Type::FloatTyID:
          EnsureFunctionExists(M, "sinf", I->arg_begin(), I->arg_end(),
                               Type::FloatTy);
        case Type::DoubleTyID:
          EnsureFunctionExists(M, "sin", I->arg_begin(), I->arg_end(),
                               Type::DoubleTy);
        case Type::X86_FP80TyID:
        case Type::FP128TyID:
        case Type::PPC_FP128TyID:
          EnsureFunctionExists(M, "sinl", I->arg_begin(), I->arg_end(),
                               I->arg_begin()->getType());
        }
        break;
      case Intrinsic::cos:
        switch((int)I->arg_begin()->getType()->getTypeID()) {
        case Type::FloatTyID:
          EnsureFunctionExists(M, "cosf", I->arg_begin(), I->arg_end(),
                               Type::FloatTy);
        case Type::DoubleTyID:
          EnsureFunctionExists(M, "cos", I->arg_begin(), I->arg_end(),
                               Type::DoubleTy);
        case Type::X86_FP80TyID:
        case Type::FP128TyID:
        case Type::PPC_FP128TyID:
          EnsureFunctionExists(M, "cosl", I->arg_begin(), I->arg_end(),
                               I->arg_begin()->getType());
        }
        break;
      case Intrinsic::pow:
        switch((int)I->arg_begin()->getType()->getTypeID()) {
        case Type::FloatTyID:
          EnsureFunctionExists(M, "powf", I->arg_begin(), I->arg_end(),
                               Type::FloatTy);
        case Type::DoubleTyID:
          EnsureFunctionExists(M, "pow", I->arg_begin(), I->arg_end(),
                               Type::DoubleTy);
        case Type::X86_FP80TyID:
        case Type::FP128TyID:
        case Type::PPC_FP128TyID:
          EnsureFunctionExists(M, "powl", I->arg_begin(), I->arg_end(),
                               I->arg_begin()->getType());
        }
        break;
      case Intrinsic::log:
        switch((int)I->arg_begin()->getType()->getTypeID()) {
        case Type::FloatTyID:
          EnsureFunctionExists(M, "logf", I->arg_begin(), I->arg_end(),
                               Type::FloatTy);
        case Type::DoubleTyID:
          EnsureFunctionExists(M, "log", I->arg_begin(), I->arg_end(),
                               Type::DoubleTy);
        case Type::X86_FP80TyID:
        case Type::FP128TyID:
        case Type::PPC_FP128TyID:
          EnsureFunctionExists(M, "logl", I->arg_begin(), I->arg_end(),
                               I->arg_begin()->getType());
        }
        break;
      case Intrinsic::log2:
        switch((int)I->arg_begin()->getType()->getTypeID()) {
        case Type::FloatTyID:
          EnsureFunctionExists(M, "log2f", I->arg_begin(), I->arg_end(),
                               Type::FloatTy);
        case Type::DoubleTyID:
          EnsureFunctionExists(M, "log2", I->arg_begin(), I->arg_end(),
                               Type::DoubleTy);
        case Type::X86_FP80TyID:
        case Type::FP128TyID:
        case Type::PPC_FP128TyID:
          EnsureFunctionExists(M, "log2l", I->arg_begin(), I->arg_end(),
                               I->arg_begin()->getType());
        }
        break;
      case Intrinsic::log10:
        switch((int)I->arg_begin()->getType()->getTypeID()) {
        case Type::FloatTyID:
          EnsureFunctionExists(M, "log10f", I->arg_begin(), I->arg_end(),
                               Type::FloatTy);
        case Type::DoubleTyID:
          EnsureFunctionExists(M, "log10", I->arg_begin(), I->arg_end(),
                               Type::DoubleTy);
Loading
Loading full blame...