clover: Add initial implementation of clCompileProgram for CL 1.2.
[mesa.git] / src / gallium / state_trackers / clover / llvm / invocation.cpp
1 //
2 // Copyright 2012 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22
23 #include "core/compiler.hpp"
24
25 #include <clang/Frontend/CompilerInstance.h>
26 #include <clang/Frontend/TextDiagnosticBuffer.h>
27 #include <clang/Frontend/TextDiagnosticPrinter.h>
28 #include <clang/CodeGen/CodeGenAction.h>
29 #include <clang/Basic/TargetInfo.h>
30 #include <llvm/Bitcode/BitstreamWriter.h>
31 #include <llvm/Bitcode/ReaderWriter.h>
32 #if HAVE_LLVM < 0x0305
33 #include <llvm/Linker.h>
34 #else
35 #include <llvm/Linker/Linker.h>
36 #include <llvm/IR/DiagnosticInfo.h>
37 #include <llvm/IR/DiagnosticPrinter.h>
38 #endif
39 #if HAVE_LLVM < 0x0303
40 #include <llvm/DerivedTypes.h>
41 #include <llvm/LLVMContext.h>
42 #include <llvm/Module.h>
43 #else
44 #include <llvm/IR/DerivedTypes.h>
45 #include <llvm/IR/LLVMContext.h>
46 #include <llvm/IR/Module.h>
47 #include <llvm/Support/SourceMgr.h>
48 #include <llvm/IRReader/IRReader.h>
49 #endif
50 #if HAVE_LLVM < 0x0305
51 #include <llvm/ADT/OwningPtr.h>
52 #endif
53 #include <llvm/PassManager.h>
54 #include <llvm/Support/CodeGen.h>
55 #include <llvm/Support/TargetSelect.h>
56 #include <llvm/Support/MemoryBuffer.h>
57 #if HAVE_LLVM < 0x0303
58 #include <llvm/Support/PathV1.h>
59 #endif
60 #include <llvm/Support/FormattedStream.h>
61 #include <llvm/Support/TargetRegistry.h>
62 #include <llvm/Transforms/IPO.h>
63 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
64 #include <llvm/Transforms/Utils/Cloning.h>
65
66
67 #if HAVE_LLVM < 0x0302
68 #include <llvm/Target/TargetData.h>
69 #elif HAVE_LLVM < 0x0303
70 #include <llvm/DataLayout.h>
71 #else
72 #include <llvm/IR/DataLayout.h>
73 #endif
74 #include <llvm/Target/TargetLibraryInfo.h>
75 #include <llvm/Target/TargetMachine.h>
76 #include <llvm/Target/TargetOptions.h>
77
78 #include <llvm-c/Target.h>
79 #include <llvm-c/TargetMachine.h>
80 #include <llvm-c/Core.h>
81
82 #include "pipe/p_state.h"
83 #include "util/u_memory.h"
84 #include "util/u_math.h"
85
86 #include <iostream>
87 #include <iomanip>
88 #include <fstream>
89 #include <cstdio>
90 #include <sstream>
91 #include <libelf.h>
92 #include <gelf.h>
93
94 using namespace clover;
95
96 namespace {
97 #if 0
98 void
99 build_binary(const std::string &source, const std::string &target,
100 const std::string &name) {
101 clang::CompilerInstance c;
102 clang::EmitObjAction act(&llvm::getGlobalContext());
103 std::string log;
104 llvm::raw_string_ostream s_log(log);
105
106 LLVMInitializeTGSITarget();
107 LLVMInitializeTGSITargetInfo();
108 LLVMInitializeTGSITargetMC();
109 LLVMInitializeTGSIAsmPrinter();
110
111 c.getFrontendOpts().Inputs.push_back(
112 std::make_pair(clang::IK_OpenCL, name));
113 c.getHeaderSearchOpts().UseBuiltinIncludes = false;
114 c.getHeaderSearchOpts().UseStandardIncludes = false;
115 c.getLangOpts().NoBuiltin = true;
116 c.getTargetOpts().Triple = target;
117 c.getInvocation().setLangDefaults(clang::IK_OpenCL);
118 c.createDiagnostics(0, NULL, new clang::TextDiagnosticPrinter(
119 s_log, c.getDiagnosticOpts()));
120
121 c.getPreprocessorOpts().addRemappedFile(
122 name, llvm::MemoryBuffer::getMemBuffer(source));
123
124 if (!c.ExecuteAction(act))
125 throw build_error(log);
126 }
127
128 module
129 load_binary(const char *name) {
130 std::ifstream fs((name));
131 std::vector<unsigned char> str((std::istreambuf_iterator<char>(fs)),
132 (std::istreambuf_iterator<char>()));
133 compat::istream cs(str);
134 return module::deserialize(cs);
135 }
136 #endif
137 void debug_log(const std::string &msg, const std::string &suffix) {
138 const char *dbg_file = debug_get_option("CLOVER_DEBUG_FILE", "stderr");
139 if (!strcmp("stderr", dbg_file)) {
140 std::cerr << msg;
141 } else {
142 std::ofstream file(dbg_file + suffix, std::ios::app);
143 file << msg;
144 }
145 }
146
147 llvm::Module *
148 compile_llvm(llvm::LLVMContext &llvm_ctx, const std::string &source,
149 const header_map &headers,
150 const std::string &name, const std::string &triple,
151 const std::string &processor, const std::string &opts,
152 clang::LangAS::Map& address_spaces, unsigned &optimization_level,
153 compat::string &r_log) {
154
155 clang::CompilerInstance c;
156 clang::EmitLLVMOnlyAction act(&llvm_ctx);
157 std::string log;
158 llvm::raw_string_ostream s_log(log);
159 std::string libclc_path = LIBCLC_LIBEXECDIR + processor + "-"
160 + triple + ".bc";
161
162 // Parse the compiler options:
163 std::vector<std::string> opts_array;
164 std::istringstream ss(opts);
165
166 while (!ss.eof()) {
167 std::string opt;
168 getline(ss, opt, ' ');
169 opts_array.push_back(opt);
170 }
171
172 opts_array.push_back(name);
173
174 std::vector<const char *> opts_carray;
175 for (unsigned i = 0; i < opts_array.size(); i++) {
176 opts_carray.push_back(opts_array.at(i).c_str());
177 }
178
179 llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID;
180 llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts;
181 clang::TextDiagnosticBuffer *DiagsBuffer;
182
183 DiagID = new clang::DiagnosticIDs();
184 DiagOpts = new clang::DiagnosticOptions();
185 DiagsBuffer = new clang::TextDiagnosticBuffer();
186
187 clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
188 bool Success;
189
190 Success = clang::CompilerInvocation::CreateFromArgs(c.getInvocation(),
191 opts_carray.data(),
192 opts_carray.data() + opts_carray.size(),
193 Diags);
194 if (!Success) {
195 throw error(CL_INVALID_BUILD_OPTIONS);
196 }
197 c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly;
198 c.getHeaderSearchOpts().UseBuiltinIncludes = true;
199 c.getHeaderSearchOpts().UseStandardSystemIncludes = true;
200 c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR;
201
202 // Add libclc generic search path
203 c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR,
204 clang::frontend::Angled,
205 false, false
206 #if HAVE_LLVM < 0x0303
207 , false
208 #endif
209 );
210
211 // Add libclc include
212 c.getPreprocessorOpts().Includes.push_back("clc/clc.h");
213
214 // clc.h requires that this macro be defined:
215 c.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers");
216 c.getPreprocessorOpts().addMacroDef("cl_khr_fp64");
217
218 c.getLangOpts().NoBuiltin = true;
219 c.getTargetOpts().Triple = triple;
220 c.getTargetOpts().CPU = processor;
221
222 // This is a workaround for a Clang bug which causes the number
223 // of warnings and errors to be printed to stderr.
224 // http://www.llvm.org/bugs/show_bug.cgi?id=19735
225 c.getDiagnosticOpts().ShowCarets = false;
226 #if HAVE_LLVM <= 0x0301
227 c.getInvocation().setLangDefaults(clang::IK_OpenCL);
228 #else
229 c.getInvocation().setLangDefaults(c.getLangOpts(), clang::IK_OpenCL,
230 clang::LangStandard::lang_opencl11);
231 #endif
232 c.createDiagnostics(
233 #if HAVE_LLVM < 0x0303
234 0, NULL,
235 #endif
236 new clang::TextDiagnosticPrinter(
237 s_log,
238 #if HAVE_LLVM <= 0x0301
239 c.getDiagnosticOpts()));
240 #else
241 &c.getDiagnosticOpts()));
242 #endif
243
244 #if HAVE_LLVM >= 0x0306
245 c.getPreprocessorOpts().addRemappedFile(name,
246 llvm::MemoryBuffer::getMemBuffer(source).release());
247 #else
248 c.getPreprocessorOpts().addRemappedFile(name,
249 llvm::MemoryBuffer::getMemBuffer(source));
250 #endif
251
252 if (headers.size()) {
253 const std::string tmp_header_path = "/tmp/clover/";
254
255 c.getHeaderSearchOpts().AddPath(tmp_header_path,
256 clang::frontend::Angled,
257 false, false
258 #if HAVE_LLVM < 0x0303
259 , false
260 #endif
261 );
262
263 for (header_map::const_iterator it = headers.begin();
264 it != headers.end(); ++it) {
265 const std::string path = tmp_header_path + std::string(it->first);
266 c.getPreprocessorOpts().addRemappedFile(path,
267 #if HAVE_LLVM >= 0x0306
268 llvm::MemoryBuffer::getMemBuffer(it->second.c_str()).release());
269 #else
270 llvm::MemoryBuffer::getMemBuffer(it->second.c_str()));
271 #endif
272 }
273 }
274
275 // Setting this attribute tells clang to link this file before
276 // performing any optimizations. This is required so that
277 // we can replace calls to the OpenCL C barrier() builtin
278 // with calls to target intrinsics that have the noduplicate
279 // attribute. This attribute will prevent Clang from creating
280 // illegal uses of barrier() (e.g. Moving barrier() inside a conditional
281 // that is no executed by all threads) during its optimizaton passes.
282 c.getCodeGenOpts().LinkBitcodeFile = libclc_path;
283
284 optimization_level = c.getCodeGenOpts().OptimizationLevel;
285
286 // Compile the code
287 bool ExecSuccess = c.ExecuteAction(act);
288 r_log = log;
289
290 if (!ExecSuccess)
291 throw build_error();
292
293 // Get address spaces map to be able to find kernel argument address space
294 memcpy(address_spaces, c.getTarget().getAddressSpaceMap(),
295 sizeof(address_spaces));
296
297 #if HAVE_LLVM >= 0x0306
298 return act.takeModule().release();
299 #else
300 return act.takeModule();
301 #endif
302 }
303
304 void
305 find_kernels(llvm::Module *mod, std::vector<llvm::Function *> &kernels) {
306 const llvm::NamedMDNode *kernel_node =
307 mod->getNamedMetadata("opencl.kernels");
308 // This means there are no kernels in the program. The spec does not
309 // require that we return an error here, but there will be an error if
310 // the user tries to pass this program to a clCreateKernel() call.
311 if (!kernel_node) {
312 return;
313 }
314
315 for (unsigned i = 0; i < kernel_node->getNumOperands(); ++i) {
316 kernels.push_back(llvm::dyn_cast<llvm::Function>(
317 kernel_node->getOperand(i)->getOperand(0)));
318 }
319 }
320
321 void
322 optimize(llvm::Module *mod, unsigned optimization_level,
323 const std::vector<llvm::Function *> &kernels) {
324
325 llvm::PassManager PM;
326 // Add a function internalizer pass.
327 //
328 // By default, the function internalizer pass will look for a function
329 // called "main" and then mark all other functions as internal. Marking
330 // functions as internal enables the optimizer to perform optimizations
331 // like function inlining and global dead-code elimination.
332 //
333 // When there is no "main" function in a module, the internalize pass will
334 // treat the module like a library, and it won't internalize any functions.
335 // Since there is no "main" function in our kernels, we need to tell
336 // the internalizer pass that this module is not a library by passing a
337 // list of kernel functions to the internalizer. The internalizer will
338 // treat the functions in the list as "main" functions and internalize
339 // all of the other functions.
340 std::vector<const char*> export_list;
341 for (std::vector<llvm::Function *>::const_iterator I = kernels.begin(),
342 E = kernels.end();
343 I != E; ++I) {
344 llvm::Function *kernel = *I;
345 export_list.push_back(kernel->getName().data());
346 }
347 #if HAVE_LLVM < 0x0306
348 PM.add(new llvm::DataLayoutPass(mod));
349 #else
350 PM.add(new llvm::DataLayoutPass());
351 #endif
352 PM.add(llvm::createInternalizePass(export_list));
353
354 llvm::PassManagerBuilder PMB;
355 PMB.OptLevel = optimization_level;
356 PMB.LibraryInfo = new llvm::TargetLibraryInfo(
357 llvm::Triple(mod->getTargetTriple()));
358 PMB.populateModulePassManager(PM);
359 PM.run(*mod);
360 }
361
362 compat::vector<module::argument>
363 get_kernel_args(const llvm::Module *mod, const std::string &kernel_name,
364 const clang::LangAS::Map &address_spaces) {
365
366 compat::vector<module::argument> args;
367 llvm::Function *kernel_func = mod->getFunction(kernel_name);
368
369 #if HAVE_LLVM < 0x0302
370 llvm::TargetData TD(kernel_func->getParent());
371 #elif HAVE_LLVM < 0x0305
372 llvm::DataLayout TD(kernel_func->getParent()->getDataLayout());
373 #else
374 llvm::DataLayout TD(mod);
375 #endif
376
377 for (llvm::Function::const_arg_iterator I = kernel_func->arg_begin(),
378 E = kernel_func->arg_end(); I != E; ++I) {
379 const llvm::Argument &arg = *I;
380
381 llvm::Type *arg_type = arg.getType();
382 const unsigned arg_store_size = TD.getTypeStoreSize(arg_type);
383
384 // OpenCL 1.2 specification, Ch. 6.1.5: "A built-in data
385 // type that is not a power of two bytes in size must be
386 // aligned to the next larger power of two". We need this
387 // alignment for three element vectors, which have
388 // non-power-of-2 store size.
389 const unsigned arg_api_size = util_next_power_of_two(arg_store_size);
390
391 llvm::Type *target_type = arg_type->isIntegerTy() ?
392 TD.getSmallestLegalIntType(mod->getContext(), arg_store_size * 8)
393 : arg_type;
394 unsigned target_size = TD.getTypeStoreSize(target_type);
395 unsigned target_align = TD.getABITypeAlignment(target_type);
396
397 if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) {
398 arg_type =
399 llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType();
400 }
401
402 if (arg_type->isPointerTy()) {
403 unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace();
404 if (address_space == address_spaces[clang::LangAS::opencl_local
405 - clang::LangAS::Offset]) {
406 args.push_back(module::argument(module::argument::local,
407 arg_api_size, target_size,
408 target_align,
409 module::argument::zero_ext));
410 } else {
411 // XXX: Correctly handle constant address space. There is no
412 // way for r600g to pass a handle for constant buffers back
413 // to clover like it can for global buffers, so
414 // creating constant arguments will break r600g. For now,
415 // continue treating constant buffers as global buffers
416 // until we can come up with a way to create handles for
417 // constant buffers.
418 args.push_back(module::argument(module::argument::global,
419 arg_api_size, target_size,
420 target_align,
421 module::argument::zero_ext));
422 }
423
424 } else {
425 llvm::AttributeSet attrs = kernel_func->getAttributes();
426 enum module::argument::ext_type ext_type =
427 (attrs.hasAttribute(arg.getArgNo() + 1,
428 llvm::Attribute::SExt) ?
429 module::argument::sign_ext :
430 module::argument::zero_ext);
431
432 args.push_back(
433 module::argument(module::argument::scalar, arg_api_size,
434 target_size, target_align, ext_type));
435 }
436 }
437
438 // Append implicit arguments. XXX - The types, ordering and
439 // vector size of the implicit arguments should depend on the
440 // target according to the selected calling convention.
441 llvm::Type *size_type =
442 TD.getSmallestLegalIntType(mod->getContext(), sizeof(cl_uint) * 8);
443
444 args.push_back(
445 module::argument(module::argument::scalar, sizeof(cl_uint),
446 TD.getTypeStoreSize(size_type),
447 TD.getABITypeAlignment(size_type),
448 module::argument::zero_ext,
449 module::argument::grid_dimension));
450
451 args.push_back(
452 module::argument(module::argument::scalar, sizeof(cl_uint),
453 TD.getTypeStoreSize(size_type),
454 TD.getABITypeAlignment(size_type),
455 module::argument::zero_ext,
456 module::argument::grid_offset));
457
458 return args;
459 }
460
461 module
462 build_module_llvm(llvm::Module *mod,
463 const std::vector<llvm::Function *> &kernels,
464 clang::LangAS::Map& address_spaces) {
465
466 module m;
467 struct pipe_llvm_program_header header;
468
469 llvm::SmallVector<char, 1024> llvm_bitcode;
470 llvm::raw_svector_ostream bitcode_ostream(llvm_bitcode);
471 llvm::BitstreamWriter writer(llvm_bitcode);
472 llvm::WriteBitcodeToFile(mod, bitcode_ostream);
473 bitcode_ostream.flush();
474
475 for (unsigned i = 0; i < kernels.size(); ++i) {
476 std::string kernel_name = kernels[i]->getName();
477 compat::vector<module::argument> args =
478 get_kernel_args(mod, kernel_name, address_spaces);
479
480 m.syms.push_back(module::symbol(kernel_name, 0, i, args ));
481 }
482
483 header.num_bytes = llvm_bitcode.size();
484 std::string data;
485 data.insert(0, (char*)(&header), sizeof(header));
486 data.insert(data.end(), llvm_bitcode.begin(),
487 llvm_bitcode.end());
488 m.secs.push_back(module::section(0, module::section::text,
489 header.num_bytes, data));
490
491 return m;
492 }
493
494 void
495 emit_code(LLVMTargetMachineRef tm, LLVMModuleRef mod,
496 LLVMCodeGenFileType file_type,
497 LLVMMemoryBufferRef *out_buffer,
498 compat::string &r_log) {
499 LLVMBool err;
500 char *err_message = NULL;
501
502 err = LLVMTargetMachineEmitToMemoryBuffer(tm, mod, file_type,
503 &err_message, out_buffer);
504
505 if (err) {
506 r_log = std::string(err_message);
507 }
508
509 LLVMDisposeMessage(err_message);
510
511 if (err) {
512 throw build_error();
513 }
514 }
515
516 std::vector<char>
517 compile_native(const llvm::Module *mod, const std::string &triple,
518 const std::string &processor, unsigned dump_asm,
519 compat::string &r_log) {
520
521 std::string log;
522 LLVMTargetRef target;
523 char *error_message;
524 LLVMMemoryBufferRef out_buffer;
525 unsigned buffer_size;
526 const char *buffer_data;
527 LLVMModuleRef mod_ref = wrap(mod);
528
529 if (LLVMGetTargetFromTriple(triple.c_str(), &target, &error_message)) {
530 r_log = std::string(error_message);
531 LLVMDisposeMessage(error_message);
532 throw build_error();
533 }
534
535 LLVMTargetMachineRef tm = LLVMCreateTargetMachine(
536 target, triple.c_str(), processor.c_str(), "",
537 LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault);
538
539 if (!tm) {
540 r_log = "Could not create TargetMachine: " + triple;
541 throw build_error();
542 }
543
544 if (dump_asm) {
545 LLVMSetTargetMachineAsmVerbosity(tm, true);
546 LLVMModuleRef debug_mod = wrap(llvm::CloneModule(mod));
547 emit_code(tm, debug_mod, LLVMAssemblyFile, &out_buffer, r_log);
548 buffer_size = LLVMGetBufferSize(out_buffer);
549 buffer_data = LLVMGetBufferStart(out_buffer);
550 debug_log(std::string(buffer_data, buffer_size), ".asm");
551
552 LLVMSetTargetMachineAsmVerbosity(tm, false);
553 LLVMDisposeMemoryBuffer(out_buffer);
554 LLVMDisposeModule(debug_mod);
555 }
556
557 emit_code(tm, mod_ref, LLVMObjectFile, &out_buffer, r_log);
558
559 buffer_size = LLVMGetBufferSize(out_buffer);
560 buffer_data = LLVMGetBufferStart(out_buffer);
561
562 std::vector<char> code(buffer_data, buffer_data + buffer_size);
563
564 LLVMDisposeMemoryBuffer(out_buffer);
565 LLVMDisposeTargetMachine(tm);
566
567 return code;
568 }
569
570 std::map<std::string, unsigned>
571 get_kernel_offsets(std::vector<char> &code,
572 const std::vector<llvm::Function *> &kernels,
573 compat::string &r_log) {
574
575 // One of the libelf implementations
576 // (http://www.mr511.de/software/english.htm) requires calling
577 // elf_version() before elf_memory().
578 //
579 elf_version(EV_CURRENT);
580
581 Elf *elf = elf_memory(&code[0], code.size());
582 size_t section_str_index;
583 elf_getshdrstrndx(elf, &section_str_index);
584 Elf_Scn *section = NULL;
585 Elf_Scn *symtab = NULL;
586 GElf_Shdr symtab_header;
587
588 // Find the symbol table
589 try {
590 while ((section = elf_nextscn(elf, section))) {
591 const char *name;
592 if (gelf_getshdr(section, &symtab_header) != &symtab_header) {
593 r_log = "Failed to read ELF section header.";
594 throw build_error();
595 }
596 name = elf_strptr(elf, section_str_index, symtab_header.sh_name);
597 if (!strcmp(name, ".symtab")) {
598 symtab = section;
599 break;
600 }
601 }
602 if (!symtab) {
603 r_log = "Unable to find symbol table.";
604 throw build_error();
605 }
606 } catch (build_error &e) {
607 elf_end(elf);
608 throw e;
609 }
610
611
612 // Extract symbol information from the table
613 Elf_Data *symtab_data = NULL;
614 GElf_Sym *symbol;
615 GElf_Sym s;
616
617 std::map<std::string, unsigned> kernel_offsets;
618 symtab_data = elf_getdata(symtab, symtab_data);
619
620 // Determine the offsets for each kernel
621 for (int i = 0; (symbol = gelf_getsym(symtab_data, i, &s)); i++) {
622 char *name = elf_strptr(elf, symtab_header.sh_link, symbol->st_name);
623 for (std::vector<llvm::Function*>::const_iterator it = kernels.begin(),
624 e = kernels.end(); it != e; ++it) {
625 llvm::Function *f = *it;
626 if (f->getName() == std::string(name))
627 kernel_offsets[f->getName()] = symbol->st_value;
628 }
629 }
630 elf_end(elf);
631 return kernel_offsets;
632 }
633
634 module
635 build_module_native(std::vector<char> &code,
636 const llvm::Module *mod,
637 const std::vector<llvm::Function *> &kernels,
638 const clang::LangAS::Map &address_spaces,
639 compat::string &r_log) {
640
641 std::map<std::string, unsigned> kernel_offsets =
642 get_kernel_offsets(code, kernels, r_log);
643
644 // Begin building the clover module
645 module m;
646 struct pipe_llvm_program_header header;
647
648 // Store the generated ELF binary in the module's text section.
649 header.num_bytes = code.size();
650 std::string data;
651 data.append((char*)(&header), sizeof(header));
652 data.append(code.begin(), code.end());
653 m.secs.push_back(module::section(0, module::section::text,
654 header.num_bytes, data));
655
656 for (std::map<std::string, unsigned>::iterator i = kernel_offsets.begin(),
657 e = kernel_offsets.end(); i != e; ++i) {
658 compat::vector<module::argument> args =
659 get_kernel_args(mod, i->first, address_spaces);
660 m.syms.push_back(module::symbol(i->first, 0, i->second, args ));
661 }
662
663 return m;
664 }
665
666 #if HAVE_LLVM >= 0x0305
667
668 void
669 diagnostic_handler(const llvm::DiagnosticInfo &di, void *data) {
670 if (di.getSeverity() == llvm::DS_Error) {
671 std::string message = *(compat::string*)data;
672 llvm::raw_string_ostream stream(message);
673 llvm::DiagnosticPrinterRawOStream dp(stream);
674 di.print(dp);
675 stream.flush();
676 *(compat::string*)data = message;
677
678 throw build_error();
679 }
680 }
681
682 #endif
683
684 void
685 init_targets() {
686 static bool targets_initialized = false;
687 if (!targets_initialized) {
688 LLVMInitializeAllTargets();
689 LLVMInitializeAllTargetInfos();
690 LLVMInitializeAllTargetMCs();
691 LLVMInitializeAllAsmPrinters();
692 targets_initialized = true;
693 }
694 }
695 } // End anonymous namespace
696
697 #define DBG_CLC (1 << 0)
698 #define DBG_LLVM (1 << 1)
699 #define DBG_ASM (1 << 2)
700
701 static const struct debug_named_value debug_options[] = {
702 {"clc", DBG_CLC, "Dump the OpenCL C code for all kernels."},
703 {"llvm", DBG_LLVM, "Dump the generated LLVM IR for all kernels."},
704 {"asm", DBG_ASM, "Dump kernel assembly code for targets specifying "
705 "PIPE_SHADER_IR_NATIVE"},
706 DEBUG_NAMED_VALUE_END // must be last
707 };
708
709 module
710 clover::compile_program_llvm(const compat::string &source,
711 const header_map &headers,
712 enum pipe_shader_ir ir,
713 const compat::string &target,
714 const compat::string &opts,
715 compat::string &r_log) {
716
717 init_targets();
718 static unsigned debug_flags = debug_get_flags_option("CLOVER_DEBUG",
719 debug_options, 0);
720
721 std::vector<llvm::Function *> kernels;
722 size_t processor_str_len = std::string(target.begin()).find_first_of("-");
723 std::string processor(target.begin(), 0, processor_str_len);
724 std::string triple(target.begin(), processor_str_len + 1,
725 target.size() - processor_str_len - 1);
726 clang::LangAS::Map address_spaces;
727 llvm::LLVMContext llvm_ctx;
728 unsigned optimization_level;
729
730 #if HAVE_LLVM >= 0x0305
731 llvm_ctx.setDiagnosticHandler(diagnostic_handler, &r_log);
732 #endif
733
734 // The input file name must have the .cl extension in order for the
735 // CompilerInvocation class to recognize it as an OpenCL source file.
736 llvm::Module *mod = compile_llvm(llvm_ctx, source, headers, "input.cl",
737 triple, processor, opts, address_spaces,
738 optimization_level, r_log);
739
740 find_kernels(mod, kernels);
741
742 optimize(mod, optimization_level, kernels);
743
744 if (debug_flags & DBG_CLC)
745 debug_log(source, ".cl");
746
747 if (debug_flags & DBG_LLVM) {
748 std::string log;
749 llvm::raw_string_ostream s_log(log);
750 mod->print(s_log, NULL);
751 s_log.flush();
752 debug_log(log, ".ll");
753 }
754
755 module m;
756 // Build the clover::module
757 switch (ir) {
758 case PIPE_SHADER_IR_TGSI:
759 //XXX: Handle TGSI
760 assert(0);
761 m = module();
762 break;
763 case PIPE_SHADER_IR_LLVM:
764 m = build_module_llvm(mod, kernels, address_spaces);
765 break;
766 case PIPE_SHADER_IR_NATIVE: {
767 std::vector<char> code = compile_native(mod, triple, processor,
768 debug_flags & DBG_ASM, r_log);
769 m = build_module_native(code, mod, kernels, address_spaces, r_log);
770 break;
771 }
772 }
773 #if HAVE_LLVM >= 0x0306
774 // LLVM 3.6 and newer, the user takes ownership of the module.
775 delete mod;
776 #endif
777
778 return m;
779 }