const size_t * lengths,
cl_int * errcode_ret)
{
- NOT_IMPLEMENTED;
- return NULL;
+ cl_program program = NULL;
+ cl_int err = CL_SUCCESS;
+
+ CHECK_CONTEXT (context);
+ program = cl_program_create_from_source(context,
+ count,
+ strings,
+ lengths,
+ &err);
+error:
+ if (errcode_ret)
+ *errcode_ret = err;
+ return program;
}
cl_program
*errcode_ret = err;
return program;
}
-
cl_int
clRetainProgram(cl_program program)
{
void (CL_CALLBACK *pfn_notify) (cl_program, void*),
void * user_data)
{
- /* It does nothing today since we only support creation from binary. We just
- * try to follow OCL specification
- */
cl_int err = CL_SUCCESS;
CHECK_PROGRAM(program);
INVALID_VALUE_IF (num_devices > 1);
}
}
- /* XXX */
- FATAL_IF (pfn_notify != NULL || user_data != NULL,
- "No call back is supported now");
-
- /* TODO support create program from source */
- assert(program->from_source == CL_FALSE);
+ /* TODO support create program from binary */
+ assert(program->source_type == FROM_LLVM ||
+ program->source_type == FROM_SOURCE);
+ cl_program_build(program);
program->is_built = CL_TRUE;
+ if (pfn_notify) pfn_notify(program, user_data);
+
error:
return err;
}
#include <string.h>
#include <assert.h>
+static void
+cl_program_release_sources(cl_program p)
+{
+ int i;
+ if (p->sources == NULL) return;
+ for (i = 0; i < p->src_n; ++i)
+ if (p->sources[i]) cl_free(p->sources[i]);
+ cl_free(p->sources);
+ p->sources = NULL;
+ p->src_n = 0;
+}
+
LOCAL void
cl_program_delete(cl_program p)
{
return;
/* We are not done with it yet */
- if ((ref = atomic_dec(&p->ref_n)) > 1)
- return;
+ if ((ref = atomic_dec(&p->ref_n)) > 1) return;
+
+ /* Destroy the sources if still allocated */
+ cl_program_release_sources(p);
/* Remove it from the list */
assert(p->ctx);
INVALID_VALUE_IF (file_name == NULL);
program = cl_program_new(ctx);
-
program->opaque = gbe_program_new_from_llvm(file_name, 0, NULL, NULL);
- if (program->opaque == NULL) {
+ if (UNLIKELY(program->opaque == NULL)) {
err = CL_INVALID_PROGRAM;
goto error;
}
/* Create all the kernels */
TRY (cl_program_load_gen_program, program);
+ program->source_type = FROM_LLVM;
+
+exit:
+ if (errcode_ret)
+ *errcode_ret = err;
+ return program;
+error:
+ cl_program_delete(program);
+ program = NULL;
+ goto exit;
+}
+
+LOCAL cl_program
+cl_program_create_from_source(cl_context ctx,
+ cl_uint count,
+ const char **strings,
+ const size_t *lengths,
+ cl_int *errcode_ret)
+
+{
+ cl_program program = NULL;
+ cl_int err = CL_SUCCESS;
+ cl_int i;
+
+ assert(ctx);
+ INVALID_VALUE_IF (count == 0);
+ INVALID_VALUE_IF (strings == NULL);
+
+ // the real compilation step will be done at build time since we do not have
+ // yet the compilation options
+ program = cl_program_new(ctx);
+ TRY_ALLOC (program->sources, cl_calloc(count, sizeof(char*)));
+ for (i = 0; i < count; ++i) {
+ size_t len;
+ if (lengths == NULL || lengths[i] == 0)
+ len = strlen(strings[i]);
+ else
+ len = lengths[i];
+ TRY_ALLOC (program->sources[i], cl_calloc(len+1, sizeof(char)));
+ memcpy(program->sources[i], strings[i], len);
+ program->sources[i][len] = 0;
+ }
+ program->src_n = count;
+ program->source_type = FROM_SOURCE;
exit:
if (errcode_ret)
goto exit;
}
+LOCAL cl_int
+cl_program_build(cl_program p)
+{
+ cl_int err = CL_SUCCESS;
+
+ if (p->source_type == FROM_SOURCE) {
+ /* XXX support multiple sources later */
+ FATAL_IF (p->src_n != 1, "Only ONE source supported");
+ p->opaque = gbe_program_new_from_source(p->sources[0], 0, NULL, NULL);
+ if (UNLIKELY(p->opaque == NULL)) {
+ err = CL_INVALID_PROGRAM;
+ goto error;
+ }
+
+ /* Create all the kernels */
+ TRY (cl_program_load_gen_program, p);
+ p->source_type = FROM_LLVM;
+ }
+
+ p->is_built = 1;
+error:
+ return err;
+}
+
LOCAL cl_kernel
cl_program_create_kernel(cl_program p, const char *name, cl_int *errcode_ret)
{
// This is the structure ouput by the compiler
struct _gbe_program;
+enum {
+ FROM_SOURCE = 0,
+ FROM_LLVM = 1,
+ FROM_BINARY = 2
+};
+
/* This maps an OCL file containing some kernels */
struct _cl_program {
uint64_t magic; /* To identify it as a program */
cl_context ctx; /* Its parent context */
char *bin; /* The program copied verbatim */
size_t bin_sz; /* Its size in memory */
+ char **sources; /* Program sources */
+ size_t src_n; /* Number of sources */
uint32_t ker_n; /* Number of declared kernels */
- uint32_t from_source:1; /* Built from binary or source? */
+ uint32_t source_type:2; /* Built from binary, source or LLVM */
uint32_t is_built:1; /* Did we call clBuildProgram on it? */
};
/* Create a kernel for the OCL user */
extern cl_kernel cl_program_create_kernel(cl_program, const char*, cl_int*);
+/* Create a program from OCL source */
+extern cl_program
+cl_program_create_from_source(cl_context ctx,
+ cl_uint count,
+ const char **strings,
+ const size_t *lengths,
+ cl_int *errcode_ret);
+
/* Directly create a program from a blob */
extern cl_program
cl_program_create_from_binary(cl_context context,
const char * fileName,
cl_int * errcode_ret);
+/* Build the program as specified by OCL */
+extern cl_int
+cl_program_build(cl_program p);
+
#endif /* __CL_PROGRAM_H__ */