• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <algorithm>
18 #include "bcc_exception.h"
19 #include "parser.h"
20 #include "type_helper.h"
21 
22 namespace ebpf {
23 namespace cc {
24 
25 using std::find;
26 using std::move;
27 using std::string;
28 using std::unique_ptr;
29 
variable_exists(VariableDeclStmtNode * decl) const30 bool Parser::variable_exists(VariableDeclStmtNode *decl) const {
31   if (scopes_->current_var()->lookup(decl->id_->name_, SCOPE_LOCAL) == NULL) {
32     return false;
33   }
34   return true;
35 }
36 
variable_add(vector<int> * types,VariableDeclStmtNode * decl)37 VariableDeclStmtNode *Parser::variable_add(vector<int> *types, VariableDeclStmtNode *decl) {
38 
39   if (variable_exists(decl)) {
40     fprintf(stderr, "redeclaration of variable %s", decl->id_->name_.c_str());
41     return nullptr;
42   }
43   decl->scope_id_ = string("v") + std::to_string(scopes_->current_var()->id_) + string("_");
44   scopes_->current_var()->add(decl->id_->name_, decl);
45   return decl;
46 }
47 
variable_add(vector<int> * types,VariableDeclStmtNode * decl,ExprNode * init_expr)48 VariableDeclStmtNode *Parser::variable_add(vector<int> *types, VariableDeclStmtNode *decl, ExprNode *init_expr) {
49   AssignExprNode::Ptr assign(new AssignExprNode(decl->id_->copy(), ExprNode::Ptr(init_expr)));
50   decl->init_.push_back(move(assign));
51 
52   if (variable_exists(decl)) {
53     fprintf(stderr, "redeclaration of variable %s", decl->id_->name_.c_str());
54     return nullptr;
55   }
56   decl->scope_id_ = string("v") + std::to_string(scopes_->current_var()->id_) + string("_");
57   scopes_->current_var()->add(decl->id_->name_, decl);
58   return decl;
59 }
60 
variable_add(StructVariableDeclStmtNode * decl,ExprNodeList * args,bool is_kv)61 StructVariableDeclStmtNode *Parser::variable_add(StructVariableDeclStmtNode *decl, ExprNodeList *args, bool is_kv) {
62   if (is_kv) {
63     // annotate the init expressions with the declared id
64     for (auto arg = args->begin(); arg != args->end(); ++arg) {
65       // decorate with the name of this decl
66       auto n = static_cast<AssignExprNode *>(arg->get());
67       auto id = static_cast<IdentExprNode *>(n->lhs_.get());
68       id->prepend_dot(decl->id_->name_);
69     }
70   } else {
71     fprintf(stderr, "must use key = value syntax\n");
72     return NULL;
73   }
74 
75   decl->init_ = move(*args);
76   delete args;
77 
78   if (variable_exists(decl)) {
79     fprintf(stderr, "ccpg: warning: redeclaration of variable '%s'\n", decl->id_->name_.c_str());
80     return nullptr;
81   }
82   decl->scope_id_ = string("v") + std::to_string(scopes_->current_var()->id_) + string("_");
83   scopes_->current_var()->add(decl->id_->name_, decl);
84   return decl;
85 }
86 
state_add(Scopes::StateScope * scope,IdentExprNode * id,BlockStmtNode * body)87 StmtNode *Parser::state_add(Scopes::StateScope *scope, IdentExprNode *id, BlockStmtNode *body) {
88   if (scopes_->current_state()->lookup(id->full_name(), SCOPE_LOCAL)) {
89     fprintf(stderr, "redeclaration of state %s\n", id->full_name().c_str());
90     // redeclaration
91     return NULL;
92   }
93   auto state = new StateDeclStmtNode(IdentExprNode::Ptr(id), BlockStmtNode::Ptr(body));
94     // add a reference to the lower scope
95   state->subs_[0].scope_ = scope;
96 
97   // add me to the upper scope
98   scopes_->current_state()->add(state->id_->full_name(), state);
99   state->scope_id_ = string("s") + std::to_string(scopes_->current_state()->id_) + string("_");
100 
101   return state;
102 }
103 
state_add(Scopes::StateScope * scope,IdentExprNode * id1,IdentExprNode * id2,BlockStmtNode * body)104 StmtNode *Parser::state_add(Scopes::StateScope *scope, IdentExprNode *id1, IdentExprNode *id2, BlockStmtNode *body) {
105   auto state = scopes_->current_state()->lookup(id1->full_name(), SCOPE_LOCAL);
106   if (!state) {
107     state = new StateDeclStmtNode(IdentExprNode::Ptr(id1), IdentExprNode::Ptr(id2), BlockStmtNode::Ptr(body));
108     // add a reference to the lower scope
109     state->subs_[0].scope_ = scope;
110 
111     // add me to the upper scope
112     scopes_->current_state()->add(state->id_->full_name(), state);
113     state->scope_id_ = string("s") + std::to_string(scopes_->current_state()->id_) + string("_");
114     return state;
115   } else {
116     if (state->find_sub(id2->name_) != state->subs_.end()) {
117       fprintf(stderr, "redeclaration of state %s, %s\n", id1->full_name().c_str(), id2->full_name().c_str());
118       return NULL;
119     }
120     state->subs_.push_back(StateDeclStmtNode::Sub(IdentExprNode::Ptr(id2), BlockStmtNode::Ptr(body),
121                                                   ParserStateStmtNode::Ptr(), scope));
122     delete id1;
123 
124     return new StateDeclStmtNode(); // stub
125   }
126 }
127 
table_exists(TableDeclStmtNode * decl,bool search_local)128 bool Parser::table_exists(TableDeclStmtNode *decl, bool search_local) {
129   if (scopes_->top_table()->lookup(decl->id_->name_, search_local) == NULL) {
130     return false;
131   }
132   return true;
133 }
134 
table_add(IdentExprNode * type,IdentExprNodeList * templates,IdentExprNode * id,string * size)135 StmtNode *Parser::table_add(IdentExprNode *type, IdentExprNodeList *templates,
136                             IdentExprNode *id, string *size) {
137   auto table = new TableDeclStmtNode(IdentExprNode::Ptr(type),
138                                      move(*templates),
139                                      IdentExprNode::Ptr(id), size);
140   if (table_exists(table, true)) {
141     fprintf(stderr, "redeclaration of table %s\n", id->name_.c_str());
142     return table;
143   }
144   scopes_->top_table()->add(id->name_, table);
145   return table;
146 }
147 
struct_add(IdentExprNode * type,FormalList * formals)148 StmtNode * Parser::struct_add(IdentExprNode *type, FormalList *formals) {
149   auto struct_decl = new StructDeclStmtNode(IdentExprNode::Ptr(type), move(*formals));
150   if (scopes_->top_struct()->lookup(type->name_, SCOPE_LOCAL) != NULL) {
151     fprintf(stderr, "redeclaration of struct %s\n", type->name_.c_str());
152     return struct_decl;
153   }
154 
155   auto pr_it = pragmas_.find("packed");
156   if (pr_it != pragmas_.end() && pr_it->second == "true")
157     struct_decl->packed_ = true;
158 
159   int i = 0;
160   size_t offset = 0;
161   for (auto it = struct_decl->stmts_.begin(); it != struct_decl->stmts_.end(); ++it, ++i) {
162     FieldType ft = bits_to_enum((*it)->bit_width_);
163     offset = struct_decl->is_packed() ? offset : align_offset(offset, ft);
164     (*it)->slot_ = i;
165     (*it)->bit_offset_ = offset;
166     offset += (*it)->bit_width_;
167   }
168   struct_decl->bit_width_ = struct_decl->is_packed() ? offset : align_offset(offset, UINT32_T);
169 
170   scopes_->top_struct()->add(type->name_, struct_decl);
171   return struct_decl;
172 }
173 
result_add(int token,IdentExprNode * id,FormalList * formals,BlockStmtNode * body)174 StmtNode * Parser::result_add(int token, IdentExprNode *id, FormalList *formals, BlockStmtNode *body) {
175   StmtNode *stmt = NULL;
176   switch (token) {
177     case Tok::TMATCH:
178       stmt = new MatchDeclStmtNode(IdentExprNode::Ptr(id), move(*formals), BlockStmtNode::Ptr(body));
179       break;
180     case Tok::TMISS:
181       stmt = new MissDeclStmtNode(IdentExprNode::Ptr(id), move(*formals), BlockStmtNode::Ptr(body));
182       break;
183     case Tok::TFAILURE:
184       stmt = new FailureDeclStmtNode(IdentExprNode::Ptr(id), move(*formals), BlockStmtNode::Ptr(body));
185       break;
186     default:
187       {}
188   }
189   return stmt;
190 }
191 
func_add(vector<int> * types,Scopes::StateScope * scope,IdentExprNode * id,FormalList * formals,BlockStmtNode * body)192 StmtNode * Parser::func_add(vector<int> *types, Scopes::StateScope *scope,
193                             IdentExprNode *id, FormalList *formals, BlockStmtNode *body) {
194   auto decl = new FuncDeclStmtNode(IdentExprNode::Ptr(id), move(*formals), BlockStmtNode::Ptr(body));
195   if (scopes_->top_func()->lookup(decl->id_->name_, SCOPE_LOCAL)) {
196     fprintf(stderr, "redeclaration of func %s\n", id->name_.c_str());
197     return decl;
198   }
199   auto cur_scope = scopes_->current_var();
200   scopes_->set_current(scope);
201   for (auto it = formals->begin(); it != formals->end(); ++it)
202     if (!variable_add(nullptr, it->get())) {
203       delete decl;
204       return nullptr;
205     }
206   scopes_->set_current(cur_scope);
207   decl->scope_ = scope;
208   scopes_->top_func()->add(id->name_, decl);
209   return decl;
210 }
211 
set_loc(Node * n,const BisonParser::location_type & loc) const212 void Parser::set_loc(Node *n, const BisonParser::location_type &loc) const {
213   n->line_ = loc.begin.line;
214   n->column_ = loc.begin.column;
215   n->text_ = lexer.text(loc);
216 }
217 
pragma(const string & name) const218 string Parser::pragma(const string &name) const {
219   auto it = pragmas_.find(name);
220   if (it == pragmas_.end()) return "main";
221   return it->second;
222 }
223 
224 }  // namespace cc
225 }  // namespace ebpf
226