Skip to content

Commit

Permalink
perf clang: Support compile IR to BPF object and add testcase
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Alexei Starovoitov <[email protected]>
Cc: He Kuang <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Joe Stringer <[email protected]>
Cc: Zefan Li <[email protected]>
Cc: [email protected]
Link: http://lkml.kernel.org/r/[email protected]
[ Remove redundant "Test" from entry descriptions ]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
WangNan0 authored and acmel committed Dec 5, 2016
1 parent e67d52d commit 5e08a76
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 7 deletions.
6 changes: 5 additions & 1 deletion tools/perf/tests/clang.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ static struct {
.func = test__clang_to_IR,
.desc = "builtin clang compile C source to IR",
},
{
.func = test__clang_to_obj,
.desc = "builtin clang compile C source to ELF object",
},
#endif
};

Expand All @@ -33,7 +37,7 @@ int test__clang(int i __maybe_unused)
return TEST_SKIP;
}
#else
int test__clang(int i __maybe_unused)
int test__clang(int i)
{
if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
return TEST_FAIL;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/c++/clang-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
31 changes: 25 additions & 6 deletions tools/perf/util/c++/clang-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ class perf_clang_scope {
~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));
Expand All @@ -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;
}

}
45 changes: 45 additions & 0 deletions tools/perf/util/c++/clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions tools/perf/util/c++/clang.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 5e08a76

Please sign in to comment.