]>
git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - tools/perf/util/c++/clang.cpp
2 * llvm C frontend for perf. Support dynamically compile C file
4 * Inspired by clang example code:
5 * http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp
7 * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
8 * Copyright (C) 2016 Huawei Inc.
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/LegacyPassManager.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Option/Option.h"
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/ManagedStatic.h"
21 #include "llvm/Support/TargetRegistry.h"
22 #include "llvm/Support/TargetSelect.h"
23 #include "llvm/Target/TargetMachine.h"
24 #include "llvm/Target/TargetOptions.h"
32 static std::unique_ptr
<llvm::LLVMContext
> LLVMCtx
;
34 using namespace clang
;
36 static CompilerInvocation
*
37 createCompilerInvocation(llvm::opt::ArgStringList CFlags
, StringRef
& Path
,
38 DiagnosticsEngine
& Diags
)
40 llvm::opt::ArgStringList CCArgs
{
42 "-triple", "bpf-pc-linux",
44 "-ferror-limit", "19",
45 "-fmessage-length", "127",
55 CCArgs
.append(CFlags
.begin(), CFlags
.end());
56 CompilerInvocation
*CI
= tooling::newInvocation(&Diags
, CCArgs
);
58 FrontendOptions
& Opts
= CI
->getFrontendOpts();
60 Opts
.Inputs
.emplace_back(Path
, IK_C
);
64 static std::unique_ptr
<llvm::Module
>
65 getModuleFromSource(llvm::opt::ArgStringList CFlags
,
66 StringRef Path
, IntrusiveRefCntPtr
<vfs::FileSystem
> VFS
)
68 CompilerInstance Clang
;
69 Clang
.createDiagnostics();
71 Clang
.setVirtualFileSystem(&*VFS
);
73 IntrusiveRefCntPtr
<CompilerInvocation
> CI
=
74 createCompilerInvocation(std::move(CFlags
), Path
,
75 Clang
.getDiagnostics());
76 Clang
.setInvocation(&*CI
);
78 std::unique_ptr
<CodeGenAction
> Act(new EmitLLVMOnlyAction(&*LLVMCtx
));
79 if (!Clang
.ExecuteAction(*Act
))
80 return std::unique_ptr
<llvm::Module
>(nullptr);
82 return Act
->takeModule();
85 std::unique_ptr
<llvm::Module
>
86 getModuleFromSource(llvm::opt::ArgStringList CFlags
,
87 StringRef Name
, StringRef Content
)
91 llvm::IntrusiveRefCntPtr
<OverlayFileSystem
> OverlayFS(
92 new OverlayFileSystem(getRealFileSystem()));
93 llvm::IntrusiveRefCntPtr
<InMemoryFileSystem
> MemFS(
94 new InMemoryFileSystem(true));
97 * pushOverlay helps setting working dir for MemFS. Must call
100 OverlayFS
->pushOverlay(MemFS
);
101 MemFS
->addFile(Twine(Name
), 0, llvm::MemoryBuffer::getMemBuffer(Content
));
103 return getModuleFromSource(std::move(CFlags
), Name
, OverlayFS
);
106 std::unique_ptr
<llvm::Module
>
107 getModuleFromSource(llvm::opt::ArgStringList CFlags
, StringRef Path
)
109 IntrusiveRefCntPtr
<vfs::FileSystem
> VFS(vfs::getRealFileSystem());
110 return getModuleFromSource(std::move(CFlags
), Path
, VFS
);
113 std::unique_ptr
<llvm::SmallVectorImpl
<char>>
114 getBPFObjectFromModule(llvm::Module
*Module
)
116 using namespace llvm
;
118 std::string
TargetTriple("bpf-pc-linux");
120 const Target
* Target
= TargetRegistry::lookupTarget(TargetTriple
, Error
);
122 llvm::errs() << Error
;
123 return std::unique_ptr
<llvm::SmallVectorImpl
<char>>(nullptr);
126 llvm::TargetOptions Opt
;
127 TargetMachine
*TargetMachine
=
128 Target
->createTargetMachine(TargetTriple
,
132 Module
->setDataLayout(TargetMachine
->createDataLayout());
133 Module
->setTargetTriple(TargetTriple
);
135 std::unique_ptr
<SmallVectorImpl
<char>> Buffer(new SmallVector
<char, 0>());
136 raw_svector_ostream
ostream(*Buffer
);
138 legacy::PassManager PM
;
139 if (TargetMachine
->addPassesToEmitFile(PM
, ostream
,
140 TargetMachine::CGFT_ObjectFile
)) {
141 llvm::errs() << "TargetMachine can't emit a file of this type\n";
142 return std::unique_ptr
<llvm::SmallVectorImpl
<char>>(nullptr);;
146 return std::move(Buffer
);
152 void perf_clang__init(void)
154 perf::LLVMCtx
.reset(new llvm::LLVMContext());
155 LLVMInitializeBPFTargetInfo();
156 LLVMInitializeBPFTarget();
157 LLVMInitializeBPFTargetMC();
158 LLVMInitializeBPFAsmPrinter();
161 void perf_clang__cleanup(void)
163 perf::LLVMCtx
.reset(nullptr);
164 llvm::llvm_shutdown();
167 int perf_clang__compile_bpf(const char *filename
,
169 size_t *p_obj_buf_sz
)
171 using namespace perf
;
173 if (!p_obj_buf
|| !p_obj_buf_sz
)
176 llvm::opt::ArgStringList CFlags
;
177 auto M
= getModuleFromSource(std::move(CFlags
), filename
);
180 auto O
= getBPFObjectFromModule(&*M
);
184 size_t size
= O
->size_in_bytes();
187 buffer
= malloc(size
);
190 memcpy(buffer
, O
->data(), size
);
192 *p_obj_buf_sz
= size
;