ir_emitter: Allow the insertion point for new instructions to be set

This commit is contained in:
MerryMage 2018-01-26 23:30:17 +00:00
parent af793c2527
commit e01b500aea
4 changed files with 33 additions and 5 deletions

View file

@ -21,6 +21,10 @@
namespace Dynarmic::IR { namespace Dynarmic::IR {
void Block::AppendNewInst(Opcode opcode, std::initializer_list<IR::Value> args) { void Block::AppendNewInst(Opcode opcode, std::initializer_list<IR::Value> args) {
PrependNewInst(end(), opcode, args);
}
Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, std::initializer_list<Value> args) {
IR::Inst* inst = new(instruction_alloc_pool->Alloc()) IR::Inst(opcode); IR::Inst* inst = new(instruction_alloc_pool->Alloc()) IR::Inst(opcode);
ASSERT(args.size() == inst->NumArgs()); ASSERT(args.size() == inst->NumArgs());
@ -29,7 +33,7 @@ void Block::AppendNewInst(Opcode opcode, std::initializer_list<IR::Value> args)
index++; index++;
}); });
instructions.push_back(inst); return instructions.insert_before(insertion_point, inst);
} }
LocationDescriptor Block::Location() const { LocationDescriptor Block::Location() const {

View file

@ -69,7 +69,7 @@ public:
const_reverse_iterator crend() const { return instructions.crend(); } 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. * handling any allocations necessary to do so.
* *
* @param op Opcode representing the instruction to add. * @param op Opcode representing the instruction to add.
@ -77,6 +77,17 @@ public:
*/ */
void AppendNewInst(Opcode op, std::initializer_list<Value> args); void AppendNewInst(Opcode op, std::initializer_list<Value> 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<Value> args);
/// Gets the starting location for this basic block. /// Gets the starting location for this basic block.
LocationDescriptor Location() const; LocationDescriptor Location() const;
/// Gets the end location for this basic block. /// Gets the end location for this basic block.

View file

@ -944,4 +944,12 @@ void IREmitter::SetTerm(const Terminal& terminal) {
block.SetTerminal(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 } // namespace Dynarmic::IR

View file

@ -55,7 +55,7 @@ struct ResultAndGE {
*/ */
class IREmitter { class IREmitter {
public: public:
explicit IREmitter(Block& block) : block(block) {} explicit IREmitter(Block& block) : block(block), insertion_point(block.end()) {}
Block& block; Block& block;
@ -247,11 +247,16 @@ public:
void SetTerm(const Terminal& terminal); void SetTerm(const Terminal& terminal);
void SetInsertionPoint(IR::Inst* new_insertion_point);
void SetInsertionPoint(IR::Block::iterator new_insertion_point);
protected: protected:
IR::Block::iterator insertion_point;
template<typename T = Value, typename ...Args> template<typename T = Value, typename ...Args>
T Inst(Opcode op, Args ...args) { T Inst(Opcode op, Args ...args) {
block.AppendNewInst(op, {Value(args)...}); auto iter = block.PrependNewInst(insertion_point, op, {Value(args)...});
return T(Value(&block.back())); return T(Value(&*iter));
} }
}; };