Home | History | Annotate | Download | only in core
      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/program.hpp"
     24 #include "llvm/invocation.hpp"
     25 #include "tgsi/invocation.hpp"
     26 
     27 using namespace clover;
     28 
     29 program::program(clover::context &ctx, const std::string &source) :
     30    has_source(true), context(ctx), _source(source), _kernel_ref_counter(0) {
     31 }
     32 
     33 program::program(clover::context &ctx,
     34                  const ref_vector<device> &devs,
     35                  const std::vector<module> &binaries) :
     36    has_source(false), context(ctx),
     37    _devices(devs), _kernel_ref_counter(0) {
     38    for_each([&](device &dev, const module &bin) {
     39          _builds[&dev] = { bin };
     40       },
     41       devs, binaries);
     42 }
     43 
     44 void
     45 program::compile(const ref_vector<device> &devs, const std::string &opts,
     46                  const header_map &headers) {
     47    if (has_source) {
     48       _devices = devs;
     49 
     50       for (auto &dev : devs) {
     51          std::string log;
     52 
     53          try {
     54             const module m = (dev.ir_format() == PIPE_SHADER_IR_TGSI ?
     55                               tgsi::compile_program(_source, log) :
     56                               llvm::compile_program(_source, headers,
     57                                                     dev.ir_target(), opts, log));
     58             _builds[&dev] = { m, opts, log };
     59          } catch (...) {
     60             _builds[&dev] = { module(), opts, log };
     61             throw;
     62          }
     63       }
     64    }
     65 }
     66 
     67 void
     68 program::link(const ref_vector<device> &devs, const std::string &opts,
     69               const ref_vector<program> &progs) {
     70    _devices = devs;
     71 
     72    for (auto &dev : devs) {
     73       const std::vector<module> ms = map([&](const program &prog) {
     74          return prog.build(dev).binary;
     75          }, progs);
     76       std::string log = _builds[&dev].log;
     77 
     78       try {
     79          const module m = (dev.ir_format() == PIPE_SHADER_IR_TGSI ?
     80                            tgsi::link_program(ms) :
     81                            llvm::link_program(ms, dev.ir_format(),
     82                                               dev.ir_target(), opts, log));
     83          _builds[&dev] = { m, opts, log };
     84       } catch (...) {
     85          _builds[&dev] = { module(), opts, log };
     86          throw;
     87       }
     88    }
     89 }
     90 
     91 const std::string &
     92 program::source() const {
     93    return _source;
     94 }
     95 
     96 program::device_range
     97 program::devices() const {
     98    return map(evals(), _devices);
     99 }
    100 
    101 cl_build_status
    102 program::build::status() const {
    103    if (!binary.secs.empty())
    104       return CL_BUILD_SUCCESS;
    105    else if (log.size())
    106       return CL_BUILD_ERROR;
    107    else
    108       return CL_BUILD_NONE;
    109 }
    110 
    111 cl_program_binary_type
    112 program::build::binary_type() const {
    113    if (any_of(type_equals(module::section::text_intermediate), binary.secs))
    114       return CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
    115    else if (any_of(type_equals(module::section::text_library), binary.secs))
    116       return CL_PROGRAM_BINARY_TYPE_LIBRARY;
    117    else if (any_of(type_equals(module::section::text_executable), binary.secs))
    118       return CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
    119    else
    120       return CL_PROGRAM_BINARY_TYPE_NONE;
    121 }
    122 
    123 const struct program::build &
    124 program::build(const device &dev) const {
    125    static const struct build null;
    126    return _builds.count(&dev) ? _builds.find(&dev)->second : null;
    127 }
    128 
    129 const std::vector<module::symbol> &
    130 program::symbols() const {
    131    if (_builds.empty())
    132       throw error(CL_INVALID_PROGRAM_EXECUTABLE);
    133 
    134    return _builds.begin()->second.binary.syms;
    135 }
    136 
    137 unsigned
    138 program::kernel_ref_count() const {
    139    return _kernel_ref_counter.ref_count();
    140 }
    141