value.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "shader_recompiler/frontend/ir/opcodes.h"
  5. #include "shader_recompiler/frontend/ir/value.h"
  6. namespace Shader::IR {
  7. Value::Value(IR::Inst* value) noexcept : type{Type::Opaque}, inst{value} {}
  8. Value::Value(IR::Block* value) noexcept : type{Type::Label}, label{value} {}
  9. Value::Value(IR::Reg value) noexcept : type{Type::Reg}, reg{value} {}
  10. Value::Value(IR::Pred value) noexcept : type{Type::Pred}, pred{value} {}
  11. Value::Value(IR::Attribute value) noexcept : type{Type::Attribute}, attribute{value} {}
  12. Value::Value(IR::Patch value) noexcept : type{Type::Patch}, patch{value} {}
  13. Value::Value(bool value) noexcept : type{Type::U1}, imm_u1{value} {}
  14. Value::Value(u8 value) noexcept : type{Type::U8}, imm_u8{value} {}
  15. Value::Value(u16 value) noexcept : type{Type::U16}, imm_u16{value} {}
  16. Value::Value(u32 value) noexcept : type{Type::U32}, imm_u32{value} {}
  17. Value::Value(f32 value) noexcept : type{Type::F32}, imm_f32{value} {}
  18. Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {}
  19. Value::Value(f64 value) noexcept : type{Type::F64}, imm_f64{value} {}
  20. bool Value::IsIdentity() const noexcept {
  21. return type == Type::Opaque && inst->GetOpcode() == Opcode::Identity;
  22. }
  23. bool Value::IsPhi() const noexcept {
  24. return type == Type::Opaque && inst->GetOpcode() == Opcode::Phi;
  25. }
  26. bool Value::IsEmpty() const noexcept {
  27. return type == Type::Void;
  28. }
  29. bool Value::IsImmediate() const noexcept {
  30. if (IsIdentity()) {
  31. return inst->Arg(0).IsImmediate();
  32. }
  33. return type != Type::Opaque;
  34. }
  35. bool Value::IsLabel() const noexcept {
  36. return type == Type::Label;
  37. }
  38. IR::Type Value::Type() const noexcept {
  39. if (IsPhi()) {
  40. // The type of a phi node is stored in its flags
  41. return inst->Flags<IR::Type>();
  42. }
  43. if (IsIdentity()) {
  44. return inst->Arg(0).Type();
  45. }
  46. if (type == Type::Opaque) {
  47. return inst->Type();
  48. }
  49. return type;
  50. }
  51. IR::Inst* Value::Inst() const {
  52. ValidateAccess(Type::Opaque);
  53. return inst;
  54. }
  55. IR::Block* Value::Label() const {
  56. ValidateAccess(Type::Label);
  57. return label;
  58. }
  59. IR::Inst* Value::InstRecursive() const {
  60. ValidateAccess(Type::Opaque);
  61. if (IsIdentity()) {
  62. return inst->Arg(0).InstRecursive();
  63. }
  64. return inst;
  65. }
  66. IR::Value Value::Resolve() const {
  67. if (IsIdentity()) {
  68. return inst->Arg(0).Resolve();
  69. }
  70. return *this;
  71. }
  72. IR::Reg Value::Reg() const {
  73. ValidateAccess(Type::Reg);
  74. return reg;
  75. }
  76. IR::Pred Value::Pred() const {
  77. ValidateAccess(Type::Pred);
  78. return pred;
  79. }
  80. IR::Attribute Value::Attribute() const {
  81. ValidateAccess(Type::Attribute);
  82. return attribute;
  83. }
  84. IR::Patch Value::Patch() const {
  85. ValidateAccess(Type::Patch);
  86. return patch;
  87. }
  88. bool Value::U1() const {
  89. if (IsIdentity()) {
  90. return inst->Arg(0).U1();
  91. }
  92. ValidateAccess(Type::U1);
  93. return imm_u1;
  94. }
  95. u8 Value::U8() const {
  96. if (IsIdentity()) {
  97. return inst->Arg(0).U8();
  98. }
  99. ValidateAccess(Type::U8);
  100. return imm_u8;
  101. }
  102. u16 Value::U16() const {
  103. if (IsIdentity()) {
  104. return inst->Arg(0).U16();
  105. }
  106. ValidateAccess(Type::U16);
  107. return imm_u16;
  108. }
  109. u32 Value::U32() const {
  110. if (IsIdentity()) {
  111. return inst->Arg(0).U32();
  112. }
  113. ValidateAccess(Type::U32);
  114. return imm_u32;
  115. }
  116. f32 Value::F32() const {
  117. if (IsIdentity()) {
  118. return inst->Arg(0).F32();
  119. }
  120. ValidateAccess(Type::F32);
  121. return imm_f32;
  122. }
  123. u64 Value::U64() const {
  124. if (IsIdentity()) {
  125. return inst->Arg(0).U64();
  126. }
  127. ValidateAccess(Type::U64);
  128. return imm_u64;
  129. }
  130. f64 Value::F64() const {
  131. if (IsIdentity()) {
  132. return inst->Arg(0).F64();
  133. }
  134. ValidateAccess(Type::F64);
  135. return imm_f64;
  136. }
  137. bool Value::operator==(const Value& other) const {
  138. if (type != other.type) {
  139. return false;
  140. }
  141. switch (type) {
  142. case Type::Void:
  143. return true;
  144. case Type::Opaque:
  145. return inst == other.inst;
  146. case Type::Label:
  147. return label == other.label;
  148. case Type::Reg:
  149. return reg == other.reg;
  150. case Type::Pred:
  151. return pred == other.pred;
  152. case Type::Attribute:
  153. return attribute == other.attribute;
  154. case Type::Patch:
  155. return patch == other.patch;
  156. case Type::U1:
  157. return imm_u1 == other.imm_u1;
  158. case Type::U8:
  159. return imm_u8 == other.imm_u8;
  160. case Type::U16:
  161. case Type::F16:
  162. return imm_u16 == other.imm_u16;
  163. case Type::U32:
  164. case Type::F32:
  165. return imm_u32 == other.imm_u32;
  166. case Type::U64:
  167. case Type::F64:
  168. return imm_u64 == other.imm_u64;
  169. case Type::U32x2:
  170. case Type::U32x3:
  171. case Type::U32x4:
  172. case Type::F16x2:
  173. case Type::F16x3:
  174. case Type::F16x4:
  175. case Type::F32x2:
  176. case Type::F32x3:
  177. case Type::F32x4:
  178. case Type::F64x2:
  179. case Type::F64x3:
  180. case Type::F64x4:
  181. break;
  182. }
  183. throw LogicError("Invalid type {}", type);
  184. }
  185. bool Value::operator!=(const Value& other) const {
  186. return !operator==(other);
  187. }
  188. void Value::ValidateAccess(IR::Type expected) const {
  189. if (type != expected) {
  190. throw LogicError("Reading {} out of {}", expected, type);
  191. }
  192. }
  193. } // namespace Shader::IR