4#include <private/qv4bytecodegenerator_p.h>
5#include <private/qv4compilercontext_p.h>
6#include <private/qqmljsastfwd_p.h>
12void BytecodeGenerator::setLocation(
const QQmlJS::SourceLocation &loc)
14 currentLine =
static_cast<
int>(loc.startLine);
15 currentSourceLocation = loc;
18void BytecodeGenerator::incrementStatement()
23int BytecodeGenerator::newRegister()
26 if (regCount < currentReg)
27 regCount = currentReg;
31int BytecodeGenerator::newRegisterArray(
int n)
35 if (regCount < currentReg)
36 regCount = currentReg;
40void BytecodeGenerator::packInstruction(I &i)
42 Instr::Type type = Instr::unpack(i.packed);
43 Q_ASSERT(
int(type) < MOTH_NUM_INSTRUCTIONS());
44 type = Instr::narrowInstructionType(type);
45 int instructionsAsInts[
sizeof(Instr)/
sizeof(
int)] = {};
46 int nMembers = Moth::InstrInfo::argumentCount[
static_cast<
int>(i.type)];
47 uchar *code = i.packed + Instr::encodedLength(type);
48 for (
int j = 0; j < nMembers; ++j) {
49 instructionsAsInts[j] = qFromLittleEndian<qint32>(code + j *
sizeof(
int));
55 for (
int n = 0; n < nMembers; ++n) {
56 if (width == Normal && (
static_cast<qint8>(instructionsAsInts[n]) != instructionsAsInts[n])) {
64 code = Instr::pack(code, type);
65 for (
int n = 0; n < nMembers; ++n) {
66 qint8 v =
static_cast<qint8>(instructionsAsInts[n]);
70 i.size = code - i.packed;
71 if (i.offsetForJump != -1)
72 i.offsetForJump = i.size - 1;
80void BytecodeGenerator::adjustJumpOffsets()
82 for (
int index = 0; index < instructions.size(); ++index) {
83 auto &i = instructions[index];
84 if (i.offsetForJump == -1)
86 Q_ASSERT(i.linkedLabel != -1 && labels.at(i.linkedLabel) != -1);
87 const auto &linkedInstruction = instructions.at(labels.at(i.linkedLabel));
88 qint8 *c =
reinterpret_cast<qint8*>(i.packed + i.offsetForJump);
89 int jumpOffset = linkedInstruction.position - (i.position + i.size);
92 Instr::Type type = Instr::unpack(i.packed);
93 if (Instr::isWide(type)) {
94 Q_ASSERT(i.offsetForJump == i.size - 4);
95 qToLittleEndian<qint32>(jumpOffset, c);
97 Q_ASSERT(i.offsetForJump == i.size - 1);
99 Q_ASSERT(o == jumpOffset);
105void BytecodeGenerator::compressInstructions()
109 for (
auto &i : instructions) {
110 i.position = position;
111 if (i.offsetForJump == -1)
120 for (
auto &i : instructions) {
121 i.position = position;
122 if (i.offsetForJump != -1)
131void BytecodeGenerator::finalize(Compiler::Context *context)
133 compressInstructions();
137 QVector<CompiledData::CodeOffsetToLineAndStatement> lineAndStatementNumbers;
140 currentStatement = -1;
143 for (qsizetype i = 0; i < instructions.size(); i++) {
144 if (instructions[i].line != currentLine || instructions[i].statement != currentStatement) {
145 currentLine = instructions[i].line;
146 currentStatement = instructions[i].statement;
147 CompiledData::CodeOffsetToLineAndStatement entry;
148 entry.codeOffset = code.size();
149 entry.line = currentLine;
150 entry.statement = currentStatement;
151 lineAndStatementNumbers.append(entry);
154 if (m_sourceLocationTable)
155 m_sourceLocationTable->entries[i].offset =
static_cast<quint32>(code.size());
157 code.append(
reinterpret_cast<
const char *>(instructions[i].packed), instructions[i].size);
160 context->code = code;
161 context->lineAndStatementNumberMapping = lineAndStatementNumbers;
162 context->sourceLocationTable = std::move(m_sourceLocationTable);
164 context->labelInfo.reserve(context->labelInfo.size() + _labelInfos.size());
165 for (
const auto &li : _labelInfos)
166 context->labelInfo.push_back(instructions.at(labels.at(li.labelIndex)).position);
169int BytecodeGenerator::addInstructionHelper(Instr::Type type,
const Instr &i,
int offsetOfOffset) {
170 if (lastInstrType ==
int(Instr::Type::StoreReg)) {
171 if (type == Instr::Type::LoadReg) {
172 if (i.LoadReg.reg == lastInstr.StoreReg.reg) {
177 if (type == Instr::Type::MoveReg) {
178 if (i.MoveReg.srcReg == lastInstr.StoreReg.reg) {
179 Instruction::StoreReg store;
180 store.reg = i.MoveReg.destReg;
181 addInstruction(store);
186 lastInstrType =
int(type);
189 if (debugMode && type != Instr::Type::Debug) {
191QT_WARNING_DISABLE_GCC(
"-Wmaybe-uninitialized")
192 if (instructions.isEmpty() || currentLine != instructions.constLast().line) {
193 addInstruction(Instruction::Debug());
194 }
else if (type == Instr::Type::Ret) {
195 currentLine = -currentLine;
196 addInstruction(Instruction::Debug());
197 currentLine = -currentLine;
198 currentSourceLocation = QQmlJS::SourceLocation();
203 const int pos = instructions.size();
205 const int argCount = Moth::InstrInfo::argumentCount[
static_cast<
int>(type)];
206 int s = argCount*
sizeof(
int);
207 if (offsetOfOffset != -1)
208 offsetOfOffset += Instr::encodedLength(type);
211 static_cast<
short>(s + Instr::encodedLength(type)),
219 uchar *code = instr.packed;
220 code = Instr::pack(code, Instr::wideInstructionType(type));
222 for (
int j = 0; j < argCount; ++j) {
223 qToLittleEndian<qint32>(i.argumentsAsInts[j], code);
227 instructions.append(instr);
228 if (m_sourceLocationTable)
229 m_sourceLocationTable->entries.append({ 0, currentSourceLocation });