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
63
65{
66 static CodegenWarningInterface iface;
67 return &iface;
68}
69
70class Q_QML_COMPILER_EXPORT Codegen: protected QQmlJS::AST::Visitor
71{
72protected:
75public:
78 bool storeSourceLocations = false);
79
80 static bool isNameGlobal(QAnyStringView name);
82
86
89
90public:
94 bool allVolatile = false;
96 public:
98 if (allVolatile)
99 return true;
101 }
102
104 void setAllVolatile() { allVolatile = true; }
105 };
106 class RValue {
108 enum Type {
109 Invalid,
111 StackSlot,
112 Const
113 } type;
114 union {
117 };
118
119 public:
128 RValue r;
129 r.codegen = codegen;
131 return r;
132 }
134 RValue r;
135 r.codegen = codegen;
136 r.type = Const;
137 r.constant = value;
138 return r;
139 }
140
141 bool operator==(const RValue &other) const;
142
143 bool isValid() const { return type != Invalid; }
144 bool isAccumulator() const { return type == Accumulator; }
145 bool isStackSlot() const { return type == StackSlot; }
146 bool isConst() const { return type == Const; }
147
150 return theStackSlot;
151 }
152
154 Q_ASSERT(isConst());
155 return constant;
156 }
157
159 void loadInAccumulator() const;
160 };
161 struct Reference {
176
177 bool isLValue() const { return !isReadonly && type > Accumulator; }
178
180 {
181 type = t;
182 codegen = cg;
183 }
184
186 constant(0),
187 name(name),
188 isArgOrEval(false),
189 isReadonly(false),
190 isReferenceToConst(false),
191 requiresTDZCheck(false),
194 isVolatile(false),
195 global(false),
196 qmlGlobal(false),
199 isOptional(false),
201 {}
202
203 Reference(const Reference &) = default;
204 Reference(Reference &&) = default;
205 Reference &operator =(const Reference &) = default;
206 Reference &operator =(Reference &&) = default;
207
208 bool operator==(const Reference &other) const;
209 bool operator!=(const Reference &other) const
210 { return !(*this == other); }
211
212 bool isValid() const { return type != Invalid; }
214 switch (type) {
215 case Name:
216 case Member:
217 case Subscript:
218 case SuperProperty:
219 return true;
220 default:
221 return requiresTDZCheck;
222 }
223 }
224 bool isConstant() const { return type == Const; }
225 bool isAccumulator() const { return type == Accumulator; }
226 bool isSuper() const { return type == Super; }
227 bool isSuperProperty() const { return type == SuperProperty; }
228 bool isStackSlot() const { return type == StackSlot; }
229 bool isRegister() const {
230 return isStackSlot();
231 }
232
237 return Reference(cg, Super);
238 }
249 r.index = index;
250 r.scope = scope;
251 return r;
252 }
255 r.index = index;
256 return r;
257 }
259 Reference r(cg, Name);
260 r.name = name;
261 return r;
262 }
263 static Reference
298 r.isReadonly = true;
299 return r;
300 }
303 r.isReadonly = true;
304 // ### Optimize this. Functions that are not derived constructors or arrow functions can't have an
305 // empty this object
306 r.requiresTDZCheck = true;
307 return r;
308 }
309
310 RValue asRValue() const;
311 Reference asLValue() const;
312
315
318
320 void storeOnStack(int tempIndex) const;
323
325
326 bool storeWipesAccumulator() const;
327 void loadInAccumulator() const;
328
329 int nameAsIndex() const {
330 Q_ASSERT(type == Name);
331 return codegen->registerString(name);
332 }
333
335 if (Q_UNLIKELY(!isStackSlot()))
337 return theStackSlot;
338 }
339
347
348 union {
351 struct { // Scoped arguments/Local
352 int index;
353 int scope;
354 };
355 struct {
358 };
359 struct {
361 union {
364 };
365 };
366 Moth::StackSlot property; // super property
367 };
369 Codegen *codegen = nullptr;
370
388
389 private:
390 void storeAccumulator() const;
392 void tdzCheck(bool requiresCheck, bool throwsReferenceError) const;
395 };
396
407
410
412 int getter = -1; // index in _module->functions or -1 if not set
413 int setter = -1;
415
416 bool hasGetter() const { return getter >= 0; }
417 bool hasSetter() const { return setter >= 0; }
418 };
419protected:
420
421 enum Format { ex, cx, nx };
422 class Result {
424
425 const BytecodeGenerator::Label *_iftrue = nullptr;
426 const BytecodeGenerator::Label *_iffalse = nullptr;
427 Format _format = ex;
429 bool _trueBlockFollowsCondition = false;
430
431 public:
432 explicit Result(const QString &name)
433 : _result(name)
434 , _requested(ex)
435 {}
436
437 explicit Result(const Reference &lrvalue)
439 , _requested(ex)
440 {}
441
444
456
459 return _iftrue;
460 }
461
464 return _iffalse;
465 }
466
467 Format format() const {
468 return _format;
469 }
470
472 {
473 if (_requested == f) {
474 _format = f;
475 return true;
476 }
477 return false;
478 }
479
483
484 const Reference &result() const {
485 return _result;
486 }
487
489 _result = result;
490 }
491
494 }
495
498 }
499 };
500
502 int leaveContext();
503public:
505 int leaveBlock() { return leaveContext(); }
506protected:
507 void leaveLoop();
508
519
521
522 void addCJump();
523
524public:
548
549 // Returns index in _module->functions
553
554protected:
560
562 {
563 if (!ast || hasError())
564 return Reference();
565
566 pushExpr(name);
567 ast->accept(this);
568 return popResult();
569 }
570
571 inline void accept(QQmlJS::AST::Node *node)
572 {
573 if (!hasError() && node)
574 node->accept(this);
575 }
576
577 void program(QQmlJS::AST::Program *ast);
581
587
589
590 void emitReturn(const Reference &expr);
591
592 // nodes
597 bool visit(QQmlJS::AST::Catch *ast) override;
615
620
622
624
625 // expressions
667
668 // statements
669 bool visit(QQmlJS::AST::Block *ast) override;
687
688 // ui object members
695
697 const QQmlJS::SourceLocation &loc);
698 virtual void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail);
699 virtual void throwReferenceError(const QQmlJS::SourceLocation &loc, const QString &detail);
701 {
703 QStringLiteral("Maximum statement or expression depth exceeded"));
704 }
705
706public:
712
713 ErrorType errorType() const { return _errorType; }
714 bool hasError() const { return _errorType != NoError; }
716 QUrl url() const;
717
721 struct Arguments { int argc; int argv; bool hasSpread; };
724
728
730
733
734
736 const QString &name, bool lhs,
738
740 bool generateUnitData = true);
742 bool debugMode, const QString &url, const QString &sourceCode,
744
746 bool debugMode, const QString &url, const QV4::Value &value);
747
748 Context *currentContext() const { return _context; }
750
751 void loadClosure(int index);
752
753 Module *module() const { return _module; }
754
760
761protected:
762 friend class ScanFunctions;
763 friend struct ControlFlow;
764 friend struct ControlFlowCatch;
765 friend struct ControlFlowFinally;
766
769 inline Reference exprResult() const { return m_expressions.back().result(); }
771
772 inline bool exprAccept(Format f) { return m_expressions.back().accept(f); }
773
774 inline const Result &currentExpr() const { return m_expressions.back(); }
775
777 inline void pushExpr(const Result &expr) { m_expressions.push_back(expr); }
779
781 {
784 return result;
785 }
786
790 return result;
791 }
792
804 bool useFastLookups = true;
806 bool insideSwitch = false;
811
820
822
827
829 {
830 public:
836
839
840 void unblock() const
842
843 void reblock() const
845
846 private:
847 Codegen *_cg;
848 bool _saved;
849 bool _onoff;
850 };
851
852private:
857 const QString &detail);
860 bool isDeleteExpression = false);
862 void generateThrowException(const QString &type, const QString &text = QString());
863};
864
865}
866
867}
868
869QT_END_NAMESPACE
870
871#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[]