[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