}
};
-/// An efficient, type-erasing, non-owning reference to a callable. This is
-/// intended for use as the type of a function parameter that is not used
-/// after the function in question returns.
-///
-/// This class does not own the callable, so it is not in general safe to store
-/// a function_ref.
-template<typename Fn> class function_ref;
-
-#if LLVM_HAS_VARIADIC_TEMPLATES
-
-template<typename Ret, typename ...Params>
-class function_ref<Ret(Params...)> {
- Ret (*callback)(void *callable, Params ...params);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable, Params ...params) {
- return reinterpret_cast<Callable&>(*callable)(
- std::forward<Params>(params)...);
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()(Params ...params) const {
- return callback(callable, std::forward<Params>(params)...);
- }
-};
-
-#else
-
-template<typename Ret>
-class function_ref<Ret()> {
- Ret (*callback)(void *callable);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable) {
- return reinterpret_cast<Callable&>(*callable)();
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()() const { return callback(callable); }
-};
-
-template<typename Ret, typename Param1>
-class function_ref<Ret(Param1)> {
- Ret (*callback)(void *callable, Param1 param1);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable, Param1 param1) {
- return reinterpret_cast<Callable&>(*callable)(
- std::forward<Param1>(param1));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()(Param1 param1) {
- return callback(callable, std::forward<Param1>(param1));
- }
-};
-
-template<typename Ret, typename Param1, typename Param2>
-class function_ref<Ret(Param1, Param2)> {
- Ret (*callback)(void *callable, Param1 param1, Param2 param2);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable, Param1 param1, Param2 param2) {
- return reinterpret_cast<Callable&>(*callable)(
- std::forward<Param1>(param1),
- std::forward<Param2>(param2));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()(Param1 param1, Param2 param2) {
- return callback(callable,
- std::forward<Param1>(param1),
- std::forward<Param2>(param2));
- }
-};
-
-template<typename Ret, typename Param1, typename Param2, typename Param3>
-class function_ref<Ret(Param1, Param2, Param3)> {
- Ret (*callback)(void *callable, Param1 param1, Param2 param2, Param3 param3);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable, Param1 param1, Param2 param2,
- Param3 param3) {
- return reinterpret_cast<Callable&>(*callable)(
- std::forward<Param1>(param1),
- std::forward<Param2>(param2),
- std::forward<Param3>(param3));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()(Param1 param1, Param2 param2, Param3 param3) {
- return callback(callable,
- std::forward<Param1>(param1),
- std::forward<Param2>(param2),
- std::forward<Param3>(param3));
- }
-};
-
-#endif
-
// deleter - Very very very simple method that is used to invoke operator
// delete on something. It is used like this:
//
#include <string>
-#include "llvm/ADT/STLExtras.h"
-
namespace llvm {
class StringRef;
class CrashRecoveryContextCleanup;
-
+
/// \brief Crash recovery helper object.
///
/// This class implements support for running operations in a safe context so
void *Impl;
CrashRecoveryContextCleanup *head;
+ /// An adaptor to convert an arbitrary functor into a void(void*), void* pair.
+ template<typename T> struct FunctorAdaptor {
+ T Fn;
+ static void invoke(void *Data) {
+ return static_cast<FunctorAdaptor<T>*>(Data)->Fn();
+ }
+ typedef void Callback(void*);
+ Callback *fn() { return &invoke; }
+ void *arg() { return this; }
+ };
+
public:
CrashRecoveryContext() : Impl(nullptr), head(nullptr) {}
~CrashRecoveryContext();
-
+
void registerCleanup(CrashRecoveryContextCleanup *cleanup);
void unregisterCleanup(CrashRecoveryContextCleanup *cleanup);
/// make as little assumptions as possible about the program state when
/// RunSafely has returned false. Clients can use getBacktrace() to retrieve
/// the backtrace of the crash on failures.
- bool RunSafely(function_ref<void()> Fn);
- bool RunSafely(void (*Fn)(void*), void *UserData) {
- return RunSafely([&]() { Fn(UserData); });
+ bool RunSafely(void (*Fn)(void*), void *UserData);
+ template<typename Functor>
+ bool RunSafely(Functor Fn) {
+ FunctorAdaptor<Functor> Adaptor = { Fn };
+ return RunSafely(Adaptor.fn(), Adaptor.arg());
}
/// \brief Execute the provide callback function (with the given arguments) in
/// requested stack size).
///
/// See RunSafely() and llvm_execute_on_thread().
- bool RunSafelyOnThread(function_ref<void()>, unsigned RequestedStackSize = 0);
bool RunSafelyOnThread(void (*Fn)(void*), void *UserData,
- unsigned RequestedStackSize = 0) {
- return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize);
+ unsigned RequestedStackSize = 0);
+ template<typename Functor>
+ bool RunSafelyOnThread(Functor Fn, unsigned RequestedStackSize = 0) {
+ FunctorAdaptor<Functor> Adaptor = { Fn };
+ return RunSafelyOnThread(Adaptor.fn(), Adaptor.arg(), RequestedStackSize);
}
/// \brief Explicitly trigger a crash recovery in the current process, and
#ifndef LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H
#define LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H
-#include "llvm/ADT/STLExtras.h"
+#include <functional>
+#include <vector>
namespace llvm {
class Function;
class Module;
+typedef bool (*ShouldRemoveCtor)(void *, Function *);
+
/// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
/// entries for which it returns true. Return true if anything changed.
-bool optimizeGlobalCtorsList(Module &M,
- function_ref<bool(Function *)> ShouldRemove);
+bool optimizeGlobalCtorsList(Module &M, ShouldRemoveCtor ShouldRemove,
+ void *Context);
} // End llvm namespace
#endif
-bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
+bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) {
// If crash recovery is disabled, do nothing.
if (gCrashRecoveryEnabled) {
assert(!Impl && "Crash recovery context already initialized!");
}
}
- Fn();
+ Fn(UserData);
return true;
}
namespace {
struct RunSafelyOnThreadInfo {
- function_ref<void()> Fn;
+ void (*Fn)(void*);
+ void *Data;
CrashRecoveryContext *CRC;
bool Result;
};
static void RunSafelyOnThread_Dispatch(void *UserData) {
RunSafelyOnThreadInfo *Info =
reinterpret_cast<RunSafelyOnThreadInfo*>(UserData);
- Info->Result = Info->CRC->RunSafely(Info->Fn);
+ Info->Result = Info->CRC->RunSafely(Info->Fn, Info->Data);
}
-bool CrashRecoveryContext::RunSafelyOnThread(function_ref<void()> Fn,
+bool CrashRecoveryContext::RunSafelyOnThread(void (*Fn)(void*), void *UserData,
unsigned RequestedStackSize) {
- RunSafelyOnThreadInfo Info = { Fn, this, false };
+ RunSafelyOnThreadInfo Info = { Fn, UserData, this, false };
llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize);
if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
CRC->setSwitchedThread();
bool RemoveUnusedGlobalValue(GlobalValue &GV);
};
-}
/// Returns true if F contains only a single "ret" instruction.
-static bool isEmptyFunction(Function *F) {
+bool isEmptyFunction(void *Context, Function *F) {
BasicBlock &Entry = F->getEntryBlock();
if (Entry.size() != 1 || !isa<ReturnInst>(Entry.front()))
return false;
ReturnInst &RI = cast<ReturnInst>(Entry.front());
return RI.getReturnValue() == NULL;
}
+}
char GlobalDCE::ID = 0;
INITIALIZE_PASS(GlobalDCE, "globaldce",
bool Changed = false;
// Remove empty functions from the global ctors list.
- Changed |= optimizeGlobalCtorsList(M, isEmptyFunction);
+ Changed |= optimizeGlobalCtorsList(M, isEmptyFunction, nullptr);
// Loop over the module, adding globals which are obviously necessary.
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
LocalChange |= OptimizeFunctions(M);
// Optimize global_ctors list.
- LocalChange |= optimizeGlobalCtorsList(M, [&](Function *F) {
- return EvaluateStaticConstructor(F, DL, TLI);
- });
+ LocalChange |= optimizeGlobalCtorsList(M, [](void *C, Function *F) -> bool {
+ GlobalOpt *self = static_cast<GlobalOpt *>(C);
+ return EvaluateStaticConstructor(F, self->DL, self->TLI);
+ }, this);
// Optimize non-address-taken globals.
LocalChange |= OptimizeGlobalVars(M);
/// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
/// entries for which it returns true. Return true if anything changed.
-bool optimizeGlobalCtorsList(Module &M,
- function_ref<bool(Function *)> ShouldRemove) {
+bool optimizeGlobalCtorsList(Module &M, ShouldRemoveCtor ShouldRemove,
+ void *Context) {
GlobalVariable *GlobalCtors = findGlobalCtors(M);
if (!GlobalCtors)
return false;
continue;
// If we can evaluate the ctor at compile time, do.
- if (ShouldRemove(F)) {
+ if (ShouldRemove(Context, F)) {
Ctors.erase(Ctors.begin() + i);
MadeChange = true;
--i;