ast.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. // Copyright 2019 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <functional>
  6. #include <list>
  7. #include <memory>
  8. #include <optional>
  9. #include <string>
  10. #include <unordered_map>
  11. #include <vector>
  12. #include "video_core/shader/expr.h"
  13. #include "video_core/shader/node.h"
  14. namespace VideoCommon::Shader {
  15. class ASTBase;
  16. class ASTProgram;
  17. class ASTIfThen;
  18. class ASTIfElse;
  19. class ASTBlockEncoded;
  20. class ASTBlockDecoded;
  21. class ASTVarSet;
  22. class ASTGoto;
  23. class ASTLabel;
  24. class ASTDoWhile;
  25. class ASTReturn;
  26. class ASTBreak;
  27. using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded,
  28. ASTVarSet, ASTGoto, ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>;
  29. using ASTNode = std::shared_ptr<ASTBase>;
  30. enum class ASTZipperType : u32 {
  31. Program,
  32. IfThen,
  33. IfElse,
  34. Loop,
  35. };
  36. class ASTZipper final {
  37. public:
  38. explicit ASTZipper();
  39. void Init(ASTNode first, ASTNode parent);
  40. ASTNode GetFirst() {
  41. return first;
  42. }
  43. ASTNode GetLast() {
  44. return last;
  45. }
  46. void PushBack(ASTNode new_node);
  47. void PushFront(ASTNode new_node);
  48. void InsertAfter(ASTNode new_node, ASTNode at_node);
  49. void InsertBefore(ASTNode new_node, ASTNode at_node);
  50. void DetachTail(ASTNode node);
  51. void DetachSingle(ASTNode node);
  52. void DetachSegment(ASTNode start, ASTNode end);
  53. void Remove(ASTNode node);
  54. ASTNode first{};
  55. ASTNode last{};
  56. };
  57. class ASTProgram {
  58. public:
  59. explicit ASTProgram() = default;
  60. ASTZipper nodes{};
  61. };
  62. class ASTIfThen {
  63. public:
  64. explicit ASTIfThen(Expr condition) : condition(condition) {}
  65. Expr condition;
  66. ASTZipper nodes{};
  67. };
  68. class ASTIfElse {
  69. public:
  70. explicit ASTIfElse() = default;
  71. ASTZipper nodes{};
  72. };
  73. class ASTBlockEncoded {
  74. public:
  75. explicit ASTBlockEncoded(u32 start, u32 end) : start{start}, end{end} {}
  76. u32 start;
  77. u32 end;
  78. };
  79. class ASTBlockDecoded {
  80. public:
  81. explicit ASTBlockDecoded(NodeBlock& new_nodes) : nodes(std::move(new_nodes)) {}
  82. NodeBlock nodes;
  83. };
  84. class ASTVarSet {
  85. public:
  86. explicit ASTVarSet(u32 index, Expr condition) : index{index}, condition{condition} {}
  87. u32 index;
  88. Expr condition;
  89. };
  90. class ASTLabel {
  91. public:
  92. explicit ASTLabel(u32 index) : index{index} {}
  93. u32 index;
  94. bool unused{};
  95. };
  96. class ASTGoto {
  97. public:
  98. explicit ASTGoto(Expr condition, u32 label) : condition{condition}, label{label} {}
  99. Expr condition;
  100. u32 label;
  101. };
  102. class ASTDoWhile {
  103. public:
  104. explicit ASTDoWhile(Expr condition) : condition(condition) {}
  105. Expr condition;
  106. ASTZipper nodes{};
  107. };
  108. class ASTReturn {
  109. public:
  110. explicit ASTReturn(Expr condition, bool kills) : condition{condition}, kills{kills} {}
  111. Expr condition;
  112. bool kills;
  113. };
  114. class ASTBreak {
  115. public:
  116. explicit ASTBreak(Expr condition) : condition{condition} {}
  117. Expr condition;
  118. };
  119. class ASTBase {
  120. public:
  121. explicit ASTBase(ASTNode parent, ASTData data) : parent{parent}, data{data} {}
  122. template <class U, class... Args>
  123. static ASTNode Make(ASTNode parent, Args&&... args) {
  124. return std::make_shared<ASTBase>(parent, ASTData(U(std::forward<Args>(args)...)));
  125. }
  126. void SetParent(ASTNode new_parent) {
  127. parent = new_parent;
  128. }
  129. ASTNode& GetParent() {
  130. return parent;
  131. }
  132. const ASTNode& GetParent() const {
  133. return parent;
  134. }
  135. u32 GetLevel() const {
  136. u32 level = 0;
  137. auto next_parent = parent;
  138. while (next_parent) {
  139. next_parent = next_parent->GetParent();
  140. level++;
  141. }
  142. return level;
  143. }
  144. ASTData* GetInnerData() {
  145. return &data;
  146. }
  147. ASTNode GetNext() const {
  148. return next;
  149. }
  150. ASTNode GetPrevious() const {
  151. return previous;
  152. }
  153. ASTZipper& GetManager() {
  154. return *manager;
  155. }
  156. std::optional<u32> GetGotoLabel() const {
  157. auto inner = std::get_if<ASTGoto>(&data);
  158. if (inner) {
  159. return {inner->label};
  160. }
  161. return {};
  162. }
  163. Expr GetGotoCondition() const {
  164. auto inner = std::get_if<ASTGoto>(&data);
  165. if (inner) {
  166. return inner->condition;
  167. }
  168. return nullptr;
  169. }
  170. void MarkLabelUnused() {
  171. auto inner = std::get_if<ASTLabel>(&data);
  172. if (inner) {
  173. inner->unused = true;
  174. }
  175. }
  176. bool IsLabelUnused() const {
  177. auto inner = std::get_if<ASTLabel>(&data);
  178. if (inner) {
  179. return inner->unused;
  180. }
  181. return true;
  182. }
  183. std::optional<u32> GetLabelIndex() const {
  184. auto inner = std::get_if<ASTLabel>(&data);
  185. if (inner) {
  186. return {inner->index};
  187. }
  188. return {};
  189. }
  190. Expr GetIfCondition() const {
  191. auto inner = std::get_if<ASTIfThen>(&data);
  192. if (inner) {
  193. return inner->condition;
  194. }
  195. return nullptr;
  196. }
  197. void SetGotoCondition(Expr new_condition) {
  198. auto inner = std::get_if<ASTGoto>(&data);
  199. if (inner) {
  200. inner->condition = new_condition;
  201. }
  202. }
  203. bool IsIfThen() const {
  204. return std::holds_alternative<ASTIfThen>(data);
  205. }
  206. bool IsIfElse() const {
  207. return std::holds_alternative<ASTIfElse>(data);
  208. }
  209. bool IsBlockEncoded() const {
  210. return std::holds_alternative<ASTBlockEncoded>(data);
  211. }
  212. void TransformBlockEncoded(NodeBlock& nodes) {
  213. data = ASTBlockDecoded(nodes);
  214. }
  215. bool IsLoop() const {
  216. return std::holds_alternative<ASTDoWhile>(data);
  217. }
  218. ASTZipper* GetSubNodes() {
  219. if (std::holds_alternative<ASTProgram>(data)) {
  220. return &std::get_if<ASTProgram>(&data)->nodes;
  221. }
  222. if (std::holds_alternative<ASTIfThen>(data)) {
  223. return &std::get_if<ASTIfThen>(&data)->nodes;
  224. }
  225. if (std::holds_alternative<ASTIfElse>(data)) {
  226. return &std::get_if<ASTIfElse>(&data)->nodes;
  227. }
  228. if (std::holds_alternative<ASTDoWhile>(data)) {
  229. return &std::get_if<ASTDoWhile>(&data)->nodes;
  230. }
  231. return nullptr;
  232. }
  233. void Clear() {
  234. next.reset();
  235. previous.reset();
  236. parent.reset();
  237. manager = nullptr;
  238. }
  239. private:
  240. friend class ASTZipper;
  241. ASTData data;
  242. ASTNode parent{};
  243. ASTNode next{};
  244. ASTNode previous{};
  245. ASTZipper* manager{};
  246. };
  247. class ASTManager final {
  248. public:
  249. ASTManager(bool full_decompile, bool disable_else_derivation);
  250. ~ASTManager();
  251. ASTManager(const ASTManager& o) = delete;
  252. ASTManager& operator=(const ASTManager& other) = delete;
  253. ASTManager(ASTManager&& other);
  254. ASTManager& operator=(ASTManager&& other);
  255. void Init();
  256. void DeclareLabel(u32 address);
  257. void InsertLabel(u32 address);
  258. void InsertGoto(Expr condition, u32 address);
  259. void InsertBlock(u32 start_address, u32 end_address);
  260. void InsertReturn(Expr condition, bool kills);
  261. std::string Print();
  262. void Decompile();
  263. void ShowCurrentState(std::string state);
  264. void SanityCheck();
  265. void Clear();
  266. bool IsFullyDecompiled() const {
  267. if (full_decompile) {
  268. return gotos.size() == 0;
  269. } else {
  270. for (ASTNode goto_node : gotos) {
  271. auto label_index = goto_node->GetGotoLabel();
  272. if (!label_index) {
  273. return false;
  274. }
  275. ASTNode glabel = labels[*label_index];
  276. if (IsBackwardsJump(goto_node, glabel)) {
  277. return false;
  278. }
  279. }
  280. return true;
  281. }
  282. }
  283. ASTNode GetProgram() const {
  284. return main_node;
  285. }
  286. u32 GetVariables() const {
  287. return variables;
  288. }
  289. const std::vector<ASTNode>& GetLabels() const {
  290. return labels;
  291. }
  292. private:
  293. bool IsBackwardsJump(ASTNode goto_node, ASTNode label_node) const;
  294. ASTNode CommonParent(ASTNode first, ASTNode second);
  295. bool IndirectlyRelated(ASTNode first, ASTNode second);
  296. bool DirectlyRelated(ASTNode first, ASTNode second);
  297. void EncloseDoWhile(ASTNode goto_node, ASTNode label);
  298. void EncloseIfThen(ASTNode goto_node, ASTNode label);
  299. void MoveOutward(ASTNode goto_node);
  300. u32 NewVariable() {
  301. return variables++;
  302. }
  303. bool full_decompile{};
  304. bool disable_else_derivation{};
  305. std::unordered_map<u32, u32> labels_map{};
  306. u32 labels_count{};
  307. std::vector<ASTNode> labels{};
  308. std::list<ASTNode> gotos{};
  309. u32 variables{};
  310. ASTProgram* program{};
  311. ASTNode main_node{};
  312. Expr false_condition{};
  313. };
  314. } // namespace VideoCommon::Shader