Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4bytecodegenerator_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
4#ifndef QV4BYTECODEGENERATOR_P_H
5#define QV4BYTECODEGENERATOR_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17#include <private/qv4instr_moth_p.h>
18#include <private/qv4compileddata_p.h>
19#include <private/qv4compilercontext_p.h>
20#include <private/qqmljssourcelocation_p.h>
21
22#include <memory>
23
25
26namespace QQmlJS {
27class SourceLocation;
28}
29
30namespace QV4 {
31
32namespace Compiler {
33struct Context;
34}
35
36namespace Moth {
37
39public:
40 BytecodeGenerator(int line, bool debug, bool storeSourceLocation = false)
41 : startLine(line), debugMode(debug)
42 {
43 if (storeSourceLocation)
44 m_sourceLocationTable.reset(new QV4::Compiler::Context::SourceLocationTable {});
45 }
46
47 struct Label {
52 Label() = default;
54 : generator(generator),
55 index(generator->labels.size()) {
56 generator->labels.append(-1);
57 if (mode == LinkNow)
58 link();
59 }
60
61 void link() const {
62 Q_ASSERT(index >= 0);
63 Q_ASSERT(generator->labels[index] == -1);
64 generator->labels[index] = generator->instructions.size();
66 }
67 bool isValid() const { return generator != nullptr; }
68
70 int index = -1;
71 };
72
73 struct Jump {
74 Jump(BytecodeGenerator *generator, int instruction)
75 : generator(generator),
76 index(instruction)
77 { Q_ASSERT(generator && index != -1); }
78
79 ~Jump() {
80 Q_ASSERT(index == -1 || generator->instructions[index].linkedLabel != -1); // make sure link() got called
81 }
82
83 Jump(Jump &&j) {
84 std::swap(generator, j.generator);
85 std::swap(index, j.index);
86 }
87
89 int index = -1;
90
91 void link() {
93 }
94 void link(Label l) {
95 Q_ASSERT(l.index >= 0);
96 Q_ASSERT(generator->instructions[index].linkedLabel == -1);
97 generator->instructions[index].linkedLabel = l.index;
98 }
99
100 private:
101 // make this type move-only:
103 // we never move-assign this type anywhere, so disable it:
104 Jump &operator=(Jump &&) = delete;
105 };
106
107 struct ExceptionHandler : public Label {
108 ExceptionHandler() = default;
110 : Label(generator, LinkLater)
111 {
112 }
114 {
115 Q_ASSERT(!generator || generator->currentExceptionHandler != this);
116 }
121 bool isValid() const { return generator != nullptr; }
122 };
123
125 return Label(this, Label::LinkNow);
126 }
127
129 return Label(this, Label::LinkLater);
130 }
131
135
136 template<int InstrT>
137 void addInstruction(const InstrData<InstrT> &data)
138 {
139 Instr genericInstr;
140 InstrMeta<InstrT>::setData(genericInstr, data);
141 addInstructionHelper(Moth::Instr::Type(InstrT), genericInstr);
142 }
143
145 {
147QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // broken gcc warns about Instruction::Debug()
149 return addJumpInstruction(data);
151 }
152
157
162
168
174
181
188
196
204
210
221
222 void unwindToLabel(int level, const Label &target)
223 {
224 if (level) {
228 } else {
229 jump().link(target);
230 }
231 }
232
233
234
235 void setLocation(const QQmlJS::SourceLocation &loc);
236 void incrementStatement();
237
239 return currentExceptionHandler;
240 }
241
242 int newRegister();
243 int newRegisterArray(int n);
244 int registerCount() const { return regCount; }
245 int currentRegister() const { return currentReg; }
246
247 void finalize(Compiler::Context *context);
248
249 template<int InstrT>
250 Jump addJumpInstruction(const InstrData<InstrT> &data)
251 {
252 Instr genericInstr;
253 InstrMeta<InstrT>::setData(genericInstr, data);
254 return Jump(this, addInstructionHelper(Moth::Instr::Type(InstrT), genericInstr, offsetof(InstrData<InstrT>, offset)));
255 }
256
257 void addCJumpInstruction(bool jumpOnFalse, const Label *trueLabel, const Label *falseLabel)
258 {
259 if (jumpOnFalse)
260 addJumpInstruction(Instruction::JumpFalse()).link(*falseLabel);
261 else
262 addJumpInstruction(Instruction::JumpTrue()).link(*trueLabel);
263 }
264
266 {
267 lastInstrType = -1;
268 }
269
270 void addLoopStart(const Label &start)
271 {
272 _labelInfos.push_back({ start.index });
273 }
274
275private:
276 friend struct Jump;
277 friend struct Label;
278 friend struct ExceptionHandler;
279
280 int addInstructionHelper(Moth::Instr::Type type, const Instr &i, int offsetOfOffset = -1);
281
282 struct I {
283 Moth::Instr::Type type;
284 short size;
285 uint position;
286 int line;
287 int statement;
288 int offsetForJump;
289 int linkedLabel;
290 unsigned char packed[sizeof(Instr) + 2]; // 2 for instruction type
291 };
292
293 void compressInstructions();
294 void packInstruction(I &i);
295 void adjustJumpOffsets();
296
297 QVector<I> instructions;
298 QVector<int> labels;
299 ExceptionHandler *currentExceptionHandler = nullptr;
300 int regCount = 0;
301public:
302 int currentReg = 0;
303private:
304 int startLine = 0;
305 int currentLine = 0;
306 int currentStatement = 0;
307 QQmlJS::SourceLocation currentSourceLocation;
308 std::unique_ptr<QV4::Compiler::Context::SourceLocationTable> m_sourceLocationTable;
309 bool debugMode = false;
310
311 int lastInstrType = -1;
312 Moth::Instr lastInstr;
313
314 struct LabelInfo {
315 int labelIndex;
316 };
317 std::vector<LabelInfo> _labelInfos;
318};
319
320}
321}
322
323QT_END_NAMESPACE
324
325#endif
Jump addJumpInstruction(const InstrData< InstrT > &data)
BytecodeGenerator(int line, bool debug, bool storeSourceLocation=false)
ExceptionHandler * exceptionHandler() const
void addInstruction(const InstrData< InstrT > &data)
void addLoopStart(const Label &start)
void addCJumpInstruction(bool jumpOnFalse, const Label *trueLabel, const Label *falseLabel)
void finalize(Compiler::Context *context)
Definition qjsvalue.h:23
QVector< Method > staticMethods
QVector< Method > methods
KeyValuePair(quint32 key, quint32 value)
QQmlJS::AST::FunctionExpression * function
bool requiresTDZCheck(const QQmlJS::SourceLocation &accessLocation, bool accessAcrossContextBoundaries) const
QQmlJS::SourceLocation declarationLocation
QQmlJS::AST::VariableScope scope
bool memberInfo(const QString &name, const Member **m) const
void emitBlockFooter(Compiler::Codegen *codegen)
QQmlJS::AST::FormalParameterList * formals
bool hasArgument(const QString &name) const
void emitBlockHeader(Compiler::Codegen *codegen)
QQmlJS::AST::BoundNames arguments
QVector< Context * > nestedContexts
std::unique_ptr< SourceLocationTable > sourceLocationTable
QVector< ImportEntry > importEntries
UsesArgumentsObject usesArgumentsObject
QVector< ExportEntry > exportEntries
QMap< QString, Member > MemberMap
QQmlJS::AST::Type * returnType
Context(Context *parent, ContextType type)
ResolvedName resolveName(const QString &name, const QQmlJS::SourceLocation &accessLocation)
void setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator)
QQmlJS::SourceLocation lastBlockInitializerLocation
QVector< CompiledData::CodeOffsetToLineAndStatement > lineAndStatementNumberMapping
void addUsedVariable(const QString &name)
std::vector< unsigned > labelInfo
Member findMember(const QString &name) const
bool addLocalVar(const QString &name, MemberType contextType, QQmlJS::AST::VariableScope scope, QQmlJS::AST::FunctionExpression *function=nullptr, const QQmlJS::SourceLocation &declarationLocation=QQmlJS::SourceLocation(), bool isInjected=false)
int findArgument(const QString &name, bool *isInjected) const
CompiledData::Location location
static bool lessThan(const ExportEntry &lhs, const ExportEntry &rhs)
CompiledData::Location location
QVector< ImportEntry > importEntries
Context * newContext(QQmlJS::AST::Node *node, Context *parent, ContextType compilationMode)
QVector< ExportEntry > localExportEntries
QHash< QQmlJS::AST::Node *, Context * > contextMap
QList< Context * > functions
QVector< TemplateObject > templateObjects
Module(const QString &fileName, const QString &finalUrl, bool debugMode)
QVector< ExportEntry > starExportEntries
QVector< ExportEntry > indirectExportEntries
bool operator==(const TemplateObject &other)
ExceptionHandler & operator=(ExceptionHandler &&)=default
ExceptionHandler & operator=(const ExceptionHandler &)=default
ExceptionHandler(ExceptionHandler &&)=default
ExceptionHandler(const ExceptionHandler &)=default
Jump(BytecodeGenerator *generator, int instruction)
Label(BytecodeGenerator *generator, LinkMode mode=LinkNow)