diff options
Diffstat (limited to 'src/qmlcompiler/qqmljsstoragegeneralizer.cpp')
-rw-r--r-- | src/qmlcompiler/qqmljsstoragegeneralizer.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/qmlcompiler/qqmljsstoragegeneralizer.cpp b/src/qmlcompiler/qqmljsstoragegeneralizer.cpp new file mode 100644 index 0000000000..937c35ddcd --- /dev/null +++ b/src/qmlcompiler/qqmljsstoragegeneralizer.cpp @@ -0,0 +1,63 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "qqmljsstoragegeneralizer_p.h" + +QT_BEGIN_NAMESPACE + +/*! + * \internal + * \class QQmlJSStorageGeneralizer + * + * The QQmlJSStorageGeneralizer is a compile pass that changes all type + * annotations and the function signature to use a generic storage type like + * QVariant or QObject*. This is necessary if we cannot rely on the original + * type to be immediately accessible, for example because we cannot include its + * header. + * + * QQmlJSStorageGeneralizer does not have to use the byte code at all but + * operates only on the annotations and the function description. + */ + +QQmlJSCompilePass::BlocksAndAnnotations +QQmlJSStorageGeneralizer::run(Function *function, QQmlJS::DiagnosticMessage *error) +{ + m_error = error; + + if (QQmlJSRegisterContent &returnType = function->returnType; returnType.isValid()) { + if (QQmlJSScope::ConstPtr stored = m_typeResolver->genericType( + returnType.storedType(), QQmlJSTypeResolver::ComponentIsGeneric::Yes)) { + returnType = returnType.storedIn(stored); + } else { + setError(QStringLiteral("Cannot store the return type %1.") + .arg(returnType.storedType()->internalName())); + return {}; + } + } + + const auto transformRegister = [&](QQmlJSRegisterContent &content) { + if (const QQmlJSScope::ConstPtr &specific = content.storedType()) + m_typeResolver->generalizeType(specific); + }; + + const auto transformRegisters = [&](VirtualRegisters ®isters) { + for (auto j = registers.begin(), jEnd = registers.end(); j != jEnd; ++j) { + QQmlJSRegisterContent &content = j.value().content; + transformRegister(content); + } + }; + + for (QQmlJSRegisterContent &argument : function->argumentTypes) { + Q_ASSERT(argument.isValid()); + transformRegister(argument); + } + + for (auto i = m_annotations.begin(), iEnd = m_annotations.end(); i != iEnd; ++i) { + transformRegister(i->second.changedRegister); + transformRegisters(i->second.typeConversions); + } + + return { std::move(m_basicBlocks), std::move(m_annotations) }; +} + +QT_END_NAMESPACE |