clover/llvm: Use metadata introspection utils for kernel enumeration.
[mesa.git] / src / gallium / state_trackers / clover / llvm / invocation.cpp
1 //
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
7 //
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:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
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.
25 //
26
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"
32
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>
56
57
58 #include <llvm/IR/DataLayout.h>
59 #include <llvm/Target/TargetMachine.h>
60 #include <llvm/Target/TargetOptions.h>
61
62 #include <llvm-c/Target.h>
63 #include <llvm-c/TargetMachine.h>
64 #include <llvm-c/Core.h>
65
66 #include "pipe/p_state.h"
67 #include "util/u_memory.h"
68 #include "util/u_math.h"
69
70 #include <iostream>
71 #include <iomanip>
72 #include <fstream>
73 #include <cstdio>
74 #include <sstream>
75 #include <libelf.h>
76 #include <gelf.h>
77
78 using namespace clover;
79 using namespace clover::llvm;
80
81 using ::llvm::cast;
82 using ::llvm::dyn_cast;
83 using ::llvm::Function;
84 using ::llvm::isa;
85 using ::llvm::LLVMContext;
86 using ::llvm::Module;
87 using ::llvm::raw_string_ostream;
88 using ::llvm::TargetMachine;
89
90 namespace {
91 // XXX - Temporary hack to avoid breaking the build for the moment, will
92 // get rid of this later.
93 namespace llvm {
94 using namespace ::llvm;
95 }
96
97 void
98 init_targets() {
99 static bool targets_initialized = false;
100 if (!targets_initialized) {
101 LLVMInitializeAllTargets();
102 LLVMInitializeAllTargetInfos();
103 LLVMInitializeAllTargetMCs();
104 LLVMInitializeAllAsmPrinters();
105 targets_initialized = true;
106 }
107 }
108
109 void
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 };
114 di.print(printer);
115 throw compile_error();
116 }
117 }
118
119 std::unique_ptr<LLVMContext>
120 create_context(std::string &r_log) {
121 init_targets();
122 std::unique_ptr<LLVMContext> ctx { new LLVMContext };
123 ctx->setDiagnosticHandler(diagnostic_handler, &r_log);
124 return ctx;
125 }
126
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 };
134
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);
140
141 if (!clang::CompilerInvocation::CreateFromArgs(
142 c->getInvocation(), copts.data(), copts.data() + copts.size(), diag))
143 throw error(CL_INVALID_COMPILER_OPTIONS);
144
145 c->getTargetOpts().CPU = target.cpu;
146 c->getTargetOpts().Triple = target.triple;
147 c->getLangOpts().NoBuiltin = true;
148
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;
153
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);
158
159 c->createDiagnostics(new clang::TextDiagnosticPrinter(
160 *new raw_string_ostream(r_log),
161 &c->getDiagnosticOpts(), true));
162
163 c->setTarget(clang::TargetInfo::CreateTargetInfo(
164 c->getDiagnostics(), c->getInvocation().TargetOpts));
165
166 return c;
167 }
168
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;
178
179 // Add libclc generic search path
180 c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR,
181 clang::frontend::Angled,
182 false, false);
183
184 // Add libclc include
185 c.getPreprocessorOpts().Includes.push_back("clc/clc.h");
186
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());
191
192 if (headers.size()) {
193 const std::string tmp_header_path = "/tmp/clover/";
194
195 c.getHeaderSearchOpts().AddPath(tmp_header_path,
196 clang::frontend::Angled,
197 false, false);
198
199 for (const auto &header : headers)
200 c.getPreprocessorOpts().addRemappedFile(
201 tmp_header_path + header.first,
202 ::llvm::MemoryBuffer::getMemBuffer(header.second).release());
203 }
204
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");
214
215 // Compile the code
216 clang::EmitLLVMOnlyAction act(&ctx);
217 if (!c.ExecuteAction(act))
218 throw compile_error();
219
220 return act.takeModule();
221 }
222
223 void
224 optimize(Module &mod, unsigned optimization_level) {
225 compat::pass_manager pm;
226
227 compat::add_data_layout_pass(pm);
228
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.
233 //
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),
242 get_kernels(mod)));
243
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);
249 pm.run(mod);
250 }
251
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;
263 else
264 unreachable("Unknown image type");
265 }
266
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);
276
277 for (const auto &arg : f.args()) {
278 const auto arg_type = arg.getType();
279
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);
287
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);
292
293 const auto type_name = get_argument_metadata(f, arg,
294 "kernel_arg_type");
295
296 if (type_name == "image2d_t" || type_name == "image3d_t") {
297 // Image.
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);
303
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);
311
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);
319
320 } else {
321 // Other types.
322 const auto actual_type =
323 isa<::llvm::PointerType>(arg_type) && arg.hasByValAttr() ?
324 cast<::llvm::PointerType>(arg_type)->getElementType() : arg_type;
325
326 if (actual_type->isPointerTy()) {
327 const unsigned address_space =
328 cast<::llvm::PointerType>(actual_type)->getAddressSpace();
329
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);
335 } else {
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
342 // constant buffers.
343 args.emplace_back(module::argument::global, arg_api_size,
344 target_size, target_align,
345 module::argument::zero_ext);
346 }
347
348 } else {
349 const bool needs_sign_ext = f.getAttributes().hasAttribute(
350 arg.getArgNo() + 1, ::llvm::Attribute::SExt);
351
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));
356 }
357 }
358 }
359
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);
368
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);
374
375 return args;
376 }
377
378 module::section
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, {} };
382
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());
386
387 return text;
388 }
389
390 module
391 build_module_common(const Module &mod,
392 const std::vector<char> &code,
393 const std::map<std::string,
394 unsigned> &offsets,
395 const clang::CompilerInstance &c) {
396 module m;
397
398 for (const auto &name : map(std::mem_fn(&Function::getName),
399 get_kernels(mod))) {
400 if (offsets.count(name))
401 m.syms.emplace_back(name, 0, offsets.at(name),
402 make_kernel_args(mod, name, c));
403 }
404
405 m.secs.push_back(make_text_section(code));
406 return m;
407 }
408
409 module
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();
418 #endif
419
420 std::map<std::string, unsigned> offsets;
421 unsigned i = 0;
422
423 for (const auto &name : map(std::mem_fn(&::llvm::Function::getName),
424 get_kernels(*mod)))
425 offsets[name] = i++;
426
427 return build_module_common(*mod, { llvm_bitcode.begin(),
428 llvm_bitcode.end() },
429 offsets, c);
430 }
431
432 std::vector<char>
433 emit_code(::llvm::Module &mod, const target &target,
434 TargetMachine::CodeGenFileType ft,
435 std::string &r_log) {
436 std::string err;
437 auto t = ::llvm::TargetRegistry::lookupTarget(target.triple, err);
438 if (!t)
439 fail(r_log, compile_error(), err);
440
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) };
446 if (!tm)
447 fail(r_log, compile_error(),
448 "Could not create TargetMachine: " + target.triple);
449
450 ::llvm::SmallVector<char, 1024> data;
451
452 {
453 compat::pass_manager pm;
454 ::llvm::raw_svector_ostream os { data };
455 compat::raw_ostream_to_emit_file fos { os };
456
457 mod.setDataLayout(compat::get_data_layout(*tm));
458 tm->Options.MCOptions.AsmVerbose =
459 (ft == TargetMachine::CGFT_AssemblyFile);
460
461 if (tm->addPassesToEmitFile(pm, fos, ft))
462 fail(r_log, compile_error(), "TargetMachine can't emit this file");
463
464 pm.run(mod);
465 }
466
467 return { data.begin(), data.end() };
468 }
469
470 std::vector<char>
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)));
478 }
479
480 return emit_code(*mod, target, TargetMachine::CGFT_ObjectFile, r_log);
481 }
482
483 namespace elf {
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()),
491 elf_end };
492 }
493
494 Elf_Scn *
495 get_symbol_table(Elf *elf) {
496 size_t section_str_index;
497 elf_getshdrstrndx(elf, &section_str_index);
498
499 for (Elf_Scn *s = elf_nextscn(elf, NULL); s; s = elf_nextscn(elf, s)) {
500 GElf_Shdr header;
501 if (gelf_getshdr(s, &header) != &header)
502 return nullptr;
503
504 if (!std::strcmp(elf_strptr(elf, section_str_index, header.sh_name),
505 ".symtab"))
506 return s;
507 }
508
509 return nullptr;
510 }
511
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);
515 GElf_Shdr header;
516 if (gelf_getshdr(symtab, &header) != &header)
517 return {};
518
519 std::map<std::string, unsigned> symbol_offsets;
520 GElf_Sym symbol;
521 unsigned i = 0;
522
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;
526 }
527
528 return symbol_offsets;
529 }
530 }
531
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());
537 if (!symtab)
538 fail(r_log, compile_error(), "Unable to find symbol table.");
539
540 return elf::get_symbol_offsets(elf.get(), symtab);
541 }
542
543 module
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);
550 }
551 } // End anonymous namespace
552
553 module
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);
562
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"),
567 r_log);
568 auto mod = compile(*ctx, *c, "input.cl", source, headers, target, opts, r_log);
569
570 optimize(*mod, c->getCodeGenOpts().OptimizationLevel);
571
572 if (has_flag(debug::llvm)) {
573 std::string log;
574 raw_string_ostream s_log(log);
575 mod->print(s_log, NULL);
576 s_log.flush();
577 debug::log(".ll", log);
578 }
579
580 module m;
581 // Build the clover::module
582 switch (ir) {
583 case PIPE_SHADER_IR_NIR:
584 case PIPE_SHADER_IR_TGSI:
585 //XXX: Handle TGSI, NIR
586 assert(0);
587 m = module();
588 break;
589 case PIPE_SHADER_IR_LLVM:
590 m = build_module_llvm(&*mod, *c);
591 break;
592 case PIPE_SHADER_IR_NATIVE:
593 m = build_module_native(&*mod, target, *c, r_log);
594 break;
595 }
596
597 return m;
598 }