diff options
author | Wang Nan <wangnan0@huawei.com> | 2016-11-26 02:03:38 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-12-05 13:51:44 -0500 |
commit | 5e08a76525b8f5e9aeb8b27d0466614abec070a9 (patch) | |
tree | 9b63f3b0fb1c35248e51c4b4f2aadf3ab68db6aa | |
parent | e67d52d411c3562263735479db2efd2ebd178db9 (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.c | 6 | ||||
-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 |
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 |
36 | int test__clang(int i __maybe_unused) | 40 | int 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); | |||
9 | extern void perf_clang__cleanup(void); | 9 | extern void perf_clang__cleanup(void); |
10 | 10 | ||
11 | extern int test__clang_to_IR(void); | 11 | extern int test__clang_to_IR(void); |
12 | extern 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 | ||
16 | extern "C" { | 16 | static std::unique_ptr<llvm::Module> |
17 | 17 | __test__clang_to_IR(void) | |
18 | int 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 | |||
34 | extern "C" { | ||
35 | int 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 | ||
48 | int 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 | ||
113 | std::unique_ptr<llvm::SmallVectorImpl<char>> | ||
114 | getBPFObjectFromModule(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 | ||
110 | extern "C" { | 151 | extern "C" { |
111 | void perf_clang__init(void) | 152 | void 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 | ||
116 | void perf_clang__cleanup(void) | 161 | 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> | |||
19 | getModuleFromSource(opt::ArgStringList CFlags, | 19 | getModuleFromSource(opt::ArgStringList CFlags, |
20 | StringRef Path); | 20 | StringRef Path); |
21 | 21 | ||
22 | std::unique_ptr<llvm::SmallVectorImpl<char>> | ||
23 | getBPFObjectFromModule(llvm::Module *Module); | ||
24 | |||
22 | } | 25 | } |
23 | #endif | 26 | #endif |