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 #include "core/program.hpp"
25 
26 using namespace clover;
27 
program(clover::context & ctx,const std::string & source)28 program::program(clover::context &ctx, const std::string &source) :
29    has_source(true), context(ctx), _devices(ctx.devices()), _source(source),
30    _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 =
55                compiler::compile_program(_source, headers, dev, opts, log);
56             _builds[&dev] = { m, opts, log };
57          } catch (...) {
58             _builds[&dev] = { module(), opts, log };
59             throw;
60          }
61       }
62    }
63 }
64 
65 void
link(const ref_vector<device> & devs,const std::string & opts,const ref_vector<program> & progs)66 program::link(const ref_vector<device> &devs, const std::string &opts,
67               const ref_vector<program> &progs) {
68    _devices = devs;
69 
70    for (auto &dev : devs) {
71       const std::vector<module> ms = map([&](const program &prog) {
72          return prog.build(dev).binary;
73          }, progs);
74       std::string log = _builds[&dev].log;
75 
76       try {
77          const module m = compiler::link_program(ms, dev, opts, log);
78          _builds[&dev] = { m, opts, log };
79       } catch (...) {
80          _builds[&dev] = { module(), opts, log };
81          throw;
82       }
83    }
84 }
85 
86 const std::string &
source() const87 program::source() const {
88    return _source;
89 }
90 
91 program::device_range
devices() const92 program::devices() const {
93    return map(evals(), _devices);
94 }
95 
96 cl_build_status
status() const97 program::build::status() const {
98    if (!binary.secs.empty())
99       return CL_BUILD_SUCCESS;
100    else if (log.size())
101       return CL_BUILD_ERROR;
102    else
103       return CL_BUILD_NONE;
104 }
105 
106 cl_program_binary_type
binary_type() const107 program::build::binary_type() const {
108    if (any_of(type_equals(module::section::text_intermediate), binary.secs))
109       return CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
110    else if (any_of(type_equals(module::section::text_library), binary.secs))
111       return CL_PROGRAM_BINARY_TYPE_LIBRARY;
112    else if (any_of(type_equals(module::section::text_executable), binary.secs))
113       return CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
114    else
115       return CL_PROGRAM_BINARY_TYPE_NONE;
116 }
117 
118 const struct program::build &
build(const device & dev) const119 program::build(const device &dev) const {
120    static const struct build null;
121    return _builds.count(&dev) ? _builds.find(&dev)->second : null;
122 }
123 
124 const std::vector<module::symbol> &
symbols() const125 program::symbols() const {
126    if (_builds.empty())
127       throw error(CL_INVALID_PROGRAM_EXECUTABLE);
128 
129    return _builds.begin()->second.binary.syms;
130 }
131 
132 unsigned
kernel_ref_count() const133 program::kernel_ref_count() const {
134    return _kernel_ref_counter.ref_count();
135 }
136