Commit 2b2161f0 authored by Brenden Blanco's avatar Brenden Blanco

Move rest of frontend implementation into subdirs

Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent d710bd7b
...@@ -25,21 +25,6 @@ ...@@ -25,21 +25,6 @@
#include <vector> #include <vector>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/CodeGen/BackendUtil.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Driver/Job.h>
#include <clang/Driver/Tool.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Frontend/FrontendDiagnostic.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/FrontendTool/Utils.h>
#include <llvm/ADT/STLExtras.h> #include <llvm/ADT/STLExtras.h>
#include <llvm/ExecutionEngine/MCJIT.h> #include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h> #include <llvm/ExecutionEngine/SectionMemoryManager.h>
...@@ -58,6 +43,7 @@ ...@@ -58,6 +43,7 @@
#include "exception.h" #include "exception.h"
#include "frontends/b/loader.h" #include "frontends/b/loader.h"
#include "frontends/clang/loader.h"
#include "frontends/clang/b_frontend_action.h" #include "frontends/clang/b_frontend_action.h"
#include "bpf_module.h" #include "bpf_module.h"
#include "kbuild_helper.h" #include "kbuild_helper.h"
...@@ -121,134 +107,11 @@ BPFModule::~BPFModule() { ...@@ -121,134 +107,11 @@ BPFModule::~BPFModule() {
ctx_.reset(); ctx_.reset();
} }
int BPFModule::load_file_module(unique_ptr<llvm::Module> *mod, const string &file, bool in_memory) {
using namespace clang;
struct utsname un;
uname(&un);
char kdir[256];
snprintf(kdir, sizeof(kdir), "%s/%s/build", KERNEL_MODULES_DIR, un.release);
// clang needs to run inside the kernel dir
DirStack dstack(kdir);
if (!dstack.ok())
return -1;
string abs_file;
if (in_memory) {
abs_file = "<bcc-memory-buffer>";
} else {
if (file.substr(0, 1) == "/")
abs_file = file;
else
abs_file = string(dstack.cwd()) + "/" + file;
}
vector<const char *> flags_cstr({"-O0", "-emit-llvm", "-I", dstack.cwd(),
"-Wno-deprecated-declarations",
"-x", "c", "-c", abs_file.c_str()});
KBuildHelper kbuild_helper;
vector<string> kflags;
if (kbuild_helper.get_flags(un.release, &kflags))
return -1;
kflags.push_back("-include");
kflags.push_back(BCC_INSTALL_PREFIX "/share/bcc/include/bcc/helpers.h");
kflags.push_back("-I");
kflags.push_back(BCC_INSTALL_PREFIX "/share/bcc/include");
for (auto it = kflags.begin(); it != kflags.end(); ++it)
flags_cstr.push_back(it->c_str());
// set up the error reporting class
IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions());
auto diag_client = new TextDiagnosticPrinter(llvm::errs(), &*diag_opts);
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
DiagnosticsEngine diags(DiagID, &*diag_opts, diag_client);
// set up the command line argument wrapper
driver::Driver drv("", "x86_64-unknown-linux-gnu", diags);
drv.setTitle("bcc-clang-driver");
drv.setCheckInputsExist(false);
unique_ptr<driver::Compilation> compilation(drv.BuildCompilation(flags_cstr));
if (!compilation)
return -1;
// expect exactly 1 job, otherwise error
const driver::JobList &jobs = compilation->getJobs();
if (jobs.size() != 1 || !isa<driver::Command>(*jobs.begin())) {
SmallString<256> msg;
llvm::raw_svector_ostream os(msg);
jobs.Print(os, "; ", true);
diags.Report(diag::err_fe_expected_compiler_job) << os.str();
return -1;
}
const driver::Command &cmd = cast<driver::Command>(*jobs.begin());
if (llvm::StringRef(cmd.getCreator().getName()) != "clang") {
diags.Report(diag::err_fe_expected_clang_command);
return -1;
}
// Initialize a compiler invocation object from the clang (-cc1) arguments.
const driver::ArgStringList &ccargs = cmd.getArguments();
// first pass
auto invocation1 = make_unique<CompilerInvocation>();
if (!CompilerInvocation::CreateFromArgs(*invocation1, const_cast<const char **>(ccargs.data()),
const_cast<const char **>(ccargs.data()) + ccargs.size(), diags))
return -1;
if (in_memory) {
invocation1->getPreprocessorOpts().addRemappedFile("<bcc-memory-buffer>",
llvm::MemoryBuffer::getMemBuffer(file).release());
invocation1->getFrontendOpts().Inputs.clear();
invocation1->getFrontendOpts().Inputs.push_back(FrontendInputFile("<bcc-memory-buffer>", IK_C));
}
invocation1->getFrontendOpts().DisableFree = false;
CompilerInstance compiler1;
compiler1.setInvocation(invocation1.release());
compiler1.createDiagnostics();
// capture the rewritten c file
string out_str;
llvm::raw_string_ostream os(out_str);
BFrontendAction bact(os);
if (!compiler1.ExecuteAction(bact))
return -1;
// this contains the open FDs
tables_ = bact.take_tables();
// second pass, clear input and take rewrite buffer
auto invocation2 = make_unique<CompilerInvocation>();
if (!CompilerInvocation::CreateFromArgs(*invocation2, const_cast<const char **>(ccargs.data()),
const_cast<const char **>(ccargs.data()) + ccargs.size(), diags))
return -1;
CompilerInstance compiler2;
invocation2->getPreprocessorOpts().addRemappedFile("<bcc-memory-buffer>",
llvm::MemoryBuffer::getMemBuffer(out_str).release());
invocation2->getFrontendOpts().Inputs.clear();
invocation2->getFrontendOpts().Inputs.push_back(FrontendInputFile("<bcc-memory-buffer>", IK_C));
invocation2->getFrontendOpts().DisableFree = false;
// suppress warnings in the 2nd pass, but bail out on errors (our fault)
invocation2->getDiagnosticOpts().IgnoreWarnings = true;
compiler2.setInvocation(invocation2.release());
compiler2.createDiagnostics();
EmitLLVMOnlyAction ir_act(&*ctx_);
if (!compiler2.ExecuteAction(ir_act))
return -1;
*mod = ir_act.takeModule();
return 0;
}
// load an entire c file as a module // load an entire c file as a module
int BPFModule::load_cfile(const string &file, bool in_memory) { int BPFModule::load_cfile(const string &file, bool in_memory) {
clang_loader_ = make_unique<ClangLoader>(&*ctx_);
unique_ptr<Module> mod; unique_ptr<Module> mod;
if (load_file_module(&mod, file, in_memory)) if (clang_loader_->parse(&mod, &tables_, file, in_memory))
return -1; return -1;
mod_ = &*mod; mod_ = &*mod;
...@@ -278,8 +141,9 @@ int BPFModule::load_cfile(const string &file, bool in_memory) { ...@@ -278,8 +141,9 @@ int BPFModule::load_cfile(const string &file, bool in_memory) {
// Load in a pre-built list of functions into the initial Module object, then // Load in a pre-built list of functions into the initial Module object, then
// build an ExecutionEngine. // build an ExecutionEngine.
int BPFModule::load_includes(const string &tmpfile) { int BPFModule::load_includes(const string &tmpfile) {
clang_loader_ = make_unique<ClangLoader>(&*ctx_);
unique_ptr<Module> mod; unique_ptr<Module> mod;
if (load_file_module(&mod, tmpfile, false)) if (clang_loader_->parse(&mod, &tables_, tmpfile, false))
return -1; return -1;
mod_ = &*mod; mod_ = &*mod;
......
...@@ -31,6 +31,7 @@ class Module; ...@@ -31,6 +31,7 @@ class Module;
namespace ebpf { namespace ebpf {
class BPFTable; class BPFTable;
class BLoader; class BLoader;
class ClangLoader;
class BPFModule { class BPFModule {
private: private:
...@@ -73,6 +74,7 @@ class BPFModule { ...@@ -73,6 +74,7 @@ class BPFModule {
std::unique_ptr<llvm::ExecutionEngine> engine_; std::unique_ptr<llvm::ExecutionEngine> engine_;
llvm::Module *mod_; llvm::Module *mod_;
std::unique_ptr<BLoader> b_loader_; std::unique_ptr<BLoader> b_loader_;
std::unique_ptr<ClangLoader> clang_loader_;
std::map<std::string, std::tuple<uint8_t *, uintptr_t>> sections_; std::map<std::string, std::tuple<uint8_t *, uintptr_t>> sections_;
std::unique_ptr<std::map<std::string, BPFTable>> tables_; std::unique_ptr<std::map<std::string, BPFTable>> tables_;
std::vector<std::string> table_names_; std::vector<std::string> table_names_;
......
/*
* 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 <memory>
#include <string>
#include <tuple>
namespace ebpf {
template <class T, class... Args>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Args &&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
typedef std::tuple<int, std::string> StatusTuple;
} // namespace ebpf
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
#pragma once
#include <string> #include <string>
namespace llvm { namespace llvm {
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <memory> #include <memory>
#include <algorithm> #include <algorithm>
#include <stdint.h> #include <stdint.h>
#include "common.h"
#include "scope.h" #include "scope.h"
#define REVISION_MASK 0xfff #define REVISION_MASK 0xfff
...@@ -41,14 +43,6 @@ ...@@ -41,14 +43,6 @@
namespace ebpf { namespace ebpf {
template <class T, class... Args>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Args &&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
typedef std::tuple<int, std::string> StatusTuple;
namespace cc { namespace cc {
using std::unique_ptr; using std::unique_ptr;
......
# Copyright (c) PLUMgrid, Inc. # Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License") # Licensed under the Apache License, Version 2.0 (the "License")
add_library(clang_frontend b_frontend_action.cc kbuild_helper.cc) add_library(clang_frontend loader.cc b_frontend_action.cc kbuild_helper.cc)
...@@ -14,9 +14,59 @@ ...@@ -14,9 +14,59 @@
* limitations under the License. * limitations under the License.
*/ */
#include <map>
#include <string>
#include <algorithm>
#include <fcntl.h>
#include <ftw.h>
#include <map>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <vector>
#include <linux/bpf.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/CodeGen/BackendUtil.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Driver/Job.h>
#include <clang/Driver/Tool.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Frontend/FrontendDiagnostic.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/FrontendTool/Utils.h>
#include <llvm/IR/Module.h>
#include "common.h"
#include "exception.h"
#include "kbuild_helper.h"
#include "b_frontend_action.h"
#include "loader.h"
using std::map;
using std::string;
using std::unique_ptr;
using std::vector;
namespace ebpf { namespace ebpf {
int Loader::load_file_module(unique_ptr<llvm::Module> *mod, const string &file, bool in_memory) { ClangLoader::ClangLoader(llvm::LLVMContext *ctx)
: ctx_(ctx)
{}
ClangLoader::~ClangLoader() {}
int ClangLoader::parse(unique_ptr<llvm::Module> *mod,
unique_ptr<map<string, BPFTable>> *tables,
const string &file, bool in_memory) {
using namespace clang; using namespace clang;
struct utsname un; struct utsname un;
...@@ -114,7 +164,7 @@ int Loader::load_file_module(unique_ptr<llvm::Module> *mod, const string &file, ...@@ -114,7 +164,7 @@ int Loader::load_file_module(unique_ptr<llvm::Module> *mod, const string &file,
if (!compiler1.ExecuteAction(bact)) if (!compiler1.ExecuteAction(bact))
return -1; return -1;
// this contains the open FDs // this contains the open FDs
tables_ = bact.take_tables(); *tables = bact.take_tables();
// second pass, clear input and take rewrite buffer // second pass, clear input and take rewrite buffer
auto invocation2 = make_unique<CompilerInvocation>(); auto invocation2 = make_unique<CompilerInvocation>();
......
...@@ -14,14 +14,21 @@ ...@@ -14,14 +14,21 @@
* limitations under the License. * limitations under the License.
*/ */
#pragma once
#include <map>
#include <memory>
#include <string> #include <string>
namespace llvm { namespace llvm {
class Module; class Module;
class LLVMContext;
} }
namespace ebpf { namespace ebpf {
class BPFTable;
namespace cc { namespace cc {
class Parser; class Parser;
class CodegenLLVM; class CodegenLLVM;
...@@ -29,11 +36,13 @@ class CodegenLLVM; ...@@ -29,11 +36,13 @@ class CodegenLLVM;
class ClangLoader { class ClangLoader {
public: public:
ClangLoader(); explicit ClangLoader(llvm::LLVMContext *ctx);
~ClangLoader(); ~ClangLoader();
int parse(llvm::Module *mod, const std::string &filename, const std::string &proto_filename); int parse(std::unique_ptr<llvm::Module> *mod,
int get_table_fd(const std::string &name) const; std::unique_ptr<std::map<std::string, BPFTable>> *tables,
const std::string &file, bool in_memory);
private: private:
llvm::LLVMContext *ctx_;
}; };
} // namespace ebpf } // namespace ebpf
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment