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

Rebecca N. Palmer rebecca_palmer at zoho.com
Tue Jul 12 19:36:10 UTC 2016


I never got a reply to this; is there something wrong with it (i.e. 
should I stop including it in Debian's beignet) or are you just not 
interested in this feature?

In the case I tested, the assert happens in LLVM 3.5 but not 3.7 (which 
instead returns the error "function with no prototype cannot use the 
spir_function calling convention"), but I don't know whether this 
applies to all missing-function errors.

On 06/06/16 23:37, Rebecca N. Palmer wrote:
> 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