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();
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
Loading…
x
Reference in New Issue
Block a user