aboutsummaryrefslogtreecommitdiff
path: root/src/cc/frontends/b/codegen_llvm.h
blob: c2947f74ebaea31dd437da7921ae6b86a812501a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * 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;
class BasicBlock;
class BranchInst;
class Constant;
class Instruction;
class IRBuilderBase;
class LLVMContext;
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;

  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