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// Qt-Security score:significant
4
5#ifndef QV4CODEGEN_P_H
6#define QV4CODEGEN_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmljsastvisitor_p.h>
20#include <private/qqmljsengine_p.h>
21#include <private/qqmljsast_p.h>
22#include <private/qqmljsdiagnosticmessage_p.h>
23#include <private/qv4compiler_p.h>
24#include <private/qv4compilercontext_p.h>
25#include <private/qv4util_p.h>
26#include <private/qv4bytecodegenerator_p.h>
27#include <private/qv4calldata_p.h>
28
29#include <QtCore/qsharedpointer.h>
30#include <QtCore/qxpfunctional.h>
31
32#include <stack>
33
34QT_BEGIN_NAMESPACE
35
36namespace QV4 {
37
38namespace Moth {
39struct Instruction;
40}
41
42namespace CompiledData {
43struct CompilationUnit;
44}
45
46namespace Compiler {
47
48struct ControlFlow;
49struct ControlFlowCatch;
51
65
67{
68 static CodegenWarningInterface iface;
69 return &iface;
70}
71
72class Q_QML_COMPILER_EXPORT Codegen: protected QQmlJS::AST::Visitor
73{
74protected:
77public:
80 bool storeSourceLocations = false);
81
82 static bool isNameGlobal(QAnyStringView name);
84
88
91
92public:
96 bool allVolatile = false;
98 public:
100 if (allVolatile)
101 return true;
103 }
104
106 void setAllVolatile() { allVolatile = true; }
107 };
108 class RValue {
110 enum Type {
111 Invalid,
113 StackSlot,
114 Const
115 } type;
116 union {
119 };
120
121 public:
130 RValue r;
131 r.codegen = codegen;
133 return r;
134 }
136 RValue r;
137 r.codegen = codegen;
138 r.type = Const;
139 r.constant = value;
140 return r;
141 }
142
143 bool operator==(const RValue &other) const;
144
145 bool isValid() const { return type != Invalid; }
146 bool isAccumulator() const { return type == Accumulator; }
147 bool isStackSlot() const { return type == StackSlot; }
148 bool isConst() const { return type == Const; }
149
152 return theStackSlot;
153 }
154
156 Q_ASSERT(isConst());
157 return constant;
158 }
159
161 void loadInAccumulator() const;
162 };
163 struct Reference {
178
179 bool isLValue() const { return !isReadonly && type > Accumulator; }
180
182 {
183 type = t;
184 codegen = cg;
185 }
186
188 constant(0),
189 name(name),
190 isArgOrEval(false),
191 isReadonly(false),
192 isReferenceToConst(false),
193 requiresTDZCheck(false),
196 isVolatile(false),
197 global(false),
198 qmlGlobal(false),
201 isOptional(false),
203 {}
204
205 Reference(const Reference &) = default;
206 Reference(Reference &&) = default;
207 Reference &operator =(const Reference &) = default;
208 Reference &operator =(Reference &&) = default;
209
210 bool operator==(const Reference &other) const;
211 bool operator!=(const Reference &other) const
212 { return !(*this == other); }
213
214 bool isValid() const { return type != Invalid; }
216 switch (type) {
217 case Name:
218 case Member:
219 case Subscript:
220 case SuperProperty:
221 return true;
222 default:
223 return requiresTDZCheck;
224 }
225 }
226 bool isConstant() const { return type == Const; }
227 bool isAccumulator() const { return type == Accumulator; }
228 bool isSuper() const { return type == Super; }
229 bool isSuperProperty() const { return type == SuperProperty; }
230 bool isStackSlot() const { return type == StackSlot; }
231 bool isRegister() const {
232 return isStackSlot();
233 }
234
239 return Reference(cg, Super);
240 }
251 r.index = index;
252 r.scope = scope;
253 return r;
254 }
257 r.index = index;
258 return r;
259 }
261 Reference r(cg, Name);
262 r.name = name;
263 return r;
264 }
265 static Reference
300 r.isReadonly = true;
301 return r;
302 }
305 r.isReadonly = true;
306 // ### Optimize this. Functions that are not derived constructors or arrow functions can't have an
307 // empty this object
308 r.requiresTDZCheck = true;
309 return r;
310 }
311
312 RValue asRValue() const;
313 Reference asLValue() const;
314
317
320
322 void storeOnStack(int tempIndex) const;
325
327
328 bool storeWipesAccumulator() const;
329 void loadInAccumulator() const;
330
331 int nameAsIndex() const {
332 Q_ASSERT(type == Name);
333 return codegen->registerString(name);
334 }
335
337 if (Q_UNLIKELY(!isStackSlot()))
339 return theStackSlot;
340 }
341
349
350 union {
353 struct { // Scoped arguments/Local
354 int index;
355 int scope;
356 };
357 struct {
360 };
361 struct {
363 union {
366 };
367 };
368 Moth::StackSlot property; // super property
369 };
371 Codegen *codegen = nullptr;
372
390
391 private:
392 void storeAccumulator() const;
394 void tdzCheck(bool requiresCheck, bool throwsReferenceError) const;
397 };
398
409
412
414 int getter = -1; // index in _module->functions or -1 if not set
415 int setter = -1;
417
418 bool hasGetter() const { return getter >= 0; }
419 bool hasSetter() const { return setter >= 0; }
420 };
421protected:
422
423 enum Format { ex, cx, nx };
424 class Result {
426
427 const BytecodeGenerator::Label *_iftrue = nullptr;
428 const BytecodeGenerator::Label *_iffalse = nullptr;
429 Format _format = ex;
431 bool _trueBlockFollowsCondition = false;
432
433 public:
434 explicit Result(const QString &name)
435 : _result(name)
436 , _requested(ex)
437 {}
438
439 explicit Result(const Reference &lrvalue)
441 , _requested(ex)
442 {}
443
446
458
461 return _iftrue;
462 }
463
466 return _iffalse;
467 }
468
469 Format format() const {
470 return _format;
471 }
472
474 {
475 if (_requested == f) {
476 _format = f;
477 return true;
478 }
479 return false;
480 }
481
485
486 const Reference &result() const {
487 return _result;
488 }
489
491 _result = result;
492 }
493
496 }
497
500 }
501 };
502
504 int leaveContext();
505public:
507 int leaveBlock() { return leaveContext(); }
508protected:
509 void leaveLoop();
510
521
523
524 void addCJump();
525
526public:
550
551 // Returns index in _module->functions
555
556protected:
562
564 {
565 if (!ast || hasError())
566 return Reference();
567
568 pushExpr(name);
569 ast->accept(this);
570 return popResult();
571 }
572
573 inline void accept(QQmlJS::AST::Node *node)
574 {
575 if (!hasError() && node)
576 node->accept(this);
577 }
578
579 void program(QQmlJS::AST::Program *ast);
583
589
591
592 void emitReturn(const Reference &expr);
593
594 // nodes
599 bool visit(QQmlJS::AST::Catch *ast) override;
617
622
624
626
627 // expressions
669
670 // statements
671 bool visit(QQmlJS::AST::Block *ast) override;
689
690 // ui object members
697
699 const QQmlJS::SourceLocation &loc);
700 virtual void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail);
701 virtual void throwReferenceError(const QQmlJS::SourceLocation &loc, const QString &detail);
703 {
705 QStringLiteral("Maximum statement or expression depth exceeded"));
706 }
707
708public:
714
715 ErrorType errorType() const { return _errorType; }
716 bool hasError() const { return _errorType != NoError; }
718 QUrl url() const;
719
723 struct Arguments { int argc; int argv; bool hasSpread; };
726
730
732
735
736
738 const QString &name, bool lhs,
740
742 bool generateUnitData = true);
744 bool debugMode, const QString &url, const QString &sourceCode,
746
748 bool debugMode, const QString &url, const QV4::Value &value);
749
750 Context *currentContext() const { return _context; }
752
753 void loadClosure(int index);
754
755 Module *module() const { return _module; }
756
762
763protected:
764 friend class ScanFunctions;
765 friend struct ControlFlow;
766 friend struct ControlFlowCatch;
767 friend struct ControlFlowFinally;
768
771 inline Reference exprResult() const { return m_expressions.back().result(); }
773
774 inline bool exprAccept(Format f) { return m_expressions.back().accept(f); }
775
776 inline const Result &currentExpr() const { return m_expressions.back(); }
777
779 inline void pushExpr(const Result &expr) { m_expressions.push_back(expr); }
781
783 {
786 return result;
787 }
788
792 return result;
793 }
794
806 bool useFastLookups = true;
808 bool insideSwitch = false;
813
822
824
829
831 {
832 public:
838
841
842 void unblock() const
844
845 void reblock() const
847
848 private:
849 Codegen *_cg;
850 bool _saved;
851 bool _onoff;
852 };
853
854private:
859 const QString &detail);
862 bool isDeleteExpression = false);
864 void generateThrowException(const QString &type, const QString &text = QString());
865};
866
867}
868
869}
870
871QT_END_NAMESPACE
872
873#endif // QV4CODEGEN_P_H
Codegen::VolatileMemoryLocations scan(AST::Node *s)
bool visit(ArrayMemberExpression *) override
CodegenWarningInterface * defaultCodegenWarningInterface()
Definition qjsvalue.h:24
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
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[]