Skip to content

Commit 69bd854

Browse files
committed
Conditionalize use of POSIX features missing on WASI/WebAssembly.
This patch makes it possible to build LLVM, Clang, and LLD for WASI/WebAssembly. This patch introduces conditionals of the form `defined(__wasi__)` or `defined(__wasm__)` wherever necessary to detect the use of the WASI platform. In addition, it introduces a `HAVE_SETJMP` feature test macro because the WASI platform can have or lack support for this feature depending on compiler options.
1 parent 3b7a7f4 commit 69bd854

18 files changed

+159
-22
lines changed

clang/lib/Driver/Driver.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1578,7 +1578,7 @@ bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
15781578
CrashDiagDir = "/";
15791579
path::append(CrashDiagDir, "Library/Logs/DiagnosticReports");
15801580
int PID =
1581-
#if LLVM_ON_UNIX
1581+
#if LLVM_ON_UNIX && !defined(__wasi__)
15821582
getpid();
15831583
#else
15841584
0;

lld/Common/Filesystem.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ void lld::unlinkAsync(StringRef path) {
4545
if (!sys::fs::exists(path) || !sys::fs::is_regular_file(path))
4646
return;
4747

48+
// If threads are disabled, remove the file synchronously.
49+
#if !LLVM_ENABLE_THREADS
50+
sys::fs::remove(path);
4851
// Removing a file is async on windows.
49-
#if defined(_WIN32)
52+
#elif defined(_WIN32)
5053
// On Windows co-operative programs can be expected to open LLD's
5154
// output in FILE_SHARE_DELETE mode. This allows us to delete the
5255
// file (by moving it to a temporary filename and then deleting

llvm/cmake/config-ix.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ check_symbol_exists(getrlimit "sys/types.h;sys/time.h;sys/resource.h" HAVE_GETRL
300300
check_symbol_exists(posix_spawn spawn.h HAVE_POSIX_SPAWN)
301301
check_symbol_exists(pread unistd.h HAVE_PREAD)
302302
check_symbol_exists(sbrk unistd.h HAVE_SBRK)
303+
check_symbol_exists(setjmp setjmp.h HAVE_SETJMP)
303304
check_symbol_exists(strerror_r string.h HAVE_STRERROR_R)
304305
check_symbol_exists(strerror_s string.h HAVE_DECL_STRERROR_S)
305306
check_symbol_exists(setenv stdlib.h HAVE_SETENV)

llvm/cmake/modules/HandleLLVMOptions.cmake

+4
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ elseif(FUCHSIA OR UNIX)
217217
else()
218218
set(LLVM_HAVE_LINK_VERSION_SCRIPT 1)
219219
endif()
220+
elseif(WASI)
221+
set(LLVM_ON_WIN32 0)
222+
set(LLVM_ON_UNIX 1)
223+
set(LLVM_HAVE_LINK_VERSION_SCRIPT 0)
220224
elseif(CMAKE_SYSTEM_NAME STREQUAL "Generic")
221225
set(LLVM_ON_WIN32 0)
222226
set(LLVM_ON_UNIX 0)

llvm/include/llvm/ADT/bit.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
3131
defined(__Fuchsia__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || \
32-
defined(__OpenBSD__) || defined(__DragonFly__)
32+
defined(__OpenBSD__) || defined(__DragonFly__) || defined(__wasm__)
3333
#include <endian.h>
3434
#elif defined(_AIX)
3535
#include <sys/machine.h>

llvm/include/llvm/Config/config.h.cmake

+4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@
164164
/* Define to 1 if you have the `sbrk' function. */
165165
#cmakedefine HAVE_SBRK ${HAVE_SBRK}
166166

167+
/* Define to 1 if you have the `setjmp' function. */
168+
/* This function is expected to be present everywhere except for a subset of WebAssembly builds. */
169+
#cmakedefine HAVE_SETJMP ${HAVE_SETJMP}
170+
167171
/* Define to 1 if you have the `setenv' function. */
168172
#cmakedefine HAVE_SETENV ${HAVE_SETENV}
169173

llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
#include "llvm/Support/raw_ostream.h"
3535
#include <cassert>
3636
#include <cmath>
37+
#if !defined(__wasi__)
3738
#include <csignal>
39+
#endif
3840
#include <cstdint>
3941
#include <cstdio>
4042
#include <cstring>
@@ -340,7 +342,11 @@ static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) {
340342
static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
341343
//FIXME: should we report or raise here?
342344
//report_fatal_error("Interpreted program raised SIGABRT");
345+
#if defined(__wasi__)
346+
abort();
347+
#else
343348
raise (SIGABRT);
349+
#endif
344350
return GenericValue();
345351
}
346352

llvm/lib/Support/CrashRecoveryContext.cpp

+36-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,17 @@
1313
#include "llvm/Support/Signals.h"
1414
#include "llvm/Support/thread.h"
1515
#include <cassert>
16+
#if !defined(__wasi__)
17+
#include <csignal>
18+
#endif
19+
#if LLVM_ENABLE_THREADS
1620
#include <mutex>
21+
#endif
22+
#if HAVE_SETJMP
23+
// We can rely on setjmp to exist everywhere except for a subset of WebAssembly
24+
// builds.
1725
#include <setjmp.h>
26+
#endif
1827

1928
using namespace llvm;
2029

@@ -31,7 +40,9 @@ struct CrashRecoveryContextImpl {
3140
const CrashRecoveryContextImpl *Next;
3241

3342
CrashRecoveryContext *CRC;
43+
#ifdef HAVE_SETJMP
3444
::jmp_buf JumpBuffer;
45+
#endif
3546
volatile unsigned Failed : 1;
3647
unsigned SwitchedThread : 1;
3748
unsigned ValidJumpBuffer : 1;
@@ -50,7 +61,7 @@ struct CrashRecoveryContextImpl {
5061
/// Called when the separate crash-recovery thread was finished, to
5162
/// indicate that we don't need to clear the thread-local CurrentContext.
5263
void setSwitchedThread() {
53-
#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
64+
#if LLVM_ENABLE_THREADS
5465
SwitchedThread = true;
5566
#endif
5667
}
@@ -72,19 +83,23 @@ struct CrashRecoveryContextImpl {
7283

7384
CRC->RetCode = RetCode;
7485

86+
#if HAVE_SETJMP
7587
// Jump back to the RunSafely we were called under.
7688
if (ValidJumpBuffer)
7789
longjmp(JumpBuffer, 1);
90+
#endif
7891

7992
// Otherwise let the caller decide of the outcome of the crash. Currently
8093
// this occurs when using SEH on Windows with MSVC or clang-cl.
8194
}
8295
};
8396

84-
std::mutex &getCrashRecoveryContextMutex() {
97+
#if LLVM_ENABLE_THREADS
98+
static std::mutex &getCrashRecoveryContextMutex() {
8599
static std::mutex CrashRecoveryContextMutex;
86100
return CrashRecoveryContextMutex;
87101
}
102+
#endif
88103

89104
static bool gCrashRecoveryEnabled = false;
90105

@@ -138,7 +153,9 @@ CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
138153
}
139154

140155
void CrashRecoveryContext::Enable() {
156+
#if LLVM_ENABLE_THREADS
141157
std::lock_guard<std::mutex> L(getCrashRecoveryContextMutex());
158+
#endif
142159
// FIXME: Shouldn't this be a refcount or something?
143160
if (gCrashRecoveryEnabled)
144161
return;
@@ -147,7 +164,9 @@ void CrashRecoveryContext::Enable() {
147164
}
148165

149166
void CrashRecoveryContext::Disable() {
167+
#if LLVM_ENABLE_THREADS
150168
std::lock_guard<std::mutex> L(getCrashRecoveryContextMutex());
169+
#endif
151170
if (!gCrashRecoveryEnabled)
152171
return;
153172
gCrashRecoveryEnabled = false;
@@ -329,7 +348,16 @@ static void uninstallExceptionOrSignalHandlers() {
329348
}
330349
}
331350

332-
#else // !_WIN32
351+
#elif defined(__wasi__)
352+
353+
// WASI implementation.
354+
//
355+
// WASI traps are always fatal, and recovery is not possible. Do nothing.
356+
357+
static void installExceptionOrSignalHandlers() {}
358+
static void uninstallExceptionOrSignalHandlers() {}
359+
360+
#else // !_WIN32 && !__wasi__
333361

334362
// Generic POSIX implementation.
335363
//
@@ -417,10 +445,12 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
417445
CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
418446
Impl = CRCI;
419447

448+
#if HAVE_SETJMP
420449
CRCI->ValidJumpBuffer = true;
421450
if (setjmp(CRCI->JumpBuffer) != 0) {
422451
return false;
423452
}
453+
#endif
424454
}
425455

426456
Fn();
@@ -467,7 +497,9 @@ bool CrashRecoveryContext::isCrash(int RetCode) {
467497
bool CrashRecoveryContext::throwIfCrash(int RetCode) {
468498
if (!isCrash(RetCode))
469499
return false;
470-
#if defined(_WIN32)
500+
#if defined(__wasi__)
501+
abort();
502+
#elif defined(_WIN32)
471503
::RaiseException(RetCode, 0, 0, NULL);
472504
#else
473505
llvm::sys::unregisterHandlers();

llvm/lib/Support/InitLLVM.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
4747
// Bring stdin/stdout/stderr into a known state.
4848
sys::AddSignalHandler(CleanupStdHandles, nullptr);
4949
#endif
50+
#if !defined(__wasi__)
5051
if (InstallPipeSignalExitHandler)
5152
// The pipe signal handler must be installed before any other handlers are
5253
// registered. This is because the Unix \ref RegisterHandlers function does
@@ -59,6 +60,7 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
5960
StackPrinter.emplace(Argc, Argv);
6061
sys::PrintStackTraceOnErrorSignal(Argv[0]);
6162
install_out_of_memory_new_handler();
63+
#endif
6264

6365
#ifdef __MVS__
6466

llvm/lib/Support/LockFileManager.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ static std::error_code getHostID(SmallVectorImpl<char> &HostID) {
9494
StringRef UUIDRef(UUIDStr);
9595
HostID.append(UUIDRef.begin(), UUIDRef.end());
9696

97-
#elif LLVM_ON_UNIX
97+
#elif !defined(__wasi__)
9898
char HostName[256];
9999
HostName[255] = 0;
100100
HostName[0] = 0;
@@ -111,7 +111,7 @@ static std::error_code getHostID(SmallVectorImpl<char> &HostID) {
111111
}
112112

113113
bool LockFileManager::processStillExecuting(StringRef HostID, int PID) {
114-
#if LLVM_ON_UNIX && !defined(__ANDROID__)
114+
#if LLVM_ON_UNIX && !defined(__ANDROID__) && !defined(__wasi__)
115115
SmallString<256> StoredHostID;
116116
if (getHostID(StoredHostID))
117117
return true; // Conservatively assume it's executing on error.

llvm/lib/Support/Signals.cpp

+13-3
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,19 @@ static bool printMarkupStackTrace(StringRef Argv0, void **StackTrace, int Depth,
273273
}
274274

275275
// Include the platform-specific parts of this class.
276-
#ifdef LLVM_ON_UNIX
276+
#if defined(__wasi__)
277+
// WASI does not have signals.
278+
void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
279+
void *Cookie) {}
280+
void llvm::sys::RunInterruptHandlers() {}
281+
void sys::CleanupOnSignal(uintptr_t Context) {}
282+
bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg) {
283+
return false;
284+
}
285+
void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) {}
286+
void llvm::sys::DisableSystemDialogsOnCrash() {}
287+
#elif defined(LLVM_ON_UNIX)
277288
#include "Unix/Signals.inc"
278-
#endif
279-
#ifdef _WIN32
289+
#elif defined(_WIN32)
280290
#include "Windows/Signals.inc"
281291
#endif

llvm/lib/Support/Unix/Memory.inc

+5
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ std::error_code Memory::releaseMappedMemory(MemoryBlock &M) {
163163

164164
std::error_code Memory::protectMappedMemory(const MemoryBlock &M,
165165
unsigned Flags) {
166+
#if defined(__wasi__)
167+
// Wasm does not allow making memory read-only or executable.
168+
return std::error_code(ENOSYS, std::generic_category());
169+
#endif
170+
166171
static const Align PageSize = Align(Process::getPageSizeEstimate());
167172
if (M.Address == nullptr || M.AllocatedSize == 0)
168173
return std::error_code();

0 commit comments

Comments
 (0)