1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "qqmljsstoragegeneralizer_p.h"
5
6QT_BEGIN_NAMESPACE
7
8/*!
9 * \internal
10 * \class QQmlJSStorageGeneralizer
11 *
12 * The QQmlJSStorageGeneralizer is a compile pass that changes all type
13 * annotations and the function signature to use a generic storage type like
14 * QVariant or QObject*. This is necessary if we cannot rely on the original
15 * type to be immediately accessible, for example because we cannot include its
16 * header.
17 *
18 * QQmlJSStorageGeneralizer does not have to use the byte code at all but
19 * operates only on the annotations and the function description.
20 */
21
22QQmlJSCompilePass::BlocksAndAnnotations QQmlJSStorageGeneralizer::run(Function *function)
23{
24 m_function = function;
25
26 if (QQmlJSRegisterContent &returnType = function->returnType; returnType.isValid()) {
27 if (QQmlJSScope::ConstPtr stored = m_typeResolver->genericType(
28 type: returnType.storedType(), allowComponent: QQmlJSTypeResolver::ComponentIsGeneric::Yes)) {
29 m_pool->generalizeType(content: returnType.storage(), generalized: stored);
30 } else {
31 addError(QStringLiteral("Cannot store the return type %1.")
32 .arg(a: returnType.storedType()->internalName()));
33 return {};
34 }
35 }
36
37 const auto transformRegister = [&](QQmlJSRegisterContent &content) {
38 QQmlJSRegisterContent specific = content.storage();
39 if (specific.isValid())
40 m_typeResolver->generalizeType(type: specific);
41 };
42
43 const auto transformRegisters = [&](VirtualRegisters &registers) {
44 for (auto j = registers.begin(), jEnd = registers.end(); j != jEnd; ++j) {
45 QQmlJSRegisterContent &content = j.value().content;
46 transformRegister(content);
47 }
48 };
49
50 for (QQmlJSRegisterContent &argument : function->argumentTypes) {
51 Q_ASSERT(argument.isValid());
52 transformRegister(argument);
53 }
54
55 for (auto i = m_annotations.begin(), iEnd = m_annotations.end(); i != iEnd; ++i) {
56 transformRegister(i->second.changedRegister);
57 transformRegisters(i->second.typeConversions);
58 transformRegisters(i->second.readRegisters);
59 }
60
61 return { .basicBlocks: std::move(m_basicBlocks), .annotations: std::move(m_annotations) };
62}
63
64QT_END_NAMESPACE
65

source code of qtdeclarative/src/qmlcompiler/qqmljsstoragegeneralizer.cpp