|  | //===- 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" | 
|  |  | 
|  | 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 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; | 
|  | } | 
|  |  | 
|  | 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 (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: | 
|  | 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 |= setDoesNotCapture(F, 1); | 
|  | Changed |= setOnlyReadsMemory(F, 1); | 
|  | return Changed; | 
|  | case LibFunc_snprintf: | 
|  | Changed |= setDoesNotThrow(F); | 
|  | Changed |= setDoesNotCapture(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: | 
|  | case LibFunc_memmove: | 
|  | Changed |= setReturnedArg(F, 0); | 
|  | LLVM_FALLTHROUGH; | 
|  | case LibFunc_mempcpy: | 
|  | case LibFunc_memccpy: | 
|  | 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::hasUnaryFloatFn(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::getUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty, | 
|  | LibFunc DoubleFn, LibFunc FloatFn, | 
|  | LibFunc LongDoubleFn) { | 
|  | assert(hasUnaryFloatFn(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"); | 
|  | } | 
|  |  | 
|  | Value *llvm::emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL, | 
|  | const TargetLibraryInfo *TLI) { | 
|  | if (!TLI->has(LibFunc_strlen)) | 
|  | return nullptr; | 
|  |  | 
|  | Module *M = B.GetInsertBlock()->getModule(); | 
|  | StringRef StrlenName = TLI->getName(LibFunc_strlen); | 
|  | LLVMContext &Context = B.GetInsertBlock()->getContext(); | 
|  | FunctionCallee StrLen = M->getOrInsertFunction( | 
|  | StrlenName, DL.getIntPtrType(Context), B.getInt8PtrTy()); | 
|  | inferLibFuncAttributes(M, StrlenName, *TLI); | 
|  | CallInst *CI = B.CreateCall(StrLen, castToCStr(Ptr, B), StrlenName); | 
|  | if (const Function *F = | 
|  | dyn_cast<Function>(StrLen.getCallee()->stripPointerCasts())) | 
|  | CI->setCallingConv(F->getCallingConv()); | 
|  |  | 
|  | return CI; | 
|  | } | 
|  |  | 
|  | Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilder<> &B, | 
|  | const TargetLibraryInfo *TLI) { | 
|  | if (!TLI->has(LibFunc_strchr)) | 
|  | return nullptr; | 
|  |  | 
|  | Module *M = B.GetInsertBlock()->getModule(); | 
|  | StringRef StrChrName = TLI->getName(LibFunc_strchr); | 
|  | Type *I8Ptr = B.getInt8PtrTy(); | 
|  | Type *I32Ty = B.getInt32Ty(); | 
|  | FunctionCallee StrChr = | 
|  | M->getOrInsertFunction(StrChrName, I8Ptr, I8Ptr, I32Ty); | 
|  | inferLibFuncAttributes(M, StrChrName, *TLI); | 
|  | CallInst *CI = B.CreateCall( | 
|  | StrChr, {castToCStr(Ptr, B), ConstantInt::get(I32Ty, C)}, StrChrName); | 
|  | if (const Function *F = | 
|  | dyn_cast<Function>(StrChr.getCallee()->stripPointerCasts())) | 
|  | CI->setCallingConv(F->getCallingConv()); | 
|  | return CI; | 
|  | } | 
|  |  | 
|  | Value *llvm::emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, | 
|  | const DataLayout &DL, const TargetLibraryInfo *TLI) { | 
|  | if (!TLI->has(LibFunc_strncmp)) | 
|  | return nullptr; | 
|  |  | 
|  | Module *M = B.GetInsertBlock()->getModule(); | 
|  | StringRef StrNCmpName = TLI->getName(LibFunc_strncmp); | 
|  | LLVMContext &Context = B.GetInsertBlock()->getContext(); | 
|  | FunctionCallee StrNCmp = | 
|  | M->getOrInsertFunction(StrNCmpName, B.getInt32Ty(), B.getInt8PtrTy(), | 
|  | B.getInt8PtrTy(), DL.getIntPtrType(Context)); | 
|  | inferLibFuncAttributes(M, StrNCmpName, *TLI); | 
|  | CallInst *CI = B.CreateCall( | 
|  | StrNCmp, {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, StrNCmpName); | 
|  |  | 
|  | if (const Function *F = | 
|  | dyn_cast<Function>(StrNCmp.getCallee()->stripPointerCasts())) | 
|  | CI->setCallingConv(F->getCallingConv()); | 
|  |  | 
|  | return CI; | 
|  | } | 
|  |  | 
|  | Value *llvm::emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, | 
|  | const TargetLibraryInfo *TLI, StringRef Name) { | 
|  | if (!TLI->has(LibFunc_strcpy)) | 
|  | return nullptr; | 
|  |  | 
|  | Module *M = B.GetInsertBlock()->getModule(); | 
|  | Type *I8Ptr = B.getInt8PtrTy(); | 
|  | FunctionCallee StrCpy = M->getOrInsertFunction(Name, I8Ptr, I8Ptr, I8Ptr); | 
|  | inferLibFuncAttributes(M, Name, *TLI); | 
|  | CallInst *CI = | 
|  | B.CreateCall(StrCpy, {castToCStr(Dst, B), castToCStr(Src, B)}, Name); | 
|  | if (const Function *F = | 
|  | dyn_cast<Function>(StrCpy.getCallee()->stripPointerCasts())) | 
|  | CI->setCallingConv(F->getCallingConv()); | 
|  | return CI; | 
|  | } | 
|  |  | 
|  | Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, | 
|  | const TargetLibraryInfo *TLI, StringRef Name) { | 
|  | if (!TLI->has(LibFunc_strncpy)) | 
|  | return nullptr; | 
|  |  | 
|  | Module *M = B.GetInsertBlock()->getModule(); | 
|  | Type *I8Ptr = B.getInt8PtrTy(); | 
|  | FunctionCallee StrNCpy = | 
|  | M->getOrInsertFunction(Name, I8Ptr, I8Ptr, I8Ptr, Len->getType()); | 
|  | inferLibFuncAttributes(M, Name, *TLI); | 
|  | CallInst *CI = B.CreateCall( | 
|  | StrNCpy, {castToCStr(Dst, B), castToCStr(Src, B), Len}, Name); | 
|  | if (const Function *F = | 
|  | dyn_cast<Function>(StrNCpy.getCallee()->stripPointerCasts())) | 
|  | CI->setCallingConv(F->getCallingConv()); | 
|  | return CI; | 
|  | } | 
|  |  | 
|  | 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) { | 
|  | if (!TLI->has(LibFunc_memchr)) | 
|  | return nullptr; | 
|  |  | 
|  | Module *M = B.GetInsertBlock()->getModule(); | 
|  | StringRef MemChrName = TLI->getName(LibFunc_memchr); | 
|  | LLVMContext &Context = B.GetInsertBlock()->getContext(); | 
|  | FunctionCallee MemChr = | 
|  | M->getOrInsertFunction(MemChrName, B.getInt8PtrTy(), B.getInt8PtrTy(), | 
|  | B.getInt32Ty(), DL.getIntPtrType(Context)); | 
|  | inferLibFuncAttributes(M, MemChrName, *TLI); | 
|  | CallInst *CI = B.CreateCall(MemChr, {castToCStr(Ptr, B), Val, Len}, MemChrName); | 
|  |  | 
|  | if (const Function *F = | 
|  | dyn_cast<Function>(MemChr.getCallee()->stripPointerCasts())) | 
|  | CI->setCallingConv(F->getCallingConv()); | 
|  |  | 
|  | return CI; | 
|  | } | 
|  |  | 
|  | Value *llvm::emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, | 
|  | const DataLayout &DL, const TargetLibraryInfo *TLI) { | 
|  | if (!TLI->has(LibFunc_memcmp)) | 
|  | return nullptr; | 
|  |  | 
|  | Module *M = B.GetInsertBlock()->getModule(); | 
|  | StringRef MemCmpName = TLI->getName(LibFunc_memcmp); | 
|  | LLVMContext &Context = B.GetInsertBlock()->getContext(); | 
|  | FunctionCallee MemCmp = | 
|  | M->getOrInsertFunction(MemCmpName, B.getInt32Ty(), B.getInt8PtrTy(), | 
|  | B.getInt8PtrTy(), DL.getIntPtrType(Context)); | 
|  | inferLibFuncAttributes(M, MemCmpName, *TLI); | 
|  | CallInst *CI = B.CreateCall( | 
|  | MemCmp, {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, MemCmpName); | 
|  |  | 
|  | if (const Function *F = | 
|  | dyn_cast<Function>(MemCmp.getCallee()->stripPointerCasts())) | 
|  | CI->setCallingConv(F->getCallingConv()); | 
|  |  | 
|  | return CI; | 
|  | } | 
|  |  | 
|  | /// 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 = getUnaryFloatFn(TLI, Op->getType(), | 
|  | DoubleFn, FloatFn, LongDoubleFn); | 
|  |  | 
|  | return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs); | 
|  | } | 
|  |  | 
|  | 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); | 
|  |  | 
|  | Module *M = B.GetInsertBlock()->getModule(); | 
|  | FunctionCallee Callee = M->getOrInsertFunction( | 
|  | Name, Op1->getType(), Op1->getType(), Op2->getType()); | 
|  | CallInst *CI = B.CreateCall(Callee, {Op1, Op2}, Name); | 
|  | CI->setAttributes(Attrs); | 
|  | if (const Function *F = | 
|  | dyn_cast<Function>(Callee.getCallee()->stripPointerCasts())) | 
|  | CI->setCallingConv(F->getCallingConv()); | 
|  |  | 
|  | return CI; | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } |