1 /*
2  * Copyright (c) 2015 PLUMgrid, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <vector>
20 #include <bitset>
21 #include <string>
22 #include <memory>
23 #include <algorithm>
24 #include <stdint.h>
25 
26 #include "common.h"
27 #include "bcc_exception.h"
28 #include "scope.h"
29 
30 #define REVISION_MASK 0xfff
31 #define MAJOR_VER_POS 22
32 #define MAJOR_VER_MASK ~((1 << MAJOR_VER_POS) - 1)
33 #define MINOR_VER_POS 12
34 #define MINOR_VER_MASK (~((1 << MINOR_VER_POS) - 1) & (~(MAJOR_VER_MASK)))
35 #define GET_MAJOR_VER(version) ((version & MAJOR_VER_MASK) >> MAJOR_VER_POS)
36 #define GET_MINOR_VER(version) ((version & MINOR_VER_MASK) >> MINOR_VER_POS)
37 #define GET_REVISION(version) (version & REVISION_MASK)
38 #define MAKE_VERSION(major, minor, rev) \
39     ((major << MAJOR_VER_POS) | \
40      (minor << MINOR_VER_POS) | \
41      (rev & REVISION_MASK))
42 
43 #define STATUS_RETURN __attribute((warn_unused_result)) StatusTuple
44 
45 namespace ebpf {
46 
47 namespace cc {
48 
49 using std::unique_ptr;
50 using std::move;
51 using std::string;
52 using std::vector;
53 using std::bitset;
54 using std::find;
55 
56 typedef unique_ptr<string> String;
57 
58 #define NODE_EXPRESSIONS(EXPAND) \
59   EXPAND(IdentExprNode, ident_expr_node) \
60   EXPAND(AssignExprNode, assign_expr_node) \
61   EXPAND(PacketExprNode, packet_expr_node) \
62   EXPAND(IntegerExprNode, integer_expr_node) \
63   EXPAND(StringExprNode, string_expr_node) \
64   EXPAND(BinopExprNode, binop_expr_node) \
65   EXPAND(UnopExprNode, unop_expr_node) \
66   EXPAND(BitopExprNode, bitop_expr_node) \
67   EXPAND(GotoExprNode, goto_expr_node) \
68   EXPAND(ReturnExprNode, return_expr_node) \
69   EXPAND(MethodCallExprNode, method_call_expr_node) \
70   EXPAND(TableIndexExprNode, table_index_expr_node)
71 
72 #define NODE_STATEMENTS(EXPAND) \
73   EXPAND(ExprStmtNode, expr_stmt_node) \
74   EXPAND(BlockStmtNode, block_stmt_node) \
75   EXPAND(IfStmtNode, if_stmt_node) \
76   EXPAND(OnValidStmtNode, onvalid_stmt_node) \
77   EXPAND(SwitchStmtNode, switch_stmt_node) \
78   EXPAND(CaseStmtNode, case_stmt_node) \
79   EXPAND(StructVariableDeclStmtNode, struct_variable_decl_stmt_node) \
80   EXPAND(IntegerVariableDeclStmtNode, integer_variable_decl_stmt_node) \
81   EXPAND(StructDeclStmtNode, struct_decl_stmt_node) \
82   EXPAND(StateDeclStmtNode, state_decl_stmt_node) \
83   EXPAND(ParserStateStmtNode, parser_state_stmt_node) \
84   EXPAND(MatchDeclStmtNode, match_decl_stmt_node) \
85   EXPAND(MissDeclStmtNode, miss_decl_stmt_node) \
86   EXPAND(FailureDeclStmtNode, failure_decl_stmt_node) \
87   EXPAND(TableDeclStmtNode, table_decl_stmt_node) \
88   EXPAND(FuncDeclStmtNode, func_decl_stmt_node)
89 
90 #define EXPAND_NODES(EXPAND) \
91   NODE_EXPRESSIONS(EXPAND) \
92   NODE_STATEMENTS(EXPAND)
93 
94 class Visitor;
95 
96 // forward declare all classes
97 #define FORWARD(type, func) class type;
EXPAND_NODES(FORWARD)98 EXPAND_NODES(FORWARD)
99 #undef FORWARD
100 
101 #define DECLARE(type) \
102   typedef unique_ptr<type> Ptr; \
103   virtual StatusTuple accept(Visitor* v);
104 
105 class Node {
106  public:
107   typedef unique_ptr<Node> Ptr;
108   Node() : line_(-1), column_(-1) {}
109   virtual ~Node() {}
110   virtual StatusTuple accept(Visitor* v) = 0;
111   int line_;
112   int column_;
113   string text_;
114 };
115 
116 template <typename... Args>
mkstatus_(Node * n,const char * fmt,Args...args)117 StatusTuple mkstatus_(Node *n, const char *fmt, Args... args) {
118   StatusTuple status = StatusTuple(n->line_ ? n->line_ : -1, fmt, args...);
119   if (n->line_ > 0)
120     status.append_msg("\n" + n->text_);
121   return status;
122 }
123 
mkstatus_(Node * n,const char * msg)124 static inline StatusTuple mkstatus_(Node *n, const char *msg) {
125   StatusTuple status = StatusTuple(n->line_ ? n->line_ : -1, msg);
126   if (n->line_ > 0)
127     status.append_msg("\n" + n->text_);
128   return status;
129 }
130 
131 class StmtNode : public Node {
132  public:
133   typedef unique_ptr<StmtNode> Ptr;
134   virtual StatusTuple accept(Visitor* v) = 0;
135 
136 };
137 typedef vector<StmtNode::Ptr> StmtNodeList;
138 
139 class ExprNode : public Node {
140  public:
141   typedef unique_ptr<ExprNode> Ptr;
142   virtual StatusTuple accept(Visitor* v) = 0;
143   enum expr_type { STRUCT, INTEGER, STRING, VOID, UNKNOWN };
144   enum prop_flag { READ = 0, WRITE, PROTO, IS_LHS, IS_REF, IS_PKT, LAST };
145   expr_type typeof_;
146   StructDeclStmtNode *struct_type_;
147   size_t bit_width_;
148   bitset<LAST> flags_;
149   unique_ptr<BitopExprNode> bitop_;
ExprNode()150   ExprNode() : typeof_(UNKNOWN), struct_type_(NULL), flags_(1 << READ) {}
copy_type(const ExprNode & other)151   void copy_type(const ExprNode& other) {
152     typeof_ = other.typeof_;
153     struct_type_ = other.struct_type_;
154     bit_width_ = other.bit_width_;
155     flags_ = other.flags_;
156   }
is_lhs()157   bool is_lhs() const { return flags_[IS_LHS]; }
is_ref()158   bool is_ref() const { return flags_[IS_REF]; }
is_pkt()159   bool is_pkt() const { return flags_[IS_PKT]; }
160 };
161 
162 typedef vector<ExprNode::Ptr> ExprNodeList;
163 
164 class IdentExprNode : public ExprNode {
165  public:
166   DECLARE(IdentExprNode)
167 
168   string name_;
169   string sub_name_;
170   string scope_name_;
171   VariableDeclStmtNode *decl_;
172   VariableDeclStmtNode *sub_decl_;
IdentExprNode(const IdentExprNode & other)173   IdentExprNode(const IdentExprNode& other) {
174     name_ = other.name_;
175     sub_name_ = other.sub_name_;
176     scope_name_ = other.scope_name_;
177     decl_ = other.decl_;
178     sub_decl_ = other.sub_decl_;
179   }
copy()180   IdentExprNode::Ptr copy() const {
181     return IdentExprNode::Ptr(new IdentExprNode(*this));
182   }
IdentExprNode(const string & id)183   explicit IdentExprNode(const string& id) : name_(id) {}
IdentExprNode(const char * id)184   explicit IdentExprNode(const char* id) : name_(id) {}
prepend_scope(const string & id)185   void prepend_scope(const string& id) {
186     scope_name_ = id;
187   }
append_scope(const string & id)188   void append_scope(const string& id) {
189     scope_name_ = move(name_);
190     name_ = id;
191   }
prepend_dot(const string & id)192   void prepend_dot(const string& id) {
193     sub_name_ = move(name_);
194     name_ = id;
195   }
append_dot(const string & id)196   void append_dot(const string& id) {
197     // we don't support nested struct so keep all subs as single variable
198     if (!sub_name_.empty()) {
199       sub_name_ += "." + id;
200     } else {
201       sub_name_ = id;
202     }
203   }
full_name()204   const string& full_name() {
205     if (full_name_.size()) {
206       return full_name_;  // lazy init
207     }
208     if (scope_name_.size()) {
209       full_name_ += scope_name_ + "::";
210     }
211     full_name_ += name_;
212     if (sub_name_.size()) {
213       full_name_ += "." + sub_name_;
214     }
215     return full_name_;
216   }
c_str()217   const char* c_str() const { return name_.c_str(); }
218  private:
219   string full_name_;
220 };
221 
222 class BitopExprNode : public ExprNode {
223  public:
224   DECLARE(BitopExprNode)
225 
226   ExprNode::Ptr expr_;
227   size_t bit_offset_;
228   size_t bit_width_;
BitopExprNode(const string & bofs,const string & bsz)229   BitopExprNode(const string& bofs, const string& bsz)
230       : bit_offset_(strtoul(bofs.c_str(), NULL, 0)), bit_width_(strtoul(bsz.c_str(), NULL, 0)) {}
231 };
232 
233 typedef vector<IdentExprNode::Ptr> IdentExprNodeList;
234 
235 class AssignExprNode : public ExprNode {
236  public:
237   DECLARE(AssignExprNode)
238 
239   //IdentExprNode *id_;
240   ExprNode::Ptr lhs_;
241   ExprNode::Ptr rhs_;
AssignExprNode(IdentExprNode::Ptr id,ExprNode::Ptr rhs)242   AssignExprNode(IdentExprNode::Ptr id, ExprNode::Ptr rhs)
243       : lhs_(move(id)), rhs_(move(rhs)) {
244     //id_ = (IdentExprNode *)lhs_.get();
245     lhs_->flags_[ExprNode::IS_LHS] = true;
246   }
AssignExprNode(ExprNode::Ptr lhs,ExprNode::Ptr rhs)247   AssignExprNode(ExprNode::Ptr lhs, ExprNode::Ptr rhs)
248       : lhs_(move(lhs)), rhs_(move(rhs)) {
249     //id_ = nullptr;
250     lhs_->flags_[ExprNode::IS_LHS] = true;
251   }
252 };
253 
254 class PacketExprNode : public ExprNode {
255  public:
256   DECLARE(PacketExprNode)
257 
258   IdentExprNode::Ptr id_;
PacketExprNode(IdentExprNode::Ptr id)259   explicit PacketExprNode(IdentExprNode::Ptr id) : id_(move(id)) {}
260 };
261 
262 class StringExprNode : public ExprNode {
263  public:
DECLARE(StringExprNode)264   DECLARE(StringExprNode)
265 
266   string val_;
267   explicit StringExprNode(string *val) : val_(move(*val)) {
268     delete val;
269   }
StringExprNode(const string & val)270   explicit StringExprNode(const string &val) : val_(val) {}
271 };
272 
273 class IntegerExprNode : public ExprNode {
274  public:
275   DECLARE(IntegerExprNode)
276 
277   size_t bits_;
278   string val_;
IntegerExprNode(string * val,string * bits)279   IntegerExprNode(string* val, string* bits)
280       : bits_(strtoul(bits->c_str(), NULL, 0)), val_(move(*val)) {
281     delete val;
282     delete bits;
283   }
IntegerExprNode(string * val)284   explicit IntegerExprNode(string* val)
285       : bits_(0), val_(move(*val)) {
286     delete val;
287   }
IntegerExprNode(const string & val)288   explicit IntegerExprNode(const string& val) : bits_(0), val_(val) {}
IntegerExprNode(const string & val,size_t bits)289   explicit IntegerExprNode(const string& val, size_t bits) : bits_(bits), val_(val) {}
290 };
291 
292 class BinopExprNode : public ExprNode {
293  public:
294   DECLARE(BinopExprNode)
295 
296   ExprNode::Ptr lhs_;
297   int op_;
298   ExprNode::Ptr rhs_;
BinopExprNode(ExprNode::Ptr lhs,int op,ExprNode::Ptr rhs)299   BinopExprNode(ExprNode::Ptr lhs, int op, ExprNode::Ptr rhs)
300       : lhs_(move(lhs)), op_(op), rhs_(move(rhs))
301   {}
302 };
303 
304 class UnopExprNode : public ExprNode {
305  public:
306   DECLARE(UnopExprNode)
307 
308   ExprNode::Ptr expr_;
309   int op_;
UnopExprNode(int op,ExprNode::Ptr expr)310   UnopExprNode(int op, ExprNode::Ptr expr) : expr_(move(expr)), op_(op) {}
311 };
312 
313 class GotoExprNode : public ExprNode {
314  public:
315   DECLARE(GotoExprNode)
316 
317   bool is_continue_;
318   IdentExprNode::Ptr id_;
319   GotoExprNode(IdentExprNode::Ptr id, bool is_continue = false)
is_continue_(is_continue)320       : is_continue_(is_continue), id_(move(id)) {}
321 };
322 
323 class ReturnExprNode : public ExprNode {
324  public:
325   DECLARE(ReturnExprNode)
326 
327   ExprNode::Ptr expr_;
ReturnExprNode(ExprNode::Ptr expr)328   ReturnExprNode(ExprNode::Ptr expr)
329       : expr_(move(expr)) {}
330 };
331 
332 class BlockStmtNode : public StmtNode {
333  public:
DECLARE(BlockStmtNode)334   DECLARE(BlockStmtNode)
335 
336   explicit BlockStmtNode(StmtNodeList stmts = StmtNodeList())
337     : stmts_(move(stmts)), scope_(NULL) {}
~BlockStmtNode()338   ~BlockStmtNode() { delete scope_; }
339   StmtNodeList stmts_;
340   Scopes::VarScope* scope_;
341 };
342 
343 class MethodCallExprNode : public ExprNode {
344  public:
345   DECLARE(MethodCallExprNode)
346 
347   IdentExprNode::Ptr id_;
348   ExprNodeList args_;
349   BlockStmtNode::Ptr block_;
MethodCallExprNode(IdentExprNode::Ptr id,ExprNodeList && args,int lineno)350   MethodCallExprNode(IdentExprNode::Ptr id, ExprNodeList&& args, int lineno)
351       : id_(move(id)), args_(move(args)), block_(make_unique<BlockStmtNode>()) {
352     line_ = lineno;
353   }
354 };
355 
356 class TableIndexExprNode : public ExprNode {
357  public:
358   DECLARE(TableIndexExprNode)
359 
360   IdentExprNode::Ptr id_;
361   IdentExprNode::Ptr sub_;
362   ExprNode::Ptr index_;
363   TableDeclStmtNode *table_;
364   VariableDeclStmtNode *sub_decl_;
TableIndexExprNode(IdentExprNode::Ptr id,ExprNode::Ptr index)365   TableIndexExprNode(IdentExprNode::Ptr id, ExprNode::Ptr index)
366       : id_(move(id)), index_(move(index)), table_(nullptr), sub_decl_(nullptr)
367   {}
368 };
369 
370 class ExprStmtNode : public StmtNode {
371  public:
372   DECLARE(ExprStmtNode)
373 
374   ExprNode::Ptr expr_;
ExprStmtNode(ExprNode::Ptr expr)375   explicit ExprStmtNode(ExprNode::Ptr expr) : expr_(move(expr)) {}
376 };
377 
378 class IfStmtNode : public StmtNode {
379  public:
380   DECLARE(IfStmtNode)
381 
382   ExprNode::Ptr cond_;
383   StmtNode::Ptr true_block_;
384   StmtNode::Ptr false_block_;
385   // create an if () {} expression
IfStmtNode(ExprNode::Ptr cond,StmtNode::Ptr true_block)386   IfStmtNode(ExprNode::Ptr cond, StmtNode::Ptr true_block)
387       : cond_(move(cond)), true_block_(move(true_block)) {}
388   // create an if () {} else {} expression
IfStmtNode(ExprNode::Ptr cond,StmtNode::Ptr true_block,StmtNode::Ptr false_block)389   IfStmtNode(ExprNode::Ptr cond, StmtNode::Ptr true_block, StmtNode::Ptr false_block)
390       : cond_(move(cond)), true_block_(move(true_block)),
391       false_block_(move(false_block)) {}
392 };
393 
394 class OnValidStmtNode : public StmtNode {
395  public:
396   DECLARE(OnValidStmtNode)
397 
398   IdentExprNode::Ptr cond_;
399   StmtNode::Ptr block_;
400   StmtNode::Ptr else_block_;
401   // create an onvalid () {} expression
OnValidStmtNode(IdentExprNode::Ptr cond,StmtNode::Ptr block)402   OnValidStmtNode(IdentExprNode::Ptr cond, StmtNode::Ptr block)
403       : cond_(move(cond)), block_(move(block)) {}
404   // create an onvalid () {} else {} expression
OnValidStmtNode(IdentExprNode::Ptr cond,StmtNode::Ptr block,StmtNode::Ptr else_block)405   OnValidStmtNode(IdentExprNode::Ptr cond, StmtNode::Ptr block, StmtNode::Ptr else_block)
406       : cond_(move(cond)), block_(move(block)),
407       else_block_(move(else_block)) {}
408 };
409 
410 class SwitchStmtNode : public StmtNode {
411  public:
412   DECLARE(SwitchStmtNode)
413   ExprNode::Ptr cond_;
414   BlockStmtNode::Ptr block_;
SwitchStmtNode(ExprNode::Ptr cond,BlockStmtNode::Ptr block)415   SwitchStmtNode(ExprNode::Ptr cond, BlockStmtNode::Ptr block)
416       : cond_(move(cond)), block_(move(block)) {}
417 };
418 
419 class CaseStmtNode : public StmtNode {
420  public:
421   DECLARE(CaseStmtNode)
422   IntegerExprNode::Ptr value_;
423   BlockStmtNode::Ptr block_;
CaseStmtNode(IntegerExprNode::Ptr value,BlockStmtNode::Ptr block)424   CaseStmtNode(IntegerExprNode::Ptr value, BlockStmtNode::Ptr block)
425       : value_(move(value)), block_(move(block)) {}
CaseStmtNode(BlockStmtNode::Ptr block)426   explicit CaseStmtNode(BlockStmtNode::Ptr block) : block_(move(block)) {}
427 };
428 
429 class VariableDeclStmtNode : public StmtNode {
430  public:
431   typedef unique_ptr<VariableDeclStmtNode> Ptr;
432   virtual StatusTuple accept(Visitor* v) = 0;
433   enum storage_type { INTEGER, STRUCT, STRUCT_REFERENCE };
434 
435   IdentExprNode::Ptr id_;
436   ExprNodeList init_;
437   enum storage_type storage_type_;
438   size_t bit_width_;
439   size_t bit_offset_;
440   int slot_;
441   string scope_id_;
442   explicit VariableDeclStmtNode(IdentExprNode::Ptr id, storage_type t, size_t bit_width = 0, size_t bit_offset = 0)
id_(move (id))443       : id_(move(id)), storage_type_(t), bit_width_(bit_width), bit_offset_(bit_offset), slot_(0) {}
scope_id()444   const char* scope_id() const { return scope_id_.c_str(); }
is_struct()445   bool is_struct() { return (storage_type_ == STRUCT || storage_type_ == STRUCT_REFERENCE); }
is_pointer()446   bool is_pointer() { return (storage_type_ == STRUCT_REFERENCE); }
447 };
448 
449 typedef vector<VariableDeclStmtNode::Ptr> FormalList;
450 
451 class StructVariableDeclStmtNode : public VariableDeclStmtNode {
452  public:
453   DECLARE(StructVariableDeclStmtNode)
454 
455   IdentExprNode::Ptr struct_id_;
456   StructVariableDeclStmtNode(IdentExprNode::Ptr struct_id, IdentExprNode::Ptr id,
457                              VariableDeclStmtNode::storage_type t = VariableDeclStmtNode::STRUCT)
VariableDeclStmtNode(move (id),t)458       : VariableDeclStmtNode(move(id), t), struct_id_(move(struct_id)) {}
459 };
460 
461 class IntegerVariableDeclStmtNode : public VariableDeclStmtNode {
462  public:
DECLARE(IntegerVariableDeclStmtNode)463   DECLARE(IntegerVariableDeclStmtNode)
464 
465   IntegerVariableDeclStmtNode(IdentExprNode::Ptr id, const string& bits)
466       : VariableDeclStmtNode(move(id), VariableDeclStmtNode::INTEGER, strtoul(bits.c_str(), NULL, 0)) {}
467 };
468 
469 class StructDeclStmtNode : public StmtNode {
470  public:
471   DECLARE(StructDeclStmtNode)
472 
473   IdentExprNode::Ptr id_;
474   FormalList stmts_;
475   size_t bit_width_;
476   bool packed_;
477   StructDeclStmtNode(IdentExprNode::Ptr id, FormalList&& stmts = FormalList())
id_(move (id))478       : id_(move(id)), stmts_(move(stmts)), bit_width_(0), packed_(false) {}
479   VariableDeclStmtNode* field(const string& name) const;
480   int indexof(const string& name) const;
is_packed()481   bool is_packed() const { return packed_; }
482 };
483 
484 class ParserStateStmtNode : public StmtNode {
485  public:
486   DECLARE(ParserStateStmtNode)
487 
488   IdentExprNode::Ptr id_;
489   StmtNode* next_state_;
490   string scope_id_;
ParserStateStmtNode(IdentExprNode::Ptr id)491   explicit ParserStateStmtNode(IdentExprNode::Ptr id)
492       : id_(move(id)) {}
make(const IdentExprNode::Ptr & id)493   static Ptr make(const IdentExprNode::Ptr& id) {
494     return Ptr(new ParserStateStmtNode(id->copy()));
495   }
scoped_name()496   string scoped_name() const { return scope_id_ + id_->name_; }
497 };
498 
499 class StateDeclStmtNode : public StmtNode {
500  public:
501   DECLARE(StateDeclStmtNode)
502 
503   struct Sub {
504     IdentExprNode::Ptr id_;
505     BlockStmtNode::Ptr block_;
506     ParserStateStmtNode::Ptr parser_;
507     Scopes::StateScope* scope_;
SubSub508     Sub(decltype(id_) id, decltype(block_) block, decltype(parser_) parser, decltype(scope_) scope)
509         : id_(move(id)), block_(move(block)), parser_(move(parser)), scope_(scope) {}
~SubSub510     ~Sub() { delete scope_; }
SubSub511     Sub(Sub&& other) : scope_(NULL) {
512       *this = move(other);
513     }
514     Sub& operator=(Sub&& other) {
515       if (this == &other) {
516         return *this;
517       }
518       id_ = move(other.id_);
519       block_ = move(other.block_);
520       parser_ = move(other.parser_);
521       std::swap(scope_, other.scope_);
522       return *this;
523     }
524   };
525 
526   IdentExprNode::Ptr id_;
527   StmtNodeList init_;
528   string scope_id_;
529   ParserStateStmtNode::Ptr parser_;
530   vector<Sub> subs_;
StateDeclStmtNode()531   StateDeclStmtNode() {}
StateDeclStmtNode(IdentExprNode::Ptr id,BlockStmtNode::Ptr block)532   StateDeclStmtNode(IdentExprNode::Ptr id, BlockStmtNode::Ptr block) : id_(move(id)) {
533     subs_.push_back(Sub(make_unique<IdentExprNode>(""), move(block), ParserStateStmtNode::Ptr(), NULL));
534   }
StateDeclStmtNode(IdentExprNode::Ptr id1,IdentExprNode::Ptr id2,BlockStmtNode::Ptr block)535   StateDeclStmtNode(IdentExprNode::Ptr id1, IdentExprNode::Ptr id2, BlockStmtNode::Ptr block)
536       : id_(move(id1)) {
537     subs_.push_back(Sub(move(id2), move(block), ParserStateStmtNode::Ptr(), NULL));
538   }
scoped_name()539   string scoped_name() const { return scope_id_ + id_->name_; }
find_sub(const string & id)540   vector<Sub>::iterator find_sub(const string& id) {
541     return find_if(subs_.begin(), subs_.end(), [&id] (const Sub& sub) {
542       if (sub.id_->name_ == id)
543         return true;
544       return false;
545     });
546 
547   }
548 };
549 
550 class MatchDeclStmtNode : public StmtNode {
551  public:
552   DECLARE(MatchDeclStmtNode)
553 
554   IdentExprNode::Ptr id_;
555   FormalList formals_;
556   BlockStmtNode::Ptr block_;
MatchDeclStmtNode(IdentExprNode::Ptr id,FormalList && formals,BlockStmtNode::Ptr block)557   MatchDeclStmtNode(IdentExprNode::Ptr id, FormalList&& formals, BlockStmtNode::Ptr block)
558       : id_(move(id)), formals_(move(formals)), block_(move(block)) {}
559 };
560 
561 class MissDeclStmtNode : public StmtNode {
562  public:
563   DECLARE(MissDeclStmtNode)
564 
565   IdentExprNode::Ptr id_;
566   FormalList formals_;
567   BlockStmtNode::Ptr block_;
MissDeclStmtNode(IdentExprNode::Ptr id,FormalList && formals,BlockStmtNode::Ptr block)568   MissDeclStmtNode(IdentExprNode::Ptr id, FormalList&& formals, BlockStmtNode::Ptr block)
569       : id_(move(id)), formals_(move(formals)), block_(move(block)) {}
570 };
571 
572 class FailureDeclStmtNode : public StmtNode {
573  public:
574   DECLARE(FailureDeclStmtNode)
575 
576   IdentExprNode::Ptr id_;
577   FormalList formals_;
578   BlockStmtNode::Ptr block_;
FailureDeclStmtNode(IdentExprNode::Ptr id,FormalList && formals,BlockStmtNode::Ptr block)579   FailureDeclStmtNode(IdentExprNode::Ptr id, FormalList&& formals, BlockStmtNode::Ptr block)
580       : id_(move(id)), formals_(move(formals)), block_(move(block)) {}
581 };
582 
583 class TableDeclStmtNode : public StmtNode {
584  public:
585   DECLARE(TableDeclStmtNode)
586 
587   IdentExprNode::Ptr table_type_;
588   IdentExprNodeList templates_;
589   IdentExprNode::Ptr id_;
590   StructDeclStmtNode *key_type_;
591   StructDeclStmtNode *leaf_type_;
key_id()592   IdentExprNode * key_id() { return templates_.at(0).get(); }
leaf_id()593   IdentExprNode * leaf_id() { return templates_.at(1).get(); }
type_id()594   IdentExprNode * type_id() { return templates_.at(2).get(); }
policy_id()595   IdentExprNode * policy_id() { return templates_.at(3).get(); }
596   size_t size_;
TableDeclStmtNode(IdentExprNode::Ptr table_type,IdentExprNodeList && templates,IdentExprNode::Ptr id,string * size)597   TableDeclStmtNode(IdentExprNode::Ptr table_type, IdentExprNodeList&& templates,
598                     IdentExprNode::Ptr id, string* size)
599       : table_type_(move(table_type)), templates_(move(templates)), id_(move(id)),
600       key_type_(nullptr), leaf_type_(nullptr), size_(strtoul(size->c_str(), NULL, 0)) {
601     delete size;
602   }
603 };
604 
605 class FuncDeclStmtNode : public StmtNode {
606  public:
607   DECLARE(FuncDeclStmtNode)
608 
609   IdentExprNode::Ptr id_;
610   FormalList formals_;
611   BlockStmtNode::Ptr block_;
612   Scopes::StateScope* scope_;
FuncDeclStmtNode(IdentExprNode::Ptr id,FormalList && formals,BlockStmtNode::Ptr block)613   FuncDeclStmtNode(IdentExprNode::Ptr id, FormalList&& formals, BlockStmtNode::Ptr block)
614       : id_(move(id)), formals_(move(formals)), block_(move(block)), scope_(NULL) {}
615 };
616 
617 class Visitor {
618  public:
619   typedef StatusTuple Ret;
~Visitor()620   virtual ~Visitor() {}
621 #define VISIT(type, func) virtual STATUS_RETURN visit_##func(type* n) = 0;
622   EXPAND_NODES(VISIT)
623 #undef VISIT
624 };
625 
626 #undef DECLARE
627 
628 }  // namespace cc
629 }  // namespace ebpf
630