From 1fd1c6d1faaa5be44ccda0cbdc0dd6d85fa8b2c0 Mon Sep 17 00:00:00 2001 From: "Rebecca N. Palmer" Date: Mon, 6 Jun 2016 23:37:59 +0100 Subject: Report build failures in backend to the build log 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 Reviewed-by: Yang Rong --- backend/src/backend/program.cpp | 18 +++++++++------ backend/src/llvm/llvm_gen_backend.cpp | 12 +++++----- backend/src/llvm/llvm_to_gen.cpp | 41 ++++++++++++++++++++++++++++++++++- backend/src/llvm/llvm_to_gen.hpp | 2 +- 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp index d13cba54..9746b22b 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 41cb7830..e2f6e4c4 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 @@ -2921,6 +2923,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) @@ -3760,11 +3765,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 41723d1b..02a69ec3 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 +#include #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(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 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 56671973..e0a6145c 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 */ -- cgit v1.2.1