diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/pnacl-llc/SRPCStreamer.cpp | 19 | ||||
-rw-r--r-- | tools/pnacl-llc/SRPCStreamer.h | 9 | ||||
-rw-r--r-- | tools/pnacl-llc/pnacl-llc.cpp | 30 | ||||
-rw-r--r-- | tools/pnacl-llc/srpc_main.cpp | 15 |
4 files changed, 56 insertions, 17 deletions
diff --git a/tools/pnacl-llc/SRPCStreamer.cpp b/tools/pnacl-llc/SRPCStreamer.cpp index e6546aef5f..ddec846d2c 100644 --- a/tools/pnacl-llc/SRPCStreamer.cpp +++ b/tools/pnacl-llc/SRPCStreamer.cpp @@ -119,19 +119,30 @@ llvm::DataStreamer *SRPCStreamer::init(void *(*Callback)(void *), void *arg, } size_t SRPCStreamer::gotChunk(unsigned char *bytes, size_t len) { - if (Error) return 0; + if (__sync_fetch_and_add(&Error, 0)) return 0; // Atomic read. return Q.PutBytes(bytes, len); } int SRPCStreamer::streamEnd(std::string *ErrMsg) { Q.SetDone(); int err = pthread_join(CompileThread, NULL); - if (err) { + __sync_synchronize(); + if (Error) { + if (ErrMsg) + *ErrMsg = std::string("PNaCl Translator Error: " + ErrorMessage); + return 1; + } else if (err) { if (ErrMsg) *ErrMsg = std::string(strerror(errno)); return err; } - if (Error && ErrMsg) *ErrMsg = std::string("compile failed."); - return Error; + return 0; +} + +void SRPCStreamer::setFatalError(const std::string& message) { + __sync_fetch_and_add(&Error, 1); + ErrorMessage = message; + __sync_synchronize(); + pthread_exit(NULL); } #endif // __native_client__ diff --git a/tools/pnacl-llc/SRPCStreamer.h b/tools/pnacl-llc/SRPCStreamer.h index 805552be1f..bde86e5d9f 100644 --- a/tools/pnacl-llc/SRPCStreamer.h +++ b/tools/pnacl-llc/SRPCStreamer.h @@ -98,11 +98,12 @@ public: size_t gotChunk(unsigned char *bytes, size_t len); // Called by the RPC thread. Wait for the compilation thread to finish. int streamEnd(std::string *ErrMsg); - // Called by the compilation thread. Signal that there was a compilation - // error so the RPC thread can abort the stream. - void setError() { Error = true; } + // Called by the compilation thread. Set the error condition and also + // terminate the thread. + void setFatalError(const std::string& message); private: - bool Error; + int Error; + std::string ErrorMessage; QueueStreamer Q; pthread_t CompileThread; }; diff --git a/tools/pnacl-llc/pnacl-llc.cpp b/tools/pnacl-llc/pnacl-llc.cpp index 31d546ab3e..cac4fa83a4 100644 --- a/tools/pnacl-llc/pnacl-llc.cpp +++ b/tools/pnacl-llc/pnacl-llc.cpp @@ -28,6 +28,7 @@ #include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" @@ -52,6 +53,7 @@ using namespace llvm; int srpc_main(int argc, char **argv); int getObjectFileFD(); DataStreamer *getNaClBitcodeStreamer(); +fatal_error_handler_t getSRPCErrorHandler(); #endif cl::opt<NaClFileFormat> @@ -215,6 +217,10 @@ int llc_main(int argc, char **argv) { LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. +#if defined(__native_client__) + install_fatal_error_handler(getSRPCErrorHandler(), NULL); +#endif + // Initialize targets first, so that --version shows registered targets. InitializeAllTargets(); InitializeAllTargetMCs(); @@ -252,11 +258,15 @@ int llc_main(int argc, char **argv) { static void CheckABIVerifyErrors(PNaClABIErrorReporter &Reporter, const Twine &Name) { if (PNaClABIVerify && Reporter.getErrorCount() > 0) { - errs() << (PNaClABIVerifyFatalErrors ? "ERROR: " : "WARNING: "); - errs() << Name << " is not valid PNaCl bitcode:\n"; - Reporter.printErrors(errs()); - if (PNaClABIVerifyFatalErrors) - exit(1); + std::string errors; + raw_string_ostream os(errors); + os << (PNaClABIVerifyFatalErrors ? "ERROR: " : "WARNING: "); + os << Name << " is not valid PNaCl bitcode:\n"; + Reporter.printErrors(os); + if (PNaClABIVerifyFatalErrors) { + report_fatal_error(os.str()); + } + errs() << os.str(); } Reporter.reset(); } @@ -273,11 +283,12 @@ static int compileModule(StringRef ProgramName, LLVMContext &Context) { #if defined(__native_client__) if (LazyBitcode) { std::string StrError; + std::string DisplayFilename("<PNaCl-translated pexe>"); M.reset(getNaClStreamedBitcodeModule( - std::string("<SRPC stream>"), + DisplayFilename, getNaClBitcodeStreamer(), Context, &StrError)); if (!StrError.empty()) - Err = SMDiagnostic(InputFilename, SourceMgr::DK_Error, StrError); + Err = SMDiagnostic(DisplayFilename, SourceMgr::DK_Error, StrError); } else { llvm_unreachable("native client SRPC only supports streaming"); } @@ -287,8 +298,13 @@ static int compileModule(StringRef ProgramName, LLVMContext &Context) { mod = M.get(); if (mod == 0) { +#if defined(__native_client__) + report_fatal_error(Err.getMessage()); +#else + // Err.print is prettier, so use it for the non-sandboxed translator. Err.print(ProgramName.data(), errs()); return 1; +#endif } if (PNaClABIVerify) { diff --git a/tools/pnacl-llc/srpc_main.cpp b/tools/pnacl-llc/srpc_main.cpp index 87178c2038..46d79ce441 100644 --- a/tools/pnacl-llc/srpc_main.cpp +++ b/tools/pnacl-llc/srpc_main.cpp @@ -32,6 +32,7 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Option/Option.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/system_error.h" using namespace llvm; @@ -202,8 +203,10 @@ void *run_streamed(void *arg) { StreamingThreadData *data = reinterpret_cast<StreamingThreadData *>(arg); data->CmdLineVec()->push_back("-streaming-bitcode"); if (DoTranslate(data->CmdLineVec(), data->ObjectFD()) != 0) { - fprintf(stderr, "DoTranslate failed.\n"); - srpc_streamer->setError(); + // llc_main only returns 1 (as opposed to calling report_fatal_error) + // in conditions we never expect to see in the browser (e.g. bad + // command-line flags). + srpc_streamer->setFatalError("llc_main unspecified failure"); return NULL; } delete data; @@ -351,6 +354,14 @@ int getObjectFileFD() { return object_file_fd; } DataStreamer *getNaClBitcodeStreamer() { return NaClBitcodeStreamer; } +// Called from the compilation thread +void FatalErrorHandler(void *user_data, const std::string& reason, + bool gen_crash_diag) { + srpc_streamer->setFatalError(reason); +} + +fatal_error_handler_t getSRPCErrorHandler() { return FatalErrorHandler; } + int srpc_main(int argc, char **argv) { if (!NaClSrpcModuleInit()) { return 1; |