1 /*
2  * Copyright (c) 2015 PLUMgrid, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <map>
20 #include <stdio.h>
21 #include <vector>
22 #include <string>
23 #include <set>
24 
25 #include "node.h"
26 #include "scope.h"
27 
28 namespace llvm {
29 class AllocaInst;
30 class BasicBlock;
31 class BranchInst;
32 class Constant;
33 class Instruction;
34 class IRBuilderBase;
35 class LLVMContext;
36 class Module;
37 class StructType;
38 class SwitchInst;
39 class Type;
40 class Value;
41 class GlobalVariable;
42 }
43 
44 namespace ebpf {
45 
46 class TableStorage;
47 
48 namespace cc {
49 
50 class BlockStack;
51 class SwitchStack;
52 
53 using std::vector;
54 using std::string;
55 using std::set;
56 
57 class CodegenLLVM : public Visitor {
58   friend class BlockStack;
59   friend class SwitchStack;
60  public:
61   CodegenLLVM(llvm::Module *mod, Scopes *scopes, Scopes *proto_scopes);
62   virtual ~CodegenLLVM();
63 
64 #define VISIT(type, func) virtual STATUS_RETURN visit_##func(type* n);
65   EXPAND_NODES(VISIT)
66 #undef VISIT
67 
68   STATUS_RETURN visit(Node *n, TableStorage &ts, const std::string &id,
69                       const std::string &maps_ns);
70 
71   int get_table_fd(const std::string &name) const;
72 
73  private:
74   STATUS_RETURN emit_short_circuit_and(BinopExprNode* n);
75   STATUS_RETURN emit_short_circuit_or(BinopExprNode* n);
76   STATUS_RETURN emit_table_lookup(MethodCallExprNode* n);
77   STATUS_RETURN emit_table_update(MethodCallExprNode* n);
78   STATUS_RETURN emit_table_delete(MethodCallExprNode* n);
79   STATUS_RETURN emit_log(MethodCallExprNode* n);
80   STATUS_RETURN emit_packet_rewrite_field(MethodCallExprNode* n);
81   STATUS_RETURN emit_atomic_add(MethodCallExprNode* n);
82   STATUS_RETURN emit_cksum(MethodCallExprNode* n);
83   STATUS_RETURN emit_incr_cksum(MethodCallExprNode* n, size_t sz = 0);
84   STATUS_RETURN emit_lb_hash(MethodCallExprNode* n);
85   STATUS_RETURN emit_sizeof(MethodCallExprNode* n);
86   STATUS_RETURN emit_get_usec_time(MethodCallExprNode* n);
87   STATUS_RETURN emit_forward_to_vnf(MethodCallExprNode* n);
88   STATUS_RETURN emit_forward_to_group(MethodCallExprNode* n);
89   STATUS_RETURN print_header();
90 
91   llvm::LLVMContext & ctx() const;
92   llvm::Constant * const_int(uint64_t val, unsigned bits = 64, bool is_signed = false);
93   llvm::Value * pop_expr();
94   llvm::BasicBlock * resolve_label(const string &label);
95   llvm::Instruction * resolve_entry_stack();
96   llvm::AllocaInst *make_alloca(llvm::Instruction *Inst, llvm::Type *Ty,
97                                 const std::string &name = "",
98                                 llvm::Value *ArraySize = nullptr);
99   llvm::AllocaInst *make_alloca(llvm::BasicBlock *BB, llvm::Type *Ty,
100                                 const std::string &name = "",
101                                 llvm::Value *ArraySize = nullptr);
102   StatusTuple lookup_var(Node *n, const std::string &name, Scopes::VarScope *scope,
103                          VariableDeclStmtNode **decl, llvm::Value **mem) const;
104   StatusTuple lookup_struct_type(StructDeclStmtNode *decl, llvm::StructType **stype) const;
105   StatusTuple lookup_struct_type(VariableDeclStmtNode *n, llvm::StructType **stype,
106                                  StructDeclStmtNode **decl = nullptr) const;
107 
108   template <typename... Args> void emit(const char *fmt, Args&&... params);
109   void emit(const char *s);
110 
111   FILE* out_;
112   llvm::Module* mod_;
113   llvm::IRBuilderBase *b_;
114   int indent_;
115   int tmp_reg_index_;
116   Scopes *scopes_;
117   Scopes *proto_scopes_;
118   vector<vector<string> > free_instructions_;
119   vector<string> table_inits_;
120   map<string, string> proto_rewrites_;
121   map<TableDeclStmtNode *, llvm::GlobalVariable *> tables_;
122   map<TableDeclStmtNode *, int> table_fds_;
123   map<VariableDeclStmtNode *, llvm::Value *> vars_;
124   map<StructDeclStmtNode *, llvm::StructType *> structs_;
125   map<string, llvm::BasicBlock *> labels_;
126   llvm::SwitchInst *cur_switch_;
127   llvm::Value *expr_;
128   llvm::AllocaInst *retval_;
129   llvm::AllocaInst *errval_;
130 };
131 
132 }  // namespace cc
133 }  // namespace ebpf
134