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 | |
6 | QT_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 | |
22 | QQmlJSCompilePass::BlocksAndAnnotations |
23 | QQmlJSStorageGeneralizer::run(Function *function, QQmlJS::DiagnosticMessage *error) |
24 | { |
25 | m_error = error; |
26 | |
27 | if (QQmlJSRegisterContent &returnType = function->returnType; returnType.isValid()) { |
28 | if (QQmlJSScope::ConstPtr stored = m_typeResolver->genericType( |
29 | type: returnType.storedType(), allowComponent: QQmlJSTypeResolver::ComponentIsGeneric::Yes)) { |
30 | returnType = returnType.storedIn(newStoredType: stored); |
31 | } else { |
32 | setError(QStringLiteral("Cannot store the return type %1.") |
33 | .arg(a: returnType.storedType()->internalName())); |
34 | return {}; |
35 | } |
36 | } |
37 | |
38 | const auto transformRegister = [&](QQmlJSRegisterContent &content) { |
39 | if (const QQmlJSScope::ConstPtr &specific = content.storedType()) |
40 | m_typeResolver->generalizeType(type: specific); |
41 | }; |
42 | |
43 | const auto transformRegisters = [&](VirtualRegisters ®isters) { |
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 | } |
59 | |
60 | return { .basicBlocks: std::move(m_basicBlocks), .annotations: std::move(m_annotations) }; |
61 | } |
62 | |
63 | QT_END_NAMESPACE |
64 |