diff options
Diffstat (limited to 'tools/perf/util/c++')
-rw-r--r-- | tools/perf/util/c++/clang-c.h | 1 | ||||
-rw-r--r-- | tools/perf/util/c++/clang-test.cpp | 31 | ||||
-rw-r--r-- | tools/perf/util/c++/clang.cpp | 45 | ||||
-rw-r--r-- | tools/perf/util/c++/clang.h | 3 |
4 files changed, 74 insertions, 6 deletions
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h index dcde4b564f3b..22b3936d1f09 100644 --- a/tools/perf/util/c++/clang-c.h +++ b/tools/perf/util/c++/clang-c.h @@ -9,6 +9,7 @@ extern void perf_clang__init(void); extern void perf_clang__cleanup(void); extern int test__clang_to_IR(void); +extern int test__clang_to_obj(void); #ifdef __cplusplus } diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp index d84e760d2aab..9b11e8c82798 100644 --- a/tools/perf/util/c++/clang-test.cpp +++ b/tools/perf/util/c++/clang-test.cpp @@ -13,15 +13,13 @@ public: ~perf_clang_scope() {perf_clang__cleanup();} }; -extern "C" { - -int test__clang_to_IR(void) +static std::unique_ptr<llvm::Module> +__test__clang_to_IR(void) { - perf_clang_scope _scope; unsigned int kernel_version; if (fetch_kernel_version(&kernel_version, NULL, 0)) - return -1; + return std::unique_ptr<llvm::Module>(nullptr); std::string cflag_kver("-DLINUX_VERSION_CODE=" + std::to_string(kernel_version)); @@ -30,14 +28,35 @@ int test__clang_to_IR(void) perf::getModuleFromSource({cflag_kver.c_str()}, "perf-test.c", test_llvm__bpf_base_prog); + return M; +} + +extern "C" { +int test__clang_to_IR(void) +{ + perf_clang_scope _scope; + auto M = __test__clang_to_IR(); if (!M) return -1; - for (llvm::Function& F : *M) if (F.getName() == "bpf_func__SyS_epoll_wait") return 0; return -1; } +int test__clang_to_obj(void) +{ + perf_clang_scope _scope; + + auto M = __test__clang_to_IR(); + if (!M) + return -1; + + auto Buffer = perf::getBPFObjectFromModule(&*M); + if (!Buffer) + return -1; + return 0; +} + } diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp index 715ca0a3dee0..2a1a75df204f 100644 --- a/tools/perf/util/c++/clang.cpp +++ b/tools/perf/util/c++/clang.cpp @@ -13,10 +13,15 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Tooling/Tooling.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Option/Option.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include <memory> #include "clang.h" @@ -105,12 +110,52 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path) return getModuleFromSource(std::move(CFlags), Path, VFS); } +std::unique_ptr<llvm::SmallVectorImpl<char>> +getBPFObjectFromModule(llvm::Module *Module) +{ + using namespace llvm; + + std::string TargetTriple("bpf-pc-linux"); + std::string Error; + const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error); + if (!Target) { + llvm::errs() << Error; + return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr); + } + + llvm::TargetOptions Opt; + TargetMachine *TargetMachine = + Target->createTargetMachine(TargetTriple, + "generic", "", + Opt, Reloc::Static); + + Module->setDataLayout(TargetMachine->createDataLayout()); + Module->setTargetTriple(TargetTriple); + + std::unique_ptr<SmallVectorImpl<char>> Buffer(new SmallVector<char, 0>()); + raw_svector_ostream ostream(*Buffer); + + legacy::PassManager PM; + if (TargetMachine->addPassesToEmitFile(PM, ostream, + TargetMachine::CGFT_ObjectFile)) { + llvm::errs() << "TargetMachine can't emit a file of this type\n"; + return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);; + } + PM.run(*Module); + + return std::move(Buffer); +} + } extern "C" { void perf_clang__init(void) { perf::LLVMCtx.reset(new llvm::LLVMContext()); + LLVMInitializeBPFTargetInfo(); + LLVMInitializeBPFTarget(); + LLVMInitializeBPFTargetMC(); + LLVMInitializeBPFAsmPrinter(); } void perf_clang__cleanup(void) diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h index b4fc2a96b79d..dd8b0427550d 100644 --- a/tools/perf/util/c++/clang.h +++ b/tools/perf/util/c++/clang.h @@ -19,5 +19,8 @@ std::unique_ptr<Module> getModuleFromSource(opt::ArgStringList CFlags, StringRef Path); +std::unique_ptr<llvm::SmallVectorImpl<char>> +getBPFObjectFromModule(llvm::Module *Module); + } #endif |