[Beignet] [PATCH] Report build failures in backend to the build log

Rebecca N. Palmer rebecca_palmer at zoho.com
Mon Jun 6 22:37:59 UTC 2016


As noted at llvm_gen_backend:94, we currently lack a mechanism for
reporting failures in backend (beignet-managed) compiler passes to the
build log, and instead print the error to stderr and assert-fail.

This patch creates such a mechanism, and uses it for "function not found".
Please note that it has not had much testing yet.

Points for discussion/improvement:
-Does not currently print source location information.
-Are there other assertions that can be triggered by invalid input, and hence
should also use this?

Signed-off-by: Rebecca Palmer <rebecca_palmer at zoho.com>

diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index 4f8167c..44cb60b 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -122,7 +122,7 @@ namespace gbe {
   bool Program::buildFromLLVMFile(const char *fileName, const void* module, std::string &error, int optLevel) {
     ir::Unit *unit = new ir::Unit();
     llvm::Module * cloned_module = NULL;
-    bool ret = true;
+    bool ret = false;
     if(module){
 #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 8
       cloned_module = llvm::CloneModule((llvm::Module*)module).release();
@@ -133,7 +133,7 @@ namespace gbe {
     bool strictMath = true;
     if (fast_relaxed_math || !OCL_STRICT_CONFORMANCE)
       strictMath = false;
-    if (llvmToGen(*unit, fileName, module, optLevel, strictMath, OCL_PROFILING_LOG) == false) {
+    if (llvmToGen(*unit, fileName, module, optLevel, strictMath, OCL_PROFILING_LOG, error) == false) {
       if (fileName)
         error = std::string(fileName) + " not found";
       delete unit;
@@ -146,15 +146,19 @@ namespace gbe {
       unit = new ir::Unit();
       if(cloned_module){
         //suppose file exists and llvmToGen will not return false.
-        llvmToGen(*unit, fileName, cloned_module, 0, strictMath, OCL_PROFILING_LOG);
+        llvmToGen(*unit, fileName, cloned_module, 0, strictMath, OCL_PROFILING_LOG, error);
       }else{
         //suppose file exists and llvmToGen will not return false.
-        llvmToGen(*unit, fileName, module, 0, strictMath, OCL_PROFILING_LOG);
+        llvmToGen(*unit, fileName, module, 0, strictMath, OCL_PROFILING_LOG, error);
       }
     }
-    assert(unit->getValid());
-    if (!this->buildFromUnit(*unit, error))
-      ret = false;
+    if(unit->getValid()){
+      std::string error2;
+      if (this->buildFromUnit(*unit, error2)){
+        ret = true;
+      }
+      error = error + error2;
+    }
     delete unit;
     if(cloned_module){
       delete (llvm::Module*) cloned_module;
diff --git a/backend/src/llvm/llvm_gen_backend.cpp b/backend/src/llvm/llvm_gen_backend.cpp
index acad1b2..bb00aab 100644
--- a/backend/src/llvm/llvm_gen_backend.cpp
+++ b/backend/src/llvm/llvm_gen_backend.cpp
@@ -513,6 +513,7 @@ namespace gbe
     Function *Func;
     const Module *TheModule;
     int btiBase;
+    bool has_errors;
     /*! legacyMode is for hardware before BDW,
      * which do not support stateless memory access */
     bool legacyMode;
@@ -528,6 +529,7 @@ namespace gbe
         LI(0),
         TheModule(0),
         btiBase(BTI_RESERVED_NUM),
+        has_errors(false),
         legacyMode(true)
     {
 #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >=7
@@ -2940,6 +2942,9 @@ namespace gbe
     pass = PASS_EMIT_REGISTERS;
     for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I)
       visit(*I);
+    
+    // Abort if this found an error (otherwise emitBasicBlock will assert)
+    if(has_errors){return;}
 
     // First create all the labels (one per block) ...
     for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
@@ -3749,11 +3754,8 @@ namespace gbe
         break;
       case GEN_OCL_NOT_FOUND:
       default:
-        std::cerr << "Caller instruction: " << std::endl;
-        I.dump();
-        std::cerr << "Callee function: " << std::endl;
-        Callee->dump();
-        GBE_ASSERT(0);
+        has_errors = true;
+        Func->getContext().emitError(&I,"function '" + fnName + "' not found or cannot be inlined");
     };
   }
 
diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp
index 41723d1..02a69ec 100644
--- a/backend/src/llvm/llvm_to_gen.cpp
+++ b/backend/src/llvm/llvm_to_gen.cpp
@@ -26,6 +26,8 @@
 
 #include "llvm/llvm_gen_backend.hpp"
 #include "llvm/llvm_to_gen.hpp"
+#include <llvm/IR/DiagnosticInfo.h>
+#include <llvm/IR/DiagnosticPrinter.h>
 #include "sys/cvar.hpp"
 #include "sys/platform.hpp"
 #include "ir/unit.hpp"
@@ -249,8 +251,36 @@ namespace gbe
   BVAR(OCL_OUTPUT_LLVM_AFTER_LINK, false);
   BVAR(OCL_OUTPUT_LLVM_AFTER_GEN, false);
 
+  class gbeDiagnosticContext
+  {
+  public:
+    gbeDiagnosticContext() : _str(""), messages(_str), printer(messages), _has_errors(false) {}
+    void process(const llvm::DiagnosticInfo &diagnostic)
+    {
+      if (diagnostic.getSeverity() != DS_Remark) { // avoid noise from function inlining remarks
+        diagnostic.print(printer);
+      }
+      if (diagnostic.getSeverity() == DS_Error) {
+        _has_errors = true;
+      }
+    }
+    std::string str(){return messages.str();}
+    bool has_errors(){return _has_errors;}
+  private:
+    std::string _str;
+    llvm::raw_string_ostream messages;
+    llvm::DiagnosticPrinterRawOStream printer;
+    bool _has_errors;
+  };
+  
+  void gbeDiagnosticHandler(const llvm::DiagnosticInfo &diagnostic, void *context)
+  {
+    gbeDiagnosticContext *dc = reinterpret_cast<gbeDiagnosticContext*>(context);
+    dc->process(diagnostic);
+  }
+
   bool llvmToGen(ir::Unit &unit, const char *fileName,const void* module,
-                 int optLevel, bool strictMath, int profiling)
+                 int optLevel, bool strictMath, int profiling, std::string &errors)
   {
     std::string errInfo;
     std::unique_ptr<llvm::raw_fd_ostream> o = NULL;
@@ -287,6 +317,9 @@ namespace gbe
 
     Module &mod = *M.get();
     DataLayout DL(&mod);
+    
+    gbeDiagnosticContext dc;
+    mod.getContext().setDiagnosticHandler(&gbeDiagnosticHandler,&dc);
 
 #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
     mod.setDataLayout(DL);
@@ -345,6 +378,12 @@ namespace gbe
       passes.add(createCFGOnlyPrinterPass());
     passes.add(createGenPass(unit));
     passes.run(mod);
+    errors = dc.str();
+    if(dc.has_errors()){
+      unit.setValid(false);
+      delete libraryInfo;
+      return true;
+    }
 
     // Print the code extra optimization passes
     OUTPUT_BITCODE(AFTER_GEN, mod);
diff --git a/backend/src/llvm/llvm_to_gen.hpp b/backend/src/llvm/llvm_to_gen.hpp
index 5667197..e0a6145 100644
--- a/backend/src/llvm/llvm_to_gen.hpp
+++ b/backend/src/llvm/llvm_to_gen.hpp
@@ -33,7 +33,7 @@ namespace gbe {
   /*! Convert the LLVM IR code to a GEN IR code,
 		  optLevel 0 equal to clang -O1 and 1 equal to clang -O2*/
   bool llvmToGen(ir::Unit &unit, const char *fileName, const void* module,
-                 int optLevel, bool strictMath, int profiling);
+                 int optLevel, bool strictMath, int profiling, std::string &errors);
 
 } /* namespace gbe */
 



More information about the Beignet mailing list