From c892359d1bf228d3c119c953c20fff44f280a7c4 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 25 Jul 2021 21:34:17 -0300
Subject: shader: Add copy constructor to instructions

---
 src/shader_recompiler/frontend/ir/basic_block.cpp      |  5 +++++
 src/shader_recompiler/frontend/ir/basic_block.h        |  3 +++
 src/shader_recompiler/frontend/ir/microinstruction.cpp | 11 +++++++++++
 src/shader_recompiler/frontend/ir/value.h              |  2 +-
 4 files changed, 20 insertions(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/shader_recompiler/frontend/ir/basic_block.cpp b/src/shader_recompiler/frontend/ir/basic_block.cpp
index 7c08b25ce2..974efa4a06 100644
--- a/src/shader_recompiler/frontend/ir/basic_block.cpp
+++ b/src/shader_recompiler/frontend/ir/basic_block.cpp
@@ -22,6 +22,11 @@ void Block::AppendNewInst(Opcode op, std::initializer_list<Value> args) {
     PrependNewInst(end(), op, args);
 }
 
+Block::iterator Block::PrependNewInst(iterator insertion_point, const Inst& base_inst) {
+    Inst* const inst{inst_pool->Create(base_inst)};
+    return instructions.insert(insertion_point, *inst);
+}
+
 Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op,
                                       std::initializer_list<Value> args, u32 flags) {
     Inst* const inst{inst_pool->Create(op, flags)};
diff --git a/src/shader_recompiler/frontend/ir/basic_block.h b/src/shader_recompiler/frontend/ir/basic_block.h
index 9ce1ed07ed..fbfe98266a 100644
--- a/src/shader_recompiler/frontend/ir/basic_block.h
+++ b/src/shader_recompiler/frontend/ir/basic_block.h
@@ -40,6 +40,9 @@ public:
     /// Appends a new instruction to the end of this basic block.
     void AppendNewInst(Opcode op, std::initializer_list<Value> args);
 
+    /// Prepends a copy of an instruction to this basic block before the insertion point.
+    iterator PrependNewInst(iterator insertion_point, const Inst& base_inst);
+
     /// Prepends a new instruction to this basic block before the insertion point.
     iterator PrependNewInst(iterator insertion_point, Opcode op,
                             std::initializer_list<Value> args = {}, u32 flags = 0);
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 30b470bdd3..97e2bf6af4 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -47,6 +47,17 @@ Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} {
     }
 }
 
+Inst::Inst(const Inst& base) : op{base.op}, flags{base.flags} {
+    if (base.op == Opcode::Phi) {
+        throw NotImplementedException("Copying phi node");
+    }
+    std::construct_at(&args);
+    const size_t num_args{base.NumArgs()};
+    for (size_t index = 0; index < num_args; ++index) {
+        SetArg(index, base.Arg(index));
+    }
+}
+
 Inst::~Inst() {
     if (op == Opcode::Phi) {
         std::destroy_at(&phi_args);
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 6c9ef6bdd6..9475798524 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -116,10 +116,10 @@ public:
 class Inst : public boost::intrusive::list_base_hook<> {
 public:
     explicit Inst(IR::Opcode op_, u32 flags_) noexcept;
+    explicit Inst(const Inst& base);
     ~Inst();
 
     Inst& operator=(const Inst&) = delete;
-    Inst(const Inst&) = delete;
 
     Inst& operator=(Inst&&) = delete;
     Inst(Inst&&) = delete;
-- 
cgit v1.2.3-70-g09d2