aboutsummaryrefslogtreecommitdiff
path: root/src/core/program.h
blob: 3e4d641f5801baa40a395c756d8fa3322e745697 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
/*
 * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr>
 * Copyright (c) 2012-2014, Texas Instruments Incorporated - http://www.ti.com/
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the copyright holder nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * \file core/program.h
 * \brief Program
 */

#ifndef __PROGRAM_H__
#define __PROGRAM_H__

#include "object.h"

#include <CL/cl.h>
#include <string>
#include <vector>

namespace llvm
{
    class MemoryBuffer;
    class Module;
    class Function;
}

namespace Coal
{

class Context;
class Compiler;
class DeviceInterface;
class DeviceProgram;
class Kernel;

/**
 * \brief Program object
 *
 * This class compiles and links a source or binaries into LLVM modules for each
 * \c Coal::DeviceInterface for which the program is built.
 *
 * It then contains functions to get the list of kernels available in the
 * program, using \c Coal::Kernel objects.
 */
class Program : public Object
{
    public:
        /**
         * \brief Constructor
         * \param ctx parent \c Coal::Context
         */
        Program(Context *ctx);
        ~Program();

        /**
         * \brief Program type
         */
        enum Type
        {
            Invalid, /*!< Invalid or unknown, type of a program not already loaded */
            Source,  /*!< Program made of sources that must be compiled and linked */
            Binary   /*!< Program made of pre-built binaries that only need to be (transformed)/linked */
        };

        /**
         * \brief Program state
         */
        enum State
        {
            Empty,   /*!< Just created */
            Loaded,  /*!< Source or binary loaded */
            Built,   /*!< Built */
            Compiled,/*!< Compiled */
            Failed,  /*!< Build failed */
        };

        /**
         * \brief Load sources into the program
         *
         * This function loads the source-code given in \p strings into the
         * program and sets its type to \c Source.
         *
         * \param count number of strings in \p strings
         * \param strings array of pointers to strings, either null-terminated
         *        or of length given in \p lengths
         * \param lengths lengths of the strings. If a field is 0, the
         *        corresponding string is null-terminated. If \p lengths is
         *        0, all the strings are null-terminated
         * \return \c CL_SUCCESS if success, an error code otherwise
         */
        cl_int loadSources(cl_uint count, const char **strings,
                           const size_t *lengths);

        /**
         * \brief Load binaries into the program
         *
         * This function allows client application to load a source, retrieve
         * binaries using \c buildInfo(), and then re-create the same program
         * (after a restart for example) by giving it a precompiled binary.
         *
         * This function loads the binaries for each device and parse them into
         * LLVM modules, then sets the program type to \c Binary or
         * \c NativeBinary.
         *
         * \param data array of pointers to binaries, one for each device
         * \param lengths lengths of the binaries pointed to by \p data
         * \param binary_status array that will be filled by this function with
         *        the status of each loaded binary (\c CL_SUCCESS if success)
         * \param num_devices number of devices for which a binary is loaded
         * \param device_list list of devices for which the binaries are loaded
         * \return \c CL_SUCCESS if success, an error code otherwise
         */
        cl_int loadBinaries(const unsigned char **data, const size_t *lengths,
                            cl_int *binary_status, cl_uint num_devices,
                            DeviceInterface * const*device_list);

        /**
         * \brief Compile the program
         * This function compiles a program's source for all the devices or a
         * specific device(s) in the OpenCL context associated with program.
         *
         * \param options options to pass to the compiler, see the OpenCL
         *        specification.
         * \param pfn_notify callback function called at the end of the build
         * \param user_data user data given to \p pfn_notify
         * \param num_devices number of devices for which binaries are being
         *        built. If it's a source-based program, this can be 0.
         * \param device_list list of devices for which the program will be built.
         * \param num_input_headers number of input headers listed in next two args:
         * \param input_headers list of cl_program objects containing embedded headers.
         * \param header_include_names An array of header pathnames, one to one
         *        correspondence with \p input_headers.
         * \return \c CL_SUCCESS if success, an error code otherwise
         */
        cl_int compile(const char *options,
                     void (CL_CALLBACK *pfn_notify)(cl_program program,
                                                    void *user_data),
                     void *user_data, cl_uint num_devices,
                     DeviceInterface * const*device_list,
                     cl_uint num_input_headers,
                     const cl_program *input_headers,
                     const char **header_include_names);

        /**
         * \brief Link a list of compiled binaries or libraries.
         * Links a set of compiled program objects and libraries for all the devices or
         * a specific device(s) in the OpenCL context and creates an executable.
         *
         * \param options options to pass to the linker, see the OpenCL
         *        specification.
         * \param pfn_notify callback function called at the end of the build
         * \param user_data user data given to \p pfn_notify
         * \param num_devices number of devices for which binaries are being
         *        built.
         * \param device_list list of devices for which the program will be built.
         * \param num_input_programs number of programs in array referenced by input_programs.
         * \param input_programs Array of compiled binaries or libraries to be linked.
         * \return \c CL_SUCCESS if success, an error code otherwise
         */
        cl_int link(const char *options,
                     void (CL_CALLBACK *pfn_notify)(cl_program program,
                                                    void *user_data),
                     void *user_data, cl_uint num_devices,
                     DeviceInterface * const * device_list,
                     cl_uint num_input_programs,
		     const cl_program * input_programs);

        /**
         * \brief Build the program
         *
         * This function compiles the sources, if any, and then link the
         * resulting binaries if the devices for which they are compiled asks
         * \c Coal::Program to do so, using \c Coal::DeviceProgram::linkStdLib().
         *
         * \param options options to pass to the compiler, see the OpenCL
         *        specification.
         * \param pfn_notify callback function called at the end of the build
         * \param user_data user data given to \p pfn_notify
         * \param num_devices number of devices for which binaries are being
         *        built. If it's a source-based program, this can be 0.
         * \param device_list list of devices for which the program will be built.
         * \return \c CL_SUCCESS if success, an error code otherwise
         */
        cl_int build(const char *options,
                     void (CL_CALLBACK *pfn_notify)(cl_program program,
                                                    void *user_data),
                     void *user_data, cl_uint num_devices,
                     DeviceInterface * const*device_list);

        Type type() const;   /*!< \brief Type of the program */
        State state() const; /*!< \brief State of the program */

        /**
         * \brief Create a kernel given a \p name
         * \param name name of the kernel to be created
         * \param errcode_ret return code (\c CL_SUCCESS if success)
         * \return a \c Coal::Kernel object corresponding to the given \p name
         */
        Kernel *createKernel(const std::string &name, cl_int *errcode_ret);

        /**
         * \brief Create kernels of the program and return given a \p name
         * \param name name of the kernel to be returned
         * \param errcode_ret return code (\c CL_SUCCESS if success)
         * \return a \c Coal::Kernel object corresponding to the given \p name
         */
        Kernel *createKernelsAndReturnKernel(const std::string &name, cl_int *errcode_ret);

        /**
         * \brief Create all the kernels of the program
         * \param errcode_ret return code (\c CL_SUCCESS if success)
         * \return the list of \c Coal::Kernel objects of this program
         */
        std::vector<Kernel *> createKernels(cl_int *errcode_ret);

        /**
         * \brief Device-specific program
         * \param device device for which the device-specific program is needed
         * \return the device-specific program requested, 0 if not found
         */
        DeviceProgram *deviceDependentProgram(DeviceInterface *device) const;
        std::string    deviceDependentCompilerOptions(DeviceInterface *device) const;

        /**
         * \brief Get information about this program
         * \copydetails Coal::DeviceInterface::info
         */
        cl_int info(cl_program_info param_name,
                    size_t param_value_size,
                    void *param_value,
                    size_t *param_value_size_ret) const;

        /**
         * \brief Get build info about this program (log, binaries, etc)
         * \copydetails Coal::DeviceInterface::info
         * \param device \c Coal::DeviceInterface for which info is needed
         */
        cl_int buildInfo(DeviceInterface *device,
                         cl_program_build_info param_name,
                         size_t param_value_size,
                         void *param_value,
                         size_t *param_value_size_ret) const;

        /**
         * \brief Get number of kernels in this program:
         */
        unsigned int getNumKernels() const;

        /**
         * \brief Get semicolon separated list of kernel names in this program
         */
        std::string getKernelNames() const;

        std::string source() { return p_source; }

        std::vector<Kernel *> kernelList;
        std::vector<Kernel *> kernelReleasedList;

    private:
        Type        p_type;
        State       p_state;
        cl_program_binary_type p_binary_type;
        std::string p_source;

        struct DeviceDependent
        {
            DeviceInterface * device;
            DeviceProgram   * program;
            std::string       unlinked_binary;
            bool              is_native_binary; // llvm kernel bitcode vs final native binary
            llvm::Module    * linked_module;
            Compiler        * compiler;
        };

        std::vector<DeviceDependent> p_device_dependent;
        DeviceDependent              p_null_device_dependent;

        void setDevices(cl_uint num_devices, DeviceInterface * const*devices);
	void resetDeviceDependent();
        DeviceDependent &deviceDependent(DeviceInterface *device);
        const DeviceDependent &deviceDependent(DeviceInterface *device) const;
        std::vector<llvm::Function *> kernelFunctions(DeviceDependent &dep);
};

}

struct _cl_program : public Coal::Program
{};

#endif