On Wed, Nov 27, 2013 at 06:44:04AM +0000, Yang, Rong R wrote: > > > -----Original Message----- > From: beignet-boun...@lists.freedesktop.org > [mailto:beignet-boun...@lists.freedesktop.org] On Behalf Of Zhigang Gong > Sent: Wednesday, November 27, 2013 10:47 AM > To: beignet@lists.freedesktop.org > Cc: Gong, Zhigang > Subject: [Beignet] [PATCH 2/2] Runtime: implement the get build log function > and fix one build error check issue. > > According to spec, we need to support CL_PROGRAM_BUILD_LOG which is used to > get the build log of a cl kernel. And we also need to check whether a build > failure is a generic build fail or a build option error. This commit also fix > the piglit case: > API/clBuildProgram. > > Another change in this commit is that it reroute all the output of the clang > excution to internal buffer and don't print to the console directly. If the > user want to get the detail build log, the CL_PROGRAM_BUILD_LOG could be used. > > Signed-off-by: Zhigang Gong <zhigang.g...@intel.com> > --- > backend/src/backend/program.cpp | 53 > ++++++++++++++++++++++++++------------- > src/cl_api.c | 5 ++-- > src/cl_program.c | 13 +++++++--- > src/cl_program.h | 3 +++ > 4 files changed, 51 insertions(+), 23 deletions(-) > > diff --git a/backend/src/backend/program.cpp > b/backend/src/backend/program.cpp index 093febc..24bf6cb 100644 > --- a/backend/src/backend/program.cpp > +++ b/backend/src/backend/program.cpp > @@ -464,7 +464,8 @@ namespace gbe { > GBE_SAFE_DELETE(program); > } > > - static void buildModuleFromSource(const char* input, const char* output, > std::string options) { > + static bool buildModuleFromSource(const char* input, const char* output, > std::string options, > + size_t stringSize, char *err, > + size_t *errSize) { > // Arguments to pass to the clang frontend > vector<const char *> args; > bool bOpt = true; > @@ -516,24 +517,26 @@ namespace gbe { > args.push_back(input); > > // 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; > #if LLVM_VERSION_MINOR <= 1 > args.push_back("-triple"); > args.push_back("ptx32"); > > clang::TextDiagnosticPrinter *DiagClient = > - new clang::TextDiagnosticPrinter(llvm::errs(), > clang::DiagnosticOptions()); > + new > + clang::TextDiagnosticPrinter(ErrorInfo, *DiagOpts) > llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new > clang::DiagnosticIDs()); > clang::DiagnosticsEngine Diags(DiagID, DiagClient); #else > args.push_back("-ffp-contract=off"); > > - llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts = new > clang::DiagnosticOptions(); > clang::TextDiagnosticPrinter *DiagClient = > - new clang::TextDiagnosticPrinter(llvm::errs(), > &*DiagOpts); > + new > + clang::TextDiagnosticPrinter(ErrorInfo, &*DiagOpts); > llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new > clang::DiagnosticIDs()); > clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); #endif > /* LLVM_VERSION_MINOR <= 1 */ > - > // Create the compiler invocation > llvm::OwningPtr<clang::CompilerInvocation> CI(new > clang::CompilerInvocation); > clang::CompilerInvocation::CreateFromArgs(*CI, > @@ -548,10 +551,12 @@ namespace gbe { > #if LLVM_VERSION_MINOR <= 2 > Clang.createDiagnostics(args.size(), &args[0]); #else > - Clang.createDiagnostics(); > + Clang.createDiagnostics(DiagClient, false); > #endif /* LLVM_VERSION_MINOR <= 2 */ > + > + Clang.getDiagnosticOpts().ShowCarets = false; > if (!Clang.hasDiagnostics()) > - return; > + return false; > > // Set Language > clang::LangOptions & lang_opts = Clang.getLangOpts(); @@ -573,23 +578,34 > @@ namespace gbe { > // Create an action and make the compiler instance carry it out > llvm::OwningPtr<clang::CodeGenAction> Act(new > clang::EmitLLVMOnlyAction()); > auto retVal = Clang.ExecuteAction(*Act); > + > + size_t errStrPos = ErrorString.copy(err, stringSize - 1, 0); > + ErrorString.clear(); > + if (errSize) > + *errSize = errStrPos; > if (!retVal) > - return; > + return false; > > llvm::Module *module = Act->takeModule(); > > - std::string ErrorInfo; > #if (LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR > 3) > auto mode = llvm::sys::fs::F_Binary; #else > auto mode = llvm::raw_fd_ostream::F_Binary; #endif > - llvm::raw_fd_ostream OS(output, ErrorInfo, mode); > + llvm::raw_fd_ostream OS(output, ErrorString, mode); > //still write to temp file for code simply, otherwise need add another > function. > //because gbe_program_new_from_llvm also be used by > cl_program_create_from_llvm, can't be removed > //TODO: Pass module to llvmToGen, if use module, should return Act and > use OwningPtr out of this funciton > llvm::WriteBitcodeToFile(module, OS); > + if (errStrPos < stringSize - 1 && ErrorString.size() > 0) { > + size_t errLen; > + errLen = ErrorString.copy(err + errStrPos, stringSize - errStrPos, 0); > + if (errSize) > + *errSize += errLen; > + } > OS.close(); > + return true; > } > > extern std::string ocl_stdlib_str; > @@ -640,15 +656,18 @@ namespace gbe { > fwrite(source, strlen(source), 1, clFile); > fclose(clFile); > > - buildModuleFromSource(clName.c_str(), llName.c_str(), clOpt.c_str()); > - remove(clName.c_str()); > + gbe_program p; > + if (buildModuleFromSource(clName.c_str(), llName.c_str(), > + clOpt.c_str(), stringSize, err, errSize)) { > > // Now build the program from llvm > - static std::mutex gbe_mutex; > - gbe_mutex.lock(); > - gbe_program p = gbe_program_new_from_llvm(llName.c_str(), stringSize, > err, errSize); > - gbe_mutex.unlock(); > - remove(llName.c_str()); > + static std::mutex gbe_mutex; > + gbe_mutex.lock(); > + p = gbe_program_new_from_llvm(llName.c_str(), stringSize, err, > errSize); > Do you need adjust stringSize and err here? And errSize return from > gbe_program_new_from_llvm don't include buildModuleFromSource. You are right. We should keep the build log for the buildModuleFromSource even the build complete successfully. I will send a new version to fix that.
Thanks, Zhigang Gong. > > + gbe_mutex.unlock(); > + remove(llName.c_str()); > + } else > + p = NULL; > + remove(clName.c_str()); > return p; > } > > diff --git a/src/cl_api.c b/src/cl_api.c index 59c47d3..0978129 100644 > --- a/src/cl_api.c > +++ b/src/cl_api.c > @@ -975,8 +975,9 @@ clGetProgramBuildInfo(cl_program program, > > FILL_GETINFO_RET (char, (strlen(ret_str)+1), ret_str, CL_SUCCESS); > } else if (param_name == CL_PROGRAM_BUILD_LOG) { > - // TODO: need to add logs in backend when compiling. > - FILL_GETINFO_RET (char, (strlen(ret_str)+1), ret_str, CL_SUCCESS); > + FILL_GETINFO_RET (char, program->build_log_sz + 1, program->build_log, > CL_SUCCESS); > + if (param_value_size_ret) > + *param_value_size_ret = program->build_log_sz + 1; > } else { > return CL_INVALID_VALUE; > } > diff --git a/src/cl_program.c b/src/cl_program.c index df2f1e0..d6d68c0 100644 > --- a/src/cl_program.c > +++ b/src/cl_program.c > @@ -109,7 +109,9 @@ cl_program_new(cl_context ctx) > p->ref_n = 1; > p->magic = CL_MAGIC_PROGRAM_HEADER; > p->ctx = ctx; > - > + p->build_log = calloc(200, sizeof(char)); if (p->build_log) > + p->build_log_max_sz = 200; > /* The queue also belongs to its context */ > cl_context_add_ref(ctx); > > @@ -223,7 +225,7 @@ cl_program_create_from_llvm(cl_context ctx, > INVALID_VALUE_IF (file_name == NULL); > > program = cl_program_new(ctx); > - program->opaque = gbe_program_new_from_llvm(file_name, 0, NULL, NULL); > + program->opaque = gbe_program_new_from_llvm(file_name, > + program->build_log_max_sz, program->build_log, > + &program->build_log_sz); > if (UNLIKELY(program->opaque == NULL)) { > err = CL_INVALID_PROGRAM; > goto error; > @@ -324,9 +326,12 @@ cl_program_build(cl_program p, const char *options) > } > > if (p->source_type == FROM_SOURCE) { > - p->opaque = gbe_program_new_from_source(p->source, 0, options, NULL, > NULL); > + p->opaque = gbe_program_new_from_source(p->source, > + p->build_log_max_sz, options, p->build_log, &p->build_log_sz); > if (UNLIKELY(p->opaque == NULL)) { > - err = CL_BUILD_PROGRAM_FAILURE; > + if (p->build_log_sz > 0 && strstr(p->build_log, "error: error reading > 'options'")) > + err = CL_INVALID_BUILD_OPTIONS; > + else > + err = CL_BUILD_PROGRAM_FAILURE; > goto error; > } > > diff --git a/src/cl_program.h b/src/cl_program.h index 2cb547a..a6d75da 100644 > --- a/src/cl_program.h > +++ b/src/cl_program.h > @@ -54,6 +54,9 @@ struct _cl_program { > uint32_t source_type:2; /* Built from binary, source or LLVM */ > uint32_t is_built:1; /* Did we call clBuildProgram on it? */ > char *build_opts; /* The build options for this program */ > + size_t build_log_max_sz; /*build log maximum size in byte.*/ > + char *build_log; /* The build log for this program. */ > + size_t build_log_sz; /* The actual build log size.*/ > }; > > /* Create a empty program */ > -- > 1.7.9.5 > > _______________________________________________ > Beignet mailing list > Beignet@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/beignet > _______________________________________________ > Beignet mailing list > Beignet@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/beignet _______________________________________________ Beignet mailing list Beignet@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/beignet