2 // Copyright 2012-2016 Francisco Jerez
3 // Copyright 2012-2016 Advanced Micro Devices, Inc.
4 // Copyright 2014-2016 Jan Vesely
5 // Copyright 2014-2015 Serge Martin
6 // Copyright 2015 Zoltan Gilian
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 // OTHER DEALINGS IN THE SOFTWARE.
27 #include <llvm/IR/DiagnosticPrinter.h>
28 #include <llvm/IR/DiagnosticInfo.h>
29 #include <llvm/IR/LLVMContext.h>
30 #include <llvm/Support/raw_ostream.h>
31 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
32 #include <llvm-c/Target.h>
34 #include <clang/CodeGen/CodeGenAction.h>
35 #include <clang/Lex/PreprocessorOptions.h>
36 #include <clang/Frontend/TextDiagnosticBuffer.h>
37 #include <clang/Frontend/TextDiagnosticPrinter.h>
38 #include <clang/Basic/TargetInfo.h>
40 // We need to include internal headers last, because the internal headers
41 // include CL headers which have #define's like:
43 //#define cl_khr_gl_sharing 1
44 //#define cl_khr_icd 1
46 // Which will break the compilation of clang/Basic/OpenCLOptions.h
48 #include "core/error.hpp"
49 #include "llvm/codegen.hpp"
50 #include "llvm/compat.hpp"
51 #include "llvm/invocation.hpp"
52 #include "llvm/metadata.hpp"
53 #include "llvm/util.hpp"
54 #include "util/algorithm.hpp"
57 using namespace clover
;
58 using namespace clover::llvm
;
60 using ::llvm::Function
;
61 using ::llvm::LLVMContext
;
63 using ::llvm::raw_string_ostream
;
68 static bool targets_initialized
= false;
69 if (!targets_initialized
) {
70 LLVMInitializeAllTargets();
71 LLVMInitializeAllTargetInfos();
72 LLVMInitializeAllTargetMCs();
73 LLVMInitializeAllAsmPrinters();
74 targets_initialized
= true;
79 diagnostic_handler(const ::llvm::DiagnosticInfo
&di
, void *data
) {
80 if (di
.getSeverity() == ::llvm::DS_Error
) {
81 raw_string_ostream os
{ *reinterpret_cast<std::string
*>(data
) };
82 ::llvm::DiagnosticPrinterRawOStream printer
{ os
};
88 std::unique_ptr
<LLVMContext
>
89 create_context(std::string
&r_log
) {
91 std::unique_ptr
<LLVMContext
> ctx
{ new LLVMContext
};
92 ctx
->setDiagnosticHandler(diagnostic_handler
, &r_log
);
96 std::unique_ptr
<clang::CompilerInstance
>
97 create_compiler_instance(const target
&target
,
98 const std::vector
<std::string
> &opts
,
100 std::unique_ptr
<clang::CompilerInstance
> c
{ new clang::CompilerInstance
};
101 clang::DiagnosticsEngine diag
{ new clang::DiagnosticIDs
,
102 new clang::DiagnosticOptions
, new clang::TextDiagnosticBuffer
};
104 // Parse the compiler options. A file name should be present at the end
105 // and must have the .cl extension in order for the CompilerInvocation
106 // class to recognize it as an OpenCL source file.
107 const std::vector
<const char *> copts
=
108 map(std::mem_fn(&std::string::c_str
), opts
);
110 if (!clang::CompilerInvocation::CreateFromArgs(
111 c
->getInvocation(), copts
.data(), copts
.data() + copts
.size(), diag
))
112 throw invalid_build_options_error();
114 c
->getTargetOpts().CPU
= target
.cpu
;
115 c
->getTargetOpts().Triple
= target
.triple
;
116 c
->getLangOpts().NoBuiltin
= true;
118 // This is a workaround for a Clang bug which causes the number
119 // of warnings and errors to be printed to stderr.
120 // http://www.llvm.org/bugs/show_bug.cgi?id=19735
121 c
->getDiagnosticOpts().ShowCarets
= false;
123 compat::set_lang_defaults(c
->getInvocation(), c
->getLangOpts(),
124 clang::IK_OpenCL
, ::llvm::Triple(target
.triple
),
125 c
->getPreprocessorOpts(),
126 clang::LangStandard::lang_opencl11
);
128 c
->createDiagnostics(new clang::TextDiagnosticPrinter(
129 *new raw_string_ostream(r_log
),
130 &c
->getDiagnosticOpts(), true));
132 c
->setTarget(clang::TargetInfo::CreateTargetInfo(
133 c
->getDiagnostics(), c
->getInvocation().TargetOpts
));
138 std::unique_ptr
<Module
>
139 compile(LLVMContext
&ctx
, clang::CompilerInstance
&c
,
140 const std::string
&name
, const std::string
&source
,
141 const header_map
&headers
, const std::string
&target
,
142 const std::string
&opts
, std::string
&r_log
) {
143 c
.getFrontendOpts().ProgramAction
= clang::frontend::EmitLLVMOnly
;
144 c
.getHeaderSearchOpts().UseBuiltinIncludes
= true;
145 c
.getHeaderSearchOpts().UseStandardSystemIncludes
= true;
146 c
.getHeaderSearchOpts().ResourceDir
= CLANG_RESOURCE_DIR
;
148 // Add libclc generic search path
149 c
.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR
,
150 clang::frontend::Angled
,
153 // Add libclc include
154 c
.getPreprocessorOpts().Includes
.push_back("clc/clc.h");
156 // clc.h requires that this macro be defined:
157 c
.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers");
158 c
.getPreprocessorOpts().addRemappedFile(
159 name
, ::llvm::MemoryBuffer::getMemBuffer(source
).release());
161 if (headers
.size()) {
162 const std::string tmp_header_path
= "/tmp/clover/";
164 c
.getHeaderSearchOpts().AddPath(tmp_header_path
,
165 clang::frontend::Angled
,
168 for (const auto &header
: headers
)
169 c
.getPreprocessorOpts().addRemappedFile(
170 tmp_header_path
+ header
.first
,
171 ::llvm::MemoryBuffer::getMemBuffer(header
.second
).release());
174 // Tell clang to link this file before performing any
175 // optimizations. This is required so that we can replace calls
176 // to the OpenCL C barrier() builtin with calls to target
177 // intrinsics that have the noduplicate attribute. This
178 // attribute will prevent Clang from creating illegal uses of
179 // barrier() (e.g. Moving barrier() inside a conditional that is
180 // no executed by all threads) during its optimizaton passes.
181 compat::add_link_bitcode_file(c
.getCodeGenOpts(),
182 LIBCLC_LIBEXECDIR
+ target
+ ".bc");
185 clang::EmitLLVMOnlyAction
act(&ctx
);
186 if (!c
.ExecuteAction(act
))
189 return act
.takeModule();
194 clover::llvm::compile_program(const std::string
&source
,
195 const header_map
&headers
,
196 const std::string
&target
,
197 const std::string
&opts
,
198 std::string
&r_log
) {
199 if (has_flag(debug::clc
))
200 debug::log(".cl", "// Options: " + opts
+ '\n' + source
);
202 auto ctx
= create_context(r_log
);
203 auto c
= create_compiler_instance(target
, tokenize(opts
+ " input.cl"),
205 auto mod
= compile(*ctx
, *c
, "input.cl", source
, headers
, target
, opts
,
208 if (has_flag(debug::llvm
))
209 debug::log(".ll", print_module_bitcode(*mod
));
211 return build_module_library(*mod
);
216 optimize(Module
&mod
, unsigned optimization_level
,
217 bool internalize_symbols
) {
218 compat::pass_manager pm
;
220 compat::add_data_layout_pass(pm
);
222 // By default, the function internalizer pass will look for a function
223 // called "main" and then mark all other functions as internal. Marking
224 // functions as internal enables the optimizer to perform optimizations
225 // like function inlining and global dead-code elimination.
227 // When there is no "main" function in a module, the internalize pass will
228 // treat the module like a library, and it won't internalize any functions.
229 // Since there is no "main" function in our kernels, we need to tell
230 // the internalizer pass that this module is not a library by passing a
231 // list of kernel functions to the internalizer. The internalizer will
232 // treat the functions in the list as "main" functions and internalize
233 // all of the other functions.
234 if (internalize_symbols
)
235 compat::add_internalize_pass(pm
, map(std::mem_fn(&Function::getName
),
238 ::llvm::PassManagerBuilder pmb
;
239 pmb
.OptLevel
= optimization_level
;
240 pmb
.LibraryInfo
= new compat::target_library_info(
241 ::llvm::Triple(mod
.getTargetTriple()));
242 pmb
.populateModulePassManager(pm
);
246 std::unique_ptr
<Module
>
247 link(LLVMContext
&ctx
, const clang::CompilerInstance
&c
,
248 const std::vector
<module
> &modules
, std::string
&r_log
) {
249 std::unique_ptr
<Module
> mod
{ new Module("link", ctx
) };
250 auto linker
= compat::create_linker(*mod
);
252 for (auto &m
: modules
) {
253 if (compat::link_in_module(*linker
,
254 parse_module_library(m
, ctx
, r_log
)))
258 return std::move(mod
);
263 clover::llvm::link_program(const std::vector
<module
> &modules
,
264 enum pipe_shader_ir ir
, const std::string
&target
,
265 const std::string
&opts
, std::string
&r_log
) {
266 std::vector
<std::string
> options
= tokenize(opts
+ " input.cl");
267 const bool create_library
= count("-create-library", options
);
268 erase_if(equals("-create-library"), options
);
270 auto ctx
= create_context(r_log
);
271 auto c
= create_compiler_instance(target
, options
, r_log
);
272 auto mod
= link(*ctx
, *c
, modules
, r_log
);
274 optimize(*mod
, c
->getCodeGenOpts().OptimizationLevel
, !create_library
);
276 if (has_flag(debug::llvm
))
277 debug::log(".ll", print_module_bitcode(*mod
));
279 if (create_library
) {
280 return build_module_library(*mod
);
282 } else if (ir
== PIPE_SHADER_IR_LLVM
) {
283 return build_module_bitcode(*mod
, *c
);
285 } else if (ir
== PIPE_SHADER_IR_NATIVE
) {
286 if (has_flag(debug::native
))
287 debug::log(".asm", print_module_native(*mod
, target
));
289 return build_module_native(*mod
, target
, *c
, r_log
);
292 unreachable("Unsupported IR.");