Commit | Line | Data |
---|---|---|
00b86691 WN |
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 | } |