-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conditionalize use of POSIX features missing on WASI/WebAssembly #92677
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-support @llvm/pr-subscribers-clang-driver Author: Catherine (whitequark) ChangesThis patch is the first in a series that makes it possible to build LLVM, Clang, and LLD for WASI/WebAssembly. This patch does not introduce conditionals of the form The complete list of feature tests introduced is:
Full diff: https://github.com/llvm/llvm-project/pull/92677.diff 11 Files Affected:
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 2868b4f2b02e9..f8b7c76e6439d 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -99,8 +99,8 @@
#include <optional>
#include <set>
#include <utility>
-#if LLVM_ON_UNIX
-#include <unistd.h> // getpid
+#if HAVE_GETPID
+#include <unistd.h>
#endif
using namespace clang::driver;
@@ -1577,7 +1577,7 @@ bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
CrashDiagDir = "/";
path::append(CrashDiagDir, "Library/Logs/DiagnosticReports");
int PID =
-#if LLVM_ON_UNIX
+#if HAVE_GETPID
getpid();
#else
0;
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index bf1b110245bb2..a1a76bb6241db 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -49,6 +49,7 @@ check_include_file(malloc/malloc.h HAVE_MALLOC_MALLOC_H)
if( NOT PURE_WINDOWS )
check_include_file(pthread.h HAVE_PTHREAD_H)
endif()
+check_include_file(pwd.h HAVE_PWD_H)
check_include_file(signal.h HAVE_SIGNAL_H)
check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H)
check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
@@ -57,6 +58,7 @@ check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H)
check_include_file(sys/stat.h HAVE_SYS_STAT_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(sys/wait.h HAVE_SYS_WAIT_H)
check_include_file(sysexits.h HAVE_SYSEXITS_H)
check_include_file(termios.h HAVE_TERMIOS_H)
check_include_file(unistd.h HAVE_UNISTD_H)
@@ -276,11 +278,15 @@ check_symbol_exists(__deregister_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE
check_symbol_exists(__unw_add_dynamic_fde "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_UNW_ADD_DYNAMIC_FDE)
check_symbol_exists(_Unwind_Backtrace "unwind.h" HAVE__UNWIND_BACKTRACE)
+check_symbol_exists(alarm unistd.h HAVE_ALARM)
+check_symbol_exists(gethostname unistd.h HAVE_GETHOSTNAME)
check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE)
+check_symbol_exists(getpid unistd.h HAVE_GETPID)
check_symbol_exists(sysconf unistd.h HAVE_SYSCONF)
check_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
check_symbol_exists(setrlimit sys/resource.h HAVE_SETRLIMIT)
check_symbol_exists(isatty unistd.h HAVE_ISATTY)
+check_symbol_exists(fchown unistd.h HAVE_FCHOWN)
check_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS)
check_symbol_exists(futimes sys/time.h HAVE_FUTIMES)
# AddressSanitizer conflicts with lib/Support/Unix/Signals.inc
@@ -298,10 +304,14 @@ check_symbol_exists(malloc_zone_statistics malloc/malloc.h
check_symbol_exists(getrlimit "sys/types.h;sys/time.h;sys/resource.h" HAVE_GETRLIMIT)
check_symbol_exists(posix_spawn spawn.h HAVE_POSIX_SPAWN)
check_symbol_exists(pread unistd.h HAVE_PREAD)
+check_symbol_exists(raise signal.h HAVE_RAISE)
check_symbol_exists(sbrk unistd.h HAVE_SBRK)
+check_symbol_exists(setjmp setjmp.h HAVE_SETJMP)
+check_symbol_exists(socket sys/socket.h HAVE_SOCKET)
check_symbol_exists(strerror_r string.h HAVE_STRERROR_R)
check_symbol_exists(strerror_s string.h HAVE_DECL_STRERROR_S)
check_symbol_exists(setenv stdlib.h HAVE_SETENV)
+check_symbol_exists(umask sys/stat.h HAVE_UMASK)
if( PURE_WINDOWS )
check_symbol_exists(_chsize_s io.h HAVE__CHSIZE_S)
@@ -327,6 +337,11 @@ if( PURE_WINDOWS )
check_function_exists(__cmpdi2 HAVE___CMPDI2)
endif()
+check_c_source_compiles("
+ struct flock lk;
+ int main(void) { return 0; }"
+ HAVE_FLOCK)
+
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX")
diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake
index 977c182e9d2b0..8cbefffb2121d 100644
--- a/llvm/include/llvm/Config/config.h.cmake
+++ b/llvm/include/llvm/Config/config.h.cmake
@@ -23,6 +23,9 @@
backslashes. */
#cmakedefine01 LLVM_WINDOWS_PREFER_FORWARD_SLASH
+/* Define to 1 if you have the `alarm' function. */
+#cmakedefine HAVE_ALARM ${HAVE_ALARM}
+
/* Define to 1 if you have the `backtrace' function. */
#cmakedefine HAVE_BACKTRACE ${HAVE_BACKTRACE}
@@ -71,6 +74,12 @@
/* Define to 1 if you have the <errno.h> header file. */
#cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H}
+/* Define to 1 if you have the `flock' structure. */
+#cmakedefine HAVE_FLOCK ${HAVE_FLOCK}
+
+/* Define to 1 if you have the `fchown' function. */
+#cmakedefine HAVE_FCHOWN ${HAVE_FCHOWN}
+
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H}
@@ -92,9 +101,15 @@
/* Define to 1 if you have the `futimes' function. */
#cmakedefine HAVE_FUTIMES ${HAVE_FUTIMES}
+/* Define to 1 if you have the `gethostname' function. */
+#cmakedefine HAVE_GETHOSTNAME ${HAVE_GETHOSTNAME}
+
/* Define to 1 if you have the `getpagesize' function. */
#cmakedefine HAVE_GETPAGESIZE ${HAVE_GETPAGESIZE}
+/* Define to 1 if you have the `getpid' function. */
+#cmakedefine HAVE_GETPID ${HAVE_GETPID}
+
/* Define to 1 if you have the `getrlimit' function. */
#cmakedefine HAVE_GETRLIMIT ${HAVE_GETRLIMIT}
@@ -161,9 +176,21 @@
/* Have pthread_rwlock_init */
#cmakedefine HAVE_PTHREAD_RWLOCK_INIT ${HAVE_PTHREAD_RWLOCK_INIT}
+/* Define to 1 if you have the <pwd.h> header file. */
+#cmakedefine HAVE_PWD_H ${HAVE_PWD_H}
+
+/* Define to 1 if you have the `raise' function. */
+#cmakedefine HAVE_RAISE ${HAVE_RAISE}
+
/* Define to 1 if you have the `sbrk' function. */
#cmakedefine HAVE_SBRK ${HAVE_SBRK}
+/* Define to 1 if you have the `setjmp' function. */
+#cmakedefine HAVE_SETJMP ${HAVE_SETJMP}
+
+/* Define to 1 if you have the `socket' function. */
+#cmakedefine HAVE_SOCKET ${HAVE_SOCKET}
+
/* Define to 1 if you have the `setenv' function. */
#cmakedefine HAVE_SETENV ${HAVE_SETENV}
@@ -209,12 +236,18 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H}
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H}
+
/* Define if the setupterm() function is supported this platform. */
#cmakedefine LLVM_ENABLE_TERMINFO ${LLVM_ENABLE_TERMINFO}
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
+/* Define to 1 if you have the `umask' function. */
+#cmakedefine HAVE_UMASK ${HAVE_UMASK}
+
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
diff --git a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
index 4f8f883a75f32..345a80e70f241 100644
--- a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
+++ b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
@@ -34,7 +34,9 @@
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cmath>
+#if HAVE_RAISE
#include <csignal>
+#endif
#include <cstdint>
#include <cstdio>
#include <cstring>
@@ -340,7 +342,11 @@ static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) {
static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
//FIXME: should we report or raise here?
//report_fatal_error("Interpreted program raised SIGABRT");
+#if HAVE_RAISE
raise (SIGABRT);
+#else
+ abort();
+#endif
return GenericValue();
}
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index f53aea177d612..d25590d4ff3a6 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -13,8 +13,13 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/thread.h"
#include <cassert>
+#if HAVE_RAISE
+#include <csignal>
+#endif
#include <mutex>
+#if HAVE_SETJMP
#include <setjmp.h>
+#endif
using namespace llvm;
@@ -31,7 +36,9 @@ struct CrashRecoveryContextImpl {
const CrashRecoveryContextImpl *Next;
CrashRecoveryContext *CRC;
+#ifdef HAVE_SETJMP
::jmp_buf JumpBuffer;
+#endif
volatile unsigned Failed : 1;
unsigned SwitchedThread : 1;
unsigned ValidJumpBuffer : 1;
@@ -72,9 +79,11 @@ struct CrashRecoveryContextImpl {
CRC->RetCode = RetCode;
+#if HAVE_SETJMP
// Jump back to the RunSafely we were called under.
if (ValidJumpBuffer)
longjmp(JumpBuffer, 1);
+#endif
// Otherwise let the caller decide of the outcome of the crash. Currently
// this occurs when using SEH on Windows with MSVC or clang-cl.
@@ -417,10 +426,12 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
Impl = CRCI;
+#if HAVE_SETJMP
CRCI->ValidJumpBuffer = true;
if (setjmp(CRCI->JumpBuffer) != 0) {
return false;
}
+#endif
}
Fn();
@@ -469,9 +480,11 @@ bool CrashRecoveryContext::throwIfCrash(int RetCode) {
return false;
#if defined(_WIN32)
::RaiseException(RetCode, 0, 0, NULL);
-#else
+#elif HAVE_RAISE
llvm::sys::unregisterHandlers();
raise(RetCode - 128);
+#else
+ abort();
#endif
return true;
}
diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp
index 083f8d7b37be3..edfa8825b3337 100644
--- a/llvm/lib/Support/LockFileManager.cpp
+++ b/llvm/lib/Support/LockFileManager.cpp
@@ -94,7 +94,7 @@ static std::error_code getHostID(SmallVectorImpl<char> &HostID) {
StringRef UUIDRef(UUIDStr);
HostID.append(UUIDRef.begin(), UUIDRef.end());
-#elif LLVM_ON_UNIX
+#elif HAVE_GETHOSTNAME
char HostName[256];
HostName[255] = 0;
HostName[0] = 0;
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index 6e679f74869f0..250e946781446 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -32,7 +32,9 @@
#endif
#include <dirent.h>
+#ifdef HAVE_PWD_H
#include <pwd.h>
+#endif
#include <sys/file.h>
#ifdef __APPLE__
@@ -673,6 +675,11 @@ static void expandTildeExpr(SmallVectorImpl<char> &Path) {
return;
}
+#if !defined(HAVE_PWD_H)
+ // No access to password database, return back the original path.
+ (void)Remainder;
+ return;
+#else
// This is a string of the form ~username/, look up this user's entry in the
// password database.
std::unique_ptr<char[]> Buf;
@@ -694,6 +701,7 @@ static void expandTildeExpr(SmallVectorImpl<char> &Path) {
Path.clear();
Path.append(Entry->pw_dir, Entry->pw_dir + strlen(Entry->pw_dir));
llvm::sys::path::append(Path, Storage);
+#endif
}
void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) {
@@ -770,11 +778,15 @@ std::error_code status(int FD, file_status &Result) {
}
unsigned getUmask() {
+#if HAVE_UMASK
// Chose arbitary new mask and reset the umask to the old mask.
// umask(2) never fails so ignore the return of the second call.
unsigned Mask = ::umask(0);
(void)::umask(Mask);
return Mask;
+#else
+ return 0022;
+#endif
}
std::error_code setPermissions(const Twine &Path, perms Permissions) {
@@ -1224,6 +1236,7 @@ Expected<size_t> readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf,
}
std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout) {
+#if HAVE_FLOCK
auto Start = std::chrono::steady_clock::now();
auto End = Start + Timeout;
do {
@@ -1241,9 +1254,13 @@ std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout) {
usleep(1000);
} while (std::chrono::steady_clock::now() < End);
return make_error_code(errc::no_lock_available);
+#else
+ return std::error_code(ENOSYS, std::generic_category());
+#endif
}
std::error_code lockFile(int FD) {
+#if HAVE_FLOCK
struct flock Lock;
memset(&Lock, 0, sizeof(Lock));
Lock.l_type = F_WRLCK;
@@ -1253,9 +1270,13 @@ std::error_code lockFile(int FD) {
if (::fcntl(FD, F_SETLKW, &Lock) != -1)
return std::error_code();
return errnoAsErrorCode();
+#else
+ return std::error_code(ENOSYS, std::generic_category());
+#endif
}
std::error_code unlockFile(int FD) {
+#if HAVE_FLOCK
struct flock Lock;
Lock.l_type = F_UNLCK;
Lock.l_whence = SEEK_SET;
@@ -1264,6 +1285,9 @@ std::error_code unlockFile(int FD) {
if (::fcntl(FD, F_SETLK, &Lock) != -1)
return std::error_code();
return errnoAsErrorCode();
+#else
+ return std::error_code(ENOSYS, std::generic_category());
+#endif
}
std::error_code closeFile(file_t &F) {
@@ -1335,11 +1359,15 @@ std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
}
std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group) {
+#if HAVE_FCHOWN
auto FChown = [&]() { return ::fchown(FD, Owner, Group); };
// Retry if fchown call fails due to interruption.
if ((sys::RetryAfterSignal(-1, FChown)) < 0)
return errnoAsErrorCode();
return std::error_code();
+#else
+ return std::error_code(ENOSYS, std::generic_category());
+#endif
}
} // end namespace fs
@@ -1349,6 +1377,7 @@ namespace path {
bool home_directory(SmallVectorImpl<char> &result) {
std::unique_ptr<char[]> Buf;
char *RequestedDir = getenv("HOME");
+#if HAVE_PWD_H
if (!RequestedDir) {
long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (BufSize <= 0)
@@ -1360,6 +1389,7 @@ bool home_directory(SmallVectorImpl<char> &result) {
if (pw && pw->pw_dir)
RequestedDir = pw->pw_dir;
}
+#endif
if (!RequestedDir)
return false;
diff --git a/llvm/lib/Support/Unix/Process.inc b/llvm/lib/Support/Unix/Process.inc
index ae90924cae1b9..02f984820590a 100644
--- a/llvm/lib/Support/Unix/Process.inc
+++ b/llvm/lib/Support/Unix/Process.inc
@@ -72,7 +72,11 @@ getRUsageTimes() {
Process::Pid Process::getProcessId() {
static_assert(sizeof(Pid) >= sizeof(pid_t),
"Process::Pid should be big enough to store pid_t");
+#if HAVE_GETPID
return Pid(::getpid());
+#else
+ return Pid(0);
+#endif
}
// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
diff --git a/llvm/lib/Support/Unix/Unix.h b/llvm/lib/Support/Unix/Unix.h
index 1599241a344af..b6988b34832b3 100644
--- a/llvm/lib/Support/Unix/Unix.h
+++ b/llvm/lib/Support/Unix/Unix.h
@@ -30,7 +30,10 @@
#include <cstring>
#include <string>
#include <sys/types.h>
-#include <sys/wait.h>
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
diff --git a/llvm/lib/Support/Unix/Watchdog.inc b/llvm/lib/Support/Unix/Watchdog.inc
index b33e52d88500d..dd65028769d37 100644
--- a/llvm/lib/Support/Unix/Watchdog.inc
+++ b/llvm/lib/Support/Unix/Watchdog.inc
@@ -19,13 +19,13 @@
namespace llvm {
namespace sys {
Watchdog::Watchdog(unsigned int seconds) {
-#ifdef HAVE_UNISTD_H
+#ifdef HAVE_ALARM
alarm(seconds);
#endif
}
Watchdog::~Watchdog() {
-#ifdef HAVE_UNISTD_H
+#ifdef HAVE_ALARM
alarm(0);
#endif
}
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 14e2308df4d7e..ae3fba3593d8e 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -41,6 +41,8 @@
using namespace llvm;
+#if defined(_WIN32) || HAVE_SOCKET
+
#ifdef _WIN32
WSABalancer::WSABalancer() {
WSADATA WsaData;
@@ -304,3 +306,5 @@ raw_socket_stream::createConnectedUnix(StringRef SocketPath) {
}
raw_socket_stream::~raw_socket_stream() {}
+
+#endif
|
@llvm/pr-subscribers-clang Author: Catherine (whitequark) ChangesThis patch is the first in a series that makes it possible to build LLVM, Clang, and LLD for WASI/WebAssembly. This patch does not introduce conditionals of the form The complete list of feature tests introduced is:
Full diff: https://github.com/llvm/llvm-project/pull/92677.diff 11 Files Affected:
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 2868b4f2b02e9..f8b7c76e6439d 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -99,8 +99,8 @@
#include <optional>
#include <set>
#include <utility>
-#if LLVM_ON_UNIX
-#include <unistd.h> // getpid
+#if HAVE_GETPID
+#include <unistd.h>
#endif
using namespace clang::driver;
@@ -1577,7 +1577,7 @@ bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
CrashDiagDir = "/";
path::append(CrashDiagDir, "Library/Logs/DiagnosticReports");
int PID =
-#if LLVM_ON_UNIX
+#if HAVE_GETPID
getpid();
#else
0;
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index bf1b110245bb2..a1a76bb6241db 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -49,6 +49,7 @@ check_include_file(malloc/malloc.h HAVE_MALLOC_MALLOC_H)
if( NOT PURE_WINDOWS )
check_include_file(pthread.h HAVE_PTHREAD_H)
endif()
+check_include_file(pwd.h HAVE_PWD_H)
check_include_file(signal.h HAVE_SIGNAL_H)
check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H)
check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
@@ -57,6 +58,7 @@ check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H)
check_include_file(sys/stat.h HAVE_SYS_STAT_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(sys/wait.h HAVE_SYS_WAIT_H)
check_include_file(sysexits.h HAVE_SYSEXITS_H)
check_include_file(termios.h HAVE_TERMIOS_H)
check_include_file(unistd.h HAVE_UNISTD_H)
@@ -276,11 +278,15 @@ check_symbol_exists(__deregister_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE
check_symbol_exists(__unw_add_dynamic_fde "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_UNW_ADD_DYNAMIC_FDE)
check_symbol_exists(_Unwind_Backtrace "unwind.h" HAVE__UNWIND_BACKTRACE)
+check_symbol_exists(alarm unistd.h HAVE_ALARM)
+check_symbol_exists(gethostname unistd.h HAVE_GETHOSTNAME)
check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE)
+check_symbol_exists(getpid unistd.h HAVE_GETPID)
check_symbol_exists(sysconf unistd.h HAVE_SYSCONF)
check_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
check_symbol_exists(setrlimit sys/resource.h HAVE_SETRLIMIT)
check_symbol_exists(isatty unistd.h HAVE_ISATTY)
+check_symbol_exists(fchown unistd.h HAVE_FCHOWN)
check_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS)
check_symbol_exists(futimes sys/time.h HAVE_FUTIMES)
# AddressSanitizer conflicts with lib/Support/Unix/Signals.inc
@@ -298,10 +304,14 @@ check_symbol_exists(malloc_zone_statistics malloc/malloc.h
check_symbol_exists(getrlimit "sys/types.h;sys/time.h;sys/resource.h" HAVE_GETRLIMIT)
check_symbol_exists(posix_spawn spawn.h HAVE_POSIX_SPAWN)
check_symbol_exists(pread unistd.h HAVE_PREAD)
+check_symbol_exists(raise signal.h HAVE_RAISE)
check_symbol_exists(sbrk unistd.h HAVE_SBRK)
+check_symbol_exists(setjmp setjmp.h HAVE_SETJMP)
+check_symbol_exists(socket sys/socket.h HAVE_SOCKET)
check_symbol_exists(strerror_r string.h HAVE_STRERROR_R)
check_symbol_exists(strerror_s string.h HAVE_DECL_STRERROR_S)
check_symbol_exists(setenv stdlib.h HAVE_SETENV)
+check_symbol_exists(umask sys/stat.h HAVE_UMASK)
if( PURE_WINDOWS )
check_symbol_exists(_chsize_s io.h HAVE__CHSIZE_S)
@@ -327,6 +337,11 @@ if( PURE_WINDOWS )
check_function_exists(__cmpdi2 HAVE___CMPDI2)
endif()
+check_c_source_compiles("
+ struct flock lk;
+ int main(void) { return 0; }"
+ HAVE_FLOCK)
+
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX")
diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake
index 977c182e9d2b0..8cbefffb2121d 100644
--- a/llvm/include/llvm/Config/config.h.cmake
+++ b/llvm/include/llvm/Config/config.h.cmake
@@ -23,6 +23,9 @@
backslashes. */
#cmakedefine01 LLVM_WINDOWS_PREFER_FORWARD_SLASH
+/* Define to 1 if you have the `alarm' function. */
+#cmakedefine HAVE_ALARM ${HAVE_ALARM}
+
/* Define to 1 if you have the `backtrace' function. */
#cmakedefine HAVE_BACKTRACE ${HAVE_BACKTRACE}
@@ -71,6 +74,12 @@
/* Define to 1 if you have the <errno.h> header file. */
#cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H}
+/* Define to 1 if you have the `flock' structure. */
+#cmakedefine HAVE_FLOCK ${HAVE_FLOCK}
+
+/* Define to 1 if you have the `fchown' function. */
+#cmakedefine HAVE_FCHOWN ${HAVE_FCHOWN}
+
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H}
@@ -92,9 +101,15 @@
/* Define to 1 if you have the `futimes' function. */
#cmakedefine HAVE_FUTIMES ${HAVE_FUTIMES}
+/* Define to 1 if you have the `gethostname' function. */
+#cmakedefine HAVE_GETHOSTNAME ${HAVE_GETHOSTNAME}
+
/* Define to 1 if you have the `getpagesize' function. */
#cmakedefine HAVE_GETPAGESIZE ${HAVE_GETPAGESIZE}
+/* Define to 1 if you have the `getpid' function. */
+#cmakedefine HAVE_GETPID ${HAVE_GETPID}
+
/* Define to 1 if you have the `getrlimit' function. */
#cmakedefine HAVE_GETRLIMIT ${HAVE_GETRLIMIT}
@@ -161,9 +176,21 @@
/* Have pthread_rwlock_init */
#cmakedefine HAVE_PTHREAD_RWLOCK_INIT ${HAVE_PTHREAD_RWLOCK_INIT}
+/* Define to 1 if you have the <pwd.h> header file. */
+#cmakedefine HAVE_PWD_H ${HAVE_PWD_H}
+
+/* Define to 1 if you have the `raise' function. */
+#cmakedefine HAVE_RAISE ${HAVE_RAISE}
+
/* Define to 1 if you have the `sbrk' function. */
#cmakedefine HAVE_SBRK ${HAVE_SBRK}
+/* Define to 1 if you have the `setjmp' function. */
+#cmakedefine HAVE_SETJMP ${HAVE_SETJMP}
+
+/* Define to 1 if you have the `socket' function. */
+#cmakedefine HAVE_SOCKET ${HAVE_SOCKET}
+
/* Define to 1 if you have the `setenv' function. */
#cmakedefine HAVE_SETENV ${HAVE_SETENV}
@@ -209,12 +236,18 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H}
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H}
+
/* Define if the setupterm() function is supported this platform. */
#cmakedefine LLVM_ENABLE_TERMINFO ${LLVM_ENABLE_TERMINFO}
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
+/* Define to 1 if you have the `umask' function. */
+#cmakedefine HAVE_UMASK ${HAVE_UMASK}
+
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
diff --git a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
index 4f8f883a75f32..345a80e70f241 100644
--- a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
+++ b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
@@ -34,7 +34,9 @@
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cmath>
+#if HAVE_RAISE
#include <csignal>
+#endif
#include <cstdint>
#include <cstdio>
#include <cstring>
@@ -340,7 +342,11 @@ static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) {
static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
//FIXME: should we report or raise here?
//report_fatal_error("Interpreted program raised SIGABRT");
+#if HAVE_RAISE
raise (SIGABRT);
+#else
+ abort();
+#endif
return GenericValue();
}
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index f53aea177d612..d25590d4ff3a6 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -13,8 +13,13 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/thread.h"
#include <cassert>
+#if HAVE_RAISE
+#include <csignal>
+#endif
#include <mutex>
+#if HAVE_SETJMP
#include <setjmp.h>
+#endif
using namespace llvm;
@@ -31,7 +36,9 @@ struct CrashRecoveryContextImpl {
const CrashRecoveryContextImpl *Next;
CrashRecoveryContext *CRC;
+#ifdef HAVE_SETJMP
::jmp_buf JumpBuffer;
+#endif
volatile unsigned Failed : 1;
unsigned SwitchedThread : 1;
unsigned ValidJumpBuffer : 1;
@@ -72,9 +79,11 @@ struct CrashRecoveryContextImpl {
CRC->RetCode = RetCode;
+#if HAVE_SETJMP
// Jump back to the RunSafely we were called under.
if (ValidJumpBuffer)
longjmp(JumpBuffer, 1);
+#endif
// Otherwise let the caller decide of the outcome of the crash. Currently
// this occurs when using SEH on Windows with MSVC or clang-cl.
@@ -417,10 +426,12 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
Impl = CRCI;
+#if HAVE_SETJMP
CRCI->ValidJumpBuffer = true;
if (setjmp(CRCI->JumpBuffer) != 0) {
return false;
}
+#endif
}
Fn();
@@ -469,9 +480,11 @@ bool CrashRecoveryContext::throwIfCrash(int RetCode) {
return false;
#if defined(_WIN32)
::RaiseException(RetCode, 0, 0, NULL);
-#else
+#elif HAVE_RAISE
llvm::sys::unregisterHandlers();
raise(RetCode - 128);
+#else
+ abort();
#endif
return true;
}
diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp
index 083f8d7b37be3..edfa8825b3337 100644
--- a/llvm/lib/Support/LockFileManager.cpp
+++ b/llvm/lib/Support/LockFileManager.cpp
@@ -94,7 +94,7 @@ static std::error_code getHostID(SmallVectorImpl<char> &HostID) {
StringRef UUIDRef(UUIDStr);
HostID.append(UUIDRef.begin(), UUIDRef.end());
-#elif LLVM_ON_UNIX
+#elif HAVE_GETHOSTNAME
char HostName[256];
HostName[255] = 0;
HostName[0] = 0;
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index 6e679f74869f0..250e946781446 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -32,7 +32,9 @@
#endif
#include <dirent.h>
+#ifdef HAVE_PWD_H
#include <pwd.h>
+#endif
#include <sys/file.h>
#ifdef __APPLE__
@@ -673,6 +675,11 @@ static void expandTildeExpr(SmallVectorImpl<char> &Path) {
return;
}
+#if !defined(HAVE_PWD_H)
+ // No access to password database, return back the original path.
+ (void)Remainder;
+ return;
+#else
// This is a string of the form ~username/, look up this user's entry in the
// password database.
std::unique_ptr<char[]> Buf;
@@ -694,6 +701,7 @@ static void expandTildeExpr(SmallVectorImpl<char> &Path) {
Path.clear();
Path.append(Entry->pw_dir, Entry->pw_dir + strlen(Entry->pw_dir));
llvm::sys::path::append(Path, Storage);
+#endif
}
void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) {
@@ -770,11 +778,15 @@ std::error_code status(int FD, file_status &Result) {
}
unsigned getUmask() {
+#if HAVE_UMASK
// Chose arbitary new mask and reset the umask to the old mask.
// umask(2) never fails so ignore the return of the second call.
unsigned Mask = ::umask(0);
(void)::umask(Mask);
return Mask;
+#else
+ return 0022;
+#endif
}
std::error_code setPermissions(const Twine &Path, perms Permissions) {
@@ -1224,6 +1236,7 @@ Expected<size_t> readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf,
}
std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout) {
+#if HAVE_FLOCK
auto Start = std::chrono::steady_clock::now();
auto End = Start + Timeout;
do {
@@ -1241,9 +1254,13 @@ std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout) {
usleep(1000);
} while (std::chrono::steady_clock::now() < End);
return make_error_code(errc::no_lock_available);
+#else
+ return std::error_code(ENOSYS, std::generic_category());
+#endif
}
std::error_code lockFile(int FD) {
+#if HAVE_FLOCK
struct flock Lock;
memset(&Lock, 0, sizeof(Lock));
Lock.l_type = F_WRLCK;
@@ -1253,9 +1270,13 @@ std::error_code lockFile(int FD) {
if (::fcntl(FD, F_SETLKW, &Lock) != -1)
return std::error_code();
return errnoAsErrorCode();
+#else
+ return std::error_code(ENOSYS, std::generic_category());
+#endif
}
std::error_code unlockFile(int FD) {
+#if HAVE_FLOCK
struct flock Lock;
Lock.l_type = F_UNLCK;
Lock.l_whence = SEEK_SET;
@@ -1264,6 +1285,9 @@ std::error_code unlockFile(int FD) {
if (::fcntl(FD, F_SETLK, &Lock) != -1)
return std::error_code();
return errnoAsErrorCode();
+#else
+ return std::error_code(ENOSYS, std::generic_category());
+#endif
}
std::error_code closeFile(file_t &F) {
@@ -1335,11 +1359,15 @@ std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
}
std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group) {
+#if HAVE_FCHOWN
auto FChown = [&]() { return ::fchown(FD, Owner, Group); };
// Retry if fchown call fails due to interruption.
if ((sys::RetryAfterSignal(-1, FChown)) < 0)
return errnoAsErrorCode();
return std::error_code();
+#else
+ return std::error_code(ENOSYS, std::generic_category());
+#endif
}
} // end namespace fs
@@ -1349,6 +1377,7 @@ namespace path {
bool home_directory(SmallVectorImpl<char> &result) {
std::unique_ptr<char[]> Buf;
char *RequestedDir = getenv("HOME");
+#if HAVE_PWD_H
if (!RequestedDir) {
long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (BufSize <= 0)
@@ -1360,6 +1389,7 @@ bool home_directory(SmallVectorImpl<char> &result) {
if (pw && pw->pw_dir)
RequestedDir = pw->pw_dir;
}
+#endif
if (!RequestedDir)
return false;
diff --git a/llvm/lib/Support/Unix/Process.inc b/llvm/lib/Support/Unix/Process.inc
index ae90924cae1b9..02f984820590a 100644
--- a/llvm/lib/Support/Unix/Process.inc
+++ b/llvm/lib/Support/Unix/Process.inc
@@ -72,7 +72,11 @@ getRUsageTimes() {
Process::Pid Process::getProcessId() {
static_assert(sizeof(Pid) >= sizeof(pid_t),
"Process::Pid should be big enough to store pid_t");
+#if HAVE_GETPID
return Pid(::getpid());
+#else
+ return Pid(0);
+#endif
}
// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
diff --git a/llvm/lib/Support/Unix/Unix.h b/llvm/lib/Support/Unix/Unix.h
index 1599241a344af..b6988b34832b3 100644
--- a/llvm/lib/Support/Unix/Unix.h
+++ b/llvm/lib/Support/Unix/Unix.h
@@ -30,7 +30,10 @@
#include <cstring>
#include <string>
#include <sys/types.h>
-#include <sys/wait.h>
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
diff --git a/llvm/lib/Support/Unix/Watchdog.inc b/llvm/lib/Support/Unix/Watchdog.inc
index b33e52d88500d..dd65028769d37 100644
--- a/llvm/lib/Support/Unix/Watchdog.inc
+++ b/llvm/lib/Support/Unix/Watchdog.inc
@@ -19,13 +19,13 @@
namespace llvm {
namespace sys {
Watchdog::Watchdog(unsigned int seconds) {
-#ifdef HAVE_UNISTD_H
+#ifdef HAVE_ALARM
alarm(seconds);
#endif
}
Watchdog::~Watchdog() {
-#ifdef HAVE_UNISTD_H
+#ifdef HAVE_ALARM
alarm(0);
#endif
}
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 14e2308df4d7e..ae3fba3593d8e 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -41,6 +41,8 @@
using namespace llvm;
+#if defined(_WIN32) || HAVE_SOCKET
+
#ifdef _WIN32
WSABalancer::WSABalancer() {
WSADATA WsaData;
@@ -304,3 +306,5 @@ raw_socket_stream::createConnectedUnix(StringRef SocketPath) {
}
raw_socket_stream::~raw_socket_stream() {}
+
+#endif
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
This patch is the first in a series that makes it possible to build LLVM, Clang, and LLD for WASI/WebAssembly. This patch does not introduce conditionals of the form `defined(__wasi__)` or `defined(__wasm__)`; instead it detects these APIs like any other platform features. While some features are never present in WASI and the feature check is functionally identical to a platform check, some may be conditionally present if emulation is turned on, e.g. `getpid`. The complete list of feature tests introduced is: * `HAVE_ALARM`: WebAssembly does not support delivery of asynchronous signals. * `HAVE_GETHOSTNAME`: WASI does not provide `gethostname`. * `HAVE_GETPID`: WASI does not have process IDs. However, it ships with a polyfill (`-D_WASI_EMULATED_GETPID`). The final behavior is the same either way. * `HAVE_FCHOWN`: WASI likely will never support UNIX ownership model. * `HAVE_FLOCK`: WASI likely will never support POSIX advisory locking. * `HAVE_PWD_H`: WASI likely will never support UNIX password databases. * `HAVE_RAISE`: WASI does not support delivery of asynchronous signals. However, it ships with a polyfill (`-D_WASI_EMULATED_SIGNAL`). This polyfill implements `raise` but not `sigaction` (only `signal`) and as a result it is not currently useful for LLVM. If `sigaction` is implemented in wasi-libc then `raise(SIGABRT);` would be able to invoke the handler. * `HAVE_SETJMP`: WebAssembly implements SjLj using exception handling. Exception handling has not been stabilized in Wasm yet. In addition, it significantly increases deployment complexity. Building with `-mllvm -wasm-enable-sjlj` enables the use of SjLj. * `HAVE_SOCKET`: WASIp1 does not provide the Berkeley socket API. WASIp2 does provide it. It will likely remain desirable to target WASIp1 for a long time. * `HAVE_SYS_WAIT_H`: WASI does not have subprocess management. * `HAVE_UMASK`: WASI likely will never support UNIX permission model, but `umask` might eventually be added in a polyfill. Of these, only `HAVE_FLOCK` requires a custom compile test: #include <sys/file.h> struct flock lk; int main(void) { return 0; }
I can see the build failure--I think it's related to the changes to crash reporting, but I'm not sure how yet. I'll fix it but I'd still very much like the feedback on the general approach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not responding sooner, but I think this approach makes sense to me. It's basically similar to autoconf where we're checking whether a feature is supported and guarding against it.
One concern I have is that someone adding new code may think they need to come up with fallback behavior in case a feature isn't available (e.g., "how do I do this if I don't have setjmp
?) and it would be nice if we could find a way to make it clear that they are not responsible for coming up with that fallback behavior. (Mostly worried about folks doing a bunch of heavy lifting before submitting a PR only to hear during review "you didn't need to do that, please pull it out because we don't have a way to test it".)
Shall I add some comments to config.h indicating as such? |
Comments in the config file isn't a harmful thing, but I'm also worried about folks who never see the config file. e.g., they're working in Path.inc on something, see So perhaps a two-pronged approach: a comment in config.h for the cases where we don't expect a graceful fallback, and a similar comment around the guarded #include in source for the folks who won't look in config.h? |
I could do that. What do you think of the fairly strongly worded objection in the RFC thread that requested I use |
Ah thank you for pointing that out, I had missed some updates on that thread. I think |
|
See also the RFC.
This patch is the first in a series that makes it possible to build LLVM, Clang, and LLD for WASI/WebAssembly. This patch does not introduce conditionals of the form
defined(__wasi__)
ordefined(__wasm__)
; instead it detects these APIs like any other platform features. While some features are never present in WASI and the feature check is functionally identical to a platform check, some may be conditionally present if emulation is turned on, e.g.getpid
.The complete list of feature tests introduced is:
HAVE_ALARM
: WebAssembly does not support delivery of asynchronous signals.HAVE_GETHOSTNAME
: WASI does not providegethostname
.HAVE_GETPID
: WASI does not have process IDs. However, it ships with a polyfill (-D_WASI_EMULATED_GETPID
). The final behavior is the same either way.HAVE_FCHOWN
: WASI likely will never support UNIX ownership model.HAVE_FLOCK
: WASI likely will never support POSIX advisory locking.HAVE_PWD_H
: WASI likely will never support UNIX password databases.HAVE_RAISE
: WASI does not support delivery of asynchronous signals. However, it ships with a polyfill (-D_WASI_EMULATED_SIGNAL
). This polyfill implementsraise
but notsigaction
(onlysignal
) and as a result it is not currently useful for LLVM. Ifsigaction
is implemented in wasi-libc thenraise(SIGABRT);
would be able to invoke the handler.HAVE_SETJMP
: WebAssembly implements SjLj using exception handling. Exception handling has not been stabilized in Wasm yet. In addition, it significantly increases deployment complexity. Building with-mllvm -wasm-enable-sjlj
enables the use of SjLj.HAVE_SOCKET
: WASIp1 does not provide the Berkeley socket API. WASIp2 does provide it. It will likely remain desirable to target WASIp1 for a long time.HAVE_SYS_WAIT_H
: WASI does not have subprocess management.HAVE_UMASK
: WASI likely will never support UNIX permission model, butumask
might eventually be added in a polyfill.Of these, only
HAVE_FLOCK
requires a custom compile test: