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
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;
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)
76 index(instruction)
77 { Q_ASSERT(generator && index != -1); }
78
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:
102 Q_DISABLE_COPY(Jump)
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;
114 {
115 Q_ASSERT(!generator || generator->currentExceptionHandler != this);
116 }
117 bool isValid() const { return generator != nullptr; }
118 };
119
121 return Label(this, Label::LinkNow);
122 }
123
125 return Label(this, Label::LinkLater);
126 }
127
131
132 template<int InstrT>
133 void addInstruction(const InstrData<InstrT> &data)
134 {
135 Instr genericInstr;
136 InstrMeta<InstrT>::setData(genericInstr, data);
137 addInstructionHelper(Moth::Instr::Type(InstrT), genericInstr);
138 }
139
141 {
143QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // broken gcc warns about Instruction::Debug()
144 Instruction::Jump data;
145 return addJumpInstruction(data);
147 }
148
150 {
151 return addJumpInstruction(Instruction::JumpTrue());
152 }
153
155 {
156 return addJumpInstruction(Instruction::JumpFalse());
157 }
158
160 {
161 Instruction::JumpNotUndefined data{};
162 return addJumpInstruction(data);
163 }
164
166 {
167 Instruction::JumpNoException data{};
168 return addJumpInstruction(data);
169 }
170
172 {
173 Instruction::GetOptionalLookup data{};
174 data.index = index;
175 return addJumpInstruction(data);
176 }
177
179 {
180 Instruction::LoadOptionalProperty data{};
181 data.name = name;
182 return addJumpInstruction(data);
183 }
184
185 void jumpStrictEqual(const StackSlot &lhs, const Label &target)
186 {
187 Instruction::CmpStrictEqual cmp;
188 cmp.lhs = lhs;
189 addInstruction(std::move(cmp));
190 addJumpInstruction(Instruction::JumpTrue()).link(target);
191 }
192
193 void jumpStrictNotEqual(const StackSlot &lhs, const Label &target)
194 {
195 Instruction::CmpStrictNotEqual cmp;
196 cmp.lhs = lhs;
197 addInstruction(std::move(cmp));
198 addJumpInstruction(Instruction::JumpTrue()).link(target);
199 }
200
202 {
203 Instruction::CheckException chk;
204 addInstruction(chk);
205 }
206
208 {
209 currentExceptionHandler = handler;
210 Instruction::SetUnwindHandler data;
211 data.offset = 0;
212 if (!handler)
214 else
215 addJumpInstruction(data).link(*handler);
216 }
217
218 void unwindToLabel(int level, const Label &target)
219 {
220 if (level) {
221 Instruction::UnwindToLabel unwind;
222 unwind.level = level;
224 } else {
225 jump().link(target);
226 }
227 }
228
229
230
231 void setLocation(const QQmlJS::SourceLocation &loc);
232 void incrementStatement();
233
235 return currentExceptionHandler;
236 }
237
238 int newRegister();
239 int newRegisterArray(int n);
240 int registerCount() const { return regCount; }
241 int currentRegister() const { return currentReg; }
242
244
245 template<int InstrT>
246 Jump addJumpInstruction(const InstrData<InstrT> &data)
247 {
248 Instr genericInstr;
249 InstrMeta<InstrT>::setData(genericInstr, data);
250 return Jump(this, addInstructionHelper(Moth::Instr::Type(InstrT), genericInstr, offsetof(InstrData<InstrT>, offset)));
251 }
252
253 void addCJumpInstruction(bool jumpOnFalse, const Label *trueLabel, const Label *falseLabel)
254 {
255 if (jumpOnFalse)
256 addJumpInstruction(Instruction::JumpFalse()).link(*falseLabel);
257 else
258 addJumpInstruction(Instruction::JumpTrue()).link(*trueLabel);
259 }
260
262 {
263 lastInstrType = -1;
264 }
265
267 {
268 _labelInfos.push_back({ start.index });
269 }
270
271private:
272 friend struct Jump;
273 friend struct Label;
274 friend struct ExceptionHandler;
275
276 int addInstructionHelper(Moth::Instr::Type type, const Instr &i, int offsetOfOffset = -1);
277
278 struct I {
280 short size;
281 uint position;
282 int line;
283 int statement;
284 int offsetForJump;
285 int linkedLabel;
286 unsigned char packed[sizeof(Instr) + 2]; // 2 for instruction type
287 };
288
289 void compressInstructions();
290 void packInstruction(I &i);
291 void adjustJumpOffsets();
292
293 QVector<I> instructions;
294 QVector<int> labels;
295 ExceptionHandler *currentExceptionHandler = nullptr;
296 int regCount = 0;
297public:
298 int currentReg = 0;
299private:
300 int startLine = 0;
301 int currentLine = 0;
302 int currentStatement = 0;
303 QQmlJS::SourceLocation currentSourceLocation;
304 std::unique_ptr<QV4::Compiler::Context::SourceLocationTable> m_sourceLocationTable;
305 bool debugMode = false;
306
307 int lastInstrType = -1;
308 Moth::Instr lastInstr;
309
310 struct LabelInfo {
311 int labelIndex;
312 };
313 std::vector<LabelInfo> _labelInfos;
314};
315
316}
317}
318
320
321#endif
Q_REQUIRED_RESULT Jump jumpOptionalLookup(int index)
void jumpStrictNotEqual(const StackSlot &lhs, const Label &target)
Q_REQUIRED_RESULT Jump jumpFalse()
Jump addJumpInstruction(const InstrData< InstrT > &data)
BytecodeGenerator(int line, bool debug, bool storeSourceLocation=false)
void setLocation(const QQmlJS::SourceLocation &loc)
void jumpStrictEqual(const StackSlot &lhs, const Label &target)
Q_REQUIRED_RESULT Jump jumpOptionalProperty(int name)
Q_REQUIRED_RESULT Jump jumpTrue()
Q_REQUIRED_RESULT Jump jumpNotUndefined()
ExceptionHandler * exceptionHandler() const
void addInstruction(const InstrData< InstrT > &data)
void setUnwindHandler(ExceptionHandler *handler)
void addLoopStart(const Label &start)
void addCJumpInstruction(bool jumpOnFalse, const Label *trueLabel, const Label *falseLabel)
void finalize(Compiler::Context *context)
void unwindToLabel(int level, const Label &target)
Q_REQUIRED_RESULT Jump jumpNoException()
Combined button and popup list for selecting options.
static void * context
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_GCC(text)
#define QT_WARNING_PUSH
#define Q_REQUIRED_RESULT
GLenum mode
GLenum GLuint GLint level
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLenum target
GLuint start
GLenum GLuint GLintptr offset
GLuint name
GLfloat n
GLuint GLenum GLsizei GLsizei GLint GLint GLboolean packed
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
unsigned int uint
Definition qtypes.h:34
Jump(BytecodeGenerator *generator, int instruction)
Label(BytecodeGenerator *generator, LinkMode mode=LinkNow)