lkml.org 
[lkml]   [2016]   [Nov]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 18/34] perf clang: Support compile IR to BPF object and add testcase
    Date
    getBPFObjectFromModule() is introduced to compile LLVM IR(Module)
    to BPF object. Add new testcase for it.

    Test result:
    $ ./buildperf/perf test -v clang
    51: Test builtin clang support :
    51.1: Test builtin clang compile C source to IR :
    --- start ---
    test child forked, pid 21822
    test child finished with 0
    ---- end ----
    Test builtin clang support subtest 0: Ok
    51.2: Test builtin clang compile C source to ELF object :
    --- start ---
    test child forked, pid 21823
    test child finished with 0
    ---- end ----
    Test builtin clang support subtest 1: Ok

    Signed-off-by: Wang Nan <wangnan0@huawei.com>
    Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Alexei Starovoitov <ast@fb.com>
    Cc: He Kuang <hekuang@huawei.com>
    Cc: Jiri Olsa <jolsa@kernel.org>
    Cc: Zefan Li <lizefan@huawei.com>
    Cc: pi3orama@163.com
    ---
    tools/perf/tests/clang.c | 6 ++++-
    tools/perf/util/c++/clang-c.h | 1 +
    tools/perf/util/c++/clang-test.cpp | 31 +++++++++++++++++++++-----
    tools/perf/util/c++/clang.cpp | 45 ++++++++++++++++++++++++++++++++++++++
    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 57ee160..2964c06 100644
    --- a/tools/perf/tests/clang.c
    +++ b/tools/perf/tests/clang.c
    @@ -12,6 +12,10 @@ static struct {
    .func = test__clang_to_IR,
    .desc = "Test builtin clang compile C source to IR",
    },
    + {
    + .func = test__clang_to_obj,
    + .desc = "Test builtin clang compile C source to ELF object",
    + },
    #endif
    };

    @@ -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;
    diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
    index dcde4b5..22b3936 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 d84e760..9b11e8c 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 715ca0a..2a1a75d 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 b4fc2a9..dd8b042 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
    --
    2.10.1
    \
     
     \ /
      Last update: 2016-11-15 05:13    [W:2.671 / U:0.292 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site