diff options
Diffstat (limited to 'src/shader_recompiler/backend/glasm/emit_glasm.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm.cpp | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 8e5d575a9..ad27b8b06 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp | |||
| @@ -39,14 +39,16 @@ struct Identity { | |||
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | template <bool scalar> | 41 | template <bool scalar> |
| 42 | struct RegWrapper { | 42 | class RegWrapper { |
| 43 | RegWrapper(EmitContext& ctx, Value value) | 43 | public: |
| 44 | : reg_alloc{ctx.reg_alloc}, allocated{value.type != Type::Register} { | 44 | RegWrapper(EmitContext& ctx, const IR::Value& ir_value) : reg_alloc{ctx.reg_alloc} { |
| 45 | if (allocated) { | 45 | const Value value{reg_alloc.Peek(ir_value)}; |
| 46 | if (value.type == Type::Register) { | ||
| 47 | inst = ir_value.InstRecursive(); | ||
| 48 | reg = Register{value}; | ||
| 49 | } else { | ||
| 46 | const bool is_long{value.type == Type::F64 || value.type == Type::U64}; | 50 | const bool is_long{value.type == Type::F64 || value.type == Type::U64}; |
| 47 | reg = is_long ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); | 51 | reg = is_long ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); |
| 48 | } else { | ||
| 49 | reg = Register{value}; | ||
| 50 | } | 52 | } |
| 51 | switch (value.type) { | 53 | switch (value.type) { |
| 52 | case Type::Register: | 54 | case Type::Register: |
| @@ -68,8 +70,11 @@ struct RegWrapper { | |||
| 68 | break; | 70 | break; |
| 69 | } | 71 | } |
| 70 | } | 72 | } |
| 73 | |||
| 71 | ~RegWrapper() { | 74 | ~RegWrapper() { |
| 72 | if (allocated) { | 75 | if (inst) { |
| 76 | reg_alloc.Unref(*inst); | ||
| 77 | } else { | ||
| 73 | reg_alloc.FreeReg(reg); | 78 | reg_alloc.FreeReg(reg); |
| 74 | } | 79 | } |
| 75 | } | 80 | } |
| @@ -78,19 +83,42 @@ struct RegWrapper { | |||
| 78 | return std::conditional_t<scalar, ScalarRegister, Register>{Value{reg}}; | 83 | return std::conditional_t<scalar, ScalarRegister, Register>{Value{reg}}; |
| 79 | } | 84 | } |
| 80 | 85 | ||
| 86 | private: | ||
| 81 | RegAlloc& reg_alloc; | 87 | RegAlloc& reg_alloc; |
| 88 | IR::Inst* inst{}; | ||
| 82 | Register reg{}; | 89 | Register reg{}; |
| 83 | bool allocated{}; | 90 | }; |
| 91 | |||
| 92 | template <typename ArgType> | ||
| 93 | class ValueWrapper { | ||
| 94 | public: | ||
| 95 | ValueWrapper(EmitContext& ctx, const IR::Value& ir_value_) | ||
| 96 | : reg_alloc{ctx.reg_alloc}, ir_value{ir_value_}, value{reg_alloc.Peek(ir_value)} {} | ||
| 97 | |||
| 98 | ~ValueWrapper() { | ||
| 99 | if (!ir_value.IsImmediate()) { | ||
| 100 | reg_alloc.Unref(*ir_value.InstRecursive()); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | ArgType Extract() { | ||
| 105 | return value; | ||
| 106 | } | ||
| 107 | |||
| 108 | private: | ||
| 109 | RegAlloc& reg_alloc; | ||
| 110 | const IR::Value& ir_value; | ||
| 111 | ArgType value; | ||
| 84 | }; | 112 | }; |
| 85 | 113 | ||
| 86 | template <typename ArgType> | 114 | template <typename ArgType> |
| 87 | auto Arg(EmitContext& ctx, const IR::Value& arg) { | 115 | auto Arg(EmitContext& ctx, const IR::Value& arg) { |
| 88 | if constexpr (std::is_same_v<ArgType, Register>) { | 116 | if constexpr (std::is_same_v<ArgType, Register>) { |
| 89 | return RegWrapper<false>{ctx, ctx.reg_alloc.Consume(arg)}; | 117 | return RegWrapper<false>{ctx, arg}; |
| 90 | } else if constexpr (std::is_same_v<ArgType, ScalarRegister>) { | 118 | } else if constexpr (std::is_same_v<ArgType, ScalarRegister>) { |
| 91 | return RegWrapper<true>{ctx, ctx.reg_alloc.Consume(arg)}; | 119 | return RegWrapper<true>{ctx, arg}; |
| 92 | } else if constexpr (std::is_base_of_v<Value, ArgType>) { | 120 | } else if constexpr (std::is_base_of_v<Value, ArgType>) { |
| 93 | return Identity{ArgType{ctx.reg_alloc.Consume(arg)}}; | 121 | return ValueWrapper<ArgType>{ctx, arg}; |
| 94 | } else if constexpr (std::is_same_v<ArgType, const IR::Value&>) { | 122 | } else if constexpr (std::is_same_v<ArgType, const IR::Value&>) { |
| 95 | return Identity{arg}; | 123 | return Identity{arg}; |
| 96 | } else if constexpr (std::is_same_v<ArgType, u32>) { | 124 | } else if constexpr (std::is_same_v<ArgType, u32>) { |