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 <map> 20 #include <string> 21 #include <vector> 22 #include <memory> 23 24 namespace ebpf { 25 namespace cc { 26 27 using std::string; 28 using std::vector; 29 using std::map; 30 using std::pair; 31 using std::unique_ptr; 32 33 class StateDeclStmtNode; 34 class VariableDeclStmtNode; 35 class TableDeclStmtNode; 36 class StructDeclStmtNode; 37 class FuncDeclStmtNode; 38 39 enum search_type { SCOPE_LOCAL, SCOPE_GLOBAL }; 40 41 template <typename T> 42 class Scope { 43 public: Scope()44 Scope() {} Scope(Scope<T> * scope,int id)45 Scope(Scope<T>* scope, int id) : parent_(scope), id_(id) {} 46 47 T* lookup(const string &name, bool search_local = true) { 48 return lookup(name, search_local ? SCOPE_LOCAL : SCOPE_GLOBAL); 49 } lookup(const string & name,search_type stype)50 T * lookup(const string &name, search_type stype) { 51 auto it = elems_.find(name); 52 if (it != elems_.end()) 53 return it->second; 54 55 if (stype == SCOPE_LOCAL || !parent_) 56 return nullptr; 57 return parent_->lookup(name, stype); 58 } add(const string & name,T * n)59 void add(const string& name, T* n) { 60 elems_[name] = n; 61 elems_ordered_.push_back(n); 62 } begin()63 typename map<string, T*>::iterator begin() { return elems_.begin(); } end()64 typename map<string, T*>::iterator end() { return elems_.end(); } obegin()65 typename vector<T*>::iterator obegin() { return elems_ordered_.begin(); } oend()66 typename vector<T*>::iterator oend() { return elems_ordered_.end(); } 67 68 Scope<T> *parent_; 69 int id_; 70 map<string, T*> elems_; 71 vector<T*> elems_ordered_; 72 }; 73 74 /** 75 * Hold the current stack of scope pointers. Lookups search upwards. 76 * Actual scope pointers are kept in the AST. 77 */ 78 class Scopes { 79 public: 80 typedef unique_ptr<Scopes> Ptr; 81 typedef Scope<StructDeclStmtNode> StructScope; 82 typedef Scope<StateDeclStmtNode> StateScope; 83 typedef Scope<VariableDeclStmtNode> VarScope; 84 typedef Scope<TableDeclStmtNode> TableScope; 85 typedef Scope<FuncDeclStmtNode> FuncScope; 86 Scopes()87 Scopes() : var_id__(0), state_id_(0), var_id_(0), 88 current_var_scope_(nullptr), top_var_scope_(nullptr), 89 current_state_scope_(nullptr), top_state_scope_(nullptr), 90 top_struct_scope_(new StructScope(nullptr, 1)), 91 top_table_scope_(new TableScope(nullptr, 1)), 92 top_func_scope_(new FuncScope(nullptr, 1)) {} ~Scopes()93 ~Scopes() { 94 delete top_func_scope_; 95 delete top_struct_scope_; 96 delete top_table_scope_; 97 delete top_state_scope_; 98 } 99 push_var(VarScope * scope)100 void push_var(VarScope *scope) { 101 if (scope == top_var_scope_) 102 return; 103 scope->parent_ = current_var_scope_; 104 current_var_scope_ = scope; 105 } pop_var()106 void pop_var() { 107 if (current_var_scope_ == top_var_scope_) 108 return; 109 VarScope *old = current_var_scope_; 110 current_var_scope_ = old->parent_; 111 old->parent_ = nullptr; 112 } 113 push_state(StateScope * scope)114 void push_state(StateScope *scope) { 115 if (scope == top_state_scope_) 116 return; 117 scope->parent_ = current_state_scope_; 118 current_state_scope_ = scope; 119 } pop_state()120 void pop_state() { 121 if (current_state_scope_ == top_state_scope_) 122 return; 123 StateScope *old = current_state_scope_; 124 current_state_scope_ = old->parent_; 125 old->parent_ = nullptr; 126 } 127 128 /// While building the AST, allocate a new scope enter_var_scope()129 VarScope* enter_var_scope() { 130 current_var_scope_ = new VarScope(current_var_scope_, next_var_id()); 131 if (!top_var_scope_) { 132 top_var_scope_ = current_var_scope_; 133 } 134 return current_var_scope_; 135 } 136 exit_var_scope()137 VarScope* exit_var_scope() { 138 current_var_scope_ = current_var_scope_->parent_; 139 return current_var_scope_; 140 } 141 enter_state_scope()142 StateScope* enter_state_scope() { 143 current_state_scope_ = new StateScope(current_state_scope_, next_state_id()); 144 if (!top_state_scope_) { 145 top_state_scope_ = current_state_scope_; 146 } 147 return current_state_scope_; 148 } 149 exit_state_scope()150 StateScope* exit_state_scope() { 151 current_state_scope_ = current_state_scope_->parent_; 152 return current_state_scope_; 153 } 154 set_current(VarScope * s)155 void set_current(VarScope* s) { current_var_scope_ = s; } current_var()156 VarScope* current_var() const { return current_var_scope_; } top_var()157 VarScope* top_var() const { return top_var_scope_; } 158 set_current(StateScope * s)159 void set_current(StateScope* s) { current_state_scope_ = s; } current_state()160 StateScope* current_state() const { return current_state_scope_; } top_state()161 StateScope* top_state() const { return top_state_scope_; } 162 top_struct()163 StructScope* top_struct() const { return top_struct_scope_; } 164 top_table()165 TableScope* top_table() const { return top_table_scope_; } top_func()166 FuncScope* top_func() const { return top_func_scope_; } 167 next_id()168 int next_id() { return ++var_id__; } next_state_id()169 int next_state_id() { return ++state_id_; } next_var_id()170 int next_var_id() { return ++var_id_; } 171 172 int var_id__; 173 int state_id_; 174 int var_id_; 175 VarScope* current_var_scope_; 176 VarScope* top_var_scope_; 177 StateScope* current_state_scope_; 178 StateScope* top_state_scope_; 179 StructScope* top_struct_scope_; 180 TableScope* top_table_scope_; 181 FuncScope* top_func_scope_; 182 }; 183 184 } // namespace cc 185 } // namespace ebpf 186