llvm-6502/lib/Target/TargetLibraryInfo.cpp
Benjamin Kramer 8e0d1c03ca Make MemoryBuiltins aware of TargetLibraryInfo.
This disables malloc-specific optimization when -fno-builtin (or -ffreestanding)
is specified. This has been a problem for a long time but became more severe
with the recent memory builtin improvements.

Since the memory builtin functions are used everywhere, this required passing
TLI in many places. This means that functions that now have an optional TLI
argument, like RecursivelyDeleteTriviallyDeadFunctions, won't remove dead
mallocs anymore if the TLI argument is missing. I've updated most passes to do
the right thing.

Fixes PR13694 and probably others.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162841 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-29 15:32:21 +00:00

353 lines
9.5 KiB
C++

//===-- TargetLibraryInfo.cpp - Runtime library information ----------------==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TargetLibraryInfo class.
//
//===----------------------------------------------------------------------===//
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/ADT/Triple.h"
using namespace llvm;
// Register the default implementation.
INITIALIZE_PASS(TargetLibraryInfo, "targetlibinfo",
"Target Library Information", false, true)
char TargetLibraryInfo::ID = 0;
void TargetLibraryInfo::anchor() { }
const char* TargetLibraryInfo::StandardNames[LibFunc::NumLibFuncs] =
{
"_ZdaPv",
"_ZdlPv",
"_Znaj",
"_ZnajRKSt9nothrow_t",
"_Znam",
"_ZnamRKSt9nothrow_t",
"_Znwj",
"_ZnwjRKSt9nothrow_t",
"_Znwm",
"_ZnwmRKSt9nothrow_t",
"__cxa_atexit",
"__cxa_guard_abort",
"__cxa_guard_acquire",
"__cxa_guard_release",
"__memcpy_chk",
"acos",
"acosf",
"acosh",
"acoshf",
"acoshl",
"acosl",
"asin",
"asinf",
"asinh",
"asinhf",
"asinhl",
"asinl",
"atan",
"atan2",
"atan2f",
"atan2l",
"atanf",
"atanh",
"atanhf",
"atanhl",
"atanl",
"calloc",
"cbrt",
"cbrtf",
"cbrtl",
"ceil",
"ceilf",
"ceill",
"copysign",
"copysignf",
"copysignl",
"cos",
"cosf",
"cosh",
"coshf",
"coshl",
"cosl",
"exp",
"exp10",
"exp10f",
"exp10l",
"exp2",
"exp2f",
"exp2l",
"expf",
"expl",
"expm1",
"expm1f",
"expm1l",
"fabs",
"fabsf",
"fabsl",
"fiprintf",
"floor",
"floorf",
"floorl",
"fmod",
"fmodf",
"fmodl",
"fputc",
"fputs",
"free",
"fwrite",
"iprintf",
"log",
"log10",
"log10f",
"log10l",
"log1p",
"log1pf",
"log1pl",
"log2",
"log2f",
"log2l",
"logb",
"logbf",
"logbl",
"logf",
"logl",
"malloc",
"memchr",
"memcmp",
"memcpy",
"memmove",
"memset",
"memset_pattern16",
"nearbyint",
"nearbyintf",
"nearbyintl",
"posix_memalign",
"pow",
"powf",
"powl",
"putchar",
"puts",
"realloc",
"reallocf",
"rint",
"rintf",
"rintl",
"round",
"roundf",
"roundl",
"sin",
"sinf",
"sinh",
"sinhf",
"sinhl",
"sinl",
"siprintf",
"sqrt",
"sqrtf",
"sqrtl",
"strcat",
"strchr",
"strcpy",
"strdup",
"strlen",
"strncat",
"strncmp",
"strncpy",
"strndup",
"strnlen",
"tan",
"tanf",
"tanh",
"tanhf",
"tanhl",
"tanl",
"trunc",
"truncf",
"truncl",
"valloc"
};
/// initialize - Initialize the set of available library functions based on the
/// specified target triple. This should be carefully written so that a missing
/// target triple gets a sane set of defaults.
static void initialize(TargetLibraryInfo &TLI, const Triple &T,
const char **StandardNames) {
initializeTargetLibraryInfoPass(*PassRegistry::getPassRegistry());
#ifndef NDEBUG
// Verify that the StandardNames array is in alphabetical order.
for (unsigned F = 1; F < LibFunc::NumLibFuncs; ++F) {
if (strcmp(StandardNames[F-1], StandardNames[F]) >= 0)
llvm_unreachable("TargetLibraryInfo function names must be sorted");
}
#endif // !NDEBUG
// memset_pattern16 is only available on iOS 3.0 and Mac OS/X 10.5 and later.
if (T.isMacOSX()) {
if (T.isMacOSXVersionLT(10, 5))
TLI.setUnavailable(LibFunc::memset_pattern16);
} else if (T.getOS() == Triple::IOS) {
if (T.isOSVersionLT(3, 0))
TLI.setUnavailable(LibFunc::memset_pattern16);
} else {
TLI.setUnavailable(LibFunc::memset_pattern16);
}
if (T.isMacOSX() && T.getArch() == Triple::x86 &&
!T.isMacOSXVersionLT(10, 7)) {
// x86-32 OSX has a scheme where fwrite and fputs (and some other functions
// we don't care about) have two versions; on recent OSX, the one we want
// has a $UNIX2003 suffix. The two implementations are identical except
// for the return value in some edge cases. However, we don't want to
// generate code that depends on the old symbols.
TLI.setAvailableWithName(LibFunc::fwrite, "fwrite$UNIX2003");
TLI.setAvailableWithName(LibFunc::fputs, "fputs$UNIX2003");
}
// iprintf and friends are only available on XCore and TCE.
if (T.getArch() != Triple::xcore && T.getArch() != Triple::tce) {
TLI.setUnavailable(LibFunc::iprintf);
TLI.setUnavailable(LibFunc::siprintf);
TLI.setUnavailable(LibFunc::fiprintf);
}
if (T.getOS() == Triple::Win32) {
// Win32 does not support long double
TLI.setUnavailable(LibFunc::acosl);
TLI.setUnavailable(LibFunc::asinl);
TLI.setUnavailable(LibFunc::atanl);
TLI.setUnavailable(LibFunc::atan2l);
TLI.setUnavailable(LibFunc::ceill);
TLI.setUnavailable(LibFunc::copysignl);
TLI.setUnavailable(LibFunc::cosl);
TLI.setUnavailable(LibFunc::coshl);
TLI.setUnavailable(LibFunc::expl);
TLI.setUnavailable(LibFunc::fabsf); // Win32 and Win64 both lack fabsf
TLI.setUnavailable(LibFunc::fabsl);
TLI.setUnavailable(LibFunc::floorl);
TLI.setUnavailable(LibFunc::fmodl);
TLI.setUnavailable(LibFunc::logl);
TLI.setUnavailable(LibFunc::powl);
TLI.setUnavailable(LibFunc::sinl);
TLI.setUnavailable(LibFunc::sinhl);
TLI.setUnavailable(LibFunc::sqrtl);
TLI.setUnavailable(LibFunc::tanl);
TLI.setUnavailable(LibFunc::tanhl);
// Win32 only has C89 math
TLI.setUnavailable(LibFunc::acosh);
TLI.setUnavailable(LibFunc::acoshf);
TLI.setUnavailable(LibFunc::acoshl);
TLI.setUnavailable(LibFunc::asinh);
TLI.setUnavailable(LibFunc::asinhf);
TLI.setUnavailable(LibFunc::asinhl);
TLI.setUnavailable(LibFunc::atanh);
TLI.setUnavailable(LibFunc::atanhf);
TLI.setUnavailable(LibFunc::atanhl);
TLI.setUnavailable(LibFunc::cbrt);
TLI.setUnavailable(LibFunc::cbrtf);
TLI.setUnavailable(LibFunc::cbrtl);
TLI.setUnavailable(LibFunc::exp10);
TLI.setUnavailable(LibFunc::exp10f);
TLI.setUnavailable(LibFunc::exp10l);
TLI.setUnavailable(LibFunc::exp2);
TLI.setUnavailable(LibFunc::exp2f);
TLI.setUnavailable(LibFunc::exp2l);
TLI.setUnavailable(LibFunc::expm1);
TLI.setUnavailable(LibFunc::expm1f);
TLI.setUnavailable(LibFunc::expm1l);
TLI.setUnavailable(LibFunc::log2);
TLI.setUnavailable(LibFunc::log2f);
TLI.setUnavailable(LibFunc::log2l);
TLI.setUnavailable(LibFunc::log1p);
TLI.setUnavailable(LibFunc::log1pf);
TLI.setUnavailable(LibFunc::log1pl);
TLI.setUnavailable(LibFunc::logb);
TLI.setUnavailable(LibFunc::logbf);
TLI.setUnavailable(LibFunc::logbl);
TLI.setUnavailable(LibFunc::nearbyint);
TLI.setUnavailable(LibFunc::nearbyintf);
TLI.setUnavailable(LibFunc::nearbyintl);
TLI.setUnavailable(LibFunc::rint);
TLI.setUnavailable(LibFunc::rintf);
TLI.setUnavailable(LibFunc::rintl);
TLI.setUnavailable(LibFunc::round);
TLI.setUnavailable(LibFunc::roundf);
TLI.setUnavailable(LibFunc::roundl);
TLI.setUnavailable(LibFunc::trunc);
TLI.setUnavailable(LibFunc::truncf);
TLI.setUnavailable(LibFunc::truncl);
// Win32 provides some C99 math with mangled names
TLI.setAvailableWithName(LibFunc::copysign, "_copysign");
if (T.getArch() == Triple::x86) {
// Win32 on x86 implements single-precision math functions as macros
TLI.setUnavailable(LibFunc::acosf);
TLI.setUnavailable(LibFunc::asinf);
TLI.setUnavailable(LibFunc::atanf);
TLI.setUnavailable(LibFunc::atan2f);
TLI.setUnavailable(LibFunc::ceilf);
TLI.setUnavailable(LibFunc::copysignf);
TLI.setUnavailable(LibFunc::cosf);
TLI.setUnavailable(LibFunc::coshf);
TLI.setUnavailable(LibFunc::expf);
TLI.setUnavailable(LibFunc::floorf);
TLI.setUnavailable(LibFunc::fmodf);
TLI.setUnavailable(LibFunc::logf);
TLI.setUnavailable(LibFunc::powf);
TLI.setUnavailable(LibFunc::sinf);
TLI.setUnavailable(LibFunc::sinhf);
TLI.setUnavailable(LibFunc::sqrtf);
TLI.setUnavailable(LibFunc::tanf);
TLI.setUnavailable(LibFunc::tanhf);
}
}
}
TargetLibraryInfo::TargetLibraryInfo() : ImmutablePass(ID) {
// Default to everything being available.
memset(AvailableArray, -1, sizeof(AvailableArray));
initialize(*this, Triple(), StandardNames);
}
TargetLibraryInfo::TargetLibraryInfo(const Triple &T) : ImmutablePass(ID) {
// Default to everything being available.
memset(AvailableArray, -1, sizeof(AvailableArray));
initialize(*this, T, StandardNames);
}
TargetLibraryInfo::TargetLibraryInfo(const TargetLibraryInfo &TLI)
: ImmutablePass(ID) {
memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray));
CustomNames = TLI.CustomNames;
}
bool TargetLibraryInfo::getLibFunc(StringRef funcName,
LibFunc::Func &F) const {
const char **Start = &StandardNames[0];
const char **End = &StandardNames[LibFunc::NumLibFuncs];
const char **I = std::lower_bound(Start, End, funcName);
if (I != End && *I == funcName) {
F = (LibFunc::Func)(I - Start);
return true;
}
return false;
}
/// disableAllFunctions - This disables all builtins, which is used for options
/// like -fno-builtin.
void TargetLibraryInfo::disableAllFunctions() {
memset(AvailableArray, 0, sizeof(AvailableArray));
}