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/compat.hpp"
28 #include "llvm/metadata.hpp"
29 #include "llvm/util.hpp"
30 #include "core/compiler.hpp"
31 #include "util/algorithm.hpp"
33 #include <clang/Frontend/CompilerInstance.h>
34 #include <clang/Frontend/TextDiagnosticBuffer.h>
35 #include <clang/Frontend/TextDiagnosticPrinter.h>
36 #include <clang/CodeGen/CodeGenAction.h>
37 #include <clang/Basic/TargetInfo.h>
38 #include <llvm/Bitcode/BitstreamWriter.h>
39 #include <llvm/Bitcode/ReaderWriter.h>
40 #include <llvm/Linker/Linker.h>
41 #include <llvm/IR/DiagnosticInfo.h>
42 #include <llvm/IR/DiagnosticPrinter.h>
43 #include <llvm/IR/DerivedTypes.h>
44 #include <llvm/IR/LLVMContext.h>
45 #include <llvm/IR/Module.h>
46 #include <llvm/Support/SourceMgr.h>
47 #include <llvm/IRReader/IRReader.h>
48 #include <llvm/Support/CodeGen.h>
49 #include <llvm/Support/TargetSelect.h>
50 #include <llvm/Support/MemoryBuffer.h>
51 #include <llvm/Support/FormattedStream.h>
52 #include <llvm/Support/TargetRegistry.h>
53 #include <llvm/Transforms/IPO.h>
54 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
55 #include <llvm/Transforms/Utils/Cloning.h>
58 #include <llvm/IR/DataLayout.h>
59 #include <llvm/Target/TargetMachine.h>
60 #include <llvm/Target/TargetOptions.h>
62 #include <llvm-c/Target.h>
63 #include <llvm-c/TargetMachine.h>
64 #include <llvm-c/Core.h>
66 #include "pipe/p_state.h"
67 #include "util/u_memory.h"
68 #include "util/u_math.h"
78 using namespace clover
;
79 using namespace clover::llvm
;
82 using ::llvm::dyn_cast
;
83 using ::llvm::Function
;
85 using ::llvm::LLVMContext
;
87 using ::llvm::raw_string_ostream
;
88 using ::llvm::TargetMachine
;
91 // XXX - Temporary hack to avoid breaking the build for the moment, will
92 // get rid of this later.
94 using namespace ::llvm
;
99 static bool targets_initialized
= false;
100 if (!targets_initialized
) {
101 LLVMInitializeAllTargets();
102 LLVMInitializeAllTargetInfos();
103 LLVMInitializeAllTargetMCs();
104 LLVMInitializeAllAsmPrinters();
105 targets_initialized
= true;
110 diagnostic_handler(const ::llvm::DiagnosticInfo
&di
, void *data
) {
111 if (di
.getSeverity() == ::llvm::DS_Error
) {
112 raw_string_ostream os
{ *reinterpret_cast<std::string
*>(data
) };
113 ::llvm::DiagnosticPrinterRawOStream printer
{ os
};
115 throw compile_error();
119 std::unique_ptr
<LLVMContext
>
120 create_context(std::string
&r_log
) {
122 std::unique_ptr
<LLVMContext
> ctx
{ new LLVMContext
};
123 ctx
->setDiagnosticHandler(diagnostic_handler
, &r_log
);
127 std::unique_ptr
<clang::CompilerInstance
>
128 create_compiler_instance(const target
&target
,
129 const std::vector
<std::string
> &opts
,
130 std::string
&r_log
) {
131 std::unique_ptr
<clang::CompilerInstance
> c
{ new clang::CompilerInstance
};
132 clang::DiagnosticsEngine diag
{ new clang::DiagnosticIDs
,
133 new clang::DiagnosticOptions
, new clang::TextDiagnosticBuffer
};
135 // Parse the compiler options. A file name should be present at the end
136 // and must have the .cl extension in order for the CompilerInvocation
137 // class to recognize it as an OpenCL source file.
138 const std::vector
<const char *> copts
=
139 map(std::mem_fn(&std::string::c_str
), opts
);
141 if (!clang::CompilerInvocation::CreateFromArgs(
142 c
->getInvocation(), copts
.data(), copts
.data() + copts
.size(), diag
))
143 throw error(CL_INVALID_COMPILER_OPTIONS
);
145 c
->getTargetOpts().CPU
= target
.cpu
;
146 c
->getTargetOpts().Triple
= target
.triple
;
147 c
->getLangOpts().NoBuiltin
= true;
149 // This is a workaround for a Clang bug which causes the number
150 // of warnings and errors to be printed to stderr.
151 // http://www.llvm.org/bugs/show_bug.cgi?id=19735
152 c
->getDiagnosticOpts().ShowCarets
= false;
154 compat::set_lang_defaults(c
->getInvocation(), c
->getLangOpts(),
155 clang::IK_OpenCL
, ::llvm::Triple(target
.triple
),
156 c
->getPreprocessorOpts(),
157 clang::LangStandard::lang_opencl11
);
159 c
->createDiagnostics(new clang::TextDiagnosticPrinter(
160 *new raw_string_ostream(r_log
),
161 &c
->getDiagnosticOpts(), true));
163 c
->setTarget(clang::TargetInfo::CreateTargetInfo(
164 c
->getDiagnostics(), c
->getInvocation().TargetOpts
));
169 std::unique_ptr
<Module
>
170 compile(LLVMContext
&ctx
, clang::CompilerInstance
&c
,
171 const std::string
&name
, const std::string
&source
,
172 const header_map
&headers
, const std::string
&target
,
173 const std::string
&opts
, std::string
&r_log
) {
174 c
.getFrontendOpts().ProgramAction
= clang::frontend::EmitLLVMOnly
;
175 c
.getHeaderSearchOpts().UseBuiltinIncludes
= true;
176 c
.getHeaderSearchOpts().UseStandardSystemIncludes
= true;
177 c
.getHeaderSearchOpts().ResourceDir
= CLANG_RESOURCE_DIR
;
179 // Add libclc generic search path
180 c
.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR
,
181 clang::frontend::Angled
,
184 // Add libclc include
185 c
.getPreprocessorOpts().Includes
.push_back("clc/clc.h");
187 // clc.h requires that this macro be defined:
188 c
.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers");
189 c
.getPreprocessorOpts().addRemappedFile(
190 name
, ::llvm::MemoryBuffer::getMemBuffer(source
).release());
192 if (headers
.size()) {
193 const std::string tmp_header_path
= "/tmp/clover/";
195 c
.getHeaderSearchOpts().AddPath(tmp_header_path
,
196 clang::frontend::Angled
,
199 for (const auto &header
: headers
)
200 c
.getPreprocessorOpts().addRemappedFile(
201 tmp_header_path
+ header
.first
,
202 ::llvm::MemoryBuffer::getMemBuffer(header
.second
).release());
205 // Tell clang to link this file before performing any
206 // optimizations. This is required so that we can replace calls
207 // to the OpenCL C barrier() builtin with calls to target
208 // intrinsics that have the noduplicate attribute. This
209 // attribute will prevent Clang from creating illegal uses of
210 // barrier() (e.g. Moving barrier() inside a conditional that is
211 // no executed by all threads) during its optimizaton passes.
212 compat::add_link_bitcode_file(c
.getCodeGenOpts(),
213 LIBCLC_LIBEXECDIR
+ target
+ ".bc");
216 clang::EmitLLVMOnlyAction
act(&ctx
);
217 if (!c
.ExecuteAction(act
))
218 throw compile_error();
220 return act
.takeModule();
224 optimize(Module
&mod
, unsigned optimization_level
) {
225 compat::pass_manager pm
;
227 compat::add_data_layout_pass(pm
);
229 // By default, the function internalizer pass will look for a function
230 // called "main" and then mark all other functions as internal. Marking
231 // functions as internal enables the optimizer to perform optimizations
232 // like function inlining and global dead-code elimination.
234 // When there is no "main" function in a module, the internalize pass will
235 // treat the module like a library, and it won't internalize any functions.
236 // Since there is no "main" function in our kernels, we need to tell
237 // the internalizer pass that this module is not a library by passing a
238 // list of kernel functions to the internalizer. The internalizer will
239 // treat the functions in the list as "main" functions and internalize
240 // all of the other functions.
241 compat::add_internalize_pass(pm
, map(std::mem_fn(&Function::getName
),
244 ::llvm::PassManagerBuilder pmb
;
245 pmb
.OptLevel
= optimization_level
;
246 pmb
.LibraryInfo
= new compat::target_library_info(
247 ::llvm::Triple(mod
.getTargetTriple()));
248 pmb
.populateModulePassManager(pm
);
252 enum module::argument::type
253 get_image_type(const std::string
&type
,
254 const std::string
&qual
) {
255 if (type
== "image2d_t" && qual
== "read_only")
256 return module::argument::image2d_rd
;
257 else if (type
== "image2d_t" && qual
== "write_only")
258 return module::argument::image2d_wr
;
259 else if (type
== "image3d_t" && qual
== "read_only")
260 return module::argument::image3d_rd
;
261 else if (type
== "image3d_t" && qual
== "write_only")
262 return module::argument::image3d_wr
;
264 unreachable("Unknown image type");
267 std::vector
<module::argument
>
268 make_kernel_args(const Module
&mod
, const std::string
&kernel_name
,
269 const clang::CompilerInstance
&c
) {
270 std::vector
<module::argument
> args
;
271 const auto address_spaces
= c
.getTarget().getAddressSpaceMap();
272 const Function
&f
= *mod
.getFunction(kernel_name
);
273 ::llvm::DataLayout
dl(&mod
);
274 const auto size_type
=
275 dl
.getSmallestLegalIntType(mod
.getContext(), sizeof(cl_uint
) * 8);
277 for (const auto &arg
: f
.args()) {
278 const auto arg_type
= arg
.getType();
280 // OpenCL 1.2 specification, Ch. 6.1.5: "A built-in data
281 // type that is not a power of two bytes in size must be
282 // aligned to the next larger power of two". We need this
283 // alignment for three element vectors, which have
284 // non-power-of-2 store size.
285 const unsigned arg_store_size
= dl
.getTypeStoreSize(arg_type
);
286 const unsigned arg_api_size
= util_next_power_of_two(arg_store_size
);
288 const auto target_type
= !arg_type
->isIntegerTy() ? arg_type
:
289 dl
.getSmallestLegalIntType(mod
.getContext(), arg_store_size
* 8);
290 const unsigned target_size
= dl
.getTypeStoreSize(target_type
);
291 const unsigned target_align
= dl
.getABITypeAlignment(target_type
);
293 const auto type_name
= get_argument_metadata(f
, arg
,
296 if (type_name
== "image2d_t" || type_name
== "image3d_t") {
298 const auto access_qual
= get_argument_metadata(
299 f
, arg
, "kernel_arg_access_qual");
300 args
.emplace_back(get_image_type(type_name
, access_qual
),
301 arg_store_size
, target_size
,
302 target_align
, module::argument::zero_ext
);
304 } else if (type_name
== "__llvm_image_size") {
305 // Image size implicit argument.
306 args
.emplace_back(module::argument::scalar
, sizeof(cl_uint
),
307 dl
.getTypeStoreSize(size_type
),
308 dl
.getABITypeAlignment(size_type
),
309 module::argument::zero_ext
,
310 module::argument::image_size
);
312 } else if (type_name
== "__llvm_image_format") {
313 // Image format implicit argument.
314 args
.emplace_back(module::argument::scalar
, sizeof(cl_uint
),
315 dl
.getTypeStoreSize(size_type
),
316 dl
.getABITypeAlignment(size_type
),
317 module::argument::zero_ext
,
318 module::argument::image_format
);
322 const auto actual_type
=
323 isa
<::llvm::PointerType
>(arg_type
) && arg
.hasByValAttr() ?
324 cast
<::llvm::PointerType
>(arg_type
)->getElementType() : arg_type
;
326 if (actual_type
->isPointerTy()) {
327 const unsigned address_space
=
328 cast
<::llvm::PointerType
>(actual_type
)->getAddressSpace();
330 if (address_space
== address_spaces
[clang::LangAS::opencl_local
331 - clang::LangAS::Offset
]) {
332 args
.emplace_back(module::argument::local
, arg_api_size
,
333 target_size
, target_align
,
334 module::argument::zero_ext
);
336 // XXX: Correctly handle constant address space. There is no
337 // way for r600g to pass a handle for constant buffers back
338 // to clover like it can for global buffers, so
339 // creating constant arguments will break r600g. For now,
340 // continue treating constant buffers as global buffers
341 // until we can come up with a way to create handles for
343 args
.emplace_back(module::argument::global
, arg_api_size
,
344 target_size
, target_align
,
345 module::argument::zero_ext
);
349 const bool needs_sign_ext
= f
.getAttributes().hasAttribute(
350 arg
.getArgNo() + 1, ::llvm::Attribute::SExt
);
352 args
.emplace_back(module::argument::scalar
, arg_api_size
,
353 target_size
, target_align
,
354 (needs_sign_ext
? module::argument::sign_ext
:
355 module::argument::zero_ext
));
360 // Append implicit arguments. XXX - The types, ordering and
361 // vector size of the implicit arguments should depend on the
362 // target according to the selected calling convention.
363 args
.emplace_back(module::argument::scalar
, sizeof(cl_uint
),
364 dl
.getTypeStoreSize(size_type
),
365 dl
.getABITypeAlignment(size_type
),
366 module::argument::zero_ext
,
367 module::argument::grid_dimension
);
369 args
.emplace_back(module::argument::scalar
, sizeof(cl_uint
),
370 dl
.getTypeStoreSize(size_type
),
371 dl
.getABITypeAlignment(size_type
),
372 module::argument::zero_ext
,
373 module::argument::grid_offset
);
379 make_text_section(const std::vector
<char> &code
) {
380 const pipe_llvm_program_header header
{ uint32_t(code
.size()) };
381 module::section text
{ 0, module::section::text
, header
.num_bytes
, {} };
383 text
.data
.insert(text
.data
.end(), reinterpret_cast<const char *>(&header
),
384 reinterpret_cast<const char *>(&header
) + sizeof(header
));
385 text
.data
.insert(text
.data
.end(), code
.begin(), code
.end());
391 build_module_common(const Module
&mod
,
392 const std::vector
<char> &code
,
393 const std::map
<std::string
,
395 const clang::CompilerInstance
&c
) {
398 for (const auto &name
: map(std::mem_fn(&Function::getName
),
400 if (offsets
.count(name
))
401 m
.syms
.emplace_back(name
, 0, offsets
.at(name
),
402 make_kernel_args(mod
, name
, c
));
405 m
.secs
.push_back(make_text_section(code
));
410 build_module_llvm(llvm::Module
*mod
,
411 const clang::CompilerInstance
&c
) {
412 llvm::SmallVector
<char, 1024> llvm_bitcode
;
413 llvm::raw_svector_ostream
bitcode_ostream(llvm_bitcode
);
414 llvm::BitstreamWriter
writer(llvm_bitcode
);
415 llvm::WriteBitcodeToFile(mod
, bitcode_ostream
);
416 #if HAVE_LLVM < 0x0308
417 bitcode_ostream
.flush();
420 std::map
<std::string
, unsigned> offsets
;
423 for (const auto &name
: map(std::mem_fn(&::llvm::Function::getName
),
427 return build_module_common(*mod
, { llvm_bitcode
.begin(),
428 llvm_bitcode
.end() },
433 emit_code(::llvm::Module
&mod
, const target
&target
,
434 TargetMachine::CodeGenFileType ft
,
435 std::string
&r_log
) {
437 auto t
= ::llvm::TargetRegistry::lookupTarget(target
.triple
, err
);
439 fail(r_log
, compile_error(), err
);
441 std::unique_ptr
<TargetMachine
> tm
{
442 t
->createTargetMachine(target
.triple
, target
.cpu
, "", {},
443 compat::default_reloc_model
,
444 ::llvm::CodeModel::Default
,
445 ::llvm::CodeGenOpt::Default
) };
447 fail(r_log
, compile_error(),
448 "Could not create TargetMachine: " + target
.triple
);
450 ::llvm::SmallVector
<char, 1024> data
;
453 compat::pass_manager pm
;
454 ::llvm::raw_svector_ostream os
{ data
};
455 compat::raw_ostream_to_emit_file fos
{ os
};
457 mod
.setDataLayout(compat::get_data_layout(*tm
));
458 tm
->Options
.MCOptions
.AsmVerbose
=
459 (ft
== TargetMachine::CGFT_AssemblyFile
);
461 if (tm
->addPassesToEmitFile(pm
, fos
, ft
))
462 fail(r_log
, compile_error(), "TargetMachine can't emit this file");
467 return { data
.begin(), data
.end() };
471 compile_native(llvm::Module
*mod
, const target
&target
,
472 std::string
&r_log
) {
473 if (has_flag(debug::native
)) {
474 std::unique_ptr
<llvm::Module
> cmod
{ CloneModule(mod
) };
475 debug::log(".asm", as_string(
476 emit_code(*cmod
, target
,
477 TargetMachine::CGFT_AssemblyFile
, r_log
)));
480 return emit_code(*mod
, target
, TargetMachine::CGFT_ObjectFile
, r_log
);
484 std::unique_ptr
<Elf
, int (*)(Elf
*)>
485 get(const std::vector
<char> &code
) {
486 // One of the libelf implementations
487 // (http://www.mr511.de/software/english.htm) requires calling
488 // elf_version() before elf_memory().
489 elf_version(EV_CURRENT
);
490 return { elf_memory(const_cast<char *>(code
.data()), code
.size()),
495 get_symbol_table(Elf
*elf
) {
496 size_t section_str_index
;
497 elf_getshdrstrndx(elf
, §ion_str_index
);
499 for (Elf_Scn
*s
= elf_nextscn(elf
, NULL
); s
; s
= elf_nextscn(elf
, s
)) {
501 if (gelf_getshdr(s
, &header
) != &header
)
504 if (!std::strcmp(elf_strptr(elf
, section_str_index
, header
.sh_name
),
512 std::map
<std::string
, unsigned>
513 get_symbol_offsets(Elf
*elf
, Elf_Scn
*symtab
) {
514 Elf_Data
*const symtab_data
= elf_getdata(symtab
, NULL
);
516 if (gelf_getshdr(symtab
, &header
) != &header
)
519 std::map
<std::string
, unsigned> symbol_offsets
;
523 while (GElf_Sym
*s
= gelf_getsym(symtab_data
, i
++, &symbol
)) {
524 const char *name
= elf_strptr(elf
, header
.sh_link
, s
->st_name
);
525 symbol_offsets
[name
] = s
->st_value
;
528 return symbol_offsets
;
532 std::map
<std::string
, unsigned>
533 get_symbol_offsets(const std::vector
<char> &code
,
534 std::string
&r_log
) {
535 const auto elf
= elf::get(code
);
536 const auto symtab
= elf::get_symbol_table(elf
.get());
538 fail(r_log
, compile_error(), "Unable to find symbol table.");
540 return elf::get_symbol_offsets(elf
.get(), symtab
);
544 build_module_native(llvm::Module
*mod
, const target
&target
,
545 const clang::CompilerInstance
&c
,
546 std::string
&r_log
) {
547 const auto code
= compile_native(mod
, target
, r_log
);
548 return build_module_common(*mod
, code
,
549 get_symbol_offsets(code
, r_log
), c
);
551 } // End anonymous namespace
554 clover::compile_program_llvm(const std::string
&source
,
555 const header_map
&headers
,
556 enum pipe_shader_ir ir
,
557 const std::string
&target
,
558 const std::string
&opts
,
559 std::string
&r_log
) {
560 if (has_flag(debug::clc
))
561 debug::log(".cl", "// Build options: " + opts
+ '\n' + source
);
563 auto ctx
= create_context(r_log
);
564 // The input file name must have the .cl extension in order for the
565 // CompilerInvocation class to recognize it as an OpenCL source file.
566 const auto c
= create_compiler_instance(target
, tokenize(opts
+ " input.cl"),
568 auto mod
= compile(*ctx
, *c
, "input.cl", source
, headers
, target
, opts
, r_log
);
570 optimize(*mod
, c
->getCodeGenOpts().OptimizationLevel
);
572 if (has_flag(debug::llvm
)) {
574 raw_string_ostream
s_log(log
);
575 mod
->print(s_log
, NULL
);
577 debug::log(".ll", log
);
581 // Build the clover::module
583 case PIPE_SHADER_IR_NIR
:
584 case PIPE_SHADER_IR_TGSI
:
585 //XXX: Handle TGSI, NIR
589 case PIPE_SHADER_IR_LLVM
:
590 m
= build_module_llvm(&*mod
, *c
);
592 case PIPE_SHADER_IR_NATIVE
:
593 m
= build_module_native(&*mod
, target
, *c
, r_log
);