[llvm] r208025 - Add llvm::function_ref (and a couple of uses of it), representing a type-erased reference to a callable object.

Richard Smith richard at metafoo.co.uk
Mon May 5 18:50:55 PDT 2014


On Mon, May 5, 2014 at 6:37 PM, Kevin Qin <kevinqindev at gmail.com> wrote:

> This commit make trunk broken. Please have a look.
>

This was already reverted. =)


> In file included from
> /home/kevin/llvm_trunk/llvm/include/llvm/Support/CrashRecoveryContext.h:15:0,
>                  from
> /home/kevin/llvm_trunk/llvm/lib/Support/CrashRecoveryContext.cpp:10:
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h: In instantiation
> of ‘static Ret llvm::function_ref<Ret()>::callback_fn(void*) [with Callable
> = llvm::CrashRecoveryContext::RunSafely(void (*)(void*), void*)::__lambda0;
> Ret = void]’:
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:105:53:
> required from ‘llvm::function_ref<Ret()>::function_ref(Callable&&) [with
> Callable = llvm::CrashRecoveryContext::RunSafely(void (*)(void*),
> void*)::__lambda0; Ret = void]’
> /home/kevin/llvm_trunk/llvm/include/llvm/Support/CrashRecoveryContext.h:82:45:
>   required from here
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:98:51: error:
> ‘void*’ is not a pointer-to-object type
>      return reinterpret_cast<Callable&>(*callable)();
>                                                    ^
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:98:51: error:
> return-statement with a value, in function returning 'void' [-fpermissive]
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h: In instantiation
> of ‘static Ret llvm::function_ref<Ret()>::callback_fn(void*) [with Callable
> = llvm::CrashRecoveryContext::RunSafelyOnThread(void (*)(void*), void*,
> unsigned int)::__lambda1; Ret = void]’:
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:105:53:
> required from ‘llvm::function_ref<Ret()>::function_ref(Callable&&) [with
> Callable = llvm::CrashRecoveryContext::RunSafelyOnThread(void (*)(void*),
> void*, unsigned int)::__lambda1; Ret = void]’
> /home/kevin/llvm_trunk/llvm/include/llvm/Support/CrashRecoveryContext.h:93:73:
>   required from here
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:98:51: error:
> ‘void*’ is not a pointer-to-object type
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:98:51: error:
> return-statement with a value, in function returning 'void' [-fpermissive]
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h: In instantiation
> of ‘static Ret llvm::function_ref<Ret()>::callback_fn(void*) [with Callable
> = llvm::function_ref<void()>&; Ret = void]’:
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:105:53:
> required from ‘llvm::function_ref<Ret()>::function_ref(Callable&&) [with
> Callable = llvm::function_ref<void()>&; Ret = void]’
> /home/kevin/llvm_trunk/llvm/lib/Support/CrashRecoveryContext.cpp:346:47:
> required from here
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:98:51: error:
> ‘void*’ is not a pointer-to-object type
> /home/kevin/llvm_trunk/llvm/include/llvm/ADT/STLExtras.h:98:51: error:
> return-statement with a value, in function returning 'void' [-fpermissive]
> make[2]: ***
> [lib/Support/CMakeFiles/LLVMSupport.dir/CrashRecoveryContext.cpp.o] Error 1
> make[1]: *** [lib/Support/CMakeFiles/LLVMSupport.dir/all] Error 2
>
>
>
> 2014-05-06 9:01 GMT+08:00 Richard Smith <richard-llvm at metafoo.co.uk>:
>
> Author: rsmith
>> Date: Mon May  5 20:01:29 2014
>> New Revision: 208025
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=208025&view=rev
>> Log:
>> Add llvm::function_ref (and a couple of uses of it), representing a
>> type-erased reference to a callable object.
>>
>> Modified:
>>     llvm/trunk/include/llvm/ADT/STLExtras.h
>>     llvm/trunk/include/llvm/Support/CrashRecoveryContext.h
>>     llvm/trunk/include/llvm/Transforms/Utils/CtorUtils.h
>>     llvm/trunk/lib/Support/CrashRecoveryContext.cpp
>>     llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
>>     llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
>>     llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp
>>
>> Modified: llvm/trunk/include/llvm/ADT/STLExtras.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/STLExtras.h?rev=208025&r1=208024&r2=208025&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/ADT/STLExtras.h (original)
>> +++ llvm/trunk/include/llvm/ADT/STLExtras.h Mon May  5 20:01:29 2014
>> @@ -55,6 +55,131 @@ struct greater_ptr : public std::binary_
>>    }
>>  };
>>
>> +/// 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:
>>  //
>>
>> Modified: llvm/trunk/include/llvm/Support/CrashRecoveryContext.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CrashRecoveryContext.h?rev=208025&r1=208024&r2=208025&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Support/CrashRecoveryContext.h (original)
>> +++ llvm/trunk/include/llvm/Support/CrashRecoveryContext.h Mon May  5
>> 20:01:29 2014
>> @@ -12,11 +12,13 @@
>>
>>  #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
>> @@ -46,21 +48,10 @@ class CrashRecoveryContext {
>>    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);
>>
>> @@ -86,11 +77,9 @@ public:
>>    /// 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(void (*Fn)(void*), void *UserData);
>> -  template<typename Functor>
>> -  bool RunSafely(Functor Fn) {
>> -    FunctorAdaptor<Functor> Adaptor = { Fn };
>> -    return RunSafely(Adaptor.fn(), Adaptor.arg());
>> +  bool RunSafely(function_ref<void()> Fn);
>> +  bool RunSafely(void (*Fn)(void*), void *UserData) {
>> +    return RunSafely([&]() { Fn(UserData); });
>>    }
>>
>>    /// \brief Execute the provide callback function (with the given
>> arguments) in
>> @@ -98,12 +87,10 @@ public:
>>    /// 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);
>> -  template<typename Functor>
>> -  bool RunSafelyOnThread(Functor Fn, unsigned RequestedStackSize = 0) {
>> -    FunctorAdaptor<Functor> Adaptor = { Fn };
>> -    return RunSafelyOnThread(Adaptor.fn(), Adaptor.arg(),
>> RequestedStackSize);
>> +                         unsigned RequestedStackSize = 0) {
>> +    return RunSafelyOnThread([&]() { Fn(UserData); },
>> RequestedStackSize);
>>    }
>>
>>    /// \brief Explicitly trigger a crash recovery in the current process,
>> and
>>
>> Modified: llvm/trunk/include/llvm/Transforms/Utils/CtorUtils.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/CtorUtils.h?rev=208025&r1=208024&r2=208025&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Transforms/Utils/CtorUtils.h (original)
>> +++ llvm/trunk/include/llvm/Transforms/Utils/CtorUtils.h Mon May  5
>> 20:01:29 2014
>> @@ -14,8 +14,7 @@
>>  #ifndef LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H
>>  #define LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H
>>
>> -#include <functional>
>> -#include <vector>
>> +#include "llvm/ADT/STLExtras.h"
>>
>>  namespace llvm {
>>
>> @@ -23,12 +22,10 @@ class GlobalVariable;
>>  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, ShouldRemoveCtor ShouldRemove,
>> -                             void *Context);
>> +bool optimizeGlobalCtorsList(Module &M,
>> +                             function_ref<bool(Function *)>
>> ShouldRemove);
>>
>>  } // End llvm namespace
>>
>>
>> Modified: llvm/trunk/lib/Support/CrashRecoveryContext.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CrashRecoveryContext.cpp?rev=208025&r1=208024&r2=208025&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Support/CrashRecoveryContext.cpp (original)
>> +++ llvm/trunk/lib/Support/CrashRecoveryContext.cpp Mon May  5 20:01:29
>> 2014
>> @@ -301,7 +301,7 @@ void CrashRecoveryContext::Disable() {
>>
>>  #endif
>>
>> -bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) {
>> +bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
>>    // If crash recovery is disabled, do nothing.
>>    if (gCrashRecoveryEnabled) {
>>      assert(!Impl && "Crash recovery context already initialized!");
>> @@ -313,7 +313,7 @@ bool CrashRecoveryContext::RunSafely(voi
>>      }
>>    }
>>
>> -  Fn(UserData);
>> +  Fn();
>>    return true;
>>  }
>>
>> @@ -334,8 +334,7 @@ const std::string &CrashRecoveryContext:
>>
>>  namespace {
>>  struct RunSafelyOnThreadInfo {
>> -  void (*Fn)(void*);
>> -  void *Data;
>> +  function_ref<void()> Fn;
>>    CrashRecoveryContext *CRC;
>>    bool Result;
>>  };
>> @@ -344,11 +343,11 @@ struct RunSafelyOnThreadInfo {
>>  static void RunSafelyOnThread_Dispatch(void *UserData) {
>>    RunSafelyOnThreadInfo *Info =
>>      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) {
>> -  RunSafelyOnThreadInfo Info = { Fn, UserData, this, false };
>> +  RunSafelyOnThreadInfo Info = { Fn, this, false };
>>    llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info,
>> RequestedStackSize);
>>    if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
>>      CRC->setSwitchedThread();
>>
>> Modified: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp?rev=208025&r1=208024&r2=208025&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp (original)
>> +++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp Mon May  5 20:01:29 2014
>> @@ -54,16 +54,16 @@ namespace {
>>
>>      bool RemoveUnusedGlobalValue(GlobalValue &GV);
>>    };
>> +}
>>
>>  /// 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();
>>    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",
>> @@ -75,7 +75,7 @@ bool GlobalDCE::runOnModule(Module &M) {
>>    bool Changed = false;
>>
>>    // 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.
>>    for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
>>
>> Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=208025&r1=208024&r2=208025&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
>> +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Mon May  5 20:01:29 2014
>> @@ -3022,10 +3022,9 @@ bool GlobalOpt::runOnModule(Module &M) {
>>      LocalChange |= OptimizeFunctions(M);
>>
>>      // Optimize global_ctors list.
>> -    LocalChange |= optimizeGlobalCtorsList(M, [](void *C, Function *F)
>> -> bool {
>> -      GlobalOpt *self = static_cast<GlobalOpt *>(C);
>> -      return EvaluateStaticConstructor(F, self->DL, self->TLI);
>> -    }, this);
>> +    LocalChange |= optimizeGlobalCtorsList(M, [&](Function *F) {
>> +      return EvaluateStaticConstructor(F, DL, TLI);
>> +    });
>>
>>      // Optimize non-address-taken globals.
>>      LocalChange |= OptimizeGlobalVars(M);
>>
>> Modified: llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp?rev=208025&r1=208024&r2=208025&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp (original)
>> +++ llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp Mon May  5 20:01:29 2014
>> @@ -132,8 +132,8 @@ GlobalVariable *findGlobalCtors(Module &
>>
>>  /// 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, ShouldRemoveCtor ShouldRemove,
>> -                             void *Context) {
>> +bool optimizeGlobalCtorsList(Module &M,
>> +                             function_ref<bool(Function *)>
>> ShouldRemove) {
>>    GlobalVariable *GlobalCtors = findGlobalCtors(M);
>>    if (!GlobalCtors)
>>      return false;
>> @@ -163,7 +163,7 @@ bool optimizeGlobalCtorsList(Module &M,
>>        continue;
>>
>>      // If we can evaluate the ctor at compile time, do.
>> -    if (ShouldRemove(Context, F)) {
>> +    if (ShouldRemove(F)) {
>>        Ctors.erase(Ctors.begin() + i);
>>        MadeChange = true;
>>        --i;
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
>
> --
> Best Regards,
>
> Kevin Qin
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140505/f14af865/attachment.html>


More information about the llvm-commits mailing list