5#ifndef QV4COMPILERCONTROLFLOW_P_H
6#define QV4COMPILERCONTROLFLOW_P_H
19#include <private/qv4codegen_p.h>
20#include <private/qqmljsast_p.h>
21#include <private/qv4bytecodegenerator_p.h>
60 cg->controlFlow =
this;
64 cg->controlFlow = parent;
73 BytecodeGenerator::Label l = flow->getUnwindTarget(type, label);
81 return UnwindTarget{ cg->returnLabel(), level };
99 return BytecodeGenerator::Label();
111 return parentUnwindHandler();
118 if (cg->_labelledStatement) {
119 label = cg->_labelledStatement->label.toString();
120 cg->_labelledStatement =
nullptr;
125 return cg->bytecodeGenerator;
140 unwindLabel = generator()->newExceptionHandler();
147 Instruction::UnwindDispatch dispatch;
148 generator()->addInstruction(dispatch);
152 return unwindLabel.isValid() ? &unwindLabel : parentUnwindHandler();
165 generator()->setUnwindHandler(&unwindLabel);
173 generator()->setUnwindHandler(parentUnwindHandler());
179 return cleanup !=
nullptr;
189 ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel =
nullptr, std::function<
void()> cleanup =
nullptr)
197 if (breakLabel && (label.isEmpty() || label == loopLabel))
201 if (continueLabel && (label.isEmpty() || label == loopLabel))
202 return *continueLabel;
207 return BytecodeGenerator::Label();
222 Instruction::PushWithContext pushScope;
223 generator()->addInstruction(pushScope);
224 generator()->setUnwindHandler(&unwindLabel);
231 generator()->setUnwindHandler(parentUnwindHandler());
232 Instruction::PopContext pop;
233 generator()->addInstruction(pop);
250 block = cg->enterBlock(ast);
251 block->emitBlockHeader(cg);
253 if (block->requiresExecutionContext) {
255 generator()->setUnwindHandler(&unwindLabel);
261 if (block->requiresExecutionContext) {
263 generator()->setUnwindHandler(parentUnwindHandler());
266 block->emitBlockFooter(cg);
268 if (block->requiresExecutionContext )
274 return block->requiresExecutionContext;
290 generator()->setUnwindHandler(&exceptionLabel);
298 return insideCatch ? &unwindLabel : &exceptionLabel;
306 Codegen::RegisterScope scope(cg);
309 exceptionLabel.link();
310 BytecodeGenerator::Jump noException = generator()->jumpNoException();
312 Context *block = cg->enterBlock(catchExpression);
314 block->emitBlockHeader(cg);
316 generator()->setUnwindHandler(&unwindLabel);
318 if (catchExpression->patternElement->bindingIdentifier.isEmpty())
320 cg->initializeAndDestructureBindingElement(catchExpression->patternElement, Reference::fromName(cg, QStringLiteral(
"@caught")));
322 cg->statementList(catchExpression->statement->statements);
326 block->emitBlockFooter(cg);
331 generator()->setUnwindHandler(parentUnwindHandler());
346 Q_ASSERT(finally !=
nullptr);
351 if (!hasCatchBlock) {
352 generator()->setUnwindHandler(&unwindLabel);
361 return insideFinally ? parentUnwindHandler() : ControlFlowUnwind::unwindHandler();
368 Codegen::RegisterScope scope(cg);
371 int returnValueTemp = -1;
372 if (cg->requiresReturnValue) {
373 returnValueTemp = generator()->newRegister();
374 Instruction::MoveReg move;
375 move.srcReg = cg->_returnAddress;
376 move.destReg = returnValueTemp;
377 generator()->addInstruction(move);
379 int exceptionTemp = generator()->newRegister();
380 Instruction::GetException instr;
381 generator()->addInstruction(instr);
382 Reference::fromStackSlot(cg, exceptionTemp).storeConsumeAccumulator();
384 generator()->setUnwindHandler(parentUnwindHandler());
385 cg->statement(finally->statement);
388 if (cg->requiresReturnValue) {
389 Instruction::MoveReg move;
390 move.srcReg = returnValueTemp;
391 move.destReg = cg->_returnAddress;
392 generator()->addInstruction(move);
394 Reference::fromStackSlot(cg, exceptionTemp).loadInAccumulator();
395 Instruction::SetException setException;
396 generator()->addInstruction(setException);
virtual ~ControlFlowBlock()
virtual bool requiresUnwind() override
ControlFlowBlock(Codegen *cg, QQmlJS::AST::Node *ast)
BytecodeGenerator::ExceptionHandler exceptionLabel
virtual bool requiresUnwind() override
ControlFlowCatch(Codegen *cg, QQmlJS::AST::Catch *catchExpression)
QQmlJS::AST::Catch * catchExpression
BytecodeGenerator::ExceptionHandler * unwindHandler() override
QQmlJS::AST::Finally * finally
BytecodeGenerator::ExceptionHandler * unwindHandler() override
virtual bool requiresUnwind() override
ControlFlowFinally(Codegen *cg, QQmlJS::AST::Finally *finally, bool hasCatchBlock)
QString label() const override
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)
~ControlFlowUnwindCleanup()
std::function< void()> cleanup
bool requiresUnwind() override
ControlFlowUnwind(Codegen *cg, Type type)
BytecodeGenerator::ExceptionHandler unwindLabel
void setupUnwindHandler()
virtual BytecodeGenerator::ExceptionHandler * unwindHandler() override
bool requiresUnwind() override
ControlFlowWith(Codegen *cg)
BytecodeGenerator::Label linkLabel
ControlFlow(Codegen *cg, Type type)
UnwindTarget unwindTarget(UnwindType type, const QString &label=QString())
virtual BytecodeGenerator::ExceptionHandler * unwindHandler()
virtual QString label() const
BytecodeGenerator * generator() const
virtual bool requiresUnwind()
BytecodeGenerator::ExceptionHandler * parentUnwindHandler()
virtual BytecodeGenerator::Label getUnwindTarget(UnwindType, const QString &=QString())
QString loopLabel() const