diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/lib/Support/Unix/Program.inc | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/lib/Support/Unix/Program.inc')
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Program.inc | 217 |
1 files changed, 121 insertions, 96 deletions
diff --git a/contrib/llvm/lib/Support/Unix/Program.inc b/contrib/llvm/lib/Support/Unix/Program.inc index aa03d48..78b2971 100644 --- a/contrib/llvm/lib/Support/Unix/Program.inc +++ b/contrib/llvm/lib/Support/Unix/Program.inc @@ -36,6 +36,9 @@ #include <unistd.h> #endif #ifdef HAVE_POSIX_SPAWN +#ifdef __sun__ +#define _RESTRICT_KYWD +#endif #include <spawn.h> #if !defined(__APPLE__) extern char **environ; @@ -47,20 +50,16 @@ namespace llvm { using namespace sys; -Program::Program() : Data_(0) {} - -Program::~Program() {} +ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {} // This function just uses the PATH environment variable to find the program. -Path -Program::FindProgramByName(const std::string& progName) { +std::string +sys::FindProgramByName(const std::string& progName) { // Check some degenerate cases if (progName.length() == 0) // no program - return Path(); - Path temp; - if (!temp.set(progName)) // invalid name - return Path(); + return ""; + std::string temp = progName; // Use the given path verbatim if it contains any slashes; this matches // the behavior of sh(1) and friends. if (progName.find('/') != std::string::npos) @@ -72,7 +71,7 @@ Program::FindProgramByName(const std::string& progName) { // Get the path. If its empty, we can't do anything to find it. const char *PathStr = getenv("PATH"); if (PathStr == 0) - return Path(); + return ""; // Now we have a colon separated list of directories to search; try them. size_t PathLen = strlen(PathStr); @@ -81,12 +80,10 @@ Program::FindProgramByName(const std::string& progName) { const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); // Check to see if this first directory contains the executable... - Path FilePath; - if (FilePath.set(std::string(PathStr,Colon))) { - FilePath.appendComponent(progName); - if (FilePath.canExecute()) - return FilePath; // Found the executable! - } + SmallString<128> FilePath(PathStr,Colon); + sys::path::append(FilePath, progName); + if (sys::fs::can_execute(Twine(FilePath))) + return FilePath.str(); // Found the executable! // Nope it wasn't in this directory, check the next path in the list! PathLen -= Colon-PathStr; @@ -98,23 +95,23 @@ Program::FindProgramByName(const std::string& progName) { PathLen--; } } - return Path(); + return ""; } -static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { +static bool RedirectIO(const StringRef *Path, int FD, std::string* ErrMsg) { if (Path == 0) // Noop return false; - const char *File; - if (Path->isEmpty()) + std::string File; + if (Path->empty()) // Redirect empty paths to /dev/null File = "/dev/null"; else - File = Path->c_str(); + File = *Path; // Open the file - int InFD = open(File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); + int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); if (InFD == -1) { - MakeErrMsg(ErrMsg, "Cannot open file '" + std::string(File) + "' for " + MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " + (FD == 0 ? "input" : "output")); return true; } @@ -130,19 +127,20 @@ static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { } #ifdef HAVE_POSIX_SPAWN -static bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg, +static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg, posix_spawn_file_actions_t *FileActions) { if (Path == 0) // Noop return false; const char *File; - if (Path->isEmpty()) + if (Path->empty()) // Redirect empty paths to /dev/null File = "/dev/null"; else File = Path->c_str(); - if (int Err = posix_spawn_file_actions_addopen(FileActions, FD, - File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666)) + if (int Err = posix_spawn_file_actions_addopen( + FileActions, FD, File, + FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666)) return MakeErrMsg(ErrMsg, "Cannot dup2", Err); return false; } @@ -180,10 +178,18 @@ static void SetMemoryLimits (unsigned size) #endif } -bool -Program::Execute(const Path &path, const char **args, const char **envp, - const Path **redirects, unsigned memoryLimit, - std::string *ErrMsg) { +} + +static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, + const char **envp, const StringRef **redirects, + unsigned memoryLimit, std::string *ErrMsg) { + if (!llvm::sys::fs::exists(Program)) { + if (ErrMsg) + *ErrMsg = std::string("Executable \"") + Program.str() + + std::string("\" doesn't exist!"); + return false; + } + // If this OS has posix_spawn and there is no memory limit being implied, use // posix_spawn. It is more efficient than fork/exec. #ifdef HAVE_POSIX_SPAWN @@ -191,18 +197,32 @@ Program::Execute(const Path &path, const char **args, const char **envp, posix_spawn_file_actions_t FileActionsStore; posix_spawn_file_actions_t *FileActions = 0; + // If we call posix_spawn_file_actions_addopen we have to make sure the + // c strings we pass to it stay alive until the call to posix_spawn, + // so we copy any StringRefs into this variable. + std::string RedirectsStorage[3]; + if (redirects) { + std::string *RedirectsStr[3] = {0, 0, 0}; + for (int I = 0; I < 3; ++I) { + if (redirects[I]) { + RedirectsStorage[I] = *redirects[I]; + RedirectsStr[I] = &RedirectsStorage[I]; + } + } + FileActions = &FileActionsStore; posix_spawn_file_actions_init(FileActions); // Redirect stdin/stdout. - if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) || - RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions)) + if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) || + RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions)) return false; if (redirects[1] == 0 || redirects[2] == 0 || *redirects[1] != *redirects[2]) { // Just redirect stderr - if (RedirectIO_PS(redirects[2], 2, ErrMsg, FileActions)) return false; + if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions)) + return false; } else { // If stdout and stderr should go to the same place, redirect stderr // to the FD already open for stdout. @@ -222,7 +242,7 @@ Program::Execute(const Path &path, const char **args, const char **envp, // Explicitly initialized to prevent what appears to be a valgrind false // positive. pid_t PID = 0; - int Err = posix_spawn(&PID, path.c_str(), FileActions, /*attrp*/0, + int Err = posix_spawn(&PID, Program.str().c_str(), FileActions, /*attrp*/0, const_cast<char **>(args), const_cast<char **>(envp)); if (FileActions) @@ -231,7 +251,8 @@ Program::Execute(const Path &path, const char **args, const char **envp, if (Err) return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); - Data_ = reinterpret_cast<void*>(PID); + PI.Pid = PID; + return true; } #endif @@ -272,12 +293,13 @@ Program::Execute(const Path &path, const char **args, const char **envp, } // Execute! + std::string PathStr = Program; if (envp != 0) - execve(path.c_str(), + execve(PathStr.c_str(), const_cast<char **>(args), const_cast<char **>(envp)); else - execv(path.c_str(), + execv(PathStr.c_str(), const_cast<char **>(args)); // If the execve() failed, we should exit. Follow Unix protocol and // return 127 if the executable was not found, and 126 otherwise. @@ -293,62 +315,71 @@ Program::Execute(const Path &path, const char **args, const char **envp, break; } - Data_ = reinterpret_cast<void*>(child); + PI.Pid = child; return true; } -int -Program::Wait(const sys::Path &path, - unsigned secondsToWait, - std::string* ErrMsg) -{ +namespace llvm { + +ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, + bool WaitUntilTerminates, std::string *ErrMsg) { #ifdef HAVE_SYS_WAIT_H struct sigaction Act, Old; - - if (Data_ == 0) { - MakeErrMsg(ErrMsg, "Process not started!"); - return -1; - } - - // Install a timeout handler. The handler itself does nothing, but the simple - // fact of having a handler at all causes the wait below to return with EINTR, - // unlike if we used SIG_IGN. - if (secondsToWait) { + assert(PI.Pid && "invalid pid to wait on, process not started?"); + + int WaitPidOptions = 0; + pid_t ChildPid = PI.Pid; + if (WaitUntilTerminates) { + SecondsToWait = 0; + ChildPid = -1; // mimic a wait() using waitpid() + } else if (SecondsToWait) { + // Install a timeout handler. The handler itself does nothing, but the + // simple fact of having a handler at all causes the wait below to return + // with EINTR, unlike if we used SIG_IGN. memset(&Act, 0, sizeof(Act)); Act.sa_handler = TimeOutHandler; sigemptyset(&Act.sa_mask); sigaction(SIGALRM, &Act, &Old); - alarm(secondsToWait); - } + alarm(SecondsToWait); + } else if (SecondsToWait == 0) + WaitPidOptions = WNOHANG; // Parent process: Wait for the child process to terminate. int status; - uint64_t pid = reinterpret_cast<uint64_t>(Data_); - pid_t child = static_cast<pid_t>(pid); - while (waitpid(pid, &status, 0) != child) - if (secondsToWait && errno == EINTR) { - // Kill the child. - kill(child, SIGKILL); - - // Turn off the alarm and restore the signal handler - alarm(0); - sigaction(SIGALRM, &Old, 0); - - // Wait for child to die - if (wait(&status) != child) - MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); - else - MakeErrMsg(ErrMsg, "Child timed out", 0); - - return -2; // Timeout detected - } else if (errno != EINTR) { - MakeErrMsg(ErrMsg, "Error waiting for child process"); - return -1; + ProcessInfo WaitResult; + WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions); + if (WaitResult.Pid != PI.Pid) { + if (WaitResult.Pid == 0) { + // Non-blocking wait. + return WaitResult; + } else { + if (SecondsToWait && errno == EINTR) { + // Kill the child. + kill(PI.Pid, SIGKILL); + + // Turn off the alarm and restore the signal handler + alarm(0); + sigaction(SIGALRM, &Old, 0); + + // Wait for child to die + if (wait(&status) != ChildPid) + MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); + else + MakeErrMsg(ErrMsg, "Child timed out", 0); + + WaitResult.ReturnCode = -2; // Timeout detected + return WaitResult; + } else if (errno != EINTR) { + MakeErrMsg(ErrMsg, "Error waiting for child process"); + WaitResult.ReturnCode = -1; + return WaitResult; + } } + } // We exited normally without timeout, so turn off the timer. - if (secondsToWait) { + if (SecondsToWait && !WaitUntilTerminates) { alarm(0); sigaction(SIGALRM, &Old, 0); } @@ -358,24 +389,19 @@ Program::Wait(const sys::Path &path, int result = 0; if (WIFEXITED(status)) { result = WEXITSTATUS(status); -#ifdef HAVE_POSIX_SPAWN - // The posix_spawn child process returns 127 on any kind of error. - // Following the POSIX convention for command-line tools (which posix_spawn - // itself apparently does not), check to see if the failure was due to some - // reason other than the file not existing, and return 126 in this case. - bool Exists; - if (result == 127 && !llvm::sys::fs::exists(path.str(), Exists) && Exists) - result = 126; -#endif + WaitResult.ReturnCode = result; + if (result == 127) { if (ErrMsg) *ErrMsg = llvm::sys::StrError(ENOENT); - return -1; + WaitResult.ReturnCode = -1; + return WaitResult; } if (result == 126) { if (ErrMsg) *ErrMsg = "Program could not be executed"; - return -1; + WaitResult.ReturnCode = -1; + return WaitResult; } } else if (WIFSIGNALED(status)) { if (ErrMsg) { @@ -387,27 +413,27 @@ Program::Wait(const sys::Path &path, } // Return a special value to indicate that the process received an unhandled // signal during execution as opposed to failing to execute. - return -2; + WaitResult.ReturnCode = -2; } - return result; #else if (ErrMsg) *ErrMsg = "Program::Wait is not implemented on this platform yet!"; - return -1; + WaitResult.ReturnCode = -2; #endif + return WaitResult; } -error_code Program::ChangeStdinToBinary(){ +error_code sys::ChangeStdinToBinary(){ // Do nothing, as Unix doesn't differentiate between text and binary. return make_error_code(errc::success); } -error_code Program::ChangeStdoutToBinary(){ +error_code sys::ChangeStdoutToBinary(){ // Do nothing, as Unix doesn't differentiate between text and binary. return make_error_code(errc::success); } -error_code Program::ChangeStderrToBinary(){ +error_code sys::ChangeStderrToBinary(){ // Do nothing, as Unix doesn't differentiate between text and binary. return make_error_code(errc::success); } @@ -432,5 +458,4 @@ bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) { } return true; } - } |