aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-06-13 10:06:03 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2017-06-19 13:36:00 +0000
commit5e9551ec5b1a782882f93310f8f07be51bb17bf7 (patch)
tree6db063718c5b6d602e2bc152a5a74843a5df16a1
parent4d329ef984d0f64b9446321ef63fc5a70cd103cd (diff)
Rework and implement Jump handling in the bytecode generator
Add Label and Jump classes to facilitate the handling, and resolve them to proper offsets at finalize() time. Change-Id: Ic140a3ceb848fb29657a1b156c97b806db6dc434 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp12
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h71
2 files changed, 70 insertions, 13 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp
index 71288b814c..0073cb4598 100644
--- a/src/qml/compiler/qv4bytecodegenerator.cpp
+++ b/src/qml/compiler/qv4bytecodegenerator.cpp
@@ -62,9 +62,21 @@ QByteArray BytecodeGenerator::finalize()
code.append(reinterpret_cast<const char *>(&push), InstrMeta<Instr::Push>::Size);
// content
+ QVector<int> instructionOffsets;
+ instructionOffsets.reserve(instructions.size());
for (const auto &i : qAsConst(instructions)) {
+ instructionOffsets.append(code.size());
code.append(reinterpret_cast<const char *>(&i.instr), i.size);
}
+ // resolve jumps
+ for (const auto &j : jumps) {
+ Q_ASSERT(j.linkedInstruction != -1);
+ int offset = instructionOffsets.at(j.instructionIndex) + j.offset;
+ char *c = code.data() + offset;
+ int linkedInstruction = instructionOffsets.at(j.linkedInstruction) - offset;
+ memcpy(c, &linkedInstruction, sizeof(int));
+ }
+
return code;
}
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h
index 7996374175..5c7480fc89 100644
--- a/src/qml/compiler/qv4bytecodegenerator_p.h
+++ b/src/qml/compiler/qv4bytecodegenerator_p.h
@@ -55,32 +55,61 @@ public:
BytecodeGenerator(IR::Function *function)
: function(function) {}
- struct CodeRef {
- int instructionIndex;
+ struct Label {
+ int index;
};
- struct Label {
- void link(CodeRef r) {
- linkedInstructions.append(r.instructionIndex);
+ struct Jump {
+ Jump(BytecodeGenerator *generator, int instruction, int offset)
+ : generator(generator),
+ index(generator->jumps.size())
+ {
+ generator->jumps.append({ instruction, offset, -1 });
}
+ BytecodeGenerator *generator;
int index;
- QVector<int> linkedInstructions;
+
+ void link() {
+ link(generator->label());
+ }
+ void link(Label l) {
+ Q_ASSERT(generator->jumps[index].linkedInstruction == -1);
+ generator->jumps[index].linkedInstruction = l.index;
+ }
};
Label label() {
- Label l;
- l.index = labels.size();
- return l;
+ return { instructions.size() };
}
template<int InstrT>
- CodeRef addInstruction(const InstrData<InstrT> &data)
+ void addInstruction(const InstrData<InstrT> &data)
{
Instr genericInstr;
genericInstr.common.instructionType = static_cast<Instr::Type>(InstrT);
InstrMeta<InstrT>::setDataNoCommon(genericInstr, data);
- return { addInstructionHelper(InstrMeta<InstrT>::Size, genericInstr) };
+ addInstructionHelper(InstrMeta<InstrT>::Size, genericInstr);
+ }
+
+ Q_REQUIRED_RESULT Jump addInstruction(const Instruction::Jump &data)
+ {
+ return addJumpInstruction(data);
+ }
+
+ Q_REQUIRED_RESULT Jump addInstruction(const Instruction::SetExceptionHandler &data)
+ {
+ return addJumpInstruction(data);
+ }
+
+ Q_REQUIRED_RESULT Jump addInstruction(const Instruction::JumpEq &data)
+ {
+ return addJumpInstruction(data);
+ }
+
+ Q_REQUIRED_RESULT Jump addInstruction(const Instruction::JumpNe &data)
+ {
+ return addJumpInstruction(data);
}
unsigned newTemp();
@@ -89,20 +118,36 @@ public:
QByteArray finalize();
private:
+ friend struct Jump;
+
+ template<int InstrT>
+ Jump addJumpInstruction(const InstrData<InstrT> &data)
+ {
+ Instr genericInstr;
+ genericInstr.common.instructionType = static_cast<Instr::Type>(InstrT);
+ InstrMeta<InstrT>::setDataNoCommon(genericInstr, data);
+ return Jump(this, addInstructionHelper(InstrMeta<InstrT>::Size, genericInstr), offsetof(InstrData<InstrT>, offset));
+ }
+
int addInstructionHelper(uint size, const Instr &i) {
int pos = instructions.size();
instructions.append({size, i});
return pos;
}
+ struct JumpData {
+ int instructionIndex;
+ int offset;
+ int linkedInstruction = -1;
+ };
+
struct I {
uint size;
Instr instr;
};
QVector<I> instructions;
-
- QVector<Label> labels;
+ QVector<JumpData> jumps;
IR::Function *function; // ### remove me at some point
};