Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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
30
31namespace QV4 {
32
33namespace Moth {
34struct Instruction;
35}
36
37namespace CompiledData {
38struct CompilationUnit;
39}
40
41namespace Compiler {
42
43struct ControlFlow;
44struct ControlFlowCatch;
45struct ControlFlowFinally;
46
48{
49public:
50 virtual void reportVarUsedBeforeDeclaration(const QString &name, const QString &fileName,
51 QQmlJS::SourceLocation declarationLocation,
52 QQmlJS::SourceLocation accessLocation);
53 virtual ~CodegenWarningInterface() = default;
54};
55
57{
58 static CodegenWarningInterface iface;
59 return &iface;
60}
61
63{
64protected:
67public:
68 Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict,
70 bool storeSourceLocations = false);
71
72 void generateFromProgram(const QString &fileName,
73 const QString &finalUrl,
74 const QString &sourceCode,
76 Module *module,
77 ContextType contextType = ContextType::Global);
78
79 void generateFromModule(const QString &fileName,
80 const QString &finalUrl,
81 const QString &sourceCode,
83 Module *module);
84
85public:
89 bool allVolatile = false;
90 QList<QStringView> specificLocations;
91 public:
93 if (allVolatile)
94 return true;
95 return specificLocations.contains(name);
96 }
97
98 void add(QStringView name) { if (!allVolatile) specificLocations.append(name); }
99 void setAllVolatile() { allVolatile = true; }
100 };
101 class RValue {
102 Codegen *codegen;
103 enum Type {
104 Invalid,
105 Accumulator,
106 StackSlot,
107 Const
108 } type;
109 union {
112 };
113
114 public:
115 static RValue fromStackSlot(Codegen *codegen, Moth::StackSlot stackSlot) {
116 RValue r;
117 r.codegen = codegen;
118 r.type = StackSlot;
119 r.theStackSlot = stackSlot;
120 return r;
121 }
122 static RValue fromAccumulator(Codegen *codegen) {
123 RValue r;
124 r.codegen = codegen;
125 r.type = Accumulator;
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
144 Q_ASSERT(isStackSlot());
145 return theStackSlot;
146 }
147
149 Q_ASSERT(isConst());
150 return constant;
151 }
152
153 Q_REQUIRED_RESULT RValue storeOnStack() const;
154 void loadInAccumulator() const;
155 };
156 struct Reference {
157 enum Type {
168 LastLValue = Import,
169 Const
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),
187 subscriptRequiresTDZCheck(false),
188 stackSlotIsLocalOrArgument(false),
189 isVolatile(false),
190 global(false),
191 qmlGlobal(false),
192 throwsReferenceError(false),
193 subscriptLoadedForCall(false)
194 {}
195
196 Reference(const Reference &) = default;
197 Reference(Reference &&) = default;
198 Reference &operator =(const Reference &) = default;
199 Reference &operator =(Reference &&) = default;
200
201 bool operator==(const Reference &other) const;
202 bool operator!=(const Reference &other) const
203 { return !(*this == other); }
204
205 bool isValid() const { return type != Invalid; }
207 switch (type) {
208 case Name:
209 case Member:
210 case Subscript:
211 case SuperProperty:
212 return true;
213 default:
214 return requiresTDZCheck;
215 }
216 }
217 bool isConstant() const { return type == Const; }
218 bool isAccumulator() const { return type == Accumulator; }
219 bool isSuper() const { return type == Super; }
220 bool isSuperProperty() const { return type == SuperProperty; }
221 bool isStackSlot() const { return type == StackSlot; }
222 bool isRegister() const {
223 return isStackSlot();
224 }
225
227 return Reference(cg, Accumulator);
228 }
230 return Reference(cg, Super);
231 }
232 static Reference fromStackSlot(Codegen *cg, int tempIndex = -1, bool isLocal = false) {
233 Reference r(cg, StackSlot);
234 if (tempIndex == -1)
235 tempIndex = cg->bytecodeGenerator->newRegister();
236 r.theStackSlot = Moth::StackSlot::createRegister(tempIndex);
237 r.stackSlotIsLocalOrArgument = isLocal;
238 return r;
239 }
240 static Reference fromScopedLocal(Codegen *cg, int index, int scope) {
241 Reference r(cg, ScopedLocal);
242 r.index = index;
243 r.scope = scope;
244 return r;
245 }
247 Reference r(cg, Import);
248 r.index = index;
249 return r;
250 }
251 static Reference fromName(Codegen *cg, const QString &name) {
252 Reference r(cg, Name);
253 r.name = name;
254 return r;
255 }
256 static Reference
257 fromMember(const Reference &baseRef, const QString &name,
261 {
262 Q_ASSERT(baseRef.isValid());
263 Reference r(baseRef.codegen, Member);
264 r.propertyBase = baseRef.asRValue();
265 r.propertyNameIndex = r.codegen->registerString(name);
266 r.requiresTDZCheck = baseRef.requiresTDZCheck;
267 r.sourceLocation = sourceLocation;
268 r.optionalChainJumpLabel.reset(new Moth::BytecodeGenerator::Label(jumpLabel));
269 r.optionalChainTargetLabel.reset(new Moth::BytecodeGenerator::Label(targetLabel));
270 return r;
271 }
273 Q_ASSERT(property.isStackSlot());
274 Reference r(property.codegen, SuperProperty);
275 r.property = property.stackSlot();
276 r.subscriptRequiresTDZCheck = property.requiresTDZCheck;
277 return r;
278 }
280 Q_ASSERT(baseRef.isStackSlot());
281 Reference r(baseRef.codegen, Subscript);
282 r.elementBase = baseRef.stackSlot();
283 r.elementSubscript = subscript.asRValue();
284 r.requiresTDZCheck = baseRef.requiresTDZCheck;
285 r.subscriptRequiresTDZCheck = subscript.requiresTDZCheck;
286 r.optionalChainTargetLabel.reset(new Moth::BytecodeGenerator::Label(targetLabel));
287 return r;
288 }
290 Reference r(cg, Const);
291 r.constant = constant;
292 r.isReadonly = true;
293 return r;
294 }
296 Reference r = fromStackSlot(cg, CallData::This);
297 r.isReadonly = true;
298 // ### Optimize this. Functions that are not derived constructors or arrow functions can't have an
299 // empty this object
300 r.requiresTDZCheck = true;
301 return r;
302 }
303
304 RValue asRValue() const;
305 Reference asLValue() const;
306
308 { return Reference::fromConst(cg, constant).storeOnStack(); }
309
310 static void storeConstOnStack(Codegen *cg, QV4::ReturnedValue constant, int stackSlot)
311 { Reference::fromConst(cg, constant).storeOnStack(stackSlot); }
312
313 Q_REQUIRED_RESULT Reference storeOnStack() const;
314 void storeOnStack(int tempIndex) const;
315 Q_REQUIRED_RESULT Reference storeRetainAccumulator() const;
316 Reference storeConsumeAccumulator() const;
317
318 Q_REQUIRED_RESULT Reference baseObject() const;
319
320 bool storeWipesAccumulator() const;
321 void loadInAccumulator() const;
322
323 int nameAsIndex() const {
324 Q_ASSERT(type == Name);
325 return codegen->registerString(name);
326 }
327
329 if (Q_UNLIKELY(!isStackSlot()))
330 Q_UNREACHABLE();
331 return theStackSlot;
332 }
333
334 void tdzCheck() const
335 {
336 if (isAccumulator())
337 tdzCheck(requiresTDZCheck, throwsReferenceError);
338 else if (isStackSlot())
339 tdzCheckStackSlot(stackSlot(), requiresTDZCheck, throwsReferenceError);
340 }
341
342 union {
345 struct { // Scoped arguments/Local
346 int index;
347 int scope;
348 };
349 struct {
352 };
353 struct {
355 union {
358 };
359 };
360 Moth::StackSlot property; // super property
361 };
363 Codegen *codegen = nullptr;
364
379
380 private:
381 void storeAccumulator() const;
382 Reference doStoreOnStack(int tempIndex) const;
383 void tdzCheck(bool requiresCheck, bool throwsReferenceError) const;
384 void tdzCheckStackSlot(
385 Moth::StackSlot slot, bool requiresCheck, bool throwsReferenceError) const;
386 };
387
390 : generator(cg->bytecodeGenerator),
391 regCountForScope(generator->currentReg) {}
393 generator->currentReg = regCountForScope;
394 }
397 };
398
401
403 int getter = -1; // index in _module->functions or -1 if not set
404 int setter = -1;
405 uint keyAsIndex = UINT_MAX;
406
407 bool hasGetter() const { return getter >= 0; }
408 bool hasSetter() const { return setter >= 0; }
409 };
410protected:
411
412 enum Format { ex, cx, nx };
413 class Result {
414 Reference _result;
415
416 const BytecodeGenerator::Label *_iftrue = nullptr;
417 const BytecodeGenerator::Label *_iffalse = nullptr;
418 Format _format = ex;
419 Format _requested;
420 bool _trueBlockFollowsCondition = false;
421
422 public:
423 explicit Result(const QString &name)
424 : _result(name)
425 , _requested(ex)
426 {}
427
428 explicit Result(const Reference &lrvalue)
429 : _result(lrvalue)
430 , _requested(ex)
431 {}
432
433 explicit Result(Format requested = ex)
434 : _requested(requested) {}
435
436 explicit Result(const BytecodeGenerator::Label *iftrue,
437 const BytecodeGenerator::Label *iffalse,
438 bool trueBlockFollowsCondition)
439 : _iftrue(iftrue)
440 , _iffalse(iffalse)
441 , _requested(cx)
442 , _trueBlockFollowsCondition(trueBlockFollowsCondition)
443 {
444 Q_ASSERT(iftrue);
445 Q_ASSERT(iffalse);
446 }
447
449 Q_ASSERT(_requested == cx);
450 return _iftrue;
451 }
452
454 Q_ASSERT(_requested == cx);
455 return _iffalse;
456 }
457
458 Format format() const {
459 return _format;
460 }
461
463 {
464 if (_requested == f) {
465 _format = f;
466 return true;
467 }
468 return false;
469 }
470
472 return _trueBlockFollowsCondition;
473 }
474
475 const Reference &result() const {
476 return _result;
477 }
478
480 _result = result;
481 }
482
484 _result = std::move(result);
485 }
486
488 _result.name.clear();
489 }
490 };
491
492 void enterContext(QQmlJS::AST::Node *node);
493 int leaveContext();
494public:
495 Context *enterBlock(QQmlJS::AST::Node *node);
496 int leaveBlock() { return leaveContext(); }
497protected:
498 void leaveLoop();
499
508 Compl
509 };
510
511 Reference unop(UnaryOperation op, const Reference &expr);
512
513 void addCJump();
514
515public:
517 return jsUnitGenerator->registerString(name);
518 }
520 {
521 return jsUnitGenerator->registerConstant(v);
522 }
524 {
525 return jsUnitGenerator->registerGetterLookup(nameIndex, mode);
526 }
527 int registerSetterLookup(int nameIndex)
528 {
529 return jsUnitGenerator->registerSetterLookup(nameIndex);
530 }
532 {
533 return jsUnitGenerator->registerGlobalGetterLookup(nameIndex, mode);
534 }
536 {
537 return jsUnitGenerator->registerQmlContextPropertyGetterLookup(nameIndex, mode);
538 }
539
540 // Returns index in _module->functions
541 virtual int defineFunction(const QString &name, QQmlJS::AST::Node *ast,
544
545protected:
546 void statement(QQmlJS::AST::Statement *ast);
547 void statement(QQmlJS::AST::ExpressionNode *ast);
548 void condition(QQmlJS::AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue,
549 const BytecodeGenerator::Label *iffalse,
550 bool trueBlockFollowsCondition);
551
553 {
554 if (!ast || hasError())
555 return Reference();
556
557 pushExpr(name);
558 ast->accept(this);
559 return popResult();
560 }
561
562 inline void accept(QQmlJS::AST::Node *node)
563 {
564 if (!hasError() && node)
565 node->accept(this);
566 }
567
568 void program(QQmlJS::AST::Program *ast);
569 void statementList(QQmlJS::AST::StatementList *ast);
570 void variableDeclaration(QQmlJS::AST::PatternElement *ast);
571 void variableDeclarationList(QQmlJS::AST::VariableDeclarationList *ast);
572
573 Reference targetForPatternElement(QQmlJS::AST::PatternElement *p);
574 void initializeAndDestructureBindingElement(QQmlJS::AST::PatternElement *e, const Reference &baseRef = Reference(), bool isDefinition = false);
575 void destructurePropertyList(const Reference &object, QQmlJS::AST::PatternPropertyList *bindingList, bool isDefinition = false);
576 void destructureElementList(const Reference &array, QQmlJS::AST::PatternElementList *bindingList, bool isDefinition = false);
577 void destructurePattern(QQmlJS::AST::Pattern *p, const Reference &rhs);
578
579 Reference referenceForPropertyName(const Codegen::Reference &object, QQmlJS::AST::PropertyName *name);
580
581 void emitReturn(const Reference &expr);
582
583 // nodes
584 bool visit(QQmlJS::AST::ArgumentList *ast) override;
585 bool visit(QQmlJS::AST::CaseBlock *ast) override;
586 bool visit(QQmlJS::AST::CaseClause *ast) override;
587 bool visit(QQmlJS::AST::CaseClauses *ast) override;
588 bool visit(QQmlJS::AST::Catch *ast) override;
589 bool visit(QQmlJS::AST::DefaultClause *ast) override;
590 bool visit(QQmlJS::AST::Elision *ast) override;
591 bool visit(QQmlJS::AST::Finally *ast) override;
592 bool visit(QQmlJS::AST::FormalParameterList *ast) override;
593 bool visit(QQmlJS::AST::Program *ast) override;
594 bool visit(QQmlJS::AST::StatementList *ast) override;
595 bool visit(QQmlJS::AST::UiArrayMemberList *ast) override;
596 bool visit(QQmlJS::AST::UiImport *ast) override;
597 bool visit(QQmlJS::AST::UiHeaderItemList *ast) override;
598 bool visit(QQmlJS::AST::UiPragmaValueList *ast) override;
599 bool visit(QQmlJS::AST::UiPragma *ast) override;
600 bool visit(QQmlJS::AST::UiObjectInitializer *ast) override;
601 bool visit(QQmlJS::AST::UiObjectMemberList *ast) override;
602 bool visit(QQmlJS::AST::UiParameterList *ast) override;
603 bool visit(QQmlJS::AST::UiProgram *ast) override;
604 bool visit(QQmlJS::AST::UiQualifiedId *ast) override;
605 bool visit(QQmlJS::AST::VariableDeclarationList *ast) override;
606
607 bool visit(QQmlJS::AST::PatternElement *ast) override;
608 bool visit(QQmlJS::AST::PatternElementList *ast) override;
609 bool visit(QQmlJS::AST::PatternProperty *ast) override;
610 bool visit(QQmlJS::AST::PatternPropertyList *ast) override;
611
612 bool visit(QQmlJS::AST::ExportDeclaration *ast) override;
613
614 bool visit(QQmlJS::AST::TypeAnnotation *ast) override;
615
616 // expressions
617 bool visit(QQmlJS::AST::Expression *ast) override;
618 bool visit(QQmlJS::AST::ArrayPattern *ast) override;
619 bool visit(QQmlJS::AST::ArrayMemberExpression *ast) override;
620 bool visit(QQmlJS::AST::BinaryExpression *ast) override;
621 bool visit(QQmlJS::AST::CallExpression *ast) override;
622 void endVisit(QQmlJS::AST::CallExpression *ast) override;
623 bool visit(QQmlJS::AST::ConditionalExpression *ast) override;
624 bool visit(QQmlJS::AST::DeleteExpression *ast) override;
625 void endVisit(QQmlJS::AST::DeleteExpression *ast) override;
626 bool visit(QQmlJS::AST::FalseLiteral *ast) override;
627 bool visit(QQmlJS::AST::SuperLiteral *ast) override;
628 bool visit(QQmlJS::AST::FieldMemberExpression *ast) override;
629 void endVisit(QQmlJS::AST::FieldMemberExpression *ast) override;
630 bool visit(QQmlJS::AST::TaggedTemplate *ast) override;
631 bool visit(QQmlJS::AST::FunctionExpression *ast) override;
632 bool visit(QQmlJS::AST::IdentifierExpression *ast) override;
633 bool visit(QQmlJS::AST::NestedExpression *ast) override;
634 bool visit(QQmlJS::AST::NewExpression *ast) override;
635 bool visit(QQmlJS::AST::NewMemberExpression *ast) override;
636 bool visit(QQmlJS::AST::NotExpression *ast) override;
637 bool visit(QQmlJS::AST::NullExpression *ast) override;
638 bool visit(QQmlJS::AST::NumericLiteral *ast) override;
639 bool visit(QQmlJS::AST::ObjectPattern *ast) override;
640 bool visit(QQmlJS::AST::PostDecrementExpression *ast) override;
641 bool visit(QQmlJS::AST::PostIncrementExpression *ast) override;
642 bool visit(QQmlJS::AST::PreDecrementExpression *ast) override;
643 bool visit(QQmlJS::AST::PreIncrementExpression *ast) override;
644 bool visit(QQmlJS::AST::RegExpLiteral *ast) override;
645 bool visit(QQmlJS::AST::StringLiteral *ast) override;
646 bool visit(QQmlJS::AST::TemplateLiteral *ast) override;
647 bool visit(QQmlJS::AST::ThisExpression *ast) override;
648 bool visit(QQmlJS::AST::TildeExpression *ast) override;
649 bool visit(QQmlJS::AST::TrueLiteral *ast) override;
650 bool visit(QQmlJS::AST::TypeOfExpression *ast) override;
651 bool visit(QQmlJS::AST::UnaryMinusExpression *ast) override;
652 bool visit(QQmlJS::AST::UnaryPlusExpression *ast) override;
653 bool visit(QQmlJS::AST::VoidExpression *ast) override;
654 bool visit(QQmlJS::AST::FunctionDeclaration *ast) override;
655 bool visit(QQmlJS::AST::YieldExpression *ast) override;
656 bool visit(QQmlJS::AST::ClassExpression *ast) override;
657 bool visit(QQmlJS::AST::ClassDeclaration *ast) override;
658
659 // statements
660 bool visit(QQmlJS::AST::Block *ast) override;
661 bool visit(QQmlJS::AST::BreakStatement *ast) override;
662 bool visit(QQmlJS::AST::ContinueStatement *ast) override;
663 bool visit(QQmlJS::AST::DebuggerStatement *ast) override;
664 bool visit(QQmlJS::AST::DoWhileStatement *ast) override;
665 bool visit(QQmlJS::AST::EmptyStatement *ast) override;
666 bool visit(QQmlJS::AST::ExpressionStatement *ast) override;
667 bool visit(QQmlJS::AST::ForEachStatement *ast) override;
668 bool visit(QQmlJS::AST::ForStatement *ast) override;
669 bool visit(QQmlJS::AST::IfStatement *ast) override;
670 bool visit(QQmlJS::AST::LabelledStatement *ast) override;
671 bool visit(QQmlJS::AST::ReturnStatement *ast) override;
672 bool visit(QQmlJS::AST::SwitchStatement *ast) override;
673 bool visit(QQmlJS::AST::ThrowStatement *ast) override;
674 bool visit(QQmlJS::AST::TryStatement *ast) override;
675 bool visit(QQmlJS::AST::VariableStatement *ast) override;
676 bool visit(QQmlJS::AST::WhileStatement *ast) override;
677 bool visit(QQmlJS::AST::WithStatement *ast) override;
678
679 // ui object members
680 bool visit(QQmlJS::AST::UiArrayBinding *ast) override;
681 bool visit(QQmlJS::AST::UiObjectBinding *ast) override;
682 bool visit(QQmlJS::AST::UiObjectDefinition *ast) override;
683 bool visit(QQmlJS::AST::UiPublicMember *ast) override;
684 bool visit(QQmlJS::AST::UiScriptBinding *ast) override;
685 bool visit(QQmlJS::AST::UiSourceElement *ast) override;
686
687 bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r,
688 const QQmlJS::SourceLocation &loc);
689 virtual void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail);
690 virtual void throwReferenceError(const QQmlJS::SourceLocation &loc, const QString &detail);
692 {
693 throwSyntaxError(QQmlJS::SourceLocation(),
694 QStringLiteral("Maximum statement or expression depth exceeded"));
695 }
696
697public:
701 ReferenceError
702 };
703
704 ErrorType errorType() const { return _errorType; }
705 bool hasError() const { return _errorType != NoError; }
707 QUrl url() const;
708
709 Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right);
710 Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right);
711 struct Arguments { int argc; int argv; bool hasSpread; };
713 void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject, bool optional = false);
714
716 bool handleTaggedTemplate(Reference base, QQmlJS::AST::TaggedTemplate *ast);
717 void createTemplateObject(QQmlJS::AST::TemplateLiteral *t);
718
719 void setUseFastLookups(bool b) { useFastLookups = b; }
720
721 void handleTryCatch(QQmlJS::AST::TryStatement *ast);
722 void handleTryFinally(QQmlJS::AST::TryStatement *ast);
723
724
725 Reference referenceForName(
726 const QString &name, bool lhs,
727 const QQmlJS::SourceLocation &accessLocation = QQmlJS::SourceLocation());
728
729 QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData = true);
730 static QV4::CompiledData::CompilationUnit compileModule(
731 bool debugMode, const QString &url, const QString &sourceCode,
732 const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics);
733
734 Context *currentContext() const { return _context; }
735 BytecodeGenerator *generator() const { return bytecodeGenerator; }
736
737 void loadClosure(int index);
738
739 Module *module() const { return _module; }
740
742 if (!_returnLabel)
743 _returnLabel = new BytecodeGenerator::Label(bytecodeGenerator->newLabel());
744 return *_returnLabel;
745 }
746
747 void setGlobalNames(const QSet<QString>& globalNames) {
748 m_globalNames = globalNames;
749 }
750
751 static const char *s_globalNames[];
752
753protected:
754 friend class ScanFunctions;
755 friend struct ControlFlow;
756 friend struct ControlFlowCatch;
757 friend struct ControlFlowFinally;
758
759 inline void setExprResult(const Reference &result) { m_expressions.back().setResult(result); }
760 inline void setExprResult(Reference &&result) { m_expressions.back().setResult(std::move(result)); }
761 inline Reference exprResult() const { return m_expressions.back().result(); }
762 inline void clearExprResultName() { m_expressions.back().clearResultName(); }
763
764 inline bool exprAccept(Format f) { return m_expressions.back().accept(f); }
765
766 inline const Result &currentExpr() const { return m_expressions.back(); }
767
768 inline void pushExpr(Result &&expr) { m_expressions.push_back(std::move(expr)); }
769 inline void pushExpr(const Result &expr) { m_expressions.push_back(expr); }
770 inline void pushExpr(const QString &name = QString()) { m_expressions.emplace_back(name); }
771
773 {
774 const Result result = m_expressions.back();
775 m_expressions.pop_back();
776 return result;
777 }
778
780 const Reference result = m_expressions.back().result();
781 m_expressions.pop_back();
782 return result;
783 }
784
785 std::vector<Result> m_expressions;
790 Context *_functionContext = nullptr;
793 BytecodeGenerator *bytecodeGenerator = nullptr;
794 Moth::BytecodeGenerator::Label *_returnLabel = nullptr;
796 bool useFastLookups = true;
797 bool requiresReturnValue = false;
798 bool insideSwitch = false;
799 bool inFormalParameterList = false;
800 bool functionEndsWithReturn = false;
801 bool _tailCallsAreAllowed = true;
802 bool storeSourceLocations = false;
806
807 ControlFlow *controlFlow = nullptr;
808
810 ErrorType _errorType = NoError;
813
815 {
816 public:
817 TailCallBlocker(Codegen *cg, bool onoff = false)
818 : _cg(cg)
819 , _saved(_cg->_tailCallsAreAllowed)
820 , _onoff(onoff)
821 { _cg->_tailCallsAreAllowed = onoff; }
822
824 { _cg->_tailCallsAreAllowed = _saved; }
825
826 void unblock() const
827 { _cg->_tailCallsAreAllowed = _saved; }
828
829 void reblock() const
830 { _cg->_tailCallsAreAllowed = _onoff; }
831
832 private:
833 Codegen *_cg;
834 bool _saved;
835 bool _onoff;
836 };
837
838private:
839 VolatileMemoryLocations scanVolatileMemoryLocations(QQmlJS::AST::Node *ast);
840 void handleConstruct(const Reference &base, QQmlJS::AST::ArgumentList *args);
841 void throwError(ErrorType errorType, const QQmlJS::SourceLocation &loc,
842 const QString &detail);
843 std::optional<Moth::BytecodeGenerator::Label> traverseOptionalChain(QQmlJS::AST::Node *node);
844 Reference loadSubscriptForCall(const Reference &base);
845 void generateThrowException(const QString &type, const QString &text = QString());
846};
847
848}
849
850}
851
853
854#endif // QV4CODEGEN_P_H
\inmodule QtCore\reentrant
Definition qdatetime.h:257
\inmodule QtCore
Definition qhash.h:818
Definition qlist.h:74
void append(parameter_type t)
Definition qlist.h:441
void accept(BaseVisitor *visitor)
Definition qset.h:18
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
\inmodule QtCore
Definition qurl.h:94
static RValue fromStackSlot(Codegen *codegen, Moth::StackSlot stackSlot)
static RValue fromAccumulator(Codegen *codegen)
QV4::ReturnedValue constantValue() const
static RValue fromConst(Codegen *codegen, QV4::ReturnedValue value)
Moth::StackSlot stackSlot() const
void setResult(const Reference &result)
Result(Format requested=ex)
const BytecodeGenerator::Label * iffalse() const
const Reference & result() const
Result(const BytecodeGenerator::Label *iftrue, const BytecodeGenerator::Label *iffalse, bool trueBlockFollowsCondition)
Result(const QString &name)
Result(const Reference &lrvalue)
const BytecodeGenerator::Label * iftrue() const
void setResult(Reference &&result)
TailCallBlocker(Codegen *cg, bool onoff=false)
void setUseFastLookups(bool b)
QQmlJS::AST::LabelledStatement * _labelledStatement
QSet< QString > m_globalNames
VolatileMemoryLocations _volatileMemoryLocations
CodegenWarningInterface * _interface
BytecodeGenerator * bytecodeGenerator
Context * currentContext() const
void accept(QQmlJS::AST::Node *node)
int registerString(const QString &name)
int registerConstant(QV4::ReturnedValue v)
int registerQmlContextPropertyGetterLookup(int nameIndex, JSUnitGenerator::LookupMode mode)
bool exprAccept(Format f)
QV4::Compiler::JSUnitGenerator * jsUnitGenerator
BytecodeGenerator::Label returnLabel()
int registerGetterLookup(int nameIndex, JSUnitGenerator::LookupMode mode)
void setExprResult(Reference &&result)
QSet< QQmlJS::AST::Node * > m_seenOptionalChainNodes
void pushExpr(const QString &name=QString())
int registerSetterLookup(int nameIndex)
void setExprResult(const Reference &result)
int registerGlobalGetterLookup(int nameIndex, JSUnitGenerator::LookupMode mode)
ErrorType errorType() const
QHash< QQmlJS::AST::Node *, Moth::BytecodeGenerator::Label > m_optionalChainLabels
std::vector< Result > m_expressions
void setGlobalNames(const QSet< QString > &globalNames)
QQmlJS::DiagnosticMessage _error
void pushExpr(Result &&expr)
const Result & currentExpr() const
Reference expression(QQmlJS::AST::ExpressionNode *ast, const QString &name=QString())
BytecodeGenerator * generator() const
Module * module() const
void pushExpr(const Result &expr)
void throwRecursionDepthError() override
Reference exprResult() const
QString text
double e
std::list< QString >::iterator Name
Definition lalr.h:29
Combined button and popup list for selecting options.
CodegenWarningInterface * defaultCodegenWarningInterface()
\qmltype Particle \inqmlmodule QtQuick.Particles
quint64 ReturnedValue
#define Q_UNLIKELY(x)
#define Q_REQUIRED_RESULT
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
@ Invalid
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLenum mode
GLuint index
[2]
GLenum condition
GLboolean r
[2]
GLdouble GLdouble right
GLfloat GLfloat f
GLint left
GLenum type
GLuint program
GLuint name
GLbyte nx
GLenum array
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition qrandom.cpp:1219
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
@ NoError
Definition main.cpp:34
#define Q_QML_COMPILER_PRIVATE_EXPORT
unsigned int quint32
Definition qtypes.h:45
unsigned int uint
Definition qtypes.h:29
static const QV4::Value & constant(Function *function, int index)
const char property[13]
Definition qwizard.cpp:101
QRandomGenerator generator(sseq)
QUrl url("example.com")
[constructor-url-reference]
QSharedPointer< T > other(t)
[5]
QJSValueList args
QJSValue global
bool contains(const AT &t) const noexcept
Definition qlist.h:44
static Reference fromScopedLocal(Codegen *cg, int index, int scope)
Reference(Reference &&)=default
static Reference fromImport(Codegen *cg, int index)
static Reference fromMember(const Reference &baseRef, const QString &name, QQmlJS::SourceLocation sourceLocation=QQmlJS::SourceLocation(), Moth::BytecodeGenerator::Label jumpLabel=Moth::BytecodeGenerator::Label(), Moth::BytecodeGenerator::Label targetLabel=Moth::BytecodeGenerator::Label())
Moth::StackSlot stackSlot() const
static void storeConstOnStack(Codegen *cg, QV4::ReturnedValue constant, int stackSlot)
static Reference fromConst(Codegen *cg, QV4::ReturnedValue constant)
Reference(const Reference &)=default
static Reference fromName(Codegen *cg, const QString &name)
static Reference fromAccumulator(Codegen *cg)
Reference(Codegen *cg, Type t=Invalid)
static Reference fromSuperProperty(const Reference &property)
static Reference fromStackSlot(Codegen *cg, int tempIndex=-1, bool isLocal=false)
static Reference fromSubscript(const Reference &baseRef, const Reference &subscript, Moth::BytecodeGenerator::Label targetLabel=Moth::BytecodeGenerator::Label())
static Q_REQUIRED_RESULT Reference storeConstOnStack(Codegen *cg, QV4::ReturnedValue constant)
Reference(const QString &name=QString())
Q_REQUIRED_RESULT Reference storeOnStack() const
bool operator!=(const Reference &other) const
static Reference fromThis(Codegen *cg)
QSharedPointer< Moth::BytecodeGenerator::Label > optionalChainJumpLabel
QSharedPointer< Moth::BytecodeGenerator::Label > optionalChainTargetLabel
static Reference fromSuper(Codegen *cg)
int registerGlobalGetterLookup(int nameIndex, LookupMode mode)
int registerSetterLookup(const QString &name)
int registerQmlContextPropertyGetterLookup(int nameIndex, LookupMode mode)
int registerConstant(ReturnedValue v)
int registerGetterLookup(const QString &name, LookupMode mode)
int registerString(const QString &str)
Definition moc.h:24