1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmlirloader_p.h"
5#include <private/qqmlirbuilder_p.h>
6
7QT_BEGIN_NAMESPACE
8
9QQmlIRLoader::QQmlIRLoader(const QV4::CompiledData::Unit *qmlData, QmlIR::Document *output)
10 : unit(qmlData)
11 , output(output)
12{
13 pool = output->jsParserEngine.pool();
14}
15
16void QQmlIRLoader::load()
17{
18 output->jsGenerator.stringTable.initializeFromBackingUnit(unit);
19
20 const QV4::CompiledData::QmlUnit *qmlUnit = unit->qmlUnit();
21
22 for (quint32 i = 0; i < qmlUnit->nImports; ++i)
23 output->imports << qmlUnit->importAt(idx: i);
24
25 using QmlIR::Pragma;
26 const auto createPragma = [&](Pragma::PragmaType type) {
27 Pragma *p = New<Pragma>();
28 p->location = QV4::CompiledData::Location();
29 p->type = type;
30 output->pragmas << p;
31 return p;
32 };
33
34 const auto createListPragma = [&](
35 Pragma::PragmaType type,
36 Pragma::ListPropertyAssignBehaviorValue value) {
37 createPragma(type)->listPropertyAssignBehavior = value;
38 };
39
40 const auto createComponentPragma = [&](
41 Pragma::PragmaType type,
42 Pragma::ComponentBehaviorValue value) {
43 createPragma(type)->componentBehavior = value;
44 };
45
46 const auto createFunctionSignaturePragma = [&](
47 Pragma::PragmaType type,
48 Pragma::FunctionSignatureBehaviorValue value) {
49 createPragma(type)->functionSignatureBehavior = value;
50 };
51
52 const auto createNativeMethodPragma = [&](
53 Pragma::PragmaType type,
54 Pragma::NativeMethodBehaviorValue value) {
55 createPragma(type)->nativeMethodBehavior = value;
56 };
57
58 const auto createValueTypePragma = [&](
59 Pragma::PragmaType type,
60 Pragma::ValueTypeBehaviorValues value) {
61 createPragma(type)->valueTypeBehavior = value;
62 };
63
64 if (unit->flags & QV4::CompiledData::Unit::IsSingleton)
65 createPragma(Pragma::Singleton);
66 if (unit->flags & QV4::CompiledData::Unit::IsStrict)
67 createPragma(Pragma::Strict);
68
69 if (unit->flags & QV4::CompiledData::Unit::ListPropertyAssignReplace)
70 createListPragma(Pragma::ListPropertyAssignBehavior, Pragma::Replace);
71 else if (unit->flags & QV4::CompiledData::Unit::ListPropertyAssignReplaceIfNotDefault)
72 createListPragma(Pragma::ListPropertyAssignBehavior, Pragma::ReplaceIfNotDefault);
73
74 if (unit->flags & QV4::CompiledData::Unit::ComponentsBound)
75 createComponentPragma(Pragma::ComponentBehavior, Pragma::Bound);
76
77 if (unit->flags & QV4::CompiledData::Unit::FunctionSignaturesIgnored)
78 createFunctionSignaturePragma(Pragma::FunctionSignatureBehavior, Pragma::Ignored);
79
80 if (unit->flags & QV4::CompiledData::Unit::NativeMethodsAcceptThisObject)
81 createNativeMethodPragma(Pragma::NativeMethodBehavior, Pragma::AcceptThisObject);
82
83 Pragma::ValueTypeBehaviorValues valueTypeBehavior = {};
84 if (unit->flags & QV4::CompiledData::Unit::ValueTypesCopied)
85 valueTypeBehavior |= Pragma::Copy;
86 if (unit->flags & QV4::CompiledData::Unit::ValueTypesAddressable)
87 valueTypeBehavior |= Pragma::Addressable;
88 if (unit->flags & QV4::CompiledData::Unit::ValueTypesAssertable)
89 valueTypeBehavior |= Pragma::Assertable;
90 if (valueTypeBehavior)
91 createValueTypePragma(Pragma::ValueTypeBehavior, valueTypeBehavior);
92
93 for (uint i = 0; i < qmlUnit->nObjects; ++i) {
94 const QV4::CompiledData::Object *serializedObject = qmlUnit->objectAt(idx: i);
95 QmlIR::Object *object = loadObject(serializedObject);
96 output->objects.append(t: object);
97 }
98}
99
100struct FakeExpression : public QQmlJS::AST::NullExpression
101{
102 FakeExpression(int start, int length)
103 : location(start, length)
104 {}
105
106 QQmlJS::SourceLocation firstSourceLocation() const override
107 { return location; }
108
109 QQmlJS::SourceLocation lastSourceLocation() const override
110 { return location; }
111
112private:
113 QQmlJS::SourceLocation location;
114};
115
116QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *serializedObject)
117{
118 QmlIR::Object *object = pool->New<QmlIR::Object>();
119 object->init(pool, typeNameIndex: serializedObject->inheritedTypeNameIndex, idIndex: serializedObject->idNameIndex,
120 location: serializedObject->location);
121
122 object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
123 object->defaultPropertyIsAlias = serializedObject->hasAliasAsDefaultProperty();
124 object->flags = serializedObject->flags();
125 object->id = serializedObject->objectId();
126 object->locationOfIdProperty = serializedObject->locationOfIdProperty;
127
128 QVector<int> functionIndices;
129 functionIndices.reserve(asize: serializedObject->nFunctions + serializedObject->nBindings / 2);
130
131 for (uint i = 0; i < serializedObject->nBindings; ++i) {
132 QmlIR::Binding *b = pool->New<QmlIR::Binding>();
133 *static_cast<QV4::CompiledData::Binding*>(b) = serializedObject->bindingTable()[i];
134 object->bindings->append(item: b);
135 if (b->type() == QV4::CompiledData::Binding::Type_Script) {
136 functionIndices.append(t: b->value.compiledScriptIndex);
137 b->value.compiledScriptIndex = functionIndices.size() - 1;
138
139 QmlIR::CompiledFunctionOrExpression *foe = pool->New<QmlIR::CompiledFunctionOrExpression>();
140 foe->nameIndex = 0;
141
142 QQmlJS::AST::ExpressionNode *expr;
143
144 if (b->stringIndex != quint32(0)) {
145 const int start = output->code.size();
146 const QString script = output->stringAt(index: b->stringIndex);
147 const int length = script.size();
148 output->code.append(s: script);
149 expr = new (pool) FakeExpression(start, length);
150 } else
151 expr = new (pool) QQmlJS::AST::NullExpression();
152 foe->node = new (pool) QQmlJS::AST::ExpressionStatement(expr); // dummy
153 object->functionsAndExpressions->append(item: foe);
154 }
155 }
156
157 Q_ASSERT(object->functionsAndExpressions->count == functionIndices.size());
158
159 for (uint i = 0; i < serializedObject->nSignals; ++i) {
160 const QV4::CompiledData::Signal *serializedSignal = serializedObject->signalAt(idx: i);
161 QmlIR::Signal *s = pool->New<QmlIR::Signal>();
162 s->nameIndex = serializedSignal->nameIndex;
163 s->location = serializedSignal->location;
164 s->parameters = pool->New<QmlIR::PoolList<QmlIR::Parameter> >();
165
166 for (uint i = 0; i < serializedSignal->nParameters; ++i) {
167 QmlIR::Parameter *p = pool->New<QmlIR::Parameter>();
168 *static_cast<QV4::CompiledData::Parameter*>(p) = *serializedSignal->parameterAt(idx: i);
169 s->parameters->append(item: p);
170 }
171
172 object->qmlSignals->append(item: s);
173 }
174
175 for (uint i = 0; i < serializedObject->nEnums; ++i) {
176 const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(idx: i);
177 QmlIR::Enum *e = pool->New<QmlIR::Enum>();
178 e->nameIndex = serializedEnum->nameIndex;
179 e->location = serializedEnum->location;
180 e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >();
181
182 for (uint i = 0; i < serializedEnum->nEnumValues; ++i) {
183 QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>();
184 *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(idx: i);
185 e->enumValues->append(item: v);
186 }
187
188 object->qmlEnums->append(item: e);
189 }
190
191 const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable();
192 for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) {
193 QmlIR::Property *p = pool->New<QmlIR::Property>();
194 *static_cast<QV4::CompiledData::Property*>(p) = *serializedProperty;
195 object->properties->append(item: p);
196 }
197
198 {
199 const QV4::CompiledData::Alias *serializedAlias = serializedObject->aliasTable();
200 for (uint i = 0; i < serializedObject->nAliases; ++i, ++serializedAlias) {
201 QmlIR::Alias *a = pool->New<QmlIR::Alias>();
202 *static_cast<QV4::CompiledData::Alias*>(a) = *serializedAlias;
203 object->aliases->append(item: a);
204 }
205 }
206
207 const quint32_le *functionIdx = serializedObject->functionOffsetTable();
208 for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
209 QmlIR::Function *f = pool->New<QmlIR::Function>();
210 const QV4::CompiledData::Function *compiledFunction = unit->functionAt(idx: *functionIdx);
211
212 functionIndices.append(t: *functionIdx);
213 f->index = functionIndices.size() - 1;
214 f->location = compiledFunction->location;
215 f->nameIndex = compiledFunction->nameIndex;
216 f->returnType = compiledFunction->returnType;
217
218 f->formals.allocate(pool, size: int(compiledFunction->nFormals));
219 const QV4::CompiledData::Parameter *formalNameIdx = compiledFunction->formalsTable();
220 for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
221 *static_cast<QV4::CompiledData::Parameter*>(&f->formals[i]) = *formalNameIdx;
222
223 object->functions->append(item: f);
224 }
225
226 object->runtimeFunctionIndices.allocate(pool, vector: functionIndices);
227
228 const QV4::CompiledData::InlineComponent *serializedInlineComponent = serializedObject->inlineComponentTable();
229 for (uint i = 0; i < serializedObject->nInlineComponents; ++i, ++serializedInlineComponent) {
230 QmlIR::InlineComponent *ic = pool->New<QmlIR::InlineComponent>();
231 *static_cast<QV4::CompiledData::InlineComponent*>(ic) = *serializedInlineComponent;
232 object->inlineComponents->append(item: ic);
233 }
234
235 const QV4::CompiledData::RequiredPropertyExtraData *serializedRequiredPropertyExtraData = serializedObject->requiredPropertyExtraDataTable();
236 for (uint i = 0u; i < serializedObject->nRequiredPropertyExtraData; ++i, ++serializedRequiredPropertyExtraData) {
237 QmlIR::RequiredPropertyExtraData *extra = pool->New<QmlIR::RequiredPropertyExtraData>();
238 *static_cast<QV4::CompiledData::RequiredPropertyExtraData *>(extra) = *serializedRequiredPropertyExtraData;
239 object->requiredPropertyExtraDatas->append(item: extra);
240 }
241
242 return object;
243}
244
245QT_END_NAMESPACE
246

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtdeclarative/src/qml/qml/qqmlirloader.cpp