/// EmitFPutS - Emit a call to the puts function.  Str is required to be a
/// pointer and File is a pointer to FILE.
Value *llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
                       const DataLayout *TD, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::fputs))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeSet AS[3];
  AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
  AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
  AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                            Attribute::NoUnwind);
  StringRef FPutsName = TLI->getName(LibFunc::fputs);
  Constant *F;
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction(FPutsName,
                               AttributeSet::get(M->getContext(), AS),
                               B.getInt32Ty(),
                               B.getInt8PtrTy(),
                               File->getType(), NULL);
  else
    F = M->getOrInsertFunction(FPutsName, B.getInt32Ty(),
                               B.getInt8PtrTy(),
                               File->getType(), NULL);
  CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs");

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCastsSafe()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
/// EmitStrNLen - Emit a call to the strnlen function to the builder, for the
/// specified pointer.  Ptr is required to be some pointer type, MaxLen must
/// be of size_t type, and the return value has 'intptr_t' type.
Value *llvm::EmitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B,
                         const DataLayout *TD, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::strnlen))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeSet AS[2];
  AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
  Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
  AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                            ArrayRef<Attribute::AttrKind>(AVs, 2));

  LLVMContext &Context = B.GetInsertBlock()->getContext();
  Constant *StrNLen = M->getOrInsertFunction("strnlen",
                                             AttributeSet::get(M->getContext(),
                                                              AS),
                                             TD->getIntPtrType(Context),
                                             B.getInt8PtrTy(),
                                             TD->getIntPtrType(Context),
                                             NULL);
  CallInst *CI = B.CreateCall2(StrNLen, CastToCStr(Ptr, B), MaxLen, "strnlen");
  if (const Function *F = dyn_cast<Function>(StrNLen->stripPointerCastsSafe()))
    CI->setCallingConv(F->getCallingConv());

  return CI;
}
/// EmitFPutC - Emit a call to the fputc function.  This assumes that Char is
/// an integer and File is a pointer to FILE.
Value *llvm::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
                       const DataLayout *TD, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::fputc))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeSet AS[2];
  AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
  AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                            Attribute::NoUnwind);
  Constant *F;
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction("fputc",
                               AttributeSet::get(M->getContext(), AS),
                               B.getInt32Ty(),
                               B.getInt32Ty(), File->getType(),
                               NULL);
  else
    F = M->getOrInsertFunction("fputc",
                               B.getInt32Ty(),
                               B.getInt32Ty(),
                               File->getType(), NULL);
  Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true,
                         "chari");
  CallInst *CI = B.CreateCall2(F, Char, File, "fputc");

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCastsSafe()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
/// EmitStrChr - Emit a call to the strchr function to the builder, for the
/// specified pointer and character.  Ptr is required to be some pointer type,
/// and the return value has 'i8*' type.
Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
                        const DataLayout *TD, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::strchr))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
  AttributeSet AS =
    AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                      ArrayRef<Attribute::AttrKind>(AVs, 2));

  Type *I8Ptr = B.getInt8PtrTy();
  Type *I32Ty = B.getInt32Ty();
  Constant *StrChr = M->getOrInsertFunction("strchr",
                                            AttributeSet::get(M->getContext(),
                                                             AS),
                                            I8Ptr, I8Ptr, I32Ty, NULL);
  CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B),
                               ConstantInt::get(I32Ty, C), "strchr");
  if (const Function *F = dyn_cast<Function>(StrChr->stripPointerCastsSafe()))
    CI->setCallingConv(F->getCallingConv());
  return CI;
}