• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
program(clover::context & ctx,const std::string & source)29 program::program(clover::context &ctx, const std::string &source) :
30    has_source(true), context(ctx), _source(source), _kernel_ref_counter(0) {
31 }
32 
program(clover::context & ctx,const ref_vector<device> & devs,const std::vector<module> & binaries)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
compile(const ref_vector<device> & devs,const std::string & opts,const header_map & headers)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
link(const ref_vector<device> & devs,const std::string & opts,const ref_vector<program> & progs)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 &
source() const92 program::source() const {
93    return _source;
94 }
95 
96 program::device_range
devices() const97 program::devices() const {
98    return map(evals(), _devices);
99 }
100 
101 cl_build_status
status() const102 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
binary_type() const112 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 &
build(const device & dev) const124 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> &
symbols() const130 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
kernel_ref_count() const138 program::kernel_ref_count() const {
139    return _kernel_ref_counter.ref_count();
140 }
141