5#include <private/qv4bytecodegenerator_p.h>
6#include <private/qv4compilercontext_p.h>
7#include <private/qqmljsastfwd_p.h>
13void BytecodeGenerator::setLocation(
const QQmlJS::SourceLocation &loc)
15 currentLine =
static_cast<
int>(loc.startLine);
16 currentSourceLocation = loc;
19void BytecodeGenerator::incrementStatement()
24int BytecodeGenerator::newRegister()
27 if (regCount < currentReg)
28 regCount = currentReg;
32int BytecodeGenerator::newRegisterArray(
int n)
36 if (regCount < currentReg)
37 regCount = currentReg;
41void BytecodeGenerator::packInstruction(I &i)
43 Instr::Type type = Instr::unpack(i.packed);
44 Q_ASSERT(
int(type) < MOTH_NUM_INSTRUCTIONS());
45 type = Instr::narrowInstructionType(type);
46 int instructionsAsInts[
sizeof(Instr)/
sizeof(
int)] = {};
47 int nMembers = Moth::InstrInfo::argumentCount[
static_cast<
int>(i.type)];
48 uchar *code = i.packed + Instr::encodedLength(type);
49 for (
int j = 0; j < nMembers; ++j) {
50 instructionsAsInts[j] = qFromLittleEndian<qint32>(code + j *
sizeof(
int));
56 for (
int n = 0; n < nMembers; ++n) {
57 if (width == Normal && (
static_cast<qint8>(instructionsAsInts[n]) != instructionsAsInts[n])) {
65 code = Instr::pack(code, type);
66 for (
int n = 0; n < nMembers; ++n) {
67 qint8 v =
static_cast<qint8>(instructionsAsInts[n]);
71 i.size = code - i.packed;
72 if (i.offsetForJump != -1)
73 i.offsetForJump = i.size - 1;
81void BytecodeGenerator::adjustJumpOffsets()
83 for (
int index = 0; index < instructions.size(); ++index) {
84 auto &i = instructions[index];
85 if (i.offsetForJump == -1)
87 Q_ASSERT(i.linkedLabel != -1 && labels.at(i.linkedLabel) != -1);
88 const auto &linkedInstruction = instructions.at(labels.at(i.linkedLabel));
89 qint8 *c =
reinterpret_cast<qint8*>(i.packed + i.offsetForJump);
90 int jumpOffset = linkedInstruction.position - (i.position + i.size);
93 Instr::Type type = Instr::unpack(i.packed);
94 if (Instr::isWide(type)) {
95 Q_ASSERT(i.offsetForJump == i.size - 4);
96 qToLittleEndian<qint32>(jumpOffset, c);
98 Q_ASSERT(i.offsetForJump == i.size - 1);
100 Q_ASSERT(o == jumpOffset);
106void BytecodeGenerator::compressInstructions()
110 for (
auto &i : instructions) {
111 i.position = position;
112 if (i.offsetForJump == -1)
121 for (
auto &i : instructions) {
122 i.position = position;
123 if (i.offsetForJump != -1)
132void BytecodeGenerator::finalize(Compiler::Context *context)
134 compressInstructions();
138 QList<CompiledData::CodeOffsetToLineAndStatement> lineAndStatementNumbers;
141 currentStatement = -1;
144 for (qsizetype i = 0; i < instructions.size(); i++) {
145 if (instructions[i].line != currentLine || instructions[i].statement != currentStatement) {
146 currentLine = instructions[i].line;
147 currentStatement = instructions[i].statement;
148 CompiledData::CodeOffsetToLineAndStatement entry;
149 entry.codeOffset = code.size();
150 entry.line = currentLine;
151 entry.statement = currentStatement;
152 lineAndStatementNumbers.append(entry);
155 if (m_sourceLocationTable)
156 m_sourceLocationTable->entries[i].offset =
static_cast<quint32>(code.size());
158 code.append(
reinterpret_cast<
const char *>(instructions[i].packed), instructions[i].size);
161 context->code = code;
162 context->lineAndStatementNumberMapping = lineAndStatementNumbers;
163 context->sourceLocationTable = std::move(m_sourceLocationTable);
165 context->labelInfo.reserve(context->labelInfo.size() + _labelInfos.size());
166 for (
const auto &li : _labelInfos)
167 context->labelInfo.push_back(instructions.at(labels.at(li.labelIndex)).position);
170int BytecodeGenerator::addInstructionHelper(Instr::Type type,
const Instr &i,
int offsetOfOffset) {
171 if (lastInstrType ==
int(Instr::Type::StoreReg)) {
172 if (type == Instr::Type::LoadReg) {
173 if (i.LoadReg.reg == lastInstr.StoreReg.reg) {
178 if (type == Instr::Type::MoveReg) {
179 if (i.MoveReg.srcReg == lastInstr.StoreReg.reg) {
180 Instruction::StoreReg store;
181 store.reg = i.MoveReg.destReg;
182 addInstruction(store);
187 lastInstrType =
int(type);
190 if (debugMode && type != Instr::Type::Debug) {
192QT_WARNING_DISABLE_GCC(
"-Wmaybe-uninitialized")
193 if (instructions.isEmpty() || currentLine != instructions.constLast().line) {
194 addInstruction(Instruction::Debug());
195 }
else if (type == Instr::Type::Ret) {
196 currentLine = -currentLine;
197 addInstruction(Instruction::Debug());
198 currentLine = -currentLine;
199 currentSourceLocation = QQmlJS::SourceLocation();
204 const int pos = instructions.size();
206 const int argCount = Moth::InstrInfo::argumentCount[
static_cast<
int>(type)];
207 int s = argCount*
sizeof(
int);
208 if (offsetOfOffset != -1)
209 offsetOfOffset += Instr::encodedLength(type);
212 static_cast<
short>(s + Instr::encodedLength(type)),
220 uchar *code = instr.packed;
221 code = Instr::pack(code, Instr::wideInstructionType(type));
223 for (
int j = 0; j < argCount; ++j) {
224 qToLittleEndian<qint32>(i.argumentsAsInts[j], code);
228 instructions.append(instr);
229 if (m_sourceLocationTable)
230 m_sourceLocationTable->entries.append({ 0, currentSourceLocation });