blob: 8a5e14962c9ff156606a92b2651d978d0890572f [file] [log] [blame]
Brenden Blancoa94bd932015-04-26 00:56:42 -07001/*
Brenden Blanco246b9422015-06-05 11:15:27 -07002 * Copyright (c) 2015 PLUMgrid, Inc.
Brenden Blancoa94bd932015-04-26 00:56:42 -07003 *
Brenden Blanco246b9422015-06-05 11:15:27 -07004 * 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
Brenden Blancoa94bd932015-04-26 00:56:42 -07007 *
Brenden Blanco246b9422015-06-05 11:15:27 -07008 * http://www.apache.org/licenses/LICENSE-2.0
Brenden Blancoa94bd932015-04-26 00:56:42 -07009 *
Brenden Blanco246b9422015-06-05 11:15:27 -070010 * 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.
Brenden Blancoa94bd932015-04-26 00:56:42 -070015 */
16
17#include <algorithm>
Teng Qin3b4e31f2016-11-28 21:58:46 -080018#include "bcc_exception.h"
Brenden Blanco13fabb72015-08-03 10:59:20 -070019#include "parser.h"
20#include "type_helper.h"
Brenden Blancoa94bd932015-04-26 00:56:42 -070021
22namespace ebpf {
23namespace cc {
24
25using std::find;
26using std::move;
27using std::string;
28using std::unique_ptr;
29
Brenden Blancocd5cb412015-04-26 09:41:58 -070030bool Parser::variable_exists(VariableDeclStmtNode *decl) const {
31 if (scopes_->current_var()->lookup(decl->id_->name_, SCOPE_LOCAL) == NULL) {
Brenden Blancoa94bd932015-04-26 00:56:42 -070032 return false;
33 }
34 return true;
35}
36
Brenden Blancocd5cb412015-04-26 09:41:58 -070037VariableDeclStmtNode *Parser::variable_add(vector<int> *types, VariableDeclStmtNode *decl) {
Brenden Blancoa94bd932015-04-26 00:56:42 -070038
Brenden Blancocd5cb412015-04-26 09:41:58 -070039 if (variable_exists(decl)) {
Brenden Blancoa94bd932015-04-26 00:56:42 -070040 fprintf(stderr, "redeclaration of variable %s", decl->id_->name_.c_str());
Brenden Blancocd5cb412015-04-26 09:41:58 -070041 return nullptr;
Brenden Blancoa94bd932015-04-26 00:56:42 -070042 }
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
Brenden Blancocd5cb412015-04-26 09:41:58 -070048VariableDeclStmtNode *Parser::variable_add(vector<int> *types, VariableDeclStmtNode *decl, ExprNode *init_expr) {
Brenden Blancoa94bd932015-04-26 00:56:42 -070049 AssignExprNode::Ptr assign(new AssignExprNode(decl->id_->copy(), ExprNode::Ptr(init_expr)));
50 decl->init_.push_back(move(assign));
51
Brenden Blancocd5cb412015-04-26 09:41:58 -070052 if (variable_exists(decl)) {
Brenden Blancoa94bd932015-04-26 00:56:42 -070053 fprintf(stderr, "redeclaration of variable %s", decl->id_->name_.c_str());
Brenden Blancocd5cb412015-04-26 09:41:58 -070054 return nullptr;
Brenden Blancoa94bd932015-04-26 00:56:42 -070055 }
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
Brenden Blancocd5cb412015-04-26 09:41:58 -070061StructVariableDeclStmtNode *Parser::variable_add(StructVariableDeclStmtNode *decl, ExprNodeList *args, bool is_kv) {
Brenden Blancoa94bd932015-04-26 00:56:42 -070062 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
Brenden Blancocd5cb412015-04-26 09:41:58 -070066 auto n = static_cast<AssignExprNode *>(arg->get());
Brenden Blanco44b93de2015-05-07 13:14:00 -070067 auto id = static_cast<IdentExprNode *>(n->lhs_.get());
68 id->prepend_dot(decl->id_->name_);
Brenden Blancoa94bd932015-04-26 00:56:42 -070069 }
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
Brenden Blancocd5cb412015-04-26 09:41:58 -070078 if (variable_exists(decl)) {
Brenden Blancoa94bd932015-04-26 00:56:42 -070079 fprintf(stderr, "ccpg: warning: redeclaration of variable '%s'\n", decl->id_->name_.c_str());
Brenden Blancocd5cb412015-04-26 09:41:58 -070080 return nullptr;
Brenden Blancoa94bd932015-04-26 00:56:42 -070081 }
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
Brenden Blancocd5cb412015-04-26 09:41:58 -070087StmtNode *Parser::state_add(Scopes::StateScope *scope, IdentExprNode *id, BlockStmtNode *body) {
88 if (scopes_->current_state()->lookup(id->full_name(), SCOPE_LOCAL)) {
Brenden Blancoa94bd932015-04-26 00:56:42 -070089 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
Brenden Blancocd5cb412015-04-26 09:41:58 -0700104StmtNode *Parser::state_add(Scopes::StateScope *scope, IdentExprNode *id1, IdentExprNode *id2, BlockStmtNode *body) {
105 auto state = scopes_->current_state()->lookup(id1->full_name(), SCOPE_LOCAL);
Brenden Blancoa94bd932015-04-26 00:56:42 -0700106 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
Brenden Blancocd5cb412015-04-26 09:41:58 -0700128bool Parser::table_exists(TableDeclStmtNode *decl, bool search_local) {
Brenden Blancoa94bd932015-04-26 00:56:42 -0700129 if (scopes_->top_table()->lookup(decl->id_->name_, search_local) == NULL) {
130 return false;
131 }
132 return true;
133}
134
Brenden Blancocd5cb412015-04-26 09:41:58 -0700135StmtNode *Parser::table_add(IdentExprNode *type, IdentExprNodeList *templates,
136 IdentExprNode *id, string *size) {
Brenden Blancoa94bd932015-04-26 00:56:42 -0700137 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
Brenden Blancocd5cb412015-04-26 09:41:58 -0700148StmtNode * Parser::struct_add(IdentExprNode *type, FormalList *formals) {
Brenden Blancoa94bd932015-04-26 00:56:42 -0700149 auto struct_decl = new StructDeclStmtNode(IdentExprNode::Ptr(type), move(*formals));
Brenden Blancocd5cb412015-04-26 09:41:58 -0700150 if (scopes_->top_struct()->lookup(type->name_, SCOPE_LOCAL) != NULL) {
Brenden Blancoa94bd932015-04-26 00:56:42 -0700151 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
Brenden Blancocd5cb412015-04-26 09:41:58 -0700174StmtNode * Parser::result_add(int token, IdentExprNode *id, FormalList *formals, BlockStmtNode *body) {
Brenden Blancoa94bd932015-04-26 00:56:42 -0700175 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
Brenden Blancocd5cb412015-04-26 09:41:58 -0700192StmtNode * 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)
jeromemarchandb84714a2018-08-08 18:09:44 +0200202 if (!variable_add(nullptr, it->get())) {
203 delete decl;
Brenden Blancocd5cb412015-04-26 09:41:58 -0700204 return nullptr;
jeromemarchandb84714a2018-08-08 18:09:44 +0200205 }
Brenden Blancocd5cb412015-04-26 09:41:58 -0700206 scopes_->set_current(cur_scope);
207 decl->scope_ = scope;
208 scopes_->top_func()->add(id->name_, decl);
209 return decl;
210}
211
Brenden Blancoa94bd932015-04-26 00:56:42 -0700212void 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
218string Parser::pragma(const string &name) const {
219 auto it = pragmas_.find(name);
Brenden Blancocd5cb412015-04-26 09:41:58 -0700220 if (it == pragmas_.end()) return "main";
Brenden Blancoa94bd932015-04-26 00:56:42 -0700221 return it->second;
222}
223
224} // namespace cc
225} // namespace ebpf