diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/BuildLibCalls.cpp')
| -rw-r--r-- | llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 1396 | 
1 files changed, 1396 insertions, 0 deletions
| diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp new file mode 100644 index 000000000000..71316ce8f758 --- /dev/null +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -0,0 +1,1396 @@ +//===- BuildLibCalls.cpp - Utility builder for libcalls -------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements some functions that will create standard C libcalls. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/BuildLibCalls.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/Analysis/MemoryBuiltins.h" + +using namespace llvm; + +#define DEBUG_TYPE "build-libcalls" + +//- Infer Attributes ---------------------------------------------------------// + +STATISTIC(NumReadNone, "Number of functions inferred as readnone"); +STATISTIC(NumReadOnly, "Number of functions inferred as readonly"); +STATISTIC(NumArgMemOnly, "Number of functions inferred as argmemonly"); +STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind"); +STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture"); +STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly"); +STATISTIC(NumNoAlias, "Number of function returns inferred as noalias"); +STATISTIC(NumNonNull, "Number of function returns inferred as nonnull returns"); +STATISTIC(NumReturnedArg, "Number of arguments inferred as returned"); + +static bool setDoesNotAccessMemory(Function &F) { +  if (F.doesNotAccessMemory()) +    return false; +  F.setDoesNotAccessMemory(); +  ++NumReadNone; +  return true; +} + +static bool setOnlyReadsMemory(Function &F) { +  if (F.onlyReadsMemory()) +    return false; +  F.setOnlyReadsMemory(); +  ++NumReadOnly; +  return true; +} + +static bool setOnlyAccessesArgMemory(Function &F) { +  if (F.onlyAccessesArgMemory()) +    return false; +  F.setOnlyAccessesArgMemory(); +  ++NumArgMemOnly; +  return true; +} + +static bool setDoesNotThrow(Function &F) { +  if (F.doesNotThrow()) +    return false; +  F.setDoesNotThrow(); +  ++NumNoUnwind; +  return true; +} + +static bool setRetDoesNotAlias(Function &F) { +  if (F.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias)) +    return false; +  F.addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); +  ++NumNoAlias; +  return true; +} + +static bool setDoesNotCapture(Function &F, unsigned ArgNo) { +  if (F.hasParamAttribute(ArgNo, Attribute::NoCapture)) +    return false; +  F.addParamAttr(ArgNo, Attribute::NoCapture); +  ++NumNoCapture; +  return true; +} + +static bool setDoesNotAlias(Function &F, unsigned ArgNo) { +  if (F.hasParamAttribute(ArgNo, Attribute::NoAlias)) +    return false; +  F.addParamAttr(ArgNo, Attribute::NoAlias); +  ++NumNoAlias; +  return true; +} + +static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) { +  if (F.hasParamAttribute(ArgNo, Attribute::ReadOnly)) +    return false; +  F.addParamAttr(ArgNo, Attribute::ReadOnly); +  ++NumReadOnlyArg; +  return true; +} + +static bool setRetNonNull(Function &F) { +  assert(F.getReturnType()->isPointerTy() && +         "nonnull applies only to pointers"); +  if (F.hasAttribute(AttributeList::ReturnIndex, Attribute::NonNull)) +    return false; +  F.addAttribute(AttributeList::ReturnIndex, Attribute::NonNull); +  ++NumNonNull; +  return true; +} + +static bool setReturnedArg(Function &F, unsigned ArgNo) { +  if (F.hasParamAttribute(ArgNo, Attribute::Returned)) +    return false; +  F.addParamAttr(ArgNo, Attribute::Returned); +  ++NumReturnedArg; +  return true; +} + +static bool setNonLazyBind(Function &F) { +  if (F.hasFnAttribute(Attribute::NonLazyBind)) +    return false; +  F.addFnAttr(Attribute::NonLazyBind); +  return true; +} + +static bool setDoesNotFreeMemory(Function &F) { +  if (F.hasFnAttribute(Attribute::NoFree)) +    return false; +  F.addFnAttr(Attribute::NoFree); +  return true; +} + +bool llvm::inferLibFuncAttributes(Module *M, StringRef Name, +                                  const TargetLibraryInfo &TLI) { +  Function *F = M->getFunction(Name); +  if (!F) +    return false; +  return inferLibFuncAttributes(*F, TLI); +} + +bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { +  LibFunc TheLibFunc; +  if (!(TLI.getLibFunc(F, TheLibFunc) && TLI.has(TheLibFunc))) +    return false; + +  bool Changed = false; + +  if(!isLibFreeFunction(&F, TheLibFunc) && !isReallocLikeFn(&F,  &TLI)) +    Changed |= setDoesNotFreeMemory(F); + +  if (F.getParent() != nullptr && F.getParent()->getRtLibUseGOT()) +    Changed |= setNonLazyBind(F); + +  switch (TheLibFunc) { +  case LibFunc_strlen: +  case LibFunc_wcslen: +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotThrow(F); +    Changed |= setOnlyAccessesArgMemory(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_strchr: +  case LibFunc_strrchr: +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotThrow(F); +    return Changed; +  case LibFunc_strtol: +  case LibFunc_strtod: +  case LibFunc_strtof: +  case LibFunc_strtoul: +  case LibFunc_strtoll: +  case LibFunc_strtold: +  case LibFunc_strtoull: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_strcpy: +  case LibFunc_strncpy: +    Changed |= setDoesNotAlias(F, 0); +    Changed |= setDoesNotAlias(F, 1); +    LLVM_FALLTHROUGH; +  case LibFunc_strcat: +  case LibFunc_strncat: +    Changed |= setReturnedArg(F, 0); +    LLVM_FALLTHROUGH; +  case LibFunc_stpcpy: +  case LibFunc_stpncpy: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_strxfrm: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_strcmp:      // 0,1 +  case LibFunc_strspn:      // 0,1 +  case LibFunc_strncmp:     // 0,1 +  case LibFunc_strcspn:     // 0,1 +  case LibFunc_strcoll:     // 0,1 +  case LibFunc_strcasecmp:  // 0,1 +  case LibFunc_strncasecmp: // +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_strstr: +  case LibFunc_strpbrk: +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_strtok: +  case LibFunc_strtok_r: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_scanf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_setbuf: +  case LibFunc_setvbuf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_strdup: +  case LibFunc_strndup: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_stat: +  case LibFunc_statvfs: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_sscanf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_sprintf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotAlias(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_snprintf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotAlias(F, 0); +    Changed |= setDoesNotCapture(F, 2); +    Changed |= setOnlyReadsMemory(F, 2); +    return Changed; +  case LibFunc_setitimer: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setDoesNotCapture(F, 2); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_system: +    // May throw; "system" is a valid pthread cancellation point. +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_malloc: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    return Changed; +  case LibFunc_memcmp: +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_memchr: +  case LibFunc_memrchr: +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotThrow(F); +    return Changed; +  case LibFunc_modf: +  case LibFunc_modff: +  case LibFunc_modfl: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_memcpy: +    Changed |= setDoesNotAlias(F, 0); +    Changed |= setDoesNotAlias(F, 1); +    Changed |= setReturnedArg(F, 0); +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_memmove: +    Changed |= setReturnedArg(F, 0); +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_mempcpy: +  case LibFunc_memccpy: +    Changed |= setDoesNotAlias(F, 0); +    Changed |= setDoesNotAlias(F, 1); +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_memcpy_chk: +    Changed |= setDoesNotThrow(F); +    return Changed; +  case LibFunc_memalign: +    Changed |= setRetDoesNotAlias(F); +    return Changed; +  case LibFunc_mkdir: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_mktime: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_realloc: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_read: +    // May throw; "read" is a valid pthread cancellation point. +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_rewind: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_rmdir: +  case LibFunc_remove: +  case LibFunc_realpath: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_rename: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_readlink: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_write: +    // May throw; "write" is a valid pthread cancellation point. +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_bcopy: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_bcmp: +    Changed |= setDoesNotThrow(F); +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_bzero: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_calloc: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    return Changed; +  case LibFunc_chmod: +  case LibFunc_chown: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_ctermid: +  case LibFunc_clearerr: +  case LibFunc_closedir: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_atoi: +  case LibFunc_atol: +  case LibFunc_atof: +  case LibFunc_atoll: +    Changed |= setDoesNotThrow(F); +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_access: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_fopen: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_fdopen: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_feof: +  case LibFunc_free: +  case LibFunc_fseek: +  case LibFunc_ftell: +  case LibFunc_fgetc: +  case LibFunc_fgetc_unlocked: +  case LibFunc_fseeko: +  case LibFunc_ftello: +  case LibFunc_fileno: +  case LibFunc_fflush: +  case LibFunc_fclose: +  case LibFunc_fsetpos: +  case LibFunc_flockfile: +  case LibFunc_funlockfile: +  case LibFunc_ftrylockfile: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_ferror: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F); +    return Changed; +  case LibFunc_fputc: +  case LibFunc_fputc_unlocked: +  case LibFunc_fstat: +  case LibFunc_frexp: +  case LibFunc_frexpf: +  case LibFunc_frexpl: +  case LibFunc_fstatvfs: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_fgets: +  case LibFunc_fgets_unlocked: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 2); +    return Changed; +  case LibFunc_fread: +  case LibFunc_fread_unlocked: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 3); +    return Changed; +  case LibFunc_fwrite: +  case LibFunc_fwrite_unlocked: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 3); +    // FIXME: readonly #1? +    return Changed; +  case LibFunc_fputs: +  case LibFunc_fputs_unlocked: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_fscanf: +  case LibFunc_fprintf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_fgetpos: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_getc: +  case LibFunc_getlogin_r: +  case LibFunc_getc_unlocked: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_getenv: +    Changed |= setDoesNotThrow(F); +    Changed |= setOnlyReadsMemory(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_gets: +  case LibFunc_getchar: +  case LibFunc_getchar_unlocked: +    Changed |= setDoesNotThrow(F); +    return Changed; +  case LibFunc_getitimer: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_getpwnam: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_ungetc: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_uname: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_unlink: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_unsetenv: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_utime: +  case LibFunc_utimes: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_putc: +  case LibFunc_putc_unlocked: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_puts: +  case LibFunc_printf: +  case LibFunc_perror: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_pread: +    // May throw; "pread" is a valid pthread cancellation point. +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_pwrite: +    // May throw; "pwrite" is a valid pthread cancellation point. +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_putchar: +  case LibFunc_putchar_unlocked: +    Changed |= setDoesNotThrow(F); +    return Changed; +  case LibFunc_popen: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_pclose: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_vscanf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_vsscanf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_vfscanf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_valloc: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    return Changed; +  case LibFunc_vprintf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_vfprintf: +  case LibFunc_vsprintf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_vsnprintf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 2); +    Changed |= setOnlyReadsMemory(F, 2); +    return Changed; +  case LibFunc_open: +    // May throw; "open" is a valid pthread cancellation point. +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_opendir: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_tmpfile: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    return Changed; +  case LibFunc_times: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_htonl: +  case LibFunc_htons: +  case LibFunc_ntohl: +  case LibFunc_ntohs: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotAccessMemory(F); +    return Changed; +  case LibFunc_lstat: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_lchown: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_qsort: +    // May throw; places call through function pointer. +    Changed |= setDoesNotCapture(F, 3); +    return Changed; +  case LibFunc_dunder_strdup: +  case LibFunc_dunder_strndup: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_dunder_strtok_r: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_under_IO_getc: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_under_IO_putc: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_dunder_isoc99_scanf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_stat64: +  case LibFunc_lstat64: +  case LibFunc_statvfs64: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_dunder_isoc99_sscanf: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_fopen64: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 0); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  case LibFunc_fseeko64: +  case LibFunc_ftello64: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    return Changed; +  case LibFunc_tmpfile64: +    Changed |= setDoesNotThrow(F); +    Changed |= setRetDoesNotAlias(F); +    return Changed; +  case LibFunc_fstat64: +  case LibFunc_fstatvfs64: +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  case LibFunc_open64: +    // May throw; "open" is a valid pthread cancellation point. +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setOnlyReadsMemory(F, 0); +    return Changed; +  case LibFunc_gettimeofday: +    // Currently some platforms have the restrict keyword on the arguments to +    // gettimeofday. To be conservative, do not add noalias to gettimeofday's +    // arguments. +    Changed |= setDoesNotThrow(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    return Changed; +  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) +    // Operator new always returns a nonnull noalias pointer +    Changed |= setRetNonNull(F); +    Changed |= setRetDoesNotAlias(F); +    return Changed; +  // TODO: add LibFunc entries for: +  // case LibFunc_memset_pattern4: +  // case LibFunc_memset_pattern8: +  case LibFunc_memset_pattern16: +    Changed |= setOnlyAccessesArgMemory(F); +    Changed |= setDoesNotCapture(F, 0); +    Changed |= setDoesNotCapture(F, 1); +    Changed |= setOnlyReadsMemory(F, 1); +    return Changed; +  // int __nvvm_reflect(const char *) +  case LibFunc_nvvm_reflect: +    Changed |= setDoesNotAccessMemory(F); +    Changed |= setDoesNotThrow(F); +    return Changed; + +  default: +    // FIXME: It'd be really nice to cover all the library functions we're +    // aware of here. +    return false; +  } +} + +bool llvm::hasFloatFn(const TargetLibraryInfo *TLI, Type *Ty, +                      LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn) { +  switch (Ty->getTypeID()) { +  case Type::HalfTyID: +    return false; +  case Type::FloatTyID: +    return TLI->has(FloatFn); +  case Type::DoubleTyID: +    return TLI->has(DoubleFn); +  default: +    return TLI->has(LongDoubleFn); +  } +} + +StringRef llvm::getFloatFnName(const TargetLibraryInfo *TLI, Type *Ty, +                               LibFunc DoubleFn, LibFunc FloatFn, +                               LibFunc LongDoubleFn) { +  assert(hasFloatFn(TLI, Ty, DoubleFn, FloatFn, LongDoubleFn) && +         "Cannot get name for unavailable function!"); + +  switch (Ty->getTypeID()) { +  case Type::HalfTyID: +    llvm_unreachable("No name for HalfTy!"); +  case Type::FloatTyID: +    return TLI->getName(FloatFn); +  case Type::DoubleTyID: +    return TLI->getName(DoubleFn); +  default: +    return TLI->getName(LongDoubleFn); +  } +} + +//- Emit LibCalls ------------------------------------------------------------// + +Value *llvm::castToCStr(Value *V, IRBuilder<> &B) { +  unsigned AS = V->getType()->getPointerAddressSpace(); +  return B.CreateBitCast(V, B.getInt8PtrTy(AS), "cstr"); +} + +static Value *emitLibCall(LibFunc TheLibFunc, Type *ReturnType, +                          ArrayRef<Type *> ParamTypes, +                          ArrayRef<Value *> Operands, IRBuilder<> &B, +                          const TargetLibraryInfo *TLI, +                          bool IsVaArgs = false) { +  if (!TLI->has(TheLibFunc)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef FuncName = TLI->getName(TheLibFunc); +  FunctionType *FuncType = FunctionType::get(ReturnType, ParamTypes, IsVaArgs); +  FunctionCallee Callee = M->getOrInsertFunction(FuncName, FuncType); +  inferLibFuncAttributes(M, FuncName, *TLI); +  CallInst *CI = B.CreateCall(Callee, Operands, FuncName); +  if (const Function *F = +          dyn_cast<Function>(Callee.getCallee()->stripPointerCasts())) +    CI->setCallingConv(F->getCallingConv()); +  return CI; +} + +Value *llvm::emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL, +                        const TargetLibraryInfo *TLI) { +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  return emitLibCall(LibFunc_strlen, DL.getIntPtrType(Context), +                     B.getInt8PtrTy(), castToCStr(Ptr, B), B, TLI); +} + +Value *llvm::emitStrDup(Value *Ptr, IRBuilder<> &B, +                        const TargetLibraryInfo *TLI) { +  return emitLibCall(LibFunc_strdup, B.getInt8PtrTy(), B.getInt8PtrTy(), +                     castToCStr(Ptr, B), B, TLI); +} + +Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilder<> &B, +                        const TargetLibraryInfo *TLI) { +  Type *I8Ptr = B.getInt8PtrTy(); +  Type *I32Ty = B.getInt32Ty(); +  return emitLibCall(LibFunc_strchr, I8Ptr, {I8Ptr, I32Ty}, +                     {castToCStr(Ptr, B), ConstantInt::get(I32Ty, C)}, B, TLI); +} + +Value *llvm::emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, +                         const DataLayout &DL, const TargetLibraryInfo *TLI) { +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  return emitLibCall( +      LibFunc_strncmp, B.getInt32Ty(), +      {B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context)}, +      {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, B, TLI); +} + +Value *llvm::emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, +                        const TargetLibraryInfo *TLI) { +  Type *I8Ptr = B.getInt8PtrTy(); +  return emitLibCall(LibFunc_strcpy, I8Ptr, {I8Ptr, I8Ptr}, +                     {castToCStr(Dst, B), castToCStr(Src, B)}, B, TLI); +} + +Value *llvm::emitStpCpy(Value *Dst, Value *Src, IRBuilder<> &B, +                        const TargetLibraryInfo *TLI) { +  Type *I8Ptr = B.getInt8PtrTy(); +  return emitLibCall(LibFunc_stpcpy, I8Ptr, {I8Ptr, I8Ptr}, +                     {castToCStr(Dst, B), castToCStr(Src, B)}, B, TLI); +} + +Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, +                         const TargetLibraryInfo *TLI) { +  Type *I8Ptr = B.getInt8PtrTy(); +  return emitLibCall(LibFunc_strncpy, I8Ptr, {I8Ptr, I8Ptr, Len->getType()}, +                     {castToCStr(Dst, B), castToCStr(Src, B), Len}, B, TLI); +} + +Value *llvm::emitStpNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, +                         const TargetLibraryInfo *TLI) { +  Type *I8Ptr = B.getInt8PtrTy(); +  return emitLibCall(LibFunc_stpncpy, I8Ptr, {I8Ptr, I8Ptr, Len->getType()}, +                     {castToCStr(Dst, B), castToCStr(Src, B), Len}, B, TLI); +} + +Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, +                           IRBuilder<> &B, const DataLayout &DL, +                           const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_memcpy_chk)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  AttributeList AS; +  AS = AttributeList::get(M->getContext(), AttributeList::FunctionIndex, +                          Attribute::NoUnwind); +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  FunctionCallee MemCpy = M->getOrInsertFunction( +      "__memcpy_chk", AttributeList::get(M->getContext(), AS), B.getInt8PtrTy(), +      B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context), +      DL.getIntPtrType(Context)); +  Dst = castToCStr(Dst, B); +  Src = castToCStr(Src, B); +  CallInst *CI = B.CreateCall(MemCpy, {Dst, Src, Len, ObjSize}); +  if (const Function *F = +          dyn_cast<Function>(MemCpy.getCallee()->stripPointerCasts())) +    CI->setCallingConv(F->getCallingConv()); +  return CI; +} + +Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, +                        const DataLayout &DL, const TargetLibraryInfo *TLI) { +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  return emitLibCall( +      LibFunc_memchr, B.getInt8PtrTy(), +      {B.getInt8PtrTy(), B.getInt32Ty(), DL.getIntPtrType(Context)}, +      {castToCStr(Ptr, B), Val, Len}, B, TLI); +} + +Value *llvm::emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, +                        const DataLayout &DL, const TargetLibraryInfo *TLI) { +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  return emitLibCall( +      LibFunc_memcmp, B.getInt32Ty(), +      {B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context)}, +      {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, B, TLI); +} + +Value *llvm::emitBCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, +                      const DataLayout &DL, const TargetLibraryInfo *TLI) { +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  return emitLibCall( +      LibFunc_bcmp, B.getInt32Ty(), +      {B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context)}, +      {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, B, TLI); +} + +Value *llvm::emitMemCCpy(Value *Ptr1, Value *Ptr2, Value *Val, Value *Len, +                         IRBuilder<> &B, const TargetLibraryInfo *TLI) { +  return emitLibCall( +      LibFunc_memccpy, B.getInt8PtrTy(), +      {B.getInt8PtrTy(), B.getInt8PtrTy(), B.getInt32Ty(), Len->getType()}, +      {Ptr1, Ptr2, Val, Len}, B, TLI); +} + +Value *llvm::emitSNPrintf(Value *Dest, Value *Size, Value *Fmt, +                          ArrayRef<Value *> VariadicArgs, IRBuilder<> &B, +                          const TargetLibraryInfo *TLI) { +  SmallVector<Value *, 8> Args{castToCStr(Dest, B), Size, castToCStr(Fmt, B)}; +  Args.insert(Args.end(), VariadicArgs.begin(), VariadicArgs.end()); +  return emitLibCall(LibFunc_snprintf, B.getInt32Ty(), +                     {B.getInt8PtrTy(), Size->getType(), B.getInt8PtrTy()}, +                     Args, B, TLI, /*IsVaArgs=*/true); +} + +Value *llvm::emitSPrintf(Value *Dest, Value *Fmt, +                         ArrayRef<Value *> VariadicArgs, IRBuilder<> &B, +                         const TargetLibraryInfo *TLI) { +  SmallVector<Value *, 8> Args{castToCStr(Dest, B), castToCStr(Fmt, B)}; +  Args.insert(Args.end(), VariadicArgs.begin(), VariadicArgs.end()); +  return emitLibCall(LibFunc_sprintf, B.getInt32Ty(), +                     {B.getInt8PtrTy(), B.getInt8PtrTy()}, Args, B, TLI, +                     /*IsVaArgs=*/true); +} + +Value *llvm::emitStrCat(Value *Dest, Value *Src, IRBuilder<> &B, +                        const TargetLibraryInfo *TLI) { +  return emitLibCall(LibFunc_strcat, B.getInt8PtrTy(), +                     {B.getInt8PtrTy(), B.getInt8PtrTy()}, +                     {castToCStr(Dest, B), castToCStr(Src, B)}, B, TLI); +} + +Value *llvm::emitStrLCpy(Value *Dest, Value *Src, Value *Size, IRBuilder<> &B, +                         const TargetLibraryInfo *TLI) { +  return emitLibCall(LibFunc_strlcpy, Size->getType(), +                     {B.getInt8PtrTy(), B.getInt8PtrTy(), Size->getType()}, +                     {castToCStr(Dest, B), castToCStr(Src, B), Size}, B, TLI); +} + +Value *llvm::emitStrLCat(Value *Dest, Value *Src, Value *Size, IRBuilder<> &B, +                         const TargetLibraryInfo *TLI) { +  return emitLibCall(LibFunc_strlcat, Size->getType(), +                     {B.getInt8PtrTy(), B.getInt8PtrTy(), Size->getType()}, +                     {castToCStr(Dest, B), castToCStr(Src, B), Size}, B, TLI); +} + +Value *llvm::emitStrNCat(Value *Dest, Value *Src, Value *Size, IRBuilder<> &B, +                         const TargetLibraryInfo *TLI) { +  return emitLibCall(LibFunc_strncat, B.getInt8PtrTy(), +                     {B.getInt8PtrTy(), B.getInt8PtrTy(), Size->getType()}, +                     {castToCStr(Dest, B), castToCStr(Src, B), Size}, B, TLI); +} + +Value *llvm::emitVSNPrintf(Value *Dest, Value *Size, Value *Fmt, Value *VAList, +                           IRBuilder<> &B, const TargetLibraryInfo *TLI) { +  return emitLibCall( +      LibFunc_vsnprintf, B.getInt32Ty(), +      {B.getInt8PtrTy(), Size->getType(), B.getInt8PtrTy(), VAList->getType()}, +      {castToCStr(Dest, B), Size, castToCStr(Fmt, B), VAList}, B, TLI); +} + +Value *llvm::emitVSPrintf(Value *Dest, Value *Fmt, Value *VAList, +                          IRBuilder<> &B, const TargetLibraryInfo *TLI) { +  return emitLibCall(LibFunc_vsprintf, B.getInt32Ty(), +                     {B.getInt8PtrTy(), B.getInt8PtrTy(), VAList->getType()}, +                     {castToCStr(Dest, B), castToCStr(Fmt, B), VAList}, B, TLI); +} + +/// Append a suffix to the function name according to the type of 'Op'. +static void appendTypeSuffix(Value *Op, StringRef &Name, +                             SmallString<20> &NameBuffer) { +  if (!Op->getType()->isDoubleTy()) { +      NameBuffer += Name; + +    if (Op->getType()->isFloatTy()) +      NameBuffer += 'f'; +    else +      NameBuffer += 'l'; + +    Name = NameBuffer; +  } +} + +static Value *emitUnaryFloatFnCallHelper(Value *Op, StringRef Name, +                                         IRBuilder<> &B, +                                         const AttributeList &Attrs) { +  assert((Name != "") && "Must specify Name to emitUnaryFloatFnCall"); + +  Module *M = B.GetInsertBlock()->getModule(); +  FunctionCallee Callee = +      M->getOrInsertFunction(Name, Op->getType(), Op->getType()); +  CallInst *CI = B.CreateCall(Callee, Op, Name); + +  // The incoming attribute set may have come from a speculatable intrinsic, but +  // is being replaced with a library call which is not allowed to be +  // speculatable. +  CI->setAttributes(Attrs.removeAttribute(B.getContext(), +                                          AttributeList::FunctionIndex, +                                          Attribute::Speculatable)); +  if (const Function *F = +          dyn_cast<Function>(Callee.getCallee()->stripPointerCasts())) +    CI->setCallingConv(F->getCallingConv()); + +  return CI; +} + +Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, +                                  const AttributeList &Attrs) { +  SmallString<20> NameBuffer; +  appendTypeSuffix(Op, Name, NameBuffer); + +  return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs); +} + +Value *llvm::emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI, +                                  LibFunc DoubleFn, LibFunc FloatFn, +                                  LibFunc LongDoubleFn, IRBuilder<> &B, +                                  const AttributeList &Attrs) { +  // Get the name of the function according to TLI. +  StringRef Name = getFloatFnName(TLI, Op->getType(), +                                  DoubleFn, FloatFn, LongDoubleFn); + +  return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs); +} + +static Value *emitBinaryFloatFnCallHelper(Value *Op1, Value *Op2, +                                          StringRef Name, IRBuilder<> &B, +                                          const AttributeList &Attrs) { +  assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall"); + +  Module *M = B.GetInsertBlock()->getModule(); +  FunctionCallee Callee = M->getOrInsertFunction(Name, Op1->getType(), +                                                 Op1->getType(), Op2->getType()); +  CallInst *CI = B.CreateCall(Callee, { Op1, Op2 }, Name); + +  // The incoming attribute set may have come from a speculatable intrinsic, but +  // is being replaced with a library call which is not allowed to be +  // speculatable. +  CI->setAttributes(Attrs.removeAttribute(B.getContext(), +                                          AttributeList::FunctionIndex, +                                          Attribute::Speculatable)); +  if (const Function *F = +          dyn_cast<Function>(Callee.getCallee()->stripPointerCasts())) +    CI->setCallingConv(F->getCallingConv()); + +  return CI; +} + +Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name, +                                   IRBuilder<> &B, const AttributeList &Attrs) { +  assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall"); + +  SmallString<20> NameBuffer; +  appendTypeSuffix(Op1, Name, NameBuffer); + +  return emitBinaryFloatFnCallHelper(Op1, Op2, Name, B, Attrs); +} + +Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, +                                   const TargetLibraryInfo *TLI, +                                   LibFunc DoubleFn, LibFunc FloatFn, +                                   LibFunc LongDoubleFn, IRBuilder<> &B, +                                   const AttributeList &Attrs) { +  // Get the name of the function according to TLI. +  StringRef Name = getFloatFnName(TLI, Op1->getType(), +                                  DoubleFn, FloatFn, LongDoubleFn); + +  return emitBinaryFloatFnCallHelper(Op1, Op2, Name, B, Attrs); +} + +Value *llvm::emitPutChar(Value *Char, IRBuilder<> &B, +                         const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_putchar)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef PutCharName = TLI->getName(LibFunc_putchar); +  FunctionCallee PutChar = +      M->getOrInsertFunction(PutCharName, B.getInt32Ty(), B.getInt32Ty()); +  inferLibFuncAttributes(M, PutCharName, *TLI); +  CallInst *CI = B.CreateCall(PutChar, +                              B.CreateIntCast(Char, +                              B.getInt32Ty(), +                              /*isSigned*/true, +                              "chari"), +                              PutCharName); + +  if (const Function *F = +          dyn_cast<Function>(PutChar.getCallee()->stripPointerCasts())) +    CI->setCallingConv(F->getCallingConv()); +  return CI; +} + +Value *llvm::emitPutS(Value *Str, IRBuilder<> &B, +                      const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_puts)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef PutsName = TLI->getName(LibFunc_puts); +  FunctionCallee PutS = +      M->getOrInsertFunction(PutsName, B.getInt32Ty(), B.getInt8PtrTy()); +  inferLibFuncAttributes(M, PutsName, *TLI); +  CallInst *CI = B.CreateCall(PutS, castToCStr(Str, B), PutsName); +  if (const Function *F = +          dyn_cast<Function>(PutS.getCallee()->stripPointerCasts())) +    CI->setCallingConv(F->getCallingConv()); +  return CI; +} + +Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B, +                       const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fputc)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef FPutcName = TLI->getName(LibFunc_fputc); +  FunctionCallee F = M->getOrInsertFunction(FPutcName, B.getInt32Ty(), +                                            B.getInt32Ty(), File->getType()); +  if (File->getType()->isPointerTy()) +    inferLibFuncAttributes(M, FPutcName, *TLI); +  Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true, +                         "chari"); +  CallInst *CI = B.CreateCall(F, {Char, File}, FPutcName); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} + +Value *llvm::emitFPutCUnlocked(Value *Char, Value *File, IRBuilder<> &B, +                               const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fputc_unlocked)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef FPutcUnlockedName = TLI->getName(LibFunc_fputc_unlocked); +  FunctionCallee F = M->getOrInsertFunction(FPutcUnlockedName, B.getInt32Ty(), +                                            B.getInt32Ty(), File->getType()); +  if (File->getType()->isPointerTy()) +    inferLibFuncAttributes(M, FPutcUnlockedName, *TLI); +  Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/ true, "chari"); +  CallInst *CI = B.CreateCall(F, {Char, File}, FPutcUnlockedName); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} + +Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B, +                       const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fputs)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef FPutsName = TLI->getName(LibFunc_fputs); +  FunctionCallee F = M->getOrInsertFunction(FPutsName, B.getInt32Ty(), +                                            B.getInt8PtrTy(), File->getType()); +  if (File->getType()->isPointerTy()) +    inferLibFuncAttributes(M, FPutsName, *TLI); +  CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, FPutsName); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} + +Value *llvm::emitFPutSUnlocked(Value *Str, Value *File, IRBuilder<> &B, +                               const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fputs_unlocked)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef FPutsUnlockedName = TLI->getName(LibFunc_fputs_unlocked); +  FunctionCallee F = M->getOrInsertFunction(FPutsUnlockedName, B.getInt32Ty(), +                                            B.getInt8PtrTy(), File->getType()); +  if (File->getType()->isPointerTy()) +    inferLibFuncAttributes(M, FPutsUnlockedName, *TLI); +  CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, FPutsUnlockedName); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} + +Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, +                        const DataLayout &DL, const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fwrite)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  StringRef FWriteName = TLI->getName(LibFunc_fwrite); +  FunctionCallee F = M->getOrInsertFunction( +      FWriteName, DL.getIntPtrType(Context), B.getInt8PtrTy(), +      DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType()); + +  if (File->getType()->isPointerTy()) +    inferLibFuncAttributes(M, FWriteName, *TLI); +  CallInst *CI = +      B.CreateCall(F, {castToCStr(Ptr, B), Size, +                       ConstantInt::get(DL.getIntPtrType(Context), 1), File}); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} + +Value *llvm::emitMalloc(Value *Num, IRBuilder<> &B, const DataLayout &DL, +                        const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_malloc)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef MallocName = TLI->getName(LibFunc_malloc); +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  FunctionCallee Malloc = M->getOrInsertFunction(MallocName, B.getInt8PtrTy(), +                                                 DL.getIntPtrType(Context)); +  inferLibFuncAttributes(M, MallocName, *TLI); +  CallInst *CI = B.CreateCall(Malloc, Num, MallocName); + +  if (const Function *F = +          dyn_cast<Function>(Malloc.getCallee()->stripPointerCasts())) +    CI->setCallingConv(F->getCallingConv()); + +  return CI; +} + +Value *llvm::emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs, +                        IRBuilder<> &B, const TargetLibraryInfo &TLI) { +  if (!TLI.has(LibFunc_calloc)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef CallocName = TLI.getName(LibFunc_calloc); +  const DataLayout &DL = M->getDataLayout(); +  IntegerType *PtrType = DL.getIntPtrType((B.GetInsertBlock()->getContext())); +  FunctionCallee Calloc = M->getOrInsertFunction( +      CallocName, Attrs, B.getInt8PtrTy(), PtrType, PtrType); +  inferLibFuncAttributes(M, CallocName, TLI); +  CallInst *CI = B.CreateCall(Calloc, {Num, Size}, CallocName); + +  if (const auto *F = +          dyn_cast<Function>(Calloc.getCallee()->stripPointerCasts())) +    CI->setCallingConv(F->getCallingConv()); + +  return CI; +} + +Value *llvm::emitFWriteUnlocked(Value *Ptr, Value *Size, Value *N, Value *File, +                                IRBuilder<> &B, const DataLayout &DL, +                                const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fwrite_unlocked)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  StringRef FWriteUnlockedName = TLI->getName(LibFunc_fwrite_unlocked); +  FunctionCallee F = M->getOrInsertFunction( +      FWriteUnlockedName, DL.getIntPtrType(Context), B.getInt8PtrTy(), +      DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType()); + +  if (File->getType()->isPointerTy()) +    inferLibFuncAttributes(M, FWriteUnlockedName, *TLI); +  CallInst *CI = B.CreateCall(F, {castToCStr(Ptr, B), Size, N, File}); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} + +Value *llvm::emitFGetCUnlocked(Value *File, IRBuilder<> &B, +                               const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fgetc_unlocked)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef FGetCUnlockedName = TLI->getName(LibFunc_fgetc_unlocked); +  FunctionCallee F = M->getOrInsertFunction(FGetCUnlockedName, B.getInt32Ty(), +                                            File->getType()); +  if (File->getType()->isPointerTy()) +    inferLibFuncAttributes(M, FGetCUnlockedName, *TLI); +  CallInst *CI = B.CreateCall(F, File, FGetCUnlockedName); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} + +Value *llvm::emitFGetSUnlocked(Value *Str, Value *Size, Value *File, +                               IRBuilder<> &B, const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fgets_unlocked)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  StringRef FGetSUnlockedName = TLI->getName(LibFunc_fgets_unlocked); +  FunctionCallee F = +      M->getOrInsertFunction(FGetSUnlockedName, B.getInt8PtrTy(), +                             B.getInt8PtrTy(), B.getInt32Ty(), File->getType()); +  inferLibFuncAttributes(M, FGetSUnlockedName, *TLI); +  CallInst *CI = +      B.CreateCall(F, {castToCStr(Str, B), Size, File}, FGetSUnlockedName); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} + +Value *llvm::emitFReadUnlocked(Value *Ptr, Value *Size, Value *N, Value *File, +                               IRBuilder<> &B, const DataLayout &DL, +                               const TargetLibraryInfo *TLI) { +  if (!TLI->has(LibFunc_fread_unlocked)) +    return nullptr; + +  Module *M = B.GetInsertBlock()->getModule(); +  LLVMContext &Context = B.GetInsertBlock()->getContext(); +  StringRef FReadUnlockedName = TLI->getName(LibFunc_fread_unlocked); +  FunctionCallee F = M->getOrInsertFunction( +      FReadUnlockedName, DL.getIntPtrType(Context), B.getInt8PtrTy(), +      DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType()); + +  if (File->getType()->isPointerTy()) +    inferLibFuncAttributes(M, FReadUnlockedName, *TLI); +  CallInst *CI = B.CreateCall(F, {castToCStr(Ptr, B), Size, N, File}); + +  if (const Function *Fn = +          dyn_cast<Function>(F.getCallee()->stripPointerCasts())) +    CI->setCallingConv(Fn->getCallingConv()); +  return CI; +} | 
