Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 <stack>
29
31
32namespace QV4 {
33
34namespace Moth {
35struct Instruction;
36}
37
38namespace CompiledData {
39struct CompilationUnit;
40}
41
42namespace Compiler {
43
44struct ControlFlow;
45struct ControlFlowCatch;
46struct ControlFlowFinally;
47
49{
50public:
51 virtual void reportVarUsedBeforeDeclaration(const QString &name, const QString &fileName,
52 QQmlJS::SourceLocation declarationLocation,
53 QQmlJS::SourceLocation accessLocation);
54 virtual ~CodegenWarningInterface() = default;
55};
56
58{
59 static CodegenWarningInterface iface;
60 return &iface;
61}
62
64{
65protected:
68public:
69 Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict,
71 bool storeSourceLocations = false);
72
73 void generateFromProgram(const QString &fileName,
74 const QString &finalUrl,
75 const QString &sourceCode,
77 Module *module,
78 ContextType contextType = ContextType::Global);
79
80 void generateFromModule(const QString &fileName,
81 const QString &finalUrl,
82 const QString &sourceCode,
84 Module *module);
85
86public:
90 bool allVolatile = false;
91 QList<QStringView> specificLocations;
92 public:
94 if (allVolatile)
95 return true;
96 return specificLocations.contains(name);
97 }
98
99 void add(QStringView name) { if (!allVolatile) specificLocations.append(name); }
100 void setAllVolatile() { allVolatile = true; }
101 };
102 class RValue {
103 Codegen *codegen;
104 enum Type {
105 Invalid,
106 Accumulator,
107 StackSlot,
108 Const
109 } type;
110 union {
113 };
114
115 public:
116 static RValue fromStackSlot(Codegen *codegen, Moth::StackSlot stackSlot) {
117 RValue r;
118 r.codegen = codegen;
119 r.type = StackSlot;
120 r.theStackSlot = stackSlot;
121 return r;
122 }
123 static RValue fromAccumulator(Codegen *codegen) {
124 RValue r;
125 r.codegen = codegen;
126 r.type = Accumulator;
127 return r;
128 }
130 RValue r;
131 r.codegen = codegen;
132 r.type = Const;
133 r.constant = value;
134 return r;
135 }
136
137 bool operator==(const RValue &other) const;
138
139 bool isValid() const { return type != Invalid; }
140 bool isAccumulator() const { return type == Accumulator; }
141 bool isStackSlot() const { return type == StackSlot; }
142 bool isConst() const { return type == Const; }
143
145 Q_ASSERT(isStackSlot());
146 return theStackSlot;
147 }
148
150 Q_ASSERT(isConst());
151 return constant;
152 }
153
154 Q_REQUIRED_RESULT RValue storeOnStack() const;
155 void loadInAccumulator() const;
156 };
157 struct Reference {
172
173 bool isLValue() const { return !isReadonly && type > Accumulator; }
174
176 {
177 type = t;
178 codegen = cg;
179 }
180
182 constant(0),
183 name(name),
184 isArgOrEval(false),
185 isReadonly(false),
186 isReferenceToConst(false),
187 requiresTDZCheck(false),
188 subscriptRequiresTDZCheck(false),
189 stackSlotIsLocalOrArgument(false),
190 isVolatile(false),
191 global(false),
192 qmlGlobal(false),
193 throwsReferenceError(false),
194 subscriptLoadedForCall(false),
195 isOptional(false),
196 hasSavedCallBaseSlot(false)
197 {}
198
199 Reference(const Reference &) = default;
200 Reference(Reference &&) = default;
201 Reference &operator =(const Reference &) = default;
202 Reference &operator =(Reference &&) = default;
203
204 bool operator==(const Reference &other) const;
205 bool operator!=(const Reference &other) const
206 { return !(*this == other); }
207
208 bool isValid() const { return type != Invalid; }
210 switch (type) {
211 case Name:
212 case Member:
213 case Subscript:
214 case SuperProperty:
215 return true;
216 default:
217 return requiresTDZCheck;
218 }
219 }
220 bool isConstant() const { return type == Const; }
221 bool isAccumulator() const { return type == Accumulator; }
222 bool isSuper() const { return type == Super; }
223 bool isSuperProperty() const { return type == SuperProperty; }
224 bool isStackSlot() const { return type == StackSlot; }
225 bool isRegister() const {
226 return isStackSlot();
227 }
228
230 return Reference(cg, Accumulator);
231 }
233 return Reference(cg, Super);
234 }
235 static Reference fromStackSlot(Codegen *cg, int tempIndex = -1, bool isLocal = false) {
236 Reference r(cg, StackSlot);
237 if (tempIndex == -1)
238 tempIndex = cg->bytecodeGenerator->newRegister();
239 r.theStackSlot = Moth::StackSlot::createRegister(tempIndex);
240 r.stackSlotIsLocalOrArgument = isLocal;
241 return r;
242 }
243 static Reference fromScopedLocal(Codegen *cg, int index, int scope) {
244 Reference r(cg, ScopedLocal);
245 r.index = index;
246 r.scope = scope;
247 return r;
248 }
250 Reference r(cg, Import);
251 r.index = index;
252 return r;
253 }
254 static Reference fromName(Codegen *cg, const QString &name) {
255 Reference r(cg, Name);
256 r.name = name;
257 return r;
258 }
259 static Reference
260 fromMember(const Reference &baseRef, const QString &name,
262 bool isOptional = false,
263 std::vector<Moth::BytecodeGenerator::Jump> *optionalChainJumpsToPatch = nullptr)
264 {
265 Q_ASSERT(baseRef.isValid());
266 Reference r(baseRef.codegen, Member);
267 r.propertyBase = baseRef.asRValue();
268 r.propertyNameIndex = r.codegen->registerString(name);
269 r.requiresTDZCheck = baseRef.requiresTDZCheck;
270 r.sourceLocation = sourceLocation;
271 r.optionalChainJumpsToPatch = optionalChainJumpsToPatch;
272 r.isOptional = isOptional;
273 return r;
274 }
276 Q_ASSERT(property.isStackSlot());
277 Reference r(property.codegen, SuperProperty);
278 r.property = property.stackSlot();
279 r.subscriptRequiresTDZCheck = property.requiresTDZCheck;
280 return r;
281 }
282 static Reference fromSubscript(const Reference &baseRef, const Reference &subscript) {
283 Q_ASSERT(baseRef.isStackSlot());
284 Reference r(baseRef.codegen, Subscript);
285 r.elementBase = baseRef.stackSlot();
286 r.elementSubscript = subscript.asRValue();
287 r.requiresTDZCheck = baseRef.requiresTDZCheck;
288 r.subscriptRequiresTDZCheck = subscript.requiresTDZCheck;
289 return r;
290 }
292 Reference r(cg, Const);
293 r.constant = constant;
294 r.isReadonly = true;
295 return r;
296 }
298 Reference r = fromStackSlot(cg, CallData::This);
299 r.isReadonly = true;
300 // ### Optimize this. Functions that are not derived constructors or arrow functions can't have an
301 // empty this object
302 r.requiresTDZCheck = true;
303 return r;
304 }
305
306 RValue asRValue() const;
307 Reference asLValue() const;
308
310 { return Reference::fromConst(cg, constant).storeOnStack(); }
311
312 static void storeConstOnStack(Codegen *cg, QV4::ReturnedValue constant, int stackSlot)
313 { Reference::fromConst(cg, constant).storeOnStack(stackSlot); }
314
315 Q_REQUIRED_RESULT Reference storeOnStack() const;
316 void storeOnStack(int tempIndex) const;
317 Q_REQUIRED_RESULT Reference storeRetainAccumulator() const;
318 Reference storeConsumeAccumulator() const;
319
320 Q_REQUIRED_RESULT Reference baseObject() const;
321
322 bool storeWipesAccumulator() const;
323 void loadInAccumulator() const;
324
325 int nameAsIndex() const {
326 Q_ASSERT(type == Name);
327 return codegen->registerString(name);
328 }
329
331 if (Q_UNLIKELY(!isStackSlot()))
332 Q_UNREACHABLE();
333 return theStackSlot;
334 }
335
336 void tdzCheck() const
337 {
338 if (isAccumulator())
339 tdzCheck(requiresTDZCheck, throwsReferenceError);
340 else if (isStackSlot())
341 tdzCheckStackSlot(stackSlot(), requiresTDZCheck, throwsReferenceError);
342 }
343
344 union {
347 struct { // Scoped arguments/Local
348 int index;
349 int scope;
350 };
351 struct {
354 };
355 struct {
357 union {
360 };
361 };
362 Moth::StackSlot property; // super property
363 };
365 Codegen *codegen = nullptr;
366
381 std::vector<Moth::BytecodeGenerator::Jump> *optionalChainJumpsToPatch = nullptr;
382 int savedCallBaseSlot = -1;
383 int savedCallPropertyNameIndex = -1;
384
385 private:
386 void storeAccumulator() const;
387 Reference doStoreOnStack(int tempIndex) const;
388 void tdzCheck(bool requiresCheck, bool throwsReferenceError) const;
389 void tdzCheckStackSlot(
390 Moth::StackSlot slot, bool requiresCheck, bool throwsReferenceError) const;
391 };
392
395 : generator(cg->bytecodeGenerator),
396 regCountForScope(generator->currentReg) {}
398 generator->currentReg = regCountForScope;
399 }
402 };
403
406
408 int getter = -1; // index in _module->functions or -1 if not set
409 int setter = -1;
410 uint keyAsIndex = UINT_MAX;
411
412 bool hasGetter() const { return getter >= 0; }
413 bool hasSetter() const { return setter >= 0; }
414 };
415protected:
416
417 enum Format { ex, cx, nx };
418 class Result {
419 Reference _result;
420
421 const BytecodeGenerator::Label *_iftrue = nullptr;
422 const BytecodeGenerator::Label *_iffalse = nullptr;
423 Format _format = ex;
424 Format _requested;
425 bool _trueBlockFollowsCondition = false;
426
427 public:
428 explicit Result(const QString &name)
429 : _result(name)
430 , _requested(ex)
431 {}
432
433 explicit Result(const Reference &lrvalue)
434 : _result(lrvalue)
435 , _requested(ex)
436 {}
437
438 explicit Result(Format requested = ex)
439 : _requested(requested) {}
440
441 explicit Result(const BytecodeGenerator::Label *iftrue,
442 const BytecodeGenerator::Label *iffalse,
443 bool trueBlockFollowsCondition)
444 : _iftrue(iftrue)
445 , _iffalse(iffalse)
446 , _requested(cx)
447 , _trueBlockFollowsCondition(trueBlockFollowsCondition)
448 {
449 Q_ASSERT(iftrue);
450 Q_ASSERT(iffalse);
451 }
452
454 Q_ASSERT(_requested == cx);
455 return _iftrue;
456 }
457
459 Q_ASSERT(_requested == cx);
460 return _iffalse;
461 }
462
463 Format format() const {
464 return _format;
465 }
466
468 {
469 if (_requested == f) {
470 _format = f;
471 return true;
472 }
473 return false;
474 }
475
477 return _trueBlockFollowsCondition;
478 }
479
480 const Reference &result() const {
481 return _result;
482 }
483
485 _result = result;
486 }
487
489 _result = std::move(result);
490 }
491
493 _result.name.clear();
494 }
495 };
496
497 void enterContext(QQmlJS::AST::Node *node);
498 int leaveContext();
499public:
500 Context *enterBlock(QQmlJS::AST::Node *node);
501 int leaveBlock() { return leaveContext(); }
502protected:
503 void leaveLoop();
504
515
516 Reference unop(UnaryOperation op, const Reference &expr);
517
518 void addCJump();
519
520public:
522 return jsUnitGenerator->registerString(name);
523 }
525 {
526 return jsUnitGenerator->registerConstant(v);
527 }
529 {
530 return jsUnitGenerator->registerGetterLookup(nameIndex, mode);
531 }
532 int registerSetterLookup(int nameIndex)
533 {
534 return jsUnitGenerator->registerSetterLookup(nameIndex);
535 }
537 {
538 return jsUnitGenerator->registerGlobalGetterLookup(nameIndex, mode);
539 }
541 {
542 return jsUnitGenerator->registerQmlContextPropertyGetterLookup(nameIndex, mode);
543 }
544
545 // Returns index in _module->functions
546 virtual int defineFunction(const QString &name, QQmlJS::AST::Node *ast,
549
550protected:
551 void statement(QQmlJS::AST::Statement *ast);
552 void statement(QQmlJS::AST::ExpressionNode *ast);
553 void condition(QQmlJS::AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue,
554 const BytecodeGenerator::Label *iffalse,
555 bool trueBlockFollowsCondition);
556
558 {
559 if (!ast || hasError())
560 return Reference();
561
562 pushExpr(name);
563 ast->accept(this);
564 return popResult();
565 }
566
567 inline void accept(QQmlJS::AST::Node *node)
568 {
569 if (!hasError() && node)
570 node->accept(this);
571 }
572
573 void program(QQmlJS::AST::Program *ast);
574 void statementList(QQmlJS::AST::StatementList *ast);
575 void variableDeclaration(QQmlJS::AST::PatternElement *ast);
576 void variableDeclarationList(QQmlJS::AST::VariableDeclarationList *ast);
577
578 Reference targetForPatternElement(QQmlJS::AST::PatternElement *p);
579 void initializeAndDestructureBindingElement(QQmlJS::AST::PatternElement *e, const Reference &baseRef = Reference(), bool isDefinition = false);
580 void destructurePropertyList(const Reference &object, QQmlJS::AST::PatternPropertyList *bindingList, bool isDefinition = false);
581 void destructureElementList(const Reference &array, QQmlJS::AST::PatternElementList *bindingList, bool isDefinition = false);
582 void destructurePattern(QQmlJS::AST::Pattern *p, const Reference &rhs);
583
584 Reference referenceForPropertyName(const Codegen::Reference &object, QQmlJS::AST::PropertyName *name);
585
586 void emitReturn(const Reference &expr);
587
588 // nodes
589 bool visit(QQmlJS::AST::ArgumentList *ast) override;
590 bool visit(QQmlJS::AST::CaseBlock *ast) override;
591 bool visit(QQmlJS::AST::CaseClause *ast) override;
592 bool visit(QQmlJS::AST::CaseClauses *ast) override;
593 bool visit(QQmlJS::AST::Catch *ast) override;
594 bool visit(QQmlJS::AST::DefaultClause *ast) override;
595 bool visit(QQmlJS::AST::Elision *ast) override;
596 bool visit(QQmlJS::AST::Finally *ast) override;
597 bool visit(QQmlJS::AST::FormalParameterList *ast) override;
598 bool visit(QQmlJS::AST::Program *ast) override;
599 bool visit(QQmlJS::AST::StatementList *ast) override;
600 bool visit(QQmlJS::AST::UiArrayMemberList *ast) override;
601 bool visit(QQmlJS::AST::UiImport *ast) override;
602 bool visit(QQmlJS::AST::UiHeaderItemList *ast) override;
603 bool visit(QQmlJS::AST::UiPragmaValueList *ast) override;
604 bool visit(QQmlJS::AST::UiPragma *ast) override;
605 bool visit(QQmlJS::AST::UiObjectInitializer *ast) override;
606 bool visit(QQmlJS::AST::UiObjectMemberList *ast) override;
607 bool visit(QQmlJS::AST::UiParameterList *ast) override;
608 bool visit(QQmlJS::AST::UiProgram *ast) override;
609 bool visit(QQmlJS::AST::UiQualifiedId *ast) override;
610 bool visit(QQmlJS::AST::VariableDeclarationList *ast) override;
611
612 bool visit(QQmlJS::AST::PatternElement *ast) override;
613 bool visit(QQmlJS::AST::PatternElementList *ast) override;
614 bool visit(QQmlJS::AST::PatternProperty *ast) override;
615 bool visit(QQmlJS::AST::PatternPropertyList *ast) override;
616
617 bool visit(QQmlJS::AST::ExportDeclaration *ast) override;
618
619 bool visit(QQmlJS::AST::TypeAnnotation *ast) override;
620
621 // expressions
622 bool visit(QQmlJS::AST::Expression *ast) override;
623 bool visit(QQmlJS::AST::ArrayPattern *ast) override;
624 bool visit(QQmlJS::AST::ArrayMemberExpression *ast) override;
625 bool visit(QQmlJS::AST::BinaryExpression *ast) override;
626 bool visit(QQmlJS::AST::CallExpression *ast) override;
627 void endVisit(QQmlJS::AST::CallExpression *ast) override;
628 bool visit(QQmlJS::AST::ConditionalExpression *ast) override;
629 bool visit(QQmlJS::AST::DeleteExpression *ast) override;
630 void endVisit(QQmlJS::AST::DeleteExpression *ast) override;
631 bool visit(QQmlJS::AST::FalseLiteral *ast) override;
632 bool visit(QQmlJS::AST::SuperLiteral *ast) override;
633 bool visit(QQmlJS::AST::FieldMemberExpression *ast) override;
634 void endVisit(QQmlJS::AST::FieldMemberExpression *ast) override;
635 bool visit(QQmlJS::AST::TaggedTemplate *ast) override;
636 bool visit(QQmlJS::AST::FunctionExpression *ast) override;
637 bool visit(QQmlJS::AST::IdentifierExpression *ast) override;
638 bool visit(QQmlJS::AST::NestedExpression *ast) override;
639 bool visit(QQmlJS::AST::NewExpression *ast) override;
640 bool visit(QQmlJS::AST::NewMemberExpression *ast) override;
641 bool visit(QQmlJS::AST::NotExpression *ast) override;
642 bool visit(QQmlJS::AST::NullExpression *ast) override;
643 bool visit(QQmlJS::AST::NumericLiteral *ast) override;
644 bool visit(QQmlJS::AST::ObjectPattern *ast) override;
645 bool visit(QQmlJS::AST::PostDecrementExpression *ast) override;
646 bool visit(QQmlJS::AST::PostIncrementExpression *ast) override;
647 bool visit(QQmlJS::AST::PreDecrementExpression *ast) override;
648 bool visit(QQmlJS::AST::PreIncrementExpression *ast) override;
649 bool visit(QQmlJS::AST::RegExpLiteral *ast) override;
650 bool visit(QQmlJS::AST::StringLiteral *ast) override;
651 bool visit(QQmlJS::AST::TemplateLiteral *ast) override;
652 bool visit(QQmlJS::AST::ThisExpression *ast) override;
653 bool visit(QQmlJS::AST::TildeExpression *ast) override;
654 bool visit(QQmlJS::AST::TrueLiteral *ast) override;
655 bool visit(QQmlJS::AST::TypeOfExpression *ast) override;
656 bool visit(QQmlJS::AST::UnaryMinusExpression *ast) override;
657 bool visit(QQmlJS::AST::UnaryPlusExpression *ast) override;
658 bool visit(QQmlJS::AST::VoidExpression *ast) override;
659 bool visit(QQmlJS::AST::FunctionDeclaration *ast) override;
660 bool visit(QQmlJS::AST::YieldExpression *ast) override;
661 bool visit(QQmlJS::AST::ClassExpression *ast) override;
662 bool visit(QQmlJS::AST::ClassDeclaration *ast) override;
663
664 // statements
665 bool visit(QQmlJS::AST::Block *ast) override;
666 bool visit(QQmlJS::AST::BreakStatement *ast) override;
667 bool visit(QQmlJS::AST::ContinueStatement *ast) override;
668 bool visit(QQmlJS::AST::DebuggerStatement *ast) override;
669 bool visit(QQmlJS::AST::DoWhileStatement *ast) override;
670 bool visit(QQmlJS::AST::EmptyStatement *ast) override;
671 bool visit(QQmlJS::AST::ExpressionStatement *ast) override;
672 bool visit(QQmlJS::AST::ForEachStatement *ast) override;
673 bool visit(QQmlJS::AST::ForStatement *ast) override;
674 bool visit(QQmlJS::AST::IfStatement *ast) override;
675 bool visit(QQmlJS::AST::LabelledStatement *ast) override;
676 bool visit(QQmlJS::AST::ReturnStatement *ast) override;
677 bool visit(QQmlJS::AST::SwitchStatement *ast) override;
678 bool visit(QQmlJS::AST::ThrowStatement *ast) override;
679 bool visit(QQmlJS::AST::TryStatement *ast) override;
680 bool visit(QQmlJS::AST::VariableStatement *ast) override;
681 bool visit(QQmlJS::AST::WhileStatement *ast) override;
682 bool visit(QQmlJS::AST::WithStatement *ast) override;
683
684 // ui object members
685 bool visit(QQmlJS::AST::UiArrayBinding *ast) override;
686 bool visit(QQmlJS::AST::UiObjectBinding *ast) override;
687 bool visit(QQmlJS::AST::UiObjectDefinition *ast) override;
688 bool visit(QQmlJS::AST::UiPublicMember *ast) override;
689 bool visit(QQmlJS::AST::UiScriptBinding *ast) override;
690 bool visit(QQmlJS::AST::UiSourceElement *ast) override;
691
692 bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r,
693 const QQmlJS::SourceLocation &loc);
694 virtual void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail);
695 virtual void throwReferenceError(const QQmlJS::SourceLocation &loc, const QString &detail);
697 {
698 throwSyntaxError(QQmlJS::SourceLocation(),
699 QStringLiteral("Maximum statement or expression depth exceeded"));
700 }
701
702public:
706 ReferenceError
707 };
708
709 ErrorType errorType() const { return _errorType; }
710 bool hasError() const { return _errorType != NoError; }
712 QUrl url() const;
713
714 Reference binopHelper(QQmlJS::AST::BinaryExpression *ast, QSOperator::Op oper, Reference &left,
715 Reference &right);
716 Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right);
717 struct Arguments { int argc; int argv; bool hasSpread; };
719 void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject, bool optional = false);
720
722 bool handleTaggedTemplate(Reference base, QQmlJS::AST::TaggedTemplate *ast);
723 void createTemplateObject(QQmlJS::AST::TemplateLiteral *t);
724
725 void setUseFastLookups(bool b) { useFastLookups = b; }
726
727 void handleTryCatch(QQmlJS::AST::TryStatement *ast);
728 void handleTryFinally(QQmlJS::AST::TryStatement *ast);
729
730
731 Reference referenceForName(
732 const QString &name, bool lhs,
733 const QQmlJS::SourceLocation &accessLocation = QQmlJS::SourceLocation());
734
735 QQmlRefPointer<QV4::CompiledData::CompilationUnit> generateCompilationUnit(
736 bool generateUnitData = true);
737 static QQmlRefPointer<QV4::CompiledData::CompilationUnit> compileModule(
738 bool debugMode, const QString &url, const QString &sourceCode,
739 const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics);
740
741 Context *currentContext() const { return _context; }
742 BytecodeGenerator *generator() const { return bytecodeGenerator; }
743
744 void loadClosure(int index);
745
746 Module *module() const { return _module; }
747
749 if (!_returnLabel)
750 _returnLabel = new BytecodeGenerator::Label(bytecodeGenerator->newLabel());
751 return *_returnLabel;
752 }
753
754 void setGlobalNames(const QSet<QString>& globalNames) {
755 m_globalNames = globalNames;
756 }
757
758 static const char *s_globalNames[];
759
760protected:
761 friend class ScanFunctions;
762 friend struct ControlFlow;
763 friend struct ControlFlowCatch;
764 friend struct ControlFlowFinally;
765
766 inline void setExprResult(const Reference &result) { m_expressions.back().setResult(result); }
767 inline void setExprResult(Reference &&result) { m_expressions.back().setResult(std::move(result)); }
768 inline Reference exprResult() const { return m_expressions.back().result(); }
769 inline void clearExprResultName() { m_expressions.back().clearResultName(); }
770
771 inline bool exprAccept(Format f) { return m_expressions.back().accept(f); }
772
773 inline const Result &currentExpr() const { return m_expressions.back(); }
774
775 inline void pushExpr(Result &&expr) { m_expressions.push_back(std::move(expr)); }
776 inline void pushExpr(const Result &expr) { m_expressions.push_back(expr); }
777 inline void pushExpr(const QString &name = QString()) { m_expressions.emplace_back(name); }
778
780 {
781 const Result result = m_expressions.back();
782 m_expressions.pop_back();
783 return result;
784 }
785
787 const Reference result = m_expressions.back().result();
788 m_expressions.pop_back();
789 return result;
790 }
791
792 std::vector<Result> m_expressions;
797 Context *_functionContext = nullptr;
800 BytecodeGenerator *bytecodeGenerator = nullptr;
801 Moth::BytecodeGenerator::Label *_returnLabel = nullptr;
803 bool useFastLookups = true;
804 bool requiresReturnValue = false;
805 bool insideSwitch = false;
806 bool inFormalParameterList = false;
807 bool functionEndsWithReturn = false;
808 bool _tailCallsAreAllowed = true;
809 bool storeSourceLocations = false;
810 QSet<QString> m_globalNames;
811
813 {
814 QQmlJS::AST::Node *tailNodeOfChain = nullptr;
815 std::vector<Moth::BytecodeGenerator::Jump> jumpsToPatch;
816 bool actuallyHasOptionals = false;
817 };
818 QSet<QQmlJS::AST::Node*> m_seenOptionalChainNodes;
819 std::stack<OptionalChainState> m_optionalChainsStates;
820
821 ControlFlow *controlFlow = nullptr;
822
824 ErrorType _errorType = NoError;
827
829 {
830 public:
831 TailCallBlocker(Codegen *cg, bool onoff = false)
832 : _cg(cg)
833 , _saved(_cg->_tailCallsAreAllowed)
834 , _onoff(onoff)
835 { _cg->_tailCallsAreAllowed = onoff; }
836
838 { _cg->_tailCallsAreAllowed = _saved; }
839
840 void unblock() const
841 { _cg->_tailCallsAreAllowed = _saved; }
842
843 void reblock() const
844 { _cg->_tailCallsAreAllowed = _onoff; }
845
846 private:
847 Codegen *_cg;
848 bool _saved;
849 bool _onoff;
850 };
851
852private:
853 Q_DISABLE_COPY(Codegen)
854 VolatileMemoryLocations scanVolatileMemoryLocations(QQmlJS::AST::Node *ast);
855 void handleConstruct(const Reference &base, QQmlJS::AST::ArgumentList *args);
856 void throwError(ErrorType errorType, const QQmlJS::SourceLocation &loc,
857 const QString &detail);
858 bool traverseOptionalChain(QQmlJS::AST::Node *node);
859 void optionalChainFinalizer(const Reference &expressionResult, bool tailOfChain,
860 bool isDeleteExpression = false);
861 Reference loadSubscriptForCall(const Reference &base);
862 void generateThrowException(const QString &type, const QString &text = QString());
863};
864
865}
866
867}
868
870
871#endif // QV4CODEGEN_P_H
\inmodule QtCore\reentrant
Definition qdatetime.h:283
void accept(BaseVisitor *visitor)
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
\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
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())
std::stack< OptionalChainState > m_optionalChainsStates
BytecodeGenerator * generator() const
Module * module() const
void pushExpr(const Result &expr)
void throwRecursionDepthError() override
Reference exprResult() const
QString text
std::list< QString >::iterator Name
Definition lalr.h:28
Combined button and popup list for selecting options.
CodegenWarningInterface * defaultCodegenWarningInterface()
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:1220
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
@ NoError
Definition main.cpp:34
#define Q_QML_COMPILER_EXPORT
unsigned int quint32
Definition qtypes.h:50
unsigned int uint
Definition qtypes.h:34
static const uint base
Definition qurlidna.cpp:20
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
std::vector< Moth::BytecodeGenerator::Jump > jumpsToPatch
static Reference fromScopedLocal(Codegen *cg, int index, int scope)
Reference(Reference &&)=default
static Reference fromImport(Codegen *cg, int index)
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 fromMember(const Reference &baseRef, const QString &name, QQmlJS::SourceLocation sourceLocation=QQmlJS::SourceLocation(), bool isOptional=false, std::vector< Moth::BytecodeGenerator::Jump > *optionalChainJumpsToPatch=nullptr)
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)
static Q_REQUIRED_RESULT Reference storeConstOnStack(Codegen *cg, QV4::ReturnedValue constant)
Reference(const QString &name=QString())
bool operator!=(const Reference &other) const
static Reference fromThis(Codegen *cg)
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:23