2424namespace llvm {
2525class Function ;
2626class Instruction ;
27+ class IntrinsicInst ;
2728class Module ;
2829} // namespace llvm
2930
@@ -90,6 +91,43 @@ namespace detail {
9091
9192class VisitorBase ;
9293
94+ // / @brief Key describing the condition of a visitor case
95+ class VisitorKey {
96+ friend class VisitorBase ;
97+
98+ public:
99+ template <typename OpT> static VisitorKey op () {
100+ VisitorKey key{Kind::OpDescription};
101+ key.m_description = &OpDescription::get<OpT>();
102+ return key;
103+ }
104+
105+ static VisitorKey intrinsic (unsigned id) {
106+ VisitorKey key{Kind::Intrinsic};
107+ key.m_intrinsicId = id;
108+ return key;
109+ }
110+
111+ bool matchInstruction (llvm::Instruction &inst) const ;
112+ bool matchDeclaration (llvm::Function &decl) const ;
113+
114+ bool canMatchDeclaration () const {
115+ return m_kind == Kind::Intrinsic || m_description->canMatchDeclaration ();
116+ }
117+
118+ private:
119+ enum class Kind {
120+ OpDescription,
121+ Intrinsic,
122+ };
123+
124+ VisitorKey (Kind kind) : m_kind(kind) {}
125+
126+ Kind m_kind;
127+ const OpDescription *m_description = nullptr ;
128+ unsigned m_intrinsicId = 0 ;
129+ };
130+
93131using VisitorCallback = void (void *, void *, llvm::Instruction *);
94132using PayloadProjectionCallback = void *(void *);
95133
@@ -101,13 +139,15 @@ struct PayloadProjection {
101139};
102140
103141struct VisitorCase {
104- const OpDescription *description = nullptr ;
142+ VisitorKey key ;
105143 VisitorCallback *callback = nullptr ;
106144 void *callbackData = nullptr ;
107145
108146 // If non-negative, a byte offset to apply to the payload. If negative,
109147 // a shifted index into the projections vector.
110148 ssize_t projection = 0 ;
149+
150+ explicit VisitorCase (VisitorKey key) : key(key) {}
111151};
112152
113153template <typename PayloadT, typename NestedPayloadT>
@@ -124,7 +164,7 @@ class VisitorBuilderBase {
124164
125165 void setStrategy (VisitorStrategy strategy);
126166
127- void add (const OpDescription &desc , void *extra, VisitorCallback *fn);
167+ void add (VisitorKey key , void *extra, VisitorCallback *fn);
128168
129169public:
130170 PayloadProjectionCallback *m_projection = nullptr ;
@@ -223,13 +263,13 @@ class VisitorBuilder : private detail::VisitorBuilderBase {
223263 Visitor<PayloadT> build () { return std::move (*this ); }
224264
225265 template <typename OpT> VisitorBuilder &add (void (*fn)(PayloadT &, OpT &)) {
226- VisitorBuilderBase::add (
227- OpDescription::get<OpT>(),
228- ( void *)fn,
229- []( void *extra, void *payload, llvm::Instruction *op) {
230- auto fn = ( void (*)(PayloadT &, OpT &))extra;
231- fn (* static_cast < PayloadT *>(payload), * llvm::cast<OpT>(op));
232- } );
266+ addCase<OpT>(detail::VisitorKey::op<OpT>(), fn);
267+ return * this ;
268+ }
269+
270+ VisitorBuilder & addIntrinsic ( unsigned id,
271+ void (*fn)( PayloadT &, llvm::IntrinsicInst &)) {
272+ addCase<llvm::IntrinsicInst>( detail::VisitorKey::intrinsic (id), fn );
233273 return *this ;
234274 }
235275
@@ -258,6 +298,17 @@ class VisitorBuilder : private detail::VisitorBuilderBase {
258298private:
259299 explicit VisitorBuilder (VisitorBuilderBase *parent)
260300 : VisitorBuilderBase(parent) {}
301+
302+ template <typename OpT>
303+ void addCase (detail::VisitorKey key, void (*fn)(PayloadT &, OpT &)) {
304+ VisitorBuilderBase::add (key, (void *)fn, &VisitorBuilder::forwarder<OpT>);
305+ }
306+
307+ template <typename OpT>
308+ static void forwarder (void *extra, void *payload, llvm::Instruction *op) {
309+ auto fn = (void (*)(PayloadT &, OpT &))extra;
310+ fn (*static_cast <PayloadT *>(payload), *llvm::cast<OpT>(op));
311+ }
261312};
262313
263314} // namespace llvm_dialects
0 commit comments