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,std::string && source,enum il_type il_type)28 program::program(clover::context &ctx, std::string &&source,
29 enum il_type il_type) :
30 context(ctx), _devices(ctx.devices()), _source(std::move(source)),
31 _kernel_ref_counter(0), _il_type(il_type) {
32 }
33
program(clover::context & ctx,const ref_vector<device> & devs,const std::vector<binary> & binaries)34 program::program(clover::context &ctx,
35 const ref_vector<device> &devs,
36 const std::vector<binary> &binaries) :
37 context(ctx), _devices(devs), _kernel_ref_counter(0),
38 _il_type(il_type::none) {
39 for_each([&](device &dev, const binary &bin) {
40 _builds[&dev] = { bin };
41 },
42 devs, binaries);
43 }
44
45 void
compile(const ref_vector<device> & devs,const std::string & opts,const header_map & headers)46 program::compile(const ref_vector<device> &devs, const std::string &opts,
47 const header_map &headers) {
48 if (_il_type != il_type::none) {
49 _devices = devs;
50
51 for (auto &dev : devs) {
52 std::string log;
53
54 try {
55 const binary b =
56 compiler::compile_program(*this, headers, dev, opts, log);
57 _builds[&dev] = { b, opts, log };
58 } catch (...) {
59 _builds[&dev] = { binary(), opts, log };
60 throw;
61 }
62 }
63 }
64 }
65
66 void
link(const ref_vector<device> & devs,const std::string & opts,const ref_vector<program> & progs)67 program::link(const ref_vector<device> &devs, const std::string &opts,
68 const ref_vector<program> &progs) {
69 _devices = devs;
70
71 for (auto &dev : devs) {
72 const std::vector<binary> bs = map([&](const program &prog) {
73 return prog.build(dev).bin;
74 }, progs);
75 std::string log = _builds[&dev].log;
76
77 try {
78 const binary b = compiler::link_program(bs, dev, opts, log);
79 _builds[&dev] = { b, opts, log };
80 } catch (...) {
81 _builds[&dev] = { binary(), opts, log };
82 throw;
83 }
84 }
85 }
86
87 enum program::il_type
il_type() const88 program::il_type() const {
89 return _il_type;
90 }
91
92 const std::string &
source() const93 program::source() const {
94 return _source;
95 }
96
97 program::device_range
devices() const98 program::devices() const {
99 return map(evals(), _devices);
100 }
101
102 cl_build_status
status() const103 program::build::status() const {
104 if (!bin.secs.empty())
105 return CL_BUILD_SUCCESS;
106 else if (log.size())
107 return CL_BUILD_ERROR;
108 else
109 return CL_BUILD_NONE;
110 }
111
112 cl_program_binary_type
binary_type() const113 program::build::binary_type() const {
114 if (any_of(type_equals(binary::section::text_intermediate), bin.secs))
115 return CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
116 else if (any_of(type_equals(binary::section::text_library), bin.secs))
117 return CL_PROGRAM_BINARY_TYPE_LIBRARY;
118 else if (any_of(type_equals(binary::section::text_executable), bin.secs))
119 return CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
120 else
121 return CL_PROGRAM_BINARY_TYPE_NONE;
122 }
123
124 const struct program::build &
build(const device & dev) const125 program::build(const device &dev) const {
126 static const struct build null;
127 return _builds.count(&dev) ? _builds.find(&dev)->second : null;
128 }
129
130 const std::vector<binary::symbol> &
symbols() const131 program::symbols() const {
132 if (_builds.empty())
133 throw error(CL_INVALID_PROGRAM_EXECUTABLE);
134
135 return _builds.begin()->second.bin.syms;
136 }
137
138 unsigned
kernel_ref_count() const139 program::kernel_ref_count() const {
140 return _kernel_ref_counter.ref_count();
141 }
142