diff options
author | Morten Johan Sørvig <morten.sorvig@qt.io> | 2018-06-01 15:13:30 +0200 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2018-08-30 06:48:33 +0000 |
commit | 29c0377f07f4942f9957ea87d59c252148dc9e5b (patch) | |
tree | cb79a59b6c47305ca024675cc1325ed0a6be8aac /src/corelib | |
parent | 707ae5b66774a2ed4713da3b8fa69c1d002c3beb (diff) |
WebAssembly for QtBase
This is the squashed diff from wip/webassembly to dev.
Done-with: Peng Wu <peng.wu@intopalo.com>
Done-with: Sami Enne <sami.enne@intopalo.com>
Done-with: Morten Johan Sørvig <morten.sorvig@qt.io>
Started-by: Andrew Knight <andrew.knight@intopalo.com>
Change-Id: I6562433c0a38d6ec49ab675e0f104f2665f3392d
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/codecs/qtextcodec_p.h | 2 | ||||
-rw-r--r-- | src/corelib/configure.json | 4 | ||||
-rw-r--r-- | src/corelib/global/archdetect.cpp | 2 | ||||
-rw-r--r-- | src/corelib/global/qcompilerdetection.h | 3 | ||||
-rw-r--r-- | src/corelib/global/qlogging.cpp | 37 | ||||
-rw-r--r-- | src/corelib/global/qprocessordetection.h | 6 | ||||
-rw-r--r-- | src/corelib/global/qsystemdetection.h | 2 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_unix.cpp | 4 | ||||
-rw-r--r-- | src/corelib/io/qsettings.cpp | 11 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 22 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_unix.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qeventloop.cpp | 24 | ||||
-rw-r--r-- | src/corelib/mimetypes/qmimedatabase.cpp | 2 | ||||
-rw-r--r-- | src/corelib/tools/qsimd.cpp | 17 | ||||
-rw-r--r-- | src/corelib/tools/qunicodetables_p.h | 6 | ||||
-rw-r--r-- | src/corelib/tools/tools.pri | 2 |
16 files changed, 135 insertions, 11 deletions
diff --git a/src/corelib/codecs/qtextcodec_p.h b/src/corelib/codecs/qtextcodec_p.h index f3c2d090c9..be0cab93e6 100644 --- a/src/corelib/codecs/qtextcodec_p.h +++ b/src/corelib/codecs/qtextcodec_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_TEXTCODEC -#if defined(Q_OS_MAC) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) +#if defined(Q_OS_MAC) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_WASM) #define QT_LOCALE_IS_UTF8 #endif diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 18fc22f18f..183eb3a13e 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -481,7 +481,7 @@ }, "eventfd": { "label": "eventfd", - "condition": "tests.eventfd", + "condition": "!config.wasm && tests.eventfd", "output": [ "feature" ] }, "futimens": { @@ -592,7 +592,7 @@ "poll_ppoll": { "label": "Native ppoll()", "emitIf": "!config.win32", - "condition": "tests.ppoll", + "condition": "!config.wasm && tests.ppoll", "output": [ "privateFeature" ] }, "poll_pollts": { diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp index 6c1a026fa8..422df3ff90 100644 --- a/src/corelib/global/archdetect.cpp +++ b/src/corelib/global/archdetect.cpp @@ -51,6 +51,8 @@ # define ARCH_PROCESSOR "avr32" #elif defined(Q_PROCESSOR_BLACKFIN) # define ARCH_PROCESSOR "bfin" +#elif defined(Q_PROCESSOR_WASM) +# define ARCH_PROCESSOR "wasm" #elif defined(Q_PROCESSOR_X86_32) # define ARCH_PROCESSOR "i386" #elif defined(Q_PROCESSOR_X86_64) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 2b85ea0815..345ab9e8ad 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -206,6 +206,9 @@ # define Q_DECL_NS_RETURNS_AUTORELEASED __attribute__((ns_returns_autoreleased)) # endif # endif +# ifdef __EMSCRIPTEN__ +# define Q_CC_EMSCRIPTEN +# endif # else /* Plain GCC */ # if Q_CC_GNU >= 405 diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index a931b43220..2aabaa2ffb 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -94,6 +94,10 @@ # include "private/qcore_unix_p.h" #endif +#ifdef Q_OS_WASM +#include <emscripten/emscripten.h> +#endif + #if QT_CONFIG(regularexpression) # ifdef __UCLIBC__ # if __UCLIBC_HAS_BACKTRACE__ @@ -1690,6 +1694,37 @@ static bool win_message_handler(QtMsgType type, const QMessageLogContext &contex } #endif +#ifdef Q_OS_WASM +static bool wasm_default_message_handler(QtMsgType type, + const QMessageLogContext &context, + const QString &message) +{ + if (shouldLogToStderr()) + return false; // Leave logging up to stderr handler + + QString formattedMessage = qFormatLogMessage(type, context, message); + int emOutputFlags = (EM_LOG_CONSOLE | EM_LOG_DEMANGLE); + QByteArray localMsg = message.toLocal8Bit(); + switch (type) { + case QtDebugMsg: + break; + case QtInfoMsg: + break; + case QtWarningMsg: + emOutputFlags |= EM_LOG_WARN; + break; + case QtCriticalMsg: + emOutputFlags |= EM_LOG_ERROR; + break; + case QtFatalMsg: + emOutputFlags |= EM_LOG_ERROR; + } + emscripten_log(emOutputFlags, "%s\n", qPrintable(formattedMessage)); + + return true; // Prevent further output to stderr +} +#endif + #endif // Bootstrap check // -------------------------------------------------------------------------- @@ -1735,6 +1770,8 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con # elif defined(QT_USE_APPLE_UNIFIED_LOGGING) if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) handledStderr |= AppleUnifiedLogger::messageHandler(type, context, message); +# elif defined Q_OS_WASM + handledStderr |= wasm_default_message_handler(type, context, message); # endif #endif diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index 9a3dfd776d..aaa27dff4a 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -320,6 +320,12 @@ # endif # define Q_BYTE_ORDER Q_BIG_ENDIAN +// -- Web Assembly -- +#elif defined(__EMSCRIPTEN__) +# define Q_PROCESSOR_WASM +# define Q_PROCESSOR_X86 6 // enables SIMD support +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN +# define Q_PROCESSOR_WORDSIZE 8 #endif /* diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index cacb95b674..aabe46f3c2 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -137,6 +137,8 @@ # define Q_OS_HPUX #elif defined(__native_client__) # define Q_OS_NACL +#elif defined(__EMSCRIPTEN__) +# define Q_OS_WASM #elif defined(__linux__) || defined(__linux) # define Q_OS_LINUX #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 835e6a6a44..eebf36416e 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -860,7 +860,7 @@ QString QFileSystemEngine::resolveUserName(uint userId) QVarLengthArray<char, 1024> buf(size_max); #endif -#if !defined(Q_OS_INTEGRITY) +#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM) struct passwd *pw = 0; #if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) struct passwd entry; @@ -884,7 +884,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId) QVarLengthArray<char, 1024> buf(size_max); #endif -#if !defined(Q_OS_INTEGRITY) +#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM) struct group *gr = 0; #if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24)) size_max = sysconf(_SC_GETGR_R_SIZE_MAX); diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 1134c6bb85..391d2a49af 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -77,6 +77,10 @@ # include <ioLib.h> #endif +#ifdef Q_OS_WASM +#include <emscripten.h> +#endif + #include <algorithm> #include <stdlib.h> @@ -1544,6 +1548,13 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile) perms |= QFile::ReadGroup | QFile::ReadOther; QFile(confFile->name).setPermissions(perms); } +#ifdef Q_OS_WASM + EM_ASM( + // Sync sandbox filesystem to persistent database filesystem. See QTBUG-70002 + FS.syncfs(false, function(err) { + }); + ); +#endif } else { setStatus(QSettings::AccessError); } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 0303916c11..1350a7aa94 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -118,6 +118,10 @@ # include <taskLib.h> #endif +#ifdef Q_OS_WASM +#include <emscripten.h> +#endif + #ifdef QT_BOOTSTRAPPED #include <private/qtrace_p.h> #else @@ -486,6 +490,13 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint QCoreApplicationPrivate::~QCoreApplicationPrivate() { +#ifdef Q_OS_WASM + EM_ASM( + // unmount persistent directory as IDBFS + // see also QTBUG-70002 + FS.unmount('/home/web_user'); + ); +#endif #ifndef QT_NO_QOBJECT cleanupThreadData(); #endif @@ -777,6 +788,17 @@ void QCoreApplicationPrivate::init() Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object"); QCoreApplication::self = q; +#ifdef Q_OS_WASM + EM_ASM( + // mount and sync persistent filesystem to sandbox + FS.mount(IDBFS, {}, '/home/web_user'); + FS.syncfs(true, function(err) { + if (err) + Module.print(err); + }); + ); +#endif + // Store app name/version (so they're still available after QCoreApplication is destroyed) if (!coreappdata()->applicationNameSet) coreappdata()->application = appName(); diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index a28f2e3f0a..535f86fefe 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -130,7 +130,7 @@ static void initThreadPipeFD(int fd) bool QThreadPipe::init() { -#if defined(Q_OS_NACL) +#if defined(Q_OS_NACL) || defined(Q_OS_WASM) // do nothing. #elif defined(Q_OS_VXWORKS) qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf())); diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index f1d32b15d1..a6cc51621a 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -48,6 +48,10 @@ #include "qeventloop_p.h" #include <private/qthread_p.h> +#ifdef Q_OS_WASM +#include <emscripten.h> +#endif + QT_BEGIN_NAMESPACE /*! @@ -208,6 +212,15 @@ int QEventLoop::exec(ProcessEventsFlags flags) if (app && app->thread() == thread()) QCoreApplication::removePostedEvents(app, QEvent::Quit); +#ifdef Q_OS_WASM + // Partial support for nested event loops: Make the runtime throw a JavaSrcript + // exception, which returns control to the browser while preserving the C++ stack. + // Event processing then continues as normal. The sleep call below never returns. + // QTBUG-70185 + if (d->threadData->loopLevel > 1) + emscripten_sleep(1); +#endif + while (!d->exit.loadAcquire()) processEvents(flags | WaitForMoreEvents | EventLoopExec); @@ -269,6 +282,17 @@ void QEventLoop::exit(int returnCode) d->returnCode.store(returnCode); d->exit.storeRelease(true); d->threadData->eventDispatcher.load()->interrupt(); + +#ifdef Q_OS_WASM + // QEventLoop::exec() never returns in emscripten. We implement approximate behavior here. + // QTBUG-70185 + if (d->threadData->loopLevel == 1) { + emscripten_force_exit(returnCode); + } else { + d->inExec = false; + --d->threadData->loopLevel; + } +#endif } /*! diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index a58698af53..10b5c8eafd 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -151,7 +151,9 @@ void QMimeDatabasePrivate::loadProviders() QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers() { +#ifndef Q_OS_WASM // stub implementation always returns true Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex +#endif if (m_providers.isEmpty()) { loadProviders(); m_lastCheck.start(); diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 85efd3cded..07a8b022bc 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -190,7 +190,9 @@ static inline quint64 detectProcessorFeatures() static int maxBasicCpuidSupported() { -#if defined(Q_CC_GNU) +#if defined(Q_CC_EMSCRIPTEN) + return 6; // All features supported by Emscripten +#elif defined(Q_CC_GNU) qregisterint tmp1; # if Q_PROCESSOR_X86 < 5 @@ -235,7 +237,7 @@ static int maxBasicCpuidSupported() static void cpuidFeatures01(uint &ecx, uint &edx) { -#if defined(Q_CC_GNU) +#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN) qregisterint tmp1; asm ("xchg " PICreg", %2\n" "cpuid\n" @@ -252,6 +254,9 @@ static void cpuidFeatures01(uint &ecx, uint &edx) __CPUID(1, info); ecx = info[2]; edx = info[3]; +#else + Q_UNUSED(ecx); + Q_UNUSED(edx); #endif } @@ -261,7 +266,7 @@ inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int) static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx) { -#if defined(Q_CC_GNU) +#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN) qregisteruint rbx; // in case it's 64-bit qregisteruint rcx = 0; qregisteruint rdx = 0; @@ -294,7 +299,7 @@ inline quint64 _xgetbv(__int64) { return 0; } #endif static void xgetbv(uint in, uint &eax, uint &edx) { -#if defined(Q_CC_GNU) || defined(Q_CC_GHS) +#if (defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)) || defined(Q_CC_GHS) asm (".byte 0x0F, 0x01, 0xD0" // xgetbv instruction : "=a" (eax), "=d" (edx) : "c" (in)); @@ -302,6 +307,10 @@ static void xgetbv(uint in, uint &eax, uint &edx) quint64 result = _xgetbv(in); eax = result; edx = result >> 32; +#else + Q_UNUSED(in); + Q_UNUSED(eax); + Q_UNUSED(edx); #endif } diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h index f3fb6ec1b0..3f2e91a9b2 100644 --- a/src/corelib/tools/qunicodetables_p.h +++ b/src/corelib/tools/qunicodetables_p.h @@ -72,6 +72,9 @@ struct Properties { signed short mirrorDiff : 16; ushort lowerCaseSpecial : 1; signed short lowerCaseDiff : 15; +#ifdef Q_OS_WASM + unsigned char : 0; //wasm 64 packing trick +#endif ushort upperCaseSpecial : 1; signed short upperCaseDiff : 15; ushort titleCaseSpecial : 1; @@ -80,6 +83,9 @@ struct Properties { signed short caseFoldDiff : 15; ushort unicodeVersion : 8; /* 5 used */ ushort nfQuickCheck : 8; +#ifdef Q_OS_WASM + unsigned char : 0; //wasm 64 packing trick +#endif ushort graphemeBreakClass : 5; /* 5 used */ ushort wordBreakClass : 5; /* 5 used */ ushort sentenceBreakClass : 8; /* 4 used */ diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 9ec6ea4894..dc28e0e0a2 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -220,7 +220,7 @@ qtConfig(system-doubleconversion) { } # Note: libm should be present by default becaue this is C++ -unix:!macx-icc:!vxworks:!haiku:!integrity: LIBS_PRIVATE += -lm +unix:!macx-icc:!vxworks:!haiku:!integrity:!wasm: LIBS_PRIVATE += -lm TR_EXCLUDE += ../3rdparty/* |