summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-09-10 15:50:33 -0700
committerThiago Macieira <thiago.macieira@intel.com>2021-10-04 14:01:40 -0700
commit349fb14c1d387e3ec052953e9f5b91b3f6b0dea7 (patch)
treeed7f285ec5283db4ebe6d01bbd2e2c0426e4609d
parent16e7366b5ce61418a69ba13a74996514b69dac37 (diff)
QPlugin: update the arch requirements to match the x86-64 ISA levels
When we created the functionality, the levels were not yet standardized. Now they are and you can use -march=x86-64-v3 (for example) to get to them. We're making a split between "v1" and "baseline" here for the benefit of 32-bit, which is not included in the ISA levels. Change-Id: I2de1b4dfacd443148279fffd16a397a700b9a15a Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp12
-rw-r--r--src/corelib/plugin/qplugin.h23
-rw-r--r--src/corelib/plugin/qplugin_p.h51
-rw-r--r--tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp19
4 files changed, 89 insertions, 16 deletions
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 5a2b9e7758..1a27559fd0 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -95,11 +95,15 @@ QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QStri
return QJsonDocument();
}
+ DecodedArchRequirements archReq =
+ header.version == 0 ? decodeVersion0ArchRequirements(header.plugin_arch_requirements)
+ : decodeVersion1ArchRequirements(header.plugin_arch_requirements);
+
QJsonObject o;
o.insert(QLatin1String("version"),
QT_VERSION_CHECK(header.qt_major_version, header.qt_minor_version, 0));
- o.insert(QLatin1String("debug"), bool(header.plugin_arch_requirements & 1));
- o.insert(QLatin1String("archreq"), header.plugin_arch_requirements);
+ o.insert(QLatin1String("debug"), archReq.isDebug);
+ o.insert(QLatin1String("archlevel"), archReq.level);
// convert the top-level map integer keys
for (auto it : metadata.toMap()) {
@@ -112,9 +116,7 @@ QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QStri
#undef CONVERT_TO_STRING
case int(QtPluginMetaDataKeys::Requirements):
- // special case: recreate the debug key
- o.insert(QLatin1String("debug"), bool(it.second.toInteger() & 1));
- key = QStringLiteral("archreq");
+ // ignore, handled above
break;
}
} else {
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
index a80ee28c52..affe3f5412 100644
--- a/src/corelib/plugin/qplugin.h
+++ b/src/corelib/plugin/qplugin.h
@@ -47,6 +47,7 @@
QT_BEGIN_NAMESPACE
+// Used up to Qt 6.2
inline constexpr unsigned char qPluginArchRequirements()
{
return 0
@@ -65,7 +66,7 @@ inline constexpr unsigned char qPluginArchRequirements()
typedef QObject *(*QtPluginInstanceFunction)();
struct QPluginMetaData
{
- static constexpr quint8 CurrentMetaDataVersion = 0;
+ static constexpr quint8 CurrentMetaDataVersion = 1;
static constexpr char MagicString[] = {
'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!'
};
@@ -79,11 +80,29 @@ struct QPluginMetaData
out[i] = in[i];
}
+ static constexpr quint8 archRequirements()
+ {
+ quint8 v = 0;
+#if defined(__AVX512F__)
+ v = 4; // x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ and AVX512VL
+#elif defined(__AVX__) || defined(__BMI__) || defined(__BMI2__) || defined(__MOVBE__)
+ v = 3; // x86-64-v3: AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE
+#elif defined(__SSE3__)
+ v = 2; // x86-64-v2: POPCNT, SSE3, SSSE3, SSE4.1 and SSE4.2.
+#elif defined(__SSE__) || defined(__MMX___)
+ v = 1; // x86-64 baseline: SSE and SSE2
+#endif
+#ifndef QT_NO_DEBUG
+ v |= 0x80;
+#endif
+ return v;
+ }
+
struct Header {
quint8 version = CurrentMetaDataVersion;
quint8 qt_major_version = QT_VERSION_MAJOR;
quint8 qt_minor_version = QT_VERSION_MINOR;
- quint8 plugin_arch_requirements = qPluginArchRequirements();
+ quint8 plugin_arch_requirements = archRequirements();
};
static_assert(alignof(Header) == 1, "Alignment of header incorrect with this compiler");
diff --git a/src/corelib/plugin/qplugin_p.h b/src/corelib/plugin/qplugin_p.h
index ce45ebf700..80ee02e761 100644
--- a/src/corelib/plugin/qplugin_p.h
+++ b/src/corelib/plugin/qplugin_p.h
@@ -72,6 +72,57 @@ enum class QtPluginMetaDataKeys {
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data") \
F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI")
+namespace {
+struct DecodedArchRequirements
+{
+ quint8 level;
+ bool isDebug;
+ friend constexpr bool operator==(DecodedArchRequirements r1, DecodedArchRequirements r2)
+ {
+ return r1.level == r2.level && r1.isDebug == r2.isDebug;
+ }
+};
+
+static constexpr DecodedArchRequirements decodeVersion0ArchRequirements(quint8 value)
+{
+ // see qPluginArchRequirements() and QPluginMetaDataV2::archRequirements()
+ DecodedArchRequirements r = {};
+#ifdef Q_PROCESSOR_X86
+ if (value & 4)
+ r.level = 4; // AVX512F -> x86-64-v4
+ else if (value & 2)
+ r.level = 3; // AVX2 -> x86-64-v3
+#endif
+ if (value & 1)
+ r.isDebug = true;
+ return r;
+}
+// self checks
+static_assert(decodeVersion0ArchRequirements(0) == DecodedArchRequirements{ 0, false });
+static_assert(decodeVersion0ArchRequirements(1) == DecodedArchRequirements{ 0, true });
+#ifdef Q_PROCESSOR_X86
+static_assert(decodeVersion0ArchRequirements(2) == DecodedArchRequirements{ 3, false });
+static_assert(decodeVersion0ArchRequirements(3) == DecodedArchRequirements{ 3, true });
+static_assert(decodeVersion0ArchRequirements(4) == DecodedArchRequirements{ 4, false });
+static_assert(decodeVersion0ArchRequirements(5) == DecodedArchRequirements{ 4, true });
+#endif
+
+static constexpr DecodedArchRequirements decodeVersion1ArchRequirements(quint8 value)
+{
+ return { quint8(value & 0x7f), bool(value & 0x80) };
+}
+// self checks
+static_assert(decodeVersion1ArchRequirements(0) == DecodedArchRequirements{ 0, false });
+static_assert(decodeVersion1ArchRequirements(0x80) == DecodedArchRequirements{ 0, true });
+#ifdef Q_PROCESSOR_X86
+static_assert(decodeVersion1ArchRequirements(1) == DecodedArchRequirements{ 1, false });
+static_assert(decodeVersion1ArchRequirements(3) == DecodedArchRequirements{ 3, false});
+static_assert(decodeVersion1ArchRequirements(4) == DecodedArchRequirements{ 4, false });
+static_assert(decodeVersion1ArchRequirements(0x82) == DecodedArchRequirements{ 2, true });
+static_assert(decodeVersion1ArchRequirements(0x84) == DecodedArchRequirements{ 4, true });
+#endif
+} // unnamed namespace
+
QT_END_NAMESPACE
#endif // QPLUGIN_P_H
diff --git a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
index 14be0082c7..ddc9ff7e7c 100644
--- a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
+++ b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
@@ -139,6 +139,7 @@ void tst_QPlugin::scanInvalidPlugin_data()
// CBOR metadata
static constexpr QPluginMetaData::MagicHeader header = {};
+ static constexpr qsizetype MagicLen = sizeof(header.magic);
QByteArray cprefix(reinterpret_cast<const char *>(&header), sizeof(header));
QByteArray cborValid = [] {
@@ -150,27 +151,27 @@ void tst_QPlugin::scanInvalidPlugin_data()
}();
QTest::newRow("cbor-control") << (cprefix + cborValid) << true << "";
- cprefix[12] = 1;
- QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false
- << " Invalid metadata version";
-
- cprefix[12] = 0;
- cprefix[13] = QT_VERSION_MAJOR + 1;
+ cprefix[MagicLen + 1] = QT_VERSION_MAJOR + 1;
QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false << "";
- cprefix[13] = QT_VERSION_MAJOR - 1;
+ cprefix[MagicLen + 1] = QT_VERSION_MAJOR - 1;
QTest::newRow("cbor-major-too-old") << (cprefix + cborValid) << false << "";
- cprefix[13] = QT_VERSION_MAJOR;
- cprefix[14] = QT_VERSION_MINOR + 1;
+ cprefix[MagicLen + 1] = QT_VERSION_MAJOR;
+ cprefix[MagicLen + 2] = QT_VERSION_MINOR + 1;
QTest::newRow("cbor-minor-too-new") << (cprefix + cborValid) << false << "";
+ cprefix[MagicLen + 2] = QT_VERSION_MINOR;
QTest::newRow("cbor-invalid") << (cprefix + "\xff") << false
<< " Metadata parsing error: Invalid CBOR stream: unexpected 'break' byte";
QTest::newRow("cbor-not-map1") << (cprefix + "\x01") << false
<< " Unexpected metadata contents";
QTest::newRow("cbor-not-map2") << (cprefix + "\x81\x01") << false
<< " Unexpected metadata contents";
+
+ ++cprefix[MagicLen + 0];
+ QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false
+ << " Invalid metadata version";
}
static const char invalidPluginSignature[] = "qplugin testfile";