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// Qt-Security score:significant
4
5#ifndef QV4BYTECODEGENERATOR_P_H
6#define QV4BYTECODEGENERATOR_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18#include <private/qv4instr_moth_p.h>
19#include <private/qv4compileddata_p.h>
20#include <private/qv4compilercontext_p.h>
21#include <private/qqmljssourcelocation_p.h>
22
23#include <memory>
24
26
27namespace QQmlJS {
28class SourceLocation;
29}
30
31namespace QV4 {
32
33namespace Compiler {
34struct Context;
35}
36
37namespace Moth {
38
40public:
41 BytecodeGenerator(int line, bool debug, bool storeSourceLocation = false)
42 : startLine(line), debugMode(debug)
43 {
44 if (storeSourceLocation)
45 m_sourceLocationTable.reset(new QV4::Compiler::Context::SourceLocationTable {});
46 }
47
48 struct Label {
53 Label() = default;
55 : generator(generator),
56 index(generator->labels.size()) {
57 generator->labels.append(-1);
58 if (mode == LinkNow)
59 link();
60 }
61
62 void link() const {
63 Q_ASSERT(index >= 0);
64 Q_ASSERT(generator->labels[index] == -1);
65 generator->labels[index] = generator->instructions.size();
67 }
68 bool isValid() const { return generator != nullptr; }
69
71 int index = -1;
72 };
73
74 struct Jump {
75 Jump(BytecodeGenerator *generator, int instruction)
76 : generator(generator),
77 index(instruction)
78 { Q_ASSERT(generator && index != -1); }
79
80 ~Jump() {
81 Q_ASSERT(index == -1 || generator->instructions[index].linkedLabel != -1); // make sure link() got called
82 }
83
84 Jump(Jump &&j) {
85 std::swap(generator, j.generator);
86 std::swap(index, j.index);
87 }
88
90 int index = -1;
91
92 void link() {
94 }
95 void link(Label l) {
96 Q_ASSERT(l.index >= 0);
97 Q_ASSERT(generator->instructions[index].linkedLabel == -1);
98 generator->instructions[index].linkedLabel = l.index;
99 }
100
101 private:
102 // make this type move-only:
104 // we never move-assign this type anywhere, so disable it:
105 Jump &operator=(Jump &&) = delete;
106 };
107
108 struct ExceptionHandler : public Label {
109 ExceptionHandler() = default;
111 : Label(generator, LinkLater)
112 {
113 }
115 {
116 Q_ASSERT(!generator || generator->currentExceptionHandler != this);
117 }
122 bool isValid() const { return generator != nullptr; }
123 };
124
126 return Label(this, Label::LinkNow);
127 }
128
130 return Label(this, Label::LinkLater);
131 }
132
136
137 template<int InstrT>
138 void addInstruction(const InstrData<InstrT> &data)
139 {
140 Instr genericInstr;
141 InstrMeta<InstrT>::setData(genericInstr, data);
142 addInstructionHelper(Moth::Instr::Type(InstrT), genericInstr);
143 }
144
146 {
148QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // broken gcc warns about Instruction::Debug()
150 return addJumpInstruction(data);
152 }
153
158
163
169
175
182
189
197
205
211
222
223 void unwindToLabel(int level, const Label &target)
224 {
225 if (level) {
229 } else {
230 jump().link(target);
231 }
232 }
233
234
235
236 void setLocation(const QQmlJS::SourceLocation &loc);
237 void incrementStatement();
238
240 return currentExceptionHandler;
241 }
242
243 int newRegister();
244 int newRegisterArray(int n);
245 int registerCount() const { return regCount; }
246 int currentRegister() const { return currentReg; }
247
248 void finalize(Compiler::Context *context);
249
250 template<int InstrT>
251 Jump addJumpInstruction(const InstrData<InstrT> &data)
252 {
253 Instr genericInstr;
254 InstrMeta<InstrT>::setData(genericInstr, data);
255 return Jump(this, addInstructionHelper(Moth::Instr::Type(InstrT), genericInstr, offsetof(InstrData<InstrT>, offset)));
256 }
257
258 void addCJumpInstruction(bool jumpOnFalse, const Label *trueLabel, const Label *falseLabel)
259 {
260 if (jumpOnFalse)
261 addJumpInstruction(Instruction::JumpFalse()).link(*falseLabel);
262 else
263 addJumpInstruction(Instruction::JumpTrue()).link(*trueLabel);
264 }
265
267 {
268 lastInstrType = -1;
269 }
270
271 void addLoopStart(const Label &start)
272 {
273 _labelInfos.push_back({ start.index });
274 }
275
276private:
277 friend struct Jump;
278 friend struct Label;
279 friend struct ExceptionHandler;
280
281 int addInstructionHelper(Moth::Instr::Type type, const Instr &i, int offsetOfOffset = -1);
282
283 struct I {
284 Moth::Instr::Type type;
285 short size;
286 uint position;
287 int line;
288 int statement;
289 int offsetForJump;
290 int linkedLabel;
291 unsigned char packed[sizeof(Instr) + 2]; // 2 for instruction type
292 };
293
294 void compressInstructions();
295 void packInstruction(I &i);
296 void adjustJumpOffsets();
297
298 QList<I> instructions;
299 QList<int> labels;
300 ExceptionHandler *currentExceptionHandler = nullptr;
301 int regCount = 0;
302public:
303 int currentReg = 0;
304private:
305 int startLine = 0;
306 int currentLine = 0;
307 int currentStatement = 0;
308 QQmlJS::SourceLocation currentSourceLocation;
309 std::unique_ptr<QV4::Compiler::Context::SourceLocationTable> m_sourceLocationTable;
310 bool debugMode = false;
311
312 int lastInstrType = -1;
313 Moth::Instr lastInstr;
314
315 struct LabelInfo {
316 int labelIndex;
317 };
318 std::vector<LabelInfo> _labelInfos;
319};
320
321}
322}
323
324QT_END_NAMESPACE
325
326#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)
Combined button and popup list for selecting options.
Definition qjsvalue.h:24
QList< Method > staticMethods
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
QList< Context * > nestedContexts
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
std::unique_ptr< SourceLocationTable > sourceLocationTable
UsesArgumentsObject usesArgumentsObject
QList< CompiledData::CodeOffsetToLineAndStatement > lineAndStatementNumberMapping
QList< ImportEntry > importEntries
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
void addUsedVariable(const QString &name)
QList< ExportEntry > exportEntries
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
Context * newContext(QQmlJS::AST::Node *node, Context *parent, ContextType compilationMode)
QHash< QQmlJS::AST::Node *, Context * > contextMap
QList< ExportEntry > indirectExportEntries
QList< Context * > functions
Module(const QString &fileName, const QString &finalUrl, bool debugMode)
QList< ExportEntry > starExportEntries
QList< TemplateObject > templateObjects
QList< ImportEntry > importEntries
QList< ExportEntry > localExportEntries
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)