Remove B language support
authorDave Marchevsky <davemarchevsky@fb.com>
Fri, 17 Dec 2021 07:54:49 +0000 (02:54 -0500)
committeryonghong-song <ys114321@gmail.com>
Fri, 17 Dec 2021 19:46:20 +0000 (11:46 -0800)
Remove support for compiling B programs (see #3682 for explanation).

There may be some vestigial logic in other files that needs to be
cleanded up for simplicity - bpf_module.cc most likely - but that can be
addressed in followup commits.

Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
37 files changed:
src/cc/CMakeLists.txt
src/cc/bcc_common.cc
src/cc/bcc_common.h
src/cc/bpf_module.cc
src/cc/bpf_module.h
src/cc/frontends/CMakeLists.txt
src/cc/frontends/b/CMakeLists.txt [deleted file]
src/cc/frontends/b/codegen_llvm.cc [deleted file]
src/cc/frontends/b/codegen_llvm.h [deleted file]
src/cc/frontends/b/lexer.h [deleted file]
src/cc/frontends/b/lexer.ll [deleted file]
src/cc/frontends/b/loader.cc [deleted file]
src/cc/frontends/b/loader.h [deleted file]
src/cc/frontends/b/node.cc [deleted file]
src/cc/frontends/b/node.h [deleted file]
src/cc/frontends/b/parser.cc [deleted file]
src/cc/frontends/b/parser.h [deleted file]
src/cc/frontends/b/parser.yy [deleted file]
src/cc/frontends/b/printer.cc [deleted file]
src/cc/frontends/b/printer.h [deleted file]
src/cc/frontends/b/scope.h [deleted file]
src/cc/frontends/b/type_check.cc [deleted file]
src/cc/frontends/b/type_check.h [deleted file]
src/cc/frontends/b/type_helper.h [deleted file]
src/lua/bcc/bpf.lua
src/lua/bcc/libbcc.lua
src/python/bcc/__init__.py
src/python/bcc/libbcc.py
tests/python/CMakeLists.txt
tests/python/kprobe.b [deleted file]
tests/python/proto.b [deleted file]
tests/python/test_stat1.b [deleted file]
tests/python/test_stat1.py
tests/python/test_trace1.b [deleted file]
tests/python/test_trace1.py [deleted file]
tests/python/test_trace2.b [deleted file]
tests/python/test_xlate1.b [deleted file]

index bcbbaebecffdb1d8ec6f5cc8f51050a46bb1e6cd..ffe8feec2592c3d964aa6d3b99e0efb357e1b233 100644 (file)
@@ -123,7 +123,7 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${llvm_lib_exclude_f
 
 # bcc_common_libs_for_a for archive libraries
 # bcc_common_libs_for_s for shared libraries
-set(bcc_common_libs b_frontend clang_frontend
+set(bcc_common_libs clang_frontend
   -Wl,--whole-archive ${clang_libs} ${llvm_libs} -Wl,--no-whole-archive
   ${LIBELF_LIBRARIES})
 if (LIBDEBUGINFOD_FOUND)
@@ -131,7 +131,7 @@ if (LIBDEBUGINFOD_FOUND)
 endif (LIBDEBUGINFOD_FOUND)
 set(bcc_common_libs_for_a ${bcc_common_libs})
 set(bcc_common_libs_for_s ${bcc_common_libs})
-set(bcc_common_libs_for_lua b_frontend clang_frontend
+set(bcc_common_libs_for_lua clang_frontend
   ${clang_libs} ${llvm_libs} ${LIBELF_LIBRARIES})
 if(LIBBPF_FOUND)
   list(APPEND bcc_common_libs_for_a ${LIBBPF_LIBRARIES})
index 1ccd8d1656b6e736d9c8b1b37f5a4281ca239e34..5c349d70d7264173d9e276279b27f1e7305fce8a 100644 (file)
 #include "bpf_module.h"
 
 extern "C" {
-void * bpf_module_create_b(const char *filename, const char *proto_filename, unsigned flags,
-                           const char *dev_name) {
-  auto mod = new ebpf::BPFModule(flags, nullptr, true, "", true, dev_name);
-  if (mod->load_b(filename, proto_filename) != 0) {
-    delete mod;
-    return nullptr;
-  }
-  return mod;
-}
-
 void * bpf_module_create_c(const char *filename, unsigned flags, const char *cflags[],
                            int ncflags, bool allow_rlimit, const char *dev_name) {
   auto mod = new ebpf::BPFModule(flags, nullptr, true, "", allow_rlimit, dev_name);
index 4377523df52d0b3173c636c4903ed249bbc3a7f0..b5f77db92af24a6b494f48da8156b42683f01acf 100644 (file)
@@ -25,8 +25,6 @@
 extern "C" {
 #endif
 
-void * bpf_module_create_b(const char *filename, const char *proto_filename, unsigned flags,
-                           const char *dev_name);
 void * bpf_module_create_c(const char *filename, unsigned flags, const char *cflags[], int ncflags,
                            bool allow_rlimit, const char *dev_name);
 void * bpf_module_create_c_from_string(const char *text, unsigned flags, const char *cflags[],
index 80d3fc64859e0d75bc827f5718e60dc90ada54a4..36f9582a562e3e95cd62de4a29c503b30d403daa 100644 (file)
@@ -38,7 +38,6 @@
 #include "common.h"
 #include "bcc_debug.h"
 #include "bcc_elf.h"
-#include "frontends/b/loader.h"
 #include "frontends/clang/loader.h"
 #include "frontends/clang/b_frontend_action.h"
 #include "bpf_module.h"
@@ -834,43 +833,6 @@ int BPFModule::table_leaf_scanf(size_t id, const char *leaf_str, void *leaf) {
   return 0;
 }
 
-// load a B file, which comes in two parts
-int BPFModule::load_b(const string &filename, const string &proto_filename) {
-  if (!sections_.empty()) {
-    fprintf(stderr, "Program already initialized\n");
-    return -1;
-  }
-  if (filename.empty() || proto_filename.empty()) {
-    fprintf(stderr, "Invalid filenames\n");
-    return -1;
-  }
-
-  // Helpers are inlined in the following file (C). Load the definitions and
-  // pass the partially compiled module to the B frontend to continue with.
-  auto helpers_h = ExportedFiles::headers().find("/virtual/include/bcc/helpers.h");
-  if (helpers_h == ExportedFiles::headers().end()) {
-    fprintf(stderr, "Internal error: missing bcc/helpers.h");
-    return -1;
-  }
-  if (int rc = load_includes(helpers_h->second))
-    return rc;
-
-  BLoader b_loader(flags_);
-  used_b_loader_ = true;
-  if (int rc = b_loader.parse(&*mod_, filename, proto_filename, *ts_, id_,
-                              maps_ns_))
-    return rc;
-  if (rw_engine_enabled_) {
-    if (int rc = annotate())
-      return rc;
-  } else {
-    annotate_light();
-  }
-  if (int rc = finalize())
-    return rc;
-  return 0;
-}
-
 // load a C file
 int BPFModule::load_c(const string &filename, const char *cflags[], int ncflags) {
   if (!sections_.empty()) {
index d5729558b67804c22b569478aca796d01a5d5baf..87938c3fa4fdbce949db3725c600d4cfe2d671c4 100644 (file)
@@ -99,7 +99,6 @@ class BPFModule {
             const char *dev_name = nullptr);
   ~BPFModule();
   int free_bcc_memory();
-  int load_b(const std::string &filename, const std::string &proto_filename);
   int load_c(const std::string &filename, const char *cflags[], int ncflags);
   int load_string(const std::string &text, const char *cflags[], int ncflags);
   std::string id() const { return id_; }
index cef6c3c7e8ccd2de560de796a52ffe0e053b513b..5d3678c6f5d1b56673d61890b1015f7b9502115e 100644 (file)
@@ -1,5 +1,4 @@
 # Copyright (c) PLUMgrid, Inc.
 # Licensed under the Apache License, Version 2.0 (the "License")
 
-add_subdirectory(b)
 add_subdirectory(clang)
diff --git a/src/cc/frontends/b/CMakeLists.txt b/src/cc/frontends/b/CMakeLists.txt
deleted file mode 100644 (file)
index 391ab27..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) PLUMgrid, Inc.
-# Licensed under the Apache License, Version 2.0 (the "License")
-
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-
-BISON_TARGET(Parser parser.yy ${CMAKE_CURRENT_BINARY_DIR}/parser.yy.cc COMPILE_FLAGS "-o parser.yy.cc -v --debug")
-FLEX_TARGET(Lexer lexer.ll ${CMAKE_CURRENT_BINARY_DIR}/lexer.ll.cc COMPILE_FLAGS "--c++ --o lexer.ll.cc")
-ADD_FLEX_BISON_DEPENDENCY(Lexer Parser)
-if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
-  set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/lexer.ll.cc PROPERTIES COMPILE_FLAGS "-Wno-deprecated-register")
-endif()
-
-add_library(b_frontend STATIC loader.cc codegen_llvm.cc node.cc parser.cc printer.cc
-  type_check.cc ${BISON_Parser_OUTPUTS} ${FLEX_Lexer_OUTPUTS})
diff --git a/src/cc/frontends/b/codegen_llvm.cc b/src/cc/frontends/b/codegen_llvm.cc
deleted file mode 100644 (file)
index 359303c..0000000
+++ /dev/null
@@ -1,1405 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <set>
-#include <algorithm>
-#include <sstream>
-
-#include <llvm/IR/BasicBlock.h>
-#include <llvm/IR/CallingConv.h>
-#include <llvm/IR/CFG.h>
-#include <llvm/IR/Constants.h>
-#include <llvm/IR/DerivedTypes.h>
-#include <llvm/IR/Function.h>
-#include <llvm/IR/GlobalVariable.h>
-#include <llvm/IR/InlineAsm.h>
-#include <llvm/IR/Instructions.h>
-#include <llvm/IR/IRPrintingPasses.h>
-#include <llvm/IR/IRBuilder.h>
-#include <llvm/IR/LLVMContext.h>
-#include <llvm/IR/Module.h>
-
-#include "bcc_exception.h"
-#include "codegen_llvm.h"
-#include "file_desc.h"
-#include "lexer.h"
-#include "libbpf.h"
-#include "linux/bpf.h"
-#include "table_storage.h"
-#include "type_helper.h"
-
-namespace ebpf {
-namespace cc {
-
-using namespace llvm;
-
-using std::for_each;
-using std::make_tuple;
-using std::map;
-using std::pair;
-using std::set;
-using std::string;
-using std::stringstream;
-using std::to_string;
-using std::vector;
-
-// can't forward declare IRBuilder in .h file (template with default
-// parameters), so cast it instead :(
-#define B (*((IRBuilder<> *)this->b_))
-
-// Helper class to push/pop the insert block
-class BlockStack {
- public:
-  explicit BlockStack(CodegenLLVM *cc, BasicBlock *bb)
-    : old_bb_(cc->b_->GetInsertBlock()), cc_(cc) {
-    cc_->b_->SetInsertPoint(bb);
-  }
-  ~BlockStack() {
-    if (old_bb_)
-      cc_->b_->SetInsertPoint(old_bb_);
-    else
-      cc_->b_->ClearInsertionPoint();
-  }
- private:
-  BasicBlock *old_bb_;
-  CodegenLLVM *cc_;
-};
-
-// Helper class to push/pop switch statement insert block
-class SwitchStack {
- public:
-  explicit SwitchStack(CodegenLLVM *cc, SwitchInst *sw)
-    : old_sw_(cc->cur_switch_), cc_(cc) {
-    cc_->cur_switch_ = sw;
-  }
-  ~SwitchStack() {
-    cc_->cur_switch_ = old_sw_;
-  }
- private:
-  SwitchInst *old_sw_;
-  CodegenLLVM *cc_;
-};
-
-CodegenLLVM::CodegenLLVM(llvm::Module *mod, Scopes *scopes, Scopes *proto_scopes)
-  : out_(stdout), mod_(mod), indent_(0), tmp_reg_index_(0), scopes_(scopes),
-    proto_scopes_(proto_scopes), expr_(nullptr) {
-  b_ = new IRBuilder<>(ctx());
-}
-CodegenLLVM::~CodegenLLVM() {
-  delete b_;
-}
-
-template <typename... Args>
-void CodegenLLVM::emit(const char *fmt, Args&&... params) {
-  //fprintf(out_, fmt, std::forward<Args>(params)...);
-  //fflush(out_);
-}
-void CodegenLLVM::emit(const char *s) {
-  //fprintf(out_, "%s", s);
-  //fflush(out_);
-}
-
-CallInst *CodegenLLVM::createCall(Value *callee, ArrayRef<Value *> args)
-{
-#if LLVM_MAJOR_VERSION >= 11
-  auto *calleePtrType = cast<PointerType>(callee->getType());
-  auto *calleeType = cast<FunctionType>(calleePtrType->getElementType());
-  return B.CreateCall(calleeType, callee, args);
-#else
-  return B.CreateCall(callee, args);
-#endif
-}
-
-LoadInst *CodegenLLVM::createLoad(Value *addr)
-{
-#if LLVM_MAJOR_VERSION >= 14
-  return B.CreateLoad(addr->getType()->getPointerElementType(), addr);
-#else
-  return B.CreateLoad(addr);
-#endif
-}
-
-Value *CodegenLLVM::createInBoundsGEP(Value *ptr, ArrayRef<Value *>idxlist)
-{
-#if LLVM_MAJOR_VERSION >= 14
-  return B.CreateInBoundsGEP(ptr->getType()->getScalarType()->getPointerElementType(),
-                             ptr, idxlist);
-#else
-  return B.CreateInBoundsGEP(ptr, idxlist);
-#endif
-}
-
-StatusTuple CodegenLLVM::visit_block_stmt_node(BlockStmtNode *n) {
-
-  // enter scope
-  if (n->scope_)
-    scopes_->push_var(n->scope_);
-
-  if (!n->stmts_.empty()) {
-    for (auto it = n->stmts_.begin(); it != n->stmts_.end(); ++it)
-      TRY2((*it)->accept(this));
-  }
-  // exit scope
-  if (n->scope_)
-    scopes_->pop_var();
-
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_if_stmt_node(IfStmtNode *n) {
-  Function *parent = B.GetInsertBlock()->getParent();
-  BasicBlock *label_then = BasicBlock::Create(ctx(), "if.then", parent);
-  BasicBlock *label_else = n->false_block_ ? BasicBlock::Create(ctx(), "if.else", parent) : nullptr;
-  BasicBlock *label_end = BasicBlock::Create(ctx(), "if.end", parent);
-
-  TRY2(n->cond_->accept(this));
-  Value *is_not_null = B.CreateIsNotNull(pop_expr());
-
-  if (n->false_block_)
-    B.CreateCondBr(is_not_null, label_then, label_else);
-  else
-    B.CreateCondBr(is_not_null, label_then, label_end);
-
-  {
-    BlockStack bstack(this, label_then);
-    TRY2(n->true_block_->accept(this));
-    if (!B.GetInsertBlock()->getTerminator())
-      B.CreateBr(label_end);
-  }
-
-  if (n->false_block_) {
-    BlockStack bstack(this, label_else);
-    TRY2(n->false_block_->accept(this));
-    if (!B.GetInsertBlock()->getTerminator())
-      B.CreateBr(label_end);
-  }
-
-  B.SetInsertPoint(label_end);
-
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_onvalid_stmt_node(OnValidStmtNode *n) {
-  TRY2(n->cond_->accept(this));
-
-  Value *is_null = B.CreateIsNotNull(pop_expr());
-
-  Function *parent = B.GetInsertBlock()->getParent();
-  BasicBlock *label_then = BasicBlock::Create(ctx(), "onvalid.then", parent);
-  BasicBlock *label_else = n->else_block_ ? BasicBlock::Create(ctx(), "onvalid.else", parent) : nullptr;
-  BasicBlock *label_end = BasicBlock::Create(ctx(), "onvalid.end", parent);
-
-  if (n->else_block_)
-    B.CreateCondBr(is_null, label_then, label_else);
-  else
-    B.CreateCondBr(is_null, label_then, label_end);
-
-  {
-    BlockStack bstack(this, label_then);
-    TRY2(n->block_->accept(this));
-    if (!B.GetInsertBlock()->getTerminator())
-      B.CreateBr(label_end);
-  }
-
-  if (n->else_block_) {
-    BlockStack bstack(this, label_else);
-    TRY2(n->else_block_->accept(this));
-    if (!B.GetInsertBlock()->getTerminator())
-      B.CreateBr(label_end);
-  }
-
-  B.SetInsertPoint(label_end);
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_switch_stmt_node(SwitchStmtNode *n) {
-  Function *parent = B.GetInsertBlock()->getParent();
-  BasicBlock *label_default = BasicBlock::Create(ctx(), "switch.default", parent);
-  BasicBlock *label_end = BasicBlock::Create(ctx(), "switch.end", parent);
-  // switch (cond)
-  TRY2(n->cond_->accept(this));
-  SwitchInst *switch_inst = B.CreateSwitch(pop_expr(), label_default);
-  B.SetInsertPoint(label_end);
-  {
-    // case 1..N
-    SwitchStack sstack(this, switch_inst);
-    TRY2(n->block_->accept(this));
-  }
-  // if other cases are terminal, erase the end label
-  if (pred_empty(label_end)) {
-    B.SetInsertPoint(resolve_label("DONE"));
-    label_end->eraseFromParent();
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_case_stmt_node(CaseStmtNode *n) {
-  if (!cur_switch_) return mkstatus_(n, "no valid switch instruction");
-  Function *parent = B.GetInsertBlock()->getParent();
-  BasicBlock *label_end = B.GetInsertBlock();
-  BasicBlock *dest;
-  if (n->value_) {
-    TRY2(n->value_->accept(this));
-    dest = BasicBlock::Create(ctx(), "switch.case", parent);
-    Value *cond = B.CreateIntCast(pop_expr(), cur_switch_->getCondition()->getType(), false);
-    cur_switch_->addCase(cast<ConstantInt>(cond), dest);
-  } else {
-    dest = cur_switch_->getDefaultDest();
-  }
-  {
-    BlockStack bstack(this, dest);
-    TRY2(n->block_->accept(this));
-    // if no trailing goto, fall to end
-    if (!B.GetInsertBlock()->getTerminator())
-      B.CreateBr(label_end);
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_ident_expr_node(IdentExprNode *n) {
-  if (!n->decl_)
-    return mkstatus_(n, "variable lookup failed: %s", n->name_.c_str());
-  if (n->decl_->is_pointer()) {
-    if (n->sub_name_.size()) {
-      if (n->bitop_) {
-        // ident is holding a host endian number, don't use dext
-        if (n->is_lhs()) {
-          emit("%s%s->%s", n->decl_->scope_id(), n->c_str(), n->sub_name_.c_str());
-        } else {
-          emit("(((%s%s->%s) >> %d) & (((%s)1 << %d) - 1))", n->decl_->scope_id(), n->c_str(), n->sub_name_.c_str(),
-              n->bitop_->bit_offset_, bits_to_uint(n->bitop_->bit_width_ + 1), n->bitop_->bit_width_);
-        }
-        return mkstatus_(n, "unsupported");
-      } else {
-        if (n->struct_type_->id_->name_ == "_Packet" && n->sub_name_.substr(0, 3) == "arg") {
-          // convert arg1~arg8 into args[0]~args[7] assuming type_check verified the range already
-          auto arg_num = stoi(n->sub_name_.substr(3, 3));
-          if (arg_num < 5) {
-            emit("%s%s->args_lo[%d]", n->decl_->scope_id(), n->c_str(), arg_num - 1);
-          } else {
-            emit("%s%s->args_hi[%d]", n->decl_->scope_id(), n->c_str(), arg_num - 5);
-          }
-          return mkstatus_(n, "unsupported");
-        } else {
-          emit("%s%s->%s", n->decl_->scope_id(), n->c_str(), n->sub_name_.c_str());
-          auto it = vars_.find(n->decl_);
-          if (it == vars_.end()) return mkstatus_(n, "Cannot locate variable %s in vars_ table", n->c_str());
-          LoadInst *load_1 = createLoad(it->second);
-          vector<Value *> indices({B.getInt32(0), B.getInt32(n->sub_decl_->slot_)});
-          expr_ = createInBoundsGEP(load_1, indices);
-          if (!n->is_lhs())
-            expr_ = createLoad(pop_expr());
-        }
-      }
-    } else {
-      auto it = vars_.find(n->decl_);
-      if (it == vars_.end()) return mkstatus_(n, "Cannot locate variable %s in vars_ table", n->c_str());
-      expr_ = n->is_lhs() ? it->second : (Value *)createLoad(it->second);
-    }
-  } else {
-    if (n->sub_name_.size()) {
-      emit("%s%s.%s", n->decl_->scope_id(), n->c_str(), n->sub_name_.c_str());
-      auto it = vars_.find(n->decl_);
-      if (it == vars_.end()) return mkstatus_(n, "Cannot locate variable %s in vars_ table", n->c_str());
-      vector<Value *> indices({const_int(0), const_int(n->sub_decl_->slot_, 32)});
-      expr_ = B.CreateGEP(nullptr, it->second, indices);
-      if (!n->is_lhs())
-        expr_ = createLoad(pop_expr());
-    } else {
-      if (n->bitop_) {
-        // ident is holding a host endian number, don't use dext
-        if (n->is_lhs())
-          return mkstatus_(n, "illegal: ident %s is a left-hand-side type", n->name_.c_str());
-        if (n->decl_->is_struct())
-          return mkstatus_(n, "illegal: can only take bitop of a struct subfield");
-        emit("(((%s%s) >> %d) & (((%s)1 << %d) - 1))", n->decl_->scope_id(), n->c_str(),
-             n->bitop_->bit_offset_, bits_to_uint(n->bitop_->bit_width_ + 1), n->bitop_->bit_width_);
-      } else {
-        emit("%s%s", n->decl_->scope_id(), n->c_str());
-        auto it = vars_.find(n->decl_);
-        if (it == vars_.end()) return mkstatus_(n, "Cannot locate variable %s in vars_ table", n->c_str());
-        if (n->is_lhs() || n->decl_->is_struct())
-          expr_ = it->second;
-        else
-          expr_ = createLoad(it->second);
-      }
-    }
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_assign_expr_node(AssignExprNode *n) {
-  if (n->bitop_) {
-    TRY2(n->lhs_->accept(this));
-    emit(" = (");
-    TRY2(n->lhs_->accept(this));
-    emit(" & ~((((%s)1 << %d) - 1) << %d)) | (", bits_to_uint(n->lhs_->bit_width_),
-         n->bitop_->bit_width_, n->bitop_->bit_offset_);
-    TRY2(n->rhs_->accept(this));
-    emit(" << %d)", n->bitop_->bit_offset_);
-    return mkstatus_(n, "unsupported");
-  } else {
-    if (n->lhs_->flags_[ExprNode::PROTO]) {
-      // auto f = n->lhs_->struct_type_->field(n->id_->sub_name_);
-      // emit("bpf_dins(%s%s + %zu, %zu, %zu, ", n->id_->decl_->scope_id(), n->id_->c_str(),
-      //      f->bit_offset_ >> 3, f->bit_offset_ & 0x7, f->bit_width_);
-      // TRY2(n->rhs_->accept(this));
-      // emit(")");
-      return mkstatus_(n, "unsupported");
-    } else {
-      TRY2(n->rhs_->accept(this));
-      if (n->lhs_->is_pkt()) {
-        TRY2(n->lhs_->accept(this));
-      } else {
-        Value *rhs = pop_expr();
-        TRY2(n->lhs_->accept(this));
-        Value *lhs = pop_expr();
-        if (!n->rhs_->is_ref())
-          rhs = B.CreateIntCast(rhs, cast<PointerType>(lhs->getType())->getElementType(), false);
-        B.CreateStore(rhs, lhs);
-      }
-    }
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::lookup_var(Node *n, const string &name, Scopes::VarScope *scope,
-                                    VariableDeclStmtNode **decl, Value **mem) const {
-  *decl = scope->lookup(name, SCOPE_GLOBAL);
-  if (!*decl) return mkstatus_(n, "cannot find %s variable", name.c_str());
-  auto it = vars_.find(*decl);
-  if (it == vars_.end()) return mkstatus_(n, "unable to find %s memory location", name.c_str());
-  *mem = it->second;
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_packet_expr_node(PacketExprNode *n) {
-  auto p = proto_scopes_->top_struct()->lookup(n->id_->name_, true);
-  VariableDeclStmtNode *offset_decl, *skb_decl;
-  Value *offset_mem, *skb_mem;
-  TRY2(lookup_var(n, "skb", scopes_->current_var(), &skb_decl, &skb_mem));
-  TRY2(lookup_var(n, "$" + n->id_->name_, scopes_->current_var(), &offset_decl, &offset_mem));
-
-  if (p) {
-    auto f = p->field(n->id_->sub_name_);
-    if (f) {
-      size_t bit_offset = f->bit_offset_;
-      size_t bit_width = f->bit_width_;
-      if (n->bitop_) {
-        bit_offset += f->bit_width_ - (n->bitop_->bit_offset_ + n->bitop_->bit_width_);
-        bit_width = std::min(bit_width - n->bitop_->bit_offset_, n->bitop_->bit_width_);
-      }
-      if (n->is_ref()) {
-        // e.g.: @ip.hchecksum, return offset of the header within packet
-        LoadInst *offset_ptr = createLoad(offset_mem);
-        Value *skb_hdr_offset = B.CreateAdd(offset_ptr, B.getInt64(bit_offset >> 3));
-        expr_ = B.CreateIntCast(skb_hdr_offset, B.getInt64Ty(), false);
-      } else if (n->is_lhs()) {
-        emit("bpf_dins_pkt(pkt, %s + %zu, %zu, %zu, ", n->id_->c_str(), bit_offset >> 3, bit_offset & 0x7, bit_width);
-        Function *store_fn = mod_->getFunction("bpf_dins_pkt");
-        if (!store_fn) return mkstatus_(n, "unable to find function bpf_dins_pkt");
-        LoadInst *skb_ptr = createLoad(skb_mem);
-        Value *skb_ptr8 = B.CreateBitCast(skb_ptr, B.getInt8PtrTy());
-        LoadInst *offset_ptr = createLoad(offset_mem);
-        Value *skb_hdr_offset = B.CreateAdd(offset_ptr, B.getInt64(bit_offset >> 3));
-        Value *rhs = B.CreateIntCast(pop_expr(), B.getInt64Ty(), false);
-        createCall(store_fn, vector<Value *>({skb_ptr8, skb_hdr_offset, B.getInt64(bit_offset & 0x7),
-                                               B.getInt64(bit_width), rhs}));
-      } else {
-        emit("bpf_dext_pkt(pkt, %s + %zu, %zu, %zu)", n->id_->c_str(), bit_offset >> 3, bit_offset & 0x7, bit_width);
-        Function *load_fn = mod_->getFunction("bpf_dext_pkt");
-        if (!load_fn) return mkstatus_(n, "unable to find function bpf_dext_pkt");
-        LoadInst *skb_ptr = createLoad(skb_mem);
-        Value *skb_ptr8 = B.CreateBitCast(skb_ptr, B.getInt8PtrTy());
-        LoadInst *offset_ptr = createLoad(offset_mem);
-        Value *skb_hdr_offset = B.CreateAdd(offset_ptr, B.getInt64(bit_offset >> 3));
-        expr_ = createCall(load_fn, vector<Value *>({skb_ptr8, skb_hdr_offset,
-                                                      B.getInt64(bit_offset & 0x7), B.getInt64(bit_width)}));
-        // this generates extra trunc insns whereas the bpf.load fns already
-        // trunc the values internally in the bpf interpreter
-        //expr_ = B.CreateTrunc(pop_expr(), B.getIntNTy(bit_width));
-      }
-    } else {
-      emit("pkt->start + pkt->offset + %s", n->id_->c_str());
-      return mkstatus_(n, "unsupported");
-    }
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_integer_expr_node(IntegerExprNode *n) {
-  APInt val;
-  StringRef(n->val_).getAsInteger(0, val);
-  expr_ = ConstantInt::get(mod_->getContext(), val);
-  if (n->bits_)
-    expr_ = B.CreateIntCast(expr_, B.getIntNTy(n->bits_), false);
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_string_expr_node(StringExprNode *n) {
-  if (n->is_lhs()) return mkstatus_(n, "cannot assign to a string");
-
-  Value *global = B.CreateGlobalString(n->val_);
-  Value *ptr = make_alloca(resolve_entry_stack(), B.getInt8Ty(), "",
-                           B.getInt64(n->val_.size() + 1));
-#if LLVM_MAJOR_VERSION >= 11
-  B.CreateMemCpy(ptr, Align(1), global, Align(1), n->val_.size() + 1);
-#elif LLVM_MAJOR_VERSION >= 7
-  B.CreateMemCpy(ptr, 1, global, 1, n->val_.size() + 1);
-#else
-  B.CreateMemCpy(ptr, global, n->val_.size() + 1, 1);
-#endif
-  expr_ = ptr;
-
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_short_circuit_and(BinopExprNode *n) {
-  Function *parent = B.GetInsertBlock()->getParent();
-  BasicBlock *label_start = B.GetInsertBlock();
-  BasicBlock *label_then = BasicBlock::Create(ctx(), "and.then", parent);
-  BasicBlock *label_end = BasicBlock::Create(ctx(), "and.end", parent);
-
-  TRY2(n->lhs_->accept(this));
-  Value *neq_zero = B.CreateICmpNE(pop_expr(), B.getIntN(n->lhs_->bit_width_, 0));
-  B.CreateCondBr(neq_zero, label_then, label_end);
-
-  {
-    BlockStack bstack(this, label_then);
-    TRY2(n->rhs_->accept(this));
-    expr_ = B.CreateICmpNE(pop_expr(), B.getIntN(n->rhs_->bit_width_, 0));
-    B.CreateBr(label_end);
-  }
-
-  B.SetInsertPoint(label_end);
-
-  PHINode *phi = B.CreatePHI(B.getInt1Ty(), 2);
-  phi->addIncoming(B.getFalse(), label_start);
-  phi->addIncoming(pop_expr(), label_then);
-  expr_ = phi;
-
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_short_circuit_or(BinopExprNode *n) {
-  Function *parent = B.GetInsertBlock()->getParent();
-  BasicBlock *label_start = B.GetInsertBlock();
-  BasicBlock *label_then = BasicBlock::Create(ctx(), "or.then", parent);
-  BasicBlock *label_end = BasicBlock::Create(ctx(), "or.end", parent);
-
-  TRY2(n->lhs_->accept(this));
-  Value *neq_zero = B.CreateICmpNE(pop_expr(), B.getIntN(n->lhs_->bit_width_, 0));
-  B.CreateCondBr(neq_zero, label_end, label_then);
-
-  {
-    BlockStack bstack(this, label_then);
-    TRY2(n->rhs_->accept(this));
-    expr_ = B.CreateICmpNE(pop_expr(), B.getIntN(n->rhs_->bit_width_, 0));
-    B.CreateBr(label_end);
-  }
-
-  B.SetInsertPoint(label_end);
-
-  PHINode *phi = B.CreatePHI(B.getInt1Ty(), 2);
-  phi->addIncoming(B.getTrue(), label_start);
-  phi->addIncoming(pop_expr(), label_then);
-  expr_ = phi;
-
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_binop_expr_node(BinopExprNode *n) {
-  if (n->op_ == Tok::TAND)
-    return emit_short_circuit_and(n);
-  if (n->op_ == Tok::TOR)
-    return emit_short_circuit_or(n);
-
-  TRY2(n->lhs_->accept(this));
-  Value *lhs = pop_expr();
-  TRY2(n->rhs_->accept(this));
-  Value *rhs = B.CreateIntCast(pop_expr(), lhs->getType(), false);
-  switch (n->op_) {
-    case Tok::TCEQ: expr_ = B.CreateICmpEQ(lhs, rhs); break;
-    case Tok::TCNE: expr_ = B.CreateICmpNE(lhs, rhs); break;
-    case Tok::TXOR: expr_ = B.CreateXor(lhs, rhs); break;
-    case Tok::TMOD: expr_ = B.CreateURem(lhs, rhs); break;
-    case Tok::TCLT: expr_ = B.CreateICmpULT(lhs, rhs); break;
-    case Tok::TCLE: expr_ = B.CreateICmpULE(lhs, rhs); break;
-    case Tok::TCGT: expr_ = B.CreateICmpUGT(lhs, rhs); break;
-    case Tok::TCGE: expr_ = B.CreateICmpUGE(lhs, rhs); break;
-    case Tok::TPLUS: expr_ = B.CreateAdd(lhs, rhs); break;
-    case Tok::TMINUS: expr_ = B.CreateSub(lhs, rhs); break;
-    case Tok::TLAND: expr_ = B.CreateAnd(lhs, rhs); break;
-    case Tok::TLOR: expr_ = B.CreateOr(lhs, rhs); break;
-    default: return mkstatus_(n, "unsupported binary operator");
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_unop_expr_node(UnopExprNode *n) {
-  TRY2(n->expr_->accept(this));
-  switch (n->op_) {
-    case Tok::TNOT: expr_ = B.CreateNot(pop_expr()); break;
-    case Tok::TCMPL: expr_ = B.CreateNeg(pop_expr()); break;
-    default: {}
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_bitop_expr_node(BitopExprNode *n) {
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_goto_expr_node(GotoExprNode *n) {
-  if (n->id_->name_ == "DONE") {
-    return mkstatus_(n, "use return statement instead");
-  }
-  string jump_label;
-  // when dealing with multistates, goto statements may be overridden
-  auto rewrite_it = proto_rewrites_.find(n->id_->full_name());
-  auto default_it = proto_rewrites_.find("");
-  if (rewrite_it != proto_rewrites_.end()) {
-    jump_label = rewrite_it->second;
-  } else if (default_it != proto_rewrites_.end()) {
-    jump_label = default_it->second;
-  } else {
-    auto state = scopes_->current_state()->lookup(n->id_->full_name(), false);
-    if (state) {
-      jump_label = state->scoped_name();
-      if (n->is_continue_) {
-        jump_label += "_continue";
-      }
-    } else {
-      state = scopes_->current_state()->lookup("EOP", false);
-      if (state) {
-        jump_label = state->scoped_name();
-      }
-    }
-  }
-  B.CreateBr(resolve_label(jump_label));
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_return_expr_node(ReturnExprNode *n) {
-  TRY2(n->expr_->accept(this));
-  Function *parent = B.GetInsertBlock()->getParent();
-  Value *cast_1 = B.CreateIntCast(pop_expr(), parent->getReturnType(), true);
-  B.CreateStore(cast_1, retval_);
-  B.CreateBr(resolve_label("DONE"));
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_table_lookup(MethodCallExprNode *n) {
-  TableDeclStmtNode* table = scopes_->top_table()->lookup(n->id_->name_);
-  IdentExprNode* arg0 = static_cast<IdentExprNode*>(n->args_.at(0).get());
-  IdentExprNode* arg1;
-  StructVariableDeclStmtNode* arg1_type;
-
-  auto table_fd_it = table_fds_.find(table);
-  if (table_fd_it == table_fds_.end())
-    return mkstatus_(n, "unable to find table %s in table_fds_", n->id_->c_str());
-
-  Function *pseudo_fn = mod_->getFunction("llvm.bpf.pseudo");
-  if (!pseudo_fn) return mkstatus_(n, "pseudo fd loader doesn't exist");
-  Function *lookup_fn = mod_->getFunction("bpf_map_lookup_elem_");
-  if (!lookup_fn) return mkstatus_(n, "bpf_map_lookup_elem_ undefined");
-
-  CallInst *pseudo_call = createCall(pseudo_fn, vector<Value *>({B.getInt64(BPF_PSEUDO_MAP_FD),
-                                                                  B.getInt64(table_fd_it->second)}));
-  Value *pseudo_map_fd = pseudo_call;
-
-  TRY2(arg0->accept(this));
-  Value *key_ptr = B.CreateBitCast(pop_expr(), B.getInt8PtrTy());
-
-  expr_ = createCall(lookup_fn, vector<Value *>({pseudo_map_fd, key_ptr}));
-
-  if (table->type_id()->name_ == "FIXED_MATCH" || table->type_id()->name_ == "INDEXED") {
-    if (n->args_.size() == 2) {
-      arg1 = static_cast<IdentExprNode*>(n->args_.at(1).get());
-      arg1_type = static_cast<StructVariableDeclStmtNode*>(arg1->decl_);
-      if (table->leaf_id()->name_ != arg1_type->struct_id_->name_) {
-        return mkstatus_(n, "lookup pointer type mismatch %s != %s", table->leaf_id()->c_str(),
-                        arg1_type->struct_id_->c_str());
-      }
-      auto it = vars_.find(arg1_type);
-      if (it == vars_.end()) return mkstatus_(n, "Cannot locate variable %s in vars_ table", n->id_->c_str());
-      expr_ = B.CreateBitCast(pop_expr(), cast<PointerType>(it->second->getType())->getElementType());
-      B.CreateStore(pop_expr(), it->second);
-    }
-  } else {
-    return mkstatus_(n, "lookup in table type %s unsupported", table->type_id()->c_str());
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_table_update(MethodCallExprNode *n) {
-  TableDeclStmtNode* table = scopes_->top_table()->lookup(n->id_->name_);
-  IdentExprNode* arg0 = static_cast<IdentExprNode*>(n->args_.at(0).get());
-  IdentExprNode* arg1 = static_cast<IdentExprNode*>(n->args_.at(1).get());
-
-  auto table_fd_it = table_fds_.find(table);
-  if (table_fd_it == table_fds_.end())
-    return mkstatus_(n, "unable to find table %s in table_fds_", n->id_->c_str());
-  Function *pseudo_fn = mod_->getFunction("llvm.bpf.pseudo");
-  if (!pseudo_fn) return mkstatus_(n, "pseudo fd loader doesn't exist");
-  Function *update_fn = mod_->getFunction("bpf_map_update_elem_");
-  if (!update_fn) return mkstatus_(n, "bpf_map_update_elem_ undefined");
-
-  CallInst *pseudo_call = createCall(pseudo_fn, vector<Value *>({B.getInt64(BPF_PSEUDO_MAP_FD),
-                                        B.getInt64(table_fd_it->second)}));
-  Value *pseudo_map_fd = pseudo_call;
-
-  TRY2(arg0->accept(this));
-  Value *key_ptr = B.CreateBitCast(pop_expr(), B.getInt8PtrTy());
-
-  if (table->type_id()->name_ == "FIXED_MATCH" || table->type_id()->name_ == "INDEXED") {
-    TRY2(arg1->accept(this));
-    Value *value_ptr = B.CreateBitCast(pop_expr(), B.getInt8PtrTy());
-
-    expr_ = createCall(update_fn, vector<Value *>({pseudo_map_fd, key_ptr, value_ptr, B.getInt64(BPF_ANY)}));
-  } else {
-    return mkstatus_(n, "unsupported");
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_table_delete(MethodCallExprNode *n) {
-  TableDeclStmtNode* table = scopes_->top_table()->lookup(n->id_->name_);
-  IdentExprNode* arg0 = static_cast<IdentExprNode*>(n->args_.at(0).get());
-
-  auto table_fd_it = table_fds_.find(table);
-  if (table_fd_it == table_fds_.end())
-    return mkstatus_(n, "unable to find table %s in table_fds_", n->id_->c_str());
-  Function *pseudo_fn = mod_->getFunction("llvm.bpf.pseudo");
-  if (!pseudo_fn) return mkstatus_(n, "pseudo fd loader doesn't exist");
-  Function *update_fn = mod_->getFunction("bpf_map_update_elem_");
-  if (!update_fn) return mkstatus_(n, "bpf_map_update_elem_ undefined");
-
-  CallInst *pseudo_call = createCall(pseudo_fn, vector<Value *>({B.getInt64(BPF_PSEUDO_MAP_FD),
-                                        B.getInt64(table_fd_it->second)}));
-  Value *pseudo_map_fd = pseudo_call;
-
-  TRY2(arg0->accept(this));
-  Value *key_ptr = B.CreateBitCast(pop_expr(), B.getInt8PtrTy());
-
-  if (table->type_id()->name_ == "FIXED_MATCH" || table->type_id()->name_ == "INDEXED") {
-    expr_ = createCall(update_fn, vector<Value *>({pseudo_map_fd, key_ptr}));
-  } else {
-    return mkstatus_(n, "unsupported");
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_log(MethodCallExprNode *n) {
-  vector<Value *> args;
-  auto arg = n->args_.begin();
-  TRY2((*arg)->accept(this));
-  args.push_back(pop_expr());
-  args.push_back(B.getInt64(((*arg)->bit_width_ >> 3) + 1));
-  ++arg;
-  for (; arg != n->args_.end(); ++arg) {
-    TRY2((*arg)->accept(this));
-    args.push_back(pop_expr());
-  }
-
-  // int bpf_trace_printk(fmt, sizeof(fmt), ...)
-  FunctionType *printk_fn_type = FunctionType::get(B.getInt32Ty(), vector<Type *>({B.getInt8PtrTy(), B.getInt64Ty()}), true);
-  Value *printk_fn = B.CreateIntToPtr(B.getInt64(BPF_FUNC_trace_printk),
-                                         PointerType::getUnqual(printk_fn_type));
-
-  expr_ = createCall(printk_fn, args);
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_packet_rewrite_field(MethodCallExprNode *n) {
-  TRY2(n->args_[1]->accept(this));
-  TRY2(n->args_[0]->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_atomic_add(MethodCallExprNode *n) {
-  TRY2(n->args_[0]->accept(this));
-  Value *lhs = B.CreateBitCast(pop_expr(), Type::getInt64PtrTy(ctx()));
-  TRY2(n->args_[1]->accept(this));
-  Value *rhs = B.CreateSExt(pop_expr(), B.getInt64Ty());
-#if LLVM_MAJOR_VERSION >= 13
-  AtomicRMWInst *atomic_inst = B.CreateAtomicRMW(
-      AtomicRMWInst::Add, lhs, rhs, Align(8),
-      AtomicOrdering::SequentiallyConsistent);
-#else
-  AtomicRMWInst *atomic_inst = B.CreateAtomicRMW(
-      AtomicRMWInst::Add, lhs, rhs, AtomicOrdering::SequentiallyConsistent);
-#endif
-  atomic_inst->setVolatile(false);
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_incr_cksum(MethodCallExprNode *n, size_t sz) {
-  Value *is_pseudo;
-  string csum_fn_str;
-  if (n->args_.size() == 4) {
-    TRY2(n->args_[3]->accept(this));
-    is_pseudo = B.CreateIntCast(B.CreateIsNotNull(pop_expr()), B.getInt64Ty(), false);
-    csum_fn_str = "bpf_l4_csum_replace_";
-  } else {
-    is_pseudo = B.getInt64(0);
-    csum_fn_str = "bpf_l3_csum_replace_";
-  }
-
-  TRY2(n->args_[2]->accept(this));
-  Value *new_val = B.CreateZExt(pop_expr(), B.getInt64Ty());
-  TRY2(n->args_[1]->accept(this));
-  Value *old_val = B.CreateZExt(pop_expr(), B.getInt64Ty());
-  TRY2(n->args_[0]->accept(this));
-  Value *offset = B.CreateZExt(pop_expr(), B.getInt64Ty());
-
-  Function *csum_fn = mod_->getFunction(csum_fn_str);
-  if (!csum_fn) return mkstatus_(n, "Undefined built-in %s", csum_fn_str.c_str());
-
-  // flags = (is_pseudo << 4) | sizeof(old_val)
-  Value *flags_lower = B.getInt64(sz ? sz : bits_to_size(n->args_[1]->bit_width_));
-  Value *flags_upper = B.CreateShl(is_pseudo, B.getInt64(4));
-  Value *flags = B.CreateOr(flags_upper, flags_lower);
-
-  VariableDeclStmtNode *skb_decl;
-  Value *skb_mem;
-  TRY2(lookup_var(n, "skb", scopes_->current_var(), &skb_decl, &skb_mem));
-  LoadInst *skb_ptr = createLoad(skb_mem);
-  Value *skb_ptr8 = B.CreateBitCast(skb_ptr, B.getInt8PtrTy());
-
-  expr_ = createCall(csum_fn, vector<Value *>({skb_ptr8, offset, old_val, new_val, flags}));
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::emit_get_usec_time(MethodCallExprNode *n) {
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_method_call_expr_node(MethodCallExprNode *n) {
-  if (n->id_->sub_name_.size()) {
-    if (n->id_->sub_name_ == "lookup") {
-      TRY2(emit_table_lookup(n));
-    } else if (n->id_->sub_name_ == "update") {
-      TRY2(emit_table_update(n));
-    } else if (n->id_->sub_name_ == "delete") {
-      TRY2(emit_table_delete(n));
-    } else if (n->id_->sub_name_ == "rewrite_field" && n->id_->name_ == "pkt") {
-      TRY2(emit_packet_rewrite_field(n));
-    }
-  } else if (n->id_->name_ == "atomic_add") {
-    TRY2(emit_atomic_add(n));
-  } else if (n->id_->name_ == "log") {
-    TRY2(emit_log(n));
-  } else if (n->id_->name_ == "incr_cksum") {
-    TRY2(emit_incr_cksum(n));
-  } else if (n->id_->name_ == "get_usec_time") {
-    TRY2(emit_get_usec_time(n));
-  } else {
-    return mkstatus_(n, "unsupported");
-  }
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-/* result = lookup(key)
- * if (!result) {
- *   update(key, {0}, BPF_NOEXIST)
- *   result = lookup(key)
- * }
- */
-StatusTuple CodegenLLVM::visit_table_index_expr_node(TableIndexExprNode *n) {
-  auto table_fd_it = table_fds_.find(n->table_);
-  if (table_fd_it == table_fds_.end())
-    return mkstatus_(n, "unable to find table %s in table_fds_", n->id_->c_str());
-
-  Function *pseudo_fn = mod_->getFunction("llvm.bpf.pseudo");
-  if (!pseudo_fn) return mkstatus_(n, "pseudo fd loader doesn't exist");
-  Function *update_fn = mod_->getFunction("bpf_map_update_elem_");
-  if (!update_fn) return mkstatus_(n, "bpf_map_update_elem_ undefined");
-  Function *lookup_fn = mod_->getFunction("bpf_map_lookup_elem_");
-  if (!lookup_fn) return mkstatus_(n, "bpf_map_lookup_elem_ undefined");
-  StructType *leaf_type;
-  TRY2(lookup_struct_type(n->table_->leaf_type_, &leaf_type));
-  PointerType *leaf_ptype = PointerType::getUnqual(leaf_type);
-
-  CallInst *pseudo_call = createCall(pseudo_fn, vector<Value *>({B.getInt64(BPF_PSEUDO_MAP_FD),
-                                        B.getInt64(table_fd_it->second)}));
-  Value *pseudo_map_fd = pseudo_call;
-
-  TRY2(n->index_->accept(this));
-  Value *key_ptr = B.CreateBitCast(pop_expr(), B.getInt8PtrTy());
-
-  // result = lookup(key)
-  Value *lookup1 = B.CreateBitCast(createCall(lookup_fn, vector<Value *>({pseudo_map_fd, key_ptr})), leaf_ptype);
-
-  Value *result = nullptr;
-  if (n->table_->policy_id()->name_ == "AUTO") {
-    Function *parent = B.GetInsertBlock()->getParent();
-    BasicBlock *label_start = B.GetInsertBlock();
-    BasicBlock *label_then = BasicBlock::Create(ctx(), n->id_->name_ + "[].then", parent);
-    BasicBlock *label_end = BasicBlock::Create(ctx(), n->id_->name_ + "[].end", parent);
-
-    Value *eq_zero = B.CreateIsNull(lookup1);
-    B.CreateCondBr(eq_zero, label_then, label_end);
-
-    B.SetInsertPoint(label_then);
-    // var Leaf leaf {0}
-    Value *leaf_ptr = B.CreateBitCast(
-        make_alloca(resolve_entry_stack(), leaf_type), B.getInt8PtrTy());
-#if LLVM_MAJOR_VERSION >= 10
-    B.CreateMemSet(leaf_ptr, B.getInt8(0), B.getInt64(n->table_->leaf_id()->bit_width_ >> 3), MaybeAlign(1));
-#else
-    B.CreateMemSet(leaf_ptr, B.getInt8(0), B.getInt64(n->table_->leaf_id()->bit_width_ >> 3), 1);
-#endif
-    // update(key, leaf)
-    createCall(update_fn, vector<Value *>({pseudo_map_fd, key_ptr, leaf_ptr, B.getInt64(BPF_NOEXIST)}));
-
-    // result = lookup(key)
-    Value *lookup2 = B.CreateBitCast(createCall(lookup_fn, vector<Value *>({pseudo_map_fd, key_ptr})), leaf_ptype);
-    B.CreateBr(label_end);
-
-    B.SetInsertPoint(label_end);
-
-    PHINode *phi = B.CreatePHI(leaf_ptype, 2);
-    phi->addIncoming(lookup1, label_start);
-    phi->addIncoming(lookup2, label_then);
-    result = phi;
-  } else if (n->table_->policy_id()->name_ == "NONE") {
-    result = lookup1;
-  }
-
-  if (n->is_lhs()) {
-    if (n->sub_decl_) {
-      Type *ptr_type = PointerType::getUnqual(B.getIntNTy(n->sub_decl_->bit_width_));
-      // u64 *errval -> uN *errval
-      Value *err_cast = B.CreateBitCast(errval_, ptr_type);
-      // if valid then &field, else &errval
-      Function *parent = B.GetInsertBlock()->getParent();
-      BasicBlock *label_start = B.GetInsertBlock();
-      BasicBlock *label_then = BasicBlock::Create(ctx(), n->id_->name_ + "[]field.then", parent);
-      BasicBlock *label_end = BasicBlock::Create(ctx(), n->id_->name_ + "[]field.end", parent);
-
-      if (1) {
-        // the PHI implementation of this doesn't load, maybe eBPF limitation?
-        B.CreateCondBr(B.CreateIsNull(result), label_then, label_end);
-        B.SetInsertPoint(label_then);
-        B.CreateStore(B.getInt32(2), retval_);
-        B.CreateBr(resolve_label("DONE"));
-
-        B.SetInsertPoint(label_end);
-        vector<Value *> indices({B.getInt32(0), B.getInt32(n->sub_decl_->slot_)});
-        expr_ = createInBoundsGEP(result, indices);
-      } else {
-        B.CreateCondBr(B.CreateIsNotNull(result), label_then, label_end);
-
-        B.SetInsertPoint(label_then);
-        vector<Value *> indices({B.getInt32(0), B.getInt32(n->sub_decl_->slot_)});
-        Value *field = createInBoundsGEP(result, indices);
-        B.CreateBr(label_end);
-
-        B.SetInsertPoint(label_end);
-        PHINode *phi = B.CreatePHI(ptr_type, 2);
-        phi->addIncoming(err_cast, label_start);
-        phi->addIncoming(field, label_then);
-        expr_ = phi;
-      }
-    } else {
-      return mkstatus_(n, "unsupported");
-    }
-  } else {
-    expr_ = result;
-  }
-  return StatusTuple::OK();
-}
-
-/// on_match
-StatusTuple CodegenLLVM::visit_match_decl_stmt_node(MatchDeclStmtNode *n) {
-  if (n->formals_.size() != 1)
-    return mkstatus_(n, "on_match expected 1 arguments, %zu given", n->formals_.size());
-  StructVariableDeclStmtNode* leaf_n = static_cast<StructVariableDeclStmtNode*>(n->formals_.at(0).get());
-  if (!leaf_n)
-    return mkstatus_(n, "invalid parameter type");
-  // lookup result variable
-  auto result_decl = scopes_->current_var()->lookup("_result", false);
-  if (!result_decl) return mkstatus_(n, "unable to find _result built-in");
-  auto result = vars_.find(result_decl);
-  if (result == vars_.end()) return mkstatus_(n, "unable to find memory for _result built-in");
-  vars_[leaf_n] = result->second;
-
-  Value *load_1 = createLoad(result->second);
-  Value *is_null = B.CreateIsNotNull(load_1);
-
-  Function *parent = B.GetInsertBlock()->getParent();
-  BasicBlock *label_then = BasicBlock::Create(ctx(), "onvalid.then", parent);
-  BasicBlock *label_end = BasicBlock::Create(ctx(), "onvalid.end", parent);
-  B.CreateCondBr(is_null, label_then, label_end);
-
-  {
-    BlockStack bstack(this, label_then);
-    TRY2(n->block_->accept(this));
-    if (!B.GetInsertBlock()->getTerminator())
-      B.CreateBr(label_end);
-  }
-
-  B.SetInsertPoint(label_end);
-  return StatusTuple::OK();
-}
-
-/// on_miss
-StatusTuple CodegenLLVM::visit_miss_decl_stmt_node(MissDeclStmtNode *n) {
-  if (n->formals_.size() != 0)
-    return mkstatus_(n, "on_match expected 0 arguments, %zu given", n->formals_.size());
-  auto result_decl = scopes_->current_var()->lookup("_result", false);
-  if (!result_decl) return mkstatus_(n, "unable to find _result built-in");
-  auto result = vars_.find(result_decl);
-  if (result == vars_.end()) return mkstatus_(n, "unable to find memory for _result built-in");
-
-  Value *load_1 = createLoad(result->second);
-  Value *is_null = B.CreateIsNull(load_1);
-
-  Function *parent = B.GetInsertBlock()->getParent();
-  BasicBlock *label_then = BasicBlock::Create(ctx(), "onvalid.then", parent);
-  BasicBlock *label_end = BasicBlock::Create(ctx(), "onvalid.end", parent);
-  B.CreateCondBr(is_null, label_then, label_end);
-
-  {
-    BlockStack bstack(this, label_then);
-    TRY2(n->block_->accept(this));
-    if (!B.GetInsertBlock()->getTerminator())
-      B.CreateBr(label_end);
-  }
-
-  B.SetInsertPoint(label_end);
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_failure_decl_stmt_node(FailureDeclStmtNode *n) {
-  return mkstatus_(n, "unsupported");
-}
-
-StatusTuple CodegenLLVM::visit_expr_stmt_node(ExprStmtNode *n) {
-  TRY2(n->expr_->accept(this));
-  expr_ = nullptr;
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_struct_variable_decl_stmt_node(StructVariableDeclStmtNode *n) {
-  if (n->struct_id_->name_ == "" || n->struct_id_->name_[0] == '_') {
-    return StatusTuple::OK();
-  }
-
-  StructType *stype;
-  StructDeclStmtNode *decl;
-  TRY2(lookup_struct_type(n, &stype, &decl));
-
-  Type *ptr_stype = n->is_pointer() ? PointerType::getUnqual(stype) : (PointerType *)stype;
-  AllocaInst *ptr_a = make_alloca(resolve_entry_stack(), ptr_stype);
-  vars_[n] = ptr_a;
-
-  if (n->struct_id_->scope_name_ == "proto") {
-    if (n->is_pointer()) {
-      ConstantPointerNull *const_null = ConstantPointerNull::get(cast<PointerType>(ptr_stype));
-      B.CreateStore(const_null, ptr_a);
-    } else {
-      return mkstatus_(n, "unsupported");
-      // string var = n->scope_id() + n->id_->name_;
-      // /* zero initialize array to be filled in with packet header */
-      // emit("uint64_t __%s[%zu] = {}; uint8_t *%s = (uint8_t*)__%s;",
-      //      var.c_str(), ((decl->bit_width_ >> 3) + 7) >> 3, var.c_str(), var.c_str());
-      // for (auto it = n->init_.begin(); it != n->init_.end(); ++it) {
-      //   auto asn = static_cast<AssignExprNode*>(it->get());
-      //   if (auto f = decl->field(asn->id_->sub_name_)) {
-      //     size_t bit_offset = f->bit_offset_;
-      //     size_t bit_width = f->bit_width_;
-      //     if (asn->bitop_) {
-      //       bit_offset += f->bit_width_ - (asn->bitop_->bit_offset_ + asn->bitop_->bit_width_);
-      //       bit_width = std::min(bit_width - asn->bitop_->bit_offset_, asn->bitop_->bit_width_);
-      //     }
-      //     emit(" bpf_dins(%s + %zu, %zu, %zu, ", var.c_str(), bit_offset >> 3, bit_offset & 0x7, bit_width);
-      //     TRY2(asn->rhs_->accept(this));
-      //     emit(");");
-      //   }
-      // }
-    }
-  } else {
-    if (n->is_pointer()) {
-      if (n->id_->name_ == "_result") {
-        // special case for capturing the return value of a previous method call
-        Value *cast_1 = B.CreateBitCast(pop_expr(), ptr_stype);
-        B.CreateStore(cast_1, ptr_a);
-      } else {
-        ConstantPointerNull *const_null = ConstantPointerNull::get(cast<PointerType>(ptr_stype));
-        B.CreateStore(const_null, ptr_a);
-      }
-    } else {
-#if LLVM_MAJOR_VERSION >= 10
-      B.CreateMemSet(ptr_a, B.getInt8(0), B.getInt64(decl->bit_width_ >> 3), MaybeAlign(1));
-#else
-      B.CreateMemSet(ptr_a, B.getInt8(0), B.getInt64(decl->bit_width_ >> 3), 1);
-#endif
-      if (!n->init_.empty()) {
-        for (auto it = n->init_.begin(); it != n->init_.end(); ++it)
-          TRY2((*it)->accept(this));
-      }
-    }
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_integer_variable_decl_stmt_node(IntegerVariableDeclStmtNode *n) {
-  if (!B.GetInsertBlock())
-    return StatusTuple::OK();
-
-  // uintX var = init
-  AllocaInst *ptr_a = make_alloca(resolve_entry_stack(),
-                                  B.getIntNTy(n->bit_width_), n->id_->name_);
-  vars_[n] = ptr_a;
-
-  // todo
-  if (!n->init_.empty())
-    TRY2(n->init_[0]->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_struct_decl_stmt_node(StructDeclStmtNode *n) {
-  ++indent_;
-  StructType *struct_type = StructType::create(ctx(), "_struct." + n->id_->name_);
-  vector<Type *> fields;
-  for (auto it = n->stmts_.begin(); it != n->stmts_.end(); ++it)
-    fields.push_back(B.getIntNTy((*it)->bit_width_));
-  struct_type->setBody(fields, n->is_packed());
-  structs_[n] = struct_type;
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_parser_state_stmt_node(ParserStateStmtNode *n) {
-  string jump_label = n->scoped_name() + "_continue";
-  BasicBlock *label_entry = resolve_label(jump_label);
-  B.SetInsertPoint(label_entry);
-  if (n->next_state_)
-    TRY2(n->next_state_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_state_decl_stmt_node(StateDeclStmtNode *n) {
-  if (!n->id_)
-    return StatusTuple::OK();
-  string jump_label = n->scoped_name();
-  BasicBlock *label_entry = resolve_label(jump_label);
-  B.SetInsertPoint(label_entry);
-
-  auto it = n->subs_.begin();
-
-  scopes_->push_state(it->scope_);
-
-  for (auto in = n->init_.begin(); in != n->init_.end(); ++in)
-    TRY2((*in)->accept(this));
-
-  if (n->subs_.size() == 1 && it->id_->name_ == "") {
-    // this is not a multistate protocol, emit everything and finish
-    TRY2(it->block_->accept(this));
-    if (n->parser_) {
-      B.CreateBr(resolve_label(jump_label + "_continue"));
-      TRY2(n->parser_->accept(this));
-    }
-  } else {
-    return mkstatus_(n, "unsupported");
-  }
-
-  scopes_->pop_state();
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_table_decl_stmt_node(TableDeclStmtNode *n) {
-  if (n->table_type_->name_ == "Table"
-      || n->table_type_->name_ == "SharedTable") {
-    if (n->templates_.size() != 4)
-      return mkstatus_(n, "%s expected 4 arguments, %zu given", n->table_type_->c_str(), n->templates_.size());
-    auto key = scopes_->top_struct()->lookup(n->key_id()->name_, /*search_local*/true);
-    if (!key) return mkstatus_(n, "cannot find key %s", n->key_id()->name_.c_str());
-    auto leaf = scopes_->top_struct()->lookup(n->leaf_id()->name_, /*search_local*/true);
-    if (!leaf) return mkstatus_(n, "cannot find leaf %s", n->leaf_id()->name_.c_str());
-
-    bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
-    if (n->type_id()->name_ == "FIXED_MATCH")
-      map_type = BPF_MAP_TYPE_HASH;
-    else if (n->type_id()->name_ == "INDEXED")
-      map_type = BPF_MAP_TYPE_ARRAY;
-    else
-      return mkstatus_(n, "Table type %s not implemented", n->type_id()->name_.c_str());
-
-    StructType *key_stype, *leaf_stype;
-    TRY2(lookup_struct_type(n->key_type_, &key_stype));
-    TRY2(lookup_struct_type(n->leaf_type_, &leaf_stype));
-#if LLVM_MAJOR_VERSION >= 12
-    StructType *decl_struct = StructType::getTypeByName(mod_->getContext(), "_struct." + n->id_->name_);
-#else
-    StructType *decl_struct = mod_->getTypeByName("_struct." + n->id_->name_);
-#endif
-    if (!decl_struct)
-      decl_struct = StructType::create(ctx(), "_struct." + n->id_->name_);
-    if (decl_struct->isOpaque())
-      decl_struct->setBody(vector<Type *>({key_stype, leaf_stype}), /*isPacked=*/false);
-    GlobalVariable *decl_gvar = new GlobalVariable(*mod_, decl_struct, false,
-                                                   GlobalValue::ExternalLinkage, 0, n->id_->name_);
-    decl_gvar->setSection("maps");
-    tables_[n] = decl_gvar;
-
-    int map_fd = bcc_create_map(map_type, n->id_->name_.c_str(),
-                                key->bit_width_ / 8, leaf->bit_width_ / 8,
-                                n->size_, 0);
-    if (map_fd >= 0)
-      table_fds_[n] = map_fd;
-  } else {
-    return mkstatus_(n, "Table %s not implemented", n->table_type_->name_.c_str());
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::lookup_struct_type(StructDeclStmtNode *decl, StructType **stype) const {
-  auto struct_it = structs_.find(decl);
-  if (struct_it == structs_.end())
-    return mkstatus_(decl, "could not find IR for type %s", decl->id_->c_str());
-  *stype = struct_it->second;
-
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::lookup_struct_type(VariableDeclStmtNode *n, StructType **stype,
-                                            StructDeclStmtNode **decl) const {
-  if (!n->is_struct())
-    return mkstatus_(n, "attempt to search for struct with a non-struct type %s", n->id_->c_str());
-
-  auto var = (StructVariableDeclStmtNode *)n;
-  StructDeclStmtNode *type;
-  if (var->struct_id_->scope_name_ == "proto")
-    type = proto_scopes_->top_struct()->lookup(var->struct_id_->name_, true);
-  else
-    type = scopes_->top_struct()->lookup(var->struct_id_->name_, true);
-
-  if (!type) return mkstatus_(n, "could not find type %s", var->struct_id_->c_str());
-
-  TRY2(lookup_struct_type(type, stype));
-
-  if (decl)
-    *decl = type;
-
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit_func_decl_stmt_node(FuncDeclStmtNode *n) {
-  if (n->formals_.size() != 1)
-    return mkstatus_(n, "Functions must have exactly 1 argument, %zd given", n->formals_.size());
-
-  vector<Type *> formals;
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    VariableDeclStmtNode *formal = it->get();
-    if (formal->is_struct()) {
-      StructType *stype;
-      //TRY2(lookup_struct_type(formal, &stype));
-      auto var = (StructVariableDeclStmtNode *)formal;
-#if LLVM_MAJOR_VERSION >= 12
-      stype = StructType::getTypeByName(mod_->getContext(), "_struct." + var->struct_id_->name_);
-#else
-      stype = mod_->getTypeByName("_struct." + var->struct_id_->name_);
-#endif
-      if (!stype) return mkstatus_(n, "could not find type %s", var->struct_id_->c_str());
-      formals.push_back(PointerType::getUnqual(stype));
-    } else {
-      formals.push_back(B.getIntNTy(formal->bit_width_));
-    }
-  }
-  FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), formals, /*isVarArg=*/false);
-
-  Function *fn = mod_->getFunction(n->id_->name_);
-  if (fn) return mkstatus_(n, "Function %s already defined", n->id_->c_str());
-  fn = Function::Create(fn_type, GlobalValue::ExternalLinkage, n->id_->name_, mod_);
-  fn->setCallingConv(CallingConv::C);
-  fn->addFnAttr(Attribute::NoUnwind);
-  fn->setSection(BPF_FN_PREFIX + n->id_->name_);
-
-  BasicBlock *label_entry = BasicBlock::Create(ctx(), "entry", fn);
-  B.SetInsertPoint(label_entry);
-  string scoped_entry_label = to_string((uintptr_t)fn) + "::entry";
-  labels_[scoped_entry_label] = label_entry;
-  BasicBlock *label_return = resolve_label("DONE");
-  retval_ = make_alloca(label_entry, fn->getReturnType(), "ret");
-  B.CreateStore(B.getInt32(0), retval_);
-  errval_ = make_alloca(label_entry, B.getInt64Ty(), "err");
-  B.CreateStore(B.getInt64(0), errval_);
-
-  auto formal = n->formals_.begin();
-  for (auto arg = fn->arg_begin(); arg != fn->arg_end(); ++arg, ++formal) {
-    TRY2((*formal)->accept(this));
-    Value *ptr = vars_[formal->get()];
-    if (!ptr) return mkstatus_(n, "cannot locate memory location for arg %s", (*formal)->id_->c_str());
-    B.CreateStore(&*arg, ptr);
-
-    // Type *ptype;
-    // if ((*formal)->is_struct()) {
-    //   StructType *type;
-    //   TRY2(lookup_struct_type(formal->get(), &type));
-    //   ptype = PointerType::getUnqual(type);
-    // } else {
-    //   ptype = PointerType::getUnqual(B.getIntNTy((*formal)->bit_width_));
-    // }
-
-    // arg->setName((*formal)->id_->name_);
-    // AllocaInst *ptr = make_alloca(label_entry, ptype, (*formal)->id_->name_);
-    // B.CreateStore(arg, ptr);
-    // vars_[formal->get()] = ptr;
-  }
-
-  // visit function scoped variables
-  {
-    scopes_->push_state(n->scope_);
-
-    for (auto it = scopes_->current_var()->obegin(); it != scopes_->current_var()->oend(); ++it)
-      TRY2((*it)->accept(this));
-
-    TRY2(n->block_->accept(this));
-
-    scopes_->pop_state();
-    if (!B.GetInsertBlock()->getTerminator())
-      B.CreateBr(resolve_label("DONE"));
-
-    // always return something
-    B.SetInsertPoint(label_return);
-    B.CreateRet(createLoad(retval_));
-  }
-
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::visit(Node *root, TableStorage &ts, const string &id,
-                               const string &maps_ns) {
-  scopes_->set_current(scopes_->top_state());
-  scopes_->set_current(scopes_->top_var());
-
-  TRY2(print_header());
-
-  for (auto it = scopes_->top_table()->obegin(); it != scopes_->top_table()->oend(); ++it)
-    TRY2((*it)->accept(this));
-
-  for (auto it = scopes_->top_func()->obegin(); it != scopes_->top_func()->oend(); ++it)
-    TRY2((*it)->accept(this));
-  //TRY2(print_parser());
-
-  for (auto table : tables_) {
-    bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
-    if (table.first->type_id()->name_ == "FIXED_MATCH")
-      map_type = BPF_MAP_TYPE_HASH;
-    else if (table.first->type_id()->name_ == "INDEXED")
-      map_type = BPF_MAP_TYPE_ARRAY;
-    ts.Insert(Path({id, table.first->id_->name_}),
-              {
-                  table.first->id_->name_, FileDesc(table_fds_[table.first]), map_type,
-                  table.first->key_type_->bit_width_ >> 3, table.first->leaf_type_->bit_width_ >> 3,
-                  table.first->size_, 0,
-              });
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple CodegenLLVM::print_header() {
-
-  GlobalVariable *gvar_license = new GlobalVariable(*mod_, ArrayType::get(Type::getInt8Ty(ctx()), 4),
-                                                    false, GlobalValue::ExternalLinkage, 0, "_license");
-  gvar_license->setSection("license");
-  gvar_license->setInitializer(ConstantDataArray::getString(ctx(), "GPL", true));
-
-  Function *pseudo_fn = mod_->getFunction("llvm.bpf.pseudo");
-  if (!pseudo_fn) {
-    pseudo_fn = Function::Create(
-        FunctionType::get(B.getInt64Ty(), vector<Type *>({B.getInt64Ty(), B.getInt64Ty()}), false),
-        GlobalValue::ExternalLinkage, "llvm.bpf.pseudo", mod_);
-  }
-
-  // declare structures
-  for (auto it = scopes_->top_struct()->obegin(); it != scopes_->top_struct()->oend(); ++it) {
-    if ((*it)->id_->name_ == "_Packet")
-      continue;
-    TRY2((*it)->accept(this));
-  }
-  for (auto it = proto_scopes_->top_struct()->obegin(); it != proto_scopes_->top_struct()->oend(); ++it) {
-    if ((*it)->id_->name_ == "_Packet")
-      continue;
-    TRY2((*it)->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-int CodegenLLVM::get_table_fd(const string &name) const {
-  TableDeclStmtNode *table = scopes_->top_table()->lookup(name);
-  if (!table)
-    return -1;
-
-  auto table_fd_it = table_fds_.find(table);
-  if (table_fd_it == table_fds_.end())
-    return -1;
-
-  return table_fd_it->second;
-}
-
-LLVMContext & CodegenLLVM::ctx() const {
-  return mod_->getContext();
-}
-
-Constant * CodegenLLVM::const_int(uint64_t val, unsigned bits, bool is_signed) {
-  return ConstantInt::get(ctx(), APInt(bits, val, is_signed));
-}
-
-Value * CodegenLLVM::pop_expr() {
-  Value *ret = expr_;
-  expr_ = nullptr;
-  return ret;
-}
-
-BasicBlock * CodegenLLVM::resolve_label(const string &label) {
-  Function *parent = B.GetInsertBlock()->getParent();
-  string scoped_label = to_string((uintptr_t)parent) + "::" + label;
-  auto it = labels_.find(scoped_label);
-  if (it != labels_.end()) return it->second;
-  BasicBlock *label_new = BasicBlock::Create(ctx(), label, parent);
-  labels_[scoped_label] = label_new;
-  return label_new;
-}
-
-Instruction * CodegenLLVM::resolve_entry_stack() {
-  BasicBlock *label_entry = resolve_label("entry");
-  return &label_entry->back();
-}
-
-AllocaInst *CodegenLLVM::make_alloca(Instruction *Inst, Type *Ty,
-                                     const string &name, Value *ArraySize) {
-  IRBuilderBase::InsertPoint ip = B.saveIP();
-  B.SetInsertPoint(Inst);
-  AllocaInst *a = B.CreateAlloca(Ty, ArraySize, name);
-  B.restoreIP(ip);
-  return a;
-}
-
-AllocaInst *CodegenLLVM::make_alloca(BasicBlock *BB, Type *Ty,
-                                     const string &name, Value *ArraySize) {
-  IRBuilderBase::InsertPoint ip = B.saveIP();
-  B.SetInsertPoint(BB);
-  AllocaInst *a = B.CreateAlloca(Ty, ArraySize, name);
-  B.restoreIP(ip);
-  return a;
-}
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/codegen_llvm.h b/src/cc/frontends/b/codegen_llvm.h
deleted file mode 100644 (file)
index 4998526..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <map>
-#include <stdio.h>
-#include <vector>
-#include <string>
-#include <set>
-
-#include "node.h"
-#include "scope.h"
-
-namespace llvm {
-class AllocaInst;
-template<typename T> class ArrayRef;
-class BasicBlock;
-class BranchInst;
-class CallInst;
-class Constant;
-class Instruction;
-class IRBuilderBase;
-class LLVMContext;
-class LoadInst;
-class Module;
-class StructType;
-class SwitchInst;
-class Type;
-class Value;
-class GlobalVariable;
-}
-
-namespace ebpf {
-
-class TableStorage;
-
-namespace cc {
-
-class BlockStack;
-class SwitchStack;
-
-using std::vector;
-using std::string;
-using std::set;
-
-class CodegenLLVM : public Visitor {
-  friend class BlockStack;
-  friend class SwitchStack;
- public:
-  CodegenLLVM(llvm::Module *mod, Scopes *scopes, Scopes *proto_scopes);
-  virtual ~CodegenLLVM();
-
-#define VISIT(type, func) virtual STATUS_RETURN visit_##func(type* n);
-  EXPAND_NODES(VISIT)
-#undef VISIT
-
-  STATUS_RETURN visit(Node *n, TableStorage &ts, const std::string &id,
-                      const std::string &maps_ns);
-
-  int get_table_fd(const std::string &name) const;
-
- private:
-  STATUS_RETURN emit_short_circuit_and(BinopExprNode* n);
-  STATUS_RETURN emit_short_circuit_or(BinopExprNode* n);
-  STATUS_RETURN emit_table_lookup(MethodCallExprNode* n);
-  STATUS_RETURN emit_table_update(MethodCallExprNode* n);
-  STATUS_RETURN emit_table_delete(MethodCallExprNode* n);
-  STATUS_RETURN emit_log(MethodCallExprNode* n);
-  STATUS_RETURN emit_packet_rewrite_field(MethodCallExprNode* n);
-  STATUS_RETURN emit_atomic_add(MethodCallExprNode* n);
-  STATUS_RETURN emit_cksum(MethodCallExprNode* n);
-  STATUS_RETURN emit_incr_cksum(MethodCallExprNode* n, size_t sz = 0);
-  STATUS_RETURN emit_lb_hash(MethodCallExprNode* n);
-  STATUS_RETURN emit_sizeof(MethodCallExprNode* n);
-  STATUS_RETURN emit_get_usec_time(MethodCallExprNode* n);
-  STATUS_RETURN emit_forward_to_vnf(MethodCallExprNode* n);
-  STATUS_RETURN emit_forward_to_group(MethodCallExprNode* n);
-  STATUS_RETURN print_header();
-
-  llvm::LLVMContext & ctx() const;
-  llvm::Constant * const_int(uint64_t val, unsigned bits = 64, bool is_signed = false);
-  llvm::Value * pop_expr();
-  llvm::BasicBlock * resolve_label(const string &label);
-  llvm::Instruction * resolve_entry_stack();
-  llvm::AllocaInst *make_alloca(llvm::Instruction *Inst, llvm::Type *Ty,
-                                const std::string &name = "",
-                                llvm::Value *ArraySize = nullptr);
-  llvm::AllocaInst *make_alloca(llvm::BasicBlock *BB, llvm::Type *Ty,
-                                const std::string &name = "",
-                                llvm::Value *ArraySize = nullptr);
-  StatusTuple lookup_var(Node *n, const std::string &name, Scopes::VarScope *scope,
-                         VariableDeclStmtNode **decl, llvm::Value **mem) const;
-  StatusTuple lookup_struct_type(StructDeclStmtNode *decl, llvm::StructType **stype) const;
-  StatusTuple lookup_struct_type(VariableDeclStmtNode *n, llvm::StructType **stype,
-                                 StructDeclStmtNode **decl = nullptr) const;
-  llvm::CallInst *createCall(llvm::Value *Callee,
-                             llvm::ArrayRef<llvm::Value *> Args);
-  llvm::LoadInst *createLoad(llvm::Value *Addr);
-  llvm::Value *createInBoundsGEP(llvm::Value *Ptr, llvm::ArrayRef<llvm::Value *> IdxList);
-
-  template <typename... Args> void emit(const char *fmt, Args&&... params);
-  void emit(const char *s);
-
-  FILE* out_;
-  llvm::Module* mod_;
-  llvm::IRBuilderBase *b_;
-  int indent_;
-  int tmp_reg_index_;
-  Scopes *scopes_;
-  Scopes *proto_scopes_;
-  vector<vector<string> > free_instructions_;
-  vector<string> table_inits_;
-  map<string, string> proto_rewrites_;
-  map<TableDeclStmtNode *, llvm::GlobalVariable *> tables_;
-  map<TableDeclStmtNode *, int> table_fds_;
-  map<VariableDeclStmtNode *, llvm::Value *> vars_;
-  map<StructDeclStmtNode *, llvm::StructType *> structs_;
-  map<string, llvm::BasicBlock *> labels_;
-  llvm::SwitchInst *cur_switch_;
-  llvm::Value *expr_;
-  llvm::AllocaInst *retval_;
-  llvm::AllocaInst *errval_;
-};
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/lexer.h b/src/cc/frontends/b/lexer.h
deleted file mode 100644 (file)
index 394daa3..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#ifndef yyFlexLexerOnce
-#undef yyFlexLexer
-#define yyFlexLexer ebpfccFlexLexer
-#include <FlexLexer.h>
-#endif
-
-#undef YY_DECL
-#define YY_DECL int ebpf::cc::Lexer::yylex()
-
-#include <iostream> // NOLINT
-#include <list>
-#include "parser.yy.hh"
-
-namespace ebpf {
-namespace cc {
-
-typedef BisonParser::token::yytokentype Tok;
-
-class Lexer : public yyFlexLexer {
- public:
-  explicit Lexer(std::istream* in)
-      : yyFlexLexer(in), prev_tok_(Tok::TSEMI), lines_({""}), yylval_(NULL), yylloc_(NULL) {
-    if (!in || !*in)
-      fprintf(stderr, "Unable to open input stream\n");
-  }
-  int yylex(BisonParser::semantic_type *lval, BisonParser::location_type *lloc) {
-    yylval_ = lval;
-    yylloc_ = lloc;
-    return yylex();
-  }
-  std::string text(const BisonParser::location_type& loc) const {
-    return text(loc.begin, loc.end);
-  }
-  std::string text(const position& begin, const position& end) const {
-    std::string result;
-    for (auto i = begin.line; i <= end.line; ++i) {
-      if (i == begin.line && i == end.line) {
-        result += lines_.at(i - 1).substr(begin.column - 1, end.column - begin.column);
-      } else if (i == begin.line && i < end.line) {
-        result += lines_.at(i - 1).substr(begin.column - 1);
-      } else if (i > begin.line && i == end.line) {
-        result += lines_.at(i - 1).substr(0, end.column);
-      } else if (i > begin.line && i == end.line) {
-        result += lines_.at(i - 1);
-      }
-    }
-    return result;
-  }
- private:
-
-  // true if a semicolon should be replaced here
-  bool next_line() {
-    lines_.push_back("");
-    yylloc_->lines();
-    yylloc_->step();
-    switch (prev_tok_) {
-    case Tok::TIDENTIFIER:
-    case Tok::TINTEGER:
-    case Tok::THEXINTEGER:
-    case Tok::TRBRACE:
-    case Tok::TRPAREN:
-    case Tok::TRBRACK:
-    case Tok::TTRUE:
-    case Tok::TFALSE:
-      // uncomment to add implicit semicolons
-      //return true;
-    default:
-      break;
-    }
-    return false;
-  }
-
-  Tok save(Tok tok, bool ignore_text = false) {
-    if (!ignore_text) {
-      save_text();
-    }
-
-    switch (tok) {
-    case Tok::TIDENTIFIER:
-    case Tok::TINTEGER:
-    case Tok::THEXINTEGER:
-      yylval_->string = new std::string(yytext, yyleng);
-      break;
-    default:
-      yylval_->token = tok;
-    }
-    prev_tok_ = tok;
-    return tok;
-  }
-
-  /*
-  std::string * alloc_string(const char *c, size_t len) {
-    strings_.push_back(std::unique_ptr<std::string>(new std::string(c, len)));
-    return strings_.back().get();
-  }
-
-  std::string * alloc_string(const std::string &s) {
-    strings_.push_back(std::unique_ptr<std::string>(new std::string(s)));
-    return strings_.back().get();
-  }
-  */
-
-  void save_text() {
-    lines_.back().append(yytext, yyleng);
-    yylloc_->columns(yyleng);
-  }
-
-  int yylex();
-  Tok prev_tok_;
-  std::vector<std::string> lines_;
-  //std::list<std::unique_ptr<std::string>> strings_;
-  BisonParser::semantic_type *yylval_;
-  BisonParser::location_type *yylloc_;
-};
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/lexer.ll b/src/cc/frontends/b/lexer.ll
deleted file mode 100644 (file)
index 1072b59..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-%{
-#include "lexer.h"
-%}
-
-%option yylineno nodefault yyclass="Lexer" noyywrap c++ prefix="ebpfcc"
-%option never-interactive
-%{
-#include <string>
-#include "parser.yy.hh"
-std::string tmp_str_cc;
-%}
-
-%x STRING_
-%%
-
-\"                      {BEGIN STRING_;}
-<STRING_>\"             { BEGIN 0;
-                        yylval_->string = new std::string(tmp_str_cc);
-                        tmp_str_cc = "";
-                        return Tok::TSTRING;
-                        }
-<STRING_>\\n            {tmp_str_cc += "\n"; }
-<STRING_>.              {tmp_str_cc += *yytext; }
-
-
-
-[ \t]+                  { save_text(); }
-\n                      { if (next_line()) { return save(Tok::TSEMI, true); } }
-"//".*\n                { if (next_line()) { return save(Tok::TSEMI, true); } }
-^"#"                    return save(Tok::TPRAGMA);
-"="                     return save(Tok::TEQUAL);
-"=="                    return save(Tok::TCEQ);
-"!="                    return save(Tok::TCNE);
-"<"                     return save(Tok::TCLT);
-"<="                    return save(Tok::TCLE);
-">"                     return save(Tok::TCGT);
-">="                    return save(Tok::TCGE);
-"("                     return save(Tok::TLPAREN);
-")"                     return save(Tok::TRPAREN);
-"{"                     return save(Tok::TLBRACE);
-"}"                     return save(Tok::TRBRACE);
-"["                     return save(Tok::TLBRACK);
-"]"                     return save(Tok::TRBRACK);
-"->"                    return save(Tok::TARROW);
-"."                     return save(Tok::TDOT);
-","                     return save(Tok::TCOMMA);
-"+"                     return save(Tok::TPLUS);
-"++"                    return save(Tok::TINCR);
-"-"                     return save(Tok::TMINUS);
-"--"                    return save(Tok::TDECR);
-"*"                     return save(Tok::TMUL);
-"/"                     return save(Tok::TDIV);
-"%"                     return save(Tok::TMOD);
-"^"                     return save(Tok::TXOR);
-"$"                     return save(Tok::TDOLLAR);
-"!"                     return save(Tok::TNOT);
-"~"                     return save(Tok::TCMPL);
-":"                     return save(Tok::TCOLON);
-"::"                    return save(Tok::TSCOPE);
-";"                     return save(Tok::TSEMI);
-"&&"                    return save(Tok::TAND);
-"||"                    return save(Tok::TOR);
-"&"                     return save(Tok::TLAND);
-"|"                     return save(Tok::TLOR);
-"@"                     return save(Tok::TAT);
-
-"case"                  return save(Tok::TCASE);
-"continue"              return save(Tok::TCONTINUE);
-"else"                  return save(Tok::TELSE);
-"false"                 return save(Tok::TFALSE);
-"goto"                  return save(Tok::TGOTO);
-"if"                    return save(Tok::TIF);
-"next"                  return save(Tok::TNEXT);
-"on_match"              return save(Tok::TMATCH);
-"on_miss"               return save(Tok::TMISS);
-"on_failure"            return save(Tok::TFAILURE);
-"on_valid"              return save(Tok::TVALID);
-"return"                return save(Tok::TRETURN);
-"state"                 return save(Tok::TSTATE);
-"struct"                return save(Tok::TSTRUCT);
-"switch"                return save(Tok::TSWITCH);
-"true"                  return save(Tok::TTRUE);
-"u8"                    return save(Tok::TU8);
-"u16"                   return save(Tok::TU16);
-"u32"                   return save(Tok::TU32);
-"u64"                   return save(Tok::TU64);
-
-[a-zA-Z_][a-zA-Z0-9_]*  return save(Tok::TIDENTIFIER);
-[0-9]+                  return save(Tok::TINTEGER);
-0x[0-9a-fA-F]+          return save(Tok::THEXINTEGER);
-
-.                       printf("Unknown token \"%s\"\n", yytext); yyterminate();
-
-%%
diff --git a/src/cc/frontends/b/loader.cc b/src/cc/frontends/b/loader.cc
deleted file mode 100644 (file)
index b7b6355..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "common.h"
-#include "parser.h"
-#include "type_check.h"
-#include "codegen_llvm.h"
-#include "loader.h"
-
-using std::string;
-using std::unique_ptr;
-using std::vector;
-
-namespace ebpf {
-
-BLoader::BLoader(unsigned flags) : flags_(flags) {
-  (void)flags_;
-}
-
-BLoader::~BLoader() {
-}
-
-int BLoader::parse(llvm::Module *mod, const string &filename, const string &proto_filename,
-                   TableStorage &ts, const string &id, const std::string &maps_ns) {
-  int rc;
-
-  proto_parser_ = make_unique<ebpf::cc::Parser>(proto_filename);
-  rc = proto_parser_->parse();
-  if (rc) {
-    fprintf(stderr, "In file: %s\n", filename.c_str());
-    return rc;
-  }
-
-  parser_ = make_unique<ebpf::cc::Parser>(filename);
-  rc = parser_->parse();
-  if (rc) {
-    fprintf(stderr, "In file: %s\n", filename.c_str());
-    return rc;
-  }
-
-  //ebpf::cc::Printer printer(stderr);
-  //printer.visit(parser_->root_node_);
-
-  ebpf::cc::TypeCheck type_check(parser_->scopes_.get(), proto_parser_->scopes_.get());
-  auto ret = type_check.visit(parser_->root_node_);
-  if (!ret.ok() || ret.msg().size()) {
-    fprintf(stderr, "Type error @line=%d: %s\n", ret.code(), ret.msg().c_str());
-    return -1;
-  }
-
-  codegen_ = ebpf::make_unique<ebpf::cc::CodegenLLVM>(mod, parser_->scopes_.get(), proto_parser_->scopes_.get());
-  ret = codegen_->visit(parser_->root_node_, ts, id, maps_ns);
-  if (!ret.ok() || ret.msg().size()) {
-    fprintf(stderr, "Codegen error @line=%d: %s\n", ret.code(), ret.msg().c_str());
-    return ret.code();
-  }
-
-  return 0;
-}
-
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/loader.h b/src/cc/frontends/b/loader.h
deleted file mode 100644 (file)
index 6330d5c..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "table_storage.h"
-
-namespace llvm {
-class Module;
-}
-
-namespace ebpf {
-
-namespace cc {
-class Parser;
-class CodegenLLVM;
-}
-
-class BLoader {
- public:
-  explicit BLoader(unsigned flags);
-  ~BLoader();
-  int parse(llvm::Module *mod, const std::string &filename, const std::string &proto_filename,
-            TableStorage &ts, const std::string &id, const std::string &maps_ns);
-
- private:
-  unsigned flags_;
-  std::unique_ptr<cc::Parser> parser_;
-  std::unique_ptr<cc::Parser> proto_parser_;
-  std::unique_ptr<cc::CodegenLLVM> codegen_;
-};
-
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/node.cc b/src/cc/frontends/b/node.cc
deleted file mode 100644 (file)
index 6dac700..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <vector>
-#include <string>
-
-#include "node.h"
-
-namespace ebpf {
-namespace cc {
-
-#define ACCEPT(type, func) \
-  STATUS_RETURN type::accept(Visitor* v) { return v->visit_##func(this); }
-EXPAND_NODES(ACCEPT)
-#undef ACCEPT
-
-VariableDeclStmtNode* StructDeclStmtNode::field(const string& name) const {
-  for (auto it = stmts_.begin(); it != stmts_.end(); ++it) {
-    if ((*it)->id_->name_ == name) {
-      return it->get();
-    }
-  }
-  return NULL;
-}
-
-int StructDeclStmtNode::indexof(const string& name) const {
-  int i = 0;
-  for (auto it = stmts_.begin(); it != stmts_.end(); ++it, ++i) {
-    if ((*it)->id_->name_ == name) {
-      return i;
-    }
-  }
-  return -1;
-}
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/node.h b/src/cc/frontends/b/node.h
deleted file mode 100644 (file)
index 6490566..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <vector>
-#include <bitset>
-#include <string>
-#include <memory>
-#include <algorithm>
-#include <stdint.h>
-
-#include "common.h"
-#include "bcc_exception.h"
-#include "scope.h"
-
-#define REVISION_MASK 0xfff
-#define MAJOR_VER_POS 22
-#define MAJOR_VER_MASK ~((1 << MAJOR_VER_POS) - 1)
-#define MINOR_VER_POS 12
-#define MINOR_VER_MASK (~((1 << MINOR_VER_POS) - 1) & (~(MAJOR_VER_MASK)))
-#define GET_MAJOR_VER(version) ((version & MAJOR_VER_MASK) >> MAJOR_VER_POS)
-#define GET_MINOR_VER(version) ((version & MINOR_VER_MASK) >> MINOR_VER_POS)
-#define GET_REVISION(version) (version & REVISION_MASK)
-#define MAKE_VERSION(major, minor, rev) \
-    ((major << MAJOR_VER_POS) | \
-     (minor << MINOR_VER_POS) | \
-     (rev & REVISION_MASK))
-
-#define STATUS_RETURN __attribute((warn_unused_result)) StatusTuple
-
-namespace ebpf {
-
-namespace cc {
-
-using std::unique_ptr;
-using std::move;
-using std::string;
-using std::vector;
-using std::bitset;
-using std::find;
-
-typedef unique_ptr<string> String;
-
-#define NODE_EXPRESSIONS(EXPAND) \
-  EXPAND(IdentExprNode, ident_expr_node) \
-  EXPAND(AssignExprNode, assign_expr_node) \
-  EXPAND(PacketExprNode, packet_expr_node) \
-  EXPAND(IntegerExprNode, integer_expr_node) \
-  EXPAND(StringExprNode, string_expr_node) \
-  EXPAND(BinopExprNode, binop_expr_node) \
-  EXPAND(UnopExprNode, unop_expr_node) \
-  EXPAND(BitopExprNode, bitop_expr_node) \
-  EXPAND(GotoExprNode, goto_expr_node) \
-  EXPAND(ReturnExprNode, return_expr_node) \
-  EXPAND(MethodCallExprNode, method_call_expr_node) \
-  EXPAND(TableIndexExprNode, table_index_expr_node)
-
-#define NODE_STATEMENTS(EXPAND) \
-  EXPAND(ExprStmtNode, expr_stmt_node) \
-  EXPAND(BlockStmtNode, block_stmt_node) \
-  EXPAND(IfStmtNode, if_stmt_node) \
-  EXPAND(OnValidStmtNode, onvalid_stmt_node) \
-  EXPAND(SwitchStmtNode, switch_stmt_node) \
-  EXPAND(CaseStmtNode, case_stmt_node) \
-  EXPAND(StructVariableDeclStmtNode, struct_variable_decl_stmt_node) \
-  EXPAND(IntegerVariableDeclStmtNode, integer_variable_decl_stmt_node) \
-  EXPAND(StructDeclStmtNode, struct_decl_stmt_node) \
-  EXPAND(StateDeclStmtNode, state_decl_stmt_node) \
-  EXPAND(ParserStateStmtNode, parser_state_stmt_node) \
-  EXPAND(MatchDeclStmtNode, match_decl_stmt_node) \
-  EXPAND(MissDeclStmtNode, miss_decl_stmt_node) \
-  EXPAND(FailureDeclStmtNode, failure_decl_stmt_node) \
-  EXPAND(TableDeclStmtNode, table_decl_stmt_node) \
-  EXPAND(FuncDeclStmtNode, func_decl_stmt_node)
-
-#define EXPAND_NODES(EXPAND) \
-  NODE_EXPRESSIONS(EXPAND) \
-  NODE_STATEMENTS(EXPAND)
-
-class Visitor;
-
-// forward declare all classes
-#define FORWARD(type, func) class type;
-EXPAND_NODES(FORWARD)
-#undef FORWARD
-
-#define DECLARE(type) \
-  typedef unique_ptr<type> Ptr; \
-  virtual StatusTuple accept(Visitor* v);
-
-class Node {
- public:
-  typedef unique_ptr<Node> Ptr;
-  Node() : line_(-1), column_(-1) {}
-  virtual ~Node() {}
-  virtual StatusTuple accept(Visitor* v) = 0;
-  int line_;
-  int column_;
-  string text_;
-};
-
-template <typename... Args>
-StatusTuple mkstatus_(Node *n, const char *fmt, Args... args) {
-  StatusTuple status = StatusTuple(n->line_ ? n->line_ : -1, fmt, args...);
-  if (n->line_ > 0)
-    status.append_msg("\n" + n->text_);
-  return status;
-}
-
-static inline StatusTuple mkstatus_(Node *n, const char *msg) {
-  StatusTuple status = StatusTuple(n->line_ ? n->line_ : -1, msg);
-  if (n->line_ > 0)
-    status.append_msg("\n" + n->text_);
-  return status;
-}
-
-class StmtNode : public Node {
- public:
-  typedef unique_ptr<StmtNode> Ptr;
-  virtual StatusTuple accept(Visitor* v) = 0;
-
-};
-typedef vector<StmtNode::Ptr> StmtNodeList;
-
-class ExprNode : public Node {
- public:
-  typedef unique_ptr<ExprNode> Ptr;
-  virtual StatusTuple accept(Visitor* v) = 0;
-  enum expr_type { STRUCT, INTEGER, STRING, VOID, UNKNOWN };
-  enum prop_flag { READ = 0, WRITE, PROTO, IS_LHS, IS_REF, IS_PKT, LAST };
-  expr_type typeof_;
-  StructDeclStmtNode *struct_type_;
-  size_t bit_width_;
-  bitset<LAST> flags_;
-  unique_ptr<BitopExprNode> bitop_;
-  ExprNode() : typeof_(UNKNOWN), struct_type_(NULL), flags_(1 << READ) {}
-  void copy_type(const ExprNode& other) {
-    typeof_ = other.typeof_;
-    struct_type_ = other.struct_type_;
-    bit_width_ = other.bit_width_;
-    flags_ = other.flags_;
-  }
-  bool is_lhs() const { return flags_[IS_LHS]; }
-  bool is_ref() const { return flags_[IS_REF]; }
-  bool is_pkt() const { return flags_[IS_PKT]; }
-};
-
-typedef vector<ExprNode::Ptr> ExprNodeList;
-
-class IdentExprNode : public ExprNode {
- public:
-  DECLARE(IdentExprNode)
-
-  string name_;
-  string sub_name_;
-  string scope_name_;
-  VariableDeclStmtNode *decl_;
-  VariableDeclStmtNode *sub_decl_;
-  IdentExprNode(const IdentExprNode& other) {
-    name_ = other.name_;
-    sub_name_ = other.sub_name_;
-    scope_name_ = other.scope_name_;
-    decl_ = other.decl_;
-    sub_decl_ = other.sub_decl_;
-  }
-  IdentExprNode::Ptr copy() const {
-    return IdentExprNode::Ptr(new IdentExprNode(*this));
-  }
-  explicit IdentExprNode(const string& id) : name_(id) {}
-  explicit IdentExprNode(const char* id) : name_(id) {}
-  void prepend_scope(const string& id) {
-    scope_name_ = id;
-  }
-  void append_scope(const string& id) {
-    scope_name_ = move(name_);
-    name_ = id;
-  }
-  void prepend_dot(const string& id) {
-    sub_name_ = move(name_);
-    name_ = id;
-  }
-  void append_dot(const string& id) {
-    // we don't support nested struct so keep all subs as single variable
-    if (!sub_name_.empty()) {
-      sub_name_ += "." + id;
-    } else {
-      sub_name_ = id;
-    }
-  }
-  const string& full_name() {
-    if (full_name_.size()) {
-      return full_name_;  // lazy init
-    }
-    if (scope_name_.size()) {
-      full_name_ += scope_name_ + "::";
-    }
-    full_name_ += name_;
-    if (sub_name_.size()) {
-      full_name_ += "." + sub_name_;
-    }
-    return full_name_;
-  }
-  const char* c_str() const { return name_.c_str(); }
- private:
-  string full_name_;
-};
-
-class BitopExprNode : public ExprNode {
- public:
-  DECLARE(BitopExprNode)
-
-  ExprNode::Ptr expr_;
-  size_t bit_offset_;
-  size_t bit_width_;
-  BitopExprNode(const string& bofs, const string& bsz)
-      : bit_offset_(strtoul(bofs.c_str(), NULL, 0)), bit_width_(strtoul(bsz.c_str(), NULL, 0)) {}
-};
-
-typedef vector<IdentExprNode::Ptr> IdentExprNodeList;
-
-class AssignExprNode : public ExprNode {
- public:
-  DECLARE(AssignExprNode)
-
-  //IdentExprNode *id_;
-  ExprNode::Ptr lhs_;
-  ExprNode::Ptr rhs_;
-  AssignExprNode(IdentExprNode::Ptr id, ExprNode::Ptr rhs)
-      : lhs_(move(id)), rhs_(move(rhs)) {
-    //id_ = (IdentExprNode *)lhs_.get();
-    lhs_->flags_[ExprNode::IS_LHS] = true;
-  }
-  AssignExprNode(ExprNode::Ptr lhs, ExprNode::Ptr rhs)
-      : lhs_(move(lhs)), rhs_(move(rhs)) {
-    //id_ = nullptr;
-    lhs_->flags_[ExprNode::IS_LHS] = true;
-  }
-};
-
-class PacketExprNode : public ExprNode {
- public:
-  DECLARE(PacketExprNode)
-
-  IdentExprNode::Ptr id_;
-  explicit PacketExprNode(IdentExprNode::Ptr id) : id_(move(id)) {}
-};
-
-class StringExprNode : public ExprNode {
- public:
-  DECLARE(StringExprNode)
-
-  string val_;
-  explicit StringExprNode(string *val) : val_(move(*val)) {
-    delete val;
-  }
-  explicit StringExprNode(const string &val) : val_(val) {}
-};
-
-class IntegerExprNode : public ExprNode {
- public:
-  DECLARE(IntegerExprNode)
-
-  size_t bits_;
-  string val_;
-  IntegerExprNode(string* val, string* bits)
-      : bits_(strtoul(bits->c_str(), NULL, 0)), val_(move(*val)) {
-    delete val;
-    delete bits;
-  }
-  explicit IntegerExprNode(string* val)
-      : bits_(0), val_(move(*val)) {
-    delete val;
-  }
-  explicit IntegerExprNode(const string& val) : bits_(0), val_(val) {}
-  explicit IntegerExprNode(const string& val, size_t bits) : bits_(bits), val_(val) {}
-};
-
-class BinopExprNode : public ExprNode {
- public:
-  DECLARE(BinopExprNode)
-
-  ExprNode::Ptr lhs_;
-  int op_;
-  ExprNode::Ptr rhs_;
-  BinopExprNode(ExprNode::Ptr lhs, int op, ExprNode::Ptr rhs)
-      : lhs_(move(lhs)), op_(op), rhs_(move(rhs))
-  {}
-};
-
-class UnopExprNode : public ExprNode {
- public:
-  DECLARE(UnopExprNode)
-
-  ExprNode::Ptr expr_;
-  int op_;
-  UnopExprNode(int op, ExprNode::Ptr expr) : expr_(move(expr)), op_(op) {}
-};
-
-class GotoExprNode : public ExprNode {
- public:
-  DECLARE(GotoExprNode)
-
-  bool is_continue_;
-  IdentExprNode::Ptr id_;
-  GotoExprNode(IdentExprNode::Ptr id, bool is_continue = false)
-      : is_continue_(is_continue), id_(move(id)) {}
-};
-
-class ReturnExprNode : public ExprNode {
- public:
-  DECLARE(ReturnExprNode)
-
-  ExprNode::Ptr expr_;
-  ReturnExprNode(ExprNode::Ptr expr)
-      : expr_(move(expr)) {}
-};
-
-class BlockStmtNode : public StmtNode {
- public:
-  DECLARE(BlockStmtNode)
-
-  explicit BlockStmtNode(StmtNodeList stmts = StmtNodeList())
-    : stmts_(move(stmts)), scope_(NULL) {}
-  ~BlockStmtNode() { delete scope_; }
-  StmtNodeList stmts_;
-  Scopes::VarScope* scope_;
-};
-
-class MethodCallExprNode : public ExprNode {
- public:
-  DECLARE(MethodCallExprNode)
-
-  IdentExprNode::Ptr id_;
-  ExprNodeList args_;
-  BlockStmtNode::Ptr block_;
-  MethodCallExprNode(IdentExprNode::Ptr id, ExprNodeList&& args, int lineno)
-      : id_(move(id)), args_(move(args)), block_(make_unique<BlockStmtNode>()) {
-    line_ = lineno;
-  }
-};
-
-class TableIndexExprNode : public ExprNode {
- public:
-  DECLARE(TableIndexExprNode)
-
-  IdentExprNode::Ptr id_;
-  IdentExprNode::Ptr sub_;
-  ExprNode::Ptr index_;
-  TableDeclStmtNode *table_;
-  VariableDeclStmtNode *sub_decl_;
-  TableIndexExprNode(IdentExprNode::Ptr id, ExprNode::Ptr index)
-      : id_(move(id)), index_(move(index)), table_(nullptr), sub_decl_(nullptr)
-  {}
-};
-
-class ExprStmtNode : public StmtNode {
- public:
-  DECLARE(ExprStmtNode)
-
-  ExprNode::Ptr expr_;
-  explicit ExprStmtNode(ExprNode::Ptr expr) : expr_(move(expr)) {}
-};
-
-class IfStmtNode : public StmtNode {
- public:
-  DECLARE(IfStmtNode)
-
-  ExprNode::Ptr cond_;
-  StmtNode::Ptr true_block_;
-  StmtNode::Ptr false_block_;
-  // create an if () {} expression
-  IfStmtNode(ExprNode::Ptr cond, StmtNode::Ptr true_block)
-      : cond_(move(cond)), true_block_(move(true_block)) {}
-  // create an if () {} else {} expression
-  IfStmtNode(ExprNode::Ptr cond, StmtNode::Ptr true_block, StmtNode::Ptr false_block)
-      : cond_(move(cond)), true_block_(move(true_block)),
-      false_block_(move(false_block)) {}
-};
-
-class OnValidStmtNode : public StmtNode {
- public:
-  DECLARE(OnValidStmtNode)
-
-  IdentExprNode::Ptr cond_;
-  StmtNode::Ptr block_;
-  StmtNode::Ptr else_block_;
-  // create an onvalid () {} expression
-  OnValidStmtNode(IdentExprNode::Ptr cond, StmtNode::Ptr block)
-      : cond_(move(cond)), block_(move(block)) {}
-  // create an onvalid () {} else {} expression
-  OnValidStmtNode(IdentExprNode::Ptr cond, StmtNode::Ptr block, StmtNode::Ptr else_block)
-      : cond_(move(cond)), block_(move(block)),
-      else_block_(move(else_block)) {}
-};
-
-class SwitchStmtNode : public StmtNode {
- public:
-  DECLARE(SwitchStmtNode)
-  ExprNode::Ptr cond_;
-  BlockStmtNode::Ptr block_;
-  SwitchStmtNode(ExprNode::Ptr cond, BlockStmtNode::Ptr block)
-      : cond_(move(cond)), block_(move(block)) {}
-};
-
-class CaseStmtNode : public StmtNode {
- public:
-  DECLARE(CaseStmtNode)
-  IntegerExprNode::Ptr value_;
-  BlockStmtNode::Ptr block_;
-  CaseStmtNode(IntegerExprNode::Ptr value, BlockStmtNode::Ptr block)
-      : value_(move(value)), block_(move(block)) {}
-  explicit CaseStmtNode(BlockStmtNode::Ptr block) : block_(move(block)) {}
-};
-
-class VariableDeclStmtNode : public StmtNode {
- public:
-  typedef unique_ptr<VariableDeclStmtNode> Ptr;
-  virtual StatusTuple accept(Visitor* v) = 0;
-  enum storage_type { INTEGER, STRUCT, STRUCT_REFERENCE };
-
-  IdentExprNode::Ptr id_;
-  ExprNodeList init_;
-  enum storage_type storage_type_;
-  size_t bit_width_;
-  size_t bit_offset_;
-  int slot_;
-  string scope_id_;
-  explicit VariableDeclStmtNode(IdentExprNode::Ptr id, storage_type t, size_t bit_width = 0, size_t bit_offset = 0)
-      : id_(move(id)), storage_type_(t), bit_width_(bit_width), bit_offset_(bit_offset), slot_(0) {}
-  const char* scope_id() const { return scope_id_.c_str(); }
-  bool is_struct() { return (storage_type_ == STRUCT || storage_type_ == STRUCT_REFERENCE); }
-  bool is_pointer() { return (storage_type_ == STRUCT_REFERENCE); }
-};
-
-typedef vector<VariableDeclStmtNode::Ptr> FormalList;
-
-class StructVariableDeclStmtNode : public VariableDeclStmtNode {
- public:
-  DECLARE(StructVariableDeclStmtNode)
-
-  IdentExprNode::Ptr struct_id_;
-  StructVariableDeclStmtNode(IdentExprNode::Ptr struct_id, IdentExprNode::Ptr id,
-                             VariableDeclStmtNode::storage_type t = VariableDeclStmtNode::STRUCT)
-      : VariableDeclStmtNode(move(id), t), struct_id_(move(struct_id)) {}
-};
-
-class IntegerVariableDeclStmtNode : public VariableDeclStmtNode {
- public:
-  DECLARE(IntegerVariableDeclStmtNode)
-
-  IntegerVariableDeclStmtNode(IdentExprNode::Ptr id, const string& bits)
-      : VariableDeclStmtNode(move(id), VariableDeclStmtNode::INTEGER, strtoul(bits.c_str(), NULL, 0)) {}
-};
-
-class StructDeclStmtNode : public StmtNode {
- public:
-  DECLARE(StructDeclStmtNode)
-
-  IdentExprNode::Ptr id_;
-  FormalList stmts_;
-  size_t bit_width_;
-  bool packed_;
-  StructDeclStmtNode(IdentExprNode::Ptr id, FormalList&& stmts = FormalList())
-      : id_(move(id)), stmts_(move(stmts)), bit_width_(0), packed_(false) {}
-  VariableDeclStmtNode* field(const string& name) const;
-  int indexof(const string& name) const;
-  bool is_packed() const { return packed_; }
-};
-
-class ParserStateStmtNode : public StmtNode {
- public:
-  DECLARE(ParserStateStmtNode)
-
-  IdentExprNode::Ptr id_;
-  StmtNode* next_state_;
-  string scope_id_;
-  explicit ParserStateStmtNode(IdentExprNode::Ptr id)
-      : id_(move(id)) {}
-  static Ptr make(const IdentExprNode::Ptr& id) {
-    return Ptr(new ParserStateStmtNode(id->copy()));
-  }
-  string scoped_name() const { return scope_id_ + id_->name_; }
-};
-
-class StateDeclStmtNode : public StmtNode {
- public:
-  DECLARE(StateDeclStmtNode)
-
-  struct Sub {
-    IdentExprNode::Ptr id_;
-    BlockStmtNode::Ptr block_;
-    ParserStateStmtNode::Ptr parser_;
-    Scopes::StateScope* scope_;
-    Sub(decltype(id_) id, decltype(block_) block, decltype(parser_) parser, decltype(scope_) scope)
-        : id_(move(id)), block_(move(block)), parser_(move(parser)), scope_(scope) {}
-    ~Sub() { delete scope_; }
-    Sub(Sub&& other) : scope_(NULL) {
-      *this = move(other);
-    }
-    Sub& operator=(Sub&& other) {
-      if (this == &other) {
-        return *this;
-      }
-      id_ = move(other.id_);
-      block_ = move(other.block_);
-      parser_ = move(other.parser_);
-      std::swap(scope_, other.scope_);
-      return *this;
-    }
-  };
-
-  IdentExprNode::Ptr id_;
-  StmtNodeList init_;
-  string scope_id_;
-  ParserStateStmtNode::Ptr parser_;
-  vector<Sub> subs_;
-  StateDeclStmtNode() {}
-  StateDeclStmtNode(IdentExprNode::Ptr id, BlockStmtNode::Ptr block) : id_(move(id)) {
-    subs_.push_back(Sub(make_unique<IdentExprNode>(""), move(block), ParserStateStmtNode::Ptr(), NULL));
-  }
-  StateDeclStmtNode(IdentExprNode::Ptr id1, IdentExprNode::Ptr id2, BlockStmtNode::Ptr block)
-      : id_(move(id1)) {
-    subs_.push_back(Sub(move(id2), move(block), ParserStateStmtNode::Ptr(), NULL));
-  }
-  string scoped_name() const { return scope_id_ + id_->name_; }
-  vector<Sub>::iterator find_sub(const string& id) {
-    return find_if(subs_.begin(), subs_.end(), [&id] (const Sub& sub) {
-      if (sub.id_->name_ == id)
-        return true;
-      return false;
-    });
-
-  }
-};
-
-class MatchDeclStmtNode : public StmtNode {
- public:
-  DECLARE(MatchDeclStmtNode)
-
-  IdentExprNode::Ptr id_;
-  FormalList formals_;
-  BlockStmtNode::Ptr block_;
-  MatchDeclStmtNode(IdentExprNode::Ptr id, FormalList&& formals, BlockStmtNode::Ptr block)
-      : id_(move(id)), formals_(move(formals)), block_(move(block)) {}
-};
-
-class MissDeclStmtNode : public StmtNode {
- public:
-  DECLARE(MissDeclStmtNode)
-
-  IdentExprNode::Ptr id_;
-  FormalList formals_;
-  BlockStmtNode::Ptr block_;
-  MissDeclStmtNode(IdentExprNode::Ptr id, FormalList&& formals, BlockStmtNode::Ptr block)
-      : id_(move(id)), formals_(move(formals)), block_(move(block)) {}
-};
-
-class FailureDeclStmtNode : public StmtNode {
- public:
-  DECLARE(FailureDeclStmtNode)
-
-  IdentExprNode::Ptr id_;
-  FormalList formals_;
-  BlockStmtNode::Ptr block_;
-  FailureDeclStmtNode(IdentExprNode::Ptr id, FormalList&& formals, BlockStmtNode::Ptr block)
-      : id_(move(id)), formals_(move(formals)), block_(move(block)) {}
-};
-
-class TableDeclStmtNode : public StmtNode {
- public:
-  DECLARE(TableDeclStmtNode)
-
-  IdentExprNode::Ptr table_type_;
-  IdentExprNodeList templates_;
-  IdentExprNode::Ptr id_;
-  StructDeclStmtNode *key_type_;
-  StructDeclStmtNode *leaf_type_;
-  IdentExprNode * key_id() { return templates_.at(0).get(); }
-  IdentExprNode * leaf_id() { return templates_.at(1).get(); }
-  IdentExprNode * type_id() { return templates_.at(2).get(); }
-  IdentExprNode * policy_id() { return templates_.at(3).get(); }
-  size_t size_;
-  TableDeclStmtNode(IdentExprNode::Ptr table_type, IdentExprNodeList&& templates,
-                    IdentExprNode::Ptr id, string* size)
-      : table_type_(move(table_type)), templates_(move(templates)), id_(move(id)),
-      key_type_(nullptr), leaf_type_(nullptr), size_(strtoul(size->c_str(), NULL, 0)) {
-    delete size;
-  }
-};
-
-class FuncDeclStmtNode : public StmtNode {
- public:
-  DECLARE(FuncDeclStmtNode)
-
-  IdentExprNode::Ptr id_;
-  FormalList formals_;
-  BlockStmtNode::Ptr block_;
-  Scopes::StateScope* scope_;
-  FuncDeclStmtNode(IdentExprNode::Ptr id, FormalList&& formals, BlockStmtNode::Ptr block)
-      : id_(move(id)), formals_(move(formals)), block_(move(block)), scope_(NULL) {}
-};
-
-class Visitor {
- public:
-  typedef StatusTuple Ret;
-  virtual ~Visitor() {}
-#define VISIT(type, func) virtual STATUS_RETURN visit_##func(type* n) = 0;
-  EXPAND_NODES(VISIT)
-#undef VISIT
-};
-
-#undef DECLARE
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/parser.cc b/src/cc/frontends/b/parser.cc
deleted file mode 100644 (file)
index 8a5e149..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <algorithm>
-#include "bcc_exception.h"
-#include "parser.h"
-#include "type_helper.h"
-
-namespace ebpf {
-namespace cc {
-
-using std::find;
-using std::move;
-using std::string;
-using std::unique_ptr;
-
-bool Parser::variable_exists(VariableDeclStmtNode *decl) const {
-  if (scopes_->current_var()->lookup(decl->id_->name_, SCOPE_LOCAL) == NULL) {
-    return false;
-  }
-  return true;
-}
-
-VariableDeclStmtNode *Parser::variable_add(vector<int> *types, VariableDeclStmtNode *decl) {
-
-  if (variable_exists(decl)) {
-    fprintf(stderr, "redeclaration of variable %s", decl->id_->name_.c_str());
-    return nullptr;
-  }
-  decl->scope_id_ = string("v") + std::to_string(scopes_->current_var()->id_) + string("_");
-  scopes_->current_var()->add(decl->id_->name_, decl);
-  return decl;
-}
-
-VariableDeclStmtNode *Parser::variable_add(vector<int> *types, VariableDeclStmtNode *decl, ExprNode *init_expr) {
-  AssignExprNode::Ptr assign(new AssignExprNode(decl->id_->copy(), ExprNode::Ptr(init_expr)));
-  decl->init_.push_back(move(assign));
-
-  if (variable_exists(decl)) {
-    fprintf(stderr, "redeclaration of variable %s", decl->id_->name_.c_str());
-    return nullptr;
-  }
-  decl->scope_id_ = string("v") + std::to_string(scopes_->current_var()->id_) + string("_");
-  scopes_->current_var()->add(decl->id_->name_, decl);
-  return decl;
-}
-
-StructVariableDeclStmtNode *Parser::variable_add(StructVariableDeclStmtNode *decl, ExprNodeList *args, bool is_kv) {
-  if (is_kv) {
-    // annotate the init expressions with the declared id
-    for (auto arg = args->begin(); arg != args->end(); ++arg) {
-      // decorate with the name of this decl
-      auto n = static_cast<AssignExprNode *>(arg->get());
-      auto id = static_cast<IdentExprNode *>(n->lhs_.get());
-      id->prepend_dot(decl->id_->name_);
-    }
-  } else {
-    fprintf(stderr, "must use key = value syntax\n");
-    return NULL;
-  }
-
-  decl->init_ = move(*args);
-  delete args;
-
-  if (variable_exists(decl)) {
-    fprintf(stderr, "ccpg: warning: redeclaration of variable '%s'\n", decl->id_->name_.c_str());
-    return nullptr;
-  }
-  decl->scope_id_ = string("v") + std::to_string(scopes_->current_var()->id_) + string("_");
-  scopes_->current_var()->add(decl->id_->name_, decl);
-  return decl;
-}
-
-StmtNode *Parser::state_add(Scopes::StateScope *scope, IdentExprNode *id, BlockStmtNode *body) {
-  if (scopes_->current_state()->lookup(id->full_name(), SCOPE_LOCAL)) {
-    fprintf(stderr, "redeclaration of state %s\n", id->full_name().c_str());
-    // redeclaration
-    return NULL;
-  }
-  auto state = new StateDeclStmtNode(IdentExprNode::Ptr(id), BlockStmtNode::Ptr(body));
-    // add a reference to the lower scope
-  state->subs_[0].scope_ = scope;
-
-  // add me to the upper scope
-  scopes_->current_state()->add(state->id_->full_name(), state);
-  state->scope_id_ = string("s") + std::to_string(scopes_->current_state()->id_) + string("_");
-
-  return state;
-}
-
-StmtNode *Parser::state_add(Scopes::StateScope *scope, IdentExprNode *id1, IdentExprNode *id2, BlockStmtNode *body) {
-  auto state = scopes_->current_state()->lookup(id1->full_name(), SCOPE_LOCAL);
-  if (!state) {
-    state = new StateDeclStmtNode(IdentExprNode::Ptr(id1), IdentExprNode::Ptr(id2), BlockStmtNode::Ptr(body));
-    // add a reference to the lower scope
-    state->subs_[0].scope_ = scope;
-
-    // add me to the upper scope
-    scopes_->current_state()->add(state->id_->full_name(), state);
-    state->scope_id_ = string("s") + std::to_string(scopes_->current_state()->id_) + string("_");
-    return state;
-  } else {
-    if (state->find_sub(id2->name_) != state->subs_.end()) {
-      fprintf(stderr, "redeclaration of state %s, %s\n", id1->full_name().c_str(), id2->full_name().c_str());
-      return NULL;
-    }
-    state->subs_.push_back(StateDeclStmtNode::Sub(IdentExprNode::Ptr(id2), BlockStmtNode::Ptr(body),
-                                                  ParserStateStmtNode::Ptr(), scope));
-    delete id1;
-
-    return new StateDeclStmtNode(); // stub
-  }
-}
-
-bool Parser::table_exists(TableDeclStmtNode *decl, bool search_local) {
-  if (scopes_->top_table()->lookup(decl->id_->name_, search_local) == NULL) {
-    return false;
-  }
-  return true;
-}
-
-StmtNode *Parser::table_add(IdentExprNode *type, IdentExprNodeList *templates,
-                            IdentExprNode *id, string *size) {
-  auto table = new TableDeclStmtNode(IdentExprNode::Ptr(type),
-                                     move(*templates),
-                                     IdentExprNode::Ptr(id), size);
-  if (table_exists(table, true)) {
-    fprintf(stderr, "redeclaration of table %s\n", id->name_.c_str());
-    return table;
-  }
-  scopes_->top_table()->add(id->name_, table);
-  return table;
-}
-
-StmtNode * Parser::struct_add(IdentExprNode *type, FormalList *formals) {
-  auto struct_decl = new StructDeclStmtNode(IdentExprNode::Ptr(type), move(*formals));
-  if (scopes_->top_struct()->lookup(type->name_, SCOPE_LOCAL) != NULL) {
-    fprintf(stderr, "redeclaration of struct %s\n", type->name_.c_str());
-    return struct_decl;
-  }
-
-  auto pr_it = pragmas_.find("packed");
-  if (pr_it != pragmas_.end() && pr_it->second == "true")
-    struct_decl->packed_ = true;
-
-  int i = 0;
-  size_t offset = 0;
-  for (auto it = struct_decl->stmts_.begin(); it != struct_decl->stmts_.end(); ++it, ++i) {
-    FieldType ft = bits_to_enum((*it)->bit_width_);
-    offset = struct_decl->is_packed() ? offset : align_offset(offset, ft);
-    (*it)->slot_ = i;
-    (*it)->bit_offset_ = offset;
-    offset += (*it)->bit_width_;
-  }
-  struct_decl->bit_width_ = struct_decl->is_packed() ? offset : align_offset(offset, UINT32_T);
-
-  scopes_->top_struct()->add(type->name_, struct_decl);
-  return struct_decl;
-}
-
-StmtNode * Parser::result_add(int token, IdentExprNode *id, FormalList *formals, BlockStmtNode *body) {
-  StmtNode *stmt = NULL;
-  switch (token) {
-    case Tok::TMATCH:
-      stmt = new MatchDeclStmtNode(IdentExprNode::Ptr(id), move(*formals), BlockStmtNode::Ptr(body));
-      break;
-    case Tok::TMISS:
-      stmt = new MissDeclStmtNode(IdentExprNode::Ptr(id), move(*formals), BlockStmtNode::Ptr(body));
-      break;
-    case Tok::TFAILURE:
-      stmt = new FailureDeclStmtNode(IdentExprNode::Ptr(id), move(*formals), BlockStmtNode::Ptr(body));
-      break;
-    default:
-      {}
-  }
-  return stmt;
-}
-
-StmtNode * Parser::func_add(vector<int> *types, Scopes::StateScope *scope,
-                            IdentExprNode *id, FormalList *formals, BlockStmtNode *body) {
-  auto decl = new FuncDeclStmtNode(IdentExprNode::Ptr(id), move(*formals), BlockStmtNode::Ptr(body));
-  if (scopes_->top_func()->lookup(decl->id_->name_, SCOPE_LOCAL)) {
-    fprintf(stderr, "redeclaration of func %s\n", id->name_.c_str());
-    return decl;
-  }
-  auto cur_scope = scopes_->current_var();
-  scopes_->set_current(scope);
-  for (auto it = formals->begin(); it != formals->end(); ++it)
-    if (!variable_add(nullptr, it->get())) {
-      delete decl;
-      return nullptr;
-    }
-  scopes_->set_current(cur_scope);
-  decl->scope_ = scope;
-  scopes_->top_func()->add(id->name_, decl);
-  return decl;
-}
-
-void Parser::set_loc(Node *n, const BisonParser::location_type &loc) const {
-  n->line_ = loc.begin.line;
-  n->column_ = loc.begin.column;
-  n->text_ = lexer.text(loc);
-}
-
-string Parser::pragma(const string &name) const {
-  auto it = pragmas_.find(name);
-  if (it == pragmas_.end()) return "main";
-  return it->second;
-}
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/parser.h b/src/cc/frontends/b/parser.h
deleted file mode 100644 (file)
index 21338b5..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <fstream> // NOLINT
-#include "node.h"
-#include "lexer.h"
-#include "scope.h"
-
-namespace ebpf {
-namespace cc {
-
-using std::pair;
-using std::string;
-using std::vector;
-
-class Parser {
- public:
-  explicit Parser(const string& infile)
-      : root_node_(NULL), scopes_(new Scopes), in_(infile), lexer(&in_), parser(lexer, *this) {
-    // parser.set_debug_level(1);
-  }
-  ~Parser() { delete root_node_; }
-  int parse() {
-    return parser.parse();
-  }
-
-  VariableDeclStmtNode * variable_add(vector<int> *types, VariableDeclStmtNode *decl);
-  VariableDeclStmtNode * variable_add(vector<int> *types, VariableDeclStmtNode *decl, ExprNode *init_expr);
-  StructVariableDeclStmtNode * variable_add(StructVariableDeclStmtNode *decl, ExprNodeList *args, bool is_kv);
-  StmtNode * state_add(Scopes::StateScope *scope, IdentExprNode *id1, BlockStmtNode *body);
-  StmtNode * state_add(Scopes::StateScope *scope, IdentExprNode *id1, IdentExprNode *id2, BlockStmtNode *body);
-  StmtNode * func_add(std::vector<int> *types, Scopes::StateScope *scope,
-                      IdentExprNode *id, FormalList *formals, BlockStmtNode *body);
-  StmtNode * table_add(IdentExprNode *type, IdentExprNodeList *templates, IdentExprNode *id, string *size);
-  StmtNode * struct_add(IdentExprNode *type, FormalList *formals);
-  StmtNode * result_add(int token, IdentExprNode *id, FormalList *formals, BlockStmtNode *body);
-  bool variable_exists(VariableDeclStmtNode *decl) const;
-  bool table_exists(TableDeclStmtNode *decl, bool search_local = true);
-  void add_pragma(const std::string& pr, const std::string& v) { pragmas_[pr] = v; }
-  void set_loc(Node *n, const BisonParser::location_type &loc) const;
-  std::string pragma(const std::string &name) const;
-
-  Node *root_node_;
-  Scopes::Ptr scopes_;
-  std::map<std::string, std::string> pragmas_;
- private:
-  std::ifstream in_;
-  Lexer lexer;
-  BisonParser parser;
-};
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/parser.yy b/src/cc/frontends/b/parser.yy
deleted file mode 100644 (file)
index e6d1592..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-%skeleton "lalr1.cc"
-%defines
-%define namespace "ebpf::cc"
-%define parser_class_name "BisonParser"
-%parse-param { ebpf::cc::Lexer &lexer }
-%parse-param { ebpf::cc::Parser &parser }
-%lex-param { ebpf::cc::Lexer &lexer }
-%locations
-
-%code requires {
-    #include <memory>
-    #include <vector>
-    #include <string>
-    #include "node.h"
-    // forward declaration
-    namespace ebpf { namespace cc {
-        class Lexer;
-        class Parser;
-    } }
-}
-
-%code {
-    static int yylex(ebpf::cc::BisonParser::semantic_type *yylval,
-                     ebpf::cc::BisonParser::location_type *yylloc,
-                     ebpf::cc::Lexer &lexer);
-}
-
-%{
-    #include "node.h"
-    #include "parser.h"
-    using std::unique_ptr;
-    using std::vector;
-    using std::string;
-    using std::move;
-%}
-
-%union {
-    Scopes::StateScope *state_scope;
-    Scopes::VarScope *var_scope;
-    BlockStmtNode *block;
-    ExprNode *expr;
-    MethodCallExprNode *call;
-    StmtNode *stmt;
-    IdentExprNode *ident;
-    IntegerExprNode *numeric;
-    BitopExprNode *bitop;
-    ExprNodeList *args;
-    IdentExprNodeList *ident_args;
-    StmtNodeList *stmts;
-    FormalList *formals;
-    VariableDeclStmtNode *decl;
-    StructVariableDeclStmtNode *type_decl;
-    TableIndexExprNode *table_index;
-    std::vector<int> *type_specifiers;
-    std::string* string;
-    int token;
-}
-
-/* Define the terminal symbols. */
-%token <string> TIDENTIFIER TINTEGER THEXINTEGER TPRAGMA TSTRING
-%token <token> TU8 TU16 TU32 TU64
-%token <token> TEQUAL TCEQ TCNE TCLT TCLE TCGT TCGE TAND TOR
-%token <token> TLPAREN TRPAREN TLBRACE TRBRACE TLBRACK TRBRACK
-%token <token> TDOT TARROW TCOMMA TPLUS TMINUS TMUL TDIV TMOD TXOR TDOLLAR TCOLON TSCOPE TNOT TSEMI TCMPL TLAND TLOR
-%token <token> TSTRUCT TSTATE TFUNC TGOTO TCONTINUE TNEXT TTRUE TFALSE TRETURN
-%token <token> TIF TELSE TSWITCH TCASE
-%token <token> TMATCH TMISS TFAILURE TVALID
-%token <token> TAT
-
-/* Define non-terminal symbols as defined in the above union */
-%type <ident> ident scoped_ident dotted_ident any_ident
-%type <expr> expr assign_expr return_expr init_arg_kv
-%type <numeric> numeric
-%type <bitop> bitop
-%type <args> call_args /*init_args*/ init_args_kv
-%type <ident_args> table_decl_args
-%type <formals> struct_decl_stmts formals
-%type <block> program block prog_decls
-%type <decl> decl_stmt int_decl ref_stmt
-%type <type_decl> type_decl ptr_decl
-%type <stmt> stmt prog_decl var_decl struct_decl state_decl func_decl
-%type <stmt> table_decl table_result_stmt if_stmt switch_stmt case_stmt onvalid_stmt
-%type <var_scope> enter_varscope exit_varscope
-%type <state_scope> enter_statescope exit_statescope
-%type <stmts> stmts table_result_stmts case_stmts
-%type <call> call_expr
-%type <table_index> table_index_expr
-%type <type_specifiers> type_specifiers
-%type <stmt> pragma_decl
-%type <token> type_specifier
-
-/* taken from C++ operator precedence wiki page */
-%nonassoc TSCOPE
-%left TDOT TLBRACK TLBRACE TLPAREN TINCR TDECR
-%right TNOT TCMPL
-%left TMUL
-%left TDIV
-%left TMOD
-%left TPLUS
-%left TMINUS
-%left TCLT TCLE TCGT TCGE
-%left TCEQ
-%left TCNE
-%left TXOR
-%left TAND
-%left TOR
-%left TLAND
-%left TLOR
-%right TEQUAL
-
-%start program
-
-%%
-
-program
-  : enter_statescope enter_varscope prog_decls exit_varscope exit_statescope
-    { parser.root_node_ = $3; $3->scope_ = $2; }
-  ;
-
-/* program is a list of declarations */
-prog_decls
-  : prog_decl
-    { $$ = new BlockStmtNode; $$->stmts_.push_back(StmtNode::Ptr($1)); }
-  | prog_decls prog_decl
-    { $1->stmts_.push_back(StmtNode::Ptr($2)); }
-  ;
-
-/*
- possible program declarations are:
-  "struct {}"
-  "state|on_miss|on_match|on_valid {}"
-  "var <var_decl>"
-  "Table <...> <ident>(size)"
- */
-prog_decl
-  : var_decl TSEMI
-  | struct_decl TSEMI
-  | state_decl
-  | table_decl TSEMI
-  | pragma_decl
-  | func_decl
-  ;
-
-pragma_decl
-  : TPRAGMA TIDENTIFIER TIDENTIFIER
-    { $$ = new BlockStmtNode; parser.add_pragma(*$2, *$3); delete $2; delete $3; }
-  | TPRAGMA TIDENTIFIER TSTRING
-    { $$ = new BlockStmtNode; parser.add_pragma(*$2, *$3); delete $2; delete $3; }
-  ;
-
-stmts
-  : stmt
-    { $$ = new StmtNodeList; $$->push_back(StmtNode::Ptr($1)); }
-  | stmts stmt
-    { $1->push_back(StmtNode::Ptr($2)); }
-  ;
-
-stmt
-  : expr TSEMI
-    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
-      parser.set_loc($$, @$); }
-  | assign_expr TSEMI
-    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
-      parser.set_loc($$, @$); }
-  | return_expr TSEMI
-    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
-      parser.set_loc($$, @$); }
-  | call_expr TLBRACE enter_varscope table_result_stmts exit_varscope TRBRACE TSEMI
-    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
-      $1->block_->stmts_ = move(*$4); delete $4;
-      $1->block_->scope_ = $3;
-      parser.set_loc($$, @$); }
-  | call_expr TLBRACE TRBRACE TSEMI  // support empty curly braces
-    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
-      parser.set_loc($$, @$); }
-  | if_stmt
-  | switch_stmt
-  | var_decl TSEMI
-    { $$ = $1; }
-  | state_decl
-  | onvalid_stmt
-  ;
-
-call_expr
-  : any_ident TLPAREN call_args TRPAREN
-    { $$ = new MethodCallExprNode(IdentExprNode::Ptr($1), move(*$3), lexer.lineno()); delete $3;
-      parser.set_loc($$, @$); }
-  ;
-
-block
-  : TLBRACE stmts TRBRACE
-    { $$ = new BlockStmtNode; $$->stmts_ = move(*$2); delete $2;
-      parser.set_loc($$, @$); }
-  | TLBRACE TRBRACE
-    { $$ = new BlockStmtNode;
-      parser.set_loc($$, @$); }
-  ;
-
-enter_varscope : /* empty */ { $$ = parser.scopes_->enter_var_scope(); } ;
-exit_varscope : /* empty */ { $$ = parser.scopes_->exit_var_scope(); } ;
-enter_statescope : /* empty */ { $$ = parser.scopes_->enter_state_scope(); } ;
-exit_statescope : /* empty */ { $$ = parser.scopes_->exit_state_scope(); } ;
-
-struct_decl
-  : TSTRUCT ident TLBRACE struct_decl_stmts TRBRACE
-    { $$ = parser.struct_add($2, $4); delete $4;
-      parser.set_loc($$, @$); }
-  ;
-
-struct_decl_stmts
-  : type_specifiers decl_stmt TSEMI
-    { $$ = new FormalList; $$->push_back(VariableDeclStmtNode::Ptr($2)); }
-  | struct_decl_stmts type_specifiers decl_stmt TSEMI
-    { $1->push_back(VariableDeclStmtNode::Ptr($3)); }
-  ;
-
-table_decl
-  : ident TCLT table_decl_args TCGT ident TLPAREN TINTEGER TRPAREN
-    { $$ = parser.table_add($1, $3, $5, $7); delete $3;
-      parser.set_loc($$, @$); }
-  ;
-
-table_decl_args
-  : ident
-    { $$ = new IdentExprNodeList; $$->push_back(IdentExprNode::Ptr($1)); }
-  | table_decl_args TCOMMA ident
-    { $$->push_back(IdentExprNode::Ptr($3)); }
-  ;
-
-state_decl
-  : TSTATE scoped_ident enter_statescope enter_varscope block exit_varscope exit_statescope
-    { $$ = parser.state_add($3, $2, $5); $5->scope_ = $4;
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  | TSTATE scoped_ident TCOMMA TMUL enter_statescope enter_varscope block exit_varscope exit_statescope
-    { $$ = parser.state_add($5, $2, new IdentExprNode(""), $7); $7->scope_ = $6;
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  | TSTATE scoped_ident TCOMMA scoped_ident enter_statescope enter_varscope block exit_varscope exit_statescope
-    { $$ = parser.state_add($5, $2, $4, $7); $7->scope_ = $6;
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  ;
-
-func_decl
-  : type_specifiers ident enter_statescope enter_varscope TLPAREN formals TRPAREN block exit_varscope exit_statescope
-    { $$ = parser.func_add($1, $3, $2, $6, $8); $8->scope_ = $4;
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  ;
-
-table_result_stmts
-  : table_result_stmt
-    { $$ = new StmtNodeList; $$->push_back(StmtNode::Ptr($1)); }
-  | table_result_stmts table_result_stmt
-    { $$->push_back(StmtNode::Ptr($2)); }
-  ;
-
-table_result_stmt
-  : TMATCH ident enter_varscope TLPAREN formals TRPAREN block exit_varscope TSEMI
-    { $$ = parser.result_add($1, $2, $5, $7); delete $5; $7->scope_ = $3;
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  | TMISS ident enter_varscope TLPAREN TRPAREN block exit_varscope TSEMI
-    { $$ = parser.result_add($1, $2, new FormalList, $6); $6->scope_ = $3;
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  | TFAILURE ident enter_varscope TLPAREN formals TRPAREN block exit_varscope TSEMI
-    { $$ = parser.result_add($1, $2, $5, $7); delete $5; $7->scope_ = $3;
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  ;
-
-formals
-  : TSTRUCT ptr_decl
-    { $$ = new FormalList; $$->push_back(VariableDeclStmtNode::Ptr(parser.variable_add(nullptr, $2))); }
-  | formals TCOMMA TSTRUCT ptr_decl
-    { $1->push_back(VariableDeclStmtNode::Ptr(parser.variable_add(nullptr, $4))); }
-  ;
-
-type_specifier
-  : TU8
-  | TU16
-  | TU32
-  | TU64
-  ;
-
-type_specifiers
-  : type_specifier { $$ = new std::vector<int>; $$->push_back($1); }
-  | type_specifiers type_specifier { $$->push_back($2); }
-  ;
-
-var_decl
-  : type_specifiers decl_stmt
-    { $$ = parser.variable_add($1, $2);
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  | type_specifiers int_decl TEQUAL expr
-    { $$ = parser.variable_add($1, $2, $4);
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  | TSTRUCT type_decl TEQUAL TLBRACE init_args_kv TRBRACE
-    { $$ = parser.variable_add($2, $5, true);
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  /*| TSTRUCT type_decl TEQUAL TLBRACE init_args TRBRACE
-    { $$ = parser.variable_add($2, $5, false);
-      parser.set_loc($$, @$); }*/
-  | TSTRUCT ref_stmt
-    { $$ = parser.variable_add(nullptr, $2);
-      if (!$$) YYERROR;
-      parser.set_loc($$, @$); }
-  ;
-
-/* "id":"bitsize" or "type" "id" */
-decl_stmt : int_decl { $$ = $1; } | type_decl { $$ = $1; };
-int_decl : ident TCOLON TINTEGER
-    { $$ = new IntegerVariableDeclStmtNode(IdentExprNode::Ptr($1), *$3); delete $3;
-      parser.set_loc($$, @$); }
-  ;
-
-type_decl : scoped_ident ident
-    { $$ = new StructVariableDeclStmtNode(IdentExprNode::Ptr($1), IdentExprNode::Ptr($2));
-      parser.set_loc($$, @$); }
-  ;
-
-/* "type" "*" "id" */
-ref_stmt : ptr_decl { $$ = $1; };
-ptr_decl : scoped_ident TMUL ident
-    { $$ = new StructVariableDeclStmtNode(IdentExprNode::Ptr($1), IdentExprNode::Ptr($3),
-                                          VariableDeclStmtNode::STRUCT_REFERENCE);
-      parser.set_loc($$, @$); }
-  ;
-
-/* normal initializer */
-/* init_args
-  : expr { $$ = new ExprNodeList; $$->push_back(ExprNode::Ptr($1)); }
-  | init_args TCOMMA expr { $$->push_back(ExprNode::Ptr($3)); }
-  ;*/
-
-/* one or more of "field" = "expr" */
-init_args_kv
-  : init_arg_kv { $$ = new ExprNodeList; $$->push_back(ExprNode::Ptr($1)); }
-  | init_args_kv TCOMMA init_arg_kv { $$->push_back(ExprNode::Ptr($3)); }
-  ;
-init_arg_kv
-  : TDOT ident TEQUAL expr
-    { $$ = new AssignExprNode(IdentExprNode::Ptr($2), ExprNode::Ptr($4));
-      parser.set_loc($$, @$); }
-  | TDOT ident bitop TEQUAL expr
-    { $$ = new AssignExprNode(IdentExprNode::Ptr($2), ExprNode::Ptr($5)); $$->bitop_ = BitopExprNode::Ptr($3);
-      parser.set_loc($$, @$); }
-  ;
-
-if_stmt
-  : TIF expr enter_varscope block exit_varscope
-    { $$ = new IfStmtNode(ExprNode::Ptr($2), StmtNode::Ptr($4));
-      $4->scope_ = $3;
-      parser.set_loc($$, @$); }
-  | TIF expr enter_varscope block exit_varscope TELSE enter_varscope block exit_varscope
-    { $$ = new IfStmtNode(ExprNode::Ptr($2), StmtNode::Ptr($4), StmtNode::Ptr($8));
-      $4->scope_ = $3; $8->scope_ = $7;
-      parser.set_loc($$, @$); }
-  | TIF expr enter_varscope block exit_varscope TELSE if_stmt
-    { $$ = new IfStmtNode(ExprNode::Ptr($2), StmtNode::Ptr($4), StmtNode::Ptr($7));
-      $4->scope_ = $3;
-      parser.set_loc($$, @$); }
-  ;
-
-onvalid_stmt
-  : TVALID TLPAREN ident TRPAREN enter_varscope block exit_varscope
-    { $$ = new OnValidStmtNode(IdentExprNode::Ptr($3), StmtNode::Ptr($6));
-      $6->scope_ = $5;
-      parser.set_loc($$, @$); }
-  | TVALID TLPAREN ident TRPAREN enter_varscope block exit_varscope TELSE enter_varscope block exit_varscope
-    { $$ = new OnValidStmtNode(IdentExprNode::Ptr($3), StmtNode::Ptr($6), StmtNode::Ptr($10));
-      $6->scope_ = $5; $10->scope_ = $9;
-      parser.set_loc($$, @$); }
-  ;
-
-switch_stmt
-  : TSWITCH expr TLBRACE case_stmts TRBRACE
-    { $$ = new SwitchStmtNode(ExprNode::Ptr($2), make_unique<BlockStmtNode>(move(*$4))); delete $4;
-      parser.set_loc($$, @$); }
-  ;
-
-case_stmts
-  : case_stmt
-    { $$ = new StmtNodeList; $$->push_back(StmtNode::Ptr($1)); }
-  | case_stmts case_stmt
-    { $$->push_back(StmtNode::Ptr($2)); }
-  ;
-
-case_stmt
-  : TCASE numeric block TSEMI
-    { $$ = new CaseStmtNode(IntegerExprNode::Ptr($2), BlockStmtNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | TCASE TMUL block TSEMI
-    { $$ = new CaseStmtNode(BlockStmtNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  ;
-
-numeric
-  : TINTEGER
-    { $$ = new IntegerExprNode($1);
-      parser.set_loc($$, @$); }
-  | THEXINTEGER
-    { $$ = new IntegerExprNode($1);
-      parser.set_loc($$, @$); }
-  | TINTEGER TCOLON TINTEGER
-    { $$ = new IntegerExprNode($1, $3);
-      parser.set_loc($$, @$); }
-  | THEXINTEGER TCOLON TINTEGER
-    { $$ = new IntegerExprNode($1, $3);
-      parser.set_loc($$, @$); }
-  | TTRUE
-    { $$ = new IntegerExprNode(new string("1"), new string("1"));
-      parser.set_loc($$, @$); }
-  | TFALSE
-    { $$ = new IntegerExprNode(new string("0"), new string("1"));
-      parser.set_loc($$, @$); }
-  ;
-
-assign_expr
-  : expr TEQUAL expr
-    { $$ = new AssignExprNode(ExprNode::Ptr($1), ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  /* The below has a reduce/reduce conflict.
-     TODO: ensure the above is handled in the type check properly */
-  /*| dotted_ident TEQUAL expr
-    { $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | dotted_ident bitop TEQUAL expr
-    { $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($4)); $$->bitop_ = BitopExprNode::Ptr($2);
-      parser.set_loc($$, @$); }*/
-  ;
-
-return_expr
-  : TRETURN expr
-    { $$ = new ReturnExprNode(ExprNode::Ptr($2));
-      parser.set_loc($$, @$); }
-  ;
-
-expr
-  : call_expr
-    { $$ = $1; }
-  | call_expr bitop
-    { $$ = $1; $$->bitop_ = BitopExprNode::Ptr($2); }
-  | table_index_expr
-    { $$ = $1; }
-  | table_index_expr TDOT ident
-    { $$ = $1; $1->sub_ = IdentExprNode::Ptr($3); }
-  | any_ident
-    { $$ = $1; }
-  | TAT dotted_ident
-    { $$ = new PacketExprNode(IdentExprNode::Ptr($2));
-      $$->flags_[ExprNode::IS_REF] = true;
-      parser.set_loc($$, @$); }
-  | TDOLLAR dotted_ident
-    { $$ = new PacketExprNode(IdentExprNode::Ptr($2));
-      $$->flags_[ExprNode::IS_PKT] = true;
-      parser.set_loc($$, @$); }
-  | TDOLLAR dotted_ident bitop
-    { $$ = new PacketExprNode(IdentExprNode::Ptr($2)); $$->bitop_ = BitopExprNode::Ptr($3);
-      $$->flags_[ExprNode::IS_PKT] = true;
-      parser.set_loc($$, @$); }
-  | TGOTO scoped_ident
-    { $$ = new GotoExprNode(IdentExprNode::Ptr($2), false);
-      parser.set_loc($$, @$); }
-  | TNEXT scoped_ident
-    { $$ = new GotoExprNode(IdentExprNode::Ptr($2), false);
-      parser.set_loc($$, @$); }
-  | TCONTINUE scoped_ident
-    { $$ = new GotoExprNode(IdentExprNode::Ptr($2), true);
-      parser.set_loc($$, @$); }
-  | TLPAREN expr TRPAREN
-    { $$ = $2; }
-  | TLPAREN expr TRPAREN bitop
-    { $$ = $2; $$->bitop_ = BitopExprNode::Ptr($4); }
-  | TSTRING
-    { $$ = new StringExprNode($1);
-      parser.set_loc($$, @$); }
-  | numeric
-    { $$ = $1; }
-  | numeric bitop
-    { $$ = $1; $$->bitop_ = BitopExprNode::Ptr($2); }
-  | expr TCLT expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TCGT expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TCGE expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TCLE expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TCNE expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TCEQ expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TPLUS expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TMINUS expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TMUL expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TDIV expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TMOD expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TXOR expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TAND expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TOR expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TLAND expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  | expr TLOR expr
-    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  /*| expr bitop
-    { $$ = $1; $$->bitop_ = BitopExprNode::Ptr($2); }*/
-  | TNOT expr
-    { $$ = new UnopExprNode($1, ExprNode::Ptr($2));
-      parser.set_loc($$, @$); }
-  | TCMPL expr
-    { $$ = new UnopExprNode($1, ExprNode::Ptr($2));
-      parser.set_loc($$, @$); }
-  ;
-
-call_args
-  : /* empty */
-    { $$ = new ExprNodeList; }
-  | expr
-    { $$ = new ExprNodeList; $$->push_back(ExprNode::Ptr($1)); }
-  | call_args TCOMMA expr
-    { $$->push_back(ExprNode::Ptr($3)); }
-  ;
-
-bitop
-  : TLBRACK TCOLON TPLUS TINTEGER TRBRACK
-    { $$ = new BitopExprNode(string("0"), *$4); delete $4;
-      parser.set_loc($$, @$); }
-  | TLBRACK TINTEGER TCOLON TPLUS TINTEGER TRBRACK
-    { $$ = new BitopExprNode(*$2, *$5); delete $2; delete $5;
-      parser.set_loc($$, @$); }
-  ;
-
-table_index_expr
-  : dotted_ident TLBRACK ident TRBRACK
-    { $$ = new TableIndexExprNode(IdentExprNode::Ptr($1), IdentExprNode::Ptr($3));
-      parser.set_loc($$, @$); }
-  ;
-
-scoped_ident
-  : ident
-    { $$ = $1; }
-  | scoped_ident TSCOPE TIDENTIFIER
-    { $$->append_scope(*$3); delete $3; }
-  ;
-
-dotted_ident
-  : ident
-    { $$ = $1; }
-  | dotted_ident TDOT TIDENTIFIER
-    { $$->append_dot(*$3); delete $3; }
-  ;
-
-any_ident
-  : ident
-    { $$ = $1; }
-  | dotted_ident TARROW TIDENTIFIER
-    { $$->append_dot(*$3); delete $3; }
-  | dotted_ident TDOT TIDENTIFIER
-    { $$->append_dot(*$3); delete $3; }
-  | scoped_ident TSCOPE TIDENTIFIER
-    { $$->append_scope(*$3); delete $3; }
-  ;
-
-ident
-  : TIDENTIFIER
-    { $$ = new IdentExprNode(*$1); delete $1;
-      parser.set_loc($$, @$); }
-  ;
-
-%%
-
-void ebpf::cc::BisonParser::error(const ebpf::cc::BisonParser::location_type &loc,
-                            const string& msg) {
-    std::cerr << "Error: " << loc << " " << msg << std::endl;
-}
-
-#include "lexer.h"
-static int yylex(ebpf::cc::BisonParser::semantic_type *yylval,
-                 ebpf::cc::BisonParser::location_type *yylloc,
-                 ebpf::cc::Lexer &lexer) {
-    return lexer.yylex(yylval, yylloc);
-}
-
diff --git a/src/cc/frontends/b/printer.cc b/src/cc/frontends/b/printer.cc
deleted file mode 100644 (file)
index 75ff907..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "printer.h"
-#include "lexer.h"
-#include "bcc_exception.h"
-
-namespace ebpf {
-namespace cc {
-
-void Printer::print_indent() {
-  fprintf(out_, "%*s", indent_, "");
-}
-
-StatusTuple Printer::visit_block_stmt_node(BlockStmtNode* n) {
-  fprintf(out_, "{\n");
-
-  if (!n->stmts_.empty()) {
-    ++indent_;
-    for (auto it = n->stmts_.begin(); it != n->stmts_.end(); ++it) {
-      print_indent();
-      TRY2((*it)->accept(this));
-      fprintf(out_, "\n");
-    }
-    --indent_;
-  }
-  fprintf(out_, "%*s}", indent_, "");
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_if_stmt_node(IfStmtNode* n) {
-  fprintf(out_, "if ");
-  TRY2(n->cond_->accept(this));
-  fprintf(out_, " ");
-  TRY2(n->true_block_->accept(this));
-  if (n->false_block_) {
-    fprintf(out_, " else ");
-    TRY2(n->false_block_->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_onvalid_stmt_node(OnValidStmtNode* n) {
-  fprintf(out_, "if ");
-  TRY2(n->cond_->accept(this));
-  fprintf(out_, " ");
-  TRY2(n->block_->accept(this));
-  if (n->else_block_) {
-    fprintf(out_, " else ");
-    TRY2(n->else_block_->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_switch_stmt_node(SwitchStmtNode* n) {
-  fprintf(out_, "switch (");
-  TRY2(n->cond_->accept(this));
-  fprintf(out_, ") ");
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_case_stmt_node(CaseStmtNode* n) {
-  if (n->value_) {
-    fprintf(out_, "case ");
-    TRY2(n->value_->accept(this));
-  } else {
-    fprintf(out_, "default");
-  }
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_ident_expr_node(IdentExprNode* n) {
-  if (n->scope_name_.size()) {
-    fprintf(out_, "%s::", n->scope_name_.c_str());
-  }
-  fprintf(out_, "%s", n->name_.c_str());
-  if (n->sub_name_.size()) {
-    fprintf(out_, ".%s", n->sub_name_.c_str());
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_assign_expr_node(AssignExprNode* n) {
-  TRY2(n->lhs_->accept(this));
-  fprintf(out_, " = ");
-  TRY2(n->rhs_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_packet_expr_node(PacketExprNode* n) {
-  fprintf(out_, "$");
-  TRY2(n->id_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_integer_expr_node(IntegerExprNode* n) {
-  fprintf(out_, "%s:%zu", n->val_.c_str(), n->bits_);
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_string_expr_node(StringExprNode *n) {
-  fprintf(out_, "%s", n->val_.c_str());
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_binop_expr_node(BinopExprNode* n) {
-  TRY2(n->lhs_->accept(this));
-  fprintf(out_, "%d", n->op_);
-  TRY2(n->rhs_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_unop_expr_node(UnopExprNode* n) {
-  const char* s = "";
-  switch (n->op_) {
-    case Tok::TNOT: s = "!"; break;
-    case Tok::TCMPL: s = "~"; break;
-    case Tok::TMOD:  s = "%"; break;
-    default: {}
-  }
-  fprintf(out_, "%s", s);
-  TRY2(n->expr_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_bitop_expr_node(BitopExprNode* n) {
-
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_return_expr_node(ReturnExprNode* n) {
-  fprintf(out_, "return ");
-  TRY2(n->expr_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_goto_expr_node(GotoExprNode* n) {
-  const char* s = n->is_continue_ ? "continue " : "goto ";
-  fprintf(out_, "%s", s);
-  TRY2(n->id_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_method_call_expr_node(MethodCallExprNode* n) {
-  TRY2(n->id_->accept(this));
-  fprintf(out_, "(");
-  for (auto it = n->args_.begin(); it != n->args_.end(); ++it) {
-    TRY2((*it)->accept(this));
-    if (it + 1 != n->args_.end()) {
-      fprintf(out_, ", ");
-    }
-  }
-  fprintf(out_, ")");
-  if (!n->block_->stmts_.empty()) {
-    fprintf(out_, " {\n");
-    ++indent_;
-    for (auto it = n->block_->stmts_.begin(); it != n->block_->stmts_.end(); ++it) {
-      print_indent();
-      TRY2((*it)->accept(this));
-      fprintf(out_, "\n");
-    }
-    --indent_;
-    fprintf(out_, "%*s}", indent_, "");
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_table_index_expr_node(TableIndexExprNode *n) {
-  fprintf(out_, "%s[", n->id_->c_str());
-  TRY2(n->index_->accept(this));
-  fprintf(out_, "]");
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_expr_stmt_node(ExprStmtNode* n) {
-  TRY2(n->expr_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_struct_variable_decl_stmt_node(StructVariableDeclStmtNode* n) {
-  fprintf(out_, "var ");
-  TRY2(n->struct_id_->accept(this));
-  fprintf(out_, " ");
-  TRY2(n->id_->accept(this));
-  if (!n->init_.empty()) {
-    fprintf(out_, "{");
-    for (auto it = n->init_.begin(); it != n->init_.end(); ++it) {
-      TRY2((*it)->accept(this));
-      if (it + 1 != n->init_.end()) {
-        fprintf(out_, ", ");
-      }
-    }
-    fprintf(out_, "}");
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_integer_variable_decl_stmt_node(IntegerVariableDeclStmtNode* n) {
-  fprintf(out_, "var ");
-  TRY2(n->id_->accept(this));
-  fprintf(out_, ":%zu", n->bit_width_);
-  if (!n->init_.empty()) {
-    fprintf(out_, "; ");
-    TRY2(n->init_[0]->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_struct_decl_stmt_node(StructDeclStmtNode* n) {
-  fprintf(out_, "struct ");
-  TRY2(n->id_->accept(this));
-  fprintf(out_, " {\n");
-  ++indent_;
-  for (auto it = n->stmts_.begin(); it != n->stmts_.end(); ++it) {
-    print_indent();
-    TRY2((*it)->accept(this));
-    fprintf(out_, "\n");
-  }
-  --indent_;
-  fprintf(out_, "%*s}", indent_, "");
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_state_decl_stmt_node(StateDeclStmtNode* n) {
-  if (!n->id_) {
-    return StatusTuple::OK();
-  }
-  fprintf(out_, "state ");
-  TRY2(n->id_->accept(this));
-  //if (!n->id2_) {
-  //  fprintf(out_, ", * ");
-  //} else {
-  //  fprintf(out_, ", ");
-  //  TRY2(n->id2_->accept(this));
-  //}
-  //TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_parser_state_stmt_node(ParserStateStmtNode* n) {
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_match_decl_stmt_node(MatchDeclStmtNode* n) {
-  fprintf(out_, "on_match ");
-  TRY2(n->id_->accept(this));
-  fprintf(out_, " (");
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    TRY2((*it)->accept(this));
-    if (it + 1 != n->formals_.end()) {
-      fprintf(out_, ", ");
-    }
-  }
-  fprintf(out_, ") ");
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_miss_decl_stmt_node(MissDeclStmtNode* n) {
-  fprintf(out_, "on_miss ");
-  TRY2(n->id_->accept(this));
-  fprintf(out_, " (");
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    TRY2((*it)->accept(this));
-    if (it + 1 != n->formals_.end()) {
-      fprintf(out_, ", ");
-    }
-  }
-  fprintf(out_, ") ");
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_failure_decl_stmt_node(FailureDeclStmtNode* n) {
-  fprintf(out_, "on_failure ");
-  TRY2(n->id_->accept(this));
-  fprintf(out_, " (");
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    TRY2((*it)->accept(this));
-    if (it + 1 != n->formals_.end()) {
-      fprintf(out_, ", ");
-    }
-  }
-  fprintf(out_, ") ");
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_table_decl_stmt_node(TableDeclStmtNode* n) {
-  TRY2(n->table_type_->accept(this));
-  fprintf(out_, "<");
-  for (auto it = n->templates_.begin(); it != n->templates_.end(); ++it) {
-    TRY2((*it)->accept(this));
-    if (it + 1 != n->templates_.end()) {
-      fprintf(out_, ", ");
-    }
-  }
-  fprintf(out_, "> ");
-  TRY2(n->id_->accept(this));
-  fprintf(out_, "(%zu)", n->size_);
-  return StatusTuple::OK();
-}
-
-StatusTuple Printer::visit_func_decl_stmt_node(FuncDeclStmtNode *n) {
-  fprintf(out_, "func ");
-  TRY2(n->id_->accept(this));
-  fprintf(out_, "(");
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    TRY2((*it)->accept(this));
-    if (it + 1 != n->formals_.end()) {
-      fprintf(out_, ", ");
-    }
-  }
-  fprintf(out_, ") ");
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/printer.h b/src/cc/frontends/b/printer.h
deleted file mode 100644 (file)
index 6dd4894..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <stdio.h>
-
-#include "node.h"
-
-namespace ebpf {
-namespace cc {
-
-class Printer : public Visitor {
- public:
-  explicit Printer(FILE* out) : out_(out), indent_(0) {}
-
-  void print_indent();
-
-#define VISIT(type, func) virtual STATUS_RETURN visit_##func(type* n);
-  EXPAND_NODES(VISIT)
-#undef VISIT
-
- private:
-  FILE* out_;
-  int indent_;
-};
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/scope.h b/src/cc/frontends/b/scope.h
deleted file mode 100644 (file)
index b0358b8..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <map>
-#include <string>
-#include <vector>
-#include <memory>
-
-namespace ebpf {
-namespace cc {
-
-using std::string;
-using std::vector;
-using std::map;
-using std::pair;
-using std::unique_ptr;
-
-class StateDeclStmtNode;
-class VariableDeclStmtNode;
-class TableDeclStmtNode;
-class StructDeclStmtNode;
-class FuncDeclStmtNode;
-
-enum search_type { SCOPE_LOCAL, SCOPE_GLOBAL };
-
-template <typename T>
-class Scope {
- public:
-  Scope() {}
-  Scope(Scope<T>* scope, int id) : parent_(scope), id_(id) {}
-
-  T* lookup(const string &name, bool search_local = true) {
-    return lookup(name, search_local ? SCOPE_LOCAL : SCOPE_GLOBAL);
-  }
-  T * lookup(const string &name, search_type stype) {
-    auto it = elems_.find(name);
-    if (it != elems_.end())
-      return it->second;
-
-    if (stype == SCOPE_LOCAL || !parent_)
-      return nullptr;
-    return parent_->lookup(name, stype);
-  }
-  void add(const string& name, T* n) {
-    elems_[name] = n;
-    elems_ordered_.push_back(n);
-  }
-  typename map<string, T*>::iterator begin() { return elems_.begin(); }
-  typename map<string, T*>::iterator end() { return elems_.end(); }
-  typename vector<T*>::iterator obegin() { return elems_ordered_.begin(); }
-  typename vector<T*>::iterator oend() { return elems_ordered_.end(); }
-
-  Scope<T> *parent_;
-  int id_;
-  map<string, T*> elems_;
-  vector<T*> elems_ordered_;
-};
-
-/**
- * Hold the current stack of scope pointers.  Lookups search upwards.
- * Actual scope pointers are kept in the AST.
- */
-class Scopes {
- public:
-  typedef unique_ptr<Scopes> Ptr;
-  typedef Scope<StructDeclStmtNode> StructScope;
-  typedef Scope<StateDeclStmtNode> StateScope;
-  typedef Scope<VariableDeclStmtNode> VarScope;
-  typedef Scope<TableDeclStmtNode> TableScope;
-  typedef Scope<FuncDeclStmtNode> FuncScope;
-
-  Scopes() : var_id__(0), state_id_(0), var_id_(0),
-    current_var_scope_(nullptr), top_var_scope_(nullptr),
-    current_state_scope_(nullptr), top_state_scope_(nullptr),
-    top_struct_scope_(new StructScope(nullptr, 1)),
-    top_table_scope_(new TableScope(nullptr, 1)),
-    top_func_scope_(new FuncScope(nullptr, 1)) {}
-  ~Scopes() {
-    delete top_func_scope_;
-    delete top_struct_scope_;
-    delete top_table_scope_;
-    delete top_state_scope_;
-  }
-
-  void push_var(VarScope *scope) {
-    if (scope == top_var_scope_)
-      return;
-    scope->parent_ = current_var_scope_;
-    current_var_scope_ = scope;
-  }
-  void pop_var() {
-    if (current_var_scope_ == top_var_scope_)
-      return;
-    VarScope *old = current_var_scope_;
-    current_var_scope_ = old->parent_;
-    old->parent_ = nullptr;
-  }
-
-  void push_state(StateScope *scope) {
-    if (scope == top_state_scope_)
-      return;
-    scope->parent_ = current_state_scope_;
-    current_state_scope_ = scope;
-  }
-  void pop_state() {
-    if (current_state_scope_ == top_state_scope_)
-      return;
-    StateScope *old = current_state_scope_;
-    current_state_scope_ = old->parent_;
-    old->parent_ = nullptr;
-  }
-
-  /// While building the AST, allocate a new scope
-  VarScope* enter_var_scope() {
-    current_var_scope_ = new VarScope(current_var_scope_, next_var_id());
-    if (!top_var_scope_) {
-      top_var_scope_ = current_var_scope_;
-    }
-    return current_var_scope_;
-  }
-
-  VarScope* exit_var_scope() {
-    current_var_scope_ = current_var_scope_->parent_;
-    return current_var_scope_;
-  }
-
-  StateScope* enter_state_scope() {
-    current_state_scope_ = new StateScope(current_state_scope_, next_state_id());
-    if (!top_state_scope_) {
-      top_state_scope_ = current_state_scope_;
-    }
-    return current_state_scope_;
-  }
-
-  StateScope* exit_state_scope() {
-    current_state_scope_ = current_state_scope_->parent_;
-    return current_state_scope_;
-  }
-
-  void set_current(VarScope* s) { current_var_scope_ = s; }
-  VarScope* current_var() const { return current_var_scope_; }
-  VarScope* top_var() const { return top_var_scope_; }
-
-  void set_current(StateScope* s) { current_state_scope_ = s; }
-  StateScope* current_state() const { return current_state_scope_; }
-  StateScope* top_state() const { return top_state_scope_; }
-
-  StructScope* top_struct() const { return top_struct_scope_; }
-
-  TableScope* top_table() const { return top_table_scope_; }
-  FuncScope* top_func() const { return top_func_scope_; }
-
-  int next_id() { return ++var_id__; }
-  int next_state_id() { return ++state_id_; }
-  int next_var_id() { return ++var_id_; }
-
-  int var_id__;
-  int state_id_;
-  int var_id_;
-  VarScope* current_var_scope_;
-  VarScope* top_var_scope_;
-  StateScope* current_state_scope_;
-  StateScope* top_state_scope_;
-  StructScope* top_struct_scope_;
-  TableScope* top_table_scope_;
-  FuncScope* top_func_scope_;
-};
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/type_check.cc b/src/cc/frontends/b/type_check.cc
deleted file mode 100644 (file)
index 4300c76..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <set>
-#include <algorithm>
-#include "bcc_exception.h"
-#include "type_check.h"
-#include "lexer.h"
-
-namespace ebpf {
-namespace cc {
-
-using std::for_each;
-using std::set;
-
-StatusTuple TypeCheck::visit_block_stmt_node(BlockStmtNode *n) {
-  // enter scope
-  if (n->scope_)
-    scopes_->push_var(n->scope_);
-  if (!n->stmts_.empty()) {
-    for (auto it = n->stmts_.begin(); it != n->stmts_.end(); ++it)
-      TRY2((*it)->accept(this));
-  }
-
-  if (n->scope_)
-    scopes_->pop_var();
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_if_stmt_node(IfStmtNode *n) {
-  TRY2(n->cond_->accept(this));
-  //if (n->cond_->typeof_ != ExprNode::INTEGER)
-  //  return mkstatus_(n, "If condition must be a numeric type");
-  TRY2(n->true_block_->accept(this));
-  if (n->false_block_) {
-    TRY2(n->false_block_->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_onvalid_stmt_node(OnValidStmtNode *n) {
-  TRY2(n->cond_->accept(this));
-  auto sdecl = static_cast<StructVariableDeclStmtNode*>(n->cond_->decl_);
-  if (sdecl->storage_type_ != StructVariableDeclStmtNode::STRUCT_REFERENCE)
-    return mkstatus_(n, "on_valid condition must be a reference type");
-  TRY2(n->block_->accept(this));
-  if (n->else_block_) {
-    TRY2(n->else_block_->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_switch_stmt_node(SwitchStmtNode *n) {
-  TRY2(n->cond_->accept(this));
-  if (n->cond_->typeof_ != ExprNode::INTEGER)
-    return mkstatus_(n, "Switch condition must be a numeric type");
-  TRY2(n->block_->accept(this));
-  for (auto it = n->block_->stmts_.begin(); it != n->block_->stmts_.end(); ++it) {
-    /// @todo check for duplicates
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_case_stmt_node(CaseStmtNode *n) {
-  if (n->value_) {
-    TRY2(n->value_->accept(this));
-    if (n->value_->typeof_ != ExprNode::INTEGER)
-      return mkstatus_(n, "Switch condition must be a numeric type");
-  }
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_ident_expr_node(IdentExprNode *n) {
-  n->decl_ = scopes_->current_var()->lookup(n->name_, SCOPE_GLOBAL);
-  if (!n->decl_)
-    return mkstatus_(n, "Variable %s lookup failed", n->c_str());
-
-  n->typeof_ = ExprNode::UNKNOWN;
-  if (n->sub_name_.empty()) {
-    if (n->decl_->storage_type_ == VariableDeclStmtNode::INTEGER) {
-      n->typeof_ = ExprNode::INTEGER;
-      n->bit_width_ = n->decl_->bit_width_;
-      n->flags_[ExprNode::WRITE] = true;
-    } else if (n->decl_->is_struct()) {
-      n->typeof_ = ExprNode::STRUCT;
-      auto sdecl = static_cast<StructVariableDeclStmtNode*>(n->decl_);
-      if (sdecl->struct_id_->scope_name_ == "proto") {
-        n->struct_type_ = proto_scopes_->top_struct()->lookup(sdecl->struct_id_->name_, true);
-        n->flags_[ExprNode::PROTO] = true;
-      } else {
-        n->struct_type_ = scopes_->top_struct()->lookup(sdecl->struct_id_->name_, true);
-      }
-      if (!n->struct_type_)
-        return mkstatus_(n, "Type %s has not been declared", sdecl->struct_id_->full_name().c_str());
-      n->bit_width_ = n->struct_type_->bit_width_;
-    }
-  } else {
-    if (n->decl_->storage_type_ == VariableDeclStmtNode::INTEGER)
-      return mkstatus_(n, "Subfield access not valid for numeric types");
-    auto sdecl = static_cast<StructVariableDeclStmtNode*>(n->decl_);
-    if (sdecl->struct_id_->scope_name_ == "proto") {
-      n->struct_type_ = proto_scopes_->top_struct()->lookup(sdecl->struct_id_->name_, true);
-      n->flags_[ExprNode::PROTO] = true;
-    } else {
-      n->struct_type_ = scopes_->top_struct()->lookup(sdecl->struct_id_->name_, true);
-    }
-    if (!n->struct_type_)
-      return mkstatus_(n, "Type %s has not been declared", sdecl->struct_id_->full_name().c_str());
-    n->sub_decl_ = n->struct_type_->field(n->sub_name_);
-
-    if (!n->sub_decl_)
-      return mkstatus_(n, "Access to invalid subfield %s.%s", n->c_str(), n->sub_name_.c_str());
-    if (n->sub_decl_->storage_type_ != VariableDeclStmtNode::INTEGER)
-      return mkstatus_(n, "Accessing non-numeric subfield %s.%s", n->c_str(), n->sub_name_.c_str());
-
-    n->typeof_ = ExprNode::INTEGER;
-    n->bit_width_ = n->sub_decl_->bit_width_;
-    n->flags_[ExprNode::WRITE] = true;
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_assign_expr_node(AssignExprNode *n) {
-  /// @todo check lhs is assignable
-  TRY2(n->lhs_->accept(this));
-  if (n->lhs_->typeof_ == ExprNode::STRUCT) {
-    TRY2(n->rhs_->accept(this));
-    if (n->rhs_->typeof_ != ExprNode::STRUCT)
-      return mkstatus_(n, "Right-hand side of assignment must be a struct");
-  } else {
-    if (n->lhs_->typeof_ != ExprNode::INTEGER)
-      return mkstatus_(n, "Left-hand side of assignment must be a numeric type");
-    if (!n->lhs_->flags_[ExprNode::WRITE])
-      return mkstatus_(n, "Left-hand side of assignment is read-only");
-    TRY2(n->rhs_->accept(this));
-    if (n->rhs_->typeof_ != ExprNode::INTEGER)
-      return mkstatus_(n, "Right-hand side of assignment must be a numeric type");
-  }
-  n->typeof_ = ExprNode::VOID;
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_packet_expr_node(PacketExprNode *n) {
-  StructDeclStmtNode *struct_type = proto_scopes_->top_struct()->lookup(n->id_->name_, true);
-  if (!struct_type)
-    return mkstatus_(n, "Undefined packet header %s", n->id_->c_str());
-  if (n->id_->sub_name_.empty()) {
-    n->typeof_ = ExprNode::STRUCT;
-    n->struct_type_ = struct_type;
-  } else {
-    VariableDeclStmtNode *sub_decl = struct_type->field(n->id_->sub_name_);
-    if (!sub_decl)
-      return mkstatus_(n, "Access to invalid subfield %s.%s", n->id_->c_str(), n->id_->sub_name_.c_str());
-    n->typeof_ = ExprNode::INTEGER;
-    if (n->is_ref())
-      n->bit_width_ = 64;
-    else
-      n->bit_width_ = sub_decl->bit_width_;
-  }
-  n->flags_[ExprNode::WRITE] = true;
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_integer_expr_node(IntegerExprNode *n) {
-  n->typeof_ = ExprNode::INTEGER;
-  n->bit_width_ = n->bits_;
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_string_expr_node(StringExprNode *n) {
-  n->typeof_ = ExprNode::STRING;
-  n->flags_[ExprNode::IS_REF] = true;
-  n->bit_width_ = n->val_.size() << 3;
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_binop_expr_node(BinopExprNode *n) {
-  TRY2(n->lhs_->accept(this));
-  if (n->lhs_->typeof_ != ExprNode::INTEGER)
-    return mkstatus_(n, "Left-hand side of binary expression must be a numeric type");
-  TRY2(n->rhs_->accept(this));
-  if (n->rhs_->typeof_ != ExprNode::INTEGER)
-    return mkstatus_(n, "Right-hand side of binary expression must be a numeric type");
-  n->typeof_ = ExprNode::INTEGER;
-  switch(n->op_) {
-    case Tok::TCEQ:
-    case Tok::TCNE:
-    case Tok::TCLT:
-    case Tok::TCLE:
-    case Tok::TCGT:
-    case Tok::TCGE:
-      n->bit_width_ = 1;
-      break;
-    default:
-      n->bit_width_ = std::max(n->lhs_->bit_width_, n->rhs_->bit_width_);
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_unop_expr_node(UnopExprNode *n) {
-  TRY2(n->expr_->accept(this));
-  if (n->expr_->typeof_ != ExprNode::INTEGER)
-    return mkstatus_(n, "Unary operand must be a numeric type");
-  n->copy_type(*n->expr_);
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_bitop_expr_node(BitopExprNode *n) {
-  if (n->expr_->typeof_ != ExprNode::INTEGER)
-    return mkstatus_(n, "Bitop [] can only operate on numeric types");
-  n->typeof_ = ExprNode::INTEGER;
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_goto_expr_node(GotoExprNode *n) {
-  //n->id_->accept(this);
-  n->typeof_ = ExprNode::VOID;
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_return_expr_node(ReturnExprNode *n) {
-  TRY2(n->expr_->accept(this));
-  n->typeof_ = ExprNode::VOID;
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::expect_method_arg(MethodCallExprNode *n, size_t num, size_t num_def_args = 0) {
-  if (num_def_args == 0) {
-    if (n->args_.size() != num)
-      return mkstatus_(n, "%s expected %d argument%s, %zu given", n->id_->sub_name_.c_str(),
-                      num, num == 1 ? "" : "s", n->args_.size());
-  } else {
-    if (n->args_.size() < num - num_def_args || n->args_.size() > num)
-      return mkstatus_(n, "%s expected %d argument%s (%d default), %zu given", n->id_->sub_name_.c_str(),
-                      num, num == 1 ? "" : "s", num_def_args, n->args_.size());
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::check_lookup_method(MethodCallExprNode *n) {
-  auto table = scopes_->top_table()->lookup(n->id_->name_);
-  if (!table)
-    return mkstatus_(n, "Unknown table name %s", n->id_->c_str());
-  TRY2(expect_method_arg(n, 2, 1));
-  if (table->type_id()->name_ == "LPM")
-    return mkstatus_(n, "LPM unsupported");
-  if (n->block_->scope_) {
-    auto result = make_unique<StructVariableDeclStmtNode>(table->leaf_id()->copy(), make_unique<IdentExprNode>("_result"),
-                                                          VariableDeclStmtNode::STRUCT_REFERENCE);
-    n->block_->scope_->add("_result", result.get());
-    n->block_->stmts_.insert(n->block_->stmts_.begin(), move(result));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::check_update_method(MethodCallExprNode *n) {
-  auto table = scopes_->top_table()->lookup(n->id_->name_);
-  if (!table)
-    return mkstatus_(n, "Unknown table name %s", n->id_->c_str());
-  if (table->type_id()->name_ == "FIXED_MATCH" || table->type_id()->name_ == "INDEXED")
-    TRY2(expect_method_arg(n, 2));
-  else if (table->type_id()->name_ == "LPM")
-    TRY2(expect_method_arg(n, 3));
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::check_delete_method(MethodCallExprNode *n) {
-  auto table = scopes_->top_table()->lookup(n->id_->name_);
-  if (!table)
-    return mkstatus_(n, "Unknown table name %s", n->id_->c_str());
-  if (table->type_id()->name_ == "FIXED_MATCH" || table->type_id()->name_ == "INDEXED")
-    TRY2(expect_method_arg(n, 1));
-  else if (table->type_id()->name_ == "LPM")
-    {}
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_method_call_expr_node(MethodCallExprNode *n) {
-  // be sure to visit those child nodes ASAP, so their properties can
-  // be propagated up to this node and be ready to be used
-  for (auto it = n->args_.begin(); it != n->args_.end(); ++it) {
-    TRY2((*it)->accept(this));
-  }
-
-  n->typeof_ = ExprNode::VOID;
-  if (n->id_->sub_name_.size()) {
-    if (n->id_->sub_name_ == "lookup") {
-      TRY2(check_lookup_method(n));
-    } else if (n->id_->sub_name_ == "update") {
-      TRY2(check_update_method(n));
-    } else if (n->id_->sub_name_ == "delete") {
-      TRY2(check_delete_method(n));
-    } else if (n->id_->sub_name_ == "rewrite_field" && n->id_->name_ == "pkt") {
-      TRY2(expect_method_arg(n, 2));
-      n->args_[0]->flags_[ExprNode::IS_LHS] = true;
-    }
-  } else if (n->id_->name_ == "log") {
-    if (n->args_.size() < 1)
-      return mkstatus_(n, "%s expected at least 1 argument", n->id_->c_str());
-    if (n->args_[0]->typeof_ != ExprNode::STRING)
-      return mkstatus_(n, "%s expected a string for argument 1", n->id_->c_str());
-    n->typeof_ = ExprNode::INTEGER;
-    n->bit_width_ = 32;
-  } else if (n->id_->name_ == "atomic_add") {
-    TRY2(expect_method_arg(n, 2));
-    n->typeof_ = ExprNode::INTEGER;
-    n->bit_width_ = n->args_[0]->bit_width_;
-    n->args_[0]->flags_[ExprNode::IS_LHS] = true;
-  } else if (n->id_->name_ == "incr_cksum") {
-    TRY2(expect_method_arg(n, 4, 1));
-    n->typeof_ = ExprNode::INTEGER;
-    n->bit_width_ = 16;
-  } else if (n->id_->name_ == "sizeof") {
-    TRY2(expect_method_arg(n, 1));
-    n->typeof_ = ExprNode::INTEGER;
-    n->bit_width_ = 32;
-  } else if (n->id_->name_ == "get_usec_time") {
-     TRY2(expect_method_arg(n, 0));
-     n->typeof_ = ExprNode::INTEGER;
-     n->bit_width_ = 64;
-  }
-
-  if (!n->block_->stmts_.empty()) {
-    if (n->id_->sub_name_ != "update" && n->id_->sub_name_ != "lookup")
-      return mkstatus_(n, "%s does not allow trailing block statements", n->id_->full_name().c_str());
-    TRY2(n->block_->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_table_index_expr_node(TableIndexExprNode *n) {
-  n->table_ = scopes_->top_table()->lookup(n->id_->name_);
-  if (!n->table_) return mkstatus_(n, "Unknown table name %s", n->id_->c_str());
-  TRY2(n->index_->accept(this));
-  if (n->index_->struct_type_ != n->table_->key_type_)
-    return mkstatus_(n, "Key to table %s lookup must be of type %s", n->id_->c_str(), n->table_->key_id()->c_str());
-
-  if (n->sub_) {
-    n->sub_decl_ = n->table_->leaf_type_->field(n->sub_->name_);
-    if (!n->sub_decl_)
-      return mkstatus_(n, "Field %s is not a member of %s", n->sub_->c_str(), n->table_->leaf_id()->c_str());
-    n->typeof_ = ExprNode::INTEGER;
-  } else {
-    n->typeof_ = ExprNode::STRUCT;
-    n->flags_[ExprNode::IS_REF] = true;
-    n->struct_type_ = n->table_->leaf_type_;
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_expr_stmt_node(ExprStmtNode *n) {
-  TRY2(n->expr_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_struct_variable_decl_stmt_node(StructVariableDeclStmtNode *n) {
-  //TRY2(n->struct_id_->accept(this));
-  //TRY2(n->id_->accept(this));
-  if (!n->init_.empty()) {
-    StructDeclStmtNode *type;
-    if (n->struct_id_->scope_name_ == "proto")
-      type = proto_scopes_->top_struct()->lookup(n->struct_id_->name_, true);
-    else
-      type = scopes_->top_struct()->lookup(n->struct_id_->name_, true);
-
-    if (!type)
-      return mkstatus_(n, "type %s does not exist", n->struct_id_->full_name().c_str());
-
-    // init remaining fields to 0
-    set<string> used;
-    for (auto i = n->init_.begin(); i != n->init_.end(); ++i) {
-      auto asn = static_cast<AssignExprNode*>(i->get());
-      auto id = static_cast<IdentExprNode *>(asn->lhs_.get());
-      used.insert(id->sub_name_);
-    }
-    for (auto f = type->stmts_.begin(); f != type->stmts_.end(); ++f) {
-      if (used.find((*f)->id_->name_) == used.end()) {
-        auto id = make_unique<IdentExprNode>(n->id_->name_);
-        id->append_dot((*f)->id_->name_);
-        n->init_.push_back(make_unique<AssignExprNode>(move(id), make_unique<IntegerExprNode>("0")));
-      }
-    }
-
-    for (auto it = n->init_.begin(); it != n->init_.end(); ++it) {
-      TRY2((*it)->accept(this));
-    }
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_integer_variable_decl_stmt_node(IntegerVariableDeclStmtNode *n) {
-  //TRY2(n->id_->accept(this));
-  if (!n->init_.empty()) {
-    TRY2(n->init_[0]->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_struct_decl_stmt_node(StructDeclStmtNode *n) {
-  //TRY2(n->id_->accept(this));
-  for (auto it = n->stmts_.begin(); it != n->stmts_.end(); ++it) {
-    TRY2((*it)->accept(this));
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_parser_state_stmt_node(ParserStateStmtNode *n) {
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_state_decl_stmt_node(StateDeclStmtNode *n) {
-  if (!n->id_) {
-    return StatusTuple::OK();
-  }
-  auto s1 = proto_scopes_->top_state()->lookup(n->id_->name_, true);
-  if (s1) {
-    const string &name = n->id_->name_;
-    auto offset_var = make_unique<IntegerVariableDeclStmtNode>(make_unique<IdentExprNode>("$" + name), "64");
-    offset_var->init_.push_back(make_unique<AssignExprNode>(offset_var->id_->copy(), make_unique<IntegerExprNode>("0")));
-    scopes_->current_var()->add("$" + name, offset_var.get());
-    s1->subs_[0].block_->scope_->add("$" + name, offset_var.get());
-    n->init_.push_back(move(offset_var));
-
-    n->parser_ = ParserStateStmtNode::make(n->id_);
-    n->parser_->next_state_ = s1->subs_[0].block_.get();
-    n->parser_->scope_id_ = n->scope_id_;
-
-    auto p = proto_scopes_->top_struct()->lookup(n->id_->name_, true);
-    if (!p) return mkstatus_(n, "unable to find struct decl for parser state %s", n->id_->full_name().c_str());
-
-    // $proto = parsed_bytes; parsed_bytes += sizeof($proto);
-    auto asn1 = make_unique<AssignExprNode>(make_unique<IdentExprNode>("$" + n->id_->name_),
-                                            make_unique<IdentExprNode>("parsed_bytes"));
-    n->init_.push_back(make_unique<ExprStmtNode>(move(asn1)));
-    auto add_expr = make_unique<BinopExprNode>(make_unique<IdentExprNode>("parsed_bytes"), Tok::TPLUS,
-                                               make_unique<IntegerExprNode>(std::to_string(p->bit_width_ >> 3), 64));
-    auto asn2 = make_unique<AssignExprNode>(make_unique<IdentExprNode>("parsed_bytes"), move(add_expr));
-    n->init_.push_back(make_unique<ExprStmtNode>(move(asn2)));
-  }
-
-  for (auto it = n->init_.begin(); it != n->init_.end(); ++it) {
-    TRY2((*it)->accept(this));
-  }
-
-  for (auto it = n->subs_.begin(); it != n->subs_.end(); ++it) {
-    scopes_->push_state(it->scope_);
-
-    TRY2(it->block_->accept(this));
-
-    if (s1) {
-      if (it->id_->name_ == "") {
-        it->parser_ = ParserStateStmtNode::make(it->id_);
-        it->parser_->next_state_ = s1->subs_[0].block_.get();
-        it->parser_->scope_id_ = n->scope_id_ + n->id_->name_ + "_";
-      } else if (auto s2 = proto_scopes_->top_state()->lookup(it->id_->name_, true)) {
-        it->parser_ = ParserStateStmtNode::make(it->id_);
-        it->parser_->next_state_ = s2->subs_[0].block_.get();
-        it->parser_->scope_id_ = n->scope_id_ + n->id_->name_ + "_";
-      }
-
-      if (it->parser_) {
-        TRY2(it->parser_->accept(this));
-      }
-    }
-
-    scopes_->pop_state();
-  }
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_match_decl_stmt_node(MatchDeclStmtNode *n) {
-  //TRY2(n->id_->accept(this));
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    TRY2((*it)->accept(this));
-  }
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_miss_decl_stmt_node(MissDeclStmtNode *n) {
-  //TRY2(n->id_->accept(this));
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    TRY2((*it)->accept(this));
-  }
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_failure_decl_stmt_node(FailureDeclStmtNode *n) {
-  //TRY2(n->id_->accept(this));
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    TRY2((*it)->accept(this));
-  }
-  TRY2(n->block_->accept(this));
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_table_decl_stmt_node(TableDeclStmtNode *n) {
-  n->key_type_ = scopes_->top_struct()->lookup(n->key_id()->name_, true);
-  if (!n->key_type_)
-    return mkstatus_(n, "Table key type %s undefined", n->key_id()->c_str());
-  n->key_id()->bit_width_ = n->key_type_->bit_width_;
-  n->leaf_type_ = scopes_->top_struct()->lookup(n->leaf_id()->name_, true);
-  if (!n->leaf_type_)
-    return mkstatus_(n, "Table leaf type %s undefined", n->leaf_id()->c_str());
-  n->leaf_id()->bit_width_ = n->leaf_type_->bit_width_;
-  if (n->type_id()->name_ == "INDEXED" && n->policy_id()->name_ != "AUTO") {
-    fprintf(stderr, "Table %s is INDEXED, policy should be AUTO\n", n->id_->c_str());
-    n->policy_id()->name_ = "AUTO";
-  }
-  if (n->policy_id()->name_ != "AUTO" && n->policy_id()->name_ != "NONE")
-    return mkstatus_(n, "Unsupported policy type %s", n->policy_id()->c_str());
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit_func_decl_stmt_node(FuncDeclStmtNode *n) {
-  for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
-    VariableDeclStmtNode *var = it->get();
-    TRY2(var->accept(this));
-    if (var->is_struct()) {
-      if (!var->is_pointer())
-        return mkstatus_(n, "Only struct references allowed in function definitions");
-    }
-  }
-  scopes_->push_state(n->scope_);
-  TRY2(n->block_->accept(this));
-  scopes_->pop_state();
-  return StatusTuple::OK();
-}
-
-StatusTuple TypeCheck::visit(Node *root) {
-  BlockStmtNode *b = static_cast<BlockStmtNode*>(root);
-
-  scopes_->set_current(scopes_->top_state());
-  scopes_->set_current(scopes_->top_var());
-
-  // // packet data in bpf socket
-  // if (scopes_->top_struct()->lookup("_skbuff", true)) {
-  //   return StatusTuple(-1, "_skbuff already defined");
-  // }
-  // auto skb_type = make_unique<StructDeclStmtNode>(make_unique<IdentExprNode>("_skbuff"));
-  // scopes_->top_struct()->add("_skbuff", skb_type.get());
-  // b->stmts_.push_back(move(skb_type));
-
-  // if (scopes_->current_var()->lookup("skb", true)) {
-  //   return StatusTuple(-1, "skb already defined");
-  // }
-  // auto skb = make_unique<StructVariableDeclStmtNode>(make_unique<IdentExprNode>("_skbuff"),
-  //                                                    make_unique<IdentExprNode>("skb"));
-  // skb->storage_type_ = VariableDeclStmtNode::STRUCT_REFERENCE;
-  // scopes_->current_var()->add("skb", skb.get());
-  // b->stmts_.push_back(move(skb));
-
-  // offset counter
-  auto parsed_bytes = make_unique<IntegerVariableDeclStmtNode>(
-                        make_unique<IdentExprNode>("parsed_bytes"), "64");
-  parsed_bytes->init_.push_back(make_unique<AssignExprNode>(parsed_bytes->id_->copy(), make_unique<IntegerExprNode>("0")));
-  scopes_->current_var()->add("parsed_bytes", parsed_bytes.get());
-  b->stmts_.push_back(move(parsed_bytes));
-
-  TRY2(b->accept(this));
-
-  if (!errors_.empty()) {
-    for (auto it = errors_.begin(); it != errors_.end(); ++it) {
-      fprintf(stderr, "%s\n", it->c_str());
-    }
-    return StatusTuple(-1, errors_.begin()->c_str());
-  }
-  return StatusTuple::OK();
-}
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/type_check.h b/src/cc/frontends/b/type_check.h
deleted file mode 100644 (file)
index dbf427a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <vector>
-#include <string>
-#include "node.h"
-#include "scope.h"
-
-namespace ebpf {
-namespace cc {
-
-class TypeCheck : public Visitor {
- public:
-  TypeCheck(Scopes *scopes, Scopes *proto_scopes)
-      : scopes_(scopes), proto_scopes_(proto_scopes) {}
-
-  virtual STATUS_RETURN visit(Node* n);
-  STATUS_RETURN expect_method_arg(MethodCallExprNode* n, size_t num, size_t num_def_args);
-  STATUS_RETURN check_lookup_method(MethodCallExprNode* n);
-  STATUS_RETURN check_update_method(MethodCallExprNode* n);
-  STATUS_RETURN check_delete_method(MethodCallExprNode* n);
-
-#define VISIT(type, func) virtual STATUS_RETURN visit_##func(type* n);
-  EXPAND_NODES(VISIT)
-#undef VISIT
-
- private:
-  Scopes *scopes_;
-  Scopes *proto_scopes_;
-  vector<string> errors_;
-};
-
-}  // namespace cc
-}  // namespace ebpf
diff --git a/src/cc/frontends/b/type_helper.h b/src/cc/frontends/b/type_helper.h
deleted file mode 100644 (file)
index ce96cc4..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2015 PLUMgrid, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-namespace ebpf {
-namespace cc {
-
-// Represent the numeric type of a protocol field
-enum FieldType {
-  INVALID = 0,
-  UINT8_T,
-  UINT16_T,
-  UINT32_T,
-  UINT64_T,
-#ifdef __SIZEOF_INT128__
-  UINT128_T,
-#endif
-  VOID
-};
-
-static inline size_t enum_to_size(const FieldType t) {
-  switch (t) {
-    case UINT8_T: return sizeof(uint8_t);
-    case UINT16_T: return sizeof(uint16_t);
-    case UINT32_T: return sizeof(uint32_t);
-    case UINT64_T: return sizeof(uint64_t);
-#ifdef __SIZEOF_INT128__
-    case UINT128_T: return sizeof(__uint128_t);
-#endif
-    default:
-      return 0;
-  }
-}
-
-/// Convert a bit size to the next highest power of 2
-static inline int next_base2(int v) {
-  --v;
-  v |= v >> 1;
-  v |= v >> 2;
-  v |= v >> 4;
-  v |= v >> 8;
-  v |= v >> 16;
-  ++v;
-  return v;
-}
-
-static inline const char* bits_to_uint(int v) {
-  v = next_base2(v);
-  if (v <= 8) {
-    return "uint8_t";
-  } else if (v == 16) {
-    return "uint16_t";
-  } else if (v == 32) {
-    return "uint32_t";
-  } else if (v == 64) {
-    return "uint64_t";
-  } else if (v >= 128) {
-    /* in plumlet 128-bit integers should be 8-byte aligned,
-     * all other ints should have natural alignment */
-    return "unsigned __int128 __attribute__((packed, aligned(8)))";
-  }
-  return "void";
-}
-
-static inline FieldType bits_to_enum(int v) {
-  v = next_base2(v);
-  if (v <= 8) {
-    return UINT8_T;
-  } else if (v == 16) {
-    return UINT16_T;
-  } else if (v == 32) {
-    return UINT32_T;
-  } else if (v == 64) {
-    return UINT64_T;
-#ifdef __SIZEOF_INT128__
-  } else if (v >= 128) {
-    return UINT128_T;
-#endif
-  }
-  return VOID;
-}
-
-static inline size_t bits_to_size(int v) {
-  return enum_to_size(bits_to_enum(v));
-}
-
-static inline size_t align_offset(size_t offset, FieldType ft) {
-  switch (ft) {
-    case UINT8_T:
-      return offset % 8 > 0 ? offset + (8 - offset % 8) : offset;
-    case UINT16_T:
-      return offset % 16 > 0 ? offset + (16 - offset % 16) : offset;
-    case UINT32_T:
-      return offset % 32 > 0 ? offset + (32 - offset % 32) : offset;
-    case UINT64_T:
-#ifdef __SIZEOF_INT128__
-    case UINT128_T:
-#endif
-      return offset % 64 > 0 ? offset + (64 - offset % 64) : offset;
-    default:
-      ;
-  }
-  return offset;
-}
-
-}  // namespace cc
-}  // namespace ebpf
index 89170f3184d45ceb6b9881216152c08481cc6c5a..45be272843a36fa478349b95058bacbc0b5724d1 100644 (file)
@@ -125,12 +125,7 @@ function Bpf:initialize(args)
   elseif args.src_file then
     local src = _find_file(Bpf.SCRIPT_ROOT, args.src_file)
 
-    if src:ends(".b") then
-      local hdr = _find_file(Bpf.SCRIPT_ROOT, args.hdr_file)
-      self.module = libbcc.bpf_module_create_b(src, hdr, llvm_debug)
-    else
-      self.module = libbcc.bpf_module_create_c(src, llvm_debug, cflags_ary, #cflags, true)
-    end
+    self.module = libbcc.bpf_module_create_c(src, llvm_debug, cflags_ary, #cflags, true)
   end
 
   assert(self.module ~= nil, "failed to compile BPF module")
index b2b5ee9014cd6c825297920d265e422a13de6587..f34fbd05873f90977f9fc2ba33b205605fefaba8 100644 (file)
@@ -58,7 +58,6 @@ int bpf_close_perf_event_fd(int fd);
 ]]
 
 ffi.cdef[[
-void * bpf_module_create_b(const char *filename, const char *proto_filename, unsigned flags);
 void * bpf_module_create_c(const char *filename, unsigned flags, const char *cflags[], int ncflags, bool allow_rlimit);
 void * bpf_module_create_c_from_string(const char *text, unsigned flags, const char *cflags[], int ncflags, bool allow_rlimit);
 void bpf_module_destroy(void *program);
index 389bc8ba6b511c39141cb3733949f89ad842ee8a..ceb2884121db88028dab6f6a83da4623e007fa70 100644 (file)
@@ -449,32 +449,28 @@ class BPF(object):
             src_file = BPF._find_file(src_file)
             hdr_file = BPF._find_file(hdr_file)
 
-        # files that end in ".b" are treated as B files. Everything else is a (BPF-)C file
-        if src_file.endswith(b".b"):
-            self.module = lib.bpf_module_create_b(src_file, hdr_file, self.debug, device)
-        else:
-            if src_file:
-                # Read the BPF C source file into the text variable. This ensures,
-                # that files and inline text are treated equally.
-                with open(src_file, mode="rb") as file:
-                    text = file.read()
-
-            ctx_array = (ct.c_void_p * len(usdt_contexts))()
-            for i, usdt in enumerate(usdt_contexts):
-                ctx_array[i] = ct.c_void_p(usdt.get_context())
-            usdt_text = lib.bcc_usdt_genargs(ctx_array, len(usdt_contexts))
-            if usdt_text is None:
-                raise Exception("can't generate USDT probe arguments; " +
-                                "possible cause is missing pid when a " +
-                                "probe in a shared object has multiple " +
-                                "locations")
-            text = usdt_text + text
-
-
-            self.module = lib.bpf_module_create_c_from_string(text,
-                                                              self.debug,
-                                                              cflags_array, len(cflags_array),
-                                                              allow_rlimit, device)
+        if src_file:
+            # Read the BPF C source file into the text variable. This ensures,
+            # that files and inline text are treated equally.
+            with open(src_file, mode="rb") as file:
+                text = file.read()
+
+        ctx_array = (ct.c_void_p * len(usdt_contexts))()
+        for i, usdt in enumerate(usdt_contexts):
+            ctx_array[i] = ct.c_void_p(usdt.get_context())
+        usdt_text = lib.bcc_usdt_genargs(ctx_array, len(usdt_contexts))
+        if usdt_text is None:
+            raise Exception("can't generate USDT probe arguments; " +
+                            "possible cause is missing pid when a " +
+                            "probe in a shared object has multiple " +
+                            "locations")
+        text = usdt_text + text
+
+
+        self.module = lib.bpf_module_create_c_from_string(text,
+                                                          self.debug,
+                                                          cflags_array, len(cflags_array),
+                                                          allow_rlimit, device)
         if not self.module:
             raise Exception("Failed to compile BPF module %s" % (src_file or "<text>"))
 
index 3a39d04475541fd71826ea3feecc1fb909d1000b..fdea8a1265966c7ae5bee49c8c6fc721e864618d 100644 (file)
@@ -20,9 +20,6 @@ lib = ct.CDLL("libbcc.so.0", use_errno=True)
 from .perf import Perf
 
 # keep in sync with bcc_common.h
-lib.bpf_module_create_b.restype = ct.c_void_p
-lib.bpf_module_create_b.argtypes = [ct.c_char_p, ct.c_char_p, ct.c_uint,
-        ct.c_char_p]
 lib.bpf_module_create_c.restype = ct.c_void_p
 lib.bpf_module_create_c.argtypes = [ct.c_char_p, ct.c_uint,
         ct.POINTER(ct.c_char_p), ct.c_int, ct.c_bool, ct.c_char_p]
index d86fcab6b9d6283609eb5798715d056b1945d426..a42a16ce1c68395f11690e6a7e1f36b766e0c063 100644 (file)
@@ -17,20 +17,14 @@ if(IPERF STREQUAL "IPERF-NOTFOUND")
   endif()
 endif()
 
-add_test(NAME py_test_stat1_b WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-  COMMAND ${TEST_WRAPPER} py_stat1_b namespace ${CMAKE_CURRENT_SOURCE_DIR}/test_stat1.py test_stat1.b proto.b)
 add_test(NAME py_test_bpf_log WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   COMMAND ${TEST_WRAPPER} py_bpf_prog sudo ${CMAKE_CURRENT_SOURCE_DIR}/test_bpf_log.py)
 add_test(NAME py_test_stat1_c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   COMMAND ${TEST_WRAPPER} py_stat1_c namespace ${CMAKE_CURRENT_SOURCE_DIR}/test_stat1.py test_stat1.c)
-#add_test(NAME py_test_xlate1_b WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-#  COMMAND ${TEST_WRAPPER} py_xlate1_b namespace ${CMAKE_CURRENT_SOURCE_DIR}/test_xlate1.py test_xlate1.b proto.b)
 add_test(NAME py_test_xlate1_c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   COMMAND ${TEST_WRAPPER} py_xlate1_c namespace ${CMAKE_CURRENT_SOURCE_DIR}/test_xlate1.py test_xlate1.c)
 add_test(NAME py_test_call1 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   COMMAND ${TEST_WRAPPER} py_call1_c namespace ${CMAKE_CURRENT_SOURCE_DIR}/test_call1.py test_call1.c)
-add_test(NAME py_test_trace1 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-  COMMAND ${TEST_WRAPPER} py_trace1 sudo ${CMAKE_CURRENT_SOURCE_DIR}/test_trace1.py test_trace1.b kprobe.b)
 add_test(NAME py_test_trace2 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   COMMAND ${TEST_WRAPPER} py_trace2 sudo ${CMAKE_CURRENT_SOURCE_DIR}/test_trace2.py)
 add_test(NAME py_test_trace3_c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/python/kprobe.b b/tests/python/kprobe.b
deleted file mode 100644 (file)
index 74a996b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) PLUMgrid, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License")
-
-#packed "false"
-
-struct pt_regs {
-  u64 r15:64;
-  u64 r14:64;
-  u64 r13:64;
-  u64 r12:64;
-  u64 bp:64;
-  u64 bx:64;
-  u64 r11:64;
-  u64 r10:64;
-  u64 r9:64;
-  u64 r8:64;
-  u64 ax:64;
-  u64 cx:64;
-  u64 dx:64;
-  u64 si:64;
-  u64 di:64;
-};
-
-
diff --git a/tests/python/proto.b b/tests/python/proto.b
deleted file mode 100644 (file)
index 78cfa5f..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) PLUMgrid, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License")
-
-#packed "true"
-
-struct ethernet {
-  u64 dst:48;
-  u64 src:48;
-  u32 type:16;
-};
-
-state ethernet {
-  switch $ethernet.type {
-    case 0x0800 {
-      next proto::ip;
-    };
-    case 0x8100 {
-      next proto::dot1q;
-    };
-    case * {
-      goto EOP;
-    };
-  }
-}
-
-
-struct dot1q {
-  u32 pri:3;
-  u32 cfi:1;
-  u32 vlanid:12;
-  u32 type:16;
-};
-
-state dot1q {
-  switch $dot1q.type {
-    case 0x0800 {
-      next proto::ip;
-    };
-    case * {
-      goto EOP;
-    };
-  }
-}
-
-
-struct ip {
-  u32 ver:4;
-  u32 hlen:4;
-  u32 tos:8;
-  u32 tlen:16;
-  u32 identification:16;
-  u32 ffo_unused:1;
-  u32 df:1;
-  u32 mf:1;
-  u32 foffset:13;
-  u32 ttl:8;
-  u32 nextp:8;
-  u32 hchecksum:16;
-  u32 src:32;
-  u32 dst:32;
-};
-
-state ip {
-  switch $ip.nextp {
-    case 6 {
-      next proto::tcp;
-    };
-    case 17 {
-      next proto::udp;
-    };
-    case 47 {
-      next proto::gre;
-    };
-    case * {
-      goto EOP;
-    };
-  }
-}
-
-
-struct udp {
-  u32 sport:16;
-  u32 dport:16;
-  u32 length:16;
-  u32 crc:16;
-};
-
-state udp {
-  switch $udp.dport {
-    case 8472 {
-      next proto::vxlan;
-    };
-    case * {
-      goto EOP;
-    };
-  }
-}
-
-struct tcp {
-  u16 src_port:16;
-  u16 dst_port:16;
-  u32 seq_num:32;
-  u32 ack_num:32;
-  u8 offset:4;
-  u8 reserved:4;
-  u8 flag_cwr:1;
-  u8 flag_ece:1;
-  u8 flag_urg:1;
-  u8 flag_ack:1;
-  u8 flag_psh:1;
-  u8 flag_rst:1;
-  u8 flag_syn:1;
-  u8 flag_fin:1;
-  u16 rcv_wnd:16;
-  u16 cksum:16;
-  u16 urg_ptr:16;
-};
-
-state tcp {
-  goto EOP;
-}
-
-struct vxlan {
-  u32 rsv1:4;
-  u32 iflag:1;
-  u32 rsv2:3;
-  u32 rsv3:24;
-  u32 key:24;
-  u32 rsv4:8;
-};
-
-state vxlan {
-  goto EOP;
-}
-
-
-struct gre {
-  u32 cflag:1;
-  u32 rflag:1;
-  u32 kflag:1;
-  u32 snflag:1;
-  u32 srflag:1;
-  u32 recurflag:3;
-  u32 reserved:5;
-  u32 vflag:3;
-  u32 protocol:16;
-  u32 key:32;
-};
-
-state gre {
-  switch $gre.protocol {
-    case * {
-      goto EOP;
-    };
-  }
-}
-
diff --git a/tests/python/test_stat1.b b/tests/python/test_stat1.b
deleted file mode 100644 (file)
index fb505d6..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) PLUMgrid, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License")
-struct IPKey {
-  u32 dip:32;
-  u32 sip:32;
-};
-struct IPLeaf {
-  u32 rx_pkts:64;
-  u32 tx_pkts:64;
-};
-Table<IPKey, IPLeaf, FIXED_MATCH, AUTO> stats(1024);
-
-struct skbuff {
-  u32 type:32;
-};
-
-u32 on_packet(struct skbuff *skb) {
-  u32 ret:32 = 0;
-
-  goto proto::ethernet;
-
-  state proto::ethernet {
-  }
-
-  state proto::dot1q {
-  }
-
-  state proto::ip {
-    u32 rx:32 = 0;
-    u32 tx:32 = 0;
-    u32 IPKey key;
-    if $ip.dst > $ip.src {
-      key.dip = $ip.dst;
-      key.sip = $ip.src;
-      rx = 1;
-      // test arbitrary return stmt
-      if false {
-        return 3;
-      }
-    } else {
-      key.dip = $ip.src;
-      key.sip = $ip.dst;
-      tx = 1;
-      ret = 1;
-    }
-    struct IPLeaf *leaf;
-    leaf = stats[key];
-    on_valid(leaf) {
-      atomic_add(leaf.rx_pkts, rx);
-      atomic_add(leaf.tx_pkts, tx);
-    }
-  }
-
-  state proto::udp {
-  }
-
-  state proto::vxlan {
-  }
-
-  state proto::gre {
-  }
-
-  state EOP {
-    return ret;
-  }
-}
index 23b3a291a741785fdf5dec70e500a6634faec7ff..1043309952009c1a5888e1e934d88b646f46e07b 100755 (executable)
@@ -19,13 +19,6 @@ if len(sys.argv) > 1:
 
 Key = None
 Leaf = None
-if arg1.endswith(".b"):
-    class Key(Structure):
-        _fields_ = [("dip", c_uint),
-                    ("sip", c_uint)]
-    class Leaf(Structure):
-        _fields_ = [("rx_pkts", c_ulong),
-                    ("tx_pkts", c_ulong)]
 
 class TestBPFSocket(TestCase):
     def setUp(self):
diff --git a/tests/python/test_trace1.b b/tests/python/test_trace1.b
deleted file mode 100644 (file)
index 05ddda6..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) PLUMgrid, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License")
-struct Ptr {
-  u64 ptr:64;
-};
-struct Counters {
-  u64 stat1:64;
-  u64 stat2:64;
-};
-Table<Ptr, Counters, FIXED_MATCH, AUTO> stats(1024);
-
-// example with on_valid syntax
-u32 sys_wr (struct proto::pt_regs *ctx) {
-  struct Ptr key = {.ptr=ctx->di};
-  struct Counters *leaf;
-  leaf = stats[key];
-  if leaf {
-    atomic_add(leaf->stat2, 1);
-  }
-  log("sys_wr: %p\n", ctx->di);
-  return 0;
-}
-
-// example with smallest available syntax
-// note: if stats[key] fails, program returns early
-u32 sys_rd (struct proto::pt_regs *ctx) {
-  struct Ptr key = {.ptr=ctx->di};
-  atomic_add(stats[key].stat1, 1);
-}
-
-// example with if/else case
-u32 sys_bpf (struct proto::pt_regs *ctx) {
-  struct Ptr key = {.ptr=ctx->di};
-  struct Counters *leaf;
-  leaf = stats[key];
-  if leaf {
-    atomic_add(leaf->stat1, 1);
-  } else {
-    log("update %llx failed\n", ctx->di);
-  }
-  return 0;
-}
-
diff --git a/tests/python/test_trace1.py b/tests/python/test_trace1.py
deleted file mode 100755 (executable)
index dc005c5..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) PLUMgrid, Inc.
-# Licensed under the Apache License, Version 2.0 (the "License")
-
-from ctypes import c_uint, c_ulong, Structure
-from bcc import BPF
-import os
-from time import sleep
-import sys
-from unittest import main, TestCase
-
-arg1 = sys.argv.pop(1)
-arg2 = ""
-if len(sys.argv) > 1:
-  arg2 = sys.argv.pop(1)
-
-Key = None
-Leaf = None
-if arg1.endswith(".b"):
-    class Key(Structure):
-        _fields_ = [("fd", c_ulong)]
-    class Leaf(Structure):
-        _fields_ = [("stat1", c_ulong),
-                    ("stat2", c_ulong)]
-
-class TestKprobe(TestCase):
-    def setUp(self):
-        b = BPF(arg1, arg2, debug=0)
-        self.stats = b.get_table("stats", Key, Leaf)
-        b.attach_kprobe(event=b.get_syscall_fnname("write"), fn_name="sys_wr")
-        b.attach_kprobe(event=b.get_syscall_fnname("read"), fn_name="sys_rd")
-        b.attach_kprobe(event="htab_map_get_next_key", fn_name="sys_rd")
-
-    def test_trace1(self):
-        with open("/dev/null", "a") as f:
-            for i in range(0, 100):
-                os.write(f.fileno(), b"")
-        with open("/etc/services", "r") as f:
-            for i in range(0, 200):
-                os.read(f.fileno(), 1)
-        for key, leaf in self.stats.items():
-            print("fd %x:" % key.fd, "stat1 %d" % leaf.stat1, "stat2 %d" % leaf.stat2)
-
-if __name__ == "__main__":
-    main()
diff --git a/tests/python/test_trace2.b b/tests/python/test_trace2.b
deleted file mode 100644 (file)
index 1e4bcd1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) PLUMgrid, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License")
-#include "kprobe.b"
-struct Ptr { u64 ptr:64; };
-struct Counters { u64 stat1:64; };
-Table<Ptr, Counters, FIXED_MATCH, AUTO> stats(1024);
-
-u32 count_sched (struct proto::pt_regs *ctx) {
-  struct Ptr key = {.ptr=ctx->bx};
-  atomic_add(stats[key].stat1, 1);
-}
diff --git a/tests/python/test_xlate1.b b/tests/python/test_xlate1.b
deleted file mode 100644 (file)
index 2db0046..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) PLUMgrid, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License")
-// test for packet modification
-
-#packed "false"
-
-struct IPKey {
-  u32 dip:32;
-  u32 sip:32;
-};
-struct IPLeaf {
-  u32 xdip:32;
-  u32 xsip:32;
-  u64 xlated_pkts:64;
-};
-Table<IPKey, IPLeaf, FIXED_MATCH, NONE> xlate(1024);
-
-struct skbuff {
-  u32 type:32;
-};
-
-u32 on_packet (struct skbuff *skb) {
-  u32 ret:32 = 1;
-
-  u32 orig_dip:32 = 0;
-  u32 orig_sip:32 = 0;
-  struct IPLeaf *xleaf;
-
-  goto proto::ethernet;
-
-  state proto::ethernet {
-  }
-
-  state proto::dot1q {
-  }
-
-  state proto::ip {
-    orig_dip = $ip.dst;
-    orig_sip = $ip.src;
-    struct IPKey key = {.dip=orig_dip, .sip=orig_sip};
-    xlate.lookup(key, xleaf) {};
-    on_valid(xleaf) {
-      incr_cksum(@ip.hchecksum, orig_dip, xleaf.xdip);
-      incr_cksum(@ip.hchecksum, orig_sip, xleaf.xsip);
-      // the below are equivalent
-      pkt.rewrite_field($ip.dst, xleaf.xdip);
-      $ip.src = xleaf.xsip;
-      atomic_add(xleaf.xlated_pkts, 1);
-    }
-  }
-
-  state proto::udp {
-    on_valid(xleaf) {
-      incr_cksum(@udp.crc, orig_dip, xleaf.xdip, 1);
-      incr_cksum(@udp.crc, orig_sip, xleaf.xsip, 1);
-    }
-  }
-
-  state proto::tcp {
-    on_valid(xleaf) {
-      incr_cksum(@tcp.cksum, orig_dip, xleaf.xdip, 1);
-      incr_cksum(@tcp.cksum, orig_sip, xleaf.xsip, 1);
-    }
-  }
-
-  state proto::vxlan {
-  }
-
-  state proto::gre {
-  }
-
-  state EOP {
-    return ret;
-  }
-}