]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/perf/util/c++/clang.cpp
perf clang: Add builtin clang support ant test case
[karo-tx-linux.git] / tools / perf / util / c++ / clang.cpp
1 /*
2  * llvm C frontend for perf. Support dynamically compile C file
3  *
4  * Inspired by clang example code:
5  * http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp
6  *
7  * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
8  * Copyright (C) 2016 Huawei Inc.
9  */
10
11 #include "clang/CodeGen/CodeGenAction.h"
12 #include "clang/Frontend/CompilerInvocation.h"
13 #include "clang/Frontend/CompilerInstance.h"
14 #include "clang/Frontend/TextDiagnosticPrinter.h"
15 #include "clang/Tooling/Tooling.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/Option/Option.h"
18 #include "llvm/Support/ManagedStatic.h"
19 #include <memory>
20
21 #include "clang.h"
22 #include "clang-c.h"
23
24 namespace perf {
25
26 static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
27
28 using namespace clang;
29
30 static vfs::InMemoryFileSystem *
31 buildVFS(StringRef& Name, StringRef& Content)
32 {
33         vfs::InMemoryFileSystem *VFS = new vfs::InMemoryFileSystem(true);
34         VFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
35         return VFS;
36 }
37
38 static CompilerInvocation *
39 createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
40 {
41         llvm::opt::ArgStringList CCArgs {
42                 "-cc1",
43                 "-triple", "bpf-pc-linux",
44                 "-fsyntax-only",
45                 "-ferror-limit", "19",
46                 "-fmessage-length", "127",
47                 "-O2",
48                 "-nostdsysteminc",
49                 "-nobuiltininc",
50                 "-vectorize-loops",
51                 "-vectorize-slp",
52                 "-Wno-unused-value",
53                 "-Wno-pointer-sign",
54                 "-x", "c"};
55         CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
56
57         FrontendOptions& Opts = CI->getFrontendOpts();
58         Opts.Inputs.clear();
59         Opts.Inputs.emplace_back(Path, IK_C);
60         return CI;
61 }
62
63 std::unique_ptr<llvm::Module>
64 getModuleFromSource(StringRef Name, StringRef Content)
65 {
66         CompilerInstance Clang;
67         Clang.createDiagnostics();
68
69         IntrusiveRefCntPtr<vfs::FileSystem> VFS = buildVFS(Name, Content);
70         Clang.setVirtualFileSystem(&*VFS);
71
72         IntrusiveRefCntPtr<CompilerInvocation> CI =
73                 createCompilerInvocation(Name, Clang.getDiagnostics());
74         Clang.setInvocation(&*CI);
75
76         std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
77         if (!Clang.ExecuteAction(*Act))
78                 return std::unique_ptr<llvm::Module>(nullptr);
79
80         return Act->takeModule();
81 }
82
83 }
84
85 extern "C" {
86 void perf_clang__init(void)
87 {
88         perf::LLVMCtx.reset(new llvm::LLVMContext());
89 }
90
91 void perf_clang__cleanup(void)
92 {
93         perf::LLVMCtx.reset(nullptr);
94         llvm::llvm_shutdown();
95 }
96 }