Merge branch '5.11' into dev
Conflicts: qmake/library/qmakebuiltins.cpp src/plugins/platforms/windows/qwindowstabletsupport.h src/plugins/platforms/xcb/qxcbconnection.cpp src/plugins/platforms/xcb/qxcbconnection.h src/plugins/platforms/xcb/qxcbconnection_xi2.cpp src/plugins/platforms/xcb/qxcbwindow.cpp src/widgets/styles/qstylesheetstyle.cpp tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp Done-With: Gatis Paeglis <gatis.paeglis@qt.io> Change-Id: I000b0eb3cea2a5c7a99b95732bfdd41507cf916e
This commit is contained in:
commit
23c9d4c98f
@ -5,7 +5,7 @@ QT_BUILD_TREE = $$shadowed($$PWD)
|
||||
# custom command line handling
|
||||
|
||||
defineTest(qtConfCommandline_qmakeArgs) {
|
||||
contains(1, QMAKE_[A-Z_]+ *[-+]?=.*) {
|
||||
contains(1, QMAKE_[A-Z0-9_]+ *[-+]?=.*) {
|
||||
config.input.qmakeArgs += $$1
|
||||
export(config.input.qmakeArgs)
|
||||
return(true)
|
||||
@ -449,8 +449,8 @@ defineTest(reloadSpec) {
|
||||
eval($$l)
|
||||
include($$QMAKESPEC/qmake.conf)
|
||||
load(spec_post)
|
||||
load(default_pre)
|
||||
CONFIG += $$_SAVED_CONFIG
|
||||
load(default_pre)
|
||||
|
||||
# ensure pristine environment for configuration. again.
|
||||
discard_from($$[QT_HOST_DATA/get]/mkspecs/qconfig.pri)
|
||||
|
@ -113,10 +113,6 @@
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-keyboard-shortcuts.html
|
||||
\title Qt Creator: Keyboard Shortcuts
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/quick-screens.html
|
||||
\title Qt Creator: Creating Screens
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/qmldesigner-pathview-editor.html
|
||||
\title Qt Creator: Editing PathView Properties
|
||||
@ -125,6 +121,22 @@
|
||||
\externalpage http://doc.qt.io/qtcreator/qmldesigner-connections.html
|
||||
\title Qt Creator: Adding Connections
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/quick-signals.html
|
||||
\title Qt Creator: Connecting Objects to Signals
|
||||
*/
|
||||
* /*!
|
||||
\externalpage http://doc.qt.io/qtcreator/quick-dynamic-properties.html
|
||||
\title Qt Creator: Specifying Dynamic Properties
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/quick-property-bindings.html
|
||||
\title Qt Creator: Adding Bindings Between Properties
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/quick-connections-backend.html
|
||||
\title Qt Creator: Managing C++ Backend Objects
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/qtcreator-transitions-example.html
|
||||
\title Qt Creator: Creating a Qt Quick Application
|
||||
@ -147,7 +159,7 @@
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-using-qt-quick-designer.html
|
||||
\title Qt Creator: Using Qt Quick Designer
|
||||
\title Qt Creator: Editing QML Files in Design Mode
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/quick-projects.html
|
||||
@ -343,7 +355,7 @@
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-analyzer.html
|
||||
\title Qt Creator: Detecting Memory Leaks
|
||||
\title Qt Creator: Detecting Memory Leaks with Memcheck
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-cache-profiler.html
|
||||
@ -351,7 +363,7 @@
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-running-valgrind-remotely.html
|
||||
\title Qt Creator: Running Valgrind Tools Remotely
|
||||
\title Qt Creator: Running Valgrind Tools on External Applications
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-valgrind-overview.html
|
||||
@ -530,8 +542,12 @@
|
||||
*/
|
||||
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-clang-static-analyzer.html
|
||||
\title Qt Creator: Using Clang Static Analyzer
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-clang-tools.html
|
||||
\title Qt Creator: Using Clang Tools
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-heob.html
|
||||
\title Qt Creator: Detecting Memory Leaks with Heob
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-cpu-usage-analyzer.html
|
||||
@ -549,3 +565,19 @@
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-writing-program.html
|
||||
\title Creating a Qt Widget Based Application
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/qtquick-navigator.html
|
||||
\title Qt Creator: Managing Item Hierarchy
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/qtquick-properties.html
|
||||
\title Qt Creator: Specifying Item Properties
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/quick-states.html
|
||||
\title Qt Creator: Adding States
|
||||
*/
|
||||
/*!
|
||||
\externalpage http://doc.qt.io/qtcreator/creator-scxml.html
|
||||
\title Qt Creator: Editing State Charts
|
||||
*/
|
||||
|
@ -83,14 +83,25 @@ TetrixWindow::TetrixWindow()
|
||||
pauseButton->setFocusPolicy(Qt::NoFocus);
|
||||
//! [3] //! [4]
|
||||
|
||||
connect(startButton, SIGNAL(clicked()), board, SLOT(start()));
|
||||
connect(startButton, &QPushButton::clicked, board, &TetrixBoard::start);
|
||||
//! [4] //! [5]
|
||||
connect(quitButton , SIGNAL(clicked()), qApp, SLOT(quit()));
|
||||
connect(pauseButton, SIGNAL(clicked()), board, SLOT(pause()));
|
||||
connect(board, SIGNAL(scoreChanged(int)), scoreLcd, SLOT(display(int)));
|
||||
connect(board, SIGNAL(levelChanged(int)), levelLcd, SLOT(display(int)));
|
||||
connect(board, SIGNAL(linesRemovedChanged(int)),
|
||||
linesLcd, SLOT(display(int)));
|
||||
connect(quitButton , &QPushButton::clicked, qApp, &QApplication::quit);
|
||||
connect(pauseButton, &QPushButton::clicked, board, &TetrixBoard::pause);
|
||||
#if __cplusplus >= 201402L
|
||||
connect(board, &TetrixBoard::scoreChanged,
|
||||
scoreLcd, qOverload<int>(&QLCDNumber::display));
|
||||
connect(board, &TetrixBoard::levelChanged,
|
||||
levelLcd, qOverload<int>(&QLCDNumber::display));
|
||||
connect(board, &TetrixBoard::linesRemovedChanged,
|
||||
linesLcd, qOverload<int>(&QLCDNumber::display));
|
||||
#else
|
||||
connect(board, &TetrixBoard::scoreChanged,
|
||||
scoreLcd, QOverload<int>::of(&QLCDNumber::display));
|
||||
connect(board, &TetrixBoard::levelChanged,
|
||||
levelLcd, QOverload<int>::of(&QLCDNumber::display));
|
||||
connect(board, &TetrixBoard::linesRemovedChanged,
|
||||
linesLcd, QOverload<int>::of(&QLCDNumber::display));
|
||||
#endif
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
@ -117,9 +128,9 @@ TetrixWindow::TetrixWindow()
|
||||
//! [7]
|
||||
QLabel *TetrixWindow::createLabel(const QString &text)
|
||||
{
|
||||
QLabel *lbl = new QLabel(text);
|
||||
lbl->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
return lbl;
|
||||
QLabel *label = new QLabel(text);
|
||||
label->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
return label;
|
||||
}
|
||||
//! [7]
|
||||
|
||||
|
@ -110,6 +110,12 @@ greaterThan(QMAKE_MSC_VER, 1909) {
|
||||
QMAKE_CXXFLAGS_CXX14 = -std:c++14
|
||||
QMAKE_CXXFLAGS_CXX1Z = -std:c++17
|
||||
}
|
||||
|
||||
# MSVC 2017 15.8+ fixed std::aligned_storage but compilation fails without
|
||||
# this flag since the fix breaks binary compatibility.
|
||||
greaterThan(QMAKE_MSC_VER, 1914) {
|
||||
DEFINES += _ENABLE_EXTENDED_ALIGNED_STORAGE
|
||||
}
|
||||
}
|
||||
|
||||
greaterThan(QMAKE_MSC_VER, 1910) {
|
||||
|
@ -11,7 +11,7 @@ CONFIG = \
|
||||
testcase_targets import_plugins import_qpa_plugin \
|
||||
$$CONFIG
|
||||
|
||||
!build_pass:!isEmpty(QT_LICHECK) {
|
||||
!build_pass:!isEmpty(QT_LICHECK):!QTDIR_build {
|
||||
#
|
||||
# call license checker (but cache result for one day)
|
||||
#
|
||||
|
@ -215,5 +215,8 @@ xcode_product_bundle_identifier_setting.name = PRODUCT_BUNDLE_IDENTIFIER
|
||||
xcode_product_bundle_identifier_setting.value = $$QMAKE_TARGET_BUNDLE_PREFIX
|
||||
isEmpty(xcode_product_bundle_identifier_setting.value): \
|
||||
xcode_product_bundle_identifier_setting.value = "com.yourcompany"
|
||||
xcode_product_bundle_identifier_setting.value = "$${xcode_product_bundle_identifier_setting.value}.${PRODUCT_NAME:rfc1034identifier}"
|
||||
xcode_product_bundle_target = $$QMAKE_BUNDLE
|
||||
isEmpty(xcode_product_bundle_target): \
|
||||
xcode_product_bundle_target = ${PRODUCT_NAME:rfc1034identifier}
|
||||
xcode_product_bundle_identifier_setting.value = "$${xcode_product_bundle_identifier_setting.value}.$${xcode_product_bundle_target}"
|
||||
QMAKE_MAC_XCODE_SETTINGS += xcode_product_bundle_identifier_setting
|
||||
|
@ -1016,7 +1016,8 @@ defineTest(qtConfTest_compile) {
|
||||
QMAKE_MAKE = "$$QMAKE_MAKE clean && $$QMAKE_MAKE"
|
||||
|
||||
mkpath($$test_out_dir)|error()
|
||||
write_file($$test_base_out_dir/.qmake.cache)|error()
|
||||
cont = "CONFIG += QTDIR_build"
|
||||
write_file($$test_base_out_dir/.qmake.cache, cont)|error()
|
||||
|
||||
$${1}.literal_args += $$qtConfAllLibraryArgs($$eval($${1}.resolved_uses))
|
||||
|
||||
|
@ -39,7 +39,7 @@ CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \
|
||||
-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS \
|
||||
-DQT_VERSION_STR=\"$(QT_VERSION)\" -DQT_VERSION_MAJOR=$(QT_MAJOR_VERSION) -DQT_VERSION_MINOR=$(QT_MINOR_VERSION) -DQT_VERSION_PATCH=$(QT_PATCH_VERSION) \
|
||||
-DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \
|
||||
-DQT_NO_FOREACH -DUNICODE
|
||||
-DQT_NO_FOREACH -DUNICODE -D_ENABLE_EXTENDED_ALIGNED_STORAGE
|
||||
CFLAGS = $(CFLAGS_PCH) $(CFLAGS_BARE) $(CFLAGS)
|
||||
|
||||
CXXFLAGS_BARE = $(CFLAGS_BARE)
|
||||
|
@ -1046,7 +1046,7 @@
|
||||
library and header files. The proper include and library paths for the
|
||||
Qt library will automatically be added to the project. This is defined
|
||||
by default, and can be fine-tuned with the \c{\l{#qt}{QT}} variable.
|
||||
\row \li x11 \li The target is a X11 application or library. The proper
|
||||
\row \li x11 \li The target is an X11 application or library. The proper
|
||||
include paths and libraries will automatically be added to the
|
||||
project.
|
||||
\row \li testcase \li The target is an automated test.
|
||||
@ -1282,7 +1282,7 @@
|
||||
\section1 LEXOBJECTS
|
||||
|
||||
Specifies the names of intermediate Lex object
|
||||
files.The value of this variable is typically handled by
|
||||
files. The value of this variable is typically handled by
|
||||
qmake and rarely needs to be modified.
|
||||
|
||||
\target LEXSOURCES
|
||||
@ -1779,9 +1779,9 @@
|
||||
|
||||
\note This variable is used on \macos, iOS, tvOS, and watchOS only.
|
||||
|
||||
For projects where the build target is an \macos, iOS, tvOS, or watchOS framework, this
|
||||
variable is used to specify the version number that will be applied to the
|
||||
framework that is built.
|
||||
For projects where the build target is a \macos, iOS, tvOS, or watchOS
|
||||
framework, this variable is used to specify the version number that will be
|
||||
applied to the framework that is built.
|
||||
|
||||
By default, this variable contains the same value as the \l{#VERSION}{VERSION}
|
||||
variable.
|
||||
@ -1865,7 +1865,7 @@
|
||||
\note This variable is used on Unix platforms only.
|
||||
|
||||
Specifies the location of X11 header file paths to be added
|
||||
to \l{INCLUDEPATH} when building a X11 target. The value of this variable
|
||||
to \l{INCLUDEPATH} when building an X11 target. The value of this variable
|
||||
is typically handled by qmake or
|
||||
\l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
|
||||
|
||||
@ -2255,7 +2255,7 @@
|
||||
|
||||
\section1 QMAKE_QMAKE
|
||||
|
||||
Contains the abosolute path of the qmake executable.
|
||||
Contains the absolute path of the qmake executable.
|
||||
|
||||
\note Do not attempt to overwrite the value of this variable.
|
||||
|
||||
@ -2323,7 +2323,7 @@
|
||||
If defined, the value of this variable is used as a path to be prepended to
|
||||
the built shared library's \c SONAME identifier. The \c SONAME is the
|
||||
identifier that the dynamic linker will later use to reference the library.
|
||||
In general this reference may be a library name or full library path. On \macos,
|
||||
In general, this reference may be a library name or full library path. On \macos,
|
||||
iOS, tvOS, and watchOS, the path may be specified relatively using the following
|
||||
placeholders:
|
||||
|
||||
@ -2629,7 +2629,7 @@
|
||||
|
||||
\section1 TARGET_x.y.z
|
||||
|
||||
Specifies the extension of \c TARGET with version number. The
|
||||
Specifies the extension of \c TARGET with a version number. The
|
||||
value of this variable is typically handled by
|
||||
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely
|
||||
needs to be modified.
|
||||
@ -2650,7 +2650,7 @@
|
||||
The subdirectories are specified using the \l{#SUBDIRS}{SUBDIRS}
|
||||
variable.
|
||||
\row \li aux \li Creates a Makefile for not building anything. Use this if no compiler
|
||||
needs to be invoked to create the target, for instance because your
|
||||
needs to be invoked to create the target; for instance, because your
|
||||
project is written in an interpreted language.
|
||||
\note This template type is only available for Makefile-based
|
||||
generators. In particular, it will not work with the vcxproj and
|
||||
@ -2832,7 +2832,7 @@
|
||||
Windows Phone.
|
||||
\row
|
||||
\li logo_480x800
|
||||
\li Splash sceen image file of size 480x800 pixels. This is only supported on
|
||||
\li Splash screen image file of size 480x800 pixels. This is only supported on
|
||||
Windows Phone.
|
||||
\row
|
||||
\li logo_large
|
||||
|
@ -1223,6 +1223,171 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
|
||||
return ReturnTrue;
|
||||
}
|
||||
|
||||
QMakeEvaluator::VisitReturn QMakeEvaluator::testFunc_cache(const ProStringList &args)
|
||||
{
|
||||
bool persist = true;
|
||||
enum { TargetStash, TargetCache, TargetSuper } target = TargetCache;
|
||||
enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet;
|
||||
ProKey srcvar;
|
||||
if (args.count() >= 2) {
|
||||
const auto opts = split_value_list(args.at(1).toQStringRef());
|
||||
for (const ProString &opt : opts) {
|
||||
if (opt == QLatin1String("transient")) {
|
||||
persist = false;
|
||||
} else if (opt == QLatin1String("super")) {
|
||||
target = TargetSuper;
|
||||
} else if (opt == QLatin1String("stash")) {
|
||||
target = TargetStash;
|
||||
} else if (opt == QLatin1String("set")) {
|
||||
mode = CacheSet;
|
||||
} else if (opt == QLatin1String("add")) {
|
||||
mode = CacheAdd;
|
||||
} else if (opt == QLatin1String("sub")) {
|
||||
mode = CacheSub;
|
||||
} else {
|
||||
evalError(fL1S("cache(): invalid flag %1.").arg(opt.toQStringView()));
|
||||
return ReturnFalse;
|
||||
}
|
||||
}
|
||||
if (args.count() >= 3) {
|
||||
srcvar = args.at(2).toKey();
|
||||
} else if (mode != CacheSet) {
|
||||
evalError(fL1S("cache(): modes other than 'set' require a source variable."));
|
||||
return ReturnFalse;
|
||||
}
|
||||
}
|
||||
QString varstr;
|
||||
ProKey dstvar = args.at(0).toKey();
|
||||
if (!dstvar.isEmpty()) {
|
||||
if (srcvar.isEmpty())
|
||||
srcvar = dstvar;
|
||||
ProValueMap::Iterator srcvarIt;
|
||||
if (!findValues(srcvar, &srcvarIt)) {
|
||||
evalError(fL1S("Variable %1 is not defined.").arg(srcvar.toQStringView()));
|
||||
return ReturnFalse;
|
||||
}
|
||||
// The caches for the host and target may differ (e.g., when we are manipulating
|
||||
// CONFIG), so we cannot compute a common new value for both.
|
||||
const ProStringList &diffval = *srcvarIt;
|
||||
ProStringList newval;
|
||||
bool changed = false;
|
||||
for (bool hostBuild = false; ; hostBuild = true) {
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
m_option->mutex.lock();
|
||||
#endif
|
||||
QMakeBaseEnv *baseEnv =
|
||||
m_option->baseEnvs.value(QMakeBaseKey(m_buildRoot, m_stashfile, hostBuild));
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
// It's ok to unlock this before locking baseEnv,
|
||||
// as we have no intention to initialize the env.
|
||||
m_option->mutex.unlock();
|
||||
#endif
|
||||
do {
|
||||
if (!baseEnv)
|
||||
break;
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
QMutexLocker locker(&baseEnv->mutex);
|
||||
if (baseEnv->inProgress && baseEnv->evaluator != this) {
|
||||
// The env is still in the works, but it may be already past the cache
|
||||
// loading. So we need to wait for completion and amend it as usual.
|
||||
QThreadPool::globalInstance()->releaseThread();
|
||||
baseEnv->cond.wait(&baseEnv->mutex);
|
||||
QThreadPool::globalInstance()->reserveThread();
|
||||
}
|
||||
if (!baseEnv->isOk)
|
||||
break;
|
||||
#endif
|
||||
QMakeEvaluator *baseEval = baseEnv->evaluator;
|
||||
const ProStringList &oldval = baseEval->values(dstvar);
|
||||
if (mode == CacheSet) {
|
||||
newval = diffval;
|
||||
} else {
|
||||
newval = oldval;
|
||||
if (mode == CacheAdd)
|
||||
newval += diffval;
|
||||
else
|
||||
newval.removeEach(diffval);
|
||||
}
|
||||
if (oldval != newval) {
|
||||
if (target != TargetStash || !m_stashfile.isEmpty()) {
|
||||
baseEval->valuesRef(dstvar) = newval;
|
||||
if (target == TargetSuper) {
|
||||
do {
|
||||
if (dstvar == QLatin1String("QMAKEPATH")) {
|
||||
baseEval->m_qmakepath = newval.toQStringList();
|
||||
baseEval->updateMkspecPaths();
|
||||
} else if (dstvar == QLatin1String("QMAKEFEATURES")) {
|
||||
baseEval->m_qmakefeatures = newval.toQStringList();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
baseEval->updateFeaturePaths();
|
||||
if (hostBuild == m_hostBuild)
|
||||
m_featureRoots = baseEval->m_featureRoots;
|
||||
} while (false);
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
} while (false);
|
||||
if (hostBuild)
|
||||
break;
|
||||
}
|
||||
// We assume that whatever got the cached value to be what it is now will do so
|
||||
// the next time as well, so we just skip the persisting if nothing changed.
|
||||
if (!persist || !changed)
|
||||
return ReturnTrue;
|
||||
varstr = dstvar.toQString();
|
||||
if (mode == CacheAdd)
|
||||
varstr += QLatin1String(" +=");
|
||||
else if (mode == CacheSub)
|
||||
varstr += QLatin1String(" -=");
|
||||
else
|
||||
varstr += QLatin1String(" =");
|
||||
if (diffval.count() == 1) {
|
||||
varstr += QLatin1Char(' ');
|
||||
varstr += quoteValue(diffval.at(0));
|
||||
} else if (!diffval.isEmpty()) {
|
||||
for (const ProString &vval : diffval) {
|
||||
varstr += QLatin1String(" \\\n ");
|
||||
varstr += quoteValue(vval);
|
||||
}
|
||||
}
|
||||
varstr += QLatin1Char('\n');
|
||||
}
|
||||
QString fn;
|
||||
QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
|
||||
if (target == TargetSuper) {
|
||||
if (m_superfile.isEmpty()) {
|
||||
m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super"));
|
||||
printf("Info: creating super cache file %s\n", qPrintable(QDir::toNativeSeparators(m_superfile)));
|
||||
valuesRef(ProKey("_QMAKE_SUPER_CACHE_")) << ProString(m_superfile);
|
||||
}
|
||||
fn = m_superfile;
|
||||
} else if (target == TargetCache) {
|
||||
if (m_cachefile.isEmpty()) {
|
||||
m_cachefile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.cache"));
|
||||
printf("Info: creating cache file %s\n", qPrintable(QDir::toNativeSeparators(m_cachefile)));
|
||||
valuesRef(ProKey("_QMAKE_CACHE_")) << ProString(m_cachefile);
|
||||
// We could update m_{source,build}Root and m_featureRoots here, or even
|
||||
// "re-home" our rootEnv, but this doesn't sound too useful - if somebody
|
||||
// wanted qmake to find something in the build directory, he could have
|
||||
// done so "from the outside".
|
||||
// The sub-projects will find the new cache all by themselves.
|
||||
}
|
||||
fn = m_cachefile;
|
||||
} else {
|
||||
fn = m_stashfile;
|
||||
if (fn.isEmpty())
|
||||
fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash"));
|
||||
if (!m_vfs->exists(fn, flags)) {
|
||||
printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn)));
|
||||
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
|
||||
}
|
||||
}
|
||||
return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr);
|
||||
}
|
||||
|
||||
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
||||
const QMakeInternal::QMakeBuiltin &adef, const ProKey &function, const ProStringList &args)
|
||||
{
|
||||
@ -1687,169 +1852,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
||||
#endif
|
||||
return ReturnTrue;
|
||||
}
|
||||
case T_CACHE: {
|
||||
bool persist = true;
|
||||
enum { TargetStash, TargetCache, TargetSuper } target = TargetCache;
|
||||
enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet;
|
||||
ProKey srcvar;
|
||||
if (args.count() >= 2) {
|
||||
const auto opts = split_value_list(args.at(1).toQStringRef());
|
||||
for (const ProString &opt : opts) {
|
||||
if (opt == QLatin1String("transient")) {
|
||||
persist = false;
|
||||
} else if (opt == QLatin1String("super")) {
|
||||
target = TargetSuper;
|
||||
} else if (opt == QLatin1String("stash")) {
|
||||
target = TargetStash;
|
||||
} else if (opt == QLatin1String("set")) {
|
||||
mode = CacheSet;
|
||||
} else if (opt == QLatin1String("add")) {
|
||||
mode = CacheAdd;
|
||||
} else if (opt == QLatin1String("sub")) {
|
||||
mode = CacheSub;
|
||||
} else {
|
||||
evalError(fL1S("cache(): invalid flag %1.").arg(opt.toQStringView()));
|
||||
return ReturnFalse;
|
||||
}
|
||||
}
|
||||
if (args.count() >= 3) {
|
||||
srcvar = args.at(2).toKey();
|
||||
} else if (mode != CacheSet) {
|
||||
evalError(fL1S("cache(): modes other than 'set' require a source variable."));
|
||||
return ReturnFalse;
|
||||
}
|
||||
}
|
||||
QString varstr;
|
||||
ProKey dstvar = args.at(0).toKey();
|
||||
if (!dstvar.isEmpty()) {
|
||||
if (srcvar.isEmpty())
|
||||
srcvar = dstvar;
|
||||
ProValueMap::Iterator srcvarIt;
|
||||
if (!findValues(srcvar, &srcvarIt)) {
|
||||
evalError(fL1S("Variable %1 is not defined.").arg(srcvar.toQStringView()));
|
||||
return ReturnFalse;
|
||||
}
|
||||
// The caches for the host and target may differ (e.g., when we are manipulating
|
||||
// CONFIG), so we cannot compute a common new value for both.
|
||||
const ProStringList &diffval = *srcvarIt;
|
||||
ProStringList newval;
|
||||
bool changed = false;
|
||||
for (bool hostBuild = false; ; hostBuild = true) {
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
m_option->mutex.lock();
|
||||
#endif
|
||||
QMakeBaseEnv *baseEnv =
|
||||
m_option->baseEnvs.value(QMakeBaseKey(m_buildRoot, m_stashfile, hostBuild));
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
// It's ok to unlock this before locking baseEnv,
|
||||
// as we have no intention to initialize the env.
|
||||
m_option->mutex.unlock();
|
||||
#endif
|
||||
do {
|
||||
if (!baseEnv)
|
||||
break;
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
QMutexLocker locker(&baseEnv->mutex);
|
||||
if (baseEnv->inProgress && baseEnv->evaluator != this) {
|
||||
// The env is still in the works, but it may be already past the cache
|
||||
// loading. So we need to wait for completion and amend it as usual.
|
||||
QThreadPool::globalInstance()->releaseThread();
|
||||
baseEnv->cond.wait(&baseEnv->mutex);
|
||||
QThreadPool::globalInstance()->reserveThread();
|
||||
}
|
||||
if (!baseEnv->isOk)
|
||||
break;
|
||||
#endif
|
||||
QMakeEvaluator *baseEval = baseEnv->evaluator;
|
||||
const ProStringList &oldval = baseEval->values(dstvar);
|
||||
if (mode == CacheSet) {
|
||||
newval = diffval;
|
||||
} else {
|
||||
newval = oldval;
|
||||
if (mode == CacheAdd)
|
||||
newval += diffval;
|
||||
else
|
||||
newval.removeEach(diffval);
|
||||
}
|
||||
if (oldval != newval) {
|
||||
if (target != TargetStash || !m_stashfile.isEmpty()) {
|
||||
baseEval->valuesRef(dstvar) = newval;
|
||||
if (target == TargetSuper) {
|
||||
do {
|
||||
if (dstvar == QLatin1String("QMAKEPATH")) {
|
||||
baseEval->m_qmakepath = newval.toQStringList();
|
||||
baseEval->updateMkspecPaths();
|
||||
} else if (dstvar == QLatin1String("QMAKEFEATURES")) {
|
||||
baseEval->m_qmakefeatures = newval.toQStringList();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
baseEval->updateFeaturePaths();
|
||||
if (hostBuild == m_hostBuild)
|
||||
m_featureRoots = baseEval->m_featureRoots;
|
||||
} while (false);
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
} while (false);
|
||||
if (hostBuild)
|
||||
break;
|
||||
}
|
||||
// We assume that whatever got the cached value to be what it is now will do so
|
||||
// the next time as well, so we just skip the persisting if nothing changed.
|
||||
if (!persist || !changed)
|
||||
return ReturnTrue;
|
||||
varstr = dstvar.toQString();
|
||||
if (mode == CacheAdd)
|
||||
varstr += QLatin1String(" +=");
|
||||
else if (mode == CacheSub)
|
||||
varstr += QLatin1String(" -=");
|
||||
else
|
||||
varstr += QLatin1String(" =");
|
||||
if (diffval.count() == 1) {
|
||||
varstr += QLatin1Char(' ');
|
||||
varstr += quoteValue(diffval.at(0));
|
||||
} else if (!diffval.isEmpty()) {
|
||||
for (const ProString &vval : diffval) {
|
||||
varstr += QLatin1String(" \\\n ");
|
||||
varstr += quoteValue(vval);
|
||||
}
|
||||
}
|
||||
varstr += QLatin1Char('\n');
|
||||
}
|
||||
QString fn;
|
||||
QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
|
||||
if (target == TargetSuper) {
|
||||
if (m_superfile.isEmpty()) {
|
||||
m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super"));
|
||||
printf("Info: creating super cache file %s\n", qPrintable(QDir::toNativeSeparators(m_superfile)));
|
||||
valuesRef(ProKey("_QMAKE_SUPER_CACHE_")) << ProString(m_superfile);
|
||||
}
|
||||
fn = m_superfile;
|
||||
} else if (target == TargetCache) {
|
||||
if (m_cachefile.isEmpty()) {
|
||||
m_cachefile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.cache"));
|
||||
printf("Info: creating cache file %s\n", qPrintable(QDir::toNativeSeparators(m_cachefile)));
|
||||
valuesRef(ProKey("_QMAKE_CACHE_")) << ProString(m_cachefile);
|
||||
// We could update m_{source,build}Root and m_featureRoots here, or even
|
||||
// "re-home" our rootEnv, but this doesn't sound too useful - if somebody
|
||||
// wanted qmake to find something in the build directory, he could have
|
||||
// done so "from the outside".
|
||||
// The sub-projects will find the new cache all by themselves.
|
||||
}
|
||||
fn = m_cachefile;
|
||||
} else {
|
||||
fn = m_stashfile;
|
||||
if (fn.isEmpty())
|
||||
fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash"));
|
||||
if (!m_vfs->exists(fn, flags)) {
|
||||
printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn)));
|
||||
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
|
||||
}
|
||||
}
|
||||
return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr);
|
||||
}
|
||||
case T_CACHE:
|
||||
return testFunc_cache(args);
|
||||
case T_RELOAD_PROPERTIES:
|
||||
#ifdef QT_BUILD_QMAKE
|
||||
m_option->reloadProperties();
|
||||
|
@ -250,6 +250,11 @@ public:
|
||||
#endif
|
||||
QByteArray getCommandOutput(const QString &args, int *exitCode) const;
|
||||
|
||||
private:
|
||||
// Implementation detail of evaluateBuiltinConditional():
|
||||
VisitReturn testFunc_cache(const ProStringList &args);
|
||||
|
||||
public:
|
||||
QMakeEvaluator *m_caller;
|
||||
#ifdef PROEVALUATOR_CUMULATIVE
|
||||
bool m_cumulative;
|
||||
|
6
src/3rdparty/pcre2/AUTHORS
vendored
6
src/3rdparty/pcre2/AUTHORS
vendored
@ -8,7 +8,7 @@ Email domain: cam.ac.uk
|
||||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2017 University of Cambridge
|
||||
Copyright (c) 1997-2018 University of Cambridge
|
||||
All rights reserved
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2017 Zoltan Herczeg
|
||||
Copyright(c) 2010-2018 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2017 Zoltan Herczeg
|
||||
Copyright(c) 2009-2018 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
####
|
||||
|
6
src/3rdparty/pcre2/LICENCE
vendored
6
src/3rdparty/pcre2/LICENCE
vendored
@ -26,7 +26,7 @@ Email domain: cam.ac.uk
|
||||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2017 University of Cambridge
|
||||
Copyright (c) 1997-2018 University of Cambridge
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2017 Zoltan Herczeg
|
||||
Copyright(c) 2010-2018 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2017 Zoltan Herczeg
|
||||
Copyright(c) 2009-2018 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
@ -88,6 +88,7 @@ FILES="
|
||||
src/pcre2_context.c
|
||||
src/pcre2_dfa_match.c
|
||||
src/pcre2_error.c
|
||||
src/pcre2_extuni.c
|
||||
src/pcre2_find_bracket.c
|
||||
src/pcre2_internal.h
|
||||
src/pcre2_intmodedep.h
|
||||
|
1
src/3rdparty/pcre2/pcre2.pro
vendored
1
src/3rdparty/pcre2/pcre2.pro
vendored
@ -27,6 +27,7 @@ SOURCES += \
|
||||
$$PWD/src/pcre2_context.c \
|
||||
$$PWD/src/pcre2_dfa_match.c \
|
||||
$$PWD/src/pcre2_error.c \
|
||||
$$PWD/src/pcre2_extuni.c \
|
||||
$$PWD/src/pcre2_find_bracket.c \
|
||||
$$PWD/src/pcre2_jit_compile.c \
|
||||
$$PWD/src/pcre2_maketables.c \
|
||||
|
7
src/3rdparty/pcre2/qt_attribution.json
vendored
7
src/3rdparty/pcre2/qt_attribution.json
vendored
@ -6,12 +6,13 @@
|
||||
|
||||
"Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
|
||||
"Homepage": "http://www.pcre.org/",
|
||||
"Version": "10.30",
|
||||
"Version": "10.31",
|
||||
"DownloadLocation": "https://ftp.pcre.org/pub/pcre/pcre2-10.31.tar.bz2",
|
||||
"License": "BSD 3-clause \"New\" or \"Revised\" License",
|
||||
"LicenseId": "BSD-3-Clause",
|
||||
"LicenseFile": "LICENCE",
|
||||
"Copyright": "Copyright (c) 1997-2017 University of Cambridge
|
||||
Copyright (c) 2009-2017 Zoltan Herczeg
|
||||
"Copyright": "Copyright (c) 1997-2018 University of Cambridge
|
||||
Copyright (c) 2009-2018 Zoltan Herczeg
|
||||
Copyright (c) 2007-2012 Google Inc.
|
||||
Copyright (c) 2013-2013 Tilera Corporation (jiwang@tilera.com)"
|
||||
}
|
||||
|
122
src/3rdparty/pcre2/src/pcre2.h
vendored
122
src/3rdparty/pcre2/src/pcre2.h
vendored
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE2_MAJOR 10
|
||||
#define PCRE2_MINOR 30
|
||||
#define PCRE2_MINOR 31
|
||||
#define PCRE2_PRERELEASE
|
||||
#define PCRE2_DATE 2017-08-14
|
||||
#define PCRE2_DATE 2018-02-12
|
||||
|
||||
/* When an application links to a PCRE DLL in Windows, the symbols that are
|
||||
imported have to be identified as such. When building PCRE2, the appropriate
|
||||
@ -208,7 +208,104 @@ greater than zero. */
|
||||
#define PCRE2_BSR_UNICODE 1
|
||||
#define PCRE2_BSR_ANYCRLF 2
|
||||
|
||||
/* Error codes: no match and partial match are "expected" errors. */
|
||||
/* Error codes for pcre2_compile(). Some of these are also used by
|
||||
pcre2_pattern_convert(). */
|
||||
|
||||
#define PCRE2_ERROR_END_BACKSLASH 101
|
||||
#define PCRE2_ERROR_END_BACKSLASH_C 102
|
||||
#define PCRE2_ERROR_UNKNOWN_ESCAPE 103
|
||||
#define PCRE2_ERROR_QUANTIFIER_OUT_OF_ORDER 104
|
||||
#define PCRE2_ERROR_QUANTIFIER_TOO_BIG 105
|
||||
#define PCRE2_ERROR_MISSING_SQUARE_BRACKET 106
|
||||
#define PCRE2_ERROR_ESCAPE_INVALID_IN_CLASS 107
|
||||
#define PCRE2_ERROR_CLASS_RANGE_ORDER 108
|
||||
#define PCRE2_ERROR_QUANTIFIER_INVALID 109
|
||||
#define PCRE2_ERROR_INTERNAL_UNEXPECTED_REPEAT 110
|
||||
#define PCRE2_ERROR_INVALID_AFTER_PARENS_QUERY 111
|
||||
#define PCRE2_ERROR_POSIX_CLASS_NOT_IN_CLASS 112
|
||||
#define PCRE2_ERROR_POSIX_NO_SUPPORT_COLLATING 113
|
||||
#define PCRE2_ERROR_MISSING_CLOSING_PARENTHESIS 114
|
||||
#define PCRE2_ERROR_BAD_SUBPATTERN_REFERENCE 115
|
||||
#define PCRE2_ERROR_NULL_PATTERN 116
|
||||
#define PCRE2_ERROR_BAD_OPTIONS 117
|
||||
#define PCRE2_ERROR_MISSING_COMMENT_CLOSING 118
|
||||
#define PCRE2_ERROR_PARENTHESES_NEST_TOO_DEEP 119
|
||||
#define PCRE2_ERROR_PATTERN_TOO_LARGE 120
|
||||
#define PCRE2_ERROR_HEAP_FAILED 121
|
||||
#define PCRE2_ERROR_UNMATCHED_CLOSING_PARENTHESIS 122
|
||||
#define PCRE2_ERROR_INTERNAL_CODE_OVERFLOW 123
|
||||
#define PCRE2_ERROR_MISSING_CONDITION_CLOSING 124
|
||||
#define PCRE2_ERROR_LOOKBEHIND_NOT_FIXED_LENGTH 125
|
||||
#define PCRE2_ERROR_ZERO_RELATIVE_REFERENCE 126
|
||||
#define PCRE2_ERROR_TOO_MANY_CONDITION_BRANCHES 127
|
||||
#define PCRE2_ERROR_CONDITION_ASSERTION_EXPECTED 128
|
||||
#define PCRE2_ERROR_BAD_RELATIVE_REFERENCE 129
|
||||
#define PCRE2_ERROR_UNKNOWN_POSIX_CLASS 130
|
||||
#define PCRE2_ERROR_INTERNAL_STUDY_ERROR 131
|
||||
#define PCRE2_ERROR_UNICODE_NOT_SUPPORTED 132
|
||||
#define PCRE2_ERROR_PARENTHESES_STACK_CHECK 133
|
||||
#define PCRE2_ERROR_CODE_POINT_TOO_BIG 134
|
||||
#define PCRE2_ERROR_LOOKBEHIND_TOO_COMPLICATED 135
|
||||
#define PCRE2_ERROR_LOOKBEHIND_INVALID_BACKSLASH_C 136
|
||||
#define PCRE2_ERROR_UNSUPPORTED_ESCAPE_SEQUENCE 137
|
||||
#define PCRE2_ERROR_CALLOUT_NUMBER_TOO_BIG 138
|
||||
#define PCRE2_ERROR_MISSING_CALLOUT_CLOSING 139
|
||||
#define PCRE2_ERROR_ESCAPE_INVALID_IN_VERB 140
|
||||
#define PCRE2_ERROR_UNRECOGNIZED_AFTER_QUERY_P 141
|
||||
#define PCRE2_ERROR_MISSING_NAME_TERMINATOR 142
|
||||
#define PCRE2_ERROR_DUPLICATE_SUBPATTERN_NAME 143
|
||||
#define PCRE2_ERROR_INVALID_SUBPATTERN_NAME 144
|
||||
#define PCRE2_ERROR_UNICODE_PROPERTIES_UNAVAILABLE 145
|
||||
#define PCRE2_ERROR_MALFORMED_UNICODE_PROPERTY 146
|
||||
#define PCRE2_ERROR_UNKNOWN_UNICODE_PROPERTY 147
|
||||
#define PCRE2_ERROR_SUBPATTERN_NAME_TOO_LONG 148
|
||||
#define PCRE2_ERROR_TOO_MANY_NAMED_SUBPATTERNS 149
|
||||
#define PCRE2_ERROR_CLASS_INVALID_RANGE 150
|
||||
#define PCRE2_ERROR_OCTAL_BYTE_TOO_BIG 151
|
||||
#define PCRE2_ERROR_INTERNAL_OVERRAN_WORKSPACE 152
|
||||
#define PCRE2_ERROR_INTERNAL_MISSING_SUBPATTERN 153
|
||||
#define PCRE2_ERROR_DEFINE_TOO_MANY_BRANCHES 154
|
||||
#define PCRE2_ERROR_BACKSLASH_O_MISSING_BRACE 155
|
||||
#define PCRE2_ERROR_INTERNAL_UNKNOWN_NEWLINE 156
|
||||
#define PCRE2_ERROR_BACKSLASH_G_SYNTAX 157
|
||||
#define PCRE2_ERROR_PARENS_QUERY_R_MISSING_CLOSING 158
|
||||
#define PCRE2_ERROR_VERB_ARGUMENT_NOT_ALLOWED 159
|
||||
#define PCRE2_ERROR_VERB_UNKNOWN 160
|
||||
#define PCRE2_ERROR_SUBPATTERN_NUMBER_TOO_BIG 161
|
||||
#define PCRE2_ERROR_SUBPATTERN_NAME_EXPECTED 162
|
||||
#define PCRE2_ERROR_INTERNAL_PARSED_OVERFLOW 163
|
||||
#define PCRE2_ERROR_INVALID_OCTAL 164
|
||||
#define PCRE2_ERROR_SUBPATTERN_NAMES_MISMATCH 165
|
||||
#define PCRE2_ERROR_MARK_MISSING_ARGUMENT 166
|
||||
#define PCRE2_ERROR_INVALID_HEXADECIMAL 167
|
||||
#define PCRE2_ERROR_BACKSLASH_C_SYNTAX 168
|
||||
#define PCRE2_ERROR_BACKSLASH_K_SYNTAX 169
|
||||
#define PCRE2_ERROR_INTERNAL_BAD_CODE_LOOKBEHINDS 170
|
||||
#define PCRE2_ERROR_BACKSLASH_N_IN_CLASS 171
|
||||
#define PCRE2_ERROR_CALLOUT_STRING_TOO_LONG 172
|
||||
#define PCRE2_ERROR_UNICODE_DISALLOWED_CODE_POINT 173
|
||||
#define PCRE2_ERROR_UTF_IS_DISABLED 174
|
||||
#define PCRE2_ERROR_UCP_IS_DISABLED 175
|
||||
#define PCRE2_ERROR_VERB_NAME_TOO_LONG 176
|
||||
#define PCRE2_ERROR_BACKSLASH_U_CODE_POINT_TOO_BIG 177
|
||||
#define PCRE2_ERROR_MISSING_OCTAL_OR_HEX_DIGITS 178
|
||||
#define PCRE2_ERROR_VERSION_CONDITION_SYNTAX 179
|
||||
#define PCRE2_ERROR_INTERNAL_BAD_CODE_AUTO_POSSESS 180
|
||||
#define PCRE2_ERROR_CALLOUT_NO_STRING_DELIMITER 181
|
||||
#define PCRE2_ERROR_CALLOUT_BAD_STRING_DELIMITER 182
|
||||
#define PCRE2_ERROR_BACKSLASH_C_CALLER_DISABLED 183
|
||||
#define PCRE2_ERROR_QUERY_BARJX_NEST_TOO_DEEP 184
|
||||
#define PCRE2_ERROR_BACKSLASH_C_LIBRARY_DISABLED 185
|
||||
#define PCRE2_ERROR_PATTERN_TOO_COMPLICATED 186
|
||||
#define PCRE2_ERROR_LOOKBEHIND_TOO_LONG 187
|
||||
#define PCRE2_ERROR_PATTERN_STRING_TOO_LONG 188
|
||||
#define PCRE2_ERROR_INTERNAL_BAD_CODE 189
|
||||
#define PCRE2_ERROR_INTERNAL_BAD_CODE_IN_SKIP 190
|
||||
#define PCRE2_ERROR_NO_SURROGATES_IN_UTF16 191
|
||||
#define PCRE2_ERROR_BAD_LITERAL_OPTIONS 192
|
||||
|
||||
|
||||
/* "Expected" matching error codes: no match and partial match. */
|
||||
|
||||
#define PCRE2_ERROR_NOMATCH (-1)
|
||||
#define PCRE2_ERROR_PARTIAL (-2)
|
||||
@ -248,10 +345,10 @@ greater than zero. */
|
||||
#define PCRE2_ERROR_UTF32_ERR1 (-27)
|
||||
#define PCRE2_ERROR_UTF32_ERR2 (-28)
|
||||
|
||||
/* Error codes for pcre2[_dfa]_match(), substring extraction functions, context
|
||||
functions, and serializing functions. They are in numerical order. Originally
|
||||
they were in alphabetical order too, but now that PCRE2 is released, the
|
||||
numbers must not be changed. */
|
||||
/* Miscellaneous error codes for pcre2[_dfa]_match(), substring extraction
|
||||
functions, context functions, and serializing functions. They are in numerical
|
||||
order. Originally they were in alphabetical order too, but now that PCRE2 is
|
||||
released, the numbers must not be changed. */
|
||||
|
||||
#define PCRE2_ERROR_BADDATA (-29)
|
||||
#define PCRE2_ERROR_MIXEDTABLES (-30) /* Name was changed */
|
||||
@ -321,6 +418,7 @@ numbers must not be changed. */
|
||||
#define PCRE2_INFO_HASBACKSLASHC 23
|
||||
#define PCRE2_INFO_FRAMESIZE 24
|
||||
#define PCRE2_INFO_HEAPLIMIT 25
|
||||
#define PCRE2_INFO_EXTRAOPTIONS 26
|
||||
|
||||
/* Request types for pcre2_config(). */
|
||||
|
||||
@ -338,6 +436,9 @@ numbers must not be changed. */
|
||||
#define PCRE2_CONFIG_UNICODE_VERSION 10
|
||||
#define PCRE2_CONFIG_VERSION 11
|
||||
#define PCRE2_CONFIG_HEAPLIMIT 12
|
||||
#define PCRE2_CONFIG_NEVER_BACKSLASH_C 13
|
||||
#define PCRE2_CONFIG_COMPILED_WIDTHS 14
|
||||
|
||||
|
||||
/* Types for code units in patterns and subject strings. */
|
||||
|
||||
@ -393,6 +494,11 @@ without changing the API of the function, thereby allowing old clients to work
|
||||
without modification. Define the generic version in a macro; the width-specific
|
||||
versions are generated from this macro below. */
|
||||
|
||||
/* Flags for the callout_flags field. These are cleared after a callout. */
|
||||
|
||||
#define PCRE2_CALLOUT_STARTMATCH 0x00000001u /* Set for each bumpalong */
|
||||
#define PCRE2_CALLOUT_BACKTRACK 0x00000002u /* Set after a backtrack */
|
||||
|
||||
#define PCRE2_STRUCTURE_LIST \
|
||||
typedef struct pcre2_callout_block { \
|
||||
uint32_t version; /* Identifies version of block */ \
|
||||
@ -412,6 +518,8 @@ typedef struct pcre2_callout_block { \
|
||||
PCRE2_SIZE callout_string_offset; /* Offset to string within pattern */ \
|
||||
PCRE2_SIZE callout_string_length; /* Length of string compiled into pattern */ \
|
||||
PCRE2_SPTR callout_string; /* String compiled into pattern */ \
|
||||
/* ------------------- Added for Version 2 -------------------------- */ \
|
||||
uint32_t callout_flags; /* See above for list */ \
|
||||
/* ------------------------------------------------------------------ */ \
|
||||
} pcre2_callout_block; \
|
||||
\
|
||||
|
56
src/3rdparty/pcre2/src/pcre2_auto_possess.c
vendored
56
src/3rdparty/pcre2/src/pcre2_auto_possess.c
vendored
@ -558,47 +558,73 @@ for(;;)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* At the end of a branch, skip to the end of the group. */
|
||||
|
||||
if (c == OP_ALT)
|
||||
{
|
||||
do code += GET(code, 1); while (*code == OP_ALT);
|
||||
c = *code;
|
||||
}
|
||||
|
||||
/* Inspect the next opcode. */
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case OP_END:
|
||||
case OP_KETRPOS:
|
||||
/* TRUE only in greedy case. The non-greedy case could be replaced by
|
||||
an OP_EXACT, but it is probably not worth it. (And note that OP_EXACT
|
||||
uses more memory, which we cannot get at this stage.) */
|
||||
/* We can always possessify a greedy iterator at the end of the pattern,
|
||||
which is reached after skipping over the final OP_KET. A non-greedy
|
||||
iterator must never be possessified. */
|
||||
|
||||
case OP_END:
|
||||
return base_list[1] != 0;
|
||||
|
||||
/* When an iterator is at the end of certain kinds of group we can inspect
|
||||
what follows the group by skipping over the closing ket. Note that this
|
||||
does not apply to OP_KETRMAX or OP_KETRMIN because what follows any given
|
||||
iteration is variable (could be another iteration or could be the next
|
||||
item). As these two opcodes are not listed in the next switch, they will
|
||||
end up as the next code to inspect, and return FALSE by virtue of being
|
||||
unsupported. */
|
||||
|
||||
case OP_KET:
|
||||
/* If the bracket is capturing, and referenced by an OP_RECURSE, or
|
||||
it is an atomic sub-pattern (assert, once, etc.) the non-greedy case
|
||||
cannot be converted to a possessive form. */
|
||||
case OP_KETRPOS:
|
||||
/* The non-greedy case cannot be converted to a possessive form. */
|
||||
|
||||
if (base_list[1] == 0) return FALSE;
|
||||
|
||||
/* If the bracket is capturing it might be referenced by an OP_RECURSE
|
||||
so its last iterator can never be possessified if the pattern contains
|
||||
recursions. (This could be improved by keeping a list of group numbers that
|
||||
are called by recursion.) */
|
||||
|
||||
switch(*(code - GET(code, 1)))
|
||||
{
|
||||
case OP_CBRA:
|
||||
case OP_SCBRA:
|
||||
case OP_CBRAPOS:
|
||||
case OP_SCBRAPOS:
|
||||
if (cb->had_recurse) return FALSE;
|
||||
break;
|
||||
|
||||
/* Atomic sub-patterns and assertions can always auto-possessify their
|
||||
last iterator. However, if the group was entered as a result of checking
|
||||
a previous iterator, this is not possible. */
|
||||
|
||||
case OP_ASSERT:
|
||||
case OP_ASSERT_NOT:
|
||||
case OP_ASSERTBACK:
|
||||
case OP_ASSERTBACK_NOT:
|
||||
case OP_ONCE:
|
||||
|
||||
/* Atomic sub-patterns and assertions can always auto-possessify their
|
||||
last iterator. However, if the group was entered as a result of checking
|
||||
a previous iterator, this is not possible. */
|
||||
|
||||
return !entered_a_group;
|
||||
}
|
||||
|
||||
/* Skip over the bracket and inspect what comes next. */
|
||||
|
||||
code += PRIV(OP_lengths)[c];
|
||||
continue;
|
||||
|
||||
/* Handle cases where the next item is a group. */
|
||||
|
||||
case OP_ONCE:
|
||||
case OP_BRA:
|
||||
case OP_CBRA:
|
||||
@ -637,11 +663,15 @@ for(;;)
|
||||
code += PRIV(OP_lengths)[c];
|
||||
continue;
|
||||
|
||||
/* The next opcode does not need special handling; fall through and use it
|
||||
to see if the base can be possessified. */
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for a supported opcode, and load its properties. */
|
||||
/* We now have the next appropriate opcode to compare with the base. Check
|
||||
for a supported opcode, and load its properties. */
|
||||
|
||||
code = get_chr_property_list(code, utf, cb->fcc, list);
|
||||
if (code == NULL) return FALSE; /* Unsupported */
|
||||
|
31
src/3rdparty/pcre2/src/pcre2_compile.c
vendored
31
src/3rdparty/pcre2/src/pcre2_compile.c
vendored
@ -2194,8 +2194,8 @@ manage_callouts(PCRE2_SPTR ptr, uint32_t **pcalloutptr, BOOL auto_callout,
|
||||
{
|
||||
uint32_t *previous_callout = *pcalloutptr;
|
||||
|
||||
if (previous_callout != NULL) previous_callout[2] = ptr - cb->start_pattern -
|
||||
(PCRE2_SIZE)previous_callout[1];
|
||||
if (previous_callout != NULL) previous_callout[2] = (uint32_t)(ptr -
|
||||
cb->start_pattern - (PCRE2_SIZE)previous_callout[1]);
|
||||
|
||||
if (!auto_callout) previous_callout = NULL; else
|
||||
{
|
||||
@ -3806,7 +3806,7 @@ while (ptr < ptrend)
|
||||
/* Remember the offset to the next item in the pattern, and set a default
|
||||
length. This should get updated after the next item is read. */
|
||||
|
||||
previous_callout[1] = ptr - cb->start_pattern;
|
||||
previous_callout[1] = (uint32_t)(ptr - cb->start_pattern);
|
||||
previous_callout[2] = 0;
|
||||
break; /* End callout */
|
||||
|
||||
@ -5599,14 +5599,17 @@ for (;; pptr++)
|
||||
/* ===================================================================*/
|
||||
/* Deal with (*VERB)s. */
|
||||
|
||||
/* Check for open captures before ACCEPT and convert it to ASSERT_ACCEPT if
|
||||
in an assertion. In the first pass, just accumulate the length required;
|
||||
/* Check for open captures before ACCEPT and close those that are within
|
||||
the same assertion level, also converting ACCEPT to ASSERT_ACCEPT in an
|
||||
assertion. In the first pass, just accumulate the length required;
|
||||
otherwise hitting (*ACCEPT) inside many nested parentheses can cause
|
||||
workspace overflow. Do not set firstcu after *ACCEPT. */
|
||||
|
||||
case META_ACCEPT:
|
||||
cb->had_accept = TRUE;
|
||||
for (oc = cb->open_caps; oc != NULL; oc = oc->next)
|
||||
for (oc = cb->open_caps;
|
||||
oc != NULL && oc->assert_depth >= cb->assert_depth;
|
||||
oc = oc->next)
|
||||
{
|
||||
if (lengthptr != NULL)
|
||||
{
|
||||
@ -7132,7 +7135,7 @@ for (;; pptr++)
|
||||
later. */
|
||||
|
||||
HANDLE_SINGLE_REFERENCE:
|
||||
if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
|
||||
if (firstcuflags == REQ_UNSET) zerofirstcuflags = firstcuflags = REQ_NONE;
|
||||
*code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF;
|
||||
PUT2INC(code, 0, meta_arg);
|
||||
|
||||
@ -7483,6 +7486,7 @@ if (*code == OP_CBRA)
|
||||
capitem.number = capnumber;
|
||||
capitem.next = cb->open_caps;
|
||||
capitem.flag = FALSE;
|
||||
capitem.assert_depth = cb->assert_depth;
|
||||
cb->open_caps = &capitem;
|
||||
}
|
||||
|
||||
@ -8102,13 +8106,13 @@ REQ_NONE in the flags.
|
||||
Arguments:
|
||||
code points to start of compiled pattern
|
||||
flags points to the first code unit flags
|
||||
inassert TRUE if in an assertion
|
||||
inassert non-zero if in an assertion
|
||||
|
||||
Returns: the fixed first code unit, or 0 with REQ_NONE in flags
|
||||
*/
|
||||
|
||||
static uint32_t
|
||||
find_firstassertedcu(PCRE2_SPTR code, int32_t *flags, BOOL inassert)
|
||||
find_firstassertedcu(PCRE2_SPTR code, int32_t *flags, uint32_t inassert)
|
||||
{
|
||||
uint32_t c = 0;
|
||||
int cflags = REQ_NONE;
|
||||
@ -8135,7 +8139,7 @@ do {
|
||||
case OP_SCBRAPOS:
|
||||
case OP_ASSERT:
|
||||
case OP_ONCE:
|
||||
d = find_firstassertedcu(scode, &dflags, op == OP_ASSERT);
|
||||
d = find_firstassertedcu(scode, &dflags, inassert + ((op==OP_ASSERT)?1:0));
|
||||
if (dflags < 0)
|
||||
return 0;
|
||||
if (cflags < 0) { c = d; cflags = dflags; }
|
||||
@ -8150,7 +8154,7 @@ do {
|
||||
case OP_PLUS:
|
||||
case OP_MINPLUS:
|
||||
case OP_POSPLUS:
|
||||
if (!inassert) return 0;
|
||||
if (inassert == 0) return 0;
|
||||
if (cflags < 0) { c = scode[1]; cflags = 0; }
|
||||
else if (c != scode[1]) return 0;
|
||||
break;
|
||||
@ -8163,7 +8167,7 @@ do {
|
||||
case OP_PLUSI:
|
||||
case OP_MINPLUSI:
|
||||
case OP_POSPLUSI:
|
||||
if (!inassert) return 0;
|
||||
if (inassert == 0) return 0;
|
||||
if (cflags < 0) { c = scode[1]; cflags = REQ_CASELESS; }
|
||||
else if (c != scode[1]) return 0;
|
||||
break;
|
||||
@ -9481,6 +9485,7 @@ re->blocksize = re_blocksize;
|
||||
re->magic_number = MAGIC_NUMBER;
|
||||
re->compile_options = options;
|
||||
re->overall_options = cb.external_options;
|
||||
re->extra_options = ccontext->extra_options;
|
||||
re->flags = PCRE2_CODE_UNIT_WIDTH/8 | cb.external_flags | setflags;
|
||||
re->limit_heap = limit_heap;
|
||||
re->limit_match = limit_match;
|
||||
@ -9670,7 +9675,7 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
|
||||
actual literals that follow). */
|
||||
|
||||
if (firstcuflags < 0)
|
||||
firstcu = find_firstassertedcu(codestart, &firstcuflags, FALSE);
|
||||
firstcu = find_firstassertedcu(codestart, &firstcuflags, 0);
|
||||
|
||||
/* Save the data for a first code unit. */
|
||||
|
||||
|
34
src/3rdparty/pcre2/src/pcre2_config.c
vendored
34
src/3rdparty/pcre2/src/pcre2_config.c
vendored
@ -84,11 +84,13 @@ if (where == NULL) /* Requests a length */
|
||||
return PCRE2_ERROR_BADOPTION;
|
||||
|
||||
case PCRE2_CONFIG_BSR:
|
||||
case PCRE2_CONFIG_COMPILED_WIDTHS:
|
||||
case PCRE2_CONFIG_DEPTHLIMIT:
|
||||
case PCRE2_CONFIG_HEAPLIMIT:
|
||||
case PCRE2_CONFIG_JIT:
|
||||
case PCRE2_CONFIG_LINKSIZE:
|
||||
case PCRE2_CONFIG_MATCHLIMIT:
|
||||
case PCRE2_CONFIG_DEPTHLIMIT:
|
||||
case PCRE2_CONFIG_NEVER_BACKSLASH_C:
|
||||
case PCRE2_CONFIG_NEWLINE:
|
||||
case PCRE2_CONFIG_PARENSLIMIT:
|
||||
case PCRE2_CONFIG_STACKRECURSE: /* Obsolete */
|
||||
@ -117,6 +119,24 @@ switch (what)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PCRE2_CONFIG_COMPILED_WIDTHS:
|
||||
*((uint32_t *)where) = 0
|
||||
#ifdef SUPPORT_PCRE2_8
|
||||
+ 1
|
||||
#endif
|
||||
#ifdef SUPPORT_PCRE2_16
|
||||
+ 2
|
||||
#endif
|
||||
#ifdef SUPPORT_PCRE2_32
|
||||
+ 4
|
||||
#endif
|
||||
;
|
||||
break;
|
||||
|
||||
case PCRE2_CONFIG_DEPTHLIMIT:
|
||||
*((uint32_t *)where) = MATCH_LIMIT_DEPTH;
|
||||
break;
|
||||
|
||||
case PCRE2_CONFIG_HEAPLIMIT:
|
||||
*((uint32_t *)where) = HEAP_LIMIT;
|
||||
break;
|
||||
@ -148,14 +168,18 @@ switch (what)
|
||||
*((uint32_t *)where) = MATCH_LIMIT;
|
||||
break;
|
||||
|
||||
case PCRE2_CONFIG_DEPTHLIMIT:
|
||||
*((uint32_t *)where) = MATCH_LIMIT_DEPTH;
|
||||
break;
|
||||
|
||||
case PCRE2_CONFIG_NEWLINE:
|
||||
*((uint32_t *)where) = NEWLINE_DEFAULT;
|
||||
break;
|
||||
|
||||
case PCRE2_CONFIG_NEVER_BACKSLASH_C:
|
||||
#ifdef NEVER_BACKSLASH_C
|
||||
*((uint32_t *)where) = 1;
|
||||
#else
|
||||
*((uint32_t *)where) = 0;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PCRE2_CONFIG_PARENSLIMIT:
|
||||
*((uint32_t *)where) = PARENS_NEST_LIMIT;
|
||||
break;
|
||||
|
430
src/3rdparty/pcre2/src/pcre2_dfa_match.c
vendored
430
src/3rdparty/pcre2/src/pcre2_dfa_match.c
vendored
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2016-2017 University of Cambridge
|
||||
New API code Copyright (c) 2016-2018 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -293,6 +293,66 @@ typedef struct stateblock {
|
||||
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Process a callout *
|
||||
*************************************************/
|
||||
|
||||
/* This function is called to perform a callout.
|
||||
|
||||
Arguments:
|
||||
code current code pointer
|
||||
offsets points to current capture offsets
|
||||
current_subject start of current subject match
|
||||
ptr current position in subject
|
||||
mb the match block
|
||||
extracode extra code offset when called from condition
|
||||
lengthptr where to return the callout length
|
||||
|
||||
Returns: the return from the callout
|
||||
*/
|
||||
|
||||
static int
|
||||
do_callout(PCRE2_SPTR code, PCRE2_SIZE *offsets, PCRE2_SPTR current_subject,
|
||||
PCRE2_SPTR ptr, dfa_match_block *mb, PCRE2_SIZE extracode,
|
||||
PCRE2_SIZE *lengthptr)
|
||||
{
|
||||
pcre2_callout_block *cb = mb->cb;
|
||||
|
||||
*lengthptr = (code[extracode] == OP_CALLOUT)?
|
||||
(PCRE2_SIZE)PRIV(OP_lengths)[OP_CALLOUT] :
|
||||
(PCRE2_SIZE)GET(code, 1 + 2*LINK_SIZE + extracode);
|
||||
|
||||
if (mb->callout == NULL) return 0; /* No callout provided */
|
||||
|
||||
/* Fixed fields in the callout block are set once and for all at the start of
|
||||
matching. */
|
||||
|
||||
cb->offset_vector = offsets;
|
||||
cb->start_match = (PCRE2_SIZE)(current_subject - mb->start_subject);
|
||||
cb->current_position = (PCRE2_SIZE)(ptr - mb->start_subject);
|
||||
cb->pattern_position = GET(code, 1 + extracode);
|
||||
cb->next_item_length = GET(code, 1 + LINK_SIZE + extracode);
|
||||
|
||||
if (code[extracode] == OP_CALLOUT)
|
||||
{
|
||||
cb->callout_number = code[1 + 2*LINK_SIZE + extracode];
|
||||
cb->callout_string_offset = 0;
|
||||
cb->callout_string = NULL;
|
||||
cb->callout_string_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cb->callout_number = 0;
|
||||
cb->callout_string_offset = GET(code, 1 + 3*LINK_SIZE + extracode);
|
||||
cb->callout_string = code + (1 + 4*LINK_SIZE + extracode) + 1;
|
||||
cb->callout_string_length = *lengthptr - (1 + 4*LINK_SIZE) - 2;
|
||||
}
|
||||
|
||||
return (mb->callout)(cb, mb->callout_data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Match a Regular Expression - DFA engine *
|
||||
*************************************************/
|
||||
@ -448,7 +508,8 @@ if (*this_start_code == OP_ASSERTBACK || *this_start_code == OP_ASSERTBACK_NOT)
|
||||
{
|
||||
if (current_subject <= start_subject) break;
|
||||
current_subject--;
|
||||
ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--);
|
||||
ACROSSCHAR(current_subject > start_subject, current_subject,
|
||||
current_subject--);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1364,63 +1425,14 @@ for (;;)
|
||||
if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
|
||||
if (clen > 0)
|
||||
{
|
||||
uint32_t lgb, rgb;
|
||||
PCRE2_SPTR nptr = ptr + clen;
|
||||
int ncount = 0;
|
||||
if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
|
||||
{
|
||||
active_count--; /* Remove non-match possibility */
|
||||
next_active_state--;
|
||||
}
|
||||
lgb = UCD_GRAPHBREAK(c);
|
||||
while (nptr < end_subject)
|
||||
{
|
||||
dlen = 1;
|
||||
if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
|
||||
rgb = UCD_GRAPHBREAK(d);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if
|
||||
there are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator &&
|
||||
rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = nptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) BACKCHAR(bptr);
|
||||
#endif
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > mb->start_subject)
|
||||
{
|
||||
bptr--;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(d, bptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
d = *bptr;
|
||||
if (UCD_GRAPHBREAK(d) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
ncount++;
|
||||
nptr += dlen;
|
||||
}
|
||||
(void)PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf,
|
||||
&ncount);
|
||||
count++;
|
||||
ADD_NEW_DATA(-state_offset, count, ncount);
|
||||
}
|
||||
@ -1663,8 +1675,6 @@ for (;;)
|
||||
ADD_ACTIVE(state_offset + 2, 0);
|
||||
if (clen > 0)
|
||||
{
|
||||
uint32_t lgb, rgb;
|
||||
PCRE2_SPTR nptr = ptr + clen;
|
||||
int ncount = 0;
|
||||
if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
|
||||
codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
|
||||
@ -1672,55 +1682,8 @@ for (;;)
|
||||
active_count--; /* Remove non-match possibility */
|
||||
next_active_state--;
|
||||
}
|
||||
lgb = UCD_GRAPHBREAK(c);
|
||||
while (nptr < end_subject)
|
||||
{
|
||||
dlen = 1;
|
||||
if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
|
||||
rgb = UCD_GRAPHBREAK(d);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if
|
||||
there are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator &&
|
||||
rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = nptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) BACKCHAR(bptr);
|
||||
#endif
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > mb->start_subject)
|
||||
{
|
||||
bptr--;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(d, bptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
d = *bptr;
|
||||
if (UCD_GRAPHBREAK(d) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
ncount++;
|
||||
nptr += dlen;
|
||||
}
|
||||
(void)PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf,
|
||||
&ncount);
|
||||
ADD_NEW_DATA(-(state_offset + count), 0, ncount);
|
||||
}
|
||||
break;
|
||||
@ -1973,63 +1936,15 @@ for (;;)
|
||||
count = current_state->count; /* Number already matched */
|
||||
if (clen > 0)
|
||||
{
|
||||
uint32_t lgb, rgb;
|
||||
PCRE2_SPTR nptr = ptr + clen;
|
||||
PCRE2_SPTR nptr;
|
||||
int ncount = 0;
|
||||
if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
|
||||
{
|
||||
active_count--; /* Remove non-match possibility */
|
||||
next_active_state--;
|
||||
}
|
||||
lgb = UCD_GRAPHBREAK(c);
|
||||
while (nptr < end_subject)
|
||||
{
|
||||
dlen = 1;
|
||||
if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
|
||||
rgb = UCD_GRAPHBREAK(d);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if
|
||||
there are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator &&
|
||||
rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = nptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) BACKCHAR(bptr);
|
||||
#endif
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > mb->start_subject)
|
||||
{
|
||||
bptr--;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(d, bptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
d = *bptr;
|
||||
if (UCD_GRAPHBREAK(d) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
ncount++;
|
||||
nptr += dlen;
|
||||
}
|
||||
nptr = PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf,
|
||||
&ncount);
|
||||
if (nptr >= end_subject && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
|
||||
reset_could_continue = TRUE;
|
||||
if (++count >= (int)GET2(code, 1))
|
||||
@ -2206,58 +2121,9 @@ for (;;)
|
||||
case OP_EXTUNI:
|
||||
if (clen > 0)
|
||||
{
|
||||
uint32_t lgb, rgb;
|
||||
PCRE2_SPTR nptr = ptr + clen;
|
||||
int ncount = 0;
|
||||
lgb = UCD_GRAPHBREAK(c);
|
||||
while (nptr < end_subject)
|
||||
{
|
||||
dlen = 1;
|
||||
if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
|
||||
rgb = UCD_GRAPHBREAK(d);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if
|
||||
there are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator &&
|
||||
rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = nptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) BACKCHAR(bptr);
|
||||
#endif
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > mb->start_subject)
|
||||
{
|
||||
bptr--;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(d, bptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
d = *bptr;
|
||||
if (UCD_GRAPHBREAK(d) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
ncount++;
|
||||
nptr += dlen;
|
||||
}
|
||||
PCRE2_SPTR nptr = PRIV(extuni)(c, ptr + clen, mb->start_subject,
|
||||
end_subject, utf, &ncount);
|
||||
if (nptr >= end_subject && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
|
||||
reset_could_continue = TRUE;
|
||||
ADD_NEW_DATA(-(state_offset + 1), 0, ncount);
|
||||
@ -2371,7 +2237,7 @@ for (;;)
|
||||
case OP_NOTI:
|
||||
if (clen > 0)
|
||||
{
|
||||
unsigned int otherd;
|
||||
uint32_t otherd;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf && d >= 128)
|
||||
otherd = UCD_OTHERCASE(d);
|
||||
@ -2761,45 +2627,10 @@ for (;;)
|
||||
if (code[LINK_SIZE + 1] == OP_CALLOUT
|
||||
|| code[LINK_SIZE + 1] == OP_CALLOUT_STR)
|
||||
{
|
||||
PCRE2_SIZE callout_length = (code[LINK_SIZE + 1] == OP_CALLOUT)?
|
||||
(PCRE2_SIZE)PRIV(OP_lengths)[OP_CALLOUT] :
|
||||
(PCRE2_SIZE)GET(code, 2 + 3*LINK_SIZE);
|
||||
|
||||
rrc = 0;
|
||||
if (mb->callout != NULL)
|
||||
{
|
||||
pcre2_callout_block cb;
|
||||
cb.version = 1;
|
||||
cb.capture_top = 1;
|
||||
cb.capture_last = 0;
|
||||
cb.offset_vector = offsets;
|
||||
cb.mark = NULL; /* No (*MARK) support */
|
||||
cb.subject = start_subject;
|
||||
cb.subject_length = (PCRE2_SIZE)(end_subject - start_subject);
|
||||
cb.start_match = (PCRE2_SIZE)(current_subject - start_subject);
|
||||
cb.current_position = (PCRE2_SIZE)(ptr - start_subject);
|
||||
cb.pattern_position = GET(code, LINK_SIZE + 2);
|
||||
cb.next_item_length = GET(code, LINK_SIZE + 2 + LINK_SIZE);
|
||||
|
||||
if (code[LINK_SIZE + 1] == OP_CALLOUT)
|
||||
{
|
||||
cb.callout_number = code[2 + 3*LINK_SIZE];
|
||||
cb.callout_string_offset = 0;
|
||||
cb.callout_string = NULL;
|
||||
cb.callout_string_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cb.callout_number = 0;
|
||||
cb.callout_string_offset = GET(code, 2 + 4*LINK_SIZE);
|
||||
cb.callout_string = code + (2 + 5*LINK_SIZE) + 1;
|
||||
cb.callout_string_length =
|
||||
callout_length - (1 + 4*LINK_SIZE) - 2;
|
||||
}
|
||||
|
||||
if ((rrc = (mb->callout)(&cb, mb->callout_data)) < 0)
|
||||
return rrc; /* Abandon */
|
||||
}
|
||||
PCRE2_SIZE callout_length;
|
||||
rrc = do_callout(code, offsets, current_subject, ptr, mb,
|
||||
1 + LINK_SIZE, &callout_length);
|
||||
if (rrc < 0) return rrc; /* Abandon */
|
||||
if (rrc > 0) break; /* Fail this thread */
|
||||
code += callout_length; /* Skip callout data */
|
||||
}
|
||||
@ -3131,44 +2962,10 @@ for (;;)
|
||||
case OP_CALLOUT:
|
||||
case OP_CALLOUT_STR:
|
||||
{
|
||||
unsigned int callout_length = (*code == OP_CALLOUT)
|
||||
? PRIV(OP_lengths)[OP_CALLOUT] : GET(code, 1 + 2*LINK_SIZE);
|
||||
rrc = 0;
|
||||
|
||||
if (mb->callout != NULL)
|
||||
{
|
||||
pcre2_callout_block cb;
|
||||
cb.version = 1;
|
||||
cb.capture_top = 1;
|
||||
cb.capture_last = 0;
|
||||
cb.offset_vector = offsets;
|
||||
cb.mark = NULL; /* No (*MARK) support */
|
||||
cb.subject = start_subject;
|
||||
cb.subject_length = (PCRE2_SIZE)(end_subject - start_subject);
|
||||
cb.start_match = (PCRE2_SIZE)(current_subject - start_subject);
|
||||
cb.current_position = (PCRE2_SIZE)(ptr - start_subject);
|
||||
cb.pattern_position = GET(code, 1);
|
||||
cb.next_item_length = GET(code, 1 + LINK_SIZE);
|
||||
|
||||
if (*code == OP_CALLOUT)
|
||||
{
|
||||
cb.callout_number = code[1 + 2*LINK_SIZE];
|
||||
cb.callout_string_offset = 0;
|
||||
cb.callout_string = NULL;
|
||||
cb.callout_string_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cb.callout_number = 0;
|
||||
cb.callout_string_offset = GET(code, 1 + 3*LINK_SIZE);
|
||||
cb.callout_string = code + (1 + 4*LINK_SIZE) + 1;
|
||||
cb.callout_string_length =
|
||||
callout_length - (1 + 4*LINK_SIZE) - 2;
|
||||
}
|
||||
|
||||
if ((rrc = (mb->callout)(&cb, mb->callout_data)) < 0)
|
||||
return rrc; /* Abandon */
|
||||
}
|
||||
PCRE2_SIZE callout_length;
|
||||
rrc = do_callout(code, offsets, current_subject, ptr, mb, 0,
|
||||
&callout_length);
|
||||
if (rrc < 0) return rrc; /* Abandon */
|
||||
if (rrc == 0)
|
||||
{ ADD_ACTIVE(state_offset + (int)callout_length, 0); }
|
||||
}
|
||||
@ -3287,6 +3084,7 @@ const uint8_t *start_bits = NULL;
|
||||
/* We need to have mb pointing to a match block, because the IS_NEWLINE macro
|
||||
is used below, and it expects NLBLOCK to be defined as a pointer. */
|
||||
|
||||
pcre2_callout_block cb;
|
||||
dfa_match_block actual_match_block;
|
||||
dfa_match_block *mb = &actual_match_block;
|
||||
|
||||
@ -3364,9 +3162,21 @@ startline = (re->flags & PCRE2_STARTLINE) != 0;
|
||||
firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;
|
||||
bumpalong_limit = end_subject;
|
||||
|
||||
/* Get data from the match context, if present, and fill in the fields in the
|
||||
match block. It is an error to set an offset limit without setting the flag at
|
||||
compile time. */
|
||||
/* Initialize and set up the fixed fields in the callout block, with a pointer
|
||||
in the match block. */
|
||||
|
||||
mb->cb = &cb;
|
||||
cb.version = 2;
|
||||
cb.subject = subject;
|
||||
cb.subject_length = (PCRE2_SIZE)(end_subject - subject);
|
||||
cb.callout_flags = 0;
|
||||
cb.capture_top = 1; /* No capture support */
|
||||
cb.capture_last = 0;
|
||||
cb.mark = NULL; /* No (*MARK) support */
|
||||
|
||||
/* Get data from the match context, if present, and fill in the remaining
|
||||
fields in the match block. It is an error to set an offset limit without
|
||||
setting the flag at compile time. */
|
||||
|
||||
if (mcontext == NULL)
|
||||
{
|
||||
@ -3554,13 +3364,13 @@ for (;;)
|
||||
if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 &&
|
||||
(options & PCRE2_DFA_RESTART) == 0)
|
||||
{
|
||||
PCRE2_SPTR save_end_subject = end_subject;
|
||||
|
||||
/* If firstline is TRUE, the start of the match is constrained to the first
|
||||
line of a multiline string. That is, the match must be before or at the
|
||||
first newline. Implement this by temporarily adjusting end_subject so that
|
||||
we stop the optimization scans for a first code unit at a newline. If the
|
||||
match fails at the newline, later code breaks this loop. */
|
||||
first newline following the start of matching. Temporarily adjust
|
||||
end_subject so that we stop the optimization scans for a first code unit
|
||||
immediately after the first character of a newline (the first code unit can
|
||||
legitimately be a newline). If the match fails at the newline, later code
|
||||
breaks this loop. */
|
||||
|
||||
if (firstline)
|
||||
{
|
||||
@ -3568,15 +3378,15 @@ for (;;)
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
while (t < mb->end_subject && !IS_NEWLINE(t))
|
||||
while (t < end_subject && !IS_NEWLINE(t))
|
||||
{
|
||||
t++;
|
||||
ACROSSCHAR(t < end_subject, *t, t++);
|
||||
ACROSSCHAR(t < end_subject, t, t++);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
while (t < mb->end_subject && !IS_NEWLINE(t)) t++;
|
||||
while (t < end_subject && !IS_NEWLINE(t)) t++;
|
||||
end_subject = t;
|
||||
}
|
||||
|
||||
@ -3648,14 +3458,18 @@ for (;;)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If we can't find the required code unit, break the bumpalong loop,
|
||||
to force a match failure, except when doing partial matching, when we
|
||||
let the next cycle run at the end of the subject. To see why, consider
|
||||
the pattern /(?<=abc)def/, which partially matches "abc", even though
|
||||
the string does not contain the starting character "d". */
|
||||
/* If we can't find the required code unit, having reached the true end
|
||||
of the subject, break the bumpalong loop, to force a match failure,
|
||||
except when doing partial matching, when we let the next cycle run at
|
||||
the end of the subject. To see why, consider the pattern /(?<=abc)def/,
|
||||
which partially matches "abc", even though the string does not contain
|
||||
the starting character "d". If we have not reached the true end of the
|
||||
subject (PCRE2_FIRSTLINE caused end_subject to be temporarily modified)
|
||||
we also let the cycle run, because the matching string is legitimately
|
||||
allowed to start with the first code unit of a newline. */
|
||||
|
||||
if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0 &&
|
||||
start_match >= end_subject)
|
||||
start_match >= mb->end_subject)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3672,8 +3486,7 @@ for (;;)
|
||||
while (start_match < end_subject && !WAS_NEWLINE(start_match))
|
||||
{
|
||||
start_match++;
|
||||
ACROSSCHAR(start_match < end_subject, *start_match,
|
||||
start_match++);
|
||||
ACROSSCHAR(start_match < end_subject, start_match, start_match++);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -3709,12 +3522,18 @@ for (;;)
|
||||
if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
|
||||
start_match++;
|
||||
}
|
||||
|
||||
/* See comment above in first_cu checking about the next line. */
|
||||
|
||||
if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0 &&
|
||||
start_match >= mb->end_subject)
|
||||
break;
|
||||
}
|
||||
} /* End of first code unit handling */
|
||||
|
||||
/* Restore fudged end_subject */
|
||||
|
||||
end_subject = save_end_subject;
|
||||
end_subject = mb->end_subject;
|
||||
|
||||
/* The following two optimizations are disabled for partial matching. */
|
||||
|
||||
@ -3829,8 +3648,7 @@ for (;;)
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
ACROSSCHAR(start_match < end_subject, *start_match,
|
||||
start_match++);
|
||||
ACROSSCHAR(start_match < end_subject, start_match, start_match++);
|
||||
}
|
||||
#endif
|
||||
if (start_match > end_subject) break;
|
||||
|
148
src/3rdparty/pcre2/src/pcre2_extuni.c
vendored
Normal file
148
src/3rdparty/pcre2/src/pcre2_extuni.c
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/*************************************************
|
||||
* Perl-Compatible Regular Expressions *
|
||||
*************************************************/
|
||||
|
||||
/* PCRE is a library of functions to support regular expressions whose syntax
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2016-2018 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* This module contains an internal function that is used to match a Unicode
|
||||
extended grapheme sequence. It is used by both pcre2_match() and
|
||||
pcre2_def_match(). However, it is called only when Unicode support is being
|
||||
compiled. Nevertheless, we provide a dummy function when there is no Unicode
|
||||
support, because some compilers do not like functionless source files. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "pcre2_internal.h"
|
||||
|
||||
|
||||
/* Dummy function */
|
||||
|
||||
#ifndef SUPPORT_UNICODE
|
||||
PCRE2_SPTR
|
||||
PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject,
|
||||
PCRE2_SPTR end_subject, BOOL utf, int *xcount)
|
||||
{
|
||||
(void)c;
|
||||
(void)eptr;
|
||||
(void)start_subject;
|
||||
(void)end_subject;
|
||||
(void)utf;
|
||||
(void)xcount;
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Match an extended grapheme sequence *
|
||||
*************************************************/
|
||||
|
||||
/*
|
||||
Arguments:
|
||||
c the first character
|
||||
eptr pointer to next character
|
||||
start_subject pointer to start of subject
|
||||
end_subject pointer to end of subject
|
||||
utf TRUE if in UTF mode
|
||||
xcount pointer to count of additional characters,
|
||||
or NULL if count not needed
|
||||
|
||||
Returns: pointer after the end of the sequence
|
||||
*/
|
||||
|
||||
PCRE2_SPTR
|
||||
PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject,
|
||||
PCRE2_SPTR end_subject, BOOL utf, int *xcount)
|
||||
{
|
||||
int lgb = UCD_GRAPHBREAK(c);
|
||||
|
||||
while (eptr < end_subject)
|
||||
{
|
||||
int rgb;
|
||||
int len = 1;
|
||||
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
|
||||
rgb = UCD_GRAPHBREAK(c);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if there
|
||||
are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = eptr - 1;
|
||||
if (utf) BACKCHAR(bptr);
|
||||
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > start_subject)
|
||||
{
|
||||
bptr--;
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(c, bptr);
|
||||
}
|
||||
else
|
||||
c = *bptr;
|
||||
if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
eptr += len;
|
||||
if (xcount != NULL) *xcount += 1;
|
||||
}
|
||||
|
||||
return eptr;
|
||||
}
|
||||
|
||||
#endif /* SUPPORT_UNICODE */
|
||||
|
||||
/* End of pcre2_extuni.c */
|
8
src/3rdparty/pcre2/src/pcre2_internal.h
vendored
8
src/3rdparty/pcre2/src/pcre2_internal.h
vendored
@ -38,6 +38,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PCRE2_INTERNAL_H_IDEMPOTENT_GUARD
|
||||
#define PCRE2_INTERNAL_H_IDEMPOTENT_GUARD
|
||||
|
||||
/* We do not support both EBCDIC and Unicode at the same time. The "configure"
|
||||
script prevents both being selected, but not everybody uses "configure". EBCDIC
|
||||
is only supported for the 8-bit library, but the check for this has to be later
|
||||
@ -1767,6 +1770,7 @@ typedef struct open_capitem {
|
||||
struct open_capitem *next; /* Chain link */
|
||||
uint16_t number; /* Capture number */
|
||||
uint16_t flag; /* Set TRUE if recursive back ref */
|
||||
uint16_t assert_depth; /* Assertion depth when opened */
|
||||
} open_capitem;
|
||||
|
||||
/* Layout of the UCP type table that translates property names into types and
|
||||
@ -1926,6 +1930,7 @@ is available. */
|
||||
|
||||
#define _pcre2_auto_possessify PCRE2_SUFFIX(_pcre2_auto_possessify_)
|
||||
#define _pcre2_check_escape PCRE2_SUFFIX(_pcre2_check_escape_)
|
||||
#define _pcre2_extuni PCRE2_SUFFIX(_pcre2_extuni_)
|
||||
#define _pcre2_find_bracket PCRE2_SUFFIX(_pcre2_find_bracket_)
|
||||
#define _pcre2_is_newline PCRE2_SUFFIX(_pcre2_is_newline_)
|
||||
#define _pcre2_jit_free_rodata PCRE2_SUFFIX(_pcre2_jit_free_rodata_)
|
||||
@ -1949,6 +1954,8 @@ extern int _pcre2_auto_possessify(PCRE2_UCHAR *, BOOL,
|
||||
const compile_block *);
|
||||
extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *,
|
||||
int *, uint32_t, BOOL, compile_block *);
|
||||
extern PCRE2_SPTR _pcre2_extuni(uint32_t, PCRE2_SPTR, PCRE2_SPTR, PCRE2_SPTR,
|
||||
BOOL, int *);
|
||||
extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int);
|
||||
extern BOOL _pcre2_is_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,
|
||||
uint32_t *, BOOL);
|
||||
@ -1970,5 +1977,6 @@ extern BOOL _pcre2_was_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,
|
||||
uint32_t *, BOOL);
|
||||
extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, BOOL);
|
||||
#endif /* PCRE2_CODE_UNIT_WIDTH */
|
||||
#endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */
|
||||
|
||||
/* End of pcre2_internal.h */
|
||||
|
31
src/3rdparty/pcre2/src/pcre2_intmodedep.h
vendored
31
src/3rdparty/pcre2/src/pcre2_intmodedep.h
vendored
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2016-2017 University of Cambridge
|
||||
New API code Copyright (c) 2016-2018 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -351,7 +351,7 @@ because almost all calls are already within a block of UTF-8 only code. */
|
||||
|
||||
/* Same as above, but it allows a fully customizable form. */
|
||||
#define ACROSSCHAR(condition, eptr, action) \
|
||||
while((condition) && ((eptr) & 0xc0u) == 0x80u) action
|
||||
while((condition) && ((*eptr) & 0xc0u) == 0x80u) action
|
||||
|
||||
/* Deposit a character into memory, returning the number of code units. */
|
||||
|
||||
@ -457,7 +457,7 @@ code. */
|
||||
|
||||
/* Same as above, but it allows a fully customizable form. */
|
||||
#define ACROSSCHAR(condition, eptr, action) \
|
||||
if ((condition) && ((eptr) & 0xfc00u) == 0xdc00u) action
|
||||
if ((condition) && ((*eptr) & 0xfc00u) == 0xdc00u) action
|
||||
|
||||
/* Deposit a character into memory, returning the number of code units. */
|
||||
|
||||
@ -623,6 +623,7 @@ typedef struct pcre2_real_code {
|
||||
uint32_t magic_number; /* Paranoid and endianness check */
|
||||
uint32_t compile_options; /* Options passed to pcre2_compile() */
|
||||
uint32_t overall_options; /* Options after processing the pattern */
|
||||
uint32_t extra_options; /* Taken from compile_context */
|
||||
uint32_t flags; /* Various state flags */
|
||||
uint32_t limit_heap; /* Limit set in the pattern */
|
||||
uint32_t limit_match; /* Limit set in the pattern */
|
||||
@ -639,11 +640,13 @@ typedef struct pcre2_real_code {
|
||||
uint16_t name_count; /* Number of name entries in the table */
|
||||
} pcre2_real_code;
|
||||
|
||||
/* The real match data structure. Define ovector large so that array bound
|
||||
checkers don't grumble. Memory for this structure is obtained by calling
|
||||
pcre2_match_data_create(), which sets the size as the offset of ovector plus
|
||||
pairs of elements for each capturing group. (See also the heapframe structure
|
||||
below.) */
|
||||
/* The real match data structure. Define ovector as large as it can ever
|
||||
actually be so that array bound checkers don't grumble. Memory for this
|
||||
structure is obtained by calling pcre2_match_data_create(), which sets the size
|
||||
as the offset of ovector plus a pair of elements for each capturable string, so
|
||||
the size varies from call to call. As the maximum number of capturing
|
||||
subpatterns is 65535 we must allow for 65536 strings to include the overall
|
||||
match. (See also the heapframe structure below.) */
|
||||
|
||||
typedef struct pcre2_real_match_data {
|
||||
pcre2_memctl memctl;
|
||||
@ -656,7 +659,7 @@ typedef struct pcre2_real_match_data {
|
||||
uint16_t matchedby; /* Type of match (normal, JIT, DFA) */
|
||||
uint16_t oveccount; /* Number of pairs */
|
||||
int rc; /* The return code from the match */
|
||||
PCRE2_SIZE ovector[10000];/* The first field */
|
||||
PCRE2_SIZE ovector[131072]; /* Must be last in the structure */
|
||||
} pcre2_real_match_data;
|
||||
|
||||
|
||||
@ -723,6 +726,8 @@ typedef struct compile_block {
|
||||
PCRE2_SIZE erroroffset; /* Offset of error in pattern */
|
||||
uint16_t names_found; /* Number of entries so far */
|
||||
uint16_t name_entry_size; /* Size of each entry */
|
||||
uint16_t parens_depth; /* Depth of nested parentheses */
|
||||
uint16_t assert_depth; /* Depth of nested assertions */
|
||||
open_capitem *open_caps; /* Chain of open capture items */
|
||||
named_group *named_groups; /* Points to vector in pre-compile */
|
||||
uint32_t named_group_list_size; /* Number of entries in the list */
|
||||
@ -741,8 +746,6 @@ typedef struct compile_block {
|
||||
uint32_t class_range_end; /* Overall class range end */
|
||||
PCRE2_UCHAR nl[4]; /* Newline string when fixed length */
|
||||
int max_lookbehind; /* Maximum lookbehind (characters) */
|
||||
int parens_depth; /* Depth of nested parentheses */
|
||||
int assert_depth; /* Depth of nested assertions */
|
||||
int req_varyopt; /* "After variable item" flag for reqbyte */
|
||||
BOOL had_accept; /* (*ACCEPT) encountered */
|
||||
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
|
||||
@ -803,7 +806,7 @@ typedef struct heapframe {
|
||||
runtime array bound checks don't catch references to it. However, for any
|
||||
specific call to pcre2_match() the memory allocated for each frame structure
|
||||
allows for exactly the right size ovector for the number of capturing
|
||||
parentheses. */
|
||||
parentheses. (See also the comment for pcre2_real_match_data above.) */
|
||||
|
||||
PCRE2_SPTR eptr; /* MUST BE FIRST */
|
||||
PCRE2_SPTR start_match; /* Can be adjusted by \K */
|
||||
@ -812,7 +815,7 @@ typedef struct heapframe {
|
||||
uint32_t capture_last; /* Most recent capture */
|
||||
PCRE2_SIZE last_group_offset; /* Saved offset to most recent group frame */
|
||||
PCRE2_SIZE offset_top; /* Offset after highest capture */
|
||||
PCRE2_SIZE ovector[10000]; /* Must be last in the structure */
|
||||
PCRE2_SIZE ovector[131072]; /* Must be last in the structure */
|
||||
} heapframe;
|
||||
|
||||
typedef char check_heapframe_size[
|
||||
@ -861,6 +864,7 @@ typedef struct match_block {
|
||||
uint32_t nltype; /* Newline type */
|
||||
uint32_t nllen; /* Newline string length */
|
||||
PCRE2_UCHAR nl[4]; /* Newline string when fixed */
|
||||
pcre2_callout_block *cb; /* Points to a callout block */
|
||||
void *callout_data; /* To pass back to callouts */
|
||||
int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */
|
||||
} match_block;
|
||||
@ -886,6 +890,7 @@ typedef struct dfa_match_block {
|
||||
uint32_t nllen; /* Newline string length */
|
||||
PCRE2_UCHAR nl[4]; /* Newline string when fixed */
|
||||
uint16_t bsr_convention; /* \R interpretation */
|
||||
pcre2_callout_block *cb; /* Points to a callout block */
|
||||
void *callout_data; /* To pass back to callouts */
|
||||
int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */
|
||||
dfa_recursion_info *recursive; /* Linked list of recursion data */
|
||||
|
590
src/3rdparty/pcre2/src/pcre2_jit_compile.c
vendored
590
src/3rdparty/pcre2/src/pcre2_jit_compile.c
vendored
@ -228,7 +228,7 @@ enum control_types {
|
||||
type_then_trap = 1
|
||||
};
|
||||
|
||||
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
|
||||
typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args);
|
||||
|
||||
/* The following structure is the key data type for the recursive
|
||||
code generator. It is allocated by compile_matchingpath, and contains
|
||||
@ -527,12 +527,27 @@ typedef struct compare_context {
|
||||
/* Used for accessing the elements of the stack. */
|
||||
#define STACK(i) ((i) * (int)sizeof(sljit_sw))
|
||||
|
||||
#ifdef SLJIT_PREF_SHIFT_REG
|
||||
#if SLJIT_PREF_SHIFT_REG == SLJIT_R2
|
||||
/* Nothing. */
|
||||
#elif SLJIT_PREF_SHIFT_REG == SLJIT_R3
|
||||
#define SHIFT_REG_IS_R3
|
||||
#else
|
||||
#error "Unsupported shift register"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define TMP1 SLJIT_R0
|
||||
#ifdef SHIFT_REG_IS_R3
|
||||
#define TMP2 SLJIT_R3
|
||||
#define TMP3 SLJIT_R2
|
||||
#else
|
||||
#define TMP2 SLJIT_R2
|
||||
#define TMP3 SLJIT_R3
|
||||
#define STR_PTR SLJIT_S0
|
||||
#define STR_END SLJIT_S1
|
||||
#define STACK_TOP SLJIT_R1
|
||||
#endif
|
||||
#define STR_PTR SLJIT_R1
|
||||
#define STR_END SLJIT_S0
|
||||
#define STACK_TOP SLJIT_S1
|
||||
#define STACK_LIMIT SLJIT_S2
|
||||
#define COUNT_MATCH SLJIT_S3
|
||||
#define ARGUMENTS SLJIT_S4
|
||||
@ -558,16 +573,13 @@ the start pointers when the end of the capturing group has not yet reached. */
|
||||
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 8
|
||||
#define MOV_UCHAR SLJIT_MOV_U8
|
||||
#define MOVU_UCHAR SLJIT_MOVU_U8
|
||||
#define IN_UCHARS(x) (x)
|
||||
#elif PCRE2_CODE_UNIT_WIDTH == 16
|
||||
#define MOV_UCHAR SLJIT_MOV_U16
|
||||
#define MOVU_UCHAR SLJIT_MOVU_U16
|
||||
#define UCHAR_SHIFT (1)
|
||||
#define IN_UCHARS(x) ((x) * 2)
|
||||
#elif PCRE2_CODE_UNIT_WIDTH == 32
|
||||
#define MOV_UCHAR SLJIT_MOV_U32
|
||||
#define MOVU_UCHAR SLJIT_MOVU_U32
|
||||
#define UCHAR_SHIFT (2)
|
||||
#define IN_UCHARS(x) ((x) * 4)
|
||||
#else
|
||||
@ -2697,12 +2709,25 @@ if (length < 8)
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS)
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
|
||||
loop = LABEL();
|
||||
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);
|
||||
OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2735,12 +2760,25 @@ if (length < 8)
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS)
|
||||
{
|
||||
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
|
||||
loop = LABEL();
|
||||
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);
|
||||
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
}
|
||||
}
|
||||
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
|
||||
@ -2750,10 +2788,10 @@ if (common->control_head_ptr != 0)
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end));
|
||||
}
|
||||
|
||||
static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, PCRE2_SPTR skip_arg)
|
||||
static sljit_sw SLJIT_FUNC do_search_mark(sljit_sw *current, PCRE2_SPTR skip_arg)
|
||||
{
|
||||
while (current != NULL)
|
||||
{
|
||||
@ -2774,13 +2812,14 @@ while (current != NULL)
|
||||
SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]);
|
||||
current = (sljit_sw*)current[0];
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
|
||||
{
|
||||
DEFINE_COMPILER;
|
||||
struct sljit_label *loop;
|
||||
BOOL has_pre;
|
||||
|
||||
/* At this point we can freely use all registers. */
|
||||
OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
|
||||
@ -2797,36 +2836,62 @@ if (common->mark_ptr != 0)
|
||||
OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),
|
||||
SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
|
||||
|
||||
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START);
|
||||
has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;
|
||||
|
||||
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));
|
||||
OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin));
|
||||
|
||||
loop = LABEL();
|
||||
OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);
|
||||
OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
|
||||
|
||||
if (has_pre)
|
||||
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));
|
||||
else
|
||||
{
|
||||
OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0);
|
||||
OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
|
||||
}
|
||||
|
||||
OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(PCRE2_SIZE));
|
||||
OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0);
|
||||
/* Copy the integer value to the output buffer */
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
|
||||
OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(sizeof(PCRE2_SIZE) == 4 || sizeof(PCRE2_SIZE) == 8);
|
||||
if (sizeof(PCRE2_SIZE) == 4)
|
||||
OP1(SLJIT_MOVU_U32, SLJIT_MEM1(SLJIT_R2), sizeof(PCRE2_SIZE), SLJIT_S1, 0);
|
||||
else
|
||||
OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R2), sizeof(PCRE2_SIZE), SLJIT_S1, 0);
|
||||
OP1(((sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV), SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0);
|
||||
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
|
||||
/* Calculate the return value, which is the maximum ovector value. */
|
||||
if (topbracket > 1)
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
|
||||
if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS)
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
|
||||
|
||||
/* OVECTOR(0) is never equal to SLJIT_S2. */
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOVU, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw)));
|
||||
OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
|
||||
CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);
|
||||
/* OVECTOR(0) is never equal to SLJIT_S2. */
|
||||
loop = LABEL();
|
||||
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw)));
|
||||
OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
|
||||
CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
|
||||
|
||||
/* OVECTOR(0) is never equal to SLJIT_S2. */
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0);
|
||||
OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
|
||||
CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
|
||||
@ -2837,7 +2902,7 @@ static SLJIT_INLINE void return_with_partial_match(compiler_common *common, stru
|
||||
DEFINE_COMPILER;
|
||||
sljit_s32 mov_opcode;
|
||||
|
||||
SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S1, str_end_must_be_saved_reg2);
|
||||
SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S0, str_end_must_be_saved_reg0);
|
||||
SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0
|
||||
&& (common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start != 0 : common->hit_start == 0));
|
||||
|
||||
@ -2847,19 +2912,19 @@ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP),
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_PARTIAL);
|
||||
|
||||
/* Store match begin and end. */
|
||||
OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin));
|
||||
OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin));
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, match_data));
|
||||
|
||||
mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;
|
||||
|
||||
OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S0, 0);
|
||||
OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S1, 0);
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
|
||||
OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);
|
||||
#endif
|
||||
OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector), SLJIT_R2, 0);
|
||||
|
||||
OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_S0, 0);
|
||||
OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_S1, 0);
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
|
||||
OP2(SLJIT_ASHR, STR_END, 0, STR_END, 0, SLJIT_IMM, UCHAR_SHIFT);
|
||||
#endif
|
||||
@ -4351,7 +4416,6 @@ struct sljit_jump *quit;
|
||||
struct sljit_jump *partial_quit[2];
|
||||
sljit_u8 instruction[8];
|
||||
sljit_s32 tmp1_ind = sljit_get_register_index(TMP1);
|
||||
// sljit_s32 tmp2_ind = sljit_get_register_index(TMP2);
|
||||
sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR);
|
||||
sljit_s32 data_ind = 0;
|
||||
sljit_s32 tmp_ind = 1;
|
||||
@ -4376,8 +4440,6 @@ if (common->mode == PCRE2_JIT_COMPLETE)
|
||||
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
|
||||
|
||||
// SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1);
|
||||
|
||||
SLJIT_ASSERT(tmp1_ind < 8);
|
||||
|
||||
/* MOVD xmm, r/m32 */
|
||||
@ -5976,93 +6038,190 @@ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
|
||||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
|
||||
}
|
||||
|
||||
#define CHAR1 STR_END
|
||||
#define CHAR2 STACK_TOP
|
||||
|
||||
static void do_casefulcmp(compiler_common *common)
|
||||
{
|
||||
DEFINE_COMPILER;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_label *label;
|
||||
int char1_reg;
|
||||
int char2_reg;
|
||||
|
||||
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
|
||||
if (sljit_get_register_index(TMP3) < 0)
|
||||
{
|
||||
char1_reg = STR_END;
|
||||
char2_reg = STACK_TOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
char1_reg = TMP3;
|
||||
char2_reg = RETURN_ADDR;
|
||||
}
|
||||
|
||||
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
|
||||
OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR2, 0);
|
||||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
label = LABEL();
|
||||
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
if (char1_reg == STR_END)
|
||||
{
|
||||
OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0);
|
||||
OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0);
|
||||
}
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
|
||||
OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
|
||||
if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
|
||||
{
|
||||
label = LABEL();
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
}
|
||||
else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
|
||||
{
|
||||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
label = LABEL();
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
label = LABEL();
|
||||
OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);
|
||||
OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);
|
||||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
}
|
||||
|
||||
if (char1_reg == STR_END)
|
||||
{
|
||||
OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0);
|
||||
OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0);
|
||||
}
|
||||
|
||||
sljit_emit_fast_return(compiler, TMP1, 0);
|
||||
}
|
||||
|
||||
#define LCC_TABLE STACK_LIMIT
|
||||
|
||||
static void do_caselesscmp(compiler_common *common)
|
||||
{
|
||||
DEFINE_COMPILER;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_label *label;
|
||||
int char1_reg = STR_END;
|
||||
int char2_reg;
|
||||
int lcc_table;
|
||||
int opt_type = 0;
|
||||
|
||||
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
|
||||
if (sljit_get_register_index(TMP3) < 0)
|
||||
{
|
||||
char2_reg = STACK_TOP;
|
||||
lcc_table = STACK_LIMIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
char2_reg = RETURN_ADDR;
|
||||
lcc_table = TMP3;
|
||||
}
|
||||
|
||||
if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
|
||||
opt_type = 1;
|
||||
else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
|
||||
opt_type = 2;
|
||||
|
||||
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
|
||||
|
||||
OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR1, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, CHAR2, 0);
|
||||
OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
|
||||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0);
|
||||
|
||||
if (char2_reg == STACK_TOP)
|
||||
{
|
||||
OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0);
|
||||
OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0);
|
||||
}
|
||||
|
||||
OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc);
|
||||
|
||||
if (opt_type == 1)
|
||||
{
|
||||
label = LABEL();
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
}
|
||||
else if (opt_type == 2)
|
||||
{
|
||||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
label = LABEL();
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
label = LABEL();
|
||||
OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);
|
||||
OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);
|
||||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
}
|
||||
|
||||
label = LABEL();
|
||||
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
jump = CMP(SLJIT_GREATER, CHAR1, 0, SLJIT_IMM, 255);
|
||||
jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255);
|
||||
#endif
|
||||
OP1(SLJIT_MOV_U8, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
|
||||
OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0);
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
JUMPHERE(jump);
|
||||
jump = CMP(SLJIT_GREATER, CHAR2, 0, SLJIT_IMM, 255);
|
||||
jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255);
|
||||
#endif
|
||||
OP1(SLJIT_MOV_U8, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
|
||||
OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0);
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
JUMPHERE(jump);
|
||||
#endif
|
||||
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
|
||||
|
||||
if (opt_type == 0)
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
|
||||
OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
|
||||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
|
||||
}
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
|
||||
#undef LCC_TABLE
|
||||
#undef CHAR1
|
||||
#undef CHAR2
|
||||
if (opt_type == 2)
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
if (char2_reg == STACK_TOP)
|
||||
{
|
||||
OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0);
|
||||
OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0);
|
||||
}
|
||||
|
||||
OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
|
||||
sljit_emit_fast_return(compiler, TMP1, 0);
|
||||
}
|
||||
|
||||
#if defined SUPPORT_UNICODE
|
||||
|
||||
static PCRE2_SPTR SLJIT_CALL do_utf_caselesscmp(PCRE2_SPTR src1, jit_arguments *args, PCRE2_SPTR end1)
|
||||
static PCRE2_SPTR SLJIT_FUNC do_utf_caselesscmp(PCRE2_SPTR src1, PCRE2_SPTR src2, PCRE2_SPTR end1, PCRE2_SPTR end2)
|
||||
{
|
||||
/* This function would be ineffective to do in JIT level. */
|
||||
sljit_u32 c1, c2;
|
||||
PCRE2_SPTR src2 = args->startchar_ptr;
|
||||
PCRE2_SPTR end2 = args->end;
|
||||
const ucd_record *ur;
|
||||
const sljit_u32 *pp;
|
||||
|
||||
@ -7048,6 +7207,122 @@ SLJIT_UNREACHABLE();
|
||||
return cc;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_UNICODE
|
||||
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 32
|
||||
|
||||
static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc)
|
||||
{
|
||||
PCRE2_SPTR start_subject = args->begin;
|
||||
PCRE2_SPTR end_subject = args->end;
|
||||
int lgb, rgb, len, ricount;
|
||||
PCRE2_SPTR prevcc, bptr;
|
||||
uint32_t c;
|
||||
|
||||
prevcc = cc;
|
||||
GETCHARINC(c, cc);
|
||||
lgb = UCD_GRAPHBREAK(c);
|
||||
|
||||
while (cc < end_subject)
|
||||
{
|
||||
len = 1;
|
||||
GETCHARLEN(c, cc, len);
|
||||
rgb = UCD_GRAPHBREAK(c);
|
||||
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if there
|
||||
are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
ricount = 0;
|
||||
bptr = prevcc;
|
||||
|
||||
/* bptr is pointing to the left-hand character */
|
||||
while (bptr > start_subject)
|
||||
{
|
||||
bptr--;
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(c, bptr);
|
||||
|
||||
if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;
|
||||
|
||||
ricount++;
|
||||
}
|
||||
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend || (lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
prevcc = cc;
|
||||
cc += len;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc)
|
||||
{
|
||||
PCRE2_SPTR start_subject = args->begin;
|
||||
PCRE2_SPTR end_subject = args->end;
|
||||
int lgb, rgb, ricount;
|
||||
PCRE2_SPTR bptr;
|
||||
uint32_t c;
|
||||
|
||||
GETCHARINC(c, cc);
|
||||
lgb = UCD_GRAPHBREAK(c);
|
||||
|
||||
while (cc < end_subject)
|
||||
{
|
||||
c = *cc;
|
||||
rgb = UCD_GRAPHBREAK(c);
|
||||
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if there
|
||||
are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
ricount = 0;
|
||||
bptr = cc - 1;
|
||||
|
||||
/* bptr is pointing to the left-hand character */
|
||||
while (bptr > start_subject)
|
||||
{
|
||||
bptr--;
|
||||
c = *bptr;
|
||||
|
||||
if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;
|
||||
|
||||
ricount++;
|
||||
}
|
||||
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend || (lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
cc++;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr)
|
||||
{
|
||||
DEFINE_COMPILER;
|
||||
@ -7057,7 +7332,6 @@ compare_context context;
|
||||
struct sljit_jump *jump[3];
|
||||
jump_list *end_list;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
struct sljit_label *label;
|
||||
PCRE2_UCHAR propdata[5];
|
||||
#endif /* SUPPORT_UNICODE */
|
||||
|
||||
@ -7224,35 +7498,22 @@ switch(type)
|
||||
case OP_EXTUNI:
|
||||
if (check_str_ptr)
|
||||
detect_partial_match(common, backtracks);
|
||||
read_char(common);
|
||||
add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
|
||||
/* Optimize register allocation: use a real register. */
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
|
||||
OP1(SLJIT_MOV_U8, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3);
|
||||
|
||||
label = LABEL();
|
||||
jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
|
||||
OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
|
||||
read_char(common);
|
||||
add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
|
||||
OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3);
|
||||
SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
|
||||
OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
|
||||
|
||||
OP2(SLJIT_SHL, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2);
|
||||
OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0);
|
||||
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
|
||||
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 32
|
||||
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,
|
||||
common->utf ? SLJIT_FUNC_OFFSET(do_extuni_utf) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));
|
||||
#else
|
||||
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_extuni_no_utf));
|
||||
#endif
|
||||
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
|
||||
JUMPHERE(jump[0]);
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
|
||||
|
||||
if (common->mode == PCRE2_JIT_PARTIAL_HARD)
|
||||
{
|
||||
jump[0] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
|
||||
jump[0] = CMP(SLJIT_LESS, SLJIT_RETURN_REG, 0, STR_END, 0);
|
||||
/* Since we successfully read a char above, partial matching must occure. */
|
||||
check_partial(common, TRUE);
|
||||
JUMPHERE(jump[0]);
|
||||
@ -7585,32 +7846,34 @@ else
|
||||
#if defined SUPPORT_UNICODE
|
||||
if (common->utf && *cc == OP_REFI)
|
||||
{
|
||||
SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1 && TMP2 == SLJIT_R2);
|
||||
SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
|
||||
if (ref)
|
||||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
|
||||
else
|
||||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
|
||||
|
||||
if (withchecks)
|
||||
jump = CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0);
|
||||
jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_R2, 0);
|
||||
/* No free saved registers so save data on stack. */
|
||||
|
||||
OP1(SLJIT_MOV, SLJIT_R3, 0, STR_END, 0);
|
||||
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
|
||||
|
||||
/* Needed to save important temporary registers. */
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), STR_PTR, 0);
|
||||
sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
if (common->mode == PCRE2_JIT_COMPLETE)
|
||||
add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
|
||||
else
|
||||
{
|
||||
add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
|
||||
nopartial = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
|
||||
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_LESS));
|
||||
|
||||
nopartial = JUMP(SLJIT_NOT_EQUAL);
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
|
||||
check_partial(common, FALSE);
|
||||
add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
|
||||
JUMPHERE(nopartial);
|
||||
}
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORT_UNICODE */
|
||||
@ -7924,7 +8187,7 @@ BACKTRACK_AS(recurse_backtrack)->matchingpath = LABEL();
|
||||
return cc + 1 + LINK_SIZE;
|
||||
}
|
||||
|
||||
static int SLJIT_CALL do_callout(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector)
|
||||
static sljit_s32 SLJIT_FUNC do_callout(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector)
|
||||
{
|
||||
PCRE2_SPTR begin;
|
||||
PCRE2_SIZE *ovector;
|
||||
@ -7941,7 +8204,8 @@ oveccount = callout_block->capture_top;
|
||||
|
||||
SLJIT_ASSERT(oveccount >= 1);
|
||||
|
||||
callout_block->version = 1;
|
||||
callout_block->version = 2;
|
||||
callout_block->callout_flags = 0;
|
||||
|
||||
/* Offsets in subject. */
|
||||
callout_block->subject_length = arguments->end - arguments->begin;
|
||||
@ -8033,23 +8297,24 @@ OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_length)
|
||||
OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_offset), SLJIT_IMM, value3);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0);
|
||||
|
||||
SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
|
||||
|
||||
/* Needed to save important temporary registers. */
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);
|
||||
/* SLJIT_R0 = arguments */
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);
|
||||
GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);
|
||||
sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));
|
||||
OP1(SLJIT_MOV_S32, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0);
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(S32) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
free_stack(common, callout_arg_size);
|
||||
|
||||
/* Check return value. */
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
|
||||
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER));
|
||||
OP2(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
|
||||
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER32));
|
||||
if (common->abort_label == NULL)
|
||||
add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL) /* SIG_LESS */);
|
||||
add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL32) /* SIG_LESS */);
|
||||
else
|
||||
JUMPTO(SLJIT_NOT_EQUAL /* SIG_LESS */, common->abort_label);
|
||||
JUMPTO(SLJIT_NOT_EQUAL32 /* SIG_LESS */, common->abort_label);
|
||||
return cc + callout_length;
|
||||
}
|
||||
|
||||
@ -11279,15 +11544,13 @@ if (common->local_quit_available)
|
||||
|
||||
if (opcode == OP_SKIP_ARG)
|
||||
{
|
||||
SLJIT_ASSERT(common->control_head_ptr != 0);
|
||||
SLJIT_ASSERT(common->control_head_ptr != 0 && TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));
|
||||
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));
|
||||
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark));
|
||||
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
|
||||
add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1));
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0);
|
||||
add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -11957,7 +12220,7 @@ if (!compiler)
|
||||
common->compiler = compiler;
|
||||
|
||||
/* Main pcre_jit_exec entry. */
|
||||
sljit_emit_enter(compiler, 0, 1, 5, 5, 0, 0, private_data_size);
|
||||
sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size);
|
||||
|
||||
/* Register init. */
|
||||
reset_ovector(common, (re->top_bracket + 1) * 2);
|
||||
@ -11970,8 +12233,8 @@ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str))
|
||||
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
|
||||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
|
||||
OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
|
||||
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, end));
|
||||
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, start));
|
||||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);
|
||||
|
||||
@ -12200,20 +12463,23 @@ common->quit_label = quit_label;
|
||||
set_jumps(common->stackalloc, LABEL());
|
||||
/* RETURN_ADDR is not a saved register. */
|
||||
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0);
|
||||
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
|
||||
OP2(SLJIT_SUB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
|
||||
|
||||
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
|
||||
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top));
|
||||
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit));
|
||||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
|
||||
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
|
||||
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
|
||||
OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE);
|
||||
OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack));
|
||||
OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0);
|
||||
|
||||
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
|
||||
|
||||
jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
|
||||
OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0);
|
||||
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
|
||||
sljit_emit_fast_return(compiler, TMP1, 0);
|
||||
|
||||
/* Allocation failed. */
|
||||
JUMPHERE(jump);
|
||||
|
8
src/3rdparty/pcre2/src/pcre2_jit_match.c
vendored
8
src/3rdparty/pcre2/src/pcre2_jit_match.c
vendored
@ -49,9 +49,9 @@ static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, jit_f
|
||||
sljit_u8 local_space[MACHINE_STACK_SIZE];
|
||||
struct sljit_stack local_stack;
|
||||
|
||||
local_stack.max_limit = local_space;
|
||||
local_stack.limit = local_space;
|
||||
local_stack.base = local_space + MACHINE_STACK_SIZE;
|
||||
local_stack.min_start = local_space;
|
||||
local_stack.start = local_space;
|
||||
local_stack.end = local_space + MACHINE_STACK_SIZE;
|
||||
local_stack.top = local_space + MACHINE_STACK_SIZE;
|
||||
arguments->stack = &local_stack;
|
||||
return executable_func(arguments);
|
||||
@ -118,7 +118,7 @@ if ((options & PCRE2_PARTIAL_HARD) != 0)
|
||||
else if ((options & PCRE2_PARTIAL_SOFT) != 0)
|
||||
index = 1;
|
||||
|
||||
if (functions->executable_funcs[index] == NULL)
|
||||
if (functions == NULL || functions->executable_funcs[index] == NULL)
|
||||
return PCRE2_ERROR_JIT_BADOPTION;
|
||||
|
||||
/* Sanity checks should be handled by pcre_exec. */
|
||||
|
334
src/3rdparty/pcre2/src/pcre2_match.c
vendored
334
src/3rdparty/pcre2/src/pcre2_match.c
vendored
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2015-2017 University of Cambridge
|
||||
New API code Copyright (c) 2015-2018 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -249,7 +249,8 @@ for (i = 0, Q = mb->match_frames;
|
||||
|
||||
/* This function is called for all callouts, whether "standalone" or at the
|
||||
start of a conditional group. Feptr will be pointing to either OP_CALLOUT or
|
||||
OP_CALLOUT_STR.
|
||||
OP_CALLOUT_STR. A callout block is allocated in pcre2_match() and initialized
|
||||
with fixed values.
|
||||
|
||||
Arguments:
|
||||
F points to the current backtracking frame
|
||||
@ -266,7 +267,7 @@ do_callout(heapframe *F, match_block *mb, PCRE2_SIZE *lengthptr)
|
||||
int rc;
|
||||
PCRE2_SIZE save0, save1;
|
||||
PCRE2_SIZE *callout_ovector;
|
||||
pcre2_callout_block cb;
|
||||
pcre2_callout_block *cb;
|
||||
|
||||
*lengthptr = (*Fecode == OP_CALLOUT)?
|
||||
PRIV(OP_lengths)[OP_CALLOUT] : GET(Fecode, 1 + 2*LINK_SIZE);
|
||||
@ -285,40 +286,42 @@ pointer. */
|
||||
|
||||
callout_ovector = (PCRE2_SIZE *)(Fovector) - 2;
|
||||
|
||||
cb.version = 1;
|
||||
cb.capture_top = (uint32_t)Foffset_top/2 + 1;
|
||||
cb.capture_last = Fcapture_last;
|
||||
cb.offset_vector = callout_ovector;
|
||||
cb.mark = mb->nomatch_mark;
|
||||
cb.subject = mb->start_subject;
|
||||
cb.subject_length = (PCRE2_SIZE)(mb->end_subject - mb->start_subject);
|
||||
cb.start_match = (PCRE2_SIZE)(Fstart_match - mb->start_subject);
|
||||
cb.current_position = (PCRE2_SIZE)(Feptr - mb->start_subject);
|
||||
cb.pattern_position = GET(Fecode, 1);
|
||||
cb.next_item_length = GET(Fecode, 1 + LINK_SIZE);
|
||||
/* The cb->version, cb->subject, cb->subject_length, and cb->start_match fields
|
||||
are set externally. The first 3 never change; the last is updated for each
|
||||
bumpalong. */
|
||||
|
||||
cb = mb->cb;
|
||||
cb->capture_top = (uint32_t)Foffset_top/2 + 1;
|
||||
cb->capture_last = Fcapture_last;
|
||||
cb->offset_vector = callout_ovector;
|
||||
cb->mark = mb->nomatch_mark;
|
||||
cb->current_position = (PCRE2_SIZE)(Feptr - mb->start_subject);
|
||||
cb->pattern_position = GET(Fecode, 1);
|
||||
cb->next_item_length = GET(Fecode, 1 + LINK_SIZE);
|
||||
|
||||
if (*Fecode == OP_CALLOUT) /* Numerical callout */
|
||||
{
|
||||
cb.callout_number = Fecode[1 + 2*LINK_SIZE];
|
||||
cb.callout_string_offset = 0;
|
||||
cb.callout_string = NULL;
|
||||
cb.callout_string_length = 0;
|
||||
cb->callout_number = Fecode[1 + 2*LINK_SIZE];
|
||||
cb->callout_string_offset = 0;
|
||||
cb->callout_string = NULL;
|
||||
cb->callout_string_length = 0;
|
||||
}
|
||||
else /* String callout */
|
||||
{
|
||||
cb.callout_number = 0;
|
||||
cb.callout_string_offset = GET(Fecode, 1 + 3*LINK_SIZE);
|
||||
cb.callout_string = Fecode + (1 + 4*LINK_SIZE) + 1;
|
||||
cb.callout_string_length =
|
||||
cb->callout_number = 0;
|
||||
cb->callout_string_offset = GET(Fecode, 1 + 3*LINK_SIZE);
|
||||
cb->callout_string = Fecode + (1 + 4*LINK_SIZE) + 1;
|
||||
cb->callout_string_length =
|
||||
*lengthptr - (1 + 4*LINK_SIZE) - 2;
|
||||
}
|
||||
|
||||
save0 = callout_ovector[0];
|
||||
save1 = callout_ovector[1];
|
||||
callout_ovector[0] = callout_ovector[1] = PCRE2_UNSET;
|
||||
rc = mb->callout(&cb, mb->callout_data);
|
||||
rc = mb->callout(cb, mb->callout_data);
|
||||
callout_ovector[0] = save0;
|
||||
callout_ovector[1] = save1;
|
||||
cb->callout_flags = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -729,7 +732,7 @@ for (;;)
|
||||
fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
#endif
|
||||
|
||||
Fop = *Fecode;
|
||||
Fop = (uint8_t)(*Fecode); /* Cast needed for 16-bit and 32-bit modes */
|
||||
switch(Fop)
|
||||
{
|
||||
/* ===================================================================== */
|
||||
@ -876,7 +879,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
}
|
||||
Feptr++;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) ACROSSCHAR(Feptr < mb->end_subject, *Feptr, Feptr++);
|
||||
if (utf) ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
|
||||
#endif
|
||||
Fecode++;
|
||||
break;
|
||||
@ -2440,55 +2443,9 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
}
|
||||
else
|
||||
{
|
||||
int lgb, rgb;
|
||||
GETCHARINCTEST(fc, Feptr);
|
||||
lgb = UCD_GRAPHBREAK(fc);
|
||||
while (Feptr < mb->end_subject)
|
||||
{
|
||||
int len = 1;
|
||||
if (!utf) fc = *Feptr; else { GETCHARLEN(fc, Feptr, len); }
|
||||
rgb = UCD_GRAPHBREAK(fc);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if there
|
||||
are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = Feptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) BACKCHAR(bptr);
|
||||
#endif
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > mb->start_subject)
|
||||
{
|
||||
bptr--;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(fc, bptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
fc = *bptr;
|
||||
if (UCD_GRAPHBREAK(fc) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
Feptr += len;
|
||||
}
|
||||
Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, utf,
|
||||
NULL);
|
||||
}
|
||||
CHECK_PARTIAL();
|
||||
Fecode++;
|
||||
@ -2785,61 +2742,13 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
}
|
||||
else
|
||||
{
|
||||
int lgb, rgb;
|
||||
GETCHARINCTEST(fc, Feptr);
|
||||
lgb = UCD_GRAPHBREAK(fc);
|
||||
while (Feptr < mb->end_subject)
|
||||
{
|
||||
int len = 1;
|
||||
if (!utf) fc = *Feptr; else { GETCHARLEN(fc, Feptr, len); }
|
||||
rgb = UCD_GRAPHBREAK(fc);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if
|
||||
there are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator &&
|
||||
rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = Feptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) BACKCHAR(bptr);
|
||||
#endif
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > mb->start_subject)
|
||||
{
|
||||
bptr--;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(fc, bptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
fc = *bptr;
|
||||
if (UCD_GRAPHBREAK(fc) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
Feptr += len;
|
||||
}
|
||||
Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject,
|
||||
mb->end_subject, utf, NULL);
|
||||
}
|
||||
CHECK_PARTIAL();
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
#endif /* SUPPORT_UNICODE */
|
||||
|
||||
@ -2867,7 +2776,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
|
||||
}
|
||||
Feptr++;
|
||||
ACROSSCHAR(Feptr < mb->end_subject, *Feptr, Feptr++);
|
||||
ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2880,7 +2789,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
Feptr++;
|
||||
ACROSSCHAR(Feptr < mb->end_subject, *Feptr, Feptr++);
|
||||
ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3034,7 +2943,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
if (cc < 128 && (mb->ctypes[cc] & ctype_space) != 0)
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
Feptr++;
|
||||
ACROSSCHAR(Feptr < mb->end_subject, *Feptr, Feptr++);
|
||||
ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3068,7 +2977,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
if (cc < 128 && (mb->ctypes[cc] & ctype_word) != 0)
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
Feptr++;
|
||||
ACROSSCHAR(Feptr < mb->end_subject, *Feptr, Feptr++);
|
||||
ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3593,56 +3502,9 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
}
|
||||
else
|
||||
{
|
||||
int lgb, rgb;
|
||||
GETCHARINCTEST(fc, Feptr);
|
||||
lgb = UCD_GRAPHBREAK(fc);
|
||||
while (Feptr < mb->end_subject)
|
||||
{
|
||||
int len = 1;
|
||||
if (!utf) fc = *Feptr; else { GETCHARLEN(fc, Feptr, len); }
|
||||
rgb = UCD_GRAPHBREAK(fc);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if
|
||||
there are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator &&
|
||||
rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = Feptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) BACKCHAR(bptr);
|
||||
#endif
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > mb->start_subject)
|
||||
{
|
||||
bptr--;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(fc, bptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
fc = *bptr;
|
||||
if (UCD_GRAPHBREAK(fc) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
Feptr += len;
|
||||
}
|
||||
Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject,
|
||||
utf, NULL);
|
||||
}
|
||||
CHECK_PARTIAL();
|
||||
}
|
||||
@ -4167,56 +4029,9 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
}
|
||||
else
|
||||
{
|
||||
int lgb, rgb;
|
||||
GETCHARINCTEST(fc, Feptr);
|
||||
lgb = UCD_GRAPHBREAK(fc);
|
||||
while (Feptr < mb->end_subject)
|
||||
{
|
||||
int len = 1;
|
||||
if (!utf) fc = *Feptr; else { GETCHARLEN(fc, Feptr, len); }
|
||||
rgb = UCD_GRAPHBREAK(fc);
|
||||
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
|
||||
|
||||
/* Not breaking between Regional Indicators is allowed only if
|
||||
there are an even number of preceding RIs. */
|
||||
|
||||
if (lgb == ucp_gbRegionalIndicator &&
|
||||
rgb == ucp_gbRegionalIndicator)
|
||||
{
|
||||
int ricount = 0;
|
||||
PCRE2_SPTR bptr = Feptr - 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf) BACKCHAR(bptr);
|
||||
#endif
|
||||
/* bptr is pointing to the left-hand character */
|
||||
|
||||
while (bptr > mb->start_subject)
|
||||
{
|
||||
bptr--;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
BACKCHAR(bptr);
|
||||
GETCHAR(fc, bptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
fc = *bptr;
|
||||
if (UCD_GRAPHBREAK(fc) != ucp_gbRegionalIndicator) break;
|
||||
ricount++;
|
||||
}
|
||||
if ((ricount & 1) != 0) break; /* Grapheme break required */
|
||||
}
|
||||
|
||||
/* If Extend follows E_Base[_GAZ] do not update lgb; this allows
|
||||
any number of Extend before a following E_Modifier. */
|
||||
|
||||
if (rgb != ucp_gbExtend ||
|
||||
(lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
|
||||
lgb = rgb;
|
||||
|
||||
Feptr += len;
|
||||
}
|
||||
Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject,
|
||||
utf, NULL);
|
||||
}
|
||||
CHECK_PARTIAL();
|
||||
}
|
||||
@ -4295,7 +4110,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
|
||||
}
|
||||
Feptr++;
|
||||
ACROSSCHAR(Feptr < mb->end_subject, *Feptr, Feptr++);
|
||||
ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4310,7 +4125,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
break;
|
||||
}
|
||||
Feptr++;
|
||||
ACROSSCHAR(Feptr < mb->end_subject, *Feptr, Feptr++);
|
||||
ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -5240,7 +5055,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
|
||||
P = (heapframe *)((char *)N - frame_size);
|
||||
if (N->group_frame_type == (GF_RECURSE | number))
|
||||
{
|
||||
if (Feptr == P->eptr) RRETURN(PCRE2_ERROR_RECURSELOOP);
|
||||
if (Feptr == P->eptr) return PCRE2_ERROR_RECURSELOOP;
|
||||
break;
|
||||
}
|
||||
offset = P->last_group_offset;
|
||||
@ -6105,8 +5920,9 @@ in rrc. */
|
||||
#define LBL(val) case val: goto L_RM##val;
|
||||
|
||||
RETURN_SWITCH:
|
||||
if (Frdepth == 0) return rrc; /* Exit from the top level */
|
||||
F = (heapframe *)((char *)F - Fback_frame); /* Back track */
|
||||
if (Frdepth == 0) return rrc; /* Exit from the top level */
|
||||
F = (heapframe *)((char *)F - Fback_frame); /* Back track */
|
||||
mb->cb->callout_flags |= PCRE2_CALLOUT_BACKTRACK; /* Note for callouts */
|
||||
|
||||
#ifdef DEBUG_SHOW_RMATCH
|
||||
fprintf(stderr, "++ RETURN %d to %d\n", rrc, Freturn_id);
|
||||
@ -6196,6 +6012,7 @@ PCRE2_SIZE frame_size;
|
||||
/* We need to have mb as a pointer to a match block, because the IS_NEWLINE
|
||||
macro is used below, and it expects NLBLOCK to be defined as a pointer. */
|
||||
|
||||
pcre2_callout_block cb;
|
||||
match_block actual_match_block;
|
||||
match_block *mb = &actual_match_block;
|
||||
|
||||
@ -6356,6 +6173,15 @@ startline = (re->flags & PCRE2_STARTLINE) != 0;
|
||||
bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)?
|
||||
end_subject : subject + mcontext->offset_limit;
|
||||
|
||||
/* Initialize and set up the fixed fields in the callout block, with a pointer
|
||||
in the match block. */
|
||||
|
||||
mb->cb = &cb;
|
||||
cb.version = 2;
|
||||
cb.subject = subject;
|
||||
cb.subject_length = (PCRE2_SIZE)(end_subject - subject);
|
||||
cb.callout_flags = 0;
|
||||
|
||||
/* Fill in the remaining fields in the match block. */
|
||||
|
||||
mb->callout = mcontext->callout;
|
||||
@ -6537,13 +6363,11 @@ for(;;)
|
||||
|
||||
if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
|
||||
{
|
||||
PCRE2_SPTR save_end_subject = end_subject;
|
||||
|
||||
/* If firstline is TRUE, the start of the match is constrained to the first
|
||||
line of a multiline string. That is, the match must be before or at the
|
||||
first newline. Implement this by temporarily adjusting end_subject so that
|
||||
we stop the optimization scans for a first code unit at a newline. If the
|
||||
match fails at the newline, later code breaks this loop. */
|
||||
first newline following the start of matching. Temporarily adjust
|
||||
end_subject so that we stop the scans for a first code unit at a newline.
|
||||
If the match fails at the newline, later code breaks the loop. */
|
||||
|
||||
if (firstline)
|
||||
{
|
||||
@ -6551,15 +6375,15 @@ for(;;)
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
{
|
||||
while (t < mb->end_subject && !IS_NEWLINE(t))
|
||||
while (t < end_subject && !IS_NEWLINE(t))
|
||||
{
|
||||
t++;
|
||||
ACROSSCHAR(t < end_subject, *t, t++);
|
||||
ACROSSCHAR(t < end_subject, t, t++);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
while (t < mb->end_subject && !IS_NEWLINE(t)) t++;
|
||||
while (t < end_subject && !IS_NEWLINE(t)) t++;
|
||||
end_subject = t;
|
||||
}
|
||||
|
||||
@ -6635,13 +6459,17 @@ for(;;)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If we can't find the required code unit, break the bumpalong loop,
|
||||
to force a match failure, except when doing partial matching, when we
|
||||
let the next cycle run at the end of the subject. To see why, consider
|
||||
the pattern /(?<=abc)def/, which partially matches "abc", even though
|
||||
the string does not contain the starting character "d". */
|
||||
/* If we can't find the required code unit, having reached the true end
|
||||
of the subject, break the bumpalong loop, to force a match failure,
|
||||
except when doing partial matching, when we let the next cycle run at
|
||||
the end of the subject. To see why, consider the pattern /(?<=abc)def/,
|
||||
which partially matches "abc", even though the string does not contain
|
||||
the starting character "d". If we have not reached the true end of the
|
||||
subject (PCRE2_FIRSTLINE caused end_subject to be temporarily modified)
|
||||
we also let the cycle run, because the matching string is legitimately
|
||||
allowed to start with the first code unit of a newline. */
|
||||
|
||||
if (!mb->partial && start_match >= end_subject)
|
||||
if (!mb->partial && start_match >= mb->end_subject)
|
||||
{
|
||||
rc = MATCH_NOMATCH;
|
||||
break;
|
||||
@ -6661,8 +6489,7 @@ for(;;)
|
||||
while (start_match < end_subject && !WAS_NEWLINE(start_match))
|
||||
{
|
||||
start_match++;
|
||||
ACROSSCHAR(start_match < end_subject, *start_match,
|
||||
start_match++);
|
||||
ACROSSCHAR(start_match < end_subject, start_match, start_match++);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -6698,12 +6525,20 @@ for(;;)
|
||||
if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
|
||||
start_match++;
|
||||
}
|
||||
|
||||
/* See comment above in first_cu checking about the next few lines. */
|
||||
|
||||
if (!mb->partial && start_match >= mb->end_subject)
|
||||
{
|
||||
rc = MATCH_NOMATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* End first code unit handling */
|
||||
|
||||
/* Restore fudged end_subject */
|
||||
|
||||
end_subject = save_end_subject;
|
||||
end_subject = mb->end_subject;
|
||||
|
||||
/* The following two optimizations must be disabled for partial matching. */
|
||||
|
||||
@ -6820,6 +6655,9 @@ for(;;)
|
||||
/* OK, we can now run the match. If "hitend" is set afterwards, remember the
|
||||
first starting point for which a partial match was found. */
|
||||
|
||||
cb.start_match = (PCRE2_SIZE)(start_match - subject);
|
||||
cb.callout_flags |= PCRE2_CALLOUT_STARTMATCH;
|
||||
|
||||
mb->start_used_ptr = start_match;
|
||||
mb->last_used_ptr = start_match;
|
||||
mb->match_call_count = 0;
|
||||
@ -6870,7 +6708,7 @@ for(;;)
|
||||
new_start_match = start_match + 1;
|
||||
#ifdef SUPPORT_UNICODE
|
||||
if (utf)
|
||||
ACROSSCHAR(new_start_match < end_subject, *new_start_match,
|
||||
ACROSSCHAR(new_start_match < end_subject, new_start_match,
|
||||
new_start_match++);
|
||||
#endif
|
||||
break;
|
||||
|
5
src/3rdparty/pcre2/src/pcre2_pattern_info.c
vendored
5
src/3rdparty/pcre2/src/pcre2_pattern_info.c
vendored
@ -76,6 +76,7 @@ if (where == NULL) /* Requests field length */
|
||||
case PCRE2_INFO_BSR:
|
||||
case PCRE2_INFO_CAPTURECOUNT:
|
||||
case PCRE2_INFO_DEPTHLIMIT:
|
||||
case PCRE2_INFO_EXTRAOPTIONS:
|
||||
case PCRE2_INFO_FIRSTCODETYPE:
|
||||
case PCRE2_INFO_FIRSTCODEUNIT:
|
||||
case PCRE2_INFO_HASBACKSLASHC:
|
||||
@ -144,6 +145,10 @@ switch(what)
|
||||
if (re->limit_depth == UINT32_MAX) return PCRE2_ERROR_UNSET;
|
||||
break;
|
||||
|
||||
case PCRE2_INFO_EXTRAOPTIONS:
|
||||
*((uint32_t *)where) = re->extra_options;
|
||||
break;
|
||||
|
||||
case PCRE2_INFO_FIRSTCODETYPE:
|
||||
*((uint32_t *)where) = ((re->flags & PCRE2_FIRSTSET) != 0)? 1 :
|
||||
((re->flags & PCRE2_STARTLINE) != 0)? 2 : 0;
|
||||
|
9
src/3rdparty/pcre2/src/pcre2_substring.c
vendored
9
src/3rdparty/pcre2/src/pcre2_substring.c
vendored
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Original API code Copyright (c) 1997-2012 University of Cambridge
|
||||
New API code Copyright (c) 2016 University of Cambridge
|
||||
New API code Copyright (c) 2016-2018 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -414,7 +414,12 @@ else
|
||||
for (i = 0; i < count2; i += 2)
|
||||
{
|
||||
size = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;
|
||||
memcpy(sp, match_data->subject + ovector[i], CU2BYTES(size));
|
||||
|
||||
/* Size == 0 includes the case when the capture is unset. Avoid adding
|
||||
PCRE2_UNSET to match_data->subject because it overflows, even though with
|
||||
zero size calling memcpy() is harmless. */
|
||||
|
||||
if (size != 0) memcpy(sp, match_data->subject + ovector[i], CU2BYTES(size));
|
||||
*listp++ = sp;
|
||||
if (lensp != NULL) *lensp++ = size;
|
||||
sp += size;
|
||||
|
6
src/3rdparty/pcre2/src/sljit/sljitConfig.h
vendored
6
src/3rdparty/pcre2/src/sljit/sljitConfig.h
vendored
@ -108,8 +108,10 @@
|
||||
|
||||
/* Force cdecl calling convention even if a better calling
|
||||
convention (e.g. fastcall) is supported by the C compiler.
|
||||
If this option is enabled, C functions without
|
||||
SLJIT_CALL can also be called from JIT code. */
|
||||
If this option is disabled (this is the default), functions
|
||||
called from JIT should be defined with SLJIT_FUNC attribute.
|
||||
Standard C functions can still be called by using the
|
||||
SLJIT_CALL_CDECL jump type. */
|
||||
#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION
|
||||
/* Disabled by default */
|
||||
#define SLJIT_USE_CDECL_CALLING_CONVENTION 0
|
||||
|
@ -60,11 +60,13 @@
|
||||
a single precision floating point array by index
|
||||
SLJIT_F64_SHIFT : the shift required to apply when accessing
|
||||
a double precision floating point array by index
|
||||
SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register
|
||||
the scratch register index of ecx is stored in this variable
|
||||
SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET)
|
||||
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
|
||||
|
||||
Other macros:
|
||||
SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT
|
||||
SLJIT_FUNC : calling convention attribute for both calling JIT form C and C calling back from JIT
|
||||
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
|
||||
*/
|
||||
|
||||
@ -471,44 +473,44 @@ typedef double sljit_f64;
|
||||
/* Calling convention of functions generated by SLJIT or called from the generated code. */
|
||||
/*****************************************************************************************/
|
||||
|
||||
#ifndef SLJIT_CALL
|
||||
#ifndef SLJIT_FUNC
|
||||
|
||||
#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION)
|
||||
|
||||
/* Force cdecl. */
|
||||
#define SLJIT_CALL
|
||||
#define SLJIT_FUNC
|
||||
|
||||
#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
#if defined(__GNUC__) && !defined(__APPLE__)
|
||||
|
||||
#define SLJIT_CALL __attribute__ ((fastcall))
|
||||
#define SLJIT_FUNC __attribute__ ((fastcall))
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#define SLJIT_CALL __fastcall
|
||||
#define SLJIT_FUNC __fastcall
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#elif defined(__BORLANDC__)
|
||||
|
||||
#define SLJIT_CALL __msfastcall
|
||||
#define SLJIT_FUNC __msfastcall
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#else /* Unknown compiler. */
|
||||
|
||||
/* The cdecl attribute is the default. */
|
||||
#define SLJIT_CALL
|
||||
#define SLJIT_FUNC
|
||||
|
||||
#endif
|
||||
|
||||
#else /* Non x86-32 architectures. */
|
||||
|
||||
#define SLJIT_CALL
|
||||
#define SLJIT_FUNC
|
||||
|
||||
#endif /* SLJIT_CONFIG_X86_32 */
|
||||
|
||||
#endif /* !SLJIT_CALL */
|
||||
#endif /* !SLJIT_FUNC */
|
||||
|
||||
#ifndef SLJIT_INDIRECT_CALL
|
||||
#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)) \
|
||||
@ -557,24 +559,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
|
||||
#else
|
||||
/* Maximum 3 arguments are passed on the stack, +1 for double alignment. */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
|
||||
#endif /* SLJIT_X86_32_FASTCALL */
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
|
||||
|
||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
||||
#ifndef _WIN64
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 13
|
||||
#ifndef _WIN64
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
|
||||
#define SLJIT_LOCALS_OFFSET_BASE 0
|
||||
#else
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 13
|
||||
#else /* _WIN64 */
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
|
||||
#endif /* _WIN64 */
|
||||
#endif /* !_WIN64 */
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R3
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
|
||||
@ -590,13 +588,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
||||
|
||||
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 25
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 26
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (2 * sizeof(sljit_sw))
|
||||
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 22
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 23
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * sizeof(sljit_sw))
|
||||
@ -622,8 +620,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 18
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
/* Add +1 for double alignment. */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((23 + 1) * sizeof(sljit_sw))
|
||||
/* saved registers (16), return struct pointer (1), space for 6 argument words (1),
|
||||
4th double arg (2), double alignment (1). */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * sizeof(sljit_sw))
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
|
||||
|
693
src/3rdparty/pcre2/src/sljit/sljitLir.c
vendored
693
src/3rdparty/pcre2/src/sljit/sljitLir.c
vendored
@ -97,8 +97,13 @@
|
||||
#define GET_ALL_FLAGS(op) \
|
||||
((op) & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
|
||||
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#define TYPE_CAST_NEEDED(op) \
|
||||
(((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16) || ((op) >= SLJIT_MOVU_U8 && (op) <= SLJIT_MOVU_S16))
|
||||
((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32)
|
||||
#else
|
||||
#define TYPE_CAST_NEEDED(op) \
|
||||
((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16)
|
||||
#endif
|
||||
|
||||
#define BUF_SIZE 4096
|
||||
|
||||
@ -118,6 +123,9 @@
|
||||
/* When reg can be unused. */
|
||||
#define SLOW_IS_REG(reg) ((reg) > 0 && (reg) <= REG_MASK)
|
||||
|
||||
/* Mask for argument types. */
|
||||
#define SLJIT_DEF_MASK ((1 << SLJIT_DEF_SHIFT) - 1)
|
||||
|
||||
/* Jump flags. */
|
||||
#define JUMP_LABEL 0x1
|
||||
#define JUMP_ADDR 0x2
|
||||
@ -591,6 +599,19 @@ static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)
|
||||
compiler->buf = prev;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types)
|
||||
{
|
||||
sljit_s32 arg_count = 0;
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
while (arg_types) {
|
||||
arg_count++;
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
return arg_count;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
@ -664,80 +685,106 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
|
||||
#define FUNCTION_CHECK_IS_REG(r) \
|
||||
(((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \
|
||||
((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))
|
||||
(((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \
|
||||
|| ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))
|
||||
|
||||
#define FUNCTION_CHECK_IS_REG_OR_UNUSED(r) \
|
||||
((r) == SLJIT_UNUSED || \
|
||||
((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \
|
||||
((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))
|
||||
#define FUNCTION_CHECK_IS_FREG(fr) \
|
||||
(((fr) >= SLJIT_FR0 && (fr) < (SLJIT_FR0 + compiler->fscratches)) \
|
||||
|| ((fr) > (SLJIT_FS0 - compiler->fsaveds) && (fr) <= SLJIT_FS0))
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
#define CHECK_NOT_VIRTUAL_REGISTER(p) \
|
||||
CHECK_ARGUMENT((p) < SLJIT_R3 || (p) > SLJIT_R6);
|
||||
#define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8)
|
||||
#else
|
||||
#define CHECK_NOT_VIRTUAL_REGISTER(p)
|
||||
#define CHECK_IF_VIRTUAL_REGISTER(p) 0
|
||||
#endif
|
||||
|
||||
#define FUNCTION_CHECK_SRC(p, i) \
|
||||
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); \
|
||||
if (FUNCTION_CHECK_IS_REG(p)) \
|
||||
CHECK_ARGUMENT((i) == 0); \
|
||||
else if ((p) == SLJIT_IMM) \
|
||||
; \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else { \
|
||||
CHECK_ARGUMENT((p) & SLJIT_MEM); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
|
||||
CHECK_ARGUMENT(!((i) & ~0x3)); \
|
||||
} \
|
||||
CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
|
||||
static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if (compiler->scratches == -1 || compiler->saveds == -1)
|
||||
return 0;
|
||||
|
||||
if (!(p & SLJIT_MEM))
|
||||
return 0;
|
||||
|
||||
if (!((p & REG_MASK) == SLJIT_UNUSED || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
|
||||
return 0;
|
||||
|
||||
if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))
|
||||
return 0;
|
||||
|
||||
if (p & OFFS_REG_MASK) {
|
||||
if ((p & REG_MASK) == SLJIT_UNUSED)
|
||||
return 0;
|
||||
|
||||
if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))
|
||||
return 0;
|
||||
|
||||
if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p)))
|
||||
return 0;
|
||||
|
||||
if ((i & ~0x3) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0;
|
||||
}
|
||||
|
||||
#define FUNCTION_CHECK_SRC_MEM(p, i) \
|
||||
CHECK_ARGUMENT(function_check_src_mem(compiler, p, i));
|
||||
|
||||
static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if (compiler->scratches == -1 || compiler->saveds == -1)
|
||||
return 0;
|
||||
|
||||
if (FUNCTION_CHECK_IS_REG(p))
|
||||
return (i == 0);
|
||||
|
||||
if (p == SLJIT_IMM)
|
||||
return 1;
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
#define FUNCTION_CHECK_SRC(p, i) \
|
||||
CHECK_ARGUMENT(function_check_src(compiler, p, i));
|
||||
|
||||
static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 unused)
|
||||
{
|
||||
if (compiler->scratches == -1 || compiler->saveds == -1)
|
||||
return 0;
|
||||
|
||||
if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED))
|
||||
return (i == 0);
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
#define FUNCTION_CHECK_DST(p, i, unused) \
|
||||
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); \
|
||||
if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED)) \
|
||||
CHECK_ARGUMENT((i) == 0); \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else { \
|
||||
CHECK_ARGUMENT((p) & SLJIT_MEM); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
|
||||
CHECK_ARGUMENT(!((i) & ~0x3)); \
|
||||
} \
|
||||
CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
|
||||
}
|
||||
CHECK_ARGUMENT(function_check_dst(compiler, p, i, unused));
|
||||
|
||||
static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if (compiler->scratches == -1 || compiler->saveds == -1)
|
||||
return 0;
|
||||
|
||||
if (FUNCTION_CHECK_IS_FREG(p))
|
||||
return (i == 0);
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
#define FUNCTION_FCHECK(p, i) \
|
||||
CHECK_ARGUMENT(compiler->fscratches != -1 && compiler->fsaveds != -1); \
|
||||
if (((p) >= SLJIT_FR0 && (p) < (SLJIT_FR0 + compiler->fscratches)) || \
|
||||
((p) > (SLJIT_FS0 - compiler->fsaveds) && (p) <= SLJIT_FS0)) \
|
||||
CHECK_ARGUMENT(i == 0); \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else { \
|
||||
CHECK_ARGUMENT((p) & SLJIT_MEM); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
|
||||
CHECK_ARGUMENT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SP) && !(i & ~0x3)); \
|
||||
} \
|
||||
CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
|
||||
}
|
||||
CHECK_ARGUMENT(function_fcheck(compiler, p, i));
|
||||
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS */
|
||||
|
||||
@ -758,64 +805,72 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
|
||||
# define SLJIT_PRINT_D ""
|
||||
#endif
|
||||
|
||||
#define sljit_verbose_reg(compiler, r) \
|
||||
do { \
|
||||
if ((r) < (SLJIT_R0 + compiler->scratches)) \
|
||||
fprintf(compiler->verbose, "r%d", (r) - SLJIT_R0); \
|
||||
else if ((r) != SLJIT_SP) \
|
||||
fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - (r)); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "sp"); \
|
||||
} while (0)
|
||||
static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r)
|
||||
{
|
||||
if (r < (SLJIT_R0 + compiler->scratches))
|
||||
fprintf(compiler->verbose, "r%d", r - SLJIT_R0);
|
||||
else if (r != SLJIT_SP)
|
||||
fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r);
|
||||
else
|
||||
fprintf(compiler->verbose, "sp");
|
||||
}
|
||||
|
||||
#define sljit_verbose_param(compiler, p, i) \
|
||||
if ((p) & SLJIT_IMM) \
|
||||
fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
if ((p) & REG_MASK) { \
|
||||
fputc('[', compiler->verbose); \
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
fprintf(compiler->verbose, " + "); \
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p)); \
|
||||
if (i) \
|
||||
fprintf(compiler->verbose, " * %d", 1 << (i)); \
|
||||
} \
|
||||
else if (i) \
|
||||
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); \
|
||||
fputc(']', compiler->verbose); \
|
||||
} \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \
|
||||
} else if (p) \
|
||||
sljit_verbose_reg(compiler, p); \
|
||||
else \
|
||||
static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r)
|
||||
{
|
||||
if (r < (SLJIT_FR0 + compiler->fscratches))
|
||||
fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0);
|
||||
else
|
||||
fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r);
|
||||
}
|
||||
|
||||
static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if ((p) & SLJIT_IMM)
|
||||
fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i));
|
||||
else if ((p) & SLJIT_MEM) {
|
||||
if ((p) & REG_MASK) {
|
||||
fputc('[', compiler->verbose);
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK);
|
||||
if ((p) & OFFS_REG_MASK) {
|
||||
fprintf(compiler->verbose, " + ");
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p));
|
||||
if (i)
|
||||
fprintf(compiler->verbose, " * %d", 1 << (i));
|
||||
}
|
||||
else if (i)
|
||||
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));
|
||||
fputc(']', compiler->verbose);
|
||||
}
|
||||
else
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));
|
||||
} else if (p)
|
||||
sljit_verbose_reg(compiler, p);
|
||||
else
|
||||
fprintf(compiler->verbose, "unused");
|
||||
}
|
||||
|
||||
#define sljit_verbose_fparam(compiler, p, i) \
|
||||
if ((p) & SLJIT_MEM) { \
|
||||
if ((p) & REG_MASK) { \
|
||||
fputc('[', compiler->verbose); \
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
fprintf(compiler->verbose, " + "); \
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p)); \
|
||||
if (i) \
|
||||
fprintf(compiler->verbose, "%d", 1 << (i)); \
|
||||
} \
|
||||
else if (i) \
|
||||
fprintf(compiler->verbose, "%" SLJIT_PRINT_D "d", (i)); \
|
||||
fputc(']', compiler->verbose); \
|
||||
} \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \
|
||||
} \
|
||||
else { \
|
||||
if ((p) < (SLJIT_FR0 + compiler->fscratches)) \
|
||||
fprintf(compiler->verbose, "fr%d", (p) - SLJIT_FR0); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - (p)); \
|
||||
static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if ((p) & SLJIT_MEM) {
|
||||
if ((p) & REG_MASK) {
|
||||
fputc('[', compiler->verbose);
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK);
|
||||
if ((p) & OFFS_REG_MASK) {
|
||||
fprintf(compiler->verbose, " + ");
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p));
|
||||
if (i)
|
||||
fprintf(compiler->verbose, "%d", 1 << (i));
|
||||
}
|
||||
else if (i)
|
||||
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));
|
||||
fputc(']', compiler->verbose);
|
||||
}
|
||||
else
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));
|
||||
}
|
||||
else
|
||||
sljit_verbose_freg(compiler, p);
|
||||
}
|
||||
|
||||
static const char* op0_names[] = {
|
||||
(char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw",
|
||||
@ -864,7 +919,11 @@ static char* jump_names[] = {
|
||||
(char*)"greater", (char*)"less_equal",
|
||||
(char*)"unordered", (char*)"ordered",
|
||||
(char*)"jump", (char*)"fast_call",
|
||||
(char*)"call0", (char*)"call1", (char*)"call2", (char*)"call3"
|
||||
(char*)"call", (char*)"call.cdecl"
|
||||
};
|
||||
|
||||
static char* call_arg_names[] = {
|
||||
(char*)"void", (char*)"sw", (char*)"uw", (char*)"s32", (char*)"u32", (char*)"f32", (char*)"f64"
|
||||
};
|
||||
|
||||
#endif /* SLJIT_VERBOSE */
|
||||
@ -897,53 +956,104 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_com
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
sljit_s32 types, arg_count, curr_type;
|
||||
#endif
|
||||
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));
|
||||
CHECK_ARGUMENT(args >= 0 && args <= 3);
|
||||
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
CHECK_ARGUMENT(args <= saveds);
|
||||
CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
CHECK_ARGUMENT((arg_types & SLJIT_DEF_MASK) == 0);
|
||||
|
||||
types = (arg_types >> SLJIT_DEF_SHIFT);
|
||||
arg_count = 0;
|
||||
while (types != 0 && arg_count < 3) {
|
||||
curr_type = (types & SLJIT_DEF_MASK);
|
||||
CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW);
|
||||
arg_count++;
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
CHECK_ARGUMENT(arg_count <= saveds && types == 0);
|
||||
|
||||
compiler->last_flags = 0;
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose))
|
||||
fprintf(compiler->verbose, " enter options:none args:%d scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",
|
||||
args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " enter options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : "");
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
while (arg_types) {
|
||||
fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
if (arg_types)
|
||||
fprintf(compiler->verbose, ",");
|
||||
}
|
||||
|
||||
fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",
|
||||
scratches, saveds, fscratches, fsaveds, local_size);
|
||||
}
|
||||
#endif
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
sljit_s32 types, arg_count, curr_type;
|
||||
#endif
|
||||
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));
|
||||
CHECK_ARGUMENT(args >= 0 && args <= 3);
|
||||
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
CHECK_ARGUMENT(args <= saveds);
|
||||
CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
|
||||
types = (arg_types >> SLJIT_DEF_SHIFT);
|
||||
arg_count = 0;
|
||||
while (types != 0 && arg_count < 3) {
|
||||
curr_type = (types & SLJIT_DEF_MASK);
|
||||
CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW);
|
||||
arg_count++;
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
CHECK_ARGUMENT(arg_count <= saveds && types == 0);
|
||||
|
||||
compiler->last_flags = 0;
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose))
|
||||
fprintf(compiler->verbose, " set_context options:none args:%d scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",
|
||||
args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " set_context options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : "");
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
while (arg_types) {
|
||||
fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
if (arg_types)
|
||||
fprintf(compiler->verbose, ",");
|
||||
}
|
||||
|
||||
fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",
|
||||
scratches, saveds, fscratches, fsaveds, local_size);
|
||||
}
|
||||
#endif
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
@ -994,6 +1104,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
CHECK_ARGUMENT(src != SLJIT_IMM);
|
||||
compiler->last_flags = 0;
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
@ -1052,9 +1163,6 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_P:
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_U32:
|
||||
case SLJIT_MOVU_P:
|
||||
/* Nothing allowed */
|
||||
CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
||||
break;
|
||||
@ -1067,28 +1175,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
|
||||
FUNCTION_CHECK_DST(dst, dstw, 1);
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
|
||||
if (GET_OPCODE(op) >= SLJIT_NOT)
|
||||
if (GET_OPCODE(op) >= SLJIT_NOT) {
|
||||
CHECK_ARGUMENT(src != SLJIT_IMM);
|
||||
compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
|
||||
else if (GET_OPCODE(op) >= SLJIT_MOVU) {
|
||||
CHECK_ARGUMENT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_SP);
|
||||
CHECK_ARGUMENT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_SP);
|
||||
if ((src & REG_MASK) != SLJIT_UNUSED) {
|
||||
CHECK_ARGUMENT((src & REG_MASK) != (dst & REG_MASK) && (src & REG_MASK) != OFFS_REG(dst));
|
||||
CHECK_ARGUMENT((src & OFFS_REG_MASK) == SLJIT_UNUSED || srcw == 0);
|
||||
}
|
||||
if ((dst & REG_MASK) != SLJIT_UNUSED) {
|
||||
CHECK_ARGUMENT((dst & REG_MASK) != OFFS_REG(src));
|
||||
CHECK_ARGUMENT((dst & OFFS_REG_MASK) == SLJIT_UNUSED || dstw == 0);
|
||||
}
|
||||
compiler->last_flags = 0;
|
||||
}
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (GET_OPCODE(op) <= SLJIT_MOVU_P)
|
||||
if (GET_OPCODE(op) <= SLJIT_MOV_P)
|
||||
{
|
||||
fprintf(compiler->verbose, " mov%s%s%s ", (GET_OPCODE(op) >= SLJIT_MOVU) ? "u" : "",
|
||||
!(op & SLJIT_I32_OP) ? "" : "32", (op != SLJIT_MOV32 && op != SLJIT_MOVU32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : "");
|
||||
fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_I32_OP) ? "" : "32",
|
||||
(op != SLJIT_MOV32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : "");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1417,9 +1514,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
|
||||
CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));
|
||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_CALL3);
|
||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL);
|
||||
CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_I32_OP));
|
||||
CHECK_ARGUMENT((type & 0xff) <= SLJIT_CALL0 || ((type & 0xff) - SLJIT_CALL0) <= compiler->scratches);
|
||||
|
||||
if ((type & 0xff) < SLJIT_JUMP) {
|
||||
if ((type & 0xff) <= SLJIT_NOT_ZERO)
|
||||
@ -1439,6 +1535,63 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
sljit_s32 i, types, curr_type, scratches, fscratches;
|
||||
|
||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
|
||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);
|
||||
|
||||
types = arg_types;
|
||||
scratches = 0;
|
||||
fscratches = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
curr_type = (types & SLJIT_DEF_MASK);
|
||||
CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64);
|
||||
if (i > 0) {
|
||||
if (curr_type == 0) {
|
||||
break;
|
||||
}
|
||||
if (curr_type >= SLJIT_ARG_TYPE_F32)
|
||||
fscratches++;
|
||||
else
|
||||
scratches++;
|
||||
} else {
|
||||
if (curr_type >= SLJIT_ARG_TYPE_F32) {
|
||||
CHECK_ARGUMENT(compiler->fscratches > 0);
|
||||
} else if (curr_type >= SLJIT_ARG_TYPE_SW) {
|
||||
CHECK_ARGUMENT(compiler->scratches > 0);
|
||||
}
|
||||
}
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
CHECK_ARGUMENT(compiler->scratches >= scratches);
|
||||
CHECK_ARGUMENT(compiler->fscratches >= fscratches);
|
||||
CHECK_ARGUMENT(types == 0);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s ret[%s", jump_names[type & 0xff],
|
||||
!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]);
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
if (arg_types) {
|
||||
fprintf(compiler->verbose, "], args[");
|
||||
do {
|
||||
fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
if (arg_types)
|
||||
fprintf(compiler->verbose, ",");
|
||||
} while (arg_types);
|
||||
}
|
||||
fprintf(compiler->verbose, "]\n");
|
||||
}
|
||||
#endif
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w)
|
||||
@ -1488,20 +1641,16 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->last_flags = 0;
|
||||
#endif
|
||||
|
||||
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
|
||||
compiler->skip_checks = 0;
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_CALL3);
|
||||
CHECK_ARGUMENT(type <= SLJIT_CALL0 || (type - SLJIT_CALL0) <= compiler->scratches);
|
||||
CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL);
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
@ -1514,6 +1663,66 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compil
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
sljit_s32 i, types, curr_type, scratches, fscratches;
|
||||
|
||||
CHECK_ARGUMENT(type == SLJIT_CALL || type == SLJIT_CALL_CDECL);
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
|
||||
types = arg_types;
|
||||
scratches = 0;
|
||||
fscratches = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
curr_type = (types & SLJIT_DEF_MASK);
|
||||
CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64);
|
||||
if (i > 0) {
|
||||
if (curr_type == 0) {
|
||||
break;
|
||||
}
|
||||
if (curr_type >= SLJIT_ARG_TYPE_F32)
|
||||
fscratches++;
|
||||
else
|
||||
scratches++;
|
||||
} else {
|
||||
if (curr_type >= SLJIT_ARG_TYPE_F32) {
|
||||
CHECK_ARGUMENT(compiler->fscratches > 0);
|
||||
} else if (curr_type >= SLJIT_ARG_TYPE_SW) {
|
||||
CHECK_ARGUMENT(compiler->scratches > 0);
|
||||
}
|
||||
}
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
CHECK_ARGUMENT(compiler->scratches >= scratches);
|
||||
CHECK_ARGUMENT(compiler->fscratches >= fscratches);
|
||||
CHECK_ARGUMENT(types == 0);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff],
|
||||
!(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]);
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
if (arg_types) {
|
||||
fprintf(compiler->verbose, "], args[");
|
||||
do {
|
||||
fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
if (arg_types)
|
||||
fprintf(compiler->verbose, ",");
|
||||
} while (arg_types);
|
||||
}
|
||||
fprintf(compiler->verbose, "], ");
|
||||
sljit_verbose_param(compiler, src, srcw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 type)
|
||||
@ -1558,6 +1767,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
|
||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
|
||||
|
||||
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));
|
||||
if (src != SLJIT_IMM) {
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src));
|
||||
@ -1574,7 +1785,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " cmov%s %s%s, ",
|
||||
!(dst_reg & SLJIT_I32_OP) ? "" : ".i",
|
||||
!(dst_reg & SLJIT_I32_OP) ? "" : "32",
|
||||
jump_names[type & 0xff], JUMP_POSTFIX(type));
|
||||
sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
@ -1585,6 +1796,72 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
|
||||
CHECK_ARGUMENT(!(type & SLJIT_I32_OP) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P));
|
||||
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||
|
||||
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
|
||||
|
||||
CHECK_ARGUMENT((mem & REG_MASK) != SLJIT_UNUSED && (mem & REG_MASK) != reg);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
|
||||
fprintf(compiler->verbose, " //");
|
||||
|
||||
fprintf(compiler->verbose, " mem%s.%s%s%s ",
|
||||
!(type & SLJIT_I32_OP) ? "" : "32",
|
||||
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
||||
op1_names[(type & 0xff) - SLJIT_OP1_BASE],
|
||||
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
|
||||
sljit_verbose_reg(compiler, reg);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(compiler, mem, memw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
|
||||
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||
|
||||
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
|
||||
fprintf(compiler->verbose, " //");
|
||||
|
||||
fprintf(compiler->verbose, " fmem.%s%s%s ",
|
||||
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
||||
!(type & SLJIT_I32_OP) ? ".f64" : ".f32",
|
||||
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
|
||||
sljit_verbose_freg(compiler, freg);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(compiler, mem, memw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
||||
{
|
||||
/* Any offset is allowed. */
|
||||
@ -1858,6 +2135,49 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(reg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(freg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
||||
@ -1943,12 +2263,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(options);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(arg_types);
|
||||
SLJIT_UNUSED_ARG(scratches);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(fscratches);
|
||||
@ -1959,12 +2279,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(options);
|
||||
SLJIT_UNUSED_ARG(args);
|
||||
SLJIT_UNUSED_ARG(arg_types);
|
||||
SLJIT_UNUSED_ARG(scratches);
|
||||
SLJIT_UNUSED_ARG(saveds);
|
||||
SLJIT_UNUSED_ARG(fscratches);
|
||||
@ -2109,6 +2429,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(arg_types);
|
||||
SLJIT_UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w)
|
||||
@ -2161,6 +2491,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(arg_types);
|
||||
SLJIT_UNUSED_ARG(src);
|
||||
SLJIT_UNUSED_ARG(srcw);
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 type)
|
||||
@ -2187,6 +2530,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(reg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(freg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
|
421
src/3rdparty/pcre2/src/sljit/sljitLir.h
vendored
421
src/3rdparty/pcre2/src/sljit/sljitLir.h
vendored
@ -153,8 +153,8 @@ of sljitConfigInternal.h */
|
||||
is not available at all.
|
||||
*/
|
||||
|
||||
/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1 and
|
||||
and sljit_emit_op2 operations the result is discarded. If no status
|
||||
/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1
|
||||
or sljit_emit_op2 operations the result is discarded. If no status
|
||||
flags are set, no instructions are emitted for these operations. Data
|
||||
prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT
|
||||
operations do not support SLJIT_UNUSED as a destination operand. */
|
||||
@ -213,14 +213,6 @@ of sljitConfigInternal.h */
|
||||
|
||||
#define SLJIT_RETURN_REG SLJIT_R0
|
||||
|
||||
/* x86 prefers specific registers for special purposes. In case of shift
|
||||
by register it supports only SLJIT_R2 for shift argument
|
||||
(which is the src2 argument of sljit_emit_op2). If another register is
|
||||
used, sljit must exchange data between registers which cause a minor
|
||||
slowdown. Other architectures has no such limitation. */
|
||||
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Floating point registers */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -257,6 +249,79 @@ of sljitConfigInternal.h */
|
||||
/* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */
|
||||
#define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Argument type definitions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Argument type definitions.
|
||||
Used by SLJIT_[DEF_]ARGx and SLJIT_[DEF]_RET macros. */
|
||||
|
||||
#define SLJIT_ARG_TYPE_VOID 0
|
||||
#define SLJIT_ARG_TYPE_SW 1
|
||||
#define SLJIT_ARG_TYPE_UW 2
|
||||
#define SLJIT_ARG_TYPE_S32 3
|
||||
#define SLJIT_ARG_TYPE_U32 4
|
||||
#define SLJIT_ARG_TYPE_F32 5
|
||||
#define SLJIT_ARG_TYPE_F64 6
|
||||
|
||||
/* The following argument type definitions are used by sljit_emit_enter,
|
||||
sljit_set_context, sljit_emit_call, and sljit_emit_icall functions.
|
||||
The following return type definitions are used by sljit_emit_call
|
||||
and sljit_emit_icall functions.
|
||||
|
||||
When a function is called, the first integer argument must be placed
|
||||
in SLJIT_R0, the second in SLJIT_R1, and so on. Similarly the first
|
||||
floating point argument must be placed in SLJIT_FR0, the second in
|
||||
SLJIT_FR1, and so on.
|
||||
|
||||
Example function definition:
|
||||
sljit_f32 SLJIT_FUNC example_c_callback(sljit_sw arg_a,
|
||||
sljit_f64 arg_b, sljit_u32 arg_c, sljit_f32 arg_d);
|
||||
|
||||
Argument type definition:
|
||||
SLJIT_DEF_RET(SLJIT_ARG_TYPE_F32)
|
||||
| SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F64)
|
||||
| SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_U32) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F32)
|
||||
|
||||
Short form of argument type definition:
|
||||
SLJIT_RET(F32) | SLJIT_ARG1(SW) | SLJIT_ARG2(F64)
|
||||
| SLJIT_ARG3(S32) | SLJIT_ARG4(F32)
|
||||
|
||||
Argument passing:
|
||||
arg_a must be placed in SLJIT_R0
|
||||
arg_c must be placed in SLJIT_R1
|
||||
arg_b must be placed in SLJIT_FR0
|
||||
arg_d must be placed in SLJIT_FR1
|
||||
|
||||
Note:
|
||||
The SLJIT_ARG_TYPE_VOID type is only supported by
|
||||
SLJIT_DEF_RET, and SLJIT_ARG_TYPE_VOID is also the
|
||||
default value when SLJIT_DEF_RET is not specified. */
|
||||
#define SLJIT_DEF_SHIFT 4
|
||||
#define SLJIT_DEF_RET(type) (type)
|
||||
#define SLJIT_DEF_ARG1(type) ((type) << SLJIT_DEF_SHIFT)
|
||||
#define SLJIT_DEF_ARG2(type) ((type) << (2 * SLJIT_DEF_SHIFT))
|
||||
#define SLJIT_DEF_ARG3(type) ((type) << (3 * SLJIT_DEF_SHIFT))
|
||||
#define SLJIT_DEF_ARG4(type) ((type) << (4 * SLJIT_DEF_SHIFT))
|
||||
|
||||
/* Short form of the macros above.
|
||||
|
||||
For example the following definition:
|
||||
SLJIT_DEF_RET(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_F32)
|
||||
|
||||
can be shortened to:
|
||||
SLJIT_RET(SW) | SLJIT_ARG1(F32)
|
||||
|
||||
Note:
|
||||
The VOID type is only supported by SLJIT_RET, and
|
||||
VOID is also the default value when SLJIT_RET is
|
||||
not specified. */
|
||||
#define SLJIT_RET(type) SLJIT_DEF_RET(SLJIT_ARG_TYPE_ ## type)
|
||||
#define SLJIT_ARG1(type) SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_ ## type)
|
||||
#define SLJIT_ARG2(type) SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_ ## type)
|
||||
#define SLJIT_ARG3(type) SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_ ## type)
|
||||
#define SLJIT_ARG4(type) SLJIT_DEF_ARG4(SLJIT_ARG_TYPE_ ## type)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Main structures and functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -331,6 +396,7 @@ struct sljit_compiler {
|
||||
sljit_s32 args;
|
||||
sljit_s32 locals_offset;
|
||||
sljit_s32 saveds_offset;
|
||||
sljit_s32 stack_tmp_size;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
@ -356,15 +422,8 @@ struct sljit_compiler {
|
||||
sljit_uw shift_imm;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
sljit_s32 cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
sljit_sw imm;
|
||||
sljit_s32 cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
@ -499,14 +558,10 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
|
||||
#define SLJIT_HAS_FPU 0
|
||||
/* [Limitation] Some registers are virtual registers. */
|
||||
#define SLJIT_HAS_VIRTUAL_REGISTERS 1
|
||||
/* [Emulated] Some forms of move with pre update is supported. */
|
||||
#define SLJIT_HAS_PRE_UPDATE 2
|
||||
/* [Emulated] Count leading zero is supported. */
|
||||
#define SLJIT_HAS_CLZ 3
|
||||
#define SLJIT_HAS_CLZ 2
|
||||
/* [Emulated] Conditional move is supported. */
|
||||
#define SLJIT_HAS_CMOV 4
|
||||
/* [Limitation] [Emulated] Shifting with register is limited to SLJIT_PREF_SHIFT_REG. */
|
||||
#define SLJIT_HAS_PREF_SHIFT_REG 5
|
||||
#define SLJIT_HAS_CMOV 3
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
/* [Not emulated] SSE2 support is available on x86. */
|
||||
@ -519,27 +574,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
error, they return with SLJIT_SUCCESS. */
|
||||
|
||||
/*
|
||||
The executable code is a function call from the viewpoint of the C
|
||||
The executable code is a function from the viewpoint of the C
|
||||
language. The function calls must obey to the ABI (Application
|
||||
Binary Interface) of the platform, which specify the purpose of
|
||||
all machine registers and stack handling among other things. The
|
||||
machine registers and stack handling among other things. The
|
||||
sljit_emit_enter function emits the necessary instructions for
|
||||
setting up a new context for the executable code and moves function
|
||||
arguments to the saved registers. Furthermore the options argument
|
||||
can be used to pass configuration options to the compiler. The
|
||||
available options are listed before sljit_emit_enter.
|
||||
|
||||
The number of sljit_sw arguments passed to the generated function
|
||||
are specified in the "args" parameter. The number of arguments must
|
||||
be less than or equal to 3. The first argument goes to SLJIT_S0,
|
||||
the second goes to SLJIT_S1 and so on. The register set used by
|
||||
the function must be declared as well. The number of scratch and
|
||||
saved registers used by the function must be passed to sljit_emit_enter.
|
||||
Only R registers between R0 and "scratches" argument can be used
|
||||
later. E.g. if "scratches" is set to 2, the register set will be
|
||||
limited to R0 and R1. The S registers and the floating point
|
||||
The function argument list is the combination of SLJIT_ARGx
|
||||
(SLJIT_DEF_ARG1) macros. Currently maximum 3 SW / UW
|
||||
(SLJIT_ARG_TYPE_SW / LJIT_ARG_TYPE_UW) arguments are supported.
|
||||
The first argument goes to SLJIT_S0, the second goes to SLJIT_S1
|
||||
and so on. The register set used by the function must be declared
|
||||
as well. The number of scratch and saved registers used by the
|
||||
function must be passed to sljit_emit_enter. Only R registers
|
||||
between R0 and "scratches" argument can be used later. E.g. if
|
||||
"scratches" is set to 2, the scratch register set will be limited
|
||||
to SLJIT_R0 and SLJIT_R1. The S registers and the floating point
|
||||
registers ("fscratches" and "fsaveds") are specified in a similar
|
||||
way. The sljit_emit_enter is also capable of allocating a stack
|
||||
manner. The sljit_emit_enter is also capable of allocating a stack
|
||||
space for local variables. The "local_size" argument contains the
|
||||
size in bytes of this local area and its staring address is stored
|
||||
in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and
|
||||
@ -566,7 +622,7 @@ offset 0 is aligned to sljit_f64. Otherwise it is aligned to sljit_sw. */
|
||||
#define SLJIT_MAX_LOCAL_SIZE 65536
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);
|
||||
|
||||
/* The machine code has a context (which contains the local stack space size,
|
||||
@ -580,7 +636,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
the previous context. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);
|
||||
|
||||
/* Return from machine code. The op argument can be SLJIT_UNUSED which means the
|
||||
@ -592,26 +648,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
/* Fast calling mechanism for utility functions (see SLJIT_FAST_CALL). All registers and
|
||||
even the stack frame is passed to the callee. The return address is preserved in
|
||||
dst/dstw by sljit_emit_fast_enter (the type of the value stored by this function
|
||||
is sljit_p), and sljit_emit_fast_return can use this as a return value later. */
|
||||
/* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL).
|
||||
Both sljit_emit_fast_enter and sljit_emit_fast_return functions preserve the
|
||||
values of all registers and stack frame. The return address is stored in the
|
||||
dst argument of sljit_emit_fast_enter, and this return address can be passed
|
||||
to sljit_emit_fast_return to continue the execution after the fast call.
|
||||
|
||||
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine
|
||||
instructions are needed. Excellent for small uility functions, where saving registers
|
||||
and setting up a new stack frame would cost too much performance. However, it is still
|
||||
possible to return to the address of the caller (or anywhere else). */
|
||||
Fast calls are cheap operations (usually only a single call instruction is
|
||||
emitted) but they do not preserve any registers. However the callee function
|
||||
can freely use / update any registers and stack values which can be
|
||||
efficiently exploited by various optimizations. Registers can be saved
|
||||
manually by the callee function if needed.
|
||||
|
||||
/* Note: may destroy flags. */
|
||||
Although returning to different address by sljit_emit_fast_return is possible,
|
||||
this address usually cannot be predicted by the return address predictor of
|
||||
modern CPUs which may reduce performance. Furthermore using sljit_emit_ijump
|
||||
to return is also inefficient since return address prediction is usually
|
||||
triggered by a specific form of ijump.
|
||||
|
||||
/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested,
|
||||
since many architectures do clever branch prediction on call / return instruction pairs. */
|
||||
Flags: - (does not modify flags). */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
/*
|
||||
Source and destination values for arithmetical instructions
|
||||
Source and destination operands for arithmetical instructions
|
||||
imm - a simple immediate value (cannot be used as a destination)
|
||||
reg - any of the registers (immediate argument must be 0)
|
||||
[imm] - absolute immediate memory address
|
||||
@ -652,6 +713,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
arm-t2: [reg+imm], -255 <= imm <= 4095
|
||||
[reg+(reg<<imm)] is supported
|
||||
Write back is supported only for [reg+imm], where -255 <= imm <= 255
|
||||
arm64: [reg+imm], -256 <= imm <= 255, 0 <= aligned imm <= 4095 * alignment
|
||||
[reg+(reg<<imm)] is supported
|
||||
Write back is supported only for [reg+imm], where -256 <= imm <= 255
|
||||
ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit
|
||||
signed load on 64 bit requires immediates divisible by 4.
|
||||
[reg+imm] is not supported for signed 8 bit values.
|
||||
@ -663,8 +727,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
[reg+reg] is supported
|
||||
*/
|
||||
|
||||
/* Register output: simply the name of the register.
|
||||
For destination, you can use SLJIT_UNUSED as well. */
|
||||
/* Macros for specifying operand types. */
|
||||
#define SLJIT_MEM 0x80
|
||||
#define SLJIT_MEM0() (SLJIT_MEM)
|
||||
#define SLJIT_MEM1(r1) (SLJIT_MEM | (r1))
|
||||
@ -833,43 +896,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
||||
S32 - signed int (32 bit) data transfer
|
||||
P - pointer (sljit_p) data transfer
|
||||
|
||||
U = move with update (pre form). If source or destination defined as
|
||||
SLJIT_MEM1(r1) or SLJIT_MEM2(r1, r2), r1 is increased by the
|
||||
offset part of the address.
|
||||
|
||||
Register arguments and base registers can only be used once for move
|
||||
with update instructions. The shift value of SLJIT_MEM2 addressing
|
||||
mode must also be 0. Reason: SLJIT_MOVU instructions are expected to
|
||||
be in high-performance loops where complex instruction emulation
|
||||
would be too costly.
|
||||
|
||||
Examples for invalid move with update instructions:
|
||||
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 8);
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_R0, 0);
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 0, SLJIT_MEM1(SLJIT_R0), 8);
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0);
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_R2, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1);
|
||||
|
||||
The following example is valid, since only the offset register is
|
||||
used multiple times:
|
||||
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_MEM2(SLJIT_R0, SLJIT_R2), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);
|
||||
|
||||
If the destination of a MOV without update instruction is SLJIT_UNUSED
|
||||
and the source operand is a memory address the compiler emits a prefetch
|
||||
instruction if this instruction is supported by the current CPU.
|
||||
Higher data sizes bring the data closer to the core: a MOV with word
|
||||
size loads the data into a higher level cache than a byte size. Otherwise
|
||||
the type does not affect the prefetch instruction. Furthermore a prefetch
|
||||
instruction never fails, so it can be used to prefetch a data from an
|
||||
address and check whether that address is NULL afterwards.
|
||||
If the destination of a MOV instruction is SLJIT_UNUSED and the source
|
||||
operand is a memory address the compiler emits a prefetch instruction
|
||||
if this instruction is supported by the current CPU. Higher data sizes
|
||||
bring the data closer to the core: a MOV with word size loads the data
|
||||
into a higher level cache than a byte size. Otherwise the type does not
|
||||
affect the prefetch instruction. Furthermore a prefetch instruction
|
||||
never fails, so it can be used to prefetch a data from an address and
|
||||
check whether that address is NULL afterwards.
|
||||
*/
|
||||
|
||||
/* Flags: - (does not modify flags) */
|
||||
@ -894,41 +928,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
||||
#define SLJIT_MOV_S32 (SLJIT_OP1_BASE + 6)
|
||||
/* Flags: - (does not modify flags) */
|
||||
#define SLJIT_MOV32 (SLJIT_MOV_S32 | SLJIT_I32_OP)
|
||||
/* Flags: - (does not modify flags) */
|
||||
/* Flags: - (does not modify flags)
|
||||
Note: load a pointer sized data, useful on x32 (a 32 bit mode on x86-64
|
||||
where all x64 features are available, e.g. 16 register) or similar
|
||||
compiling modes */
|
||||
#define SLJIT_MOV_P (SLJIT_OP1_BASE + 7)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU (SLJIT_OP1_BASE + 8)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_U8 (SLJIT_OP1_BASE + 9)
|
||||
#define SLJIT_MOVU32_U8 (SLJIT_MOVU_U8 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_S8 (SLJIT_OP1_BASE + 10)
|
||||
#define SLJIT_MOVU32_S8 (SLJIT_MOVU_S8 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_U16 (SLJIT_OP1_BASE + 11)
|
||||
#define SLJIT_MOVU32_U16 (SLJIT_MOVU_U16 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_S16 (SLJIT_OP1_BASE + 12)
|
||||
#define SLJIT_MOVU32_S16 (SLJIT_MOVU_S16 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags)
|
||||
Note: no SLJIT_MOVU32_U32 form, since it is the same as SLJIT_MOVU32 */
|
||||
#define SLJIT_MOVU_U32 (SLJIT_OP1_BASE + 13)
|
||||
/* Flags: - (may destroy flags)
|
||||
Note: no SLJIT_MOVU32_S32 form, since it is the same as SLJIT_MOVU32 */
|
||||
#define SLJIT_MOVU_S32 (SLJIT_OP1_BASE + 14)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU32 (SLJIT_MOVU_S32 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_P (SLJIT_OP1_BASE + 15)
|
||||
/* Flags: Z */
|
||||
#define SLJIT_NOT (SLJIT_OP1_BASE + 16)
|
||||
/* Flags: Z
|
||||
Note: immediate source argument is not supported */
|
||||
#define SLJIT_NOT (SLJIT_OP1_BASE + 8)
|
||||
#define SLJIT_NOT32 (SLJIT_NOT | SLJIT_I32_OP)
|
||||
/* Flags: Z | OVERFLOW */
|
||||
#define SLJIT_NEG (SLJIT_OP1_BASE + 17)
|
||||
/* Flags: Z | OVERFLOW
|
||||
Note: immediate source argument is not supported */
|
||||
#define SLJIT_NEG (SLJIT_OP1_BASE + 9)
|
||||
#define SLJIT_NEG32 (SLJIT_NEG | SLJIT_I32_OP)
|
||||
/* Count leading zeroes
|
||||
Flags: - (may destroy flags) */
|
||||
#define SLJIT_CLZ (SLJIT_OP1_BASE + 18)
|
||||
Flags: - (may destroy flags)
|
||||
Note: immediate source argument is not supported */
|
||||
#define SLJIT_CLZ (SLJIT_OP1_BASE + 10)
|
||||
#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_I32_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
@ -1136,25 +1152,32 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
||||
|
||||
/* Unconditional jump types. */
|
||||
#define SLJIT_JUMP 24
|
||||
/* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */
|
||||
#define SLJIT_FAST_CALL 25
|
||||
#define SLJIT_CALL0 26
|
||||
#define SLJIT_CALL1 27
|
||||
#define SLJIT_CALL2 28
|
||||
#define SLJIT_CALL3 29
|
||||
|
||||
/* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */
|
||||
/* Called function must be declared with the SLJIT_FUNC attribute. */
|
||||
#define SLJIT_CALL 26
|
||||
/* Called function must be decalred with cdecl attribute.
|
||||
This is the default attribute for C functions. */
|
||||
#define SLJIT_CALL_CDECL 27
|
||||
|
||||
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
|
||||
#define SLJIT_REWRITABLE_JUMP 0x1000
|
||||
|
||||
/* Emit a jump instruction. The destination is not set, only the type of the jump.
|
||||
type must be between SLJIT_EQUAL and SLJIT_CALL3
|
||||
type must be between SLJIT_EQUAL and SLJIT_FAST_CALL
|
||||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
|
||||
|
||||
Flags: does not modify flags for conditional and unconditional
|
||||
jumps but destroy all flags for calls. */
|
||||
Flags: does not modify flags. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type);
|
||||
|
||||
/* Emit a C compiler (ABI) compatible function call.
|
||||
type must be SLJIT_CALL or SLJIT_CALL_CDECL
|
||||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
|
||||
arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros
|
||||
|
||||
Flags: destroy all flags. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types);
|
||||
|
||||
/* Basic arithmetic comparison. In most architectures it is implemented as
|
||||
an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
|
||||
appropriate flags) followed by a sljit_emit_jump. However some
|
||||
@ -1162,6 +1185,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
It is suggested to use this comparison form when appropriate.
|
||||
type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL
|
||||
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
|
||||
|
||||
Flags: may destroy flags. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
@ -1186,15 +1210,23 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl
|
||||
/* Set the destination address of the jump to this label. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);
|
||||
|
||||
/* Call function or jump anywhere. Both direct and indirect form
|
||||
type must be between SLJIT_JUMP and SLJIT_CALL3
|
||||
Direct form: set src to SLJIT_IMM() and srcw to the address
|
||||
Indirect form: any other valid addressing mode
|
||||
/* Emit an indirect jump or fast call. Both direct and indirect form
|
||||
Direct form: set src to SLJIT_IMM() and srcw to the address
|
||||
Indirect form: any other valid addressing mode
|
||||
type must be between SLJIT_JUMP and SLJIT_FAST_CALL
|
||||
|
||||
Flags: does not modify flags for unconditional jumps but
|
||||
destroy all flags for calls. */
|
||||
Flags: does not modify flags. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
/* Emit a C compiler (ABI) compatible function call.
|
||||
Direct form: set src to SLJIT_IMM() and srcw to the address
|
||||
Indirect form: any other valid addressing mode
|
||||
type must be SLJIT_CALL or SLJIT_CALL_CDECL
|
||||
arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros
|
||||
|
||||
Flags: destroy all flags. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
/* Perform the operation using the conditional flags as the second argument.
|
||||
Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_F64. The value
|
||||
represented by the type is 1, if the condition represented by the type
|
||||
@ -1213,7 +1245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||
|
||||
/* Emit a conditional mov instruction which moves source to destination,
|
||||
if the condition is satisfied. Unlike other arithmetic operations this
|
||||
instruction does not support memory accesses.
|
||||
instruction does not support memory access.
|
||||
|
||||
type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64
|
||||
dst_reg must be a valid register and it can be combined
|
||||
@ -1225,6 +1257,51 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
||||
sljit_s32 dst_reg,
|
||||
sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */
|
||||
|
||||
/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.
|
||||
Instead the function returns with SLJIT_SUCCESS if the instruction
|
||||
form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag
|
||||
allows runtime checking of available instruction forms. */
|
||||
#define SLJIT_MEM_SUPP 0x0200
|
||||
/* Memory load operation. This is the default. */
|
||||
#define SLJIT_MEM_LOAD 0x0000
|
||||
/* Memory store operation. */
|
||||
#define SLJIT_MEM_STORE 0x0400
|
||||
/* Base register is updated before the memory access. */
|
||||
#define SLJIT_MEM_PRE 0x0800
|
||||
/* Base register is updated after the memory access. */
|
||||
#define SLJIT_MEM_POST 0x1000
|
||||
|
||||
/* Emit a single memory load or store with update instruction. When the
|
||||
requested instruction from is not supported by the CPU, it returns
|
||||
with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This
|
||||
allows specializing tight loops based on the supported instruction
|
||||
forms (see SLJIT_MEM_SUPP flag).
|
||||
|
||||
type must be between SLJIT_MOV and SLJIT_MOV_P and can be
|
||||
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
|
||||
or SLJIT_MEM_POST must be specified.
|
||||
reg is the source or destination register, and must be
|
||||
different from the base register of the mem operand
|
||||
mem must be a SLJIT_MEM1() or SLJIT_MEM2() operand
|
||||
|
||||
Flags: - (does not modify flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw);
|
||||
|
||||
/* Same as sljit_emit_mem except the followings:
|
||||
|
||||
type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be
|
||||
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
|
||||
or SLJIT_MEM_POST must be specified.
|
||||
freg is the source or destination floating point register */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw);
|
||||
|
||||
/* Copies the base address of SLJIT_SP + offset to dst. The offset can be
|
||||
anything to negate the effect of relative addressing. For example if an
|
||||
array of sljit_sw values is stored on the stack from offset 0x40, and R0
|
||||
@ -1270,58 +1347,58 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void);
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
/* This global lock is useful to compile common functions. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void);
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
|
||||
|
||||
/* The sljit_stack is a utility extension of sljit, which provides
|
||||
a top-down stack. The stack starts at base and goes down to
|
||||
max_limit, so the memory region for this stack is between
|
||||
max_limit (inclusive) and base (exclusive). However the
|
||||
application can only use the region between limit (inclusive)
|
||||
and base (exclusive). The sljit_stack_resize can be used to
|
||||
extend this region up to max_limit.
|
||||
/* The sljit_stack structure and its manipulation functions provides
|
||||
an implementation for a top-down stack. The stack top is stored
|
||||
in the end field of the sljit_stack structure and the stack goes
|
||||
down to the min_start field, so the memory region reserved for
|
||||
this stack is between min_start (inclusive) and end (exclusive)
|
||||
fields. However the application can only use the region between
|
||||
start (inclusive) and end (exclusive) fields. The sljit_stack_resize
|
||||
function can be used to extend this region up to min_start.
|
||||
|
||||
This feature uses the "address space reserve" feature of modern
|
||||
operating systems, so instead of allocating a huge memory block
|
||||
applications can allocate a small region and extend it later
|
||||
without moving the memory area. Hence pointers can be stored
|
||||
in this area. */
|
||||
operating systems. Instead of allocating a large memory block
|
||||
applications can allocate a small memory region and extend it
|
||||
later without moving the content of the memory area. Therefore
|
||||
after a successful resize by sljit_stack_resize all pointers into
|
||||
this region are still valid.
|
||||
|
||||
/* Note: base and max_limit fields are aligned to PAGE_SIZE bytes
|
||||
(usually 4 Kbyte or more).
|
||||
Note: stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more.
|
||||
Note: this structure may not be supported by all operating systems.
|
||||
Some kind of fallback mechanism is suggested when SLJIT_UTIL_STACK
|
||||
is not defined. */
|
||||
Note:
|
||||
this structure may not be supported by all operating systems.
|
||||
end and max_limit fields are aligned to PAGE_SIZE bytes (usually
|
||||
4 Kbyte or more).
|
||||
stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more. */
|
||||
|
||||
struct sljit_stack {
|
||||
/* User data, anything can be stored here.
|
||||
Starting with the same value as base. */
|
||||
Initialized to the same value as the end field. */
|
||||
sljit_u8 *top;
|
||||
/* These members are read only. */
|
||||
sljit_u8 *base;
|
||||
sljit_u8 *limit;
|
||||
sljit_u8 *max_limit;
|
||||
/* These members are read only. */
|
||||
/* End address of the stack */
|
||||
sljit_u8 *end;
|
||||
/* Current start address of the stack. */
|
||||
sljit_u8 *start;
|
||||
/* Lowest start address of the stack. */
|
||||
sljit_u8 *min_start;
|
||||
};
|
||||
|
||||
/* Returns NULL if unsuccessful.
|
||||
Note: max_limit contains the maximum stack size in bytes.
|
||||
Note: limit contains the starting stack size in bytes.
|
||||
Note: the top field is initialized to base.
|
||||
/* Allocates a new stack. Returns NULL if unsuccessful.
|
||||
Note: see sljit_create_compiler for the explanation of allocator_data. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *stack, void *allocator_data);
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data);
|
||||
|
||||
/* Can be used to increase (allocate) or decrease (free) the memory area.
|
||||
Returns with a non-zero value if unsuccessful. If new_limit is greater than
|
||||
max_limit, it will fail. It is very easy to implement a stack data structure,
|
||||
since the growth ratio can be added to the current limit, and sljit_stack_resize
|
||||
will do all the necessary checks. The fields of the stack are not changed if
|
||||
sljit_stack_resize fails. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit);
|
||||
/* Can be used to increase (extend) or decrease (shrink) the stack
|
||||
memory area. Returns with new_start if successful and NULL otherwise.
|
||||
It always fails if new_start is less than min_start or greater or equal
|
||||
than end fields. The fields of the stack are not changed if the returned
|
||||
value is NULL (the current memory content is never lost). */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start);
|
||||
|
||||
#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */
|
||||
|
||||
|
750
src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c
vendored
750
src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c
vendored
File diff suppressed because it is too large
Load Diff
746
src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c
vendored
746
src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c
vendored
File diff suppressed because it is too large
Load Diff
535
src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
vendored
535
src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
vendored
@ -26,7 +26,11 @@
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
||||
{
|
||||
return "ARM-Thumb2" SLJIT_CPUINFO;
|
||||
#ifdef __SOFTFP__
|
||||
return "ARM-Thumb2" SLJIT_CPUINFO " ABI:softfp";
|
||||
#else
|
||||
return "ARM-Thumb2" SLJIT_CPUINFO " ABI:hardfp";
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Length of an instruction word. */
|
||||
@ -37,12 +41,16 @@ typedef sljit_u32 sljit_ins;
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
|
||||
|
||||
/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
|
||||
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
0, 0, 1, 2, 12, 11, 10, 9, 8, 7, 6, 5, 4, 13, 3, 14, 15
|
||||
0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15
|
||||
};
|
||||
|
||||
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 7
|
||||
};
|
||||
|
||||
#define COPY_BITS(src, from, to, bits) \
|
||||
@ -69,9 +77,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
#define RN4(rn) (reg_map[rn] << 16)
|
||||
#define RM4(rm) (reg_map[rm])
|
||||
#define RT4(rt) (reg_map[rt] << 12)
|
||||
#define DD4(dd) ((dd) << 12)
|
||||
#define DN4(dn) ((dn) << 16)
|
||||
#define DM4(dm) (dm)
|
||||
#define DD4(dd) (freg_map[dd] << 12)
|
||||
#define DN4(dn) (freg_map[dn] << 16)
|
||||
#define DM4(dm) (freg_map[dm])
|
||||
#define IMM5(imm) \
|
||||
(COPY_BITS(imm, 2, 12, 3) | ((imm & 0x3) << 6))
|
||||
#define IMM12(imm) \
|
||||
@ -178,6 +186,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
#define VDIV_F32 0xee800a00
|
||||
#define VMOV_F32 0xeeb00a40
|
||||
#define VMOV 0xee000a10
|
||||
#define VMOV2 0xec400a10
|
||||
#define VMRS 0xeef1fa10
|
||||
#define VMUL_F32 0xee200a00
|
||||
#define VNEG_F32 0xeeb10a40
|
||||
@ -208,10 +217,10 @@ static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)
|
||||
{
|
||||
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) |
|
||||
COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
|
||||
return push_inst32(compiler, MOVT | RD4(dst) |
|
||||
COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
|
||||
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst)
|
||||
| COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
|
||||
return push_inst32(compiler, MOVT | RD4(dst)
|
||||
| COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm)
|
||||
@ -444,7 +453,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
case SLJIT_HAS_PRE_UPDATE:
|
||||
case SLJIT_HAS_CLZ:
|
||||
case SLJIT_HAS_CMOV:
|
||||
return 1;
|
||||
@ -522,13 +530,13 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst,
|
||||
}
|
||||
|
||||
/* set low 16 bits, set hi 16 bits to 0. */
|
||||
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) |
|
||||
COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
|
||||
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst)
|
||||
| COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
|
||||
|
||||
/* set hi 16 bit if needed. */
|
||||
if (imm >= 0x10000)
|
||||
return push_inst32(compiler, MOVT | RD4(dst) |
|
||||
COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
|
||||
return push_inst32(compiler, MOVT | RD4(dst)
|
||||
| COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -729,34 +737,26 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_U32:
|
||||
case SLJIT_MOVU_S32:
|
||||
case SLJIT_MOVU_P:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (dst == arg2)
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOVU_U8:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (IS_2_LO_REGS(dst, arg2))
|
||||
return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2));
|
||||
return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2));
|
||||
case SLJIT_MOV_S8:
|
||||
case SLJIT_MOVU_S8:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (IS_2_LO_REGS(dst, arg2))
|
||||
return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2));
|
||||
return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2));
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOVU_U16:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (IS_2_LO_REGS(dst, arg2))
|
||||
return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2));
|
||||
return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2));
|
||||
case SLJIT_MOV_S16:
|
||||
case SLJIT_MOVU_S16:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (IS_2_LO_REGS(dst, arg2))
|
||||
return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2));
|
||||
@ -840,8 +840,6 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||
#define HALF_SIZE 0x08
|
||||
#define PRELOAD 0x0c
|
||||
|
||||
#define UPDATE 0x10
|
||||
|
||||
#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))
|
||||
#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))
|
||||
|
||||
@ -940,12 +938,10 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
||||
sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
|
||||
{
|
||||
sljit_s32 other_r;
|
||||
sljit_s32 update = flags & UPDATE;
|
||||
sljit_uw tmp;
|
||||
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
|
||||
flags &= ~UPDATE;
|
||||
arg &= ~SLJIT_MEM;
|
||||
|
||||
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
|
||||
@ -961,63 +957,6 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg));
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(update)) {
|
||||
SLJIT_ASSERT(reg != arg);
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
other_r = OFFS_REG(arg);
|
||||
arg &= 0xf;
|
||||
|
||||
if (IS_3_LO_REGS(reg, arg, other_r))
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
|
||||
else
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r)));
|
||||
return push_inst16(compiler, ADD | SET_REGS44(arg, other_r));
|
||||
}
|
||||
|
||||
if (argw > 0xff) {
|
||||
tmp = get_imm(argw & ~0xff);
|
||||
if (tmp != INVALID_IMM) {
|
||||
push_inst32(compiler, ADD_WI | RD4(arg) | RN4(arg) | tmp);
|
||||
argw = argw & 0xff;
|
||||
}
|
||||
}
|
||||
else if (argw < -0xff) {
|
||||
tmp = get_imm(-argw & ~0xff);
|
||||
if (tmp != INVALID_IMM) {
|
||||
push_inst32(compiler, SUB_WI | RD4(arg) | RN4(arg) | tmp);
|
||||
argw = -(-argw & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
if (argw == 0) {
|
||||
if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags])
|
||||
return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg));
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg));
|
||||
}
|
||||
|
||||
if (argw <= 0xff && argw >= -0xff) {
|
||||
if (argw >= 0)
|
||||
argw |= 0x200;
|
||||
else {
|
||||
argw = -argw;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff);
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw);
|
||||
}
|
||||
|
||||
FAIL_IF(load_immediate(compiler, tmp_reg, argw));
|
||||
|
||||
SLJIT_ASSERT(reg != tmp_reg);
|
||||
|
||||
if (IS_3_LO_REGS(reg, arg, tmp_reg))
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg)));
|
||||
else
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg)));
|
||||
return push_inst16(compiler, ADD | SET_REGS44(arg, tmp_reg));
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
argw &= 0x3;
|
||||
other_r = OFFS_REG(arg);
|
||||
@ -1088,15 +1027,15 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_s32 size, i, tmp;
|
||||
sljit_s32 args, size, i, tmp;
|
||||
sljit_ins push = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
|
||||
for (i = SLJIT_S0; i >= tmp; i--)
|
||||
@ -1120,6 +1059,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, local_size));
|
||||
}
|
||||
|
||||
args = get_arg_count(arg_types);
|
||||
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0, SLJIT_R0)));
|
||||
if (args >= 2)
|
||||
@ -1131,14 +1072,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_s32 size;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
|
||||
compiler->local_size = ((size + local_size + 7) & ~7) - size;
|
||||
@ -1219,11 +1160,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
||||
case SLJIT_DIV_UW:
|
||||
case SLJIT_DIV_SW:
|
||||
SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
|
||||
SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12);
|
||||
SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);
|
||||
|
||||
saved_reg_count = 0;
|
||||
if (compiler->scratches >= 4)
|
||||
saved_reg_list[saved_reg_count++] = 12;
|
||||
saved_reg_list[saved_reg_count++] = 3;
|
||||
if (compiler->scratches >= 3)
|
||||
saved_reg_list[saved_reg_count++] = 2;
|
||||
if (op >= SLJIT_DIV_UW)
|
||||
@ -1289,7 +1230,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_U32:
|
||||
@ -1317,32 +1258,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_s16)srcw;
|
||||
break;
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_U32:
|
||||
case SLJIT_MOVU_S32:
|
||||
case SLJIT_MOVU_P:
|
||||
flags = WORD_SIZE | UPDATE;
|
||||
break;
|
||||
case SLJIT_MOVU_U8:
|
||||
flags = BYTE_SIZE | UPDATE;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_u8)srcw;
|
||||
break;
|
||||
case SLJIT_MOVU_S8:
|
||||
flags = BYTE_SIZE | SIGNED | UPDATE;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_s8)srcw;
|
||||
break;
|
||||
case SLJIT_MOVU_U16:
|
||||
flags = HALF_SIZE | UPDATE;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_u16)srcw;
|
||||
break;
|
||||
case SLJIT_MOVU_S16:
|
||||
flags = HALF_SIZE | SIGNED | UPDATE;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_s16)srcw;
|
||||
break;
|
||||
default:
|
||||
SLJIT_UNREACHABLE();
|
||||
flags = 0;
|
||||
@ -1352,7 +1267,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
if (src & SLJIT_IMM)
|
||||
FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, srcw));
|
||||
else if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, ((flags & UPDATE) && dst_r == TMP_REG1) ? TMP_REG2 : TMP_REG1));
|
||||
FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1));
|
||||
} else {
|
||||
if (dst_r != TMP_REG1)
|
||||
return emit_op_imm(compiler, op, dst_r, TMP_REG2, src);
|
||||
@ -1362,7 +1277,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, (dst_r == TMP_REG1) ? TMP_REG2 : TMP_REG1);
|
||||
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
|
||||
}
|
||||
|
||||
if (op == SLJIT_NEG) {
|
||||
@ -1375,20 +1290,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
|
||||
flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
|
||||
|
||||
if (src & SLJIT_IMM)
|
||||
flags |= ARG2_IMM;
|
||||
else if (src & SLJIT_MEM) {
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
|
||||
srcw = TMP_REG1;
|
||||
src = TMP_REG1;
|
||||
}
|
||||
else
|
||||
srcw = src;
|
||||
|
||||
emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, srcw);
|
||||
emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, src);
|
||||
|
||||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
|
||||
if (SLJIT_UNLIKELY(dst & SLJIT_MEM))
|
||||
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
@ -1448,7 +1359,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
|
||||
{
|
||||
CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
|
||||
return reg << 1;
|
||||
return (freg_map[reg] << 1);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
@ -1702,11 +1613,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
|
||||
}
|
||||
else if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
|
||||
|
||||
return push_inst16(compiler, BX | RN3(TMP_REG2));
|
||||
}
|
||||
|
||||
@ -1798,7 +1707,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
type &= 0xff;
|
||||
|
||||
/* In ARM, we don't need to touch the arguments. */
|
||||
PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
|
||||
if (type < SLJIT_JUMP) {
|
||||
jump->flags |= IS_COND;
|
||||
@ -1818,6 +1726,241 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
return jump;
|
||||
}
|
||||
|
||||
#ifdef __SOFTFP__
|
||||
|
||||
static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
|
||||
{
|
||||
sljit_s32 stack_offset = 0;
|
||||
sljit_s32 arg_count = 0;
|
||||
sljit_s32 word_arg_offset = 0;
|
||||
sljit_s32 float_arg_count = 0;
|
||||
sljit_s32 types = 0;
|
||||
sljit_s32 src_offset = 4 * sizeof(sljit_sw);
|
||||
sljit_u8 offsets[4];
|
||||
|
||||
if (src && FAST_IS_REG(*src))
|
||||
src_offset = reg_map[*src] * sizeof(sljit_sw);
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
offsets[arg_count] = (sljit_u8)stack_offset;
|
||||
stack_offset += sizeof(sljit_f32);
|
||||
arg_count++;
|
||||
float_arg_count++;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (stack_offset & 0x7)
|
||||
stack_offset += sizeof(sljit_sw);
|
||||
offsets[arg_count] = (sljit_u8)stack_offset;
|
||||
stack_offset += sizeof(sljit_f64);
|
||||
arg_count++;
|
||||
float_arg_count++;
|
||||
break;
|
||||
default:
|
||||
offsets[arg_count] = (sljit_u8)stack_offset;
|
||||
stack_offset += sizeof(sljit_sw);
|
||||
arg_count++;
|
||||
word_arg_offset += sizeof(sljit_sw);
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
if (stack_offset > 16)
|
||||
FAIL_IF(push_inst16(compiler, SUB_SP | (((stack_offset - 16) + 0x7) & ~0x7) >> 2));
|
||||
|
||||
SLJIT_ASSERT(reg_map[TMP_REG1] == 12);
|
||||
|
||||
/* Process arguments in reversed direction. */
|
||||
while (types) {
|
||||
switch (types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
arg_count--;
|
||||
float_arg_count--;
|
||||
stack_offset = offsets[arg_count];
|
||||
|
||||
if (stack_offset < 16) {
|
||||
if (src_offset == stack_offset) {
|
||||
FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
|
||||
*src = TMP_REG1;
|
||||
}
|
||||
FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10)));
|
||||
} else
|
||||
FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
arg_count--;
|
||||
float_arg_count--;
|
||||
stack_offset = offsets[arg_count];
|
||||
|
||||
SLJIT_ASSERT((stack_offset & 0x7) == 0);
|
||||
|
||||
if (stack_offset < 16) {
|
||||
if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) {
|
||||
FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
|
||||
*src = TMP_REG1;
|
||||
}
|
||||
FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count));
|
||||
} else
|
||||
FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));
|
||||
break;
|
||||
default:
|
||||
arg_count--;
|
||||
word_arg_offset -= sizeof(sljit_sw);
|
||||
stack_offset = offsets[arg_count];
|
||||
|
||||
SLJIT_ASSERT(stack_offset >= word_arg_offset);
|
||||
|
||||
if (stack_offset != word_arg_offset) {
|
||||
if (stack_offset < 16) {
|
||||
if (src_offset == stack_offset) {
|
||||
FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
|
||||
*src = TMP_REG1;
|
||||
}
|
||||
else if (src_offset == word_arg_offset) {
|
||||
*src = 1 + (stack_offset >> 2);
|
||||
src_offset = stack_offset;
|
||||
}
|
||||
FAIL_IF(push_inst16(compiler, MOV | (stack_offset >> 2) | (word_arg_offset << 1)));
|
||||
} else
|
||||
FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((stack_offset - 16) >> 2)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
|
||||
{
|
||||
sljit_s32 stack_size = 0;
|
||||
|
||||
if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32)
|
||||
FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12)));
|
||||
if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64)
|
||||
FAIL_IF(push_inst32(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
stack_size += sizeof(sljit_f32);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (stack_size & 0x7)
|
||||
stack_size += sizeof(sljit_sw);
|
||||
stack_size += sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
stack_size += sizeof(sljit_sw);
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
if (stack_size <= 16)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return push_inst16(compiler, ADD_SP | ((((stack_size - 16) + 0x7) & ~0x7) >> 2));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
|
||||
{
|
||||
sljit_u32 remap = 0;
|
||||
sljit_u32 offset = 0;
|
||||
sljit_u32 new_offset, mask;
|
||||
|
||||
/* Remove return value. */
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) {
|
||||
new_offset = 0;
|
||||
mask = 1;
|
||||
|
||||
while (remap & mask) {
|
||||
new_offset++;
|
||||
mask <<= 1;
|
||||
}
|
||||
remap |= mask;
|
||||
|
||||
if (offset != new_offset)
|
||||
FAIL_IF(push_inst32(compiler, VMOV_F32 | DD4((new_offset >> 1) + 1)
|
||||
| ((new_offset & 0x1) ? 0x400000 : 0) | DM4((offset >> 1) + 1)));
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) {
|
||||
new_offset = 0;
|
||||
mask = 3;
|
||||
|
||||
while (remap & mask) {
|
||||
new_offset += 2;
|
||||
mask <<= 2;
|
||||
}
|
||||
remap |= mask;
|
||||
|
||||
if (offset != new_offset)
|
||||
FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_F32_OP | DD4((new_offset >> 1) + 1) | DM4((offset >> 1) + 1)));
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
#ifdef __SOFTFP__
|
||||
struct sljit_jump *jump;
|
||||
#endif
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
#ifdef __SOFTFP__
|
||||
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
jump = sljit_emit_jump(compiler, type);
|
||||
PTR_FAIL_IF(jump == NULL);
|
||||
|
||||
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
||||
return jump;
|
||||
#else
|
||||
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
return sljit_emit_jump(compiler, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
@ -1826,16 +1969,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
||||
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
/* In ARM, we don't need to touch the arguments. */
|
||||
SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
|
||||
|
||||
if (!(src & SLJIT_IMM)) {
|
||||
if (FAST_IS_REG(src))
|
||||
if (FAST_IS_REG(src)) {
|
||||
SLJIT_ASSERT(reg_map[src] != 14);
|
||||
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));
|
||||
}
|
||||
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw, TMP_REG1));
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
return push_inst16(compiler, BLX | RN3(TMP_REG1));
|
||||
}
|
||||
|
||||
/* These jumps are converted to jump/call instructions when possible. */
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
|
||||
@ -1846,6 +1993,41 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
||||
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
#ifdef __SOFTFP__
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||
|
||||
return softfloat_post_call_with_args(compiler, arg_types);
|
||||
#else /* !__SOFTFP__ */
|
||||
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
#endif /* __SOFTFP__ */
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 type)
|
||||
@ -1896,8 +2078,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
/* The condition must always be set, even if the ORR/EORI is not executed above. */
|
||||
if (reg_map[dst_r] <= 7)
|
||||
return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst_r));
|
||||
return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));
|
||||
}
|
||||
|
||||
@ -1924,8 +2104,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
||||
if (tmp < 0x10000) {
|
||||
/* set low 16 bits, set hi 16 bits to 0. */
|
||||
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||
return push_inst32(compiler, MOVW | RD4(dst_reg) |
|
||||
COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));
|
||||
return push_inst32(compiler, MOVW | RD4(dst_reg)
|
||||
| COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));
|
||||
}
|
||||
|
||||
tmp = get_imm(srcw);
|
||||
@ -1943,10 +2123,67 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
||||
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));
|
||||
|
||||
tmp = (sljit_uw) srcw;
|
||||
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg) |
|
||||
COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)));
|
||||
return push_inst32(compiler, MOVT | RD4(dst_reg) |
|
||||
COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16));
|
||||
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg)
|
||||
| COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)));
|
||||
return push_inst32(compiler, MOVT | RD4(dst_reg)
|
||||
| COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
sljit_s32 flags;
|
||||
sljit_ins inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -255))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
if (type & SLJIT_MEM_SUPP)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
switch (type & 0xff) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
flags = WORD_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_U8:
|
||||
flags = BYTE_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_S8:
|
||||
flags = BYTE_SIZE | SIGNED;
|
||||
break;
|
||||
case SLJIT_MOV_U16:
|
||||
flags = HALF_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_S16:
|
||||
flags = HALF_SIZE | SIGNED;
|
||||
break;
|
||||
default:
|
||||
SLJIT_UNREACHABLE();
|
||||
flags = WORD_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type & SLJIT_MEM_STORE)
|
||||
flags |= STORE;
|
||||
|
||||
inst = sljit_mem32[flags] | 0x900;
|
||||
|
||||
if (type & SLJIT_MEM_PRE)
|
||||
inst |= 0x400;
|
||||
|
||||
if (memw >= 0)
|
||||
inst |= 0x200;
|
||||
else
|
||||
memw = -memw;
|
||||
|
||||
return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | memw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
|
229
src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
vendored
229
src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
vendored
@ -435,3 +435,232 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
|
||||
{
|
||||
sljit_s32 stack_offset = 0;
|
||||
sljit_s32 arg_count = 0;
|
||||
sljit_s32 float_arg_count = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
sljit_s32 types = 0;
|
||||
sljit_s32 arg_count_save, types_save;
|
||||
sljit_ins prev_ins = NOP;
|
||||
sljit_ins ins = NOP;
|
||||
sljit_u8 offsets[4];
|
||||
|
||||
SLJIT_ASSERT(reg_map[TMP_REG3] == 4 && freg_map[TMP_FREG1] == 12);
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
offsets[arg_count] = (sljit_u8)stack_offset;
|
||||
|
||||
if (word_arg_count == 0 && arg_count <= 1)
|
||||
offsets[arg_count] = 254 + arg_count;
|
||||
|
||||
stack_offset += sizeof(sljit_f32);
|
||||
arg_count++;
|
||||
float_arg_count++;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (stack_offset & 0x7)
|
||||
stack_offset += sizeof(sljit_sw);
|
||||
offsets[arg_count] = (sljit_u8)stack_offset;
|
||||
|
||||
if (word_arg_count == 0 && arg_count <= 1)
|
||||
offsets[arg_count] = 254 + arg_count;
|
||||
|
||||
stack_offset += sizeof(sljit_f64);
|
||||
arg_count++;
|
||||
float_arg_count++;
|
||||
break;
|
||||
default:
|
||||
offsets[arg_count] = (sljit_u8)stack_offset;
|
||||
stack_offset += sizeof(sljit_sw);
|
||||
arg_count++;
|
||||
word_arg_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
/* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */
|
||||
if (stack_offset > 16)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));
|
||||
|
||||
types_save = types;
|
||||
arg_count_save = arg_count;
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
arg_count--;
|
||||
if (offsets[arg_count] < 254)
|
||||
ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);
|
||||
float_arg_count--;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
arg_count--;
|
||||
if (offsets[arg_count] < 254)
|
||||
ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);
|
||||
float_arg_count--;
|
||||
break;
|
||||
default:
|
||||
if (offsets[arg_count - 1] >= 16)
|
||||
ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(offsets[arg_count - 1]);
|
||||
else if (arg_count != word_arg_count)
|
||||
ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (offsets[arg_count - 1] >> 2));
|
||||
else if (arg_count == 1)
|
||||
ins = ADDU | S(SLJIT_R0) | TA(0) | D(TMP_REG3);
|
||||
|
||||
arg_count--;
|
||||
word_arg_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins != NOP) {
|
||||
if (prev_ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
|
||||
prev_ins = ins;
|
||||
ins = NOP;
|
||||
}
|
||||
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
types = types_save;
|
||||
arg_count = arg_count_save;
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
arg_count--;
|
||||
if (offsets[arg_count] == 254)
|
||||
ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
|
||||
else if (offsets[arg_count] < 16)
|
||||
ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
arg_count--;
|
||||
if (offsets[arg_count] == 254)
|
||||
ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
|
||||
else if (offsets[arg_count] < 16) {
|
||||
if (prev_ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
|
||||
prev_ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);
|
||||
ins = LW | S(SLJIT_SP) | TA(5 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count] + sizeof(sljit_sw));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
arg_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins != NOP) {
|
||||
if (prev_ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
|
||||
prev_ins = ins;
|
||||
ins = NOP;
|
||||
}
|
||||
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
*ins_ptr = prev_ins;
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
|
||||
{
|
||||
sljit_s32 stack_offset = 0;
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
stack_offset += sizeof(sljit_f32);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (stack_offset & 0x7)
|
||||
stack_offset += sizeof(sljit_sw);
|
||||
stack_offset += sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
stack_offset += sizeof(sljit_sw);
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
/* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */
|
||||
if (stack_offset > 16)
|
||||
return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(16), DR(SLJIT_SP));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_ins ins;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
PTR_FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
type &= 0xff;
|
||||
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
|
||||
|
||||
jump->flags |= IS_JAL | IS_CALL;
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
|
||||
|
||||
PTR_FAIL_IF(post_call_with_args(compiler, arg_types));
|
||||
|
||||
return jump;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ins ins;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
|
||||
if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
||||
else if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
|
||||
}
|
||||
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||
|
||||
/* Register input. */
|
||||
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
|
||||
return post_call_with_args(compiler, arg_types);
|
||||
}
|
||||
|
129
src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
vendored
129
src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
vendored
@ -537,3 +537,132 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 6);
|
||||
}
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
|
||||
{
|
||||
sljit_s32 arg_count = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
sljit_s32 float_arg_count = 0;
|
||||
sljit_s32 types = 0;
|
||||
sljit_ins prev_ins = NOP;
|
||||
sljit_ins ins = NOP;
|
||||
|
||||
SLJIT_ASSERT(reg_map[TMP_REG3] == 4 && freg_map[TMP_FREG1] == 12);
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
arg_count++;
|
||||
float_arg_count++;
|
||||
break;
|
||||
default:
|
||||
arg_count++;
|
||||
word_arg_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
if (arg_count != float_arg_count)
|
||||
ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count);
|
||||
else if (arg_count == 1)
|
||||
ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
|
||||
arg_count--;
|
||||
float_arg_count--;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (arg_count != float_arg_count)
|
||||
ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);
|
||||
else if (arg_count == 1)
|
||||
ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
|
||||
arg_count--;
|
||||
float_arg_count--;
|
||||
break;
|
||||
default:
|
||||
if (arg_count != word_arg_count)
|
||||
ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);
|
||||
else if (arg_count == 1)
|
||||
ins = DADDU | S(SLJIT_R0) | TA(0) | D(TMP_REG3);
|
||||
arg_count--;
|
||||
word_arg_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins != NOP) {
|
||||
if (prev_ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
|
||||
prev_ins = ins;
|
||||
ins = NOP;
|
||||
}
|
||||
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
*ins_ptr = prev_ins;
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_ins ins;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
PTR_FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
type &= 0xff;
|
||||
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
|
||||
|
||||
jump->flags |= IS_JAL | IS_CALL;
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
|
||||
|
||||
return jump;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_ins ins;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
|
||||
if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
||||
else if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
|
||||
}
|
||||
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||
|
||||
/* Register input. */
|
||||
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
return push_inst(compiler, ins, UNMOVABLE_INS);
|
||||
}
|
||||
|
@ -60,13 +60,27 @@ typedef sljit_u32 sljit_ins;
|
||||
#define EQUAL_FLAG 31
|
||||
#define OTHER_FLAG 1
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1)
|
||||
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
|
||||
|
||||
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4
|
||||
};
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
|
||||
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
||||
0, 0, 14, 2, 4, 6, 8, 12, 10
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
||||
0, 0, 13, 14, 15, 16, 17, 12, 18
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Instrucion forms */
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -74,21 +88,23 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
#define S(s) (reg_map[s] << 21)
|
||||
#define T(t) (reg_map[t] << 16)
|
||||
#define D(d) (reg_map[d] << 11)
|
||||
#define FT(t) (freg_map[t] << 16)
|
||||
#define FS(s) (freg_map[s] << 11)
|
||||
#define FD(d) (freg_map[d] << 6)
|
||||
/* Absolute registers. */
|
||||
#define SA(s) ((s) << 21)
|
||||
#define TA(t) ((t) << 16)
|
||||
#define DA(d) ((d) << 11)
|
||||
#define FT(t) ((t) << 16)
|
||||
#define FS(s) ((s) << 11)
|
||||
#define FD(d) ((d) << 6)
|
||||
#define IMM(imm) ((imm) & 0xffff)
|
||||
#define SH_IMM(imm) ((imm) << 6)
|
||||
|
||||
#define DR(dr) (reg_map[dr])
|
||||
#define FR(dr) (freg_map[dr])
|
||||
#define HI(opcode) ((opcode) << 26)
|
||||
#define LO(opcode) (opcode)
|
||||
/* S = (16 << 21) D = (17 << 21) */
|
||||
#define FMT_S (16 << 21)
|
||||
#define FMT_D (17 << 21)
|
||||
|
||||
#define ABS_S (HI(17) | FMT_S | LO(5))
|
||||
#define ADD_S (HI(17) | FMT_S | LO(0))
|
||||
@ -153,6 +169,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
#define OR (HI(0) | LO(37))
|
||||
#define ORI (HI(13))
|
||||
#define SD (HI(63))
|
||||
#define SDC1 (HI(61))
|
||||
#define SLT (HI(0) | LO(42))
|
||||
#define SLTI (HI(10))
|
||||
#define SLTIU (HI(11))
|
||||
@ -166,6 +183,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||
#define SUB_S (HI(17) | FMT_S | LO(1))
|
||||
#define SUBU (HI(0) | LO(35))
|
||||
#define SW (HI(43))
|
||||
#define SWC1 (HI(57))
|
||||
#define TRUNC_W_S (HI(17) | FMT_S | LO(13))
|
||||
#define XOR (HI(0) | LO(38))
|
||||
#define XORI (HI(14))
|
||||
@ -540,21 +558,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
|
||||
#define MEM_MASK 0x1f
|
||||
|
||||
#define WRITE_BACK 0x00020
|
||||
#define ARG_TEST 0x00040
|
||||
#define ALT_KEEP_CACHE 0x00080
|
||||
#define CUMULATIVE_OP 0x00100
|
||||
#define LOGICAL_OP 0x00200
|
||||
#define IMM_OP 0x00400
|
||||
#define SRC2_IMM 0x00800
|
||||
#define ARG_TEST 0x00020
|
||||
#define ALT_KEEP_CACHE 0x00040
|
||||
#define CUMULATIVE_OP 0x00080
|
||||
#define LOGICAL_OP 0x00100
|
||||
#define IMM_OP 0x00200
|
||||
#define SRC2_IMM 0x00400
|
||||
|
||||
#define UNUSED_DEST 0x01000
|
||||
#define REG_DEST 0x02000
|
||||
#define REG1_SOURCE 0x04000
|
||||
#define REG2_SOURCE 0x08000
|
||||
#define SLOW_SRC1 0x10000
|
||||
#define SLOW_SRC2 0x20000
|
||||
#define SLOW_DEST 0x40000
|
||||
#define UNUSED_DEST 0x00800
|
||||
#define REG_DEST 0x01000
|
||||
#define REG1_SOURCE 0x02000
|
||||
#define REG2_SOURCE 0x04000
|
||||
#define SLOW_SRC1 0x08000
|
||||
#define SLOW_SRC2 0x10000
|
||||
#define SLOW_DEST 0x20000
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#define STACK_STORE SW
|
||||
@ -564,6 +581,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
#define STACK_LOAD LD
|
||||
#endif
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#include "sljitNativeMIPS_32.c"
|
||||
#else
|
||||
@ -571,15 +590,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_ins base;
|
||||
sljit_s32 i, tmp, offs;
|
||||
sljit_s32 args, i, tmp, offs;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
@ -616,6 +635,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
|
||||
}
|
||||
|
||||
args = get_arg_count(arg_types);
|
||||
|
||||
if (args >= 1)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_S0), DR(SLJIT_S0)));
|
||||
if (args >= 2)
|
||||
@ -627,12 +648,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
@ -734,7 +755,7 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag
|
||||
{
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if ((!(flags & WRITE_BACK) || !(arg & REG_MASK)) && !(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
||||
if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
||||
/* Works for both absoulte and relative addresses. */
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
@ -791,12 +812,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
|
||||
base = arg & REG_MASK;
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
if (SLJIT_UNLIKELY(flags & WRITE_BACK)) {
|
||||
SLJIT_ASSERT(argw == 0);
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | D(base), DR(base)));
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
|
||||
argw &= 0x3;
|
||||
|
||||
/* Using the cache. */
|
||||
@ -833,29 +848,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {
|
||||
if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
||||
if (argw)
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base)));
|
||||
}
|
||||
else {
|
||||
if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
|
||||
if (argw != compiler->cache_argw) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
|
||||
compiler->cache_argw = argw;
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
|
||||
}
|
||||
else {
|
||||
compiler->cache_arg = SLJIT_MEM;
|
||||
compiler->cache_argw = argw;
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
|
||||
}
|
||||
}
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
|
||||
if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
|
||||
if (argw != compiler->cache_argw) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
|
||||
@ -929,7 +921,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
||||
else if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
||||
sugg_src2_r = dst_r;
|
||||
}
|
||||
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
|
||||
@ -983,7 +975,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
||||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG2_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
||||
dst_r = src2_r;
|
||||
}
|
||||
else if (src2 & SLJIT_IMM) {
|
||||
@ -994,7 +986,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
||||
}
|
||||
else {
|
||||
src2_r = 0;
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM))
|
||||
dst_r = 0;
|
||||
}
|
||||
}
|
||||
@ -1133,11 +1125,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) {
|
||||
if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT)
|
||||
flags |= INT_DATA | SIGNED_DATA;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_s32)srcw;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
@ -1171,36 +1160,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
case SLJIT_MOV_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_P:
|
||||
return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_U32:
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#else
|
||||
return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
|
||||
#endif
|
||||
|
||||
case SLJIT_MOVU_S32:
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#else
|
||||
return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw);
|
||||
#endif
|
||||
|
||||
case SLJIT_MOVU_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_NOT:
|
||||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
@ -1211,6 +1170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
}
|
||||
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
@ -1282,6 +1242,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
||||
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
@ -1298,7 +1259,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
|
||||
{
|
||||
CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
|
||||
return reg << 1;
|
||||
return FR(reg);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
@ -1328,11 +1289,9 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
|
||||
#endif
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
|
||||
src = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
|
||||
FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
|
||||
|
||||
@ -1340,7 +1299,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
|
||||
return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
|
||||
|
||||
/* Store the integer value from a VFP register. */
|
||||
return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
|
||||
return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# undef is_long
|
||||
@ -1357,13 +1316,13 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
|
||||
sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) << 21;
|
||||
#endif
|
||||
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
|
||||
else if (src & SLJIT_MEM) {
|
||||
/* Load the integer value into a VFP register. */
|
||||
FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
|
||||
}
|
||||
else {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
@ -1377,7 +1336,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
|
||||
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
@ -1392,18 +1351,14 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
|
||||
sljit_ins inst;
|
||||
|
||||
if (src1 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
else
|
||||
src2 <<= 1;
|
||||
|
||||
switch (GET_FLAG_TYPE(op)) {
|
||||
case SLJIT_EQUAL_F64:
|
||||
@ -1443,14 +1398,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
|
||||
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
|
||||
op ^= SLJIT_F32_OP;
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));
|
||||
src = dst_r;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV_F64:
|
||||
@ -1474,7 +1427,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1494,42 +1447,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
|
||||
|
||||
if (src1 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {
|
||||
FAIL_IF(compiler->error);
|
||||
src1 = TMP_FREG1;
|
||||
} else
|
||||
flags |= SLOW_SRC1;
|
||||
}
|
||||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {
|
||||
FAIL_IF(compiler->error);
|
||||
src2 = TMP_FREG2;
|
||||
} else
|
||||
flags |= SLOW_SRC2;
|
||||
}
|
||||
else
|
||||
src2 <<= 1;
|
||||
|
||||
if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
|
||||
if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
|
||||
}
|
||||
else {
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
|
||||
}
|
||||
}
|
||||
else if (flags & SLOW_SRC1)
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
|
||||
else if (flags & SLOW_SRC2)
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
|
||||
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
|
||||
|
||||
if (flags & SLOW_SRC1)
|
||||
src1 = TMP_FREG1;
|
||||
@ -1555,7 +1504,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
|
||||
}
|
||||
|
||||
if (dst_r == TMP_FREG2)
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
@ -1585,10 +1534,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
|
||||
else if (src & SLJIT_MEM)
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
|
||||
else if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, RETURN_ADDR_REG, srcw));
|
||||
|
||||
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
@ -1705,19 +1652,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
|
||||
if (type <= SLJIT_JUMP) {
|
||||
|
||||
if (type <= SLJIT_JUMP)
|
||||
PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
} else {
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
/* Cannot be optimized out if type is >= CALL0. */
|
||||
jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? IS_CALL : 0);
|
||||
else {
|
||||
jump->flags |= IS_JAL;
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
/* A NOP if type < CALL1. */
|
||||
PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), UNMOVABLE_INS));
|
||||
}
|
||||
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
return jump;
|
||||
}
|
||||
|
||||
@ -1873,41 +1817,12 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 src_r = TMP_REG2;
|
||||
struct sljit_jump *jump = NULL;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
if (DR(src) != 4)
|
||||
src_r = src;
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
|
||||
}
|
||||
|
||||
if (type >= SLJIT_CALL0) {
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
if (src & (SLJIT_IMM | SLJIT_MEM)) {
|
||||
if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
||||
else {
|
||||
SLJIT_ASSERT(src_r == TMP_REG2 && (src & SLJIT_MEM));
|
||||
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
/* We need an extra instruction in any case. */
|
||||
return push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
/* Register input. */
|
||||
if (type >= SLJIT_CALL1)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), 4));
|
||||
FAIL_IF(push_inst(compiler, JALR | S(src_r) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
return push_inst(compiler, ADDU_W | S(src_r) | TA(0) | D(PIC_ADDR_REG), UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
FAIL_IF(!jump);
|
||||
@ -1918,11 +1833,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
||||
jump->flags |= IS_MOVABLE;
|
||||
|
||||
FAIL_IF(emit_const(compiler, TMP_REG2, 0));
|
||||
src = TMP_REG2;
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw));
|
||||
src = TMP_REG2;
|
||||
}
|
||||
else if (src & SLJIT_MEM)
|
||||
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
|
||||
|
||||
FAIL_IF(push_inst(compiler, JR | S(src_r), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
|
||||
if (jump)
|
||||
jump->addr = compiler->size;
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
|
55
src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c
vendored
55
src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c
vendored
@ -413,6 +413,61 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
|
||||
{
|
||||
sljit_s32 arg_count = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
sljit_s32 types = 0;
|
||||
sljit_s32 reg = 0;
|
||||
|
||||
if (src)
|
||||
reg = *src & REG_MASK;
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
arg_count++;
|
||||
break;
|
||||
default:
|
||||
arg_count++;
|
||||
word_arg_count++;
|
||||
|
||||
if (arg_count != word_arg_count && arg_count == reg) {
|
||||
FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));
|
||||
*src = TMP_CALL_REG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
arg_count--;
|
||||
break;
|
||||
default:
|
||||
if (arg_count != word_arg_count)
|
||||
FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));
|
||||
|
||||
arg_count--;
|
||||
word_arg_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
|
||||
|
986
src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c
vendored
986
src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c
vendored
File diff suppressed because it is too large
Load Diff
119
src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
vendored
119
src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
vendored
@ -138,6 +138,125 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
|
||||
{
|
||||
sljit_s32 reg_index = 8;
|
||||
sljit_s32 word_reg_index = 8;
|
||||
sljit_s32 float_arg_index = 1;
|
||||
sljit_s32 double_arg_count = 0;
|
||||
sljit_s32 float_offset = (16 + 6) * sizeof(sljit_sw);
|
||||
sljit_s32 types = 0;
|
||||
sljit_s32 reg = 0;
|
||||
sljit_s32 move_to_tmp2 = 0;
|
||||
|
||||
if (src)
|
||||
reg = reg_map[*src & REG_MASK];
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
float_arg_index++;
|
||||
if (reg_index == reg)
|
||||
move_to_tmp2 = 1;
|
||||
reg_index++;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
float_arg_index++;
|
||||
double_arg_count++;
|
||||
if (reg_index == reg || reg_index + 1 == reg)
|
||||
move_to_tmp2 = 1;
|
||||
reg_index += 2;
|
||||
break;
|
||||
default:
|
||||
if (reg_index != word_reg_index && reg_index < 14 && reg_index == reg)
|
||||
move_to_tmp2 = 1;
|
||||
reg_index++;
|
||||
word_reg_index++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (move_to_tmp2) {
|
||||
move_to_tmp2 = 0;
|
||||
if (reg < 14)
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2A(reg), DR(TMP_REG1)));
|
||||
*src = TMP_REG1;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
arg_types = types;
|
||||
|
||||
while (arg_types) {
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
float_arg_index--;
|
||||
FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
|
||||
float_offset -= sizeof(sljit_f64);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
float_arg_index--;
|
||||
if (float_arg_index == 4 && double_arg_count == 4) {
|
||||
FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM((16 + 7) * sizeof(sljit_sw)), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | (1 << 25) | S1(SLJIT_SP) | IMM((16 + 8) * sizeof(sljit_sw)), MOVABLE_INS));
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, STDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
|
||||
float_offset -= sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
float_offset = (16 + 6) * sizeof(sljit_sw);
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
reg_index--;
|
||||
if (reg_index < 14)
|
||||
FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
|
||||
float_offset -= sizeof(sljit_f64);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
reg_index -= 2;
|
||||
if (reg_index < 14) {
|
||||
if ((reg_index & 0x1) != 0) {
|
||||
FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
|
||||
if (reg_index < 13)
|
||||
FAIL_IF(push_inst(compiler, LDUW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), reg_index + 1));
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, LDD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
|
||||
}
|
||||
float_offset -= sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
reg_index--;
|
||||
word_reg_index--;
|
||||
|
||||
if (reg_index != word_reg_index) {
|
||||
if (reg_index < 14)
|
||||
FAIL_IF(push_inst(compiler, OR | DA(reg_index) | S1(0) | S2A(word_reg_index), reg_index));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, STW | DA(word_reg_index) | S1(SLJIT_SP) | IMM(92), word_reg_index));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst)));
|
||||
|
@ -90,13 +90,19 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
|
||||
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
||||
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
||||
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
||||
/* This register is modified by calls, which affects the instruction
|
||||
in the delay slot if it is used as a source register. */
|
||||
#define TMP_LINK (SLJIT_NUMBER_OF_REGISTERS + 5)
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1)
|
||||
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
||||
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
|
||||
|
||||
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
0, 8, 9, 10, 13, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 11, 12, 15
|
||||
0, 8, 9, 10, 11, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 12, 13, 15
|
||||
};
|
||||
|
||||
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
||||
0, 0, 2, 4, 6, 8, 10, 12, 14
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -104,10 +110,15 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define D(d) (reg_map[d] << 25)
|
||||
#define FD(d) (freg_map[d] << 25)
|
||||
#define FDN(d) ((freg_map[d] | 0x1) << 25)
|
||||
#define DA(d) ((d) << 25)
|
||||
#define S1(s1) (reg_map[s1] << 14)
|
||||
#define S2(s2) (reg_map[s2])
|
||||
#define FS1(s1) (freg_map[s1] << 14)
|
||||
#define S1A(s1) ((s1) << 14)
|
||||
#define S2(s2) (reg_map[s2])
|
||||
#define FS2(s2) (freg_map[s2])
|
||||
#define FS2N(s2) (freg_map[s2] | 0x1)
|
||||
#define S2A(s2) (s2)
|
||||
#define IMM_ARG 0x2000
|
||||
#define DOP(op) ((op) << 5)
|
||||
@ -144,6 +155,8 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
#define FSUBD (OPC1(0x2) | OPC3(0x34) | DOP(0x46))
|
||||
#define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45))
|
||||
#define JMPL (OPC1(0x2) | OPC3(0x38))
|
||||
#define LDD (OPC1(0x3) | OPC3(0x03))
|
||||
#define LDUW (OPC1(0x3) | OPC3(0x00))
|
||||
#define NOP (OPC1(0x0) | OPC2(0x04))
|
||||
#define OR (OPC1(0x2) | OPC3(0x02))
|
||||
#define ORN (OPC1(0x2) | OPC3(0x06))
|
||||
@ -157,6 +170,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
|
||||
#define SRAX (OPC1(0x2) | OPC3(0x27) | (1 << 12))
|
||||
#define SRL (OPC1(0x2) | OPC3(0x26))
|
||||
#define SRLX (OPC1(0x2) | OPC3(0x26) | (1 << 12))
|
||||
#define STDF (OPC1(0x3) | OPC3(0x27))
|
||||
#define STF (OPC1(0x3) | OPC3(0x24))
|
||||
#define STW (OPC1(0x3) | OPC3(0x04))
|
||||
#define SUB (OPC1(0x2) | OPC3(0x04))
|
||||
#define SUBC (OPC1(0x2) | OPC3(0x0c))
|
||||
#define TA (OPC1(0x2) | OPC3(0x3a) | (8 << 25))
|
||||
@ -433,18 +449,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
|
||||
#define MEM_MASK 0x1f
|
||||
|
||||
#define WRITE_BACK 0x00020
|
||||
#define ARG_TEST 0x00040
|
||||
#define ALT_KEEP_CACHE 0x00080
|
||||
#define CUMULATIVE_OP 0x00100
|
||||
#define IMM_OP 0x00200
|
||||
#define SRC2_IMM 0x00400
|
||||
#define ARG_TEST 0x00020
|
||||
#define ALT_KEEP_CACHE 0x00040
|
||||
#define CUMULATIVE_OP 0x00080
|
||||
#define IMM_OP 0x00100
|
||||
#define SRC2_IMM 0x00200
|
||||
|
||||
#define REG_DEST 0x00800
|
||||
#define REG2_SOURCE 0x01000
|
||||
#define SLOW_SRC1 0x02000
|
||||
#define SLOW_SRC2 0x04000
|
||||
#define SLOW_DEST 0x08000
|
||||
#define REG_DEST 0x00400
|
||||
#define REG2_SOURCE 0x00800
|
||||
#define SLOW_SRC1 0x01000
|
||||
#define SLOW_SRC2 0x02000
|
||||
#define SLOW_DEST 0x04000
|
||||
|
||||
/* SET_FLAGS (0x10 << 19) also belong here! */
|
||||
|
||||
@ -455,12 +470,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7;
|
||||
compiler->local_size = local_size;
|
||||
@ -479,12 +494,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7;
|
||||
return SLJIT_SUCCESS;
|
||||
@ -546,18 +561,16 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag
|
||||
{
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if (!(flags & WRITE_BACK) || !(arg & REG_MASK)) {
|
||||
if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN)
|
||||
|| ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) {
|
||||
/* Works for both absoulte and relative addresses (immediate case). */
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]
|
||||
| ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg))
|
||||
| S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)),
|
||||
((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));
|
||||
return -1;
|
||||
}
|
||||
if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN)
|
||||
|| ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) {
|
||||
/* Works for both absoulte and relative addresses (immediate case). */
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]
|
||||
| ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))
|
||||
| S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)),
|
||||
((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -638,14 +651,11 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
|
||||
}
|
||||
}
|
||||
|
||||
dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg));
|
||||
dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg));
|
||||
delay_slot = ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS;
|
||||
if (!base)
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(arg2) | IMM(0), delay_slot);
|
||||
if (!(flags & WRITE_BACK))
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot));
|
||||
return push_inst(compiler, ADD | D(base) | S1(base) | S2(arg2), DR(base));
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
||||
@ -687,7 +697,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
||||
if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
||||
sugg_src2_r = dst_r;
|
||||
}
|
||||
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
|
||||
@ -738,7 +748,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
||||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG2_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
||||
dst_r = src2_r;
|
||||
}
|
||||
else if (src2 & SLJIT_IMM) {
|
||||
@ -749,7 +759,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
||||
}
|
||||
else {
|
||||
src2_r = 0;
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM))
|
||||
dst_r = 0;
|
||||
}
|
||||
}
|
||||
@ -875,28 +885,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
case SLJIT_MOV_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_P:
|
||||
return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_U32:
|
||||
return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_S32:
|
||||
return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_NOT:
|
||||
case SLJIT_CLZ:
|
||||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
@ -962,7 +950,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
|
||||
{
|
||||
CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
|
||||
return reg << 1;
|
||||
return freg_map[reg];
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
@ -990,10 +978,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
src = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | DA(TMP_FREG1) | S2A(src), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | FD(TMP_FREG1) | FS2(src), MOVABLE_INS));
|
||||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
|
||||
@ -1008,7 +994,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
@ -1027,7 +1013,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
|
||||
}
|
||||
|
||||
FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FITOS, FITOD) | DA(dst_r) | S2A(TMP_FREG1), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FITOS, FITOD) | FD(dst_r) | FS2(TMP_FREG1), MOVABLE_INS));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
|
||||
@ -1042,17 +1028,13 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
else
|
||||
src2 <<= 1;
|
||||
|
||||
return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(src1) | S2A(src2), FCC_IS_SET | MOVABLE_INS);
|
||||
return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | FS1(src1) | FS2(src2), FCC_IS_SET | MOVABLE_INS);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
@ -1071,39 +1053,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
|
||||
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
|
||||
op ^= SLJIT_F32_OP;
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
|
||||
src = dst_r;
|
||||
}
|
||||
else
|
||||
src <<= 1;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV_F64:
|
||||
if (src != dst_r) {
|
||||
if (dst_r != TMP_FREG1) {
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, FMOVS | FD(dst_r) | FS2(src), MOVABLE_INS));
|
||||
if (!(op & SLJIT_F32_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));
|
||||
}
|
||||
else
|
||||
dst_r = src;
|
||||
}
|
||||
break;
|
||||
case SLJIT_NEG_F64:
|
||||
FAIL_IF(push_inst(compiler, FNEGS | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, FNEGS | FD(dst_r) | FS2(src), MOVABLE_INS));
|
||||
if (dst_r != src && !(op & SLJIT_F32_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_ABS_F64:
|
||||
FAIL_IF(push_inst(compiler, FABSS | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, FABSS | FD(dst_r) | FS2(src), MOVABLE_INS));
|
||||
if (dst_r != src && !(op & SLJIT_F32_OP))
|
||||
FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));
|
||||
break;
|
||||
case SLJIT_CONV_F64_FROM_F32:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | DA(dst_r) | S2A(src), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | FD(dst_r) | FS2(src), MOVABLE_INS));
|
||||
op ^= SLJIT_F32_OP;
|
||||
break;
|
||||
}
|
||||
@ -1129,7 +1109,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
|
||||
|
||||
if (src1 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
|
||||
@ -1138,8 +1118,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
|
||||
} else
|
||||
flags |= SLOW_SRC1;
|
||||
}
|
||||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
|
||||
@ -1148,8 +1126,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
|
||||
} else
|
||||
flags |= SLOW_SRC2;
|
||||
}
|
||||
else
|
||||
src2 <<= 1;
|
||||
|
||||
if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
|
||||
if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
|
||||
@ -1173,19 +1149,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADD_F64:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_SUB_F64:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_MUL_F64:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));
|
||||
break;
|
||||
|
||||
case SLJIT_DIV_F64:
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1223,10 +1199,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK)));
|
||||
else if (src & SLJIT_MEM)
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw));
|
||||
else if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, TMP_LINK, srcw));
|
||||
|
||||
FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS));
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
@ -1339,21 +1313,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#endif
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)
|
||||
jump->flags |= IS_MOVABLE;
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
jump->flags |= IS_CALL;
|
||||
}
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
|
||||
PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG2) | IMM(0), UNMOVABLE_INS));
|
||||
PTR_FAIL_IF(emit_const(compiler, TMP_REG1, 0));
|
||||
PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG1) | IMM(0), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
|
||||
return jump;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
struct sljit_jump *jump = NULL;
|
||||
@ -1370,17 +1361,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
||||
FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, JUMP_ADDR);
|
||||
jump->u.target = srcw;
|
||||
|
||||
if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)
|
||||
jump->flags |= IS_MOVABLE;
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
jump->flags |= IS_CALL;
|
||||
|
||||
FAIL_IF(emit_const(compiler, TMP_REG2, 0));
|
||||
src_r = TMP_REG2;
|
||||
FAIL_IF(emit_const(compiler, TMP_REG1, 0));
|
||||
src_r = TMP_REG1;
|
||||
}
|
||||
else {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw));
|
||||
src_r = TMP_REG2;
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
|
||||
src_r = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));
|
||||
@ -1389,6 +1381,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 type)
|
||||
|
415
src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c
vendored
415
src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c
vendored
@ -64,29 +64,28 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_s32 size;
|
||||
sljit_s32 args, size;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
args = get_arg_count(arg_types);
|
||||
compiler->args = args;
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
/* [esp+0] for saving temporaries and third argument for calls. */
|
||||
compiler->saveds_offset = 1 * sizeof(sljit_sw);
|
||||
#else
|
||||
/* [esp+0] for saving temporaries and space for maximum three arguments. */
|
||||
if (scratches <= 1)
|
||||
compiler->saveds_offset = 1 * sizeof(sljit_sw);
|
||||
else
|
||||
compiler->saveds_offset = ((scratches == 2) ? 2 : 3) * sizeof(sljit_sw);
|
||||
/* [esp+0] for saving temporaries and function calls. */
|
||||
compiler->stack_tmp_size = 2 * sizeof(sljit_sw);
|
||||
|
||||
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (scratches > 3)
|
||||
compiler->stack_tmp_size = 3 * sizeof(sljit_sw);
|
||||
#endif
|
||||
|
||||
compiler->saveds_offset = compiler->stack_tmp_size;
|
||||
if (scratches > 3)
|
||||
compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
|
||||
|
||||
@ -178,10 +177,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
/* Space for a single argument. This amount is excluded when the stack is allocated below. */
|
||||
local_size -= sizeof(sljit_sw);
|
||||
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
|
||||
FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, sizeof(sljit_sw)));
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
FAIL_IF(sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARG1(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -192,12 +191,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SP, 0);
|
||||
|
||||
/* Some space might allocated during sljit_grow_stack() above on WIN32. */
|
||||
FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size + sizeof(sljit_sw)));
|
||||
|
||||
#if defined _WIN32 && !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->local_size > 1024)
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)));
|
||||
#endif
|
||||
|
||||
@ -213,31 +212,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), compiler->local_size, TMP_REG1, 0);
|
||||
}
|
||||
#endif
|
||||
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
compiler->args = args;
|
||||
compiler->args = get_arg_count(arg_types);
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
/* [esp+0] for saving temporaries and third argument for calls. */
|
||||
compiler->saveds_offset = 1 * sizeof(sljit_sw);
|
||||
#else
|
||||
/* [esp+0] for saving temporaries and space for maximum three arguments. */
|
||||
if (scratches <= 1)
|
||||
compiler->saveds_offset = 1 * sizeof(sljit_sw);
|
||||
else
|
||||
compiler->saveds_offset = ((scratches == 2) ? 2 : 3) * sizeof(sljit_sw);
|
||||
/* [esp+0] for saving temporaries and function calls. */
|
||||
compiler->stack_tmp_size = 2 * sizeof(sljit_sw);
|
||||
|
||||
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (scratches > 3)
|
||||
compiler->stack_tmp_size = 3 * sizeof(sljit_sw);
|
||||
#endif
|
||||
|
||||
compiler->saveds_offset = compiler->stack_tmp_size;
|
||||
if (scratches > 3)
|
||||
compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
|
||||
|
||||
@ -278,10 +275,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
|
||||
if (compiler->options & SLJIT_F64_ALIGNMENT)
|
||||
EMIT_MOV(compiler, SLJIT_SP, 0, SLJIT_MEM1(SLJIT_SP), compiler->local_size)
|
||||
else
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
|
||||
#else
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
|
||||
#endif
|
||||
|
||||
@ -418,7 +415,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
|
||||
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
|
||||
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
if (a & SLJIT_IMM)
|
||||
*buf_ptr = 0;
|
||||
else if (!(flags & EX86_SSE2_OP1))
|
||||
*buf_ptr = reg_map[a] << 3;
|
||||
@ -490,42 +487,324 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
|
||||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static SLJIT_INLINE sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
|
||||
static sljit_s32 c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)
|
||||
{
|
||||
sljit_s32 stack_size = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
stack_size += sizeof(sljit_f32);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
stack_size += sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
word_arg_count++;
|
||||
if (word_arg_count > 2)
|
||||
stack_size += sizeof(sljit_sw);
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
if (word_arg_count_ptr)
|
||||
*word_arg_count_ptr = word_arg_count;
|
||||
|
||||
return stack_size;
|
||||
}
|
||||
|
||||
static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler,
|
||||
sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count, sljit_s32 swap_args)
|
||||
{
|
||||
sljit_u8 *inst;
|
||||
sljit_s32 float_arg_count;
|
||||
|
||||
if (stack_size == sizeof(sljit_sw) && word_arg_count == 3) {
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
PUSH_REG(reg_map[SLJIT_R2]);
|
||||
}
|
||||
else if (stack_size > 0) {
|
||||
if (word_arg_count >= 4)
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw));
|
||||
|
||||
FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));
|
||||
|
||||
stack_size = 0;
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
word_arg_count = 0;
|
||||
float_arg_count = 0;
|
||||
while (arg_types) {
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
float_arg_count++;
|
||||
FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
|
||||
stack_size += sizeof(sljit_f32);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
float_arg_count++;
|
||||
FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
|
||||
stack_size += sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
word_arg_count++;
|
||||
if (word_arg_count == 3) {
|
||||
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, SLJIT_R2, 0);
|
||||
stack_size += sizeof(sljit_sw);
|
||||
}
|
||||
else if (word_arg_count == 4) {
|
||||
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, TMP_REG1, 0);
|
||||
stack_size += sizeof(sljit_sw);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
if (word_arg_count > 0) {
|
||||
if (swap_args) {
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
|
||||
*inst++ = XCHG_EAX_r | reg_map[SLJIT_R2];
|
||||
}
|
||||
else {
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(2);
|
||||
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0];
|
||||
}
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static sljit_s32 cdecl_call_get_stack_size(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)
|
||||
{
|
||||
sljit_s32 stack_size = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
stack_size += sizeof(sljit_f32);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
stack_size += sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
word_arg_count++;
|
||||
stack_size += sizeof(sljit_sw);
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
if (word_arg_count_ptr)
|
||||
*word_arg_count_ptr = word_arg_count;
|
||||
|
||||
if (stack_size <= compiler->stack_tmp_size)
|
||||
return 0;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
return ((stack_size - compiler->stack_tmp_size + 15) & ~15);
|
||||
#else
|
||||
return stack_size - compiler->stack_tmp_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
static sljit_s32 cdecl_call_with_args(struct sljit_compiler *compiler,
|
||||
sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count)
|
||||
{
|
||||
sljit_s32 float_arg_count = 0;
|
||||
|
||||
if (word_arg_count >= 4)
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw));
|
||||
|
||||
if (stack_size > 0)
|
||||
FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));
|
||||
|
||||
stack_size = 0;
|
||||
word_arg_count = 0;
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
float_arg_count++;
|
||||
FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
|
||||
stack_size += sizeof(sljit_f32);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
float_arg_count++;
|
||||
FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
|
||||
stack_size += sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
word_arg_count++;
|
||||
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, (word_arg_count >= 4) ? TMP_REG1 : word_arg_count, 0);
|
||||
stack_size += sizeof(sljit_sw);
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 post_call_with_args(struct sljit_compiler *compiler,
|
||||
sljit_s32 arg_types, sljit_s32 stack_size)
|
||||
{
|
||||
sljit_u8 *inst;
|
||||
sljit_s32 single;
|
||||
|
||||
if (stack_size > 0)
|
||||
FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));
|
||||
|
||||
if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
single = ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32);
|
||||
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(3);
|
||||
inst[0] = single ? FSTPS : FSTPD;
|
||||
inst[1] = (0x03 << 3) | 0x04;
|
||||
inst[2] = (0x04 << 3) | reg_map[SLJIT_SP];
|
||||
|
||||
return emit_sse2_load(compiler, single, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), 0);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_s32 stack_size = 0;
|
||||
sljit_s32 word_arg_count;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
inst = (sljit_u8*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
|
||||
if ((type & 0xff) == SLJIT_CALL) {
|
||||
stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count);
|
||||
PTR_FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, 0));
|
||||
|
||||
if (type >= SLJIT_CALL3)
|
||||
PUSH_REG(reg_map[SLJIT_R2]);
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0];
|
||||
#else
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(4 * (type - SLJIT_CALL0));
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R0] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = 0;
|
||||
if (type >= SLJIT_CALL2) {
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R1] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = sizeof(sljit_sw);
|
||||
}
|
||||
if (type >= SLJIT_CALL3) {
|
||||
*inst++ = MOV_rm_r;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_R2] << 3) | 0x4 /* SIB */;
|
||||
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP];
|
||||
*inst++ = 2 * sizeof(sljit_sw);
|
||||
jump = sljit_emit_jump(compiler, type);
|
||||
PTR_FAIL_IF(jump == NULL);
|
||||
|
||||
PTR_FAIL_IF(post_call_with_args(compiler, arg_types, 0));
|
||||
return jump;
|
||||
}
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count);
|
||||
PTR_FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
jump = sljit_emit_jump(compiler, type);
|
||||
PTR_FAIL_IF(jump == NULL);
|
||||
|
||||
PTR_FAIL_IF(post_call_with_args(compiler, arg_types, stack_size));
|
||||
return jump;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 stack_size = 0;
|
||||
sljit_s32 word_arg_count;
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
sljit_s32 swap_args;
|
||||
#endif
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
SLJIT_ASSERT(reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R2] == 1 && SLJIT_R0 == 1 && SLJIT_R2 == 3);
|
||||
|
||||
if ((type & 0xff) == SLJIT_CALL) {
|
||||
stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count);
|
||||
swap_args = 0;
|
||||
|
||||
if (word_arg_count > 0) {
|
||||
if ((src & REG_MASK) == SLJIT_R2 || OFFS_REG(src) == SLJIT_R2) {
|
||||
swap_args = 1;
|
||||
if (((src & REG_MASK) | 0x2) == SLJIT_R2)
|
||||
src ^= 0x2;
|
||||
if ((OFFS_REG(src) | 0x2) == SLJIT_R2)
|
||||
src ^= TO_OFFS_REG(0x2);
|
||||
}
|
||||
}
|
||||
|
||||
FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, swap_args));
|
||||
|
||||
compiler->saveds_offset += stack_size;
|
||||
compiler->locals_offset += stack_size;
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||
|
||||
compiler->saveds_offset -= stack_size;
|
||||
compiler->locals_offset -= stack_size;
|
||||
|
||||
return post_call_with_args(compiler, arg_types, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count);
|
||||
FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count));
|
||||
|
||||
compiler->saveds_offset += stack_size;
|
||||
compiler->locals_offset += stack_size;
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||
|
||||
compiler->saveds_offset -= stack_size;
|
||||
compiler->locals_offset -= stack_size;
|
||||
|
||||
return post_call_with_args(compiler, arg_types, stack_size);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
@ -576,7 +855,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_map[src]);
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
else {
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = GROUP_FF;
|
||||
@ -586,16 +865,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
/* SLJIT_IMM. */
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*inst++ = PUSH_i32;
|
||||
sljit_unaligned_store_sw(inst, srcw);
|
||||
inst += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
|
248
src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c
vendored
248
src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c
vendored
@ -41,24 +41,31 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
|
||||
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
|
||||
{
|
||||
int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff);
|
||||
|
||||
/* The relative jump below specialized for this case. */
|
||||
SLJIT_ASSERT(reg_map[TMP_REG2] >= 8);
|
||||
|
||||
if (type < SLJIT_JUMP) {
|
||||
/* Invert type. */
|
||||
*code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
|
||||
*code_ptr++ = 10 + 3;
|
||||
*code_ptr++ = short_addr ? (6 + 3) : (10 + 3);
|
||||
}
|
||||
|
||||
*code_ptr++ = REX_W | ((reg_map[TMP_REG2] <= 7) ? 0 : REX_B);
|
||||
*code_ptr++ = short_addr ? REX_B : (REX_W | REX_B);
|
||||
*code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2];
|
||||
jump->addr = (sljit_uw)code_ptr;
|
||||
|
||||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MD;
|
||||
else if (short_addr)
|
||||
sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target);
|
||||
else
|
||||
sljit_unaligned_store_sw(code_ptr, jump->u.target);
|
||||
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
if (reg_map[TMP_REG2] >= 8)
|
||||
*code_ptr++ = REX_B;
|
||||
code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw);
|
||||
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = GROUP_FF;
|
||||
*code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2];
|
||||
|
||||
@ -66,15 +73,15 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_s32 i, tmp, size, saved_register_size;
|
||||
sljit_s32 args, i, tmp, size, saved_register_size;
|
||||
sljit_u8 *inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Two/four register slots for parameters plus space for xmm6 register if needed. */
|
||||
@ -108,6 +115,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
PUSH_REG(reg_lmap[i]);
|
||||
}
|
||||
|
||||
args = get_arg_count(arg_types);
|
||||
|
||||
if (args > 0) {
|
||||
size = args * 3;
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
|
||||
@ -182,7 +191,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
FAIL_IF(sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARG1(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -223,14 +232,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
{
|
||||
sljit_s32 saved_register_size;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Two/four register slots for parameters plus space for xmm6 register if needed. */
|
||||
@ -414,7 +423,11 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!(flags & EX86_SSE2_OP2) && reg_map[b] >= 8)
|
||||
else if (!(flags & EX86_SSE2_OP2)) {
|
||||
if (reg_map[b] >= 8)
|
||||
rex |= REX_B;
|
||||
}
|
||||
else if (freg_map[b] >= 8)
|
||||
rex |= REX_B;
|
||||
|
||||
if (a & SLJIT_IMM) {
|
||||
@ -441,7 +454,11 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
|
||||
else {
|
||||
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
|
||||
/* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
|
||||
if (!(flags & EX86_SSE2_OP1) && reg_map[a] >= 8)
|
||||
if (!(flags & EX86_SSE2_OP1)) {
|
||||
if (reg_map[a] >= 8)
|
||||
rex |= REX_R;
|
||||
}
|
||||
else if (freg_map[a] >= 8)
|
||||
rex |= REX_R;
|
||||
}
|
||||
|
||||
@ -468,12 +485,12 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
|
||||
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
|
||||
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
|
||||
|
||||
if ((a & SLJIT_IMM) || (a == 0))
|
||||
if (a & SLJIT_IMM)
|
||||
*buf_ptr = 0;
|
||||
else if (!(flags & EX86_SSE2_OP1))
|
||||
*buf_ptr = reg_lmap[a] << 3;
|
||||
else
|
||||
*buf_ptr = a << 3;
|
||||
*buf_ptr = freg_lmap[a] << 3;
|
||||
}
|
||||
else {
|
||||
if (a & SLJIT_IMM) {
|
||||
@ -487,7 +504,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
|
||||
}
|
||||
|
||||
if (!(b & SLJIT_MEM))
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : b);
|
||||
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : freg_lmap[b]);
|
||||
else if ((b & REG_MASK) != SLJIT_UNUSED) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
|
||||
if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {
|
||||
@ -545,45 +562,161 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
|
||||
/* Call / return instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type)
|
||||
{
|
||||
sljit_u8 *inst;
|
||||
|
||||
/* After any change update IS_REG_CHANGED_BY_CALL as well. */
|
||||
#ifndef _WIN64
|
||||
SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8 && reg_map[TMP_REG1] == 2);
|
||||
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
/* Move third argument to TMP_REG1. */
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_R2];
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 src = src_ptr ? (*src_ptr) : 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
|
||||
SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R3] == 1 && reg_map[TMP_REG1] == 2);
|
||||
|
||||
compiler->mode32 = 0;
|
||||
|
||||
/* Remove return value. */
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32)
|
||||
word_arg_count++;
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_R0];
|
||||
|
||||
if (word_arg_count == 0)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
|
||||
*src_ptr = TMP_REG2;
|
||||
}
|
||||
else if (src == SLJIT_R2 && word_arg_count >= SLJIT_R2)
|
||||
*src_ptr = TMP_REG1;
|
||||
|
||||
if (word_arg_count >= 3)
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0);
|
||||
return emit_mov(compiler, SLJIT_R2, 0, SLJIT_R0, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
SLJIT_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8 && reg_map[TMP_REG1] == 8);
|
||||
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
|
||||
if (type >= SLJIT_CALL3) {
|
||||
/* Move third argument to TMP_REG1. */
|
||||
*inst++ = REX_W | REX_R;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_R2];
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 src = src_ptr ? (*src_ptr) : 0;
|
||||
sljit_s32 arg_count = 0;
|
||||
sljit_s32 word_arg_count = 0;
|
||||
sljit_s32 float_arg_count = 0;
|
||||
sljit_s32 types = 0;
|
||||
sljit_s32 data_trandfer = 0;
|
||||
static sljit_u8 word_arg_regs[5] = { 0, SLJIT_R3, SLJIT_R1, SLJIT_R2, TMP_REG1 };
|
||||
|
||||
SLJIT_ASSERT(reg_map[SLJIT_R3] == 1 && reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R2] == 8 && reg_map[TMP_REG1] == 9);
|
||||
|
||||
compiler->mode32 = 0;
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
arg_count++;
|
||||
float_arg_count++;
|
||||
|
||||
if (arg_count != float_arg_count)
|
||||
data_trandfer = 1;
|
||||
break;
|
||||
default:
|
||||
arg_count++;
|
||||
word_arg_count++;
|
||||
|
||||
if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) {
|
||||
data_trandfer = 1;
|
||||
|
||||
if (src == word_arg_regs[arg_count]) {
|
||||
EMIT_MOV(compiler, TMP_REG2, 0, src, 0);
|
||||
*src_ptr = TMP_REG2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
*inst++ = REX_W;
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_R0];
|
||||
#endif
|
||||
|
||||
if (!data_trandfer)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
|
||||
*src_ptr = TMP_REG2;
|
||||
}
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_DEF_MASK) {
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
if (arg_count != float_arg_count)
|
||||
FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0));
|
||||
arg_count--;
|
||||
float_arg_count--;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
if (arg_count != float_arg_count)
|
||||
FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0));
|
||||
arg_count--;
|
||||
float_arg_count--;
|
||||
break;
|
||||
default:
|
||||
if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count])
|
||||
EMIT_MOV(compiler, word_arg_regs[arg_count], 0, word_arg_count, 0);
|
||||
arg_count--;
|
||||
word_arg_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
types >>= SLJIT_DEF_SHIFT;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types)
|
||||
{
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL, 0));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 arg_types,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &src, srcw));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
sljit_u8 *inst;
|
||||
@ -629,11 +762,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
|
||||
FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
if (reg_map[src] < 8) {
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
@ -651,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
else {
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
@ -663,23 +791,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
||||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(IS_HALFWORD(srcw));
|
||||
/* SLJIT_IMM. */
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*inst++ = PUSH_i32;
|
||||
sljit_unaligned_store_s32(inst, srcw);
|
||||
inst += sizeof(sljit_s32);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Extend input */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
205
src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c
vendored
205
src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c
vendored
@ -26,7 +26,11 @@
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
||||
{
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
return "x86" SLJIT_CPUINFO " ABI:fastcall";
|
||||
#else
|
||||
return "x86" SLJIT_CPUINFO;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -35,7 +39,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
||||
1 - ECX
|
||||
2 - EDX
|
||||
3 - EBX
|
||||
4 - none
|
||||
4 - ESP
|
||||
5 - EBP
|
||||
6 - ESI
|
||||
7 - EDI
|
||||
@ -47,7 +51,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
||||
1 - RCX
|
||||
2 - RDX
|
||||
3 - RBX
|
||||
4 - none
|
||||
4 - RSP
|
||||
5 - RBP
|
||||
6 - RSI
|
||||
7 - RDI
|
||||
@ -92,23 +96,32 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
|
||||
#ifndef _WIN64
|
||||
/* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */
|
||||
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
|
||||
0, 0, 6, 1, 7, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9
|
||||
0, 0, 6, 7, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9
|
||||
};
|
||||
/* low-map. reg_map & 0x7. */
|
||||
static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
|
||||
0, 0, 6, 1, 7, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1
|
||||
0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1
|
||||
};
|
||||
#else
|
||||
/* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */
|
||||
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
|
||||
0, 0, 2, 1, 10, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 8, 9
|
||||
0, 0, 2, 8, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 9, 10
|
||||
};
|
||||
/* low-map. reg_map & 0x7. */
|
||||
static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
|
||||
0, 0, 2, 1, 2, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 0, 1
|
||||
0, 0, 2, 0, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 1, 2
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Args: xmm0-xmm3 */
|
||||
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {
|
||||
4, 0, 1, 2, 3, 5, 6
|
||||
};
|
||||
/* low-map. freg_map & 0x7. */
|
||||
static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {
|
||||
4, 0, 1, 2, 3, 5, 6
|
||||
};
|
||||
|
||||
#define REX_W 0x48
|
||||
#define REX_R 0x44
|
||||
#define REX_X 0x42
|
||||
@ -178,6 +191,8 @@ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
|
||||
#define CVTTSD2SI_r_xm 0x2c
|
||||
#define DIV (/* GROUP_F7 */ 6 << 3)
|
||||
#define DIVSD_x_xm 0x5e
|
||||
#define FSTPS 0xd9
|
||||
#define FSTPD 0xdd
|
||||
#define INT3 0xcc
|
||||
#define IDIV (/* GROUP_F7 */ 7 << 3)
|
||||
#define IMUL (/* GROUP_F7 */ 5 << 3)
|
||||
@ -462,11 +477,7 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code
|
||||
code_ptr += sizeof(sljit_s8);
|
||||
} else {
|
||||
jump->flags |= PATCH_MW;
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
#else
|
||||
code_ptr += sizeof(sljit_s32);
|
||||
#endif
|
||||
}
|
||||
|
||||
return code_ptr;
|
||||
@ -613,9 +624,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
get_cpu_features();
|
||||
return cpu_has_cmov;
|
||||
|
||||
case SLJIT_HAS_PREF_SHIFT_REG:
|
||||
return 1;
|
||||
|
||||
case SLJIT_HAS_SSE2:
|
||||
#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||
if (cpu_has_sse2 == -1)
|
||||
@ -634,14 +642,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||
/* Operators */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode))
|
||||
|
||||
static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
|
||||
sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm,
|
||||
sljit_u32 op_types,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w);
|
||||
|
||||
static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,
|
||||
sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm,
|
||||
sljit_u32 op_types,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w);
|
||||
@ -653,10 +663,16 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler,
|
||||
#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
|
||||
FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,
|
||||
sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src);
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,
|
||||
sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <malloc.h>
|
||||
|
||||
static void SLJIT_CALL sljit_grow_stack(sljit_sw local_size)
|
||||
static void SLJIT_FUNC sljit_grow_stack(sljit_sw local_size)
|
||||
{
|
||||
/* Workaround for calling the internal _chkstk() function on Windows.
|
||||
This function touches all 4k pages belongs to the requested stack space,
|
||||
@ -1115,7 +1131,7 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode,
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))
|
||||
dst = TMP_REG1;
|
||||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
@ -1182,12 +1198,6 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
|
||||
|
||||
SLJIT_UNUSED_ARG(op_flags);
|
||||
|
||||
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
|
||||
src = TMP_REG1;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
if (cpu_has_cmov == -1)
|
||||
get_cpu_features();
|
||||
|
||||
@ -1242,13 +1252,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 update = 0;
|
||||
sljit_s32 op_flags = GET_ALL_FLAGS(op);
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
sljit_s32 dst_is_ereg = 0;
|
||||
sljit_s32 src_is_ereg = 0;
|
||||
#else
|
||||
# define src_is_ereg 0
|
||||
#endif
|
||||
|
||||
CHECK_ERROR();
|
||||
@ -1257,7 +1263,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
|
||||
CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1);
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
compiler->mode32 = op_flags & SLJIT_I32_OP;
|
||||
#endif
|
||||
@ -1270,32 +1276,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
compiler->mode32 = 0;
|
||||
#endif
|
||||
|
||||
if (op_flags & SLJIT_I32_OP) {
|
||||
if (FAST_IS_REG(src) && src == dst) {
|
||||
if (!TYPE_CAST_NEEDED(op))
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (op == SLJIT_MOV_S32 && (src & SLJIT_MEM))
|
||||
op = SLJIT_MOV_U32;
|
||||
if (op == SLJIT_MOVU_S32 && (src & SLJIT_MEM))
|
||||
op = SLJIT_MOVU_U32;
|
||||
if (op == SLJIT_MOV_U32 && (src & SLJIT_IMM))
|
||||
op = SLJIT_MOV_S32;
|
||||
if (op == SLJIT_MOVU_U32 && (src & SLJIT_IMM))
|
||||
op = SLJIT_MOVU_S32;
|
||||
#endif
|
||||
if (FAST_IS_REG(src) && src == dst) {
|
||||
if (!TYPE_CAST_NEEDED(op))
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_COMPILE_ASSERT(SLJIT_MOV + 8 == SLJIT_MOVU, movu_offset);
|
||||
if (op >= SLJIT_MOVU) {
|
||||
update = 1;
|
||||
op -= 8;
|
||||
if (op_flags & SLJIT_I32_OP) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (src & SLJIT_MEM) {
|
||||
if (op == SLJIT_MOV_S32)
|
||||
op = SLJIT_MOV_U32;
|
||||
}
|
||||
else if (src & SLJIT_IMM) {
|
||||
if (op == SLJIT_MOV_U32)
|
||||
op = SLJIT_MOV_S32;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
@ -1369,28 +1370,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1)
|
||||
return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);
|
||||
#endif
|
||||
|
||||
if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & REG_MASK)) {
|
||||
if ((src & OFFS_REG_MASK) != 0) {
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
(src & REG_MASK), 0, (src & REG_MASK), 0, OFFS_REG(dst), 0));
|
||||
}
|
||||
else if (srcw != 0) {
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
(src & REG_MASK), 0, (src & REG_MASK), 0, SLJIT_IMM, srcw));
|
||||
}
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK)) {
|
||||
if ((dst & OFFS_REG_MASK) != 0) {
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
(dst & REG_MASK), 0, (dst & REG_MASK), 0, OFFS_REG(dst), 0));
|
||||
}
|
||||
else if (dstw != 0) {
|
||||
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
(dst & REG_MASK), 0, (dst & REG_MASK), 0, SLJIT_IMM, dstw));
|
||||
}
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1408,10 +1387,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
# undef src_is_ereg
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
@ -1445,12 +1420,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||
#endif
|
||||
|
||||
static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
|
||||
sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm,
|
||||
sljit_u32 op_types,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_u8* inst;
|
||||
sljit_u8 op_eax_imm = (op_types >> 24);
|
||||
sljit_u8 op_rm = (op_types >> 16) & 0xff;
|
||||
sljit_u8 op_mr = (op_types >> 8) & 0xff;
|
||||
sljit_u8 op_imm = op_types & 0xff;
|
||||
|
||||
if (dst == SLJIT_UNUSED) {
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
|
||||
@ -1561,12 +1540,16 @@ static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
|
||||
}
|
||||
|
||||
static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,
|
||||
sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm,
|
||||
sljit_u32 op_types,
|
||||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src1, sljit_sw src1w,
|
||||
sljit_s32 src2, sljit_sw src2w)
|
||||
{
|
||||
sljit_u8* inst;
|
||||
sljit_u8 op_eax_imm = (op_types >> 24);
|
||||
sljit_u8 op_rm = (op_types >> 16) & 0xff;
|
||||
sljit_u8 op_mr = (op_types >> 8) & 0xff;
|
||||
sljit_u8 op_imm = op_types & 0xff;
|
||||
|
||||
if (dst == SLJIT_UNUSED) {
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
|
||||
@ -2044,7 +2027,7 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler,
|
||||
*inst |= mode;
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
|
||||
}
|
||||
else if (FAST_IS_REG(dst) && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
|
||||
else if (SLOW_IS_REG(dst) && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
|
||||
if (src1 != dst)
|
||||
EMIT_MOV(compiler, dst, 0, src1, src1w);
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);
|
||||
@ -2057,27 +2040,24 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler,
|
||||
else {
|
||||
/* This case is complex since ecx itself may be used for
|
||||
addressing, and this case must be supported as well. */
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0);
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
|
||||
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
|
||||
FAIL_IF(!inst);
|
||||
*inst |= mode;
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0);
|
||||
EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
|
||||
#else
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
|
||||
EMIT_MOV(compiler, TMP_REG2, 0, src2, src2w);
|
||||
inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
|
||||
FAIL_IF(!inst);
|
||||
*inst = XCHG_r_rm;
|
||||
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
|
||||
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
|
||||
FAIL_IF(!inst);
|
||||
*inst |= mode;
|
||||
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
|
||||
EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
|
||||
#endif
|
||||
if (dst != SLJIT_UNUSED)
|
||||
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
@ -2101,7 +2081,7 @@ static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler,
|
||||
if (!set_flags)
|
||||
return emit_mov(compiler, dst, dstw, src1, src1w);
|
||||
/* OR dst, src, 0 */
|
||||
return emit_cum_binary(compiler, OR_r_rm, OR_rm_r, OR, OR_EAX_i32,
|
||||
return emit_cum_binary(compiler, BINARY_OPCODE(OR),
|
||||
dst, dstw, src1, src1w, SLJIT_IMM, 0);
|
||||
}
|
||||
|
||||
@ -2111,10 +2091,10 @@ static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler,
|
||||
if (!FAST_IS_REG(dst))
|
||||
FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));
|
||||
|
||||
FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w));
|
||||
FAIL_IF(emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w));
|
||||
|
||||
if (FAST_IS_REG(dst))
|
||||
return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);
|
||||
return emit_cmp_binary(compiler, (dst == SLJIT_UNUSED) ? TMP_REG1 : dst, dstw, SLJIT_IMM, 0);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2145,10 +2125,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
||||
if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
|
||||
return compiler->error;
|
||||
}
|
||||
return emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
|
||||
return emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_ADDC:
|
||||
return emit_cum_binary(compiler, ADC_r_rm, ADC_rm_r, ADC, ADC_EAX_i32,
|
||||
return emit_cum_binary(compiler, BINARY_OPCODE(ADC),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_SUB:
|
||||
if (!HAS_FLAGS(op)) {
|
||||
@ -2158,23 +2138,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
|
||||
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
|
||||
return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_SUBC:
|
||||
return emit_non_cum_binary(compiler, SBB_r_rm, SBB_rm_r, SBB, SBB_EAX_i32,
|
||||
return emit_non_cum_binary(compiler, BINARY_OPCODE(SBB),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_MUL:
|
||||
return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_AND:
|
||||
if (dst == SLJIT_UNUSED)
|
||||
return emit_test_binary(compiler, src1, src1w, src2, src2w);
|
||||
return emit_cum_binary(compiler, AND_r_rm, AND_rm_r, AND, AND_EAX_i32,
|
||||
return emit_cum_binary(compiler, BINARY_OPCODE(AND),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_OR:
|
||||
return emit_cum_binary(compiler, OR_r_rm, OR_rm_r, OR, OR_EAX_i32,
|
||||
return emit_cum_binary(compiler, BINARY_OPCODE(OR),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_XOR:
|
||||
return emit_cum_binary(compiler, XOR_r_rm, XOR_rm_r, XOR, XOR_EAX_i32,
|
||||
return emit_cum_binary(compiler, BINARY_OPCODE(XOR),
|
||||
dst, dstw, src1, src1w, src2, src2w);
|
||||
case SLJIT_SHL:
|
||||
return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op),
|
||||
@ -2203,7 +2183,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
|
||||
{
|
||||
CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
return reg;
|
||||
#else
|
||||
return freg_map[reg];
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
||||
@ -2345,6 +2329,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
|
||||
FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));
|
||||
src1 = TMP_FREG;
|
||||
}
|
||||
|
||||
return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_F32_OP), src1, src2, src2w);
|
||||
}
|
||||
|
||||
@ -2516,9 +2501,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
type &= 0xff;
|
||||
|
||||
if (type >= SLJIT_CALL1)
|
||||
PTR_FAIL_IF(call_with_args(compiler, type));
|
||||
|
||||
/* Worst case size. */
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
compiler->size += (type >= SLJIT_JUMP) ? 5 : 6;
|
||||
@ -2534,14 +2516,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
||||
return jump;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
#ifndef _WIN64
|
||||
#define IS_REG_CHANGED_BY_CALL(src, type) ((src) == SLJIT_R3)
|
||||
#else
|
||||
#define IS_REG_CHANGED_BY_CALL(src, type) ((src) == SLJIT_R2)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_u8 *inst;
|
||||
@ -2553,25 +2527,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
||||
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if (type >= SLJIT_CALL1) {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (src == SLJIT_R2) {
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
|
||||
src = TMP_REG1;
|
||||
}
|
||||
if (src == SLJIT_MEM1(SLJIT_SP) && type >= SLJIT_CALL3)
|
||||
srcw += sizeof(sljit_sw);
|
||||
#endif
|
||||
#else
|
||||
if ((src & SLJIT_MEM) || IS_REG_CHANGED_BY_CALL(src, type)) {
|
||||
EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
|
||||
src = TMP_REG2;
|
||||
}
|
||||
#endif
|
||||
FAIL_IF(call_with_args(compiler, type));
|
||||
}
|
||||
|
||||
if (src == SLJIT_IMM) {
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
FAIL_IF_NULL(jump);
|
||||
|
103
src/3rdparty/pcre2/src/sljit/sljitUtils.c
vendored
103
src/3rdparty/pcre2/src/sljit/sljitUtils.c
vendored
@ -48,12 +48,12 @@ static SLJIT_INLINE void allocator_release_lock(void)
|
||||
|
||||
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void)
|
||||
{
|
||||
/* Always successful. */
|
||||
}
|
||||
@ -88,7 +88,7 @@ static SLJIT_INLINE void allocator_release_lock(void)
|
||||
|
||||
static HANDLE global_mutex = 0;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void)
|
||||
{
|
||||
/* No idea what to do if an error occures. Static mutexes should never fail... */
|
||||
if (!global_mutex)
|
||||
@ -97,7 +97,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
WaitForSingleObject(global_mutex, INFINITE);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void)
|
||||
{
|
||||
ReleaseMutex(global_mutex);
|
||||
}
|
||||
@ -130,12 +130,12 @@ static SLJIT_INLINE void allocator_release_lock(void)
|
||||
|
||||
static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&global_mutex);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&global_mutex);
|
||||
}
|
||||
@ -203,7 +203,7 @@ static SLJIT_INLINE sljit_s32 open_dev_zero(void)
|
||||
/* Planning to make it even more clever in the future. */
|
||||
static sljit_sw sljit_page_align = 0;
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data)
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
|
||||
{
|
||||
struct sljit_stack *stack;
|
||||
void *ptr;
|
||||
@ -212,7 +212,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
|
||||
#endif
|
||||
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
if (limit > max_limit || limit < 1)
|
||||
if (start_size > max_size || start_size < 1)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -234,25 +234,27 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
|
||||
if (!stack)
|
||||
return NULL;
|
||||
|
||||
/* Align max_limit. */
|
||||
max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
|
||||
/* Align max_size. */
|
||||
max_size = (max_size + sljit_page_align) & ~sljit_page_align;
|
||||
|
||||
#ifdef _WIN32
|
||||
ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
|
||||
ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (!ptr) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
stack->max_limit = (sljit_u8 *)ptr;
|
||||
stack->base = stack->max_limit + max_limit;
|
||||
stack->limit = stack->base;
|
||||
if (sljit_stack_resize(stack, stack->base - limit)) {
|
||||
|
||||
stack->min_start = (sljit_u8 *)ptr;
|
||||
stack->end = stack->min_start + max_size;
|
||||
stack->start = stack->end;
|
||||
|
||||
if (sljit_stack_resize(stack, stack->end - start_size) == NULL) {
|
||||
sljit_free_stack(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
#ifdef MAP_ANON
|
||||
ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
if (dev_zero < 0) {
|
||||
if (open_dev_zero()) {
|
||||
@ -260,73 +262,70 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
|
||||
ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
|
||||
#endif
|
||||
if (ptr == MAP_FAILED) {
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
return NULL;
|
||||
}
|
||||
stack->max_limit = (sljit_u8 *)ptr;
|
||||
stack->base = stack->max_limit + max_limit;
|
||||
stack->limit = stack->base - limit;
|
||||
stack->min_start = (sljit_u8 *)ptr;
|
||||
stack->end = stack->min_start + max_size;
|
||||
stack->start = stack->end - start_size;
|
||||
#endif
|
||||
stack->top = stack->base;
|
||||
stack->top = stack->end;
|
||||
return stack;
|
||||
}
|
||||
|
||||
#undef PAGE_ALIGN
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(allocator_data);
|
||||
#ifdef _WIN32
|
||||
VirtualFree((void*)stack->max_limit, 0, MEM_RELEASE);
|
||||
VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap((void*)stack->max_limit, stack->base - stack->max_limit);
|
||||
munmap((void*)stack->min_start, stack->end - stack->min_start);
|
||||
#endif
|
||||
SLJIT_FREE(stack, allocator_data);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit)
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
|
||||
{
|
||||
sljit_uw aligned_old_limit;
|
||||
sljit_uw aligned_new_limit;
|
||||
sljit_uw aligned_old_start;
|
||||
sljit_uw aligned_new_start;
|
||||
|
||||
if ((new_start < stack->min_start) || (new_start >= stack->end))
|
||||
return NULL;
|
||||
|
||||
if ((new_limit < stack->max_limit) || (new_limit >= stack->base))
|
||||
return -1;
|
||||
#ifdef _WIN32
|
||||
aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align;
|
||||
aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align;
|
||||
if (aligned_new_limit != aligned_old_limit) {
|
||||
if (aligned_new_limit < aligned_old_limit) {
|
||||
if (!VirtualAlloc((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_COMMIT, PAGE_READWRITE))
|
||||
return -1;
|
||||
aligned_new_start = (sljit_uw)new_start & ~sljit_page_align;
|
||||
aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align;
|
||||
if (aligned_new_start != aligned_old_start) {
|
||||
if (aligned_new_start < aligned_old_start) {
|
||||
if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE))
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
if (!VirtualFree((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_DECOMMIT))
|
||||
return -1;
|
||||
if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
#else
|
||||
if (new_limit <= stack->limit) {
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
}
|
||||
aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align;
|
||||
aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align;
|
||||
/* If madvise is available, we release the unnecessary space. */
|
||||
if (stack->start < new_start) {
|
||||
aligned_new_start = (sljit_uw)new_start & ~sljit_page_align;
|
||||
aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align;
|
||||
/* If madvise is available, we release the unnecessary space. */
|
||||
#if defined(MADV_DONTNEED)
|
||||
if (aligned_new_limit > aligned_old_limit)
|
||||
madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MADV_DONTNEED);
|
||||
if (aligned_new_start > aligned_old_start)
|
||||
madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED);
|
||||
#elif defined(POSIX_MADV_DONTNEED)
|
||||
if (aligned_new_limit > aligned_old_limit)
|
||||
posix_madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, POSIX_MADV_DONTNEED);
|
||||
if (aligned_new_start > aligned_old_start)
|
||||
posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);
|
||||
#endif
|
||||
stack->limit = new_limit;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
stack->start = new_start;
|
||||
return new_start;
|
||||
}
|
||||
|
||||
#endif /* SLJIT_UTIL_STACK */
|
||||
|
@ -131,7 +131,7 @@ list.removeAll("sun");
|
||||
QList<QString> list;
|
||||
list << "sun" << "cloud" << "sun" << "rain";
|
||||
list.removeOne("sun");
|
||||
// list: ["cloud", ,"sun", "rain"]
|
||||
// list: ["cloud", "sun", "rain"]
|
||||
//! [10]
|
||||
|
||||
|
||||
|
@ -715,6 +715,37 @@ QString QDir::dirName() const
|
||||
return d->dirEntry.fileName();
|
||||
}
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
static int drivePrefixLength(const QString &path)
|
||||
{
|
||||
// Used to extract path's drive for use as prefix for an "absolute except for drive" path
|
||||
const int size = path.length();
|
||||
int drive = 2; // length of drive prefix
|
||||
if (size > 1 && path.at(1).unicode() == ':') {
|
||||
if (Q_UNLIKELY(!path.at(0).isLetter()))
|
||||
return 0;
|
||||
} else if (path.startsWith(QLatin1String("//"))) {
|
||||
// UNC path; use its //server/share part as "drive" - it's as sane a
|
||||
// thing as we can do.
|
||||
for (int i = 2; i-- > 0; ) { // Scan two "path fragments":
|
||||
while (drive < size && path.at(drive).unicode() == '/')
|
||||
drive++;
|
||||
if (drive >= size) {
|
||||
qWarning("Base directory starts with neither a drive nor a UNC share: %s",
|
||||
qUtf8Printable(QDir::toNativeSeparators(path)));
|
||||
return 0;
|
||||
}
|
||||
while (drive < size && path.at(drive).unicode() != '/')
|
||||
drive++;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return drive;
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
/*!
|
||||
Returns the path name of a file in the directory. Does \e not
|
||||
check if the file actually exists in the directory; but see
|
||||
@ -727,16 +758,27 @@ QString QDir::dirName() const
|
||||
QString QDir::filePath(const QString &fileName) const
|
||||
{
|
||||
const QDirPrivate* d = d_ptr.constData();
|
||||
if (isAbsolutePath(fileName))
|
||||
// Mistrust our own isAbsolutePath() for real files; Q_OS_WIN needs a drive.
|
||||
if (fileName.startsWith(QLatin1Char(':')) // i.e. resource path
|
||||
? isAbsolutePath(fileName) : QFileSystemEntry(fileName).isAbsolute()) {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
QString ret = d->dirEntry.filePath();
|
||||
if (!fileName.isEmpty()) {
|
||||
if (!ret.isEmpty() && ret[(int)ret.length()-1] != QLatin1Char('/') && fileName[0] != QLatin1Char('/'))
|
||||
ret += QLatin1Char('/');
|
||||
ret += fileName;
|
||||
if (fileName.isEmpty())
|
||||
return ret;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (fileName.startsWith(QLatin1Char('/')) || fileName.startsWith(QLatin1Char('\\'))) {
|
||||
// Handle the "absolute except for drive" case (i.e. \blah not c:\blah):
|
||||
const int drive = drivePrefixLength(ret);
|
||||
return drive > 0 ? ret.leftRef(drive) % fileName : fileName;
|
||||
}
|
||||
return ret;
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
if (ret.isEmpty() || ret.endsWith(QLatin1Char('/')))
|
||||
return ret % fileName;
|
||||
return ret % QLatin1Char('/') % fileName;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -750,9 +792,11 @@ QString QDir::filePath(const QString &fileName) const
|
||||
QString QDir::absoluteFilePath(const QString &fileName) const
|
||||
{
|
||||
const QDirPrivate* d = d_ptr.constData();
|
||||
// Don't trust our own isAbsolutePath(); Q_OS_WIN needs a drive.
|
||||
if (QFileSystemEntry(fileName).isAbsolute())
|
||||
// Mistrust our own isAbsolutePath() for real files; Q_OS_WIN needs a drive.
|
||||
if (fileName.startsWith(QLatin1Char(':')) // i.e. resource path
|
||||
? isAbsolutePath(fileName) : QFileSystemEntry(fileName).isAbsolute()) {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
d->resolveAbsoluteEntry();
|
||||
const QString absoluteDirPath = d->absoluteDirEntry.filePath();
|
||||
@ -760,35 +804,15 @@ QString QDir::absoluteFilePath(const QString &fileName) const
|
||||
return absoluteDirPath;
|
||||
#ifdef Q_OS_WIN
|
||||
// Handle the "absolute except for drive" case (i.e. \blah not c:\blah):
|
||||
int size = absoluteDirPath.length();
|
||||
if ((fileName.startsWith(QLatin1Char('/'))
|
||||
|| fileName.startsWith(QLatin1Char('\\')))
|
||||
&& size > 1) {
|
||||
if (fileName.startsWith(QLatin1Char('/')) || fileName.startsWith(QLatin1Char('\\'))) {
|
||||
// Combine absoluteDirPath's drive with fileName
|
||||
int drive = 2; // length of drive prefix
|
||||
if (Q_UNLIKELY(absoluteDirPath.at(1).unicode() != ':')) {
|
||||
// Presumably, absoluteDirPath is an UNC path; use its //server/share
|
||||
// part as "drive" - it's as sane a thing as we can do.
|
||||
for (int i = 2; i-- > 0; ) { // Scan two "path fragments":
|
||||
while (drive < size && absoluteDirPath.at(drive).unicode() == '/')
|
||||
drive++;
|
||||
if (drive >= size) {
|
||||
qWarning("Base directory starts with neither a drive nor a UNC share: %s",
|
||||
qPrintable(QDir::toNativeSeparators(absoluteDirPath)));
|
||||
return QString();
|
||||
}
|
||||
while (drive < size && absoluteDirPath.at(drive).unicode() != '/')
|
||||
drive++;
|
||||
}
|
||||
// We'll append fileName, which starts with a slash; so omit trailing slash:
|
||||
if (absoluteDirPath.at(drive).unicode() == '/')
|
||||
drive--;
|
||||
} else if (!absoluteDirPath.at(0).isLetter()) {
|
||||
qWarning("Base directory's drive is not a letter: %s",
|
||||
qPrintable(QDir::toNativeSeparators(absoluteDirPath)));
|
||||
return QString();
|
||||
}
|
||||
return absoluteDirPath.leftRef(drive) % fileName;
|
||||
const int drive = drivePrefixLength(absoluteDirPath);
|
||||
if (Q_LIKELY(drive))
|
||||
return absoluteDirPath.leftRef(drive) % fileName;
|
||||
|
||||
qWarning("Base directory's drive is not a letter: %s",
|
||||
qUtf8Printable(QDir::toNativeSeparators(absoluteDirPath)));
|
||||
return QString();
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
if (!absoluteDirPath.endsWith(QLatin1Char('/')))
|
||||
|
@ -636,6 +636,7 @@ bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
|
||||
|
||||
uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
|
||||
{
|
||||
qint64 maxFileOffset = std::numeric_limits<QT_OFF_T>::max();
|
||||
#if (defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)) && Q_PROCESSOR_WORDSIZE == 4
|
||||
// The Linux mmap2 system call on 32-bit takes a page-shifted 32-bit
|
||||
// integer so the maximum offset is 1 << (32+12) (the shift is always 12,
|
||||
@ -644,9 +645,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
|
||||
// and Bionic): all of them do the right shift, but don't confirm that the
|
||||
// result fits into the 32-bit parameter to the kernel.
|
||||
|
||||
static qint64 MaxFileOffset = (Q_INT64_C(1) << (32+12)) - 1;
|
||||
#else
|
||||
static qint64 MaxFileOffset = std::numeric_limits<QT_OFF_T>::max();
|
||||
maxFileOffset = qMin((Q_INT64_C(1) << (32+12)) - 1, maxFileOffset);
|
||||
#endif
|
||||
|
||||
Q_Q(QFSFileEngine);
|
||||
@ -655,7 +654,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (offset < 0 || offset > MaxFileOffset
|
||||
if (offset < 0 || offset > maxFileOffset
|
||||
|| size < 0 || quint64(size) > quint64(size_t(-1))) {
|
||||
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
|
||||
return 0;
|
||||
|
@ -129,7 +129,7 @@ static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type)
|
||||
}
|
||||
|
||||
// Convenience for SHGetKnownFolderPath().
|
||||
static QString sHGetKnownFolderPath(const GUID &clsid, QStandardPaths::StandardLocation type, bool warn = false)
|
||||
static QString sHGetKnownFolderPath(const GUID &clsid)
|
||||
{
|
||||
QString result;
|
||||
typedef HRESULT (WINAPI *GetKnownFolderPath)(const GUID&, DWORD, HANDLE, LPWSTR*);
|
||||
@ -141,11 +141,6 @@ static QString sHGetKnownFolderPath(const GUID &clsid, QStandardPaths::StandardL
|
||||
if (Q_LIKELY(sHGetKnownFolderPath && SUCCEEDED(sHGetKnownFolderPath(clsid, KF_FLAG_DONT_VERIFY, 0, &path)))) {
|
||||
result = convertCharArray(path);
|
||||
CoTaskMemFree(path);
|
||||
} else {
|
||||
if (warn) {
|
||||
qErrnoWarning("SHGetKnownFolderPath() failed for standard location \"%s\".",
|
||||
qPrintable(displayName(type)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -155,7 +150,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
QString result;
|
||||
switch (type) {
|
||||
case DownloadLocation:
|
||||
result = sHGetKnownFolderPath(FOLDERID_Downloads, type);
|
||||
result = sHGetKnownFolderPath(FOLDERID_Downloads);
|
||||
if (result.isEmpty())
|
||||
result = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
break;
|
||||
@ -164,7 +159,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
// Although Microsoft has a Cache key it is a pointer to IE's cache, not a cache
|
||||
// location for everyone. Most applications seem to be using a
|
||||
// cache directory located in their AppData directory
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(AppLocalDataLocation), type, /* warn */ true);
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(AppLocalDataLocation));
|
||||
if (!result.isEmpty()) {
|
||||
appendTestMode(result);
|
||||
appendOrganizationAndApp(result);
|
||||
@ -173,7 +168,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
break;
|
||||
|
||||
case GenericCacheLocation:
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(GenericDataLocation), type, /* warn */ true);
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(GenericDataLocation));
|
||||
if (!result.isEmpty()) {
|
||||
appendTestMode(result);
|
||||
result += QLatin1String("/cache");
|
||||
@ -190,7 +185,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
break;
|
||||
|
||||
default:
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(type), type, /* warn */ isConfigLocation(type));
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(type));
|
||||
if (!result.isEmpty() && isConfigLocation(type)) {
|
||||
appendTestMode(result);
|
||||
if (!isGenericConfigLocation(type))
|
||||
@ -214,7 +209,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
|
||||
|
||||
// type-specific handling goes here
|
||||
if (isConfigLocation(type)) {
|
||||
QString programData = sHGetKnownFolderPath(FOLDERID_ProgramData, type);
|
||||
QString programData = sHGetKnownFolderPath(FOLDERID_ProgramData);
|
||||
if (!programData.isEmpty()) {
|
||||
if (!isGenericConfigLocation(type))
|
||||
appendOrganizationAndApp(programData);
|
||||
|
@ -2545,7 +2545,7 @@ int QUrl::port(int defaultPort) const
|
||||
The \a path data is interpreted according to \a mode: in StrictMode,
|
||||
any '%' characters must be followed by exactly two hexadecimal characters
|
||||
and some characters (including space) are not allowed in undecoded form. In
|
||||
TolerantMode (the default), all characters are accepted in undecoded form and the
|
||||
TolerantMode, all characters are accepted in undecoded form and the
|
||||
tolerant parser will correct stray '%' not followed by two hex characters.
|
||||
In DecodedMode, '%' stand for themselves and encoded characters are not
|
||||
possible.
|
||||
|
@ -44,6 +44,12 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __GLIBC__
|
||||
# include <sys/syscall.h>
|
||||
# include <pthread.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
@ -79,6 +85,20 @@ QByteArray qt_readlink(const char *path)
|
||||
return buf;
|
||||
}
|
||||
|
||||
#if defined(Q_PROCESSOR_X86_32) && defined(__GLIBC__)
|
||||
# if !__GLIBC_PREREQ(2, 22)
|
||||
// glibc prior to release 2.22 had a bug that suppresses the third argument to
|
||||
// open() / open64() / openat(), causing file creation with O_TMPFILE to have
|
||||
// the wrong permissions. So we bypass the glibc implementation and go straight
|
||||
// for the syscall. See
|
||||
// https://sourceware.org/git/?p=glibc.git;a=commit;h=65f6f938cd562a614a68e15d0581a34b177ec29d
|
||||
int qt_open64(const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
return syscall(SYS_open, pathname, flags | O_LARGEFILE, mode);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
|
||||
#if QT_CONFIG(poll_pollts)
|
||||
|
@ -176,6 +176,14 @@ inline void qt_ignore_sigpipe()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(Q_PROCESSOR_X86_32) && defined(__GLIBC__)
|
||||
# if !__GLIBC_PREREQ(2, 22)
|
||||
int qt_open64(const char *pathname, int flags, mode_t);
|
||||
# undef QT_OPEN
|
||||
# define QT_OPEN qt_open64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// don't call QT_OPEN or ::open
|
||||
// call qt_safe_open
|
||||
static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
|
||||
|
@ -204,6 +204,12 @@ QT_BEGIN_NAMESPACE
|
||||
\value Scroll The object needs to scroll to the supplied position (QScrollEvent).
|
||||
\value Shortcut Key press in child for shortcut key handling (QShortcutEvent).
|
||||
\value ShortcutOverride Key press in child, for overriding shortcut key handling (QKeyEvent).
|
||||
When a shortcut is about to trigger, \c ShortcutOverride
|
||||
is sent to the active window. This allows clients (e.g. widgets)
|
||||
to signal that they will handle the shortcut themselves, by
|
||||
accepting the event. If the shortcut override is accepted, the
|
||||
event is delivered as a normal key press to the focus widget.
|
||||
Otherwise, it triggers the shortcut action, if one exists.
|
||||
\value Show Widget was shown on screen (QShowEvent).
|
||||
\value ShowToParent A child widget has been shown.
|
||||
\value SockAct Socket activated, used to implement QSocketNotifier.
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -58,6 +59,29 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static inline int metaDataSignatureLength()
|
||||
{
|
||||
return sizeof("QTMETADATA ") - 1;
|
||||
}
|
||||
|
||||
QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype sectionSize)
|
||||
{
|
||||
raw += metaDataSignatureLength();
|
||||
sectionSize -= metaDataSignatureLength();
|
||||
|
||||
// the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h)
|
||||
uint size = qFromLittleEndian<uint>(raw + 8);
|
||||
// but the maximum size of binary JSON is 128 MB
|
||||
size = qMin(size, 128U * 1024 * 1024);
|
||||
// and it doesn't include the size of the header (8 bytes)
|
||||
size += 8;
|
||||
// finally, it can't be bigger than the file or section size
|
||||
size = qMin(sectionSize, qsizetype(size));
|
||||
|
||||
QByteArray json(raw, size);
|
||||
return QJsonDocument::fromBinaryData(json);
|
||||
}
|
||||
|
||||
class QFactoryLoaderPrivate : public QObjectPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QFactoryLoader)
|
||||
|
@ -66,14 +66,7 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
inline QJsonDocument qJsonFromRawLibraryMetaData(const char *raw)
|
||||
{
|
||||
raw += strlen("QTMETADATA ");
|
||||
// the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h),
|
||||
// but doesn't include the size of the header (8 bytes)
|
||||
QByteArray json(raw, qFromLittleEndian<uint>(*(const uint *)(raw + 8)) + 8);
|
||||
return QJsonDocument::fromBinaryData(json);
|
||||
}
|
||||
QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size);
|
||||
|
||||
class QFactoryLoaderPrivate;
|
||||
class Q_CORE_EXPORT QFactoryLoader : public QObject
|
||||
|
@ -317,7 +317,7 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
|
||||
if (pos >= 0) {
|
||||
if (hasMetaData) {
|
||||
const char *data = filedata + pos;
|
||||
QJsonDocument doc = qJsonFromRawLibraryMetaData(data);
|
||||
QJsonDocument doc = qJsonFromRawLibraryMetaData(data, qsizetype(fdlen));
|
||||
lib->metaData = doc.object();
|
||||
if (qt_debug_component())
|
||||
qWarning("Found metadata in lib %s, metadata=\n%s\n",
|
||||
@ -691,7 +691,8 @@ static bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryP
|
||||
if (!szData)
|
||||
return false;
|
||||
|
||||
QJsonDocument doc = qJsonFromRawLibraryMetaData(szData);
|
||||
// the data is already loaded, so the size doesn't matter
|
||||
QJsonDocument doc = qJsonFromRawLibraryMetaData(szData, INT_MAX);
|
||||
if (doc.isNull())
|
||||
return false;
|
||||
priv->metaData = doc.object();
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -474,7 +475,10 @@ QVector<QStaticPlugin> QPluginLoader::staticPlugins()
|
||||
*/
|
||||
QJsonObject QStaticPlugin::metaData() const
|
||||
{
|
||||
return qJsonFromRawLibraryMetaData(rawMetaData()).object();
|
||||
// the data is already loaded, so this doesn't matter
|
||||
qsizetype rawMetaDataSize = INT_MAX;
|
||||
|
||||
return qJsonFromRawLibraryMetaData(rawMetaData(), rawMetaDataSize).object();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -1082,7 +1082,7 @@ QDataStream &QDataStream::readBytes(char *&s, uint &l)
|
||||
Reads at most \a len bytes from the stream into \a s and returns the number of
|
||||
bytes read. If an error occurs, this function returns -1.
|
||||
|
||||
The buffer \a s must be preallocated. The data is \e not encoded.
|
||||
The buffer \a s must be preallocated. The data is \e not decoded.
|
||||
|
||||
\sa readBytes(), QIODevice::read(), writeRawData()
|
||||
*/
|
||||
|
@ -344,6 +344,7 @@ QByteArray QJsonDocument::toJson() const
|
||||
|
||||
/*!
|
||||
\enum QJsonDocument::JsonFormat
|
||||
\since 5.1
|
||||
|
||||
This value defines the format of the JSON byte array produced
|
||||
when converting to a QJsonDocument using toJson().
|
||||
@ -368,6 +369,7 @@ QByteArray QJsonDocument::toJson() const
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 5.1
|
||||
Converts the QJsonDocument to a UTF-8 encoded JSON document in the provided \a format.
|
||||
|
||||
\sa fromJson(), JsonFormat
|
||||
|
@ -588,6 +588,7 @@ bool QJsonValue::toBool(bool defaultValue) const
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.2
|
||||
Converts the value to an int and returns it.
|
||||
|
||||
If type() is not Double or the value is not a whole number,
|
||||
|
@ -93,7 +93,9 @@ public:
|
||||
Q_STATIC_ASSERT(sizeof(wchar_t) == sizeof(ushort));
|
||||
#endif
|
||||
#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
|
||||
# if !defined(_WCHAR_T_DEFINED) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
Q_DECL_CONSTEXPR QChar(wchar_t ch) Q_DECL_NOTHROW : ucs(ushort(ch)) {} // implicit
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_CAST_FROM_ASCII
|
||||
|
@ -89,7 +89,12 @@ QCollator::QCollator(const QLocale &locale)
|
||||
QCollator::QCollator(const QCollator &other)
|
||||
: d(other.d)
|
||||
{
|
||||
d->ref.ref();
|
||||
if (d) {
|
||||
// Ensure clean, lest both copies try to init() at the same time:
|
||||
if (d->dirty)
|
||||
d->init();
|
||||
d->ref.ref();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -110,7 +115,12 @@ QCollator &QCollator::operator=(const QCollator &other)
|
||||
if (d && !d->ref.deref())
|
||||
delete d;
|
||||
d = other.d;
|
||||
if (d) d->ref.ref();
|
||||
if (d) {
|
||||
// Ensure clean, lest both copies try to init() at the same time:
|
||||
if (d->dirty)
|
||||
d->init();
|
||||
d->ref.ref();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI
|
||||
\variable QIconEngine::ScaledPixmapArgument::pixmap
|
||||
|
||||
\brief The pixmap that is the best match for the given \l size, \l mode, \l
|
||||
\state, and \l scale. This is an output parameter that is set after calling
|
||||
state, and \l scale. This is an output parameter that is set after calling
|
||||
\l virtual_hook().
|
||||
*/
|
||||
|
||||
|
@ -5031,7 +5031,9 @@ void QTouchEvent::TouchPoint::setLastNormalizedPos(const QPointF &lastNormalized
|
||||
}
|
||||
|
||||
// ### remove the following 3 setRect functions and their usages soon
|
||||
/*! \internal \obsolete */
|
||||
/*! \internal
|
||||
\obsolete
|
||||
*/
|
||||
void QTouchEvent::TouchPoint::setRect(const QRectF &rect)
|
||||
{
|
||||
if (d->ref.load() != 1)
|
||||
@ -5040,7 +5042,9 @@ void QTouchEvent::TouchPoint::setRect(const QRectF &rect)
|
||||
d->ellipseDiameters = rect.size();
|
||||
}
|
||||
|
||||
/*! \internal \obsolete */
|
||||
/*! \internal
|
||||
\obsolete
|
||||
*/
|
||||
void QTouchEvent::TouchPoint::setSceneRect(const QRectF &sceneRect)
|
||||
{
|
||||
if (d->ref.load() != 1)
|
||||
@ -5049,7 +5053,9 @@ void QTouchEvent::TouchPoint::setSceneRect(const QRectF &sceneRect)
|
||||
d->ellipseDiameters = sceneRect.size();
|
||||
}
|
||||
|
||||
/*! \internal \obsolete */
|
||||
/*! \internal
|
||||
\obsolete
|
||||
*/
|
||||
void QTouchEvent::TouchPoint::setScreenRect(const QRectF &screenRect)
|
||||
{
|
||||
if (d->ref.load() != 1)
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
DeviceTypeTablet
|
||||
};
|
||||
|
||||
QInputDeviceManager(QObject *parent = 0);
|
||||
QInputDeviceManager(QObject *parent = nullptr);
|
||||
|
||||
int deviceCount(DeviceType type) const;
|
||||
|
||||
|
@ -66,7 +66,7 @@ class Q_GUI_EXPORT QPlatformInputContextPlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QPlatformInputContextPlugin(QObject *parent = 0);
|
||||
explicit QPlatformInputContextPlugin(QObject *parent = nullptr);
|
||||
~QPlatformInputContextPlugin();
|
||||
|
||||
virtual QPlatformInputContext *create(const QString &key, const QStringList ¶mList) = 0;
|
||||
|
@ -64,7 +64,7 @@ class Q_GUI_EXPORT QPlatformIntegrationPlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QPlatformIntegrationPlugin(QObject *parent = 0);
|
||||
explicit QPlatformIntegrationPlugin(QObject *parent = nullptr);
|
||||
~QPlatformIntegrationPlugin();
|
||||
|
||||
virtual QPlatformIntegration *create(const QString &key, const QStringList ¶mList);
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
OpenGLTexture
|
||||
};
|
||||
|
||||
explicit QPlatformSharedGraphicsCache(QObject *parent = 0) : QObject(parent) {}
|
||||
explicit QPlatformSharedGraphicsCache(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
virtual void beginRequestBatch() = 0;
|
||||
virtual void ensureCacheInitialized(const QByteArray &cacheId, BufferType bufferType,
|
||||
|
@ -63,7 +63,7 @@ class Q_GUI_EXPORT QPlatformThemePlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QPlatformThemePlugin(QObject *parent = 0);
|
||||
explicit QPlatformThemePlugin(QObject *parent = nullptr);
|
||||
~QPlatformThemePlugin();
|
||||
|
||||
virtual QPlatformTheme *create(const QString &key, const QStringList ¶mList) = 0;
|
||||
|
@ -371,7 +371,7 @@ void QOpenGLBuffer::write(int offset, const void *data, int count)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
if (!isCreated())
|
||||
qWarning("QOpenGLBuffer::allocate(): buffer not created");
|
||||
qWarning("QOpenGLBuffer::write(): buffer not created");
|
||||
#endif
|
||||
Q_D(QOpenGLBuffer);
|
||||
if (d->guard && d->guard->id())
|
||||
|
@ -664,10 +664,10 @@ void QNetworkRequest::setAttribute(Attribute code, const QVariant &value)
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
/*!
|
||||
Returns this network request's SSL configuration. By default, no
|
||||
SSL settings are specified.
|
||||
Returns this network request's SSL configuration. By default this is the same
|
||||
as QSslConfiguration::defaultConfiguration().
|
||||
|
||||
\sa setSslConfiguration()
|
||||
\sa setSslConfiguration(), QSslConfiguration::defaultConfiguration()
|
||||
*/
|
||||
QSslConfiguration QNetworkRequest::sslConfiguration() const
|
||||
{
|
||||
@ -683,9 +683,6 @@ QSslConfiguration QNetworkRequest::sslConfiguration() const
|
||||
certificates and the ciphers that the SSL backend is allowed to
|
||||
use.
|
||||
|
||||
By default, no SSL configuration is set, which allows the backends
|
||||
to choose freely what configuration is best for them.
|
||||
|
||||
\sa sslConfiguration(), QSslConfiguration::defaultConfiguration()
|
||||
*/
|
||||
void QNetworkRequest::setSslConfiguration(const QSslConfiguration &config)
|
||||
|
@ -486,11 +486,8 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
|
||||
|
||||
const int z = currentDevice == QTabletEvent::FourDMouse ? int(packet.pkZ) : 0;
|
||||
|
||||
// This code is to delay the tablet data one cycle to sync with the mouse location.
|
||||
QPointF globalPosF = m_oldGlobalPosF;
|
||||
const QPointF currentGlobalPosF =
|
||||
QPointF globalPosF =
|
||||
m_devices.at(m_currentDevice).scaleCoordinates(packet.pkX, packet.pkY, virtualDesktopArea);
|
||||
m_oldGlobalPosF = currentGlobalPosF;
|
||||
|
||||
QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target; // Pass to window that grabbed it.
|
||||
|
||||
@ -498,10 +495,10 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
|
||||
const QPoint mouseLocation = QWindowsCursor::mousePosition();
|
||||
if (m_state == PenProximity) {
|
||||
m_state = PenDown;
|
||||
m_mode = (mouseLocation - currentGlobalPosF).manhattanLength() > m_absoluteRange
|
||||
m_mode = (mouseLocation - globalPosF).manhattanLength() > m_absoluteRange
|
||||
? MouseMode : PenMode;
|
||||
qCDebug(lcQpaTablet) << __FUNCTION__ << "mode=" << m_mode << "pen:"
|
||||
<< currentGlobalPosF << "mouse:" << mouseLocation;
|
||||
<< globalPosF << "mouse:" << mouseLocation;
|
||||
}
|
||||
if (m_mode == MouseMode)
|
||||
globalPosF = mouseLocation;
|
||||
|
@ -150,7 +150,6 @@ private:
|
||||
bool m_tiltSupport = false;
|
||||
QVector<QWindowsTabletDeviceData> m_devices;
|
||||
int m_currentDevice = -1;
|
||||
QPointF m_oldGlobalPosF;
|
||||
Mode m_mode = PenMode;
|
||||
State m_state = PenUp;
|
||||
};
|
||||
|
@ -364,7 +364,7 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
|
||||
setVariantBool(accessible->state().focusable, pRetVal);
|
||||
break;
|
||||
case UIA_IsOffscreenPropertyId:
|
||||
setVariantBool(false, pRetVal);
|
||||
setVariantBool(accessible->state().offscreen, pRetVal);
|
||||
break;
|
||||
case UIA_IsContentElementPropertyId:
|
||||
setVariantBool(true, pRetVal);
|
||||
@ -453,30 +453,53 @@ HRESULT QWindowsUiaMainProvider::Navigate(NavigateDirection direction, IRawEleme
|
||||
|
||||
QAccessibleInterface *targetacc = nullptr;
|
||||
|
||||
switch (direction) {
|
||||
case NavigateDirection_Parent:
|
||||
targetacc = accessible->parent();
|
||||
if (targetacc && (targetacc->role() == QAccessible::Application)) {
|
||||
targetacc = nullptr; // The app's children are considered top level objects.
|
||||
}
|
||||
break;
|
||||
case NavigateDirection_FirstChild:
|
||||
targetacc = accessible->child(0);
|
||||
break;
|
||||
case NavigateDirection_LastChild:
|
||||
targetacc = accessible->child(accessible->childCount() - 1);
|
||||
break;
|
||||
case NavigateDirection_NextSibling:
|
||||
case NavigateDirection_PreviousSibling:
|
||||
if (direction == NavigateDirection_Parent) {
|
||||
if (QAccessibleInterface *parent = accessible->parent()) {
|
||||
if (parent->isValid()) {
|
||||
int index = parent->indexOfChild(accessible);
|
||||
index += (direction == NavigateDirection_NextSibling) ? 1 : -1;
|
||||
if (index >= 0 && index < parent->childCount())
|
||||
targetacc = parent->child(index);
|
||||
// The Application's children are considered top level objects.
|
||||
if (parent->isValid() && parent->role() != QAccessible::Application) {
|
||||
targetacc = parent;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QAccessibleInterface *parent = nullptr;
|
||||
int index = 0;
|
||||
int incr = 1;
|
||||
switch (direction) {
|
||||
case NavigateDirection_FirstChild:
|
||||
parent = accessible;
|
||||
index = 0;
|
||||
incr = 1;
|
||||
break;
|
||||
case NavigateDirection_LastChild:
|
||||
parent = accessible;
|
||||
index = accessible->childCount() - 1;
|
||||
incr = -1;
|
||||
break;
|
||||
case NavigateDirection_NextSibling:
|
||||
if ((parent = accessible->parent()))
|
||||
index = parent->indexOfChild(accessible) + 1;
|
||||
incr = 1;
|
||||
break;
|
||||
case NavigateDirection_PreviousSibling:
|
||||
if ((parent = accessible->parent()))
|
||||
index = parent->indexOfChild(accessible) - 1;
|
||||
incr = -1;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
if (parent && parent->isValid()) {
|
||||
for (int count = parent->childCount(); index >= 0 && index < count; index += incr) {
|
||||
if (QAccessibleInterface *child = parent->child(index)) {
|
||||
if (child->isValid() && !child->state().invisible) {
|
||||
targetacc = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (targetacc)
|
||||
|
@ -1253,10 +1253,11 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
|
||||
boolean isPressed;
|
||||
pointerPoint->get_IsInContact(&isPressed);
|
||||
|
||||
// Devices like the Hololens set a static pressure of 0.5 independent
|
||||
// of the pressed state. In those cases we need to synthesize the
|
||||
// pressure value. To our knowledge this does not apply to pens
|
||||
if (pointerDeviceType == PointerDeviceType_Touch && pressure == 0.5f)
|
||||
// Devices like the Hololens set a static pressure of 0.0 or 0.5
|
||||
// (depending on the image) independent of the pressed state.
|
||||
// In those cases we need to synthesize the pressure value. To our
|
||||
// knowledge this does not apply to pens
|
||||
if (pointerDeviceType == PointerDeviceType_Touch && (pressure == 0.0f || pressure == 0.5f))
|
||||
pressure = isPressed ? 1. : 0.;
|
||||
|
||||
const QRectF areaRect(area.X * d->scaleFactor, area.Y * d->scaleFactor,
|
||||
|
@ -591,6 +591,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
|
||||
|
||||
m_setup = xcb_get_setup(xcb_connection());
|
||||
|
||||
m_xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower();
|
||||
|
||||
initializeAllAtoms();
|
||||
|
||||
initializeXSync();
|
||||
@ -1691,8 +1693,10 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex,
|
||||
continue;
|
||||
if (isXIType(next, m_xiOpCode, XCB_INPUT_TOUCH_UPDATE)) {
|
||||
auto *touchUpdateNextEvent = reinterpret_cast<xcb_input_touch_update_event_t *>(next);
|
||||
if (id == touchUpdateNextEvent->detail % INT_MAX)
|
||||
if (id == touchUpdateNextEvent->detail % INT_MAX &&
|
||||
touchUpdateNextEvent->deviceid == touchUpdateEvent->deviceid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -503,6 +503,9 @@ public:
|
||||
void grabServer();
|
||||
void ungrabServer();
|
||||
|
||||
bool isUnity() const { return m_xdgCurrentDesktop == "unity"; }
|
||||
bool isGnome() const { return m_xdgCurrentDesktop == "gnome"; }
|
||||
|
||||
QXcbNativeInterface *nativeInterface() const { return m_nativeInterface; }
|
||||
|
||||
QXcbSystemTrayTracker *systemTrayTracker() const;
|
||||
@ -521,6 +524,7 @@ public:
|
||||
Qt::MouseButton xiToQtMouseButton(uint32_t b);
|
||||
void xi2UpdateScrollingDevices();
|
||||
bool startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner);
|
||||
void abortSystemMoveResizeForTouch();
|
||||
bool isTouchScreen(int id);
|
||||
#endif
|
||||
QXcbEventReader *eventReader() const { return m_reader; }
|
||||
@ -565,6 +569,7 @@ private:
|
||||
|
||||
bool m_xi2Enabled = false;
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
QVector<int> m_floatingSlaveDevices;
|
||||
int m_xi2Minor = -1;
|
||||
void initializeXInput2();
|
||||
void xi2SetupDevice(void *info, bool removeExisting = true);
|
||||
@ -720,6 +725,8 @@ private:
|
||||
bool m_peekerIndexCacheDirty = false;
|
||||
QHash<qint32, qint32> m_peekerToCachedIndex;
|
||||
friend class QXcbEventReader;
|
||||
|
||||
QByteArray m_xdgCurrentDesktop;
|
||||
};
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
#if QT_CONFIG(tabletevent)
|
||||
|
@ -113,7 +113,7 @@ void QXcbConnection::xi2SelectDeviceEvents(xcb_window_t window)
|
||||
}
|
||||
|
||||
qt_xcb_input_event_mask_t mask;
|
||||
mask.header.deviceid = XCB_INPUT_DEVICE_ALL_MASTER;
|
||||
mask.header.deviceid = XCB_INPUT_DEVICE_ALL;
|
||||
mask.header.mask_len = 1;
|
||||
mask.mask = bitMask;
|
||||
xcb_void_cookie_t cookie =
|
||||
@ -309,6 +309,7 @@ void QXcbConnection::xi2SetupDevices()
|
||||
m_scrollingDevices.clear();
|
||||
m_touchDevices.clear();
|
||||
m_xiMasterPointerIds.clear();
|
||||
m_floatingSlaveDevices.clear();
|
||||
|
||||
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, m_connection, XCB_INPUT_DEVICE_ALL);
|
||||
if (!reply) {
|
||||
@ -319,6 +320,10 @@ void QXcbConnection::xi2SetupDevices()
|
||||
auto it = xcb_input_xi_query_device_infos_iterator(reply.get());
|
||||
for (; it.rem; xcb_input_xi_device_info_next(&it)) {
|
||||
xcb_input_xi_device_info_t *deviceInfo = it.data;
|
||||
if (deviceInfo->type == XCB_INPUT_DEVICE_TYPE_FLOATING_SLAVE) {
|
||||
m_floatingSlaveDevices.append(deviceInfo->deviceid);
|
||||
continue;
|
||||
}
|
||||
if (deviceInfo->type == XCB_INPUT_DEVICE_TYPE_MASTER_POINTER) {
|
||||
m_xiMasterPointerIds.append(deviceInfo->deviceid);
|
||||
continue;
|
||||
@ -542,6 +547,72 @@ static inline qreal fixed1616ToReal(xcb_input_fp1616_t val)
|
||||
}
|
||||
#endif // QT_CONFIG(tabletevent)
|
||||
|
||||
namespace {
|
||||
|
||||
/*! \internal
|
||||
|
||||
Qt listens for XIAllDevices to avoid losing mouse events. This function
|
||||
ensures that we don't process the same event twice: from a slave device and
|
||||
then again from a master device.
|
||||
|
||||
In a normal use case (e.g. mouse press and release inside a window), we will
|
||||
drop events from master devices as duplicates. Other advantage of processing
|
||||
events from slave devices is that they don't share button state. All buttons
|
||||
on a master device share the state.
|
||||
|
||||
Examples of special cases:
|
||||
|
||||
- During system move/resize, window manager (_NET_WM_MOVERESIZE) grabs the
|
||||
master pointer, in this case we process the matching release from the slave
|
||||
device. A master device event is not sent by the server, hence no duplicate
|
||||
event to drop. If we listened for XIAllMasterDevices instead, we would never
|
||||
see a release event in this case.
|
||||
|
||||
- If we dismiss a context menu by clicking somewhere outside a Qt application,
|
||||
we will process the mouse press from the master pointer as that is the
|
||||
device we are grabbing. We are not grabbing slave devices (grabbing on the
|
||||
slave device is buggy according to 19d289ab1b5bde3e136765e5432b5c7d004df3a4).
|
||||
And since the event occurs outside our window, the slave device event is
|
||||
not sent to us by the server, hence no duplicate event to drop.
|
||||
*/
|
||||
bool isDuplicateEvent(xcb_ge_event_t *event)
|
||||
{
|
||||
struct qXIEvent {
|
||||
bool isValid = false;
|
||||
uint16_t sourceid;
|
||||
uint8_t event_type;
|
||||
uint32_t detail;
|
||||
int32_t root_x;
|
||||
int32_t root_y;
|
||||
};
|
||||
static qXIEvent lastSeenEvent;
|
||||
|
||||
bool isDuplicate = false;
|
||||
auto xiDeviceEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
|
||||
if (lastSeenEvent.isValid) {
|
||||
isDuplicate = lastSeenEvent.sourceid == xiDeviceEvent->sourceid &&
|
||||
lastSeenEvent.event_type == xiDeviceEvent->event_type &&
|
||||
lastSeenEvent.detail == xiDeviceEvent->detail &&
|
||||
lastSeenEvent.root_x == xiDeviceEvent->root_x &&
|
||||
lastSeenEvent.root_y == xiDeviceEvent->root_y;
|
||||
} else {
|
||||
lastSeenEvent.isValid = true;
|
||||
}
|
||||
lastSeenEvent.sourceid = xiDeviceEvent->sourceid;
|
||||
lastSeenEvent.event_type = xiDeviceEvent->event_type;
|
||||
lastSeenEvent.detail = xiDeviceEvent->detail;
|
||||
lastSeenEvent.root_x = xiDeviceEvent->root_x;
|
||||
lastSeenEvent.root_y = xiDeviceEvent->root_y;
|
||||
|
||||
if (isDuplicate)
|
||||
// This sanity check ensures that special cases like QTBUG-59277 keep working.
|
||||
lastSeenEvent.isValid = false; // An event can be a duplicate only once.
|
||||
|
||||
return isDuplicate;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
||||
{
|
||||
auto *xiEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
|
||||
@ -550,15 +621,31 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
||||
xcb_input_enter_event_t *xiEnterEvent = nullptr;
|
||||
QXcbWindowEventListener *eventListener = 0;
|
||||
|
||||
bool isTouchEvent = true;
|
||||
switch (xiEvent->event_type) {
|
||||
case XCB_INPUT_BUTTON_PRESS:
|
||||
case XCB_INPUT_BUTTON_RELEASE:
|
||||
case XCB_INPUT_MOTION:
|
||||
isTouchEvent = false;
|
||||
if (!xi2MouseEventsDisabled() && isDuplicateEvent(event))
|
||||
return;
|
||||
case XCB_INPUT_TOUCH_BEGIN:
|
||||
case XCB_INPUT_TOUCH_UPDATE:
|
||||
case XCB_INPUT_TOUCH_END:
|
||||
{
|
||||
xiDeviceEvent = xiEvent;
|
||||
|
||||
if (m_floatingSlaveDevices.contains(xiDeviceEvent->sourceid))
|
||||
return; // Not interested in floating slave device events, only in attached slaves.
|
||||
|
||||
bool isSlaveEvent = xiDeviceEvent->deviceid == xiDeviceEvent->sourceid;
|
||||
if (!xi2MouseEventsDisabled() && isTouchEvent && isSlaveEvent) {
|
||||
// For touch events we want events only from master devices, at least
|
||||
// currently there is no apparent reason why we would need to consider
|
||||
// events from slave devices.
|
||||
return;
|
||||
}
|
||||
|
||||
eventListener = windowEventListenerFromId(xiDeviceEvent->event);
|
||||
sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
|
||||
break;
|
||||
@ -830,6 +917,11 @@ bool QXcbConnection::startSystemMoveResizeForTouchBegin(xcb_window_t window, con
|
||||
return false;
|
||||
}
|
||||
|
||||
void QXcbConnection::abortSystemMoveResizeForTouch()
|
||||
{
|
||||
m_startSystemMoveResizeInfo.window = XCB_NONE;
|
||||
}
|
||||
|
||||
bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
|
||||
{
|
||||
bool ok = false;
|
||||
|
@ -2569,18 +2569,41 @@ bool QXcbWindow::startSystemMove(const QPoint &pos)
|
||||
|
||||
bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
|
||||
{
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
||||
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
|
||||
return false;
|
||||
|
||||
const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner))
|
||||
return true;
|
||||
#endif
|
||||
return doStartSystemMoveResize(globalPos, corner);
|
||||
// ### FIXME QTBUG-53389
|
||||
bool startedByTouch = connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner);
|
||||
if (startedByTouch) {
|
||||
if (connection()->isUnity() || connection()->isGnome()) {
|
||||
// These desktops fail to move/resize via _NET_WM_MOVERESIZE (WM bug?).
|
||||
connection()->abortSystemMoveResizeForTouch();
|
||||
return false;
|
||||
}
|
||||
// KWin, Openbox, AwesomeWM have been tested to work with _NET_WM_MOVERESIZE.
|
||||
} else { // Started by mouse press.
|
||||
if (!connection()->hasXInput2() || connection()->xi2MouseEventsDisabled()) {
|
||||
// Without XI2 we can't get button press/move/release events.
|
||||
return false;
|
||||
}
|
||||
if (connection()->isUnity())
|
||||
return false; // _NET_WM_MOVERESIZE on this WM is bouncy (WM bug?).
|
||||
|
||||
doStartSystemMoveResize(globalPos, corner);
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
Q_UNUSED(pos);
|
||||
Q_UNUSED(corner);
|
||||
return false;
|
||||
#endif // xcb_xinput
|
||||
}
|
||||
|
||||
bool QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
|
||||
void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
|
||||
{
|
||||
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
||||
xcb_client_message_event_t xev;
|
||||
@ -2607,7 +2630,6 @@ bool QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
|
||||
xcb_send_event(connection()->xcb_connection(), false, xcbScreen()->root(),
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
|
||||
(const char *)&xev);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sends an XEmbed message.
|
||||
|
@ -171,7 +171,7 @@ public:
|
||||
QXcbScreen *xcbScreen() const;
|
||||
|
||||
bool startSystemMoveResize(const QPoint &pos, int corner);
|
||||
bool doStartSystemMoveResize(const QPoint &globalPos, int corner);
|
||||
void doStartSystemMoveResize(const QPoint &globalPos, int corner);
|
||||
|
||||
bool isTrayIconWindow() const { return m_trayIconWindow; }
|
||||
|
||||
|
@ -1827,6 +1827,8 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
|
||||
auto *button = static_cast<NSButton *>(bv);
|
||||
button.buttonType = buttonType;
|
||||
button.bezelStyle = bezelStyle;
|
||||
if (widget.type == Button_CheckBox)
|
||||
button.allowsMixedState = YES;
|
||||
}
|
||||
|
||||
return bv;
|
||||
|
@ -37,10 +37,9 @@
|
||||
drawing, ensuring that they look exactly like the equivalent
|
||||
native widgets.
|
||||
|
||||
Qt comes with a selection of built-in styles. Some styles are only
|
||||
available on specific platforms (such as the Mac and Windows
|
||||
Vista styles). Custom styles are made available as plugins or by
|
||||
creating an instance of a specific style class with
|
||||
Qt comes with a selection of built-in styles. Certain styles are only
|
||||
available on specific platforms. Custom styles are made available as
|
||||
plugins or by creating an instance of a specific style class with
|
||||
QStyleFactory::create() and setting it with QApplication::setStyle().
|
||||
|
||||
\section1 Customizing a Style
|
||||
|
@ -2925,10 +2925,7 @@ void QStyleSheetStyle::unpolish(QWidget *w)
|
||||
styleSheetCaches->renderRulesCache.remove(w);
|
||||
styleSheetCaches->styleSheetCache.remove(w);
|
||||
unsetPalette(w);
|
||||
w->setProperty("_q_stylesheet_minw", QVariant());
|
||||
w->setProperty("_q_stylesheet_minh", QVariant());
|
||||
w->setProperty("_q_stylesheet_maxw", QVariant());
|
||||
w->setProperty("_q_stylesheet_maxh", QVariant());
|
||||
setGeometry(w);
|
||||
w->setAttribute(Qt::WA_StyleSheetTarget, false);
|
||||
w->setAttribute(Qt::WA_StyleSheet, false);
|
||||
QObject::disconnect(w, 0, this, 0);
|
||||
|
@ -510,7 +510,7 @@ void tst_LargeFile::mapFile()
|
||||
//Mac: memory-mapping beyond EOF may succeed but it could generate bus error on access
|
||||
//FreeBSD: same
|
||||
//Linux: memory-mapping beyond EOF usually succeeds, but depends on the filesystem
|
||||
// 32-bit: limited to 44-bit offsets
|
||||
// 32-bit: limited to 44-bit offsets (when sizeof(off_t) == 8)
|
||||
//Windows: memory-mapping beyond EOF is not allowed
|
||||
void tst_LargeFile::mapOffsetOverflow()
|
||||
{
|
||||
@ -521,9 +521,9 @@ void tst_LargeFile::mapOffsetOverflow()
|
||||
#else
|
||||
Succeeds = true,
|
||||
# if (defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)) && Q_PROCESSOR_WORDSIZE == 4
|
||||
MaxOffset = 43
|
||||
MaxOffset = sizeof(QT_OFF_T) > 4 ? 43 : 30
|
||||
# else
|
||||
MaxOffset = 63
|
||||
MaxOffset = 8 * sizeof(QT_OFF_T) - 1
|
||||
# endif
|
||||
#endif
|
||||
};
|
||||
|
@ -56,6 +56,12 @@
|
||||
#define Q_NO_SYMLINKS
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define DRIVE "Q:"
|
||||
#else
|
||||
#define DRIVE
|
||||
#endif
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -1385,14 +1391,12 @@ void tst_QDir::absoluteFilePath_data()
|
||||
QTest::addColumn<QString>("expectedFilePath");
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
QTest::newRow("UNC") << "//machine" << "share" << "//machine/share";
|
||||
QTest::newRow("Drive") << "c:/side/town" << "/my/way/home" << "c:/my/way/home";
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define DRIVE "Q:"
|
||||
#else
|
||||
#define DRIVE
|
||||
QTest::newRow("UNC-rel") << "//machine/share" << "dir" << "//machine/share/dir";
|
||||
QTest::newRow("UNC-abs") << "//machine/share/path/to/blah" << "/dir" << "//machine/share/dir";
|
||||
QTest::newRow("UNC-UNC") << "//machine/share/path/to/blah" << "//host/share/path" << "//host/share/path";
|
||||
QTest::newRow("Drive-UNC") << "c:/side/town" << "//host/share/path" << "//host/share/path";
|
||||
QTest::newRow("Drive-LTUNC") << "c:/side/town" << "\\/leaning\\toothpick/path" << "\\/leaning\\toothpick/path";
|
||||
QTest::newRow("Drive-abs") << "c:/side/town" << "/my/way/home" << "c:/my/way/home";
|
||||
#endif
|
||||
|
||||
QTest::newRow("0") << DRIVE "/etc" << "/passwd" << DRIVE "/passwd";
|
||||
@ -1401,8 +1405,10 @@ void tst_QDir::absoluteFilePath_data()
|
||||
QTest::newRow("3") << "relative" << "path" << QDir::currentPath() + "/relative/path";
|
||||
QTest::newRow("4") << "" << "" << QDir::currentPath();
|
||||
|
||||
QTest::newRow("resource") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar";
|
||||
#undef DRIVE
|
||||
// Resource paths are absolute:
|
||||
QTest::newRow("resource-rel") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar";
|
||||
QTest::newRow("abs-res-res") << ":/prefix" << ":/abc.txt" << ":/abc.txt";
|
||||
QTest::newRow("abs-res-path") << DRIVE "/etc" << ":/abc.txt" << ":/abc.txt";
|
||||
}
|
||||
|
||||
void tst_QDir::absoluteFilePath()
|
||||
@ -1517,12 +1523,17 @@ void tst_QDir::filePath_data()
|
||||
QTest::addColumn<QString>("fileName");
|
||||
QTest::addColumn<QString>("expectedFilePath");
|
||||
|
||||
QTest::newRow("0") << "/etc" << "/passwd" << "/passwd";
|
||||
QTest::newRow("1") << "/etc" << "passwd" << "/etc/passwd";
|
||||
QTest::newRow("2") << "/" << "passwd" << "/passwd";
|
||||
QTest::newRow("3") << "relative" << "path" << "relative/path";
|
||||
QTest::newRow("4") << "" << "" << ".";
|
||||
QTest::newRow("abs-abs") << DRIVE "/etc" << DRIVE "/passwd" << DRIVE "/passwd";
|
||||
QTest::newRow("abs-rel") << DRIVE "/etc" << "passwd" << DRIVE "/etc/passwd";
|
||||
QTest::newRow("root-rel") << DRIVE "/" << "passwd" << DRIVE "/passwd";
|
||||
QTest::newRow("rel-rel") << "relative" << "path" << "relative/path";
|
||||
QTest::newRow("empty-empty") << "" << "" << ".";
|
||||
QTest::newRow("resource") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar";
|
||||
#ifdef Q_OS_WIN
|
||||
QTest::newRow("abs-LTUNC") << "Q:/path" << "\\/leaning\\tooth/pick" << "\\/leaning\\tooth/pick";
|
||||
QTest::newRow("LTUNC-slash") << "\\/leaning\\tooth/pick" << "/path" << "//leaning/tooth/path";
|
||||
QTest::newRow("LTUNC-abs") << "\\/leaning\\tooth/pick" << "Q:/path" << "Q:/path";
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QDir::filePath()
|
||||
@ -1588,6 +1599,9 @@ void tst_QDir::exists2_data()
|
||||
QTest::newRow("2") << "" << false;
|
||||
QTest::newRow("3") << "testData" << true;
|
||||
QTest::newRow("4") << "/testData" << false;
|
||||
#ifdef Q_OS_WIN
|
||||
QTest::newRow("abs") << "Q:/testData" << false;
|
||||
#endif
|
||||
QTest::newRow("5") << "tst_qdir.cpp" << true;
|
||||
QTest::newRow("6") << "/resources.cpp" << false;
|
||||
QTest::newRow("resource0") << ":/prefix/foo.bar" << false;
|
||||
|
@ -1904,6 +1904,8 @@ void tst_QSortFilterProxyModel::changeSourceData_data()
|
||||
QTest::addColumn<QString>("newValue");
|
||||
QTest::addColumn<IntPairList>("removeIntervals");
|
||||
QTest::addColumn<IntPairList>("insertIntervals");
|
||||
QTest::addColumn<int>("expectedDataChangedRow"); // -1 if no dataChanged signal expected
|
||||
QTest::addColumn<bool>("expectedLayoutChanged");
|
||||
QTest::addColumn<QStringList>("proxyItems");
|
||||
|
||||
QTest::newRow("move_to_end_ascending")
|
||||
@ -1916,6 +1918,8 @@ void tst_QSortFilterProxyModel::changeSourceData_data()
|
||||
<< "z" // newValue
|
||||
<< IntPairList() // removeIntervals
|
||||
<< IntPairList() // insertIntervals
|
||||
<< 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though)
|
||||
<< true // layoutChanged
|
||||
<< (QStringList() << "b" << "c" << "z") // proxyItems
|
||||
;
|
||||
|
||||
@ -1929,6 +1933,8 @@ void tst_QSortFilterProxyModel::changeSourceData_data()
|
||||
<< "a" // newValue
|
||||
<< IntPairList() // removeIntervals
|
||||
<< IntPairList() // insertIntervals
|
||||
<< 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though)
|
||||
<< true // layoutChanged
|
||||
<< (QStringList() << "z" << "b" << "a") // proxyItems
|
||||
;
|
||||
|
||||
@ -1942,9 +1948,26 @@ void tst_QSortFilterProxyModel::changeSourceData_data()
|
||||
<< "a" // newValue
|
||||
<< IntPairList() // removeIntervals
|
||||
<< IntPairList() // insertIntervals
|
||||
<< -1 // no dataChanged signal
|
||||
<< false // layoutChanged
|
||||
<< (QStringList() << "b" << "a") // proxyItems
|
||||
;
|
||||
|
||||
QTest::newRow("no_effect_on_filtering")
|
||||
<< (QStringList() << "a" << "b") // sourceItems
|
||||
<< static_cast<int>(Qt::AscendingOrder) // sortOrder
|
||||
<< "" // filter
|
||||
<< (QStringList() << "a" << "b") // expectedInitialProxyItems
|
||||
<< true // dynamic
|
||||
<< 1 // row
|
||||
<< "z" // newValue
|
||||
<< IntPairList() // removeIntervals
|
||||
<< IntPairList() // insertIntervals
|
||||
<< 1 // expectedDataChangedRow
|
||||
<< false // layoutChanged
|
||||
<< (QStringList() << "a" << "z") // proxyItems
|
||||
;
|
||||
|
||||
QTest::newRow("filtered_out_value_stays_out")
|
||||
<< (QStringList() << "a" << "b" << "c" << "d") // sourceItems
|
||||
<< static_cast<int>(Qt::AscendingOrder) // sortOrder
|
||||
@ -1955,6 +1978,8 @@ void tst_QSortFilterProxyModel::changeSourceData_data()
|
||||
<< "x" // newValue
|
||||
<< IntPairList() // removeIntervals
|
||||
<< IntPairList() // insertIntervals
|
||||
<< -1 // no dataChanged signal
|
||||
<< false // layoutChanged
|
||||
<< (QStringList() << "a" << "c") // proxyItems
|
||||
;
|
||||
|
||||
@ -1968,6 +1993,8 @@ void tst_QSortFilterProxyModel::changeSourceData_data()
|
||||
<< "x" // newValue
|
||||
<< IntPairList() // removeIntervals
|
||||
<< (IntPairList() << IntPair(2, 2)) // insertIntervals
|
||||
<< -1 // no dataChanged signal
|
||||
<< false // layoutChanged
|
||||
<< (QStringList() << "a" << "c" << "x") // proxyItems
|
||||
;
|
||||
|
||||
@ -1981,6 +2008,8 @@ void tst_QSortFilterProxyModel::changeSourceData_data()
|
||||
<< "x" // newValue
|
||||
<< (IntPairList() << IntPair(1, 1)) // removeIntervals
|
||||
<< IntPairList() // insertIntervals
|
||||
<< -1 // no dataChanged signal
|
||||
<< false // layoutChanged
|
||||
<< (QStringList() << "a") // proxyItems
|
||||
;
|
||||
|
||||
@ -1994,6 +2023,8 @@ void tst_QSortFilterProxyModel::changeSourceData_data()
|
||||
<< "x" // newValue
|
||||
<< IntPairList() // removeIntervals
|
||||
<< IntPairList() // insertIntervals
|
||||
<< 0 // expectedDataChangedRow
|
||||
<< false // layoutChanged
|
||||
<< (QStringList() << "x" << "b" << "c") // proxyItems
|
||||
;
|
||||
}
|
||||
@ -2009,6 +2040,8 @@ void tst_QSortFilterProxyModel::changeSourceData()
|
||||
QFETCH(QString, newValue);
|
||||
QFETCH(IntPairList, removeIntervals);
|
||||
QFETCH(IntPairList, insertIntervals);
|
||||
QFETCH(int, expectedDataChangedRow);
|
||||
QFETCH(bool, expectedLayoutChanged);
|
||||
QFETCH(QStringList, proxyItems);
|
||||
|
||||
QStandardItemModel model;
|
||||
@ -2037,9 +2070,13 @@ void tst_QSortFilterProxyModel::changeSourceData()
|
||||
|
||||
QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
|
||||
QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
|
||||
QSignalSpy dataChangedSpy(&proxy, &QSortFilterProxyModel::dataChanged);
|
||||
QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
|
||||
|
||||
QVERIFY(removeSpy.isValid());
|
||||
QVERIFY(insertSpy.isValid());
|
||||
QVERIFY(dataChangedSpy.isValid());
|
||||
QVERIFY(layoutChangedSpy.isValid());
|
||||
|
||||
{
|
||||
QModelIndex index = model.index(row, 0, QModelIndex());
|
||||
@ -2069,6 +2106,17 @@ void tst_QSortFilterProxyModel::changeSourceData()
|
||||
QModelIndex index = proxy.index(i, 0, QModelIndex());
|
||||
QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i));
|
||||
}
|
||||
|
||||
if (expectedDataChangedRow == -1) {
|
||||
QCOMPARE(dataChangedSpy.count(), 0);
|
||||
} else {
|
||||
QCOMPARE(dataChangedSpy.count(), 1);
|
||||
const QModelIndex idx = dataChangedSpy.at(0).at(0).value<QModelIndex>();
|
||||
QCOMPARE(idx.row(), expectedDataChangedRow);
|
||||
QCOMPARE(idx.column(), 0);
|
||||
}
|
||||
|
||||
QCOMPARE(layoutChangedSpy.count(), expectedLayoutChanged ? 1 : 0);
|
||||
}
|
||||
|
||||
// Checks that the model is a table, and that each and every row is like this:
|
||||
|
@ -11,5 +11,6 @@ qtConfig(library): SUBDIRS += \
|
||||
contains(CONFIG, static) {
|
||||
message(Disabling tests requiring shared build of Qt)
|
||||
SUBDIRS -= qfactoryloader \
|
||||
qplugin \
|
||||
qpluginloader
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
QT = core
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin
|
||||
SOURCES = main.cpp
|
||||
DESTDIR = ../plugins
|
49
tests/auto/corelib/plugin/qplugin/invalidplugin/main.cpp
Normal file
49
tests/auto/corelib/plugin/qplugin/invalidplugin/main.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <qplugin.h>
|
||||
|
||||
QT_PLUGIN_METADATA_SECTION
|
||||
static const char pluginMetaData[512] = {
|
||||
'q', 'p', 'l', 'u', 'g', 'i', 'n', ' ',
|
||||
't', 'e', 's', 't', 'f', 'i', 'l', 'e'
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
const void *qt_plugin_query_metadata()
|
||||
{
|
||||
return pluginMetaData;
|
||||
}
|
||||
|
||||
Q_DECL_EXPORT void *qt_plugin_instance()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
TEMPLATE = subdirs
|
||||
TESTPLUGINS =
|
||||
TESTPLUGINS = invalidplugin
|
||||
|
||||
win32 {
|
||||
contains(QT_CONFIG, debug): TESTPLUGINS += debugplugin
|
||||
@ -8,7 +8,7 @@ win32 {
|
||||
CONFIG(debug, debug|release): TESTPLUGINS += debugplugin
|
||||
CONFIG(release, debug|release): TESTPLUGINS += releaseplugin
|
||||
} else {
|
||||
TESTPLUGINS = debugplugin releaseplugin
|
||||
TESTPLUGINS += debugplugin releaseplugin
|
||||
}
|
||||
|
||||
SUBDIRS += main $$TESTPLUGINS
|
||||
|
@ -37,6 +37,7 @@ class tst_QPlugin : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
QDir dir;
|
||||
QString invalidPluginName;
|
||||
|
||||
public:
|
||||
tst_QPlugin();
|
||||
@ -45,6 +46,8 @@ private slots:
|
||||
void initTestCase();
|
||||
void loadDebugPlugin();
|
||||
void loadReleasePlugin();
|
||||
void scanInvalidPlugin_data();
|
||||
void scanInvalidPlugin();
|
||||
};
|
||||
|
||||
tst_QPlugin::tst_QPlugin()
|
||||
@ -57,6 +60,10 @@ void tst_QPlugin::initTestCase()
|
||||
QVERIFY2(dir.exists(),
|
||||
qPrintable(QString::fromLatin1("Cannot find the 'plugins' directory starting from '%1'").
|
||||
arg(QDir::toNativeSeparators(QDir::currentPath()))));
|
||||
|
||||
const auto fileNames = dir.entryList({"*invalid*"}, QDir::Files);
|
||||
if (!fileNames.isEmpty())
|
||||
invalidPluginName = dir.absoluteFilePath(fileNames.first());
|
||||
}
|
||||
|
||||
void tst_QPlugin::loadDebugPlugin()
|
||||
@ -90,6 +97,7 @@ void tst_QPlugin::loadReleasePlugin()
|
||||
{
|
||||
const auto fileNames = dir.entryList(QStringList() << "*release*", QDir::Files);
|
||||
for (const QString &fileName : fileNames) {
|
||||
if (!QLibrary::isLibrary(fileName))
|
||||
continue;
|
||||
QPluginLoader loader(dir.filePath(fileName));
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
|
||||
@ -112,5 +120,105 @@ void tst_QPlugin::loadReleasePlugin()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QPlugin::scanInvalidPlugin_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("metadata");
|
||||
QTest::addColumn<bool>("loads");
|
||||
|
||||
QByteArray prefix = "QTMETADATA ";
|
||||
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj.insert("IID", "org.qt-project.tst_qplugin");
|
||||
obj.insert("className", "tst");
|
||||
obj.insert("version", int(QT_VERSION));
|
||||
#ifdef QT_NO_DEBUG
|
||||
obj.insert("debug", false);
|
||||
#else
|
||||
obj.insert("debug", true);
|
||||
#endif
|
||||
obj.insert("MetaData", QJsonObject());
|
||||
QTest::newRow("control") << (prefix + QJsonDocument(obj).toBinaryData()) << true;
|
||||
}
|
||||
|
||||
QTest::newRow("zeroes") << prefix << false;
|
||||
|
||||
prefix += "qbjs";
|
||||
QTest::newRow("bad-json-version0") << prefix << false;
|
||||
QTest::newRow("bad-json-version2") << (prefix + QByteArray("\2\0\0\0", 4)) << false;
|
||||
|
||||
// valid qbjs version 1
|
||||
prefix += QByteArray("\1\0\0\0");
|
||||
|
||||
// too large for the file (100 MB)
|
||||
QTest::newRow("bad-json-size-large1") << (prefix + QByteArray("\0\0\x40\x06")) << false;
|
||||
|
||||
// too large for binary JSON (512 MB)
|
||||
QTest::newRow("bad-json-size-large2") << (prefix + QByteArray("\0\0\0\x20")) << false;
|
||||
|
||||
// could overflow
|
||||
QTest::newRow("bad-json-size-large3") << (prefix + "\xff\xff\xff\x7f") << false;
|
||||
|
||||
}
|
||||
|
||||
static const char invalidPluginSignature[] = "qplugin testfile";
|
||||
static qsizetype locateMetadata(const uchar *data, qsizetype len)
|
||||
{
|
||||
const uchar *dataend = data + len - strlen(invalidPluginSignature);
|
||||
|
||||
for (const uchar *ptr = data; ptr < dataend; ++ptr) {
|
||||
if (*ptr != invalidPluginSignature[0])
|
||||
continue;
|
||||
|
||||
int r = memcmp(ptr, invalidPluginSignature, strlen(invalidPluginSignature));
|
||||
if (r)
|
||||
continue;
|
||||
|
||||
return ptr - data;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void tst_QPlugin::scanInvalidPlugin()
|
||||
{
|
||||
QVERIFY(!invalidPluginName.isEmpty());
|
||||
|
||||
// copy the file
|
||||
QFileInfo fn(invalidPluginName);
|
||||
QTemporaryDir tmpdir;
|
||||
QVERIFY(tmpdir.isValid());
|
||||
|
||||
QString newName = tmpdir.path() + '/' + fn.fileName();
|
||||
QVERIFY(QFile::copy(invalidPluginName, newName));
|
||||
|
||||
{
|
||||
QFile f(newName);
|
||||
QVERIFY(f.open(QIODevice::ReadWrite | QIODevice::Unbuffered));
|
||||
QVERIFY(f.size() > qint64(strlen(invalidPluginSignature)));
|
||||
uchar *data = f.map(0, f.size());
|
||||
QVERIFY(data);
|
||||
|
||||
static const qsizetype offset = locateMetadata(data, f.size());
|
||||
QVERIFY(offset > 0);
|
||||
|
||||
QFETCH(QByteArray, metadata);
|
||||
|
||||
// sanity check
|
||||
QVERIFY(metadata.size() < 512);
|
||||
|
||||
// replace the data
|
||||
memcpy(data + offset, metadata.constData(), metadata.size());
|
||||
memset(data + offset + metadata.size(), 0, 512 - metadata.size());
|
||||
}
|
||||
|
||||
// now try to load this
|
||||
QFETCH(bool, loads);
|
||||
QPluginLoader loader(newName);
|
||||
QCOMPARE(loader.load(), loads);
|
||||
if (loads)
|
||||
loader.unload();
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QPlugin)
|
||||
#include "tst_qplugin.moc"
|
||||
|
@ -186,7 +186,7 @@ void tst_QPluginLoader::errorString()
|
||||
QVERIFY(!unloaded);
|
||||
}
|
||||
|
||||
#if !defined Q_OS_WIN && !defined Q_OS_MAC && !defined Q_OS_HPUX
|
||||
#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && !defined(Q_OS_HPUX)
|
||||
{
|
||||
QPluginLoader loader( sys_qualifiedLibraryName("almostplugin")); //a plugin with unresolved symbols
|
||||
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
||||
|
@ -72,6 +72,9 @@ void tst_QCollator::moveSemantics()
|
||||
QCOMPARE(c2.locale(), de_AT);
|
||||
QVERIFY(dpointer_is_null(c1));
|
||||
|
||||
QCollator c3(c1);
|
||||
QVERIFY(dpointer_is_null(c3));
|
||||
|
||||
c1 = std::move(c2);
|
||||
QCOMPARE(c1.locale(), de_AT);
|
||||
QVERIFY(dpointer_is_null(c2));
|
||||
|
@ -99,6 +99,7 @@ private slots:
|
||||
void appStyle();
|
||||
void QTBUG11658_cachecrash();
|
||||
void styleSheetTargetAttribute();
|
||||
void unpolish();
|
||||
|
||||
private:
|
||||
QColor COLOR(const QWidget& w) {
|
||||
@ -2054,6 +2055,17 @@ void tst_QStyleSheetStyle::styleSheetTargetAttribute()
|
||||
QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), false);
|
||||
}
|
||||
|
||||
void tst_QStyleSheetStyle::unpolish()
|
||||
{
|
||||
QWidget w;
|
||||
QCOMPARE(w.minimumWidth(), 0);
|
||||
w.setStyleSheet("QWidget { min-width: 100; }");
|
||||
w.ensurePolished();
|
||||
QCOMPARE(w.minimumWidth(), 100);
|
||||
w.setStyleSheet("");
|
||||
QCOMPARE(w.minimumWidth(), 0);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QStyleSheetStyle)
|
||||
#include "tst_qstylesheetstyle.moc"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user