blob: 6cb200ac02c4243e06d63663bc82f6e2f4fcc7f6 [file] [log] [blame]
// Generated by llvm2cpp - DO NOT MODIFY!
#include <algorithm>
#include <map>
#include <string>
#include <llvm/ADT/STLExtras.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/IR/IRPrintingPasses.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Object/ObjectFile.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include "exception.h"
#include "parser.h"
#include "type_check.h"
#include "codegen_llvm.h"
#include "bpf_program.h"
namespace ebpf {
using std::get;
using std::make_tuple;
using std::map;
using std::move;
using std::string;
using std::tuple;
using std::unique_ptr;
using namespace llvm;
// Snooping class to remember the sections as the JIT creates them
class MyMemoryManager : public SectionMemoryManager {
public:
explicit MyMemoryManager(map<string, tuple<uint8_t *, uintptr_t>> *sections)
: sections_(sections) {
}
virtual ~MyMemoryManager() {}
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
StringRef SectionName) override {
uint8_t *Addr = SectionMemoryManager::allocateCodeSection(Size, Alignment, SectionID, SectionName);
//printf("allocateCodeSection: %s Addr %p Size %ld Alignment %d SectionID %d\n",
// SectionName.str().c_str(), (void *)Addr, Size, Alignment, SectionID);
(*sections_)[SectionName.str()] = make_tuple(Addr, Size);
return Addr;
}
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
bool isReadOnly) override {
uint8_t *Addr = SectionMemoryManager::allocateDataSection(Size, Alignment, SectionID, SectionName, isReadOnly);
//printf("allocateDataSection: %s Addr %p Size %ld Alignment %d SectionID %d RO %d\n",
// SectionName.str().c_str(), (void *)Addr, Size, Alignment, SectionID, isReadOnly);
(*sections_)[SectionName.str()] = make_tuple(Addr, Size);
return Addr;
}
map<string, tuple<uint8_t *, uintptr_t>> *sections_;
};
BPFProgram::BPFProgram(unsigned flags)
: flags_(flags) {
LLVMInitializeBPFTarget();
LLVMInitializeBPFTargetMC();
LLVMInitializeBPFTargetInfo();
LLVMInitializeBPFAsmPrinter();
LLVMLinkInMCJIT(); /* call empty function to force linking of MCJIT */
}
BPFProgram::~BPFProgram() {
engine_.reset();
LLVMShutdown();
}
int BPFProgram::parse() {
int rc;
proto_parser_ = make_unique<ebpf::cc::Parser>(proto_filename_);
rc = proto_parser_->parse();
if (rc) return rc;
parser_ = make_unique<ebpf::cc::Parser>(filename_);
rc = parser_->parse();
if (rc) return rc;
//ebpf::cc::Printer printer(stderr);
//printer.visit(parser_->root_node_);
ebpf::cc::TypeCheck type_check(parser_->scopes_.get(), proto_parser_->scopes_.get(), parser_->pragmas_);
auto ret = type_check.visit(parser_->root_node_);
if (get<0>(ret) != 0 || get<1>(ret).size()) {
fprintf(stderr, "Type error @line=%d: %s\n", get<0>(ret), get<1>(ret).c_str());
exit(1);
}
codegen_ = ebpf::make_unique<ebpf::cc::CodegenLLVM>(mod_, parser_->scopes_.get(),
proto_parser_->scopes_.get(),
/*use_pre_header*/false,
parser_->pragma("name"));
ret = codegen_->visit(parser_->root_node_);
if (get<0>(ret) != 0 || get<1>(ret).size()) {
fprintf(stderr, "Codegen error @line=%d: %s\n", get<0>(ret), get<1>(ret).c_str());
return get<0>(ret);
}
return 0;
}
string BPFProgram::load_helper() const {
// generated from bitops.cc -> bitops.bc -> hexdump -> bitops.h
#include "cc/bitops.h"
return string((const char *)bitops_bc, bitops_bc_len);
}
// Load in a pre-built list of functions into the initial Module object, then
// build an ExecutionEngine.
int BPFProgram::init_engine() {
SMDiagnostic diag;
string helper = load_helper();
MemoryBufferRef helper_mem(helper, "helper");
unique_ptr<Module> mod = parseIR(helper_mem, diag, getGlobalContext());
if (!mod) {
diag.print("bitops", errs());
exit(1);
}
mod_ = mod.get();
mod_->setDataLayout("e-m:e-i64:64-f80:128-n8:16:32:64-S128");
mod_->setTargetTriple("bpf");
for (auto fn = mod_->getFunctionList().begin(); fn != mod_->getFunctionList().end(); ++fn)
fn->addFnAttr(Attribute::AlwaysInline);
string err;
engine_ = unique_ptr<ExecutionEngine>(EngineBuilder(move(mod))
.setErrorStr(&err)
.setMCJITMemoryManager(make_unique<MyMemoryManager>(&sections_))
.setMArch("bpf")
.create());
if (!engine_) {
fprintf(stderr, "Could not create ExecutionEngine: %s\n", err.c_str());
return -1;
}
return 0;
}
void BPFProgram::dump_ir() {
legacy::PassManager PM;
PM.add(createPrintModulePass(outs()));
PM.run(*mod_);
}
int BPFProgram::finalize() {
if (verifyModule(*mod_, &errs())) {
if (flags_ & 1)
dump_ir();
return -1;
}
legacy::PassManager PM;
PassManagerBuilder PMB;
PMB.OptLevel = 3;
PM.add(createFunctionInliningPass());
PM.add(createAlwaysInlinerPass());
PMB.populateModulePassManager(PM);
if (flags_ & 1)
PM.add(createPrintModulePass(outs()));
PM.run(*mod_);
engine_->finalizeObject();
return 0;
}
uint8_t * BPFProgram::start(const string &name) const {
auto section = sections_.find(name);
if (section == sections_.end())
return nullptr;
return get<0>(section->second);
}
size_t BPFProgram::size(const string &name) const {
auto section = sections_.find(name);
if (section == sections_.end())
return 0;
return get<1>(section->second);
}
char * BPFProgram::license() const {
auto section = sections_.find("license");
if (section == sections_.end())
return nullptr;
return (char *)get<0>(section->second);
}
int BPFProgram::table_fd(const string &name) const {
return codegen_->get_table_fd(name);
}
int BPFProgram::load(const string &filename, const string &proto_filename) {
if (!sections_.empty()) {
fprintf(stderr, "Program already initialized\n");
return -1;
}
filename_ = filename;
proto_filename_ = proto_filename;
if (int rc = init_engine())
return rc;
if (int rc = parse())
return rc;
if (int rc = finalize())
return rc;
return 0;
}
} // namespace ebpf