3#ifndef QV4COMPILERCONTROLFLOW_P_H
4#define QV4COMPILERCONTROLFLOW_P_H
17#include <private/qv4codegen_p.h>
18#include <private/qqmljsast_p.h>
19#include <private/qv4bytecodegenerator_p.h>
58 cg->controlFlow =
this;
62 cg->controlFlow = parent;
71 BytecodeGenerator::Label l = flow->getUnwindTarget(type, label);
79 return UnwindTarget{ cg->returnLabel(), level };
97 return BytecodeGenerator::Label();
109 return parentUnwindHandler();
116 if (cg->_labelledStatement) {
117 label = cg->_labelledStatement->label.toString();
118 cg->_labelledStatement =
nullptr;
123 return cg->bytecodeGenerator;
138 unwindLabel = generator()->newExceptionHandler();
145 Instruction::UnwindDispatch dispatch;
146 generator()->addInstruction(dispatch);
150 return unwindLabel.isValid() ? &unwindLabel : parentUnwindHandler();
163 generator()->setUnwindHandler(&unwindLabel);
171 generator()->setUnwindHandler(parentUnwindHandler());
177 return cleanup !=
nullptr;
187 ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel =
nullptr, std::function<
void()> cleanup =
nullptr)
195 if (breakLabel && (label.isEmpty() || label == loopLabel))
199 if (continueLabel && (label.isEmpty() || label == loopLabel))
200 return *continueLabel;
205 return BytecodeGenerator::Label();
220 Instruction::PushWithContext pushScope;
221 generator()->addInstruction(pushScope);
222 generator()->setUnwindHandler(&unwindLabel);
229 generator()->setUnwindHandler(parentUnwindHandler());
230 Instruction::PopContext pop;
231 generator()->addInstruction(pop);
248 block = cg->enterBlock(ast);
249 block->emitBlockHeader(cg);
251 if (block->requiresExecutionContext) {
253 generator()->setUnwindHandler(&unwindLabel);
259 if (block->requiresExecutionContext) {
261 generator()->setUnwindHandler(parentUnwindHandler());
264 block->emitBlockFooter(cg);
266 if (block->requiresExecutionContext )
272 return block->requiresExecutionContext;
288 generator()->setUnwindHandler(&exceptionLabel);
296 return insideCatch ? &unwindLabel : &exceptionLabel;
304 Codegen::RegisterScope scope(cg);
307 exceptionLabel.link();
308 BytecodeGenerator::Jump noException = generator()->jumpNoException();
310 Context *block = cg->enterBlock(catchExpression);
312 block->emitBlockHeader(cg);
314 generator()->setUnwindHandler(&unwindLabel);
316 if (catchExpression->patternElement->bindingIdentifier.isEmpty())
318 cg->initializeAndDestructureBindingElement(catchExpression->patternElement, Reference::fromName(cg, QStringLiteral(
"@caught")));
320 cg->statementList(catchExpression->statement->statements);
324 block->emitBlockFooter(cg);
329 generator()->setUnwindHandler(parentUnwindHandler());
344 Q_ASSERT(finally !=
nullptr);
349 if (!hasCatchBlock) {
350 generator()->setUnwindHandler(&unwindLabel);
359 return insideFinally ? parentUnwindHandler() : ControlFlowUnwind::unwindHandler();
366 Codegen::RegisterScope scope(cg);
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);
377 int exceptionTemp = generator()->newRegister();
378 Instruction::GetException instr;
379 generator()->addInstruction(instr);
380 Reference::fromStackSlot(cg, exceptionTemp).storeConsumeAccumulator();
382 generator()->setUnwindHandler(parentUnwindHandler());
383 cg->statement(finally->statement);
386 if (cg->requiresReturnValue) {
387 Instruction::MoveReg move;
388 move.srcReg = returnValueTemp;
389 move.destReg = cg->_returnAddress;
390 generator()->addInstruction(move);
392 Reference::fromStackSlot(cg, exceptionTemp).loadInAccumulator();
393 Instruction::SetException setException;
394 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