use table to define and query binary headers.

Submitted by Luo, Xionghu on Oct. 16, 2015, 5:57 a.m.

Details

Message ID 1444975026-29177-1-git-send-email-xionghu.luo@intel.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Luo, Xionghu Oct. 16, 2015, 5:57 a.m.
From: Luo Xionghu <xionghu.luo@intel.com>

currently, we support create program from 4 types of binary: SPIR(BITCODE),
LLVM Compiled Object, LLVM Library and GEN Binary. The detailed formats are
listed in code.
also use table to match or fill gen binary header in backend.

Signed-off-by: Luo Xionghu <xionghu.luo@intel.com>
---
 backend/src/backend/gen_program.cpp | 107 ++++++++++++++++++++++--------------
 src/cl_program.c                    |  51 ++++++++++-------
 2 files changed, 95 insertions(+), 63 deletions(-)

Patch hide | download patch | download mbox

diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index 233dfe9..28d4ab9 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -205,32 +205,60 @@  namespace gbe {
   }
 
 #define BINARY_HEADER_LENGTH 8
-#define IS_GEN_BINARY(binary) (*binary == '\0' && *(binary+1) == 'G'&& *(binary+2) == 'E' &&*(binary+3) == 'N' &&*(binary+4) == 'C')
-#define FILL_GEN_BINARY(binary) do{*binary = '\0'; *(binary+1) = 'G'; *(binary+2) = 'E'; *(binary+3) = 'N'; *(binary+4) = 'C';}while(0)
-#define FILL_DEVICE_ID(binary, src_hw_info) do {*(binary+5) = src_hw_info[0]; *(binary+6) = src_hw_info[1]; *(binary+7) = src_hw_info[2];}while(0)
-#define DEVICE_MATCH(typeA, src_hw_info) ((IS_IVYBRIDGE(typeA) && !strcmp(src_hw_info, "IVB")) ||  \
-                                      (IS_IVYBRIDGE(typeA) && !strcmp(src_hw_info, "BYT")) ||  \
-                                      (IS_BAYTRAIL_T(typeA) && !strcmp(src_hw_info, "BYT")) ||  \
-                                      (IS_HASWELL(typeA) && !strcmp(src_hw_info, "HSW")) ||  \
-                                      (IS_BROADWELL(typeA) && !strcmp(src_hw_info, "BDW")) ||  \
-                                      (IS_CHERRYVIEW(typeA) && !strcmp(src_hw_info, "CHV")) ||  \
-                                      (IS_SKYLAKE(typeA) && !strcmp(src_hw_info, "SKL")) )
+
+static const unsigned char gen_binary_header[7][BINARY_HEADER_LENGTH]= \
+                                             {{0, 'G','E', 'N', 'C', 'B', 'Y', 'T'},
+                                              {0, 'G','E', 'N', 'C', 'I', 'V', 'B'},
+                                              {0, 'G','E', 'N', 'C', 'H', 'S', 'W'},
+                                              {0, 'G','E', 'N', 'C', 'C', 'H', 'V'},
+                                              {0, 'G','E', 'N', 'C', 'B', 'D', 'W'},
+                                              {0, 'G','E', 'N', 'C', 'S', 'K', 'L'},
+                                              {0}};
+
+#define FILL_GEN_HEADER(binary, index)  do {int i = 0; do {*(binary+i) = gen_binary_header[index][i]; i++; }while(i < BINARY_HEADER_LENGTH);}while(0)
+#define FILL_BYT_HEADER(binary) FILL_GEN_HEADER(binary, 0)
+#define FILL_IVB_HEADER(binary) FILL_GEN_HEADER(binary, 1)
+#define FILL_HSW_HEADER(binary) FILL_GEN_HEADER(binary, 2)
+#define FILL_CHV_HEADER(binary) FILL_GEN_HEADER(binary, 3)
+#define FILL_BDW_HEADER(binary) FILL_GEN_HEADER(binary, 4)
+#define FILL_SKL_HEADER(binary) FILL_GEN_HEADER(binary, 5)
+
+   static bool binaryCompare8(const unsigned char *BufPtr1, const unsigned char* BufPtr2)
+   {
+     return BufPtr1[0] == BufPtr2[0] &&
+       BufPtr1[1] == BufPtr2[1] &&
+       BufPtr1[2] == BufPtr2[2] &&
+       BufPtr1[3] == BufPtr2[3] &&
+       BufPtr1[4] == BufPtr2[4] &&
+       BufPtr1[5] == BufPtr2[5] &&
+       BufPtr1[6] == BufPtr2[6] &&
+       BufPtr1[7] == BufPtr2[7];
+   }
+
+#define MATCH_BYT_HEADER(binary) binaryCompare8(binary, gen_binary_header[0])
+#define MATCH_IVB_HEADER(binary) binaryCompare8(binary, gen_binary_header[1])
+#define MATCH_HSW_HEADER(binary) binaryCompare8(binary, gen_binary_header[2])
+#define MATCH_CHV_HEADER(binary) binaryCompare8(binary, gen_binary_header[3])
+#define MATCH_BDW_HEADER(binary) binaryCompare8(binary, gen_binary_header[4])
+#define MATCH_SKL_HEADER(binary) binaryCompare8(binary, gen_binary_header[5])
+
+#define MATCH_DEVICE(typeA, binary) ((IS_IVYBRIDGE(typeA) && MATCH_IVB_HEADER(binary)) ||  \
+                                      (IS_IVYBRIDGE(typeA) && MATCH_IVB_HEADER(binary)) ||  \
+                                      (IS_BAYTRAIL_T(typeA) && MATCH_BYT_HEADER(binary)) ||  \
+                                      (IS_HASWELL(typeA) && MATCH_HSW_HEADER(binary)) ||  \
+                                      (IS_BROADWELL(typeA) && MATCH_BDW_HEADER(binary)) ||  \
+                                      (IS_CHERRYVIEW(typeA) && MATCH_CHV_HEADER(binary)) ||  \
+                                      (IS_SKYLAKE(typeA) && MATCH_SKL_HEADER(binary)) )
 
   static gbe_program genProgramNewFromBinary(uint32_t deviceID, const char *binary, size_t size) {
     using namespace gbe;
     std::string binary_content;
+
+    if(size < BINARY_HEADER_LENGTH)
+      return NULL;
+
     //the header length is 8 bytes: 1 byte is binary type, 4 bytes are bitcode header, 3  bytes are hw info.
-    char src_hw_info[4]="";
-    src_hw_info[0] = *(binary+5);
-    src_hw_info[1] = *(binary+6);
-    src_hw_info[2] = *(binary+7);
-
-    // check whether is gen binary ('/0GENC')
-    if(!IS_GEN_BINARY(binary)){
-        return NULL;
-    }
-    // check the whether the current device ID match the binary file's.
-    if(!DEVICE_MATCH(deviceID, src_hw_info)){
+    if(!MATCH_DEVICE(deviceID, (unsigned char*)binary)){
       return NULL;
     }
 
@@ -300,36 +328,28 @@  namespace gbe {
       //add header to differetiate from llvm bitcode binary.
       //the header length is 8 bytes: 1 byte is binary type, 4 bytes are bitcode header, 3  bytes are hw info.
       *binary = (char *)malloc(sizeof(char) * (sz+BINARY_HEADER_LENGTH) );
+      if(*binary == NULL)
+        return 0;
+
       memset(*binary, 0, sizeof(char) * (sz+BINARY_HEADER_LENGTH) );
-      FILL_GEN_BINARY(*binary);
-      char src_hw_info[4]="";
       if(IS_IVYBRIDGE(prog->deviceID)){
-        src_hw_info[0]='I';
-        src_hw_info[1]='V';
-        src_hw_info[2]='B';
+        FILL_IVB_HEADER(*binary);
         if(IS_BAYTRAIL_T(prog->deviceID)){
-          src_hw_info[0]='B';
-          src_hw_info[1]='Y';
-          src_hw_info[2]='T';
+        FILL_BYT_HEADER(*binary);
         }
       }else if(IS_HASWELL(prog->deviceID)){
-        src_hw_info[0]='H';
-        src_hw_info[1]='S';
-        src_hw_info[2]='W';
+        FILL_HSW_HEADER(*binary);
       }else if(IS_BROADWELL(prog->deviceID)){
-        src_hw_info[0]='B';
-        src_hw_info[1]='D';
-        src_hw_info[2]='W';
+        FILL_BDW_HEADER(*binary);
       }else if(IS_CHERRYVIEW(prog->deviceID)){
-        src_hw_info[0]='C';
-        src_hw_info[1]='H';
-        src_hw_info[2]='V';
+        FILL_CHV_HEADER(*binary);
       }else if(IS_SKYLAKE(prog->deviceID)){
-        src_hw_info[0]='S';
-        src_hw_info[1]='K';
-        src_hw_info[2]='L';
+        FILL_SKL_HEADER(*binary);
+      }else {
+        free(*binary);
+        *binary = NULL;
+        return 0;
       }
-      FILL_DEVICE_ID(*binary, src_hw_info);
       memcpy(*binary+BINARY_HEADER_LENGTH, oss.str().c_str(), sz*sizeof(char));
       return sz+BINARY_HEADER_LENGTH;
     }else{
@@ -340,6 +360,9 @@  namespace gbe {
       std::string& bin_str = OS.str();
       int llsz = bin_str.size();
       *binary = (char *)malloc(sizeof(char) * (llsz+1) );
+      if(*binary == NULL)
+        return 0;
+
       *(*binary) = binary_type;
       memcpy(*binary+1, bin_str.c_str(), llsz);
       return llsz+1;
diff --git a/src/cl_program.c b/src/cl_program.c
index 55c1ee8..ceda6ac 100644
--- a/src/cl_program.c
+++ b/src/cl_program.c
@@ -166,29 +166,34 @@  error:
   return err;
 }
 
-inline cl_bool isBitcodeWrapper(const unsigned char *BufPtr, const unsigned char *BufEnd)
+inline cl_bool binaryCompare4(const unsigned char *BufPtr1, const unsigned char* BufPtr2)
 {
-  // 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;
+  return BufPtr1[0] == BufPtr2[0] &&
+    BufPtr1[1] == BufPtr2[1] &&
+    BufPtr1[2] == BufPtr2[2] &&
+    BufPtr1[3] == BufPtr2[3];
 }
 
-inline cl_bool isRawBitcode(const unsigned char *BufPtr, const unsigned char *BufEnd)
+inline cl_bool binaryCompare5(const unsigned char *BufPtr1, const unsigned char* BufPtr2)
 {
-  // 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;
+  return BufPtr1[0] == BufPtr2[0] &&
+    BufPtr1[1] == BufPtr2[1] &&
+    BufPtr1[2] == BufPtr2[2] &&
+    BufPtr1[3] == BufPtr2[3] &&
+    BufPtr1[4] == BufPtr2[4];
 }
 
-#define isBitcode(BufPtr,BufEnd)  (isBitcodeWrapper(BufPtr, BufEnd) || isRawBitcode(BufPtr, BufEnd))
+static const unsigned char binary_type_header[5][5]=  \
+                                              {{'B','C', 0xC0, 0xDE},
+                                               {1, 'B', 'C', 0xC0, 0xDE},
+                                               {2, 'B', 'C', 0xC0, 0xDE},
+                                               {0, 'G','E', 'N', 'C'},
+                                               {0}};
+
+#define isSPIR(BufPtr)      binaryCompare4(BufPtr, binary_type_header[0])
+#define isLLVM_C_O(BufPtr)  binaryCompare5(BufPtr, binary_type_header[1])
+#define isLLVM_LIB(BufPtr)  binaryCompare5(BufPtr, binary_type_header[2])
+#define isGenBinary(BufPtr) binaryCompare5(BufPtr, binary_type_header[3])
 
 LOCAL cl_program
 cl_program_create_from_binary(cl_context             ctx,
@@ -216,7 +221,7 @@  cl_program_create_from_binary(cl_context             ctx,
     goto error;
   }
 
-  if (lengths[0] == 0) {
+  if (lengths[0] == 0 || lengths[0] < 4) {
     err = CL_INVALID_VALUE;
     if (binary_status)
       binary_status[0] = CL_INVALID_VALUE;
@@ -235,7 +240,7 @@  cl_program_create_from_binary(cl_context             ctx,
   program->binary_sz = lengths[0];
   program->source_type = FROM_BINARY;
 
-  if(isBitcode((unsigned char*)program->binary, (unsigned char*)program->binary+program->binary_sz)) {
+  if(isSPIR((unsigned char*)program->binary)) {
 
     char* typed_binary;
     TRY_ALLOC(typed_binary, cl_calloc(lengths[0]+1, sizeof(char)));
@@ -249,7 +254,7 @@  cl_program_create_from_binary(cl_context             ctx,
     }
 
     program->source_type = FROM_LLVM_SPIR;
-  }else if(isBitcode((unsigned char*)program->binary+1, (unsigned char*)program->binary+program->binary_sz)) {
+  }else if(isLLVM_C_O((unsigned char*)program->binary) || isLLVM_LIB((unsigned char*)program->binary)) {
     if(*program->binary == 1){
       program->binary_type = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
     }else if(*program->binary == 2){
@@ -266,7 +271,7 @@  cl_program_create_from_binary(cl_context             ctx,
     }
     program->source_type = FROM_LLVM;
   }
-  else if (*program->binary == 0) {
+  else if (isGenBinary((unsigned char*)program->binary)) {
     program->opaque = interp_program_new_from_binary(program->ctx->device->device_id, program->binary, program->binary_sz);
     if (UNLIKELY(program->opaque == NULL)) {
       err = CL_INVALID_PROGRAM;
@@ -277,6 +282,10 @@  cl_program_create_from_binary(cl_context             ctx,
     TRY (cl_program_load_gen_program, program);
     program->binary_type = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
   }
+  else {
+    err= CL_INVALID_BINARY;
+    goto error;
+  }
 
   if (binary_status)
     binary_status[0] = CL_SUCCESS;