mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	Re-commit r208025, reverted in r208030, with a fix for a conformance issue
which GCC detects and Clang does not! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208033 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -108,6 +108,8 @@ unlikely to be supported by our host compilers. | |||||||
| * Lambdas: N2927_ | * Lambdas: N2927_ | ||||||
|  |  | ||||||
|   * But *not* ``std::function``, until Clang implements `MSVC-compatible RTTI`_. |   * But *not* ``std::function``, until Clang implements `MSVC-compatible RTTI`_. | ||||||
|  |     In many cases, you may be able to use ``llvm::function_ref`` instead, and it | ||||||
|  |     is a superior choice in those cases. | ||||||
|   * And *not* lambdas with default arguments. |   * And *not* lambdas with default arguments. | ||||||
|  |  | ||||||
| * ``decltype``: N2343_ | * ``decltype``: N2343_ | ||||||
|   | |||||||
| @@ -263,6 +263,78 @@ almost never be stored or mentioned directly.  They are intended solely for use | |||||||
| when defining a function which should be able to efficiently accept concatenated | when defining a function which should be able to efficiently accept concatenated | ||||||
| strings. | strings. | ||||||
|  |  | ||||||
|  | .. _function_apis: | ||||||
|  |  | ||||||
|  | Passing functions and other callable objects | ||||||
|  | -------------------------------------------- | ||||||
|  |  | ||||||
|  | Sometimes you may want a function to be passed a callback object. In order to | ||||||
|  | support lambda expressions and other function objects, you should not use the | ||||||
|  | traditional C approach of taking a function pointer and an opaque cookie: | ||||||
|  |  | ||||||
|  | .. code-block:: c++ | ||||||
|  |  | ||||||
|  |     void takeCallback(bool (*Callback)(Function *, void *), void *Cookie); | ||||||
|  |  | ||||||
|  | Instead, use one of the following approaches: | ||||||
|  |  | ||||||
|  | Function template | ||||||
|  | ^^^^^^^^^^^^^^^^^ | ||||||
|  |  | ||||||
|  | If you don't mind putting the definition of your function into a header file, | ||||||
|  | make it a function template that is templated on the callable type. | ||||||
|  |  | ||||||
|  | .. code-block:: c++ | ||||||
|  |  | ||||||
|  |     template<typename Callable> | ||||||
|  |     void takeCallback(Callable Callback) { | ||||||
|  |       Callback(1, 2, 3); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | The ``function_ref`` class template | ||||||
|  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
|  |  | ||||||
|  | The ``function_ref`` | ||||||
|  | (`doxygen <http://llvm.org/doxygen/classllvm_1_1function_ref.html>`__) class | ||||||
|  | template represents a reference to a callable object, templated over the type | ||||||
|  | of the callable. This is a good choice for passing a callback to a function, | ||||||
|  | if you don't need to hold onto the callback after the function returns. | ||||||
|  |  | ||||||
|  | ``function_ref<Ret(Param1, Param2, ...)>`` can be implicitly constructed from | ||||||
|  | any callable object that can be called with arguments of type ``Param1``, | ||||||
|  | ``Param2``, ..., and returns a value that can be converted to type ``Ret``. | ||||||
|  | For example: | ||||||
|  |  | ||||||
|  | .. code-block:: c++ | ||||||
|  |  | ||||||
|  |     void visitBasicBlocks(Function *F, function_ref<bool (BasicBlock*)> Callback) { | ||||||
|  |       for (BasicBlock &BB : *F) | ||||||
|  |         if (Callback(&BB)) | ||||||
|  |           return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | can be called using: | ||||||
|  |  | ||||||
|  | .. code-block:: c++ | ||||||
|  |  | ||||||
|  |     visitBasicBlocks(F, [&](BasicBlock *BB) { | ||||||
|  |       if (process(BB)) | ||||||
|  |         return isEmpty(BB); | ||||||
|  |       return false; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | Note that a ``function_ref`` object contains pointers to external memory, so | ||||||
|  | it is not generally safe to store an instance of the class (unless you know | ||||||
|  | that the external storage will not be freed). | ||||||
|  | ``function_ref`` is small enough that it should always be passed by value. | ||||||
|  |  | ||||||
|  | ``std::function`` | ||||||
|  | ^^^^^^^^^^^^^^^^^ | ||||||
|  |  | ||||||
|  | You cannot use ``std::function`` within LLVM code, because it is not supported | ||||||
|  | by all our target toolchains. | ||||||
|  |  | ||||||
|  |  | ||||||
| .. _DEBUG: | .. _DEBUG: | ||||||
|  |  | ||||||
| The ``DEBUG()`` macro and ``-debug`` option | The ``DEBUG()`` macro and ``-debug`` option | ||||||
|   | |||||||
| @@ -55,6 +55,131 @@ struct greater_ptr : public std::binary_function<Ty, Ty, bool> { | |||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /// 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<typename std::remove_reference<Callable>::type>), | ||||||
|  |         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<typename std::remove_reference<Callable>::type>), | ||||||
|  |         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<typename std::remove_reference<Callable>::type>), | ||||||
|  |         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<typename std::remove_reference<Callable>::type>), | ||||||
|  |         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<typename std::remove_reference<Callable>::type>), | ||||||
|  |         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 | // deleter - Very very very simple method that is used to invoke operator | ||||||
| // delete on something.  It is used like this: | // delete on something.  It is used like this: | ||||||
| // | // | ||||||
|   | |||||||
| @@ -12,6 +12,8 @@ | |||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
|  | #include "llvm/ADT/STLExtras.h" | ||||||
|  |  | ||||||
| namespace llvm { | namespace llvm { | ||||||
| class StringRef; | class StringRef; | ||||||
|  |  | ||||||
| @@ -46,17 +48,6 @@ class CrashRecoveryContext { | |||||||
|   void *Impl; |   void *Impl; | ||||||
|   CrashRecoveryContextCleanup *head; |   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: | public: | ||||||
|   CrashRecoveryContext() : Impl(nullptr), head(nullptr) {} |   CrashRecoveryContext() : Impl(nullptr), head(nullptr) {} | ||||||
|   ~CrashRecoveryContext(); |   ~CrashRecoveryContext(); | ||||||
| @@ -86,11 +77,9 @@ public: | |||||||
|   /// make as little assumptions as possible about the program state when |   /// make as little assumptions as possible about the program state when | ||||||
|   /// RunSafely has returned false. Clients can use getBacktrace() to retrieve |   /// RunSafely has returned false. Clients can use getBacktrace() to retrieve | ||||||
|   /// the backtrace of the crash on failures. |   /// the backtrace of the crash on failures. | ||||||
|   bool RunSafely(void (*Fn)(void*), void *UserData); |   bool RunSafely(function_ref<void()> Fn); | ||||||
|   template<typename Functor> |   bool RunSafely(void (*Fn)(void*), void *UserData) { | ||||||
|   bool RunSafely(Functor Fn) { |     return RunSafely([&]() { Fn(UserData); }); | ||||||
|     FunctorAdaptor<Functor> Adaptor = { Fn }; |  | ||||||
|     return RunSafely(Adaptor.fn(), Adaptor.arg()); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /// \brief Execute the provide callback function (with the given arguments) in |   /// \brief Execute the provide callback function (with the given arguments) in | ||||||
| @@ -98,12 +87,10 @@ public: | |||||||
|   /// requested stack size). |   /// requested stack size). | ||||||
|   /// |   /// | ||||||
|   /// See RunSafely() and llvm_execute_on_thread(). |   /// See RunSafely() and llvm_execute_on_thread(). | ||||||
|  |   bool RunSafelyOnThread(function_ref<void()>, unsigned RequestedStackSize = 0); | ||||||
|   bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, |   bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, | ||||||
|                          unsigned RequestedStackSize = 0); |                          unsigned RequestedStackSize = 0) { | ||||||
|   template<typename Functor> |     return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize); | ||||||
|   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 |   /// \brief Explicitly trigger a crash recovery in the current process, and | ||||||
|   | |||||||
| @@ -14,8 +14,7 @@ | |||||||
| #ifndef LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H | #ifndef LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H | ||||||
| #define LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H | #define LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H | ||||||
|  |  | ||||||
| #include <functional> | #include "llvm/ADT/STLExtras.h" | ||||||
| #include <vector> |  | ||||||
|  |  | ||||||
| namespace llvm { | namespace llvm { | ||||||
|  |  | ||||||
| @@ -23,12 +22,10 @@ class GlobalVariable; | |||||||
| class Function; | class Function; | ||||||
| class Module; | class Module; | ||||||
|  |  | ||||||
| typedef bool (*ShouldRemoveCtor)(void *, Function *); |  | ||||||
|  |  | ||||||
| /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the | /// 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. | /// entries for which it returns true.  Return true if anything changed. | ||||||
| bool optimizeGlobalCtorsList(Module &M, ShouldRemoveCtor ShouldRemove, | bool optimizeGlobalCtorsList(Module &M, | ||||||
|                              void *Context); |                              function_ref<bool(Function *)> ShouldRemove); | ||||||
|  |  | ||||||
| } // End llvm namespace | } // End llvm namespace | ||||||
|  |  | ||||||
|   | |||||||
| @@ -301,7 +301,7 @@ void CrashRecoveryContext::Disable() { | |||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) { | bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { | ||||||
|   // If crash recovery is disabled, do nothing. |   // If crash recovery is disabled, do nothing. | ||||||
|   if (gCrashRecoveryEnabled) { |   if (gCrashRecoveryEnabled) { | ||||||
|     assert(!Impl && "Crash recovery context already initialized!"); |     assert(!Impl && "Crash recovery context already initialized!"); | ||||||
| @@ -313,7 +313,7 @@ bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Fn(UserData); |   Fn(); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -334,8 +334,7 @@ const std::string &CrashRecoveryContext::getBacktrace() const { | |||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
| struct RunSafelyOnThreadInfo { | struct RunSafelyOnThreadInfo { | ||||||
|   void (*Fn)(void*); |   function_ref<void()> Fn; | ||||||
|   void *Data; |  | ||||||
|   CrashRecoveryContext *CRC; |   CrashRecoveryContext *CRC; | ||||||
|   bool Result; |   bool Result; | ||||||
| }; | }; | ||||||
| @@ -344,11 +343,11 @@ struct RunSafelyOnThreadInfo { | |||||||
| static void RunSafelyOnThread_Dispatch(void *UserData) { | static void RunSafelyOnThread_Dispatch(void *UserData) { | ||||||
|   RunSafelyOnThreadInfo *Info = |   RunSafelyOnThreadInfo *Info = | ||||||
|     reinterpret_cast<RunSafelyOnThreadInfo*>(UserData); |     reinterpret_cast<RunSafelyOnThreadInfo*>(UserData); | ||||||
|   Info->Result = Info->CRC->RunSafely(Info->Fn, Info->Data); |   Info->Result = Info->CRC->RunSafely(Info->Fn); | ||||||
| } | } | ||||||
| bool CrashRecoveryContext::RunSafelyOnThread(void (*Fn)(void*), void *UserData, | bool CrashRecoveryContext::RunSafelyOnThread(function_ref<void()> Fn, | ||||||
|                                              unsigned RequestedStackSize) { |                                              unsigned RequestedStackSize) { | ||||||
|   RunSafelyOnThreadInfo Info = { Fn, UserData, this, false }; |   RunSafelyOnThreadInfo Info = { Fn, this, false }; | ||||||
|   llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize); |   llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize); | ||||||
|   if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl) |   if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl) | ||||||
|     CRC->setSwitchedThread(); |     CRC->setSwitchedThread(); | ||||||
|   | |||||||
| @@ -54,16 +54,16 @@ namespace { | |||||||
|  |  | ||||||
|     bool RemoveUnusedGlobalValue(GlobalValue &GV); |     bool RemoveUnusedGlobalValue(GlobalValue &GV); | ||||||
|   }; |   }; | ||||||
|  | } | ||||||
|  |  | ||||||
| /// Returns true if F contains only a single "ret" instruction. | /// Returns true if F contains only a single "ret" instruction. | ||||||
| bool isEmptyFunction(void *Context, Function *F) { | static bool isEmptyFunction(Function *F) { | ||||||
|   BasicBlock &Entry = F->getEntryBlock(); |   BasicBlock &Entry = F->getEntryBlock(); | ||||||
|   if (Entry.size() != 1 || !isa<ReturnInst>(Entry.front())) |   if (Entry.size() != 1 || !isa<ReturnInst>(Entry.front())) | ||||||
|     return false; |     return false; | ||||||
|   ReturnInst &RI = cast<ReturnInst>(Entry.front()); |   ReturnInst &RI = cast<ReturnInst>(Entry.front()); | ||||||
|   return RI.getReturnValue() == NULL; |   return RI.getReturnValue() == NULL; | ||||||
| } | } | ||||||
| } |  | ||||||
|  |  | ||||||
| char GlobalDCE::ID = 0; | char GlobalDCE::ID = 0; | ||||||
| INITIALIZE_PASS(GlobalDCE, "globaldce", | INITIALIZE_PASS(GlobalDCE, "globaldce", | ||||||
| @@ -75,7 +75,7 @@ bool GlobalDCE::runOnModule(Module &M) { | |||||||
|   bool Changed = false; |   bool Changed = false; | ||||||
|  |  | ||||||
|   // Remove empty functions from the global ctors list. |   // Remove empty functions from the global ctors list. | ||||||
|   Changed |= optimizeGlobalCtorsList(M, isEmptyFunction, nullptr); |   Changed |= optimizeGlobalCtorsList(M, isEmptyFunction); | ||||||
|  |  | ||||||
|   // Loop over the module, adding globals which are obviously necessary. |   // Loop over the module, adding globals which are obviously necessary. | ||||||
|   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { |   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { | ||||||
|   | |||||||
| @@ -3022,10 +3022,9 @@ bool GlobalOpt::runOnModule(Module &M) { | |||||||
|     LocalChange |= OptimizeFunctions(M); |     LocalChange |= OptimizeFunctions(M); | ||||||
|  |  | ||||||
|     // Optimize global_ctors list. |     // Optimize global_ctors list. | ||||||
|     LocalChange |= optimizeGlobalCtorsList(M, [](void *C, Function *F) -> bool { |     LocalChange |= optimizeGlobalCtorsList(M, [&](Function *F) { | ||||||
|       GlobalOpt *self = static_cast<GlobalOpt *>(C); |       return EvaluateStaticConstructor(F, DL, TLI); | ||||||
|       return EvaluateStaticConstructor(F, self->DL, self->TLI); |     }); | ||||||
|     }, this); |  | ||||||
|  |  | ||||||
|     // Optimize non-address-taken globals. |     // Optimize non-address-taken globals. | ||||||
|     LocalChange |= OptimizeGlobalVars(M); |     LocalChange |= OptimizeGlobalVars(M); | ||||||
|   | |||||||
| @@ -132,8 +132,8 @@ GlobalVariable *findGlobalCtors(Module &M) { | |||||||
|  |  | ||||||
| /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the | /// 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. | /// entries for which it returns true.  Return true if anything changed. | ||||||
| bool optimizeGlobalCtorsList(Module &M, ShouldRemoveCtor ShouldRemove, | bool optimizeGlobalCtorsList(Module &M, | ||||||
|                              void *Context) { |                              function_ref<bool(Function *)> ShouldRemove) { | ||||||
|   GlobalVariable *GlobalCtors = findGlobalCtors(M); |   GlobalVariable *GlobalCtors = findGlobalCtors(M); | ||||||
|   if (!GlobalCtors) |   if (!GlobalCtors) | ||||||
|     return false; |     return false; | ||||||
| @@ -163,7 +163,7 @@ bool optimizeGlobalCtorsList(Module &M, ShouldRemoveCtor ShouldRemove, | |||||||
|       continue; |       continue; | ||||||
|  |  | ||||||
|     // If we can evaluate the ctor at compile time, do. |     // If we can evaluate the ctor at compile time, do. | ||||||
|     if (ShouldRemove(Context, F)) { |     if (ShouldRemove(F)) { | ||||||
|       Ctors.erase(Ctors.begin() + i); |       Ctors.erase(Ctors.begin() + i); | ||||||
|       MadeChange = true; |       MadeChange = true; | ||||||
|       --i; |       --i; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user