clover/llvm: Use device in llvm compilation instead of copying fields
[mesa.git] / src / gallium / state_trackers / clover / core / program.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/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, dev,
57 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, opts, log));
82 _builds[&dev] = { m, opts, log };
83 } catch (...) {
84 _builds[&dev] = { module(), opts, log };
85 throw;
86 }
87 }
88 }
89
90 const std::string &
91 program::source() const {
92 return _source;
93 }
94
95 program::device_range
96 program::devices() const {
97 return map(evals(), _devices);
98 }
99
100 cl_build_status
101 program::build::status() const {
102 if (!binary.secs.empty())
103 return CL_BUILD_SUCCESS;
104 else if (log.size())
105 return CL_BUILD_ERROR;
106 else
107 return CL_BUILD_NONE;
108 }
109
110 cl_program_binary_type
111 program::build::binary_type() const {
112 if (any_of(type_equals(module::section::text_intermediate), binary.secs))
113 return CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
114 else if (any_of(type_equals(module::section::text_library), binary.secs))
115 return CL_PROGRAM_BINARY_TYPE_LIBRARY;
116 else if (any_of(type_equals(module::section::text_executable), binary.secs))
117 return CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
118 else
119 return CL_PROGRAM_BINARY_TYPE_NONE;
120 }
121
122 const struct program::build &
123 program::build(const device &dev) const {
124 static const struct build null;
125 return _builds.count(&dev) ? _builds.find(&dev)->second : null;
126 }
127
128 const std::vector<module::symbol> &
129 program::symbols() const {
130 if (_builds.empty())
131 throw error(CL_INVALID_PROGRAM_EXECUTABLE);
132
133 return _builds.begin()->second.binary.syms;
134 }
135
136 unsigned
137 program::kernel_ref_count() const {
138 return _kernel_ref_counter.ref_count();
139 }