diff --git a/llvm/include/llvm/Support/ErrorHandling.h b/llvm/include/llvm/Support/ErrorHandling.h index 85daaee10458c..d66993b5b2d7a 100644 --- a/llvm/include/llvm/Support/ErrorHandling.h +++ b/llvm/include/llvm/Support/ErrorHandling.h @@ -17,47 +17,46 @@ #include "llvm/Support/Compiler.h" namespace llvm { - class StringRef; - class Twine; - - /// An error handler callback. - typedef void (*fatal_error_handler_t)(void *user_data, - const char *reason, - bool gen_crash_diag); - - /// install_fatal_error_handler - Installs a new error handler to be used - /// whenever a serious (non-recoverable) error is encountered by LLVM. - /// - /// If no error handler is installed the default is to print the error message - /// to stderr, and call exit(1). If an error handler is installed then it is - /// the handler's responsibility to log the message, it will no longer be - /// printed to stderr. If the error handler returns, then exit(1) will be - /// called. - /// - /// It is dangerous to naively use an error handler which throws an exception. - /// Even though some applications desire to gracefully recover from arbitrary - /// faults, blindly throwing exceptions through unfamiliar code isn't a way to - /// achieve this. - /// - /// \param user_data - An argument which will be passed to the install error - /// handler. - void install_fatal_error_handler(fatal_error_handler_t handler, - void *user_data = nullptr); - - /// Restores default error handling behaviour. - void remove_fatal_error_handler(); - - /// ScopedFatalErrorHandler - This is a simple helper class which just - /// calls install_fatal_error_handler in its constructor and - /// remove_fatal_error_handler in its destructor. - struct ScopedFatalErrorHandler { - explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, - void *user_data = nullptr) { - install_fatal_error_handler(handler, user_data); - } - - ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } - }; +class StringRef; +class Twine; + +/// An error handler callback. +typedef void (*fatal_error_handler_t)(void *user_data, const char *reason, + bool gen_crash_diag); + +/// install_fatal_error_handler - Installs a new error handler to be used +/// whenever a serious (non-recoverable) error is encountered by LLVM. +/// +/// If no error handler is installed the default is to print the error message +/// to stderr, and call exit(1). If an error handler is installed then it is +/// the handler's responsibility to log the message, it will no longer be +/// printed to stderr. If the error handler returns, then exit(1) will be +/// called. +/// +/// It is dangerous to naively use an error handler which throws an exception. +/// Even though some applications desire to gracefully recover from arbitrary +/// faults, blindly throwing exceptions through unfamiliar code isn't a way to +/// achieve this. +/// +/// \param user_data - An argument which will be passed to the install error +/// handler. +void install_fatal_error_handler(fatal_error_handler_t handler, + void *user_data = nullptr); + +/// Restores default error handling behaviour. +void remove_fatal_error_handler(); + +/// ScopedFatalErrorHandler - This is a simple helper class which just +/// calls install_fatal_error_handler in its constructor and +/// remove_fatal_error_handler in its destructor. +struct ScopedFatalErrorHandler { + explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, + void *user_data = nullptr) { + install_fatal_error_handler(handler, user_data); + } + + ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } +}; /// @deprecated Use reportFatalInternalError() or reportFatalUsageError() /// instead. @@ -139,10 +138,10 @@ void install_out_of_memory_new_handler(); /// This function calls abort(), and prints the optional message to stderr. /// Use the llvm_unreachable macro (that adds location info), instead of /// calling this function directly. -[[noreturn]] void -llvm_unreachable_internal(const char *msg = nullptr, const char *file = nullptr, - unsigned line = 0); -} +[[noreturn]] void llvm_unreachable_internal(const char *msg = nullptr, + const char *file = nullptr, + unsigned line = 0); +} // namespace llvm /// Marks that the current location is not supposed to be reachable. /// In !NDEBUG builds, prints the message and location info to stderr. @@ -162,7 +161,7 @@ llvm_unreachable_internal(const char *msg = nullptr, const char *file = nullptr, /// diagnostics for unreachable code paths, and allows compilers to omit /// unnecessary code. #ifndef NDEBUG -#define llvm_unreachable(msg) \ +#define llvm_unreachable(msg) \ ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) #elif !defined(LLVM_BUILTIN_UNREACHABLE) #define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() diff --git a/llvm/include/llvm/Support/FileUtilities.h b/llvm/include/llvm/Support/FileUtilities.h index 9707724d63170..c5a8457ca3fbb 100644 --- a/llvm/include/llvm/Support/FileUtilities.h +++ b/llvm/include/llvm/Support/FileUtilities.h @@ -22,81 +22,79 @@ namespace llvm { - /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if - /// the files match, 1 if they are different, and 2 if there is a file error. - /// This function allows you to specify an absolute and relative FP error that - /// is allowed to exist. If you specify a string to fill in for the error - /// option, it will set the string to an error message if an error occurs, or - /// if the files are different. - /// - int DiffFilesWithTolerance(StringRef FileA, - StringRef FileB, - double AbsTol, double RelTol, - std::string *Error = nullptr); - - - /// FileRemover - This class is a simple object meant to be stack allocated. - /// If an exception is thrown from a region, the object removes the filename - /// specified (if deleteIt is true). - /// - class FileRemover { - SmallString<128> Filename; - bool DeleteIt; - public: - FileRemover() : DeleteIt(false) {} - - explicit FileRemover(const Twine& filename, bool deleteIt = true) +/// DiffFilesWithTolerance - Compare the two files specified, returning 0 if +/// the files match, 1 if they are different, and 2 if there is a file error. +/// This function allows you to specify an absolute and relative FP error that +/// is allowed to exist. If you specify a string to fill in for the error +/// option, it will set the string to an error message if an error occurs, or +/// if the files are different. +/// +int DiffFilesWithTolerance(StringRef FileA, StringRef FileB, double AbsTol, + double RelTol, std::string *Error = nullptr); + +/// FileRemover - This class is a simple object meant to be stack allocated. +/// If an exception is thrown from a region, the object removes the filename +/// specified (if deleteIt is true). +/// +class FileRemover { + SmallString<128> Filename; + bool DeleteIt; + +public: + FileRemover() : DeleteIt(false) {} + + explicit FileRemover(const Twine &filename, bool deleteIt = true) : DeleteIt(deleteIt) { - filename.toVector(Filename); - } + filename.toVector(Filename); + } - ~FileRemover() { - if (DeleteIt) { - // Ignore problems deleting the file. - sys::fs::remove(Filename); - } + ~FileRemover() { + if (DeleteIt) { + // Ignore problems deleting the file. + sys::fs::remove(Filename); } - - /// setFile - Give ownership of the file to the FileRemover so it will - /// be removed when the object is destroyed. If the FileRemover already - /// had ownership of a file, remove it first. - void setFile(const Twine& filename, bool deleteIt = true) { - if (DeleteIt) { - // Ignore problems deleting the file. - sys::fs::remove(Filename); - } - - Filename.clear(); - filename.toVector(Filename); - DeleteIt = deleteIt; + } + + /// setFile - Give ownership of the file to the FileRemover so it will + /// be removed when the object is destroyed. If the FileRemover already + /// had ownership of a file, remove it first. + void setFile(const Twine &filename, bool deleteIt = true) { + if (DeleteIt) { + // Ignore problems deleting the file. + sys::fs::remove(Filename); } - /// releaseFile - Take ownership of the file away from the FileRemover so it - /// will not be removed when the object is destroyed. - void releaseFile() { DeleteIt = false; } - }; - - /// FilePermssionsApplier helps to copy permissions from an input file to - /// an output one. It memorizes the status of the input file and can apply - /// permissions and dates to the output file. - class FilePermissionsApplier { - public: - static Expected create(StringRef InputFilename); - - /// Apply stored permissions to the \p OutputFilename. - /// Copy LastAccess and ModificationTime if \p CopyDates is true. - /// Overwrite stored permissions if \p OverwritePermissions is specified. - Error - apply(StringRef OutputFilename, bool CopyDates = false, - std::optional OverwritePermissions = std::nullopt); - - private: - FilePermissionsApplier(StringRef InputFilename, sys::fs::file_status Status) - : InputFilename(InputFilename), InputStatus(Status) {} - - StringRef InputFilename; - sys::fs::file_status InputStatus; - }; -} // End llvm namespace + Filename.clear(); + filename.toVector(Filename); + DeleteIt = deleteIt; + } + + /// releaseFile - Take ownership of the file away from the FileRemover so it + /// will not be removed when the object is destroyed. + void releaseFile() { DeleteIt = false; } +}; + +/// FilePermssionsApplier helps to copy permissions from an input file to +/// an output one. It memorizes the status of the input file and can apply +/// permissions and dates to the output file. +class FilePermissionsApplier { +public: + static Expected create(StringRef InputFilename); + + /// Apply stored permissions to the \p OutputFilename. + /// Copy LastAccess and ModificationTime if \p CopyDates is true. + /// Overwrite stored permissions if \p OverwritePermissions is specified. + Error + apply(StringRef OutputFilename, bool CopyDates = false, + std::optional OverwritePermissions = std::nullopt); + +private: + FilePermissionsApplier(StringRef InputFilename, sys::fs::file_status Status) + : InputFilename(InputFilename), InputStatus(Status) {} + + StringRef InputFilename; + sys::fs::file_status InputStatus; +}; +} // namespace llvm #endif diff --git a/llvm/include/llvm/Support/Program.h b/llvm/include/llvm/Support/Program.h index 9df94eb604c7d..7ef532dfdedef 100644 --- a/llvm/include/llvm/Support/Program.h +++ b/llvm/include/llvm/Support/Program.h @@ -1,4 +1,4 @@ -//===- llvm/Support/Program.h ------------------------------------*- C++ -*-===// +//===- llvm/Support/Program.h -----------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -26,222 +26,222 @@ namespace llvm { class BitVector; namespace sys { - /// This is the OS-specific separator for PATH like environment variables: - // a colon on Unix or a semicolon on Windows. +/// This is the OS-specific separator for PATH like environment variables: +// a colon on Unix or a semicolon on Windows. #if defined(LLVM_ON_UNIX) - const char EnvPathSeparator = ':'; -#elif defined (_WIN32) - const char EnvPathSeparator = ';'; +const char EnvPathSeparator = ':'; +#elif defined(_WIN32) +const char EnvPathSeparator = ';'; #endif #if defined(_WIN32) - typedef unsigned long procid_t; // Must match the type of DWORD on Windows. - typedef void *process_t; // Must match the type of HANDLE on Windows. +typedef unsigned long procid_t; // Must match the type of DWORD on Windows. +typedef void *process_t; // Must match the type of HANDLE on Windows. #else - typedef ::pid_t procid_t; - typedef procid_t process_t; +typedef ::pid_t procid_t; +typedef procid_t process_t; #endif - /// This struct encapsulates information about a process. - struct ProcessInfo { - enum : procid_t { InvalidPid = 0 }; - - procid_t Pid; /// The process identifier. - process_t Process; /// Platform-dependent process object. - - /// The return code, set after execution. - int ReturnCode; - - ProcessInfo(); - }; - - /// This struct encapsulates information about a process execution. - struct ProcessStatistics { - std::chrono::microseconds TotalTime; - std::chrono::microseconds UserTime; - uint64_t PeakMemory = 0; ///< Maximum resident set size in KiB. - }; - - /// Find the first executable file \p Name in \p Paths. - /// - /// This does not perform hashing as a shell would but instead stats each PATH - /// entry individually so should generally be avoided. Core LLVM library - /// functions and options should instead require fully specified paths. - /// - /// \param Name name of the executable to find. If it contains any system - /// slashes, it will be returned as is. - /// \param Paths optional list of paths to search for \p Name. If empty it - /// will use the system PATH environment instead. - /// - /// \returns The fully qualified path to the first \p Name in \p Paths if it - /// exists. \p Name if \p Name has slashes in it. Otherwise an error. - ErrorOr - findProgramByName(StringRef Name, ArrayRef Paths = {}); - - // These functions change the specified standard stream (stdin or stdout) mode - // based on the Flags. They return errc::success if the specified stream was - // changed. Otherwise, a platform dependent error is returned. - std::error_code ChangeStdinMode(fs::OpenFlags Flags); - std::error_code ChangeStdoutMode(fs::OpenFlags Flags); - - // These functions change the specified standard stream (stdin or stdout) to - // binary mode. They return errc::success if the specified stream - // was changed. Otherwise a platform dependent error is returned. - std::error_code ChangeStdinToBinary(); - std::error_code ChangeStdoutToBinary(); - - /// This function executes the program using the arguments provided. The - /// invoked program will inherit the stdin, stdout, and stderr file - /// descriptors, the environment and other configuration settings of the - /// invoking program. - /// This function waits for the program to finish, so should be avoided in - /// library functions that aren't expected to block. Consider using - /// ExecuteNoWait() instead. - /// \returns an integer result code indicating the status of the program. - /// A zero or positive value indicates the result code of the program. - /// -1 indicates failure to execute - /// -2 indicates a crash during execution or timeout - int ExecuteAndWait( - StringRef Program, ///< Path of the program to be executed. It is - ///< presumed this is the result of the findProgramByName method. - ArrayRef Args, ///< An array of strings that are passed to the - ///< program. The first element should be the name of the program. - ///< The array should **not** be terminated by an empty StringRef. - std::optional> Env = - std::nullopt, ///< An optional vector of - ///< strings to use for the program's environment. If not provided, the - ///< current program's environment will be used. If specified, the - ///< vector should **not** be terminated by an empty StringRef. - ArrayRef> Redirects = {}, ///< - ///< An array of optional paths. Should have a size of zero or three. - ///< If the array is empty, no redirections are performed. - ///< Otherwise, the inferior process's stdin(0), stdout(1), and stderr(2) - ///< will be redirected to the corresponding paths, if the optional path - ///< is present (not \c std::nullopt). - ///< When an empty path is passed in, the corresponding file descriptor - ///< will be disconnected (ie, /dev/null'd) in a portable way. - unsigned SecondsToWait = 0, ///< If non-zero, this specifies the amount - ///< of time to wait for the child process to exit. If the time - ///< expires, the child is killed and this call returns. If zero, - ///< this function will wait until the child finishes or forever if - ///< it doesn't. - unsigned MemoryLimit = 0, ///< If non-zero, this specifies max. amount - ///< of memory can be allocated by process. If memory usage will be - ///< higher limit, the child is killed and this call returns. If zero - ///< - no memory limit. - std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a - ///< string instance in which error messages will be returned. If the - ///< string is non-empty upon return an error occurred while invoking the - ///< program. - bool *ExecutionFailed = nullptr, - std::optional *ProcStat = nullptr, ///< If non-zero, - /// provides a pointer to a structure in which process execution - /// statistics will be stored. - BitVector *AffinityMask = nullptr ///< CPUs or processors the new - /// program shall run on. - ); - - /// Similar to \ref ExecuteAndWait, but returns immediately. - /// \returns The \ref ProcessInfo of the newly launched process. - /// \note On Microsoft Windows systems, users will need to either call - /// \ref Wait until the process has finished executing or win32's CloseHandle - /// API on ProcessInfo.ProcessHandle to avoid memory leaks. - ProcessInfo ExecuteNoWait( - StringRef Program, ArrayRef Args, - std::optional> Env, - ArrayRef> Redirects = {}, - unsigned MemoryLimit = 0, std::string *ErrMsg = nullptr, - bool *ExecutionFailed = nullptr, BitVector *AffinityMask = nullptr, - /// If true the executed program detatches from the controlling - /// terminal. I/O streams such as llvm::outs, llvm::errs, and stdin will - /// be closed until redirected to another output location - bool DetachProcess = false); - - /// Return true if the given arguments fit within system-specific - /// argument length limits. - bool commandLineFitsWithinSystemLimits(StringRef Program, - ArrayRef Args); - - /// Return true if the given arguments fit within system-specific - /// argument length limits. - bool commandLineFitsWithinSystemLimits(StringRef Program, - ArrayRef Args); - - /// File encoding options when writing contents that a non-UTF8 tool will - /// read (on Windows systems). For UNIX, we always use UTF-8. - enum WindowsEncodingMethod { - /// UTF-8 is the LLVM native encoding, being the same as "do not perform - /// encoding conversion". - WEM_UTF8, - WEM_CurrentCodePage, - WEM_UTF16 - }; - - /// Saves the UTF8-encoded \p contents string into the file \p FileName - /// using a specific encoding. - /// - /// This write file function adds the possibility to choose which encoding - /// to use when writing a text file. On Windows, this is important when - /// writing files with internationalization support with an encoding that is - /// different from the one used in LLVM (UTF-8). We use this when writing - /// response files, since GCC tools on MinGW only understand legacy code - /// pages, and VisualStudio tools only understand UTF-16. - /// For UNIX, using different encodings is silently ignored, since all tools - /// work well with UTF-8. - /// This function assumes that you only use UTF-8 *text* data and will convert - /// it to your desired encoding before writing to the file. - /// - /// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in - /// a MinGW/MinGW-w64 environment, which has serious flaws but currently is - /// our best shot to make gcc/ld understand international characters. This - /// should be changed as soon as binutils fix this to support UTF16 on mingw. - /// - /// \returns non-zero error_code if failed - std::error_code - writeFileWithEncoding(StringRef FileName, StringRef Contents, - WindowsEncodingMethod Encoding = WEM_UTF8); - - /// This function waits for the process specified by \p PI to finish. - /// \returns A \see ProcessInfo struct with Pid set to: - /// \li The process id of the child process if the child process has changed - /// state. - /// \li 0 if the child process has not changed state. - /// \note Users of this function should always check the ReturnCode member of - /// the \see ProcessInfo returned from this function. - ProcessInfo - Wait(const ProcessInfo &PI, ///< The child process that should be waited on. - std::optional SecondsToWait, ///< If std::nullopt, waits until - ///< child has terminated. - ///< If a value, this specifies the amount of time to wait for the child - ///< process. If the time expires, and \p Polling is false, the child is - ///< killed and this < function returns. If the time expires and \p - ///< Polling is true, the child is resumed. - ///< - ///< If zero, this function will perform a non-blocking - ///< wait on the child process. - std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a - ///< string instance in which error messages will be returned. If the - ///< string is non-empty upon return an error occurred while invoking the - ///< program. - std::optional *ProcStat = - nullptr, ///< If non-zero, provides - /// a pointer to a structure in which process execution statistics will - /// be stored. - - bool Polling = false ///< If true, do not kill the process on timeout. - ); - - /// Print a command argument, and optionally quote it. - void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote); +/// This struct encapsulates information about a process. +struct ProcessInfo { + enum : procid_t { InvalidPid = 0 }; + + procid_t Pid; /// The process identifier. + process_t Process; /// Platform-dependent process object. + + /// The return code, set after execution. + int ReturnCode; + + ProcessInfo(); +}; + +/// This struct encapsulates information about a process execution. +struct ProcessStatistics { + std::chrono::microseconds TotalTime; + std::chrono::microseconds UserTime; + uint64_t PeakMemory = 0; ///< Maximum resident set size in KiB. +}; + +/// Find the first executable file \p Name in \p Paths. +/// +/// This does not perform hashing as a shell would but instead stats each PATH +/// entry individually so should generally be avoided. Core LLVM library +/// functions and options should instead require fully specified paths. +/// +/// \param Name name of the executable to find. If it contains any system +/// slashes, it will be returned as is. +/// \param Paths optional list of paths to search for \p Name. If empty it +/// will use the system PATH environment instead. +/// +/// \returns The fully qualified path to the first \p Name in \p Paths if it +/// exists. \p Name if \p Name has slashes in it. Otherwise an error. +ErrorOr findProgramByName(StringRef Name, + ArrayRef Paths = {}); + +// These functions change the specified standard stream (stdin or stdout) mode +// based on the Flags. They return errc::success if the specified stream was +// changed. Otherwise, a platform dependent error is returned. +std::error_code ChangeStdinMode(fs::OpenFlags Flags); +std::error_code ChangeStdoutMode(fs::OpenFlags Flags); + +// These functions change the specified standard stream (stdin or stdout) to +// binary mode. They return errc::success if the specified stream +// was changed. Otherwise a platform dependent error is returned. +std::error_code ChangeStdinToBinary(); +std::error_code ChangeStdoutToBinary(); + +/// This function executes the program using the arguments provided. The +/// invoked program will inherit the stdin, stdout, and stderr file +/// descriptors, the environment and other configuration settings of the +/// invoking program. +/// This function waits for the program to finish, so should be avoided in +/// library functions that aren't expected to block. Consider using +/// ExecuteNoWait() instead. +/// \returns an integer result code indicating the status of the program. +/// A zero or positive value indicates the result code of the program. +/// -1 indicates failure to execute +/// -2 indicates a crash during execution or timeout +int ExecuteAndWait( + StringRef Program, ///< Path of the program to be executed. It is + ///< presumed this is the result of the findProgramByName method. + ArrayRef Args, ///< An array of strings that are passed to the + ///< program. The first element should be the name of the program. + ///< The array should **not** be terminated by an empty StringRef. + std::optional> Env = + std::nullopt, ///< An optional vector of + ///< strings to use for the program's environment. If not provided, the + ///< current program's environment will be used. If specified, the + ///< vector should **not** be terminated by an empty StringRef. + ArrayRef> Redirects = {}, ///< + ///< An array of optional paths. Should have a size of zero or three. + ///< If the array is empty, no redirections are performed. + ///< Otherwise, the inferior process's stdin(0), stdout(1), and stderr(2) + ///< will be redirected to the corresponding paths, if the optional path + ///< is present (not \c std::nullopt). + ///< When an empty path is passed in, the corresponding file descriptor + ///< will be disconnected (ie, /dev/null'd) in a portable way. + unsigned SecondsToWait = 0, ///< If non-zero, this specifies the amount + ///< of time to wait for the child process to exit. If the time + ///< expires, the child is killed and this call returns. If zero, + ///< this function will wait until the child finishes or forever if + ///< it doesn't. + unsigned MemoryLimit = 0, ///< If non-zero, this specifies max. amount + ///< of memory can be allocated by process. If memory usage will be + ///< higher limit, the child is killed and this call returns. If zero + ///< - no memory limit. + std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a + ///< string instance in which error messages will be returned. If the + ///< string is non-empty upon return an error occurred while invoking the + ///< program. + bool *ExecutionFailed = nullptr, + std::optional *ProcStat = nullptr, ///< If non-zero, + /// provides a pointer to a structure in which process execution + /// statistics will be stored. + BitVector *AffinityMask = nullptr ///< CPUs or processors the new + /// program shall run on. +); + +/// Similar to \ref ExecuteAndWait, but returns immediately. +/// \returns The \ref ProcessInfo of the newly launched process. +/// \note On Microsoft Windows systems, users will need to either call +/// \ref Wait until the process has finished executing or win32's CloseHandle +/// API on ProcessInfo.ProcessHandle to avoid memory leaks. +ProcessInfo ExecuteNoWait( + StringRef Program, ArrayRef Args, + std::optional> Env, + ArrayRef> Redirects = {}, unsigned MemoryLimit = 0, + std::string *ErrMsg = nullptr, bool *ExecutionFailed = nullptr, + BitVector *AffinityMask = nullptr, + /// If true the executed program detatches from the controlling + /// terminal. I/O streams such as llvm::outs, llvm::errs, and stdin will + /// be closed until redirected to another output location + bool DetachProcess = false); + +/// Return true if the given arguments fit within system-specific +/// argument length limits. +bool commandLineFitsWithinSystemLimits(StringRef Program, + ArrayRef Args); + +/// Return true if the given arguments fit within system-specific +/// argument length limits. +bool commandLineFitsWithinSystemLimits(StringRef Program, + ArrayRef Args); + +/// File encoding options when writing contents that a non-UTF8 tool will +/// read (on Windows systems). For UNIX, we always use UTF-8. +enum WindowsEncodingMethod { + /// UTF-8 is the LLVM native encoding, being the same as "do not perform + /// encoding conversion". + WEM_UTF8, + WEM_CurrentCodePage, + WEM_UTF16 +}; + +/// Saves the UTF8-encoded \p contents string into the file \p FileName +/// using a specific encoding. +/// +/// This write file function adds the possibility to choose which encoding +/// to use when writing a text file. On Windows, this is important when +/// writing files with internationalization support with an encoding that is +/// different from the one used in LLVM (UTF-8). We use this when writing +/// response files, since GCC tools on MinGW only understand legacy code +/// pages, and VisualStudio tools only understand UTF-16. +/// For UNIX, using different encodings is silently ignored, since all tools +/// work well with UTF-8. +/// This function assumes that you only use UTF-8 *text* data and will convert +/// it to your desired encoding before writing to the file. +/// +/// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in +/// a MinGW/MinGW-w64 environment, which has serious flaws but currently is +/// our best shot to make gcc/ld understand international characters. This +/// should be changed as soon as binutils fix this to support UTF16 on mingw. +/// +/// \returns non-zero error_code if failed +std::error_code +writeFileWithEncoding(StringRef FileName, StringRef Contents, + WindowsEncodingMethod Encoding = WEM_UTF8); + +/// This function waits for the process specified by \p PI to finish. +/// \returns A \see ProcessInfo struct with Pid set to: +/// \li The process id of the child process if the child process has changed +/// state. +/// \li 0 if the child process has not changed state. +/// \note Users of this function should always check the ReturnCode member of +/// the \see ProcessInfo returned from this function. +ProcessInfo +Wait(const ProcessInfo &PI, ///< The child process that should be waited on. + std::optional SecondsToWait, ///< If std::nullopt, waits until + ///< child has terminated. + ///< If a value, this specifies the amount of time to wait for the child + ///< process. If the time expires, and \p Polling is false, the child is + ///< killed and this < function returns. If the time expires and \p + ///< Polling is true, the child is resumed. + ///< + ///< If zero, this function will perform a non-blocking + ///< wait on the child process. + std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a + ///< string instance in which error messages will be returned. If the + ///< string is non-empty upon return an error occurred while invoking the + ///< program. + std::optional *ProcStat = + nullptr, ///< If non-zero, provides + /// a pointer to a structure in which process execution statistics will + /// be stored. + + bool Polling = false ///< If true, do not kill the process on timeout. +); + +/// Print a command argument, and optionally quote it. +void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote); #if defined(_WIN32) - /// Given a list of command line arguments, quote and escape them as necessary - /// to build a single flat command line appropriate for calling CreateProcess - /// on - /// Windows. - ErrorOr flattenWindowsCommandLine(ArrayRef Args); +/// Given a list of command line arguments, quote and escape them as necessary +/// to build a single flat command line appropriate for calling CreateProcess +/// on +/// Windows. +ErrorOr flattenWindowsCommandLine(ArrayRef Args); #endif - } -} +} // namespace sys +} // namespace llvm #endif diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 70749ce30184a..0a560e645e1f0 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -1,4 +1,4 @@ -//===- llvm/Support/Signals.h - Signal Handling support ----------*- C++ -*-===// +//===- llvm/Support/Signals.h - Signal Handling support ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -23,107 +23,107 @@ class raw_ostream; namespace sys { - /// This function runs all the registered interrupt handlers, including the - /// removal of files registered by RemoveFileOnSignal. - void RunInterruptHandlers(); - - /// This function registers signal handlers to ensure that if a signal gets - /// delivered that the named file is removed. - /// Remove a file if a fatal signal occurs. - bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = nullptr); - - /// This function removes a file from the list of files to be removed on - /// signal delivery. - void DontRemoveFileOnSignal(StringRef Filename); - - /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the - /// process, print a stack trace and then exit. - /// Print a stack trace if a fatal signal occurs. - /// \param Argv0 the current binary name, used to find the symbolizer - /// relative to the current binary before searching $PATH; can be - /// StringRef(), in which case we will only search $PATH. - /// \param DisableCrashReporting if \c true, disable the normal crash - /// reporting mechanisms on the underlying operating system. - void PrintStackTraceOnErrorSignal(StringRef Argv0, - bool DisableCrashReporting = false); - - /// Disable all system dialog boxes that appear when the process crashes. - void DisableSystemDialogsOnCrash(); - - /// Print the stack trace using the given \c raw_ostream object. - /// \param Depth refers to the number of stackframes to print. If not - /// specified, the entire frame is printed. - void PrintStackTrace(raw_ostream &OS, int Depth = 0); - - // Run all registered signal handlers. - void RunSignalHandlers(); - - using SignalHandlerCallback = void (*)(void *); - - /// Add a function to be called when an abort/kill signal is delivered to the - /// process. The handler can have a cookie passed to it to identify what - /// instance of the handler it is. - void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie); - - /// This function registers a function to be called when the user "interrupts" - /// the program (typically by pressing ctrl-c). When the user interrupts the - /// program, the specified interrupt function is called instead of the program - /// being killed, and the interrupt function automatically disabled. - /// - /// Note that interrupt functions are not allowed to call any non-reentrant - /// functions. An null interrupt function pointer disables the current - /// installed function. Note also that the handler may be executed on a - /// different thread on some platforms. - void SetInterruptFunction(void (*IF)()); - - /// Registers a function to be called when an "info" signal is delivered to - /// the process. - /// - /// On POSIX systems, this will be SIGUSR1; on systems that have it, SIGINFO - /// will also be used (typically ctrl-t). - /// - /// Note that signal handlers are not allowed to call any non-reentrant - /// functions. An null function pointer disables the current installed - /// function. Note also that the handler may be executed on a different - /// thread on some platforms. - void SetInfoSignalFunction(void (*Handler)()); - - /// Registers a function to be called in a "one-shot" manner when a pipe - /// signal is delivered to the process (i.e., on a failed write to a pipe). - /// After the pipe signal is handled once, the handler is unregistered. - /// - /// The LLVM signal handling code will not install any handler for the pipe - /// signal unless one is provided with this API (see \ref - /// DefaultOneShotPipeSignalHandler). This handler must be provided before - /// any other LLVM signal handlers are installed: the \ref InitLLVM - /// constructor has a flag that can simplify this setup. - /// - /// Note that the handler is not allowed to call any non-reentrant - /// functions. A null handler pointer disables the current installed - /// function. Note also that the handler may be executed on a - /// different thread on some platforms. - void SetOneShotPipeSignalFunction(void (*Handler)()); - - /// On Unix systems and Windows, this function exits with an "IO error" exit - /// code. - void DefaultOneShotPipeSignalHandler(); +/// This function runs all the registered interrupt handlers, including the +/// removal of files registered by RemoveFileOnSignal. +void RunInterruptHandlers(); + +/// This function registers signal handlers to ensure that if a signal gets +/// delivered that the named file is removed. +/// Remove a file if a fatal signal occurs. +bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg = nullptr); + +/// This function removes a file from the list of files to be removed on +/// signal delivery. +void DontRemoveFileOnSignal(StringRef Filename); + +/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the +/// process, print a stack trace and then exit. +/// Print a stack trace if a fatal signal occurs. +/// \param Argv0 the current binary name, used to find the symbolizer +/// relative to the current binary before searching $PATH; can be +/// StringRef(), in which case we will only search $PATH. +/// \param DisableCrashReporting if \c true, disable the normal crash +/// reporting mechanisms on the underlying operating system. +void PrintStackTraceOnErrorSignal(StringRef Argv0, + bool DisableCrashReporting = false); + +/// Disable all system dialog boxes that appear when the process crashes. +void DisableSystemDialogsOnCrash(); + +/// Print the stack trace using the given \c raw_ostream object. +/// \param Depth refers to the number of stackframes to print. If not +/// specified, the entire frame is printed. +void PrintStackTrace(raw_ostream &OS, int Depth = 0); + +// Run all registered signal handlers. +void RunSignalHandlers(); + +using SignalHandlerCallback = void (*)(void *); + +/// Add a function to be called when an abort/kill signal is delivered to the +/// process. The handler can have a cookie passed to it to identify what +/// instance of the handler it is. +void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie); + +/// This function registers a function to be called when the user "interrupts" +/// the program (typically by pressing ctrl-c). When the user interrupts the +/// program, the specified interrupt function is called instead of the program +/// being killed, and the interrupt function automatically disabled. +/// +/// Note that interrupt functions are not allowed to call any non-reentrant +/// functions. An null interrupt function pointer disables the current +/// installed function. Note also that the handler may be executed on a +/// different thread on some platforms. +void SetInterruptFunction(void (*IF)()); + +/// Registers a function to be called when an "info" signal is delivered to +/// the process. +/// +/// On POSIX systems, this will be SIGUSR1; on systems that have it, SIGINFO +/// will also be used (typically ctrl-t). +/// +/// Note that signal handlers are not allowed to call any non-reentrant +/// functions. An null function pointer disables the current installed +/// function. Note also that the handler may be executed on a different +/// thread on some platforms. +void SetInfoSignalFunction(void (*Handler)()); + +/// Registers a function to be called in a "one-shot" manner when a pipe +/// signal is delivered to the process (i.e., on a failed write to a pipe). +/// After the pipe signal is handled once, the handler is unregistered. +/// +/// The LLVM signal handling code will not install any handler for the pipe +/// signal unless one is provided with this API (see \ref +/// DefaultOneShotPipeSignalHandler). This handler must be provided before +/// any other LLVM signal handlers are installed: the \ref InitLLVM +/// constructor has a flag that can simplify this setup. +/// +/// Note that the handler is not allowed to call any non-reentrant +/// functions. A null handler pointer disables the current installed +/// function. Note also that the handler may be executed on a +/// different thread on some platforms. +void SetOneShotPipeSignalFunction(void (*Handler)()); + +/// On Unix systems and Windows, this function exits with an "IO error" exit +/// code. +void DefaultOneShotPipeSignalHandler(); #ifdef _WIN32 - /// Windows does not support signals and this handler must be called manually. - void CallOneShotPipeSignalHandler(); +/// Windows does not support signals and this handler must be called manually. +void CallOneShotPipeSignalHandler(); #endif - /// This function does the following: - /// - clean up any temporary files registered with RemoveFileOnSignal() - /// - dump the callstack from the exception context - /// - call any relevant interrupt/signal handlers - /// - create a core/mini dump of the exception context whenever possible - /// Context is a system-specific failure context: it is the signal type on - /// Unix; the ExceptionContext on Windows. - void CleanupOnSignal(uintptr_t Context); - - void unregisterHandlers(); -} // End sys namespace -} // End llvm namespace +/// This function does the following: +/// - clean up any temporary files registered with RemoveFileOnSignal() +/// - dump the callstack from the exception context +/// - call any relevant interrupt/signal handlers +/// - create a core/mini dump of the exception context whenever possible +/// Context is a system-specific failure context: it is the signal type on +/// Unix; the ExceptionContext on Windows. +void CleanupOnSignal(uintptr_t Context); + +void unregisterHandlers(); +} // namespace sys +} // namespace llvm #endif