blob: cf96199b4b6f4e20e1235bb6f87b6f7745538c0d [file] [log] [blame]
Wang Nan00b86692016-11-26 07:03:34 +00001/*
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"
Wang Nan77dfa842016-11-26 07:03:35 +000018#include "llvm/Support/FileSystem.h"
Wang Nan00b86692016-11-26 07:03:34 +000019#include "llvm/Support/ManagedStatic.h"
20#include <memory>
21
22#include "clang.h"
23#include "clang-c.h"
24
25namespace perf {
26
27static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
28
29using namespace clang;
30
Wang Nan00b86692016-11-26 07:03:34 +000031static CompilerInvocation *
32createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
33{
34 llvm::opt::ArgStringList CCArgs {
35 "-cc1",
36 "-triple", "bpf-pc-linux",
37 "-fsyntax-only",
38 "-ferror-limit", "19",
39 "-fmessage-length", "127",
40 "-O2",
41 "-nostdsysteminc",
42 "-nobuiltininc",
43 "-vectorize-loops",
44 "-vectorize-slp",
45 "-Wno-unused-value",
46 "-Wno-pointer-sign",
47 "-x", "c"};
48 CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
49
50 FrontendOptions& Opts = CI->getFrontendOpts();
51 Opts.Inputs.clear();
52 Opts.Inputs.emplace_back(Path, IK_C);
53 return CI;
54}
55
Wang Nan77dfa842016-11-26 07:03:35 +000056static std::unique_ptr<llvm::Module>
57getModuleFromSource(StringRef Path,
58 IntrusiveRefCntPtr<vfs::FileSystem> VFS)
Wang Nan00b86692016-11-26 07:03:34 +000059{
60 CompilerInstance Clang;
61 Clang.createDiagnostics();
62
Wang Nan00b86692016-11-26 07:03:34 +000063 Clang.setVirtualFileSystem(&*VFS);
64
65 IntrusiveRefCntPtr<CompilerInvocation> CI =
Wang Nan77dfa842016-11-26 07:03:35 +000066 createCompilerInvocation(Path, Clang.getDiagnostics());
Wang Nan00b86692016-11-26 07:03:34 +000067 Clang.setInvocation(&*CI);
68
69 std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
70 if (!Clang.ExecuteAction(*Act))
71 return std::unique_ptr<llvm::Module>(nullptr);
72
73 return Act->takeModule();
74}
75
Wang Nan77dfa842016-11-26 07:03:35 +000076std::unique_ptr<llvm::Module>
77getModuleFromSource(StringRef Name, StringRef Content)
78{
79 using namespace vfs;
80
81 llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS(
82 new OverlayFileSystem(getRealFileSystem()));
83 llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS(
84 new InMemoryFileSystem(true));
85
86 /*
87 * pushOverlay helps setting working dir for MemFS. Must call
88 * before addFile.
89 */
90 OverlayFS->pushOverlay(MemFS);
91 MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
92
93 return getModuleFromSource(Name, OverlayFS);
94}
95
96std::unique_ptr<llvm::Module>
97getModuleFromSource(StringRef Path)
98{
99 IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
100 return getModuleFromSource(Path, VFS);
101}
102
Wang Nan00b86692016-11-26 07:03:34 +0000103}
104
105extern "C" {
106void perf_clang__init(void)
107{
108 perf::LLVMCtx.reset(new llvm::LLVMContext());
109}
110
111void perf_clang__cleanup(void)
112{
113 perf::LLVMCtx.reset(nullptr);
114 llvm::llvm_shutdown();
115}
116}