aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/pnacl-llc/SRPCStreamer.cpp19
-rw-r--r--tools/pnacl-llc/SRPCStreamer.h9
-rw-r--r--tools/pnacl-llc/pnacl-llc.cpp30
-rw-r--r--tools/pnacl-llc/srpc_main.cpp15
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;