[Beignet] [PATCH V5] add binary type support for compiled object and library.

xionghu.luo at intel.com xionghu.luo at intel.com
Tue Jun 17 14:16:04 PDT 2014


From: Luo <xionghu.luo at intel.com>

save the llvm bitcode to program->binary: insert a byte in front of the
bitcode stands for binary type(0 means GEN binary, 1 means COMPILED_OBJECT, 2 means LIBRARY);
load the binary to module by ParseIR.

create random directory to save compile header files.
use strncpy and strncat to replace strcpy and strcat.

Signed-off-by: Luo <xionghu.luo at intel.com>
---
 backend/src/backend/gen_program.cpp | 71 +++++++++++++++++++++++++++++++-----
 backend/src/backend/program.cpp     |  1 +
 backend/src/backend/program.h       |  8 +++--
 backend/src/gbe_bin_generater.cpp   | 16 ++++++++-
 src/cl_api.c                        | 25 +++++++++++--
 src/cl_gbe_loader.cpp               | 11 ++++--
 src/cl_gbe_loader.h                 | 10 +++---
 src/cl_program.c                    | 72 +++++++++++++++++++++++++++++++++----
 src/cl_program.h                    |  1 +
 9 files changed, 187 insertions(+), 28 deletions(-)

diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index 300741e..8897dbb 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -35,6 +35,12 @@
 
 #include "llvm/Linker.h"
 #include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/IRReader/IRReader.h"
 
 #include "backend/program.h"
 #include "backend/gen_program.h"
@@ -55,6 +61,7 @@
 #include <iostream>
 #include <fstream>
 #include <mutex>
+#include <unistd.h>
 
 namespace gbe {
 
@@ -188,7 +195,8 @@ namespace gbe {
   static gbe_program genProgramNewFromBinary(uint32_t deviceID, const char *binary, size_t size) {
     using namespace gbe;
     std::string binary_content;
-    binary_content.assign(binary, size);
+    //the first 5 bytes are header to differentiate from llvm bitcode binary.
+    binary_content.assign(binary+5, size-5);
     GenProgram *program = GBE_NEW(GenProgram, deviceID);
     std::istringstream ifs(binary_content, std::ostringstream::binary);
     // FIXME we need to check the whether the current device ID match the binary file's.
@@ -203,20 +211,66 @@ namespace gbe {
     return reinterpret_cast<gbe_program>(program);
   }
 
-  static size_t genProgramSerializeToBinary(gbe_program program, char **binary) {
+  static gbe_program genProgramNewFromLLVMBinary(uint32_t deviceID, const char *binary, size_t size) {
+#ifdef GBE_COMPILER_AVAILABLE
+    using namespace gbe;
+    std::string binary_content;
+    //the first byte stands for binary_type.
+    binary_content.assign(binary+1, size-1);
+    llvm::StringRef llvm_bin_str(binary_content);
+    llvm::LLVMContext& c = llvm::getGlobalContext();
+    llvm::SMDiagnostic Err;
+    llvm::MemoryBuffer* memory_buffer = llvm::MemoryBuffer::getMemBuffer(llvm_bin_str, "llvm_bin_str");
+    acquireLLVMContextLock();
+    llvm::Module* module = llvm::ParseIR(memory_buffer, Err, c);
+    releaseLLVMContextLock();
+    if(module == NULL){
+      GBE_ASSERT(0);
+    }
+
+    GenProgram *program = GBE_NEW(GenProgram, deviceID, module);
+
+    //program->printStatus(0, std::cout);
+    return reinterpret_cast<gbe_program>(program);
+#else
+      return NULL;
+#endif
+  }
+
+  static size_t genProgramSerializeToBinary(gbe_program program, char **binary, int binary_type) {
     using namespace gbe;
     size_t sz;
     std::ostringstream oss;
     GenProgram *prog = (GenProgram*)program;
 
-    if ((sz = prog->serializeToBin(oss)) == 0) {
-      *binary = 0;
+    //0 means GEN binary, 1 means LLVM bitcode compiled object, 2 means LLVM bitcode library
+    if(binary_type == 0){
+      if ((sz = prog->serializeToBin(oss)) == 0) {
+        *binary = NULL;
+        return 0;
+      }
+
+      //add header to differetiate from llvm bitcode binary.
+      //the header length is 5 bytes: 1 binary type, 4 bitcode header.
+      *binary = (char *)malloc(sizeof(char) * (sz+5) );
+      memset(*binary, 0, sizeof(char) * (sz+5) );
+      memcpy(*binary+5, oss.str().c_str(), sz*sizeof(char));
+      return sz+5;
+    }else{
+#ifdef GBE_COMPILER_AVAILABLE
+      std::string str;
+      llvm::raw_string_ostream OS(str);
+      llvm::WriteBitcodeToFile((llvm::Module*)prog->module, OS);
+      std::string& bin_str = OS.str();
+      int llsz = bin_str.size();
+      *binary = (char *)malloc(sizeof(char) * (llsz+1) );
+      *(*binary) = binary_type;
+      memcpy(*binary+1, bin_str.c_str(), llsz);
+      return llsz+1;
+#else
       return 0;
+#endif
     }
-
-    *binary = (char *)malloc(sizeof(char) * sz);
-    memcpy(*binary, oss.str().c_str(), sz*sizeof(char));
-    return sz;
   }
 
   static gbe_program genProgramNewFromLLVM(uint32_t deviceID,
@@ -337,6 +391,7 @@ namespace gbe {
 void genSetupCallBacks(void)
 {
   gbe_program_new_from_binary = gbe::genProgramNewFromBinary;
+  gbe_program_new_from_llvm_binary = gbe::genProgramNewFromLLVMBinary;
   gbe_program_serialize_to_binary = gbe::genProgramSerializeToBinary;
   gbe_program_new_from_llvm = gbe::genProgramNewFromLLVM;
   gbe_program_new_gen_program = gbe::genProgramNewGenProgram;
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index 45983fd..98e7ab7 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -1158,6 +1158,7 @@ GBE_EXPORT_SYMBOL gbe_program_new_from_source_cb *gbe_program_new_from_source =
 GBE_EXPORT_SYMBOL gbe_program_compile_from_source_cb *gbe_program_compile_from_source = NULL;
 GBE_EXPORT_SYMBOL gbe_program_link_program_cb *gbe_program_link_program = NULL;
 GBE_EXPORT_SYMBOL gbe_program_new_from_binary_cb *gbe_program_new_from_binary = NULL;
+GBE_EXPORT_SYMBOL gbe_program_new_from_llvm_binary_cb *gbe_program_new_from_llvm_binary = NULL;
 GBE_EXPORT_SYMBOL gbe_program_serialize_to_binary_cb *gbe_program_serialize_to_binary = NULL;
 GBE_EXPORT_SYMBOL gbe_program_new_from_llvm_cb *gbe_program_new_from_llvm = NULL;
 GBE_EXPORT_SYMBOL gbe_program_new_gen_program_cb *gbe_program_new_gen_program = NULL;
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h
index 508fe64..c56b94a 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -179,8 +179,12 @@ extern gbe_program_new_gen_program_cb *gbe_program_new_gen_program;
 typedef gbe_program (gbe_program_new_from_binary_cb)(uint32_t deviceID, const char *binary, size_t size);
 extern gbe_program_new_from_binary_cb *gbe_program_new_from_binary;
 
-/*! Serialize a program to a bin */
-typedef size_t (gbe_program_serialize_to_binary_cb)(gbe_program program, char **binary);
+/*! Create a new program from the llvm bitcode*/
+typedef gbe_program (gbe_program_new_from_llvm_binary_cb)(uint32_t deviceID, const char *binary, size_t size);
+extern gbe_program_new_from_llvm_binary_cb *gbe_program_new_from_llvm_binary;
+
+/*! Serialize a program to a bin, 0 means executable, 1 means llvm bitcode*/
+typedef size_t (gbe_program_serialize_to_binary_cb)(gbe_program program, char **binary, int binary_type);
 extern gbe_program_serialize_to_binary_cb *gbe_program_serialize_to_binary;
 
 /*! Create a new program from the given LLVM file */
diff --git a/backend/src/gbe_bin_generater.cpp b/backend/src/gbe_bin_generater.cpp
index dce0792..a6b73d4 100644
--- a/backend/src/gbe_bin_generater.cpp
+++ b/backend/src/gbe_bin_generater.cpp
@@ -38,6 +38,7 @@
 
 #include "backend/program.h"
 #include "backend/program.hpp"
+#include "backend/src/sys/platform.hpp"
 
 using namespace std;
 
@@ -148,14 +149,24 @@ public:
 
 string program_build_instance::bin_path;
 bool program_build_instance::str_fmt_out = false;
+#define OUT_UPDATE_SZ(elt) SERIALIZE_OUT(elt, oss, header_sz)
 
 void program_build_instance::serialize_program(void) throw(int)
 {
     ofstream ofs;
     ostringstream oss;
-    size_t sz;
+    size_t sz, header_sz = 0;
     ofs.open(bin_path, ofstream::out | ofstream::trunc | ofstream::binary);
 
+    //add header to differeciate from llvm bitcode binary.
+    // (5 bytes: 1 byte for binary type, 4 byte for bc code.)
+    char header = '0';
+    OUT_UPDATE_SZ(header);
+    OUT_UPDATE_SZ(header);
+    OUT_UPDATE_SZ(header);
+    OUT_UPDATE_SZ(header);
+    OUT_UPDATE_SZ(header);
+
     if (str_fmt_out) {
         string array_name = "Unkown_name_array";
         unsigned long last_slash = bin_path.rfind("/");
@@ -168,6 +179,8 @@ void program_build_instance::serialize_program(void) throw(int)
 
         sz = gbe_prog->serializeToBin(oss);
 
+        sz+=5;
+
         for (size_t i = 0; i < sz; i++) {
             unsigned char c = oss.str().c_str()[i];
             char asic_str[9];
@@ -181,6 +194,7 @@ void program_build_instance::serialize_program(void) throw(int)
 	string array_size = array_name + "_size";
 	ofs << "int " << array_size << " = " << sz << ";" << "\n";
     } else {
+        ofs << "00000";
         sz = gbe_prog->serializeToBin(ofs);
     }
 
diff --git a/src/cl_api.c b/src/cl_api.c
index 327f02b..c4a8730 100644
--- a/src/cl_api.c
+++ b/src/cl_api.c
@@ -1065,8 +1065,16 @@ clGetProgramInfo(cl_program       program,
     FILL_GETINFO_RET (char, (strlen(program->source) + 1),
                    program->source, CL_SUCCESS);
   } else if (param_name == CL_PROGRAM_BINARY_SIZES) {
-    if (program->binary == NULL) {
-      program->binary_sz = compiler_program_serialize_to_binary(program->opaque, &program->binary);
+    if (program->binary == NULL){
+      if( program->binary_type == CL_PROGRAM_BINARY_TYPE_EXECUTABLE) {
+        program->binary_sz = compiler_program_serialize_to_binary(program->opaque, &program->binary, 0);
+      }else if( program->binary_type == CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT) {
+        program->binary_sz = compiler_program_serialize_to_binary(program->opaque, &program->binary, 1);
+      }else if( program->binary_type == CL_PROGRAM_BINARY_TYPE_LIBRARY) {
+        program->binary_sz = compiler_program_serialize_to_binary(program->opaque, &program->binary, 2);
+      }else{
+        return CL_INVALID_BINARY;
+      }
     }
 
     if (program->binary == NULL || program->binary_sz == 0) {
@@ -1082,7 +1090,15 @@ clGetProgramInfo(cl_program       program,
     /* param_value points to an array of n
        pointers allocated by the caller */
     if (program->binary == NULL) {
-      program->binary_sz = compiler_program_serialize_to_binary(program->opaque, &program->binary);
+      if( program->binary_type == CL_PROGRAM_BINARY_TYPE_EXECUTABLE) {
+        program->binary_sz = compiler_program_serialize_to_binary(program->opaque, &program->binary, 0);
+      }else if( program->binary_type == CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT) {
+        program->binary_sz = compiler_program_serialize_to_binary(program->opaque, &program->binary, 1);
+      }else if( program->binary_type == CL_PROGRAM_BINARY_TYPE_LIBRARY) {
+        program->binary_sz = compiler_program_serialize_to_binary(program->opaque, &program->binary, 2);
+      }else{
+        return CL_INVALID_BINARY;
+      }
     }
 
     if (program->binary == NULL || program->binary_sz == 0) {
@@ -1134,6 +1150,9 @@ clGetProgramBuildInfo(cl_program             program,
     FILL_GETINFO_RET (char, program->build_log_sz + 1, program->build_log, CL_SUCCESS);
     if (param_value_size_ret)
       *param_value_size_ret = program->build_log_sz + 1;
+  }else if (param_name == CL_PROGRAM_BINARY_TYPE){
+
+    FILL_GETINFO_RET (cl_uint, 1, &program->binary_type, CL_SUCCESS);
   } else {
     return CL_INVALID_VALUE;
   }
diff --git a/src/cl_gbe_loader.cpp b/src/cl_gbe_loader.cpp
index 470299b..2fda50c 100644
--- a/src/cl_gbe_loader.cpp
+++ b/src/cl_gbe_loader.cpp
@@ -24,13 +24,14 @@
 
 //function pointer from libgbe.so
 gbe_program_new_from_source_cb *compiler_program_new_from_source = NULL;
-gbe_program_serialize_to_binary_cb *compiler_program_serialize_to_binary = NULL;
-gbe_program_new_from_llvm_cb *compiler_program_new_from_llvm = NULL;
-gbe_set_image_base_index_cb *compiler_set_image_base_index = NULL;
 gbe_program_compile_from_source_cb *compiler_program_compile_from_source = NULL;
 gbe_program_new_gen_program_cb *compiler_program_new_gen_program = NULL;
 gbe_program_link_program_cb *compiler_program_link_program = NULL;
 gbe_program_build_from_llvm_cb *compiler_program_build_from_llvm = NULL;
+gbe_program_new_from_llvm_binary_cb *compiler_program_new_from_llvm_binary = NULL;
+gbe_program_serialize_to_binary_cb *compiler_program_serialize_to_binary = NULL;
+gbe_program_new_from_llvm_cb *compiler_program_new_from_llvm = NULL;
+gbe_set_image_base_index_cb *compiler_set_image_base_index = NULL;
 
 //function pointer from libgbeinterp.so
 gbe_program_new_from_binary_cb *interp_program_new_from_binary = NULL;
@@ -272,6 +273,10 @@ struct GbeLoaderInitializer
       if (compiler_program_build_from_llvm == NULL)
         return;
 
+      compiler_program_new_from_llvm_binary = *(gbe_program_new_from_llvm_binary_cb **)dlsym(dlhCompiler, "gbe_program_new_from_llvm_binary");
+      if (compiler_program_new_from_llvm_binary == NULL)
+        return;
+
       compiler_program_serialize_to_binary = *(gbe_program_serialize_to_binary_cb **)dlsym(dlhCompiler, "gbe_program_serialize_to_binary");
       if (compiler_program_serialize_to_binary == NULL)
         return;
diff --git a/src/cl_gbe_loader.h b/src/cl_gbe_loader.h
index bd6afe6..632163b 100644
--- a/src/cl_gbe_loader.h
+++ b/src/cl_gbe_loader.h
@@ -25,9 +25,15 @@
 extern "C" {
 #endif
 extern gbe_program_new_from_source_cb *compiler_program_new_from_source;
+extern gbe_program_compile_from_source_cb *compiler_program_compile_from_source;
+extern gbe_program_new_gen_program_cb *compiler_program_new_gen_program;
+extern gbe_program_link_program_cb *compiler_program_link_program;
+extern gbe_program_build_from_llvm_cb *compiler_program_build_from_llvm;
+extern gbe_program_new_from_llvm_binary_cb *compiler_program_new_from_llvm_binary;
 extern gbe_program_serialize_to_binary_cb *compiler_program_serialize_to_binary;
 extern gbe_program_new_from_llvm_cb *compiler_program_new_from_llvm;
 extern gbe_set_image_base_index_cb *compiler_set_image_base_index;
+
 extern gbe_program_new_from_binary_cb *interp_program_new_from_binary;
 extern gbe_program_get_global_constant_size_cb *interp_program_get_global_constant_size;
 extern gbe_program_get_global_constant_data_cb *interp_program_get_global_constant_data;
@@ -63,10 +69,6 @@ extern gbe_get_printf_sizeof_size_cb* interp_get_printf_sizeof_size;
 extern gbe_release_printf_info_cb* interp_release_printf_info;
 extern gbe_output_printf_cb* interp_output_printf;
 //extern gbe_set_image_base_index_cb *gbe_set_image_base_index_interp;
-extern gbe_program_compile_from_source_cb *compiler_program_compile_from_source;
-extern gbe_program_new_gen_program_cb *compiler_program_new_gen_program;
-extern gbe_program_link_program_cb *compiler_program_link_program;
-extern gbe_program_build_from_llvm_cb *compiler_program_build_from_llvm;
 extern gbe_kernel_get_arg_info_cb *interp_kernel_get_arg_info;
 
 int CompilerSupported();
diff --git a/src/cl_program.c b/src/cl_program.c
index 240453c..0dcc59a 100644
--- a/src/cl_program.c
+++ b/src/cl_program.c
@@ -156,6 +156,30 @@ error:
   return err;
 }
 
+inline cl_bool isBitcodeWrapper(const unsigned char *BufPtr, const unsigned char *BufEnd)
+{
+  // See if you can find the hidden message in the magic bytes :-).
+  // (Hint: it's a little-endian encoding.)
+  return BufPtr != BufEnd &&
+    BufPtr[0] == 0xDE &&
+    BufPtr[1] == 0xC0 &&
+    BufPtr[2] == 0x17 &&
+    BufPtr[3] == 0x0B;
+}
+
+inline cl_bool isRawBitcode(const unsigned char *BufPtr, const unsigned char *BufEnd)
+{
+  // These bytes sort of have a hidden message, but it's not in
+  // little-endian this time, and it's a little redundant.
+  return BufPtr != BufEnd &&
+    BufPtr[0] == 'B' &&
+    BufPtr[1] == 'C' &&
+    BufPtr[2] == 0xc0 &&
+    BufPtr[3] == 0xde;
+}
+
+#define isBitcode(BufPtr,BufEnd)  (isBitcodeWrapper(BufPtr, BufEnd) || isRawBitcode(BufPtr, BufEnd))
+
 LOCAL cl_program
 cl_program_create_from_binary(cl_context             ctx,
                               cl_uint                num_devices,
@@ -197,6 +221,23 @@ cl_program_create_from_binary(cl_context             ctx,
   program->binary_sz = lengths[0];
   program->source_type = FROM_BINARY;
 
+  if(isBitcode((unsigned char*)program->binary+1, (unsigned char*)program->binary+program->binary_sz)) {
+    if(*program->binary == 1){
+      program->binary_type = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
+    }else if(*program->binary == 2){
+      program->binary_type = CL_PROGRAM_BINARY_TYPE_LIBRARY;
+    }else{
+      err= CL_INVALID_BINARY;
+      goto error;
+    }
+    program->opaque = compiler_program_new_from_llvm_binary(program->ctx->device->vendor_id, program->binary, program->binary_sz);
+
+    if (UNLIKELY(program->opaque == NULL)) {
+      err = CL_INVALID_PROGRAM;
+      goto error;
+    }
+  }
+
   if (binary_status)
     binary_status[0] = CL_SUCCESS;
 
@@ -360,6 +401,7 @@ cl_program_create_from_source(cl_context ctx,
   *p = '\0';
 
   program->source_type = FROM_SOURCE;
+  program->binary_type = CL_PROGRAM_BINARY_TYPE_NONE;
 
 exit:
   cl_free(lens);
@@ -432,6 +474,7 @@ cl_program_build(cl_program p, const char *options)
     TRY (cl_program_load_gen_program, p);
     p->source_type = FROM_LLVM;
   }
+  p->binary_type = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
 
   for (i = 0; i < p->ker_n; i ++) {
     const gbe_kernel opaque = interp_program_get_kernel(p->opaque, i);
@@ -468,6 +511,7 @@ cl_program_link(cl_context            context,
   p->opaque = compiler_program_new_gen_program(context->device->vendor_id, NULL, NULL);
 
   for(i = 0; i < num_input_programs; i++) {
+    // if program create with llvm binary, need deserilize first to get module.
     if(input_programs[i])
       compiler_program_link_program(p->opaque, input_programs[i]->opaque,
         p->build_log_max_sz, p->build_log, &p->build_log_sz);
@@ -477,6 +521,13 @@ cl_program_link(cl_context            context,
     }
   }
 
+  if(options && strstr(options, "-create-library")){
+    p->binary_type = CL_PROGRAM_BINARY_TYPE_LIBRARY;
+    return p;
+  }else{
+    p->binary_type = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
+  }
+
   compiler_program_build_from_llvm(p->opaque, p->build_log_max_sz, p->build_log, &p->build_log_sz, options);
 
   /* Create all the kernels */
@@ -534,7 +585,9 @@ cl_program_compile(cl_program            p,
     p->build_opts = NULL;
   }
 
-  const char* temp_header_path = "/tmp/beignet_header/";
+  char temp_header_template[]= "/tmp/beignet.XXXXXX";
+  char* temp_header_path = mkdtemp(temp_header_template);
+
   if (p->source_type == FROM_SOURCE) {
 
     if (!CompilerSupported()) {
@@ -542,14 +595,15 @@ cl_program_compile(cl_program            p,
       goto error;
     }
 
-    //write the headers to /tmp/beignet_header for include.
+    //write the headers to /tmp/beignet.XXXXXX for include.
     for (i = 0; i < num_input_headers; i++) {
       if(header_include_names[i] == NULL || input_headers[i] == NULL)
         continue;
 
-      char temp_path[255];
-      strcpy(temp_path, temp_header_path);
-      strcat(temp_path, header_include_names[i]);
+      char temp_path[255]="";
+      strncpy(temp_path, temp_header_path, strlen(temp_header_path));
+      strncat(temp_path, "/", 1);
+      strncat(temp_path, header_include_names[i], strlen(header_include_names[i]));
       char* dirc = strdup(temp_path);
       char* dir = dirname(dirc);
       mkdir(dir, 0755);
@@ -572,9 +626,12 @@ cl_program_compile(cl_program            p,
     p->opaque = compiler_program_compile_from_source(p->ctx->device->vendor_id, p->source, temp_header_path,
         p->build_log_max_sz, options, p->build_log, &p->build_log_sz);
 
-    int rm_ret = system("rm /tmp/beignet_header/* -rf");
+    char rm_path[255]="rm ";
+    strncat(rm_path, temp_header_path, strlen(temp_header_path));
+    strncat(rm_path, " -rf", 4);
+    int temp = system(rm_path);
 
-    if(rm_ret){
+    if(temp){
       assert(0);
     }
 
@@ -588,6 +645,7 @@ cl_program_compile(cl_program            p,
 
     /* Create all the kernels */
     p->source_type = FROM_LLVM;
+    p->binary_type = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
   }
   p->is_built = 1;
   return CL_SUCCESS;
diff --git a/src/cl_program.h b/src/cl_program.h
index 49a4f48..52d1ac1 100644
--- a/src/cl_program.h
+++ b/src/cl_program.h
@@ -50,6 +50,7 @@ struct _cl_program {
   char *source;           /* Program sources */
   char *binary;           /* Program binary. */
   size_t binary_sz;       /* The binary size. */
+  uint32_t binary_type;   /* binary type: COMPILED_OBJECT(LLVM IR), LIBRARY(LLVM IR with option "-create-library"), or EXECUTABLE(GEN binary). */
   uint32_t ker_n;         /* Number of declared kernels */
   uint32_t source_type:2; /* Built from binary, source or LLVM */
   uint32_t is_built:1;    /* Did we call clBuildProgram on it? */
-- 
1.8.1.2



More information about the Beignet mailing list