Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions src/wasm-traversal.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ namespace wasm {

// A generic visitor, defaulting to doing nothing on each visit

template<typename SubType, typename ReturnType = void> struct Visitor {
template<typename SubType, typename ReturnType_ = void> struct Visitor {
// Capture the parameter in something we can access later.
using ReturnType = ReturnType_;

// Expression visitors
#define DELEGATE(CLASS_TO_VISIT) \
ReturnType visit##CLASS_TO_VISIT(CLASS_TO_VISIT* curr) { \
Expand Down Expand Up @@ -351,9 +354,40 @@ struct PostWalker : public Walker<SubType, VisitorType> {

#define DELEGATE_ID curr->_id

// Don't push empty tasks, that is, functions that we just push to the
// stack, pop, and then nothing happens when we call the empty function. The
// default visitFoo() in Visitor is empty, and the static doVisitFoo() in
// Walker just calls it, so if neither have been changed, we know that
// nothing will run.
//
// Note that we check Visitor<..> and not VisitorType. Only Visitor is the
// actual top type we know has empty visitors, while VisitorType could be
// anything.
//
// Unfortunately we must avoid this in gcc 11 and earlier, as they error on
// these function pointers not being constexpr. Remove the constexpr there.
// Note that even if this ends up being a runtime check, it should be faster
// than pushing empty tasks, as the check is much faster than the push/pop/
// call, and a large number of our calls (most, perhaps) are not overridden.
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 11
#define DELEGATE_START(id) \
if (&SubType::visit##id != \
&Visitor<SubType, typename SubType::ReturnType>::visit##id || \
&SubType::doVisit##id != &Walker<SubType, VisitorType>::doVisit##id) { \
self->pushTask(SubType::doVisit##id, currp); \
} \
[[maybe_unused]] auto* cast = curr->cast<id>();
#else
#define DELEGATE_START(id) \
self->pushTask(SubType::doVisit##id, currp); \
if constexpr (&SubType::visit##id != \
&Visitor<SubType, \
typename SubType::ReturnType>::visit##id || \
&SubType::doVisit##id != \
&Walker<SubType, VisitorType>::doVisit##id) { \
self->pushTask(SubType::doVisit##id, currp); \
} \
[[maybe_unused]] auto* cast = curr->cast<id>();
#endif

#define DELEGATE_GET_FIELD(id, field) cast->field

Expand Down
Loading