diff --git a/src/frontend/ir/basic_block.cpp b/src/frontend/ir/basic_block.cpp index b8bfa7e4..96bc7dd2 100644 --- a/src/frontend/ir/basic_block.cpp +++ b/src/frontend/ir/basic_block.cpp @@ -21,6 +21,10 @@ namespace Dynarmic::IR { void Block::AppendNewInst(Opcode opcode, std::initializer_list args) { + PrependNewInst(end(), opcode, args); +} + +Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, std::initializer_list args) { IR::Inst* inst = new(instruction_alloc_pool->Alloc()) IR::Inst(opcode); ASSERT(args.size() == inst->NumArgs()); @@ -29,7 +33,7 @@ void Block::AppendNewInst(Opcode opcode, std::initializer_list args) index++; }); - instructions.push_back(inst); + return instructions.insert_before(insertion_point, inst); } LocationDescriptor Block::Location() const { diff --git a/src/frontend/ir/basic_block.h b/src/frontend/ir/basic_block.h index 8dd15768..40a404d7 100644 --- a/src/frontend/ir/basic_block.h +++ b/src/frontend/ir/basic_block.h @@ -69,7 +69,7 @@ public: const_reverse_iterator crend() const { return instructions.crend(); } /** - * Appends a new instruction to this basic block, + * Appends a new instruction to the end of this basic block, * handling any allocations necessary to do so. * * @param op Opcode representing the instruction to add. @@ -77,6 +77,17 @@ public: */ void AppendNewInst(Opcode op, std::initializer_list args); + /** + * Prepends a new instruction to this basic block before the insertion point, + * handling any allocations necessary to do so. + * + * @param insertion_point Where to insert the new instruction. + * @param op Opcode representing the instruction to add. + * @param args A sequence of Value instances used as arguments for the instruction. + * @returns Iterator to the newly created instruction. + */ + iterator PrependNewInst(iterator insertion_point, Opcode op, std::initializer_list args); + /// Gets the starting location for this basic block. LocationDescriptor Location() const; /// Gets the end location for this basic block. diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 0b6b9eb3..d138c17c 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -944,4 +944,12 @@ void IREmitter::SetTerm(const Terminal& terminal) { block.SetTerminal(terminal); } +void IREmitter::SetInsertionPoint(IR::Inst* new_insertion_point) { + insertion_point = IR::Block::iterator{*new_insertion_point}; +} + +void IREmitter::SetInsertionPoint(IR::Block::iterator new_insertion_point) { + insertion_point = new_insertion_point; +} + } // namespace Dynarmic::IR diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 61b1edee..3c40d8fa 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -55,7 +55,7 @@ struct ResultAndGE { */ class IREmitter { public: - explicit IREmitter(Block& block) : block(block) {} + explicit IREmitter(Block& block) : block(block), insertion_point(block.end()) {} Block& block; @@ -247,11 +247,16 @@ public: void SetTerm(const Terminal& terminal); + void SetInsertionPoint(IR::Inst* new_insertion_point); + void SetInsertionPoint(IR::Block::iterator new_insertion_point); + protected: + IR::Block::iterator insertion_point; + template T Inst(Opcode op, Args ...args) { - block.AppendNewInst(op, {Value(args)...}); - return T(Value(&block.back())); + auto iter = block.PrependNewInst(insertion_point, op, {Value(args)...}); + return T(Value(&*iter)); } };