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
qv4compilercontrolflow_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 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 QV4COMPILERCONTROLFLOW_P_H
4#define QV4COMPILERCONTROLFLOW_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/qv4codegen_p.h>
18#include <private/qqmljsast_p.h>
19#include <private/qv4bytecodegenerator_p.h>
20
22
23namespace QV4 {
24
25namespace Compiler {
26
31
39
45
50
54
56 : cg(cg), parent(cg->controlFlow), type(type)
57 {
58 cg->controlFlow = this;
59 }
60
61 virtual ~ControlFlow() {
63 }
64
66 {
67 Q_ASSERT(type == Break || type == Continue || type == Return);
68 ControlFlow *flow = this;
69 int level = 0;
70 while (flow) {
72 if (l.isValid())
73 return UnwindTarget{l, level};
74 if (flow->requiresUnwind())
75 ++level;
76 flow = flow->parent;
77 }
78 if (type == Return)
79 return UnwindTarget{ cg->returnLabel(), level };
80 return UnwindTarget();
81 }
82
83 virtual QString label() const { return QString(); }
84
85 bool hasLoop() const {
86 const ControlFlow *flow = this;
87 while (flow) {
88 if (flow->type == Loop)
89 return true;
90 flow = flow->parent;
91 }
92 return false;
93 }
94
95protected:
99 virtual bool requiresUnwind() {
100 return false;
101 }
102
103public:
107
111
112
113protected:
116 if (cg->_labelledStatement) {
118 cg->_labelledStatement = nullptr;
119 }
120 return label;
121 }
123 return cg->bytecodeGenerator;
124 }
125};
126
128{
130
135
140
142 {
144
145 Instruction::UnwindDispatch dispatch;
146 generator()->addInstruction(dispatch);
147 }
148
152};
153
155{
156 std::function<void()> cleanup = nullptr;
157
166
175
176 bool requiresUnwind() override {
177 return cleanup != nullptr;
178 }
179};
180
182{
186
191
193 switch (type) {
194 case Break:
195 if (breakLabel && (label.isEmpty() || label == loopLabel))
196 return *breakLabel;
197 break;
198 case Continue:
199 if (continueLabel && (label.isEmpty() || label == loopLabel))
200 return *continueLabel;
201 break;
202 default:
203 break;
204 }
206 }
207
208 QString label() const override { return loopLabel; }
209};
210
211
213{
216 {
218
219 // assumes the with object is in the accumulator
220 Instruction::PushWithContext pushScope;
221 generator()->addInstruction(pushScope);
223 }
224
226 // emit code for unwinding
228
230 Instruction::PopContext pop;
232
234 }
235
236 bool requiresUnwind() override {
237 return true;
238 }
239
240
241};
242
244{
256
258 // emit code for unwinding
262 }
263
265
268 cg->leaveBlock();
269 }
270
271 virtual bool requiresUnwind() override {
273 }
274
276};
277
279{
281 bool insideCatch = false;
283
290
291 virtual bool requiresUnwind() override {
292 return true;
293 }
294
298
300 // emit code for unwinding
301 insideCatch = true;
303
305
306 // exceptions inside the try block go here
309
311
312 block->emitBlockHeader(cg);
313
315
317 // destructuring pattern
319 // skip the additional block
321
322 // exceptions inside catch and break/return statements go here
324 block->emitBlockFooter(cg);
325
326 cg->leaveBlock();
327
328 noException.link();
330
332 insideCatch = false;
333 }
334};
335
337{
339 bool insideFinally = false;
340
341 ControlFlowFinally(Codegen *cg, QQmlJS::AST::Finally *finally, bool hasCatchBlock)
343 {
344 Q_ASSERT(finally != nullptr);
346
347 // No need to set the handler for the finally now if there is a catch block.
348 // In that case, a handler for the latter will be set immediately after this.
349 if (!hasCatchBlock) {
351 }
352 }
353
354 virtual bool requiresUnwind() override {
355 return !insideFinally;
356 }
357
361
363 // emit code for unwinding
365
367
368 insideFinally = true;
369 int returnValueTemp = -1;
370 if (cg->requiresReturnValue) {
371 returnValueTemp = generator()->newRegister();
372 Instruction::MoveReg move;
373 move.srcReg = cg->_returnAddress;
374 move.destReg = returnValueTemp;
375 generator()->addInstruction(move);
376 }
377 int exceptionTemp = generator()->newRegister();
378 Instruction::GetException instr;
379 generator()->addInstruction(instr);
380 Reference::fromStackSlot(cg, exceptionTemp).storeConsumeAccumulator();
381
384 insideFinally = false;
385
386 if (cg->requiresReturnValue) {
387 Instruction::MoveReg move;
388 move.srcReg = returnValueTemp;
389 move.destReg = cg->_returnAddress;
390 generator()->addInstruction(move);
391 }
392 Reference::fromStackSlot(cg, exceptionTemp).loadInAccumulator();
393 Instruction::SetException setException;
394 generator()->addInstruction(setException);
395
397 }
398};
399
400} } // QV4::Compiler namespace
401
403
404#endif
StatementList * statements
PatternElement * patternElement
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1121
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QQmlJS::AST::LabelledStatement * _labelledStatement
BytecodeGenerator * bytecodeGenerator
void initializeAndDestructureBindingElement(QQmlJS::AST::PatternElement *e, const Reference &baseRef=Reference(), bool isDefinition=false)
BytecodeGenerator::Label returnLabel()
void statement(QQmlJS::AST::Statement *ast)
Context * enterBlock(QQmlJS::AST::Node *node)
ControlFlow * controlFlow
void statementList(QQmlJS::AST::StatementList *ast)
void addInstruction(const InstrData< InstrT > &data)
void setUnwindHandler(ExceptionHandler *handler)
Q_REQUIRED_RESULT Jump jumpNoException()
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
GLenum GLuint GLint level
GLenum type
GLuint GLsizei const GLchar * label
[43]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
static Reference fromName(Codegen *cg, const QString &name)
static Reference fromStackSlot(Codegen *cg, int tempIndex=-1, bool isLocal=false)
void emitBlockFooter(Compiler::Codegen *codegen)
void emitBlockHeader(Compiler::Codegen *codegen)
ControlFlowBlock(Codegen *cg, QQmlJS::AST::Node *ast)
BytecodeGenerator::ExceptionHandler exceptionLabel
ControlFlowCatch(Codegen *cg, QQmlJS::AST::Catch *catchExpression)
BytecodeGenerator::ExceptionHandler * unwindHandler() override
BytecodeGenerator::ExceptionHandler * unwindHandler() override
ControlFlowFinally(Codegen *cg, QQmlJS::AST::Finally *finally, bool hasCatchBlock)
ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel=nullptr, std::function< void()> cleanup=nullptr)
BytecodeGenerator::Label * continueLabel
BytecodeGenerator::Label getUnwindTarget(UnwindType type, const QString &label) override
BytecodeGenerator::Label * breakLabel
ControlFlowUnwindCleanup(Codegen *cg, std::function< void()> cleanup, Type type=Block)
BytecodeGenerator::ExceptionHandler unwindLabel
virtual BytecodeGenerator::ExceptionHandler * unwindHandler() override
ControlFlow(Codegen *cg, Type type)
UnwindTarget unwindTarget(UnwindType type, const QString &label=QString())
virtual BytecodeGenerator::ExceptionHandler * unwindHandler()
BytecodeGenerator * generator() const
BytecodeGenerator::ExceptionHandler * parentUnwindHandler()
virtual BytecodeGenerator::Label getUnwindTarget(UnwindType, const QString &=QString())
Definition moc.h:23