aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2016-11-26 02:03:38 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-12-05 13:51:44 -0500
commit5e08a76525b8f5e9aeb8b27d0466614abec070a9 (patch)
tree9b63f3b0fb1c35248e51c4b4f2aadf3ab68db6aa
parente67d52d411c3562263735479db2efd2ebd178db9 (diff)
perf clang: Support compile IR to BPF object and add testcase
getBPFObjectFromModule() is introduced to compile LLVM IR(Module) to BPF object. Add new testcase for it. Test result: $ ./buildperf/perf test -v clang 51: builtin clang support : 51.1: builtin clang compile C source to IR : --- start --- test child forked, pid 21822 test child finished with 0 ---- end ---- builtin clang support subtest 0: Ok 51.2: builtin clang compile C source to ELF object : --- start --- test child forked, pid 21823 test child finished with 0 ---- end ---- builtin clang support subtest 1: Ok Signed-off-by: Wang Nan <wangnan0@huawei.com> Cc: Alexei Starovoitov <ast@fb.com> Cc: He Kuang <hekuang@huawei.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Joe Stringer <joe@ovn.org> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-15-wangnan0@huawei.com [ Remove redundant "Test" from entry descriptions ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/tests/clang.c6
-rw-r--r--tools/perf/util/c++/clang-c.h1
-rw-r--r--tools/perf/util/c++/clang-test.cpp31
-rw-r--r--tools/perf/util/c++/clang.cpp45
-rw-r--r--tools/perf/util/c++/clang.h3
5 files changed, 79 insertions, 7 deletions
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index 636d6d0e9037..f853e242a86c 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -12,6 +12,10 @@ static struct {
12 .func = test__clang_to_IR, 12 .func = test__clang_to_IR,
13 .desc = "builtin clang compile C source to IR", 13 .desc = "builtin clang compile C source to IR",
14 }, 14 },
15 {
16 .func = test__clang_to_obj,
17 .desc = "builtin clang compile C source to ELF object",
18 },
15#endif 19#endif
16}; 20};
17 21
@@ -33,7 +37,7 @@ int test__clang(int i __maybe_unused)
33 return TEST_SKIP; 37 return TEST_SKIP;
34} 38}
35#else 39#else
36int test__clang(int i __maybe_unused) 40int test__clang(int i)
37{ 41{
38 if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table)) 42 if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
39 return TEST_FAIL; 43 return TEST_FAIL;
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);
9extern void perf_clang__cleanup(void); 9extern void perf_clang__cleanup(void);
10 10
11extern int test__clang_to_IR(void); 11extern int test__clang_to_IR(void);
12extern int test__clang_to_obj(void);
12 13
13#ifdef __cplusplus 14#ifdef __cplusplus
14} 15}
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:
13 ~perf_clang_scope() {perf_clang__cleanup();} 13 ~perf_clang_scope() {perf_clang__cleanup();}
14}; 14};
15 15
16extern "C" { 16static std::unique_ptr<llvm::Module>
17 17__test__clang_to_IR(void)
18int test__clang_to_IR(void)
19{ 18{
20 perf_clang_scope _scope;
21 unsigned int kernel_version; 19 unsigned int kernel_version;
22 20
23 if (fetch_kernel_version(&kernel_version, NULL, 0)) 21 if (fetch_kernel_version(&kernel_version, NULL, 0))
24 return -1; 22 return std::unique_ptr<llvm::Module>(nullptr);
25 23
26 std::string cflag_kver("-DLINUX_VERSION_CODE=" + 24 std::string cflag_kver("-DLINUX_VERSION_CODE=" +
27 std::to_string(kernel_version)); 25 std::to_string(kernel_version));
@@ -30,14 +28,35 @@ int test__clang_to_IR(void)
30 perf::getModuleFromSource({cflag_kver.c_str()}, 28 perf::getModuleFromSource({cflag_kver.c_str()},
31 "perf-test.c", 29 "perf-test.c",
32 test_llvm__bpf_base_prog); 30 test_llvm__bpf_base_prog);
31 return M;
32}
33
34extern "C" {
35int test__clang_to_IR(void)
36{
37 perf_clang_scope _scope;
33 38
39 auto M = __test__clang_to_IR();
34 if (!M) 40 if (!M)
35 return -1; 41 return -1;
36
37 for (llvm::Function& F : *M) 42 for (llvm::Function& F : *M)
38 if (F.getName() == "bpf_func__SyS_epoll_wait") 43 if (F.getName() == "bpf_func__SyS_epoll_wait")
39 return 0; 44 return 0;
40 return -1; 45 return -1;
41} 46}
42 47
48int test__clang_to_obj(void)
49{
50 perf_clang_scope _scope;
51
52 auto M = __test__clang_to_IR();
53 if (!M)
54 return -1;
55
56 auto Buffer = perf::getBPFObjectFromModule(&*M);
57 if (!Buffer)
58 return -1;
59 return 0;
60}
61
43} 62}
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 @@
13#include "clang/Frontend/CompilerInstance.h" 13#include "clang/Frontend/CompilerInstance.h"
14#include "clang/Frontend/TextDiagnosticPrinter.h" 14#include "clang/Frontend/TextDiagnosticPrinter.h"
15#include "clang/Tooling/Tooling.h" 15#include "clang/Tooling/Tooling.h"
16#include "llvm/IR/LegacyPassManager.h"
16#include "llvm/IR/Module.h" 17#include "llvm/IR/Module.h"
17#include "llvm/Option/Option.h" 18#include "llvm/Option/Option.h"
18#include "llvm/Support/FileSystem.h" 19#include "llvm/Support/FileSystem.h"
19#include "llvm/Support/ManagedStatic.h" 20#include "llvm/Support/ManagedStatic.h"
21#include "llvm/Support/TargetRegistry.h"
22#include "llvm/Support/TargetSelect.h"
23#include "llvm/Target/TargetMachine.h"
24#include "llvm/Target/TargetOptions.h"
20#include <memory> 25#include <memory>
21 26
22#include "clang.h" 27#include "clang.h"
@@ -105,12 +110,52 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
105 return getModuleFromSource(std::move(CFlags), Path, VFS); 110 return getModuleFromSource(std::move(CFlags), Path, VFS);
106} 111}
107 112
113std::unique_ptr<llvm::SmallVectorImpl<char>>
114getBPFObjectFromModule(llvm::Module *Module)
115{
116 using namespace llvm;
117
118 std::string TargetTriple("bpf-pc-linux");
119 std::string Error;
120 const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error);
121 if (!Target) {
122 llvm::errs() << Error;
123 return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);
124 }
125
126 llvm::TargetOptions Opt;
127 TargetMachine *TargetMachine =
128 Target->createTargetMachine(TargetTriple,
129 "generic", "",
130 Opt, Reloc::Static);
131
132 Module->setDataLayout(TargetMachine->createDataLayout());
133 Module->setTargetTriple(TargetTriple);
134
135 std::unique_ptr<SmallVectorImpl<char>> Buffer(new SmallVector<char, 0>());
136 raw_svector_ostream ostream(*Buffer);
137
138 legacy::PassManager PM;
139 if (TargetMachine->addPassesToEmitFile(PM, ostream,
140 TargetMachine::CGFT_ObjectFile)) {
141 llvm::errs() << "TargetMachine can't emit a file of this type\n";
142 return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
143 }
144 PM.run(*Module);
145
146 return std::move(Buffer);
147}
148
108} 149}
109 150
110extern "C" { 151extern "C" {
111void perf_clang__init(void) 152void perf_clang__init(void)
112{ 153{
113 perf::LLVMCtx.reset(new llvm::LLVMContext()); 154 perf::LLVMCtx.reset(new llvm::LLVMContext());
155 LLVMInitializeBPFTargetInfo();
156 LLVMInitializeBPFTarget();
157 LLVMInitializeBPFTargetMC();
158 LLVMInitializeBPFAsmPrinter();
114} 159}
115 160
116void perf_clang__cleanup(void) 161void 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>
19getModuleFromSource(opt::ArgStringList CFlags, 19getModuleFromSource(opt::ArgStringList CFlags,
20 StringRef Path); 20 StringRef Path);
21 21
22std::unique_ptr<llvm::SmallVectorImpl<char>>
23getBPFObjectFromModule(llvm::Module *Module);
24
22} 25}
23#endif 26#endif