[Beignet] [PATCH] Fix piglit clLinkProgram fail.

Yang Rong rong.r.yang at intel.com
Sun Aug 23 20:59:36 PDT 2015


1. return CL_INVALID_LINKER_OPTIONS when invalid options, using clang to check the options.
2. return CL_INVALID_OPERATION when the binary type is not same.
3. When link fail, will not return CL_LINK_PROGRAM_FAILURE, fix it.
4. Should not delete program in genProgramBuildFromLLVM, the program is new and delete from runtime.

Signed-off-by: Yang Rong <rong.r.yang at intel.com>
---
 backend/src/backend/gen_program.cpp |  5 ++--
 backend/src/backend/program.cpp     | 46 +++++++++++++++++++++++++++++++++++--
 backend/src/backend/program.h       | 10 ++++++--
 src/cl_api.c                        |  1 +
 src/cl_gbe_loader.cpp               |  5 ++++
 src/cl_gbe_loader.h                 |  1 +
 src/cl_program.c                    | 20 +++++++++++++---
 7 files changed, 79 insertions(+), 9 deletions(-)

diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index 3c4983e..04da692 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -386,7 +386,7 @@ namespace gbe {
     return (gbe_program) program;
   }
 
-  static void genProgramLinkFromLLVM(gbe_program           dst_program,
+  static bool genProgramLinkFromLLVM(gbe_program           dst_program,
                                      gbe_program           src_program,
                                      size_t                stringSize,
                                      char *                err,
@@ -408,10 +408,12 @@ namespace gbe {
           err[stringSize-1] = '\0';
           *errSize = strlen(err);
         }
+        return true;
       }
     }
     // Everything run fine
 #endif
+    return false;
   }
 
   static void genProgramBuildFromLLVM(gbe_program program,
@@ -444,7 +446,6 @@ namespace gbe {
         std::memcpy(err, error.c_str(), msgSize);
         *errSize = error.size();
       }
-      GBE_DELETE(p);
     }
     releaseLLVMContextLock();
 #endif
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index c02096f..9808e9e 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -913,23 +913,63 @@ namespace gbe {
 #endif
 
 #ifdef GBE_COMPILER_AVAILABLE
-  static void programLinkProgram(gbe_program           dst_program,
+  static bool programLinkProgram(gbe_program           dst_program,
                                  gbe_program           src_program,
                                  size_t                stringSize,
                                  char *                err,
                                  size_t *              errSize)
   {
+    bool ret = 0;
     acquireLLVMContextLock();
 
-    gbe_program_link_from_llvm(dst_program, src_program, stringSize, err, errSize);
+    ret = gbe_program_link_from_llvm(dst_program, src_program, stringSize, err, errSize);
 
     releaseLLVMContextLock();
 
     if (OCL_OUTPUT_BUILD_LOG && err)
       llvm::errs() << err;
+    return ret;
   }
 #endif
 
+#ifdef GBE_COMPILER_AVAILABLE
+    static bool programCheckOption(const char * option)
+    {
+      vector<const char *> args;
+      std::string s(option);
+      size_t pos = s.find("-create-library");
+      //clang don't accept -create-library and -enable-link-options, erase them
+      if(pos != std::string::npos) {
+        s.erase(pos, strlen("-create-library"));
+      }
+      pos = s.find("-enable-link-options");
+      if(pos != std::string::npos) {
+        s.erase(pos, strlen("-enable-link-options"));
+      }
+      args.push_back(s.c_str());
+
+      // The compiler invocation needs a DiagnosticsEngine so it can report problems
+      std::string ErrorString;
+      llvm::raw_string_ostream ErrorInfo(ErrorString);
+      llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts = new clang::DiagnosticOptions();
+      DiagOpts->ShowCarets = false;
+      DiagOpts->ShowPresumedLoc = true;
+
+      clang::TextDiagnosticPrinter *DiagClient =
+                               new clang::TextDiagnosticPrinter(ErrorInfo, &*DiagOpts);
+      llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
+      clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
+
+      // Create the compiler invocation
+      std::unique_ptr<clang::CompilerInvocation> CI(new clang::CompilerInvocation);
+      return clang::CompilerInvocation::CreateFromArgs(*CI,
+                                                       &args[0],
+                                                       &args[0] + args.size(),
+                                                       Diags);
+    }
+#endif
+
+
   static size_t programGetGlobalConstantSize(gbe_program gbeProgram) {
     if (gbeProgram == NULL) return 0;
     const gbe::Program *program = (const gbe::Program*) gbeProgram;
@@ -1174,6 +1214,7 @@ void releaseLLVMContextLock()
 GBE_EXPORT_SYMBOL gbe_program_new_from_source_cb *gbe_program_new_from_source = NULL;
 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_check_opt_cb *gbe_program_check_opt = 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;
@@ -1229,6 +1270,7 @@ namespace gbe
       gbe_program_new_from_source = gbe::programNewFromSource;
       gbe_program_compile_from_source = gbe::programCompileFromSource;
       gbe_program_link_program = gbe::programLinkProgram;
+      gbe_program_check_opt = gbe::programCheckOption;
       gbe_program_get_global_constant_size = gbe::programGetGlobalConstantSize;
       gbe_program_get_global_constant_data = gbe::programGetGlobalConstantData;
       gbe_program_clean_llvm_resource = gbe::programCleanLlvmResource;
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h
index fa75052..67d9db0 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -30,6 +30,7 @@
 
 #include <stdint.h>
 #include <stdlib.h>
+#include <stdbool.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -180,14 +181,19 @@ typedef gbe_program (gbe_program_compile_from_source_cb)(uint32_t deviceID,
                                                          char *err,
                                                          size_t *err_size);
 extern gbe_program_compile_from_source_cb *gbe_program_compile_from_source;
+
 /*! link the programs. */
-typedef void (gbe_program_link_program_cb)(gbe_program           dst_program,
+typedef bool (gbe_program_link_program_cb)(gbe_program           dst_program,
                                            gbe_program           src_program,
                                            size_t                stringSize,
                                            char *                err,
                                            size_t *              errSize);
 extern gbe_program_link_program_cb *gbe_program_link_program;
 
+/*! check link option. */
+typedef bool (gbe_program_check_opt_cb)(const char *option);
+extern gbe_program_check_opt_cb *gbe_program_check_opt;
+
 /*! create s new genprogram for link. */
 typedef gbe_program (gbe_program_new_gen_program_cb)(uint32_t deviceID,
                                                      const void *module,
@@ -219,7 +225,7 @@ typedef gbe_program (gbe_program_new_from_llvm_cb)(uint32_t deviceID,
 extern gbe_program_new_from_llvm_cb *gbe_program_new_from_llvm;
 
 /*! link the programs from llvm level. */
-typedef void (gbe_program_link_from_llvm_cb)(gbe_program dst_program,
+typedef bool (gbe_program_link_from_llvm_cb)(gbe_program dst_program,
                                              gbe_program src_program,
                                              size_t      stringSize,
                                              char *      err,
diff --git a/src/cl_api.c b/src/cl_api.c
index 5c9b250..d0aebbd 100644
--- a/src/cl_api.c
+++ b/src/cl_api.c
@@ -1015,6 +1015,7 @@ clLinkProgram(cl_context            context,
   INVALID_VALUE_IF (pfn_notify  == 0 && user_data   != NULL);
   INVALID_VALUE_IF (num_input_programs == 0 && input_programs != NULL);
   INVALID_VALUE_IF (num_input_programs != 0 && input_programs == NULL);
+  INVALID_VALUE_IF (num_input_programs == 0 && input_programs == NULL);
 
   program = cl_program_link(context, num_input_programs, input_programs, options, &err);
 
diff --git a/src/cl_gbe_loader.cpp b/src/cl_gbe_loader.cpp
index c3454e8..e832a53 100644
--- a/src/cl_gbe_loader.cpp
+++ b/src/cl_gbe_loader.cpp
@@ -27,6 +27,7 @@ gbe_program_new_from_source_cb *compiler_program_new_from_source = 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_check_opt_cb *compiler_program_check_opt = 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;
@@ -279,6 +280,10 @@ struct GbeLoaderInitializer
       if (compiler_program_link_program == NULL)
         return;
 
+      compiler_program_check_opt = *(gbe_program_check_opt_cb **)dlsym(dlhCompiler, "gbe_program_check_opt");
+      if (compiler_program_check_opt == NULL)
+        return;
+
       compiler_program_build_from_llvm = *(gbe_program_build_from_llvm_cb **)dlsym(dlhCompiler, "gbe_program_build_from_llvm");
       if (compiler_program_build_from_llvm == NULL)
         return;
diff --git a/src/cl_gbe_loader.h b/src/cl_gbe_loader.h
index 6fa4c98..de91c85 100644
--- a/src/cl_gbe_loader.h
+++ b/src/cl_gbe_loader.h
@@ -28,6 +28,7 @@ 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_check_opt_cb *compiler_program_check_opt;
 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;
diff --git a/src/cl_program.c b/src/cl_program.c
index 4870d5d..ee5b8b1 100644
--- a/src/cl_program.c
+++ b/src/cl_program.c
@@ -605,20 +605,34 @@ cl_program_link(cl_context            context,
   cl_int i = 0;
   int copyed = 0;
   p = cl_program_new(context);
+  cl_bool ret = 0;
 
   if (!check_cl_version_option(p, options)) {
     err = CL_BUILD_PROGRAM_FAILURE;
     goto error;
   }
 
+  //Although we don't use options, but still need check options
+  if(!compiler_program_check_opt(options)) {
+    err = CL_INVALID_LINKER_OPTIONS;
+    goto error;
+  }
+
   p->opaque = compiler_program_new_gen_program(context->device->device_id, NULL, NULL);
 
+  for(i = 1; i < num_input_programs; i++) {
+    //num_input_programs >0 and input_programs MUST not NULL, so compare with input_programs[0] directly.
+    if(input_programs[i]->binary_type != input_programs[0]->binary_type) {
+      err = CL_INVALID_OPERATION;
+      goto error;
+    }
+  }
   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);
-    if (UNLIKELY(p->opaque == NULL)) {
+      ret = compiler_program_link_program(p->opaque, input_programs[i]->opaque,
+                                          p->build_log_max_sz, p->build_log, &p->build_log_sz);
+    if (UNLIKELY(ret)) {
       err = CL_LINK_PROGRAM_FAILURE;
       goto error;
     }
-- 
1.9.1



More information about the Beignet mailing list