Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4codegen_p.h
Go to the documentation of this file.
1// Copyright (C) 2017 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#ifndef QV4CODEGEN_P_H
4#define QV4CODEGEN_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <private/qqmljsastvisitor_p.h>
18#include <private/qqmljsengine_p.h>
19#include <private/qqmljsast_p.h>
20#include <private/qqmljsdiagnosticmessage_p.h>
21#include <private/qv4compiler_p.h>
22#include <private/qv4compilercontext_p.h>
23#include <private/qv4util_p.h>
24#include <private/qv4bytecodegenerator_p.h>
25#include <private/qv4calldata_p.h>
26
27#include <QtCore/qsharedpointer.h>
28#include <QtCore/qxpfunctional.h>
29
30#include <stack>
31
32QT_BEGIN_NAMESPACE
33
34namespace QV4 {
35
36namespace Moth {
37struct Instruction;
38}
39
40namespace CompiledData {
41struct CompilationUnit;
42}
43
44namespace Compiler {
45
46struct ControlFlow;
47struct ControlFlowCatch;
49
50class Q_QML_COMPILER_EXPORT CodegenWarningInterface
51{
52public:
56 virtual ~CodegenWarningInterface() = default;
57};
58
60{
61 static CodegenWarningInterface iface;
62 return &iface;
63}
64
65class Q_QML_COMPILER_EXPORT Codegen: protected QQmlJS::AST::Visitor
66{
67protected:
70public:
73 bool storeSourceLocations = false);
74
75 static bool isNameGlobal(QAnyStringView name);
77
81
84
85public:
89 bool allVolatile = false;
91 public:
93 if (allVolatile)
94 return true;
96 }
97
99 void setAllVolatile() { allVolatile = true; }
100 };
101 class RValue {
103 enum Type {
104 Invalid,
106 StackSlot,
107 Const
108 } type;
109 union {
112 };
113
114 public:
123 RValue r;
124 r.codegen = codegen;
126 return r;
127 }
129 RValue r;
130 r.codegen = codegen;
131 r.type = Const;
132 r.constant = value;
133 return r;
134 }
135
136 bool operator==(const RValue &other) const;
137
138 bool isValid() const { return type != Invalid; }
139 bool isAccumulator() const { return type == Accumulator; }
140 bool isStackSlot() const { return type == StackSlot; }
141 bool isConst() const { return type == Const; }
142
145 return theStackSlot;
146 }
147
149 Q_ASSERT(isConst());
150 return constant;
151 }
152
154 void loadInAccumulator() const;
155 };
156 struct Reference {
171
172 bool isLValue() const { return !isReadonly && type > Accumulator; }
173
175 {
176 type = t;
177 codegen = cg;
178 }
179
181 constant(0),
182 name(name),
183 isArgOrEval(false),
184 isReadonly(false),
185 isReferenceToConst(false),
186 requiresTDZCheck(false),
189 isVolatile(false),
190 global(false),
191 qmlGlobal(false),
194 isOptional(false),
196 {}
197
198 Reference(const Reference &) = default;
199 Reference(Reference &&) = default;
200 Reference &operator =(const Reference &) = default;
201 Reference &operator =(Reference &&) = default;
202
203 bool operator==(const Reference &other) const;
204 bool operator!=(const Reference &other) const
205 { return !(*this == other); }
206
207 bool isValid() const { return type != Invalid; }
209 switch (type) {
210 case Name:
211 case Member:
212 case Subscript:
213 case SuperProperty:
214 return true;
215 default:
216 return requiresTDZCheck;
217 }
218 }
219 bool isConstant() const { return type == Const; }
220 bool isAccumulator() const { return type == Accumulator; }
221 bool isSuper() const { return type == Super; }
222 bool isSuperProperty() const { return type == SuperProperty; }
223 bool isStackSlot() const { return type == StackSlot; }
224 bool isRegister() const {
225 return isStackSlot();
226 }
227
232 return Reference(cg, Super);
233 }
244 r.index = index;
245 r.scope = scope;
246 return r;
247 }
250 r.index = index;
251 return r;
252 }
254 Reference r(cg, Name);
255 r.name = name;
256 return r;
257 }
258 static Reference
293 r.isReadonly = true;
294 return r;
295 }
298 r.isReadonly = true;
299 // ### Optimize this. Functions that are not derived constructors or arrow functions can't have an
300 // empty this object
301 r.requiresTDZCheck = true;
302 return r;
303 }
304
305 RValue asRValue() const;
306 Reference asLValue() const;
307
310
313
315 void storeOnStack(int tempIndex) const;
318
320
321 bool storeWipesAccumulator() const;
322 void loadInAccumulator() const;
323
324 int nameAsIndex() const {
325 Q_ASSERT(type == Name);
326 return codegen->registerString(name);
327 }
328
330 if (Q_UNLIKELY(!isStackSlot()))
332 return theStackSlot;
333 }
334
342
343 union {
346 struct { // Scoped arguments/Local
347 int index;
348 int scope;
349 };
350 struct {
353 };
354 struct {
356 union {
359 };
360 };
361 Moth::StackSlot property; // super property
362 };
364 Codegen *codegen = nullptr;
365
383
384 private:
385 void storeAccumulator() const;
387 void tdzCheck(bool requiresCheck, bool throwsReferenceError) const;
390 };
391
402
405
407 int getter = -1; // index in _module->functions or -1 if not set
408 int setter = -1;
410
411 bool hasGetter() const { return getter >= 0; }
412 bool hasSetter() const { return setter >= 0; }
413 };
414protected:
415
416 enum Format { ex, cx, nx };
417 class Result {
419
420 const BytecodeGenerator::Label *_iftrue = nullptr;
421 const BytecodeGenerator::Label *_iffalse = nullptr;
422 Format _format = ex;
424 bool _trueBlockFollowsCondition = false;
425
426 public:
427 explicit Result(const QString &name)
428 : _result(name)
429 , _requested(ex)
430 {}
431
432 explicit Result(const Reference &lrvalue)
434 , _requested(ex)
435 {}
436
439
451
454 return _iftrue;
455 }
456
459 return _iffalse;
460 }
461
462 Format format() const {
463 return _format;
464 }
465
467 {
468 if (_requested == f) {
469 _format = f;
470 return true;
471 }
472 return false;
473 }
474
478
479 const Reference &result() const {
480 return _result;
481 }
482
484 _result = result;
485 }
486
489 }
490
493 }
494 };
495
497 int leaveContext();
498public:
500 int leaveBlock() { return leaveContext(); }
501protected:
502 void leaveLoop();
503
514
516
517 void addCJump();
518
519public:
543
544 // Returns index in _module->functions
548
549protected:
555
557 {
558 if (!ast || hasError())
559 return Reference();
560
561 pushExpr(name);
562 ast->accept(this);
563 return popResult();
564 }
565
566 inline void accept(QQmlJS::AST::Node *node)
567 {
568 if (!hasError() && node)
569 node->accept(this);
570 }
571
572 void program(QQmlJS::AST::Program *ast);
576
582
584
585 void emitReturn(const Reference &expr);
586
587 // nodes
592 bool visit(QQmlJS::AST::Catch *ast) override;
610
615
617
619
620 // expressions
662
663 // statements
664 bool visit(QQmlJS::AST::Block *ast) override;
682
683 // ui object members
690
692 const QQmlJS::SourceLocation &loc);
693 virtual void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail);
694 virtual void throwReferenceError(const QQmlJS::SourceLocation &loc, const QString &detail);
696 {
698 QStringLiteral("Maximum statement or expression depth exceeded"));
699 }
700
701public:
707
708 ErrorType errorType() const { return _errorType; }
709 bool hasError() const { return _errorType != NoError; }
711 QUrl url() const;
712
716 struct Arguments { int argc; int argv; bool hasSpread; };
719
723
725
728
729
731 const QString &name, bool lhs,
733
735 bool generateUnitData = true);
737 bool debugMode, const QString &url, const QString &sourceCode,
739
741 bool debugMode, const QString &url, const QV4::Value &value);
742
743 Context *currentContext() const { return _context; }
745
746 void loadClosure(int index);
747
748 Module *module() const { return _module; }
749
755
756protected:
757 friend class ScanFunctions;
758 friend struct ControlFlow;
759 friend struct ControlFlowCatch;
760 friend struct ControlFlowFinally;
761
764 inline Reference exprResult() const { return m_expressions.back().result(); }
766
767 inline bool exprAccept(Format f) { return m_expressions.back().accept(f); }
768
769 inline const Result &currentExpr() const { return m_expressions.back(); }
770
772 inline void pushExpr(const Result &expr) { m_expressions.push_back(expr); }
774
776 {
779 return result;
780 }
781
785 return result;
786 }
787
799 bool useFastLookups = true;
801 bool insideSwitch = false;
806
815
817
822
824 {
825 public:
831
834
835 void unblock() const
837
838 void reblock() const
840
841 private:
842 Codegen *_cg;
843 bool _saved;
844 bool _onoff;
845 };
846
847private:
852 const QString &detail);
855 bool isDeleteExpression = false);
857 void generateThrowException(const QString &type, const QString &text = QString());
858};
859
860}
861
862}
863
864QT_END_NAMESPACE
865
866#endif // QV4CODEGEN_P_H
Codegen::VolatileMemoryLocations scan(AST::Node *s)
bool visit(ArrayMemberExpression *) override
CodegenWarningInterface * defaultCodegenWarningInterface()
Definition qjsvalue.h:23
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
static Node * completionStatement(StatementList *list)
static CompletionState completionState(StatementList *list)
static QSOperator::Op baseOp(int op)
CompletionState
static bool endsWithReturn(Module *module, Node *node)
static void setJumpOutLocation(QV4::Moth::BytecodeGenerator *bytecodeGenerator, const Statement *body, const SourceLocation &fallback)
static constexpr const QLatin1StringView s_globalNames[]