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>
This commit is contained in:
parent
16e7366b5c
commit
349fb14c1d
@ -95,11 +95,15 @@ QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QStri
|
|||||||
return QJsonDocument();
|
return QJsonDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DecodedArchRequirements archReq =
|
||||||
|
header.version == 0 ? decodeVersion0ArchRequirements(header.plugin_arch_requirements)
|
||||||
|
: decodeVersion1ArchRequirements(header.plugin_arch_requirements);
|
||||||
|
|
||||||
QJsonObject o;
|
QJsonObject o;
|
||||||
o.insert(QLatin1String("version"),
|
o.insert(QLatin1String("version"),
|
||||||
QT_VERSION_CHECK(header.qt_major_version, header.qt_minor_version, 0));
|
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("debug"), archReq.isDebug);
|
||||||
o.insert(QLatin1String("archreq"), header.plugin_arch_requirements);
|
o.insert(QLatin1String("archlevel"), archReq.level);
|
||||||
|
|
||||||
// convert the top-level map integer keys
|
// convert the top-level map integer keys
|
||||||
for (auto it : metadata.toMap()) {
|
for (auto it : metadata.toMap()) {
|
||||||
@ -112,9 +116,7 @@ QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QStri
|
|||||||
#undef CONVERT_TO_STRING
|
#undef CONVERT_TO_STRING
|
||||||
|
|
||||||
case int(QtPluginMetaDataKeys::Requirements):
|
case int(QtPluginMetaDataKeys::Requirements):
|
||||||
// special case: recreate the debug key
|
// ignore, handled above
|
||||||
o.insert(QLatin1String("debug"), bool(it.second.toInteger() & 1));
|
|
||||||
key = QStringLiteral("archreq");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
// Used up to Qt 6.2
|
||||||
inline constexpr unsigned char qPluginArchRequirements()
|
inline constexpr unsigned char qPluginArchRequirements()
|
||||||
{
|
{
|
||||||
return 0
|
return 0
|
||||||
@ -65,7 +66,7 @@ inline constexpr unsigned char qPluginArchRequirements()
|
|||||||
typedef QObject *(*QtPluginInstanceFunction)();
|
typedef QObject *(*QtPluginInstanceFunction)();
|
||||||
struct QPluginMetaData
|
struct QPluginMetaData
|
||||||
{
|
{
|
||||||
static constexpr quint8 CurrentMetaDataVersion = 0;
|
static constexpr quint8 CurrentMetaDataVersion = 1;
|
||||||
static constexpr char MagicString[] = {
|
static constexpr char MagicString[] = {
|
||||||
'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!'
|
'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!'
|
||||||
};
|
};
|
||||||
@ -79,11 +80,29 @@ struct QPluginMetaData
|
|||||||
out[i] = in[i];
|
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 {
|
struct Header {
|
||||||
quint8 version = CurrentMetaDataVersion;
|
quint8 version = CurrentMetaDataVersion;
|
||||||
quint8 qt_major_version = QT_VERSION_MAJOR;
|
quint8 qt_major_version = QT_VERSION_MAJOR;
|
||||||
quint8 qt_minor_version = QT_VERSION_MINOR;
|
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");
|
static_assert(alignof(Header) == 1, "Alignment of header incorrect with this compiler");
|
||||||
|
|
||||||
|
@ -72,6 +72,57 @@ enum class QtPluginMetaDataKeys {
|
|||||||
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data") \
|
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data") \
|
||||||
F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI")
|
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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QPLUGIN_P_H
|
#endif // QPLUGIN_P_H
|
||||||
|
@ -139,6 +139,7 @@ void tst_QPlugin::scanInvalidPlugin_data()
|
|||||||
|
|
||||||
// CBOR metadata
|
// CBOR metadata
|
||||||
static constexpr QPluginMetaData::MagicHeader header = {};
|
static constexpr QPluginMetaData::MagicHeader header = {};
|
||||||
|
static constexpr qsizetype MagicLen = sizeof(header.magic);
|
||||||
QByteArray cprefix(reinterpret_cast<const char *>(&header), sizeof(header));
|
QByteArray cprefix(reinterpret_cast<const char *>(&header), sizeof(header));
|
||||||
|
|
||||||
QByteArray cborValid = [] {
|
QByteArray cborValid = [] {
|
||||||
@ -150,27 +151,27 @@ void tst_QPlugin::scanInvalidPlugin_data()
|
|||||||
}();
|
}();
|
||||||
QTest::newRow("cbor-control") << (cprefix + cborValid) << true << "";
|
QTest::newRow("cbor-control") << (cprefix + cborValid) << true << "";
|
||||||
|
|
||||||
cprefix[12] = 1;
|
cprefix[MagicLen + 1] = QT_VERSION_MAJOR + 1;
|
||||||
QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false
|
|
||||||
<< " Invalid metadata version";
|
|
||||||
|
|
||||||
cprefix[12] = 0;
|
|
||||||
cprefix[13] = QT_VERSION_MAJOR + 1;
|
|
||||||
QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false << "";
|
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 << "";
|
QTest::newRow("cbor-major-too-old") << (cprefix + cborValid) << false << "";
|
||||||
|
|
||||||
cprefix[13] = QT_VERSION_MAJOR;
|
cprefix[MagicLen + 1] = QT_VERSION_MAJOR;
|
||||||
cprefix[14] = QT_VERSION_MINOR + 1;
|
cprefix[MagicLen + 2] = QT_VERSION_MINOR + 1;
|
||||||
QTest::newRow("cbor-minor-too-new") << (cprefix + cborValid) << false << "";
|
QTest::newRow("cbor-minor-too-new") << (cprefix + cborValid) << false << "";
|
||||||
|
|
||||||
|
cprefix[MagicLen + 2] = QT_VERSION_MINOR;
|
||||||
QTest::newRow("cbor-invalid") << (cprefix + "\xff") << false
|
QTest::newRow("cbor-invalid") << (cprefix + "\xff") << false
|
||||||
<< " Metadata parsing error: Invalid CBOR stream: unexpected 'break' byte";
|
<< " Metadata parsing error: Invalid CBOR stream: unexpected 'break' byte";
|
||||||
QTest::newRow("cbor-not-map1") << (cprefix + "\x01") << false
|
QTest::newRow("cbor-not-map1") << (cprefix + "\x01") << false
|
||||||
<< " Unexpected metadata contents";
|
<< " Unexpected metadata contents";
|
||||||
QTest::newRow("cbor-not-map2") << (cprefix + "\x81\x01") << false
|
QTest::newRow("cbor-not-map2") << (cprefix + "\x81\x01") << false
|
||||||
<< " Unexpected metadata contents";
|
<< " Unexpected metadata contents";
|
||||||
|
|
||||||
|
++cprefix[MagicLen + 0];
|
||||||
|
QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false
|
||||||
|
<< " Invalid metadata version";
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char invalidPluginSignature[] = "qplugin testfile";
|
static const char invalidPluginSignature[] = "qplugin testfile";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user