ast.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. // Copyright 2019 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <string>
  5. #include <string_view>
  6. #include <fmt/format.h>
  7. #include "common/assert.h"
  8. #include "common/common_types.h"
  9. #include "video_core/shader/ast.h"
  10. #include "video_core/shader/expr.h"
  11. namespace VideoCommon::Shader {
  12. ASTZipper::ASTZipper() = default;
  13. void ASTZipper::Init(const ASTNode new_first, const ASTNode parent) {
  14. ASSERT(new_first->manager == nullptr);
  15. first = new_first;
  16. last = new_first;
  17. ASTNode current = first;
  18. while (current) {
  19. current->manager = this;
  20. current->parent = parent;
  21. last = current;
  22. current = current->next;
  23. }
  24. }
  25. void ASTZipper::PushBack(const ASTNode new_node) {
  26. ASSERT(new_node->manager == nullptr);
  27. new_node->previous = last;
  28. if (last) {
  29. last->next = new_node;
  30. }
  31. new_node->next.reset();
  32. last = new_node;
  33. if (!first) {
  34. first = new_node;
  35. }
  36. new_node->manager = this;
  37. }
  38. void ASTZipper::PushFront(const ASTNode new_node) {
  39. ASSERT(new_node->manager == nullptr);
  40. new_node->previous.reset();
  41. new_node->next = first;
  42. if (first) {
  43. first->previous = new_node;
  44. }
  45. if (last == first) {
  46. last = new_node;
  47. }
  48. first = new_node;
  49. new_node->manager = this;
  50. }
  51. void ASTZipper::InsertAfter(const ASTNode new_node, const ASTNode at_node) {
  52. ASSERT(new_node->manager == nullptr);
  53. if (!at_node) {
  54. PushFront(new_node);
  55. return;
  56. }
  57. const ASTNode next = at_node->next;
  58. if (next) {
  59. next->previous = new_node;
  60. }
  61. new_node->previous = at_node;
  62. if (at_node == last) {
  63. last = new_node;
  64. }
  65. new_node->next = next;
  66. at_node->next = new_node;
  67. new_node->manager = this;
  68. }
  69. void ASTZipper::InsertBefore(const ASTNode new_node, const ASTNode at_node) {
  70. ASSERT(new_node->manager == nullptr);
  71. if (!at_node) {
  72. PushBack(new_node);
  73. return;
  74. }
  75. const ASTNode previous = at_node->previous;
  76. if (previous) {
  77. previous->next = new_node;
  78. }
  79. new_node->next = at_node;
  80. if (at_node == first) {
  81. first = new_node;
  82. }
  83. new_node->previous = previous;
  84. at_node->previous = new_node;
  85. new_node->manager = this;
  86. }
  87. void ASTZipper::DetachTail(ASTNode node) {
  88. ASSERT(node->manager == this);
  89. if (node == first) {
  90. first.reset();
  91. last.reset();
  92. return;
  93. }
  94. last = node->previous;
  95. last->next.reset();
  96. node->previous.reset();
  97. ASTNode current = std::move(node);
  98. while (current) {
  99. current->manager = nullptr;
  100. current->parent.reset();
  101. current = current->next;
  102. }
  103. }
  104. void ASTZipper::DetachSegment(const ASTNode start, const ASTNode end) {
  105. ASSERT(start->manager == this && end->manager == this);
  106. if (start == end) {
  107. DetachSingle(start);
  108. return;
  109. }
  110. const ASTNode prev = start->previous;
  111. const ASTNode post = end->next;
  112. if (!prev) {
  113. first = post;
  114. } else {
  115. prev->next = post;
  116. }
  117. if (!post) {
  118. last = prev;
  119. } else {
  120. post->previous = prev;
  121. }
  122. start->previous.reset();
  123. end->next.reset();
  124. ASTNode current = start;
  125. bool found = false;
  126. while (current) {
  127. current->manager = nullptr;
  128. current->parent.reset();
  129. found |= current == end;
  130. current = current->next;
  131. }
  132. ASSERT(found);
  133. }
  134. void ASTZipper::DetachSingle(const ASTNode node) {
  135. ASSERT(node->manager == this);
  136. const ASTNode prev = node->previous;
  137. const ASTNode post = node->next;
  138. node->previous.reset();
  139. node->next.reset();
  140. if (!prev) {
  141. first = post;
  142. } else {
  143. prev->next = post;
  144. }
  145. if (!post) {
  146. last = prev;
  147. } else {
  148. post->previous = prev;
  149. }
  150. node->manager = nullptr;
  151. node->parent.reset();
  152. }
  153. void ASTZipper::Remove(const ASTNode node) {
  154. ASSERT(node->manager == this);
  155. const ASTNode next = node->next;
  156. const ASTNode previous = node->previous;
  157. if (previous) {
  158. previous->next = next;
  159. }
  160. if (next) {
  161. next->previous = previous;
  162. }
  163. node->parent.reset();
  164. node->manager = nullptr;
  165. if (node == last) {
  166. last = previous;
  167. }
  168. if (node == first) {
  169. first = next;
  170. }
  171. }
  172. class ExprPrinter final {
  173. public:
  174. void operator()(const ExprAnd& expr) {
  175. inner += "( ";
  176. std::visit(*this, *expr.operand1);
  177. inner += " && ";
  178. std::visit(*this, *expr.operand2);
  179. inner += ')';
  180. }
  181. void operator()(const ExprOr& expr) {
  182. inner += "( ";
  183. std::visit(*this, *expr.operand1);
  184. inner += " || ";
  185. std::visit(*this, *expr.operand2);
  186. inner += ')';
  187. }
  188. void operator()(const ExprNot& expr) {
  189. inner += "!";
  190. std::visit(*this, *expr.operand1);
  191. }
  192. void operator()(const ExprPredicate& expr) {
  193. inner += "P" + std::to_string(expr.predicate);
  194. }
  195. void operator()(const ExprCondCode& expr) {
  196. u32 cc = static_cast<u32>(expr.cc);
  197. inner += "CC" + std::to_string(cc);
  198. }
  199. void operator()(const ExprVar& expr) {
  200. inner += "V" + std::to_string(expr.var_index);
  201. }
  202. void operator()(const ExprBoolean& expr) {
  203. inner += expr.value ? "true" : "false";
  204. }
  205. void operator()(const ExprGprEqual& expr) {
  206. inner += "( gpr_" + std::to_string(expr.gpr) + " == " + std::to_string(expr.value) + ')';
  207. }
  208. const std::string& GetResult() const {
  209. return inner;
  210. }
  211. private:
  212. std::string inner;
  213. };
  214. class ASTPrinter {
  215. public:
  216. void operator()(const ASTProgram& ast) {
  217. scope++;
  218. inner += "program {\n";
  219. ASTNode current = ast.nodes.GetFirst();
  220. while (current) {
  221. Visit(current);
  222. current = current->GetNext();
  223. }
  224. inner += "}\n";
  225. scope--;
  226. }
  227. void operator()(const ASTIfThen& ast) {
  228. ExprPrinter expr_parser{};
  229. std::visit(expr_parser, *ast.condition);
  230. inner += fmt::format("{}if ({}) {{\n", Indent(), expr_parser.GetResult());
  231. scope++;
  232. ASTNode current = ast.nodes.GetFirst();
  233. while (current) {
  234. Visit(current);
  235. current = current->GetNext();
  236. }
  237. scope--;
  238. inner += fmt::format("{}}}\n", Indent());
  239. }
  240. void operator()(const ASTIfElse& ast) {
  241. inner += Indent();
  242. inner += "else {\n";
  243. scope++;
  244. ASTNode current = ast.nodes.GetFirst();
  245. while (current) {
  246. Visit(current);
  247. current = current->GetNext();
  248. }
  249. scope--;
  250. inner += Indent();
  251. inner += "}\n";
  252. }
  253. void operator()(const ASTBlockEncoded& ast) {
  254. inner += fmt::format("{}Block({}, {});\n", Indent(), ast.start, ast.end);
  255. }
  256. void operator()([[maybe_unused]] const ASTBlockDecoded& ast) {
  257. inner += Indent();
  258. inner += "Block;\n";
  259. }
  260. void operator()(const ASTVarSet& ast) {
  261. ExprPrinter expr_parser{};
  262. std::visit(expr_parser, *ast.condition);
  263. inner += fmt::format("{}V{} := {};\n", Indent(), ast.index, expr_parser.GetResult());
  264. }
  265. void operator()(const ASTLabel& ast) {
  266. inner += fmt::format("Label_{}:\n", ast.index);
  267. }
  268. void operator()(const ASTGoto& ast) {
  269. ExprPrinter expr_parser{};
  270. std::visit(expr_parser, *ast.condition);
  271. inner +=
  272. fmt::format("{}({}) -> goto Label_{};\n", Indent(), expr_parser.GetResult(), ast.label);
  273. }
  274. void operator()(const ASTDoWhile& ast) {
  275. ExprPrinter expr_parser{};
  276. std::visit(expr_parser, *ast.condition);
  277. inner += fmt::format("{}do {{\n", Indent());
  278. scope++;
  279. ASTNode current = ast.nodes.GetFirst();
  280. while (current) {
  281. Visit(current);
  282. current = current->GetNext();
  283. }
  284. scope--;
  285. inner += fmt::format("{}}} while ({});\n", Indent(), expr_parser.GetResult());
  286. }
  287. void operator()(const ASTReturn& ast) {
  288. ExprPrinter expr_parser{};
  289. std::visit(expr_parser, *ast.condition);
  290. inner += fmt::format("{}({}) -> {};\n", Indent(), expr_parser.GetResult(),
  291. ast.kills ? "discard" : "exit");
  292. }
  293. void operator()(const ASTBreak& ast) {
  294. ExprPrinter expr_parser{};
  295. std::visit(expr_parser, *ast.condition);
  296. inner += fmt::format("{}({}) -> break;\n", Indent(), expr_parser.GetResult());
  297. }
  298. void Visit(const ASTNode& node) {
  299. std::visit(*this, *node->GetInnerData());
  300. }
  301. const std::string& GetResult() const {
  302. return inner;
  303. }
  304. private:
  305. std::string_view Indent() {
  306. if (space_segment_scope == scope) {
  307. return space_segment;
  308. }
  309. // Ensure that we don't exceed our view.
  310. ASSERT(scope * 2 < spaces.size());
  311. space_segment = spaces.substr(0, scope * 2);
  312. space_segment_scope = scope;
  313. return space_segment;
  314. }
  315. std::string inner{};
  316. std::string_view space_segment;
  317. u32 scope{};
  318. u32 space_segment_scope{};
  319. static constexpr std::string_view spaces{" "};
  320. };
  321. std::string ASTManager::Print() const {
  322. ASTPrinter printer{};
  323. printer.Visit(main_node);
  324. return printer.GetResult();
  325. }
  326. ASTManager::ASTManager(bool full_decompile, bool disable_else_derivation)
  327. : full_decompile{full_decompile}, disable_else_derivation{disable_else_derivation} {};
  328. ASTManager::~ASTManager() {
  329. Clear();
  330. }
  331. void ASTManager::Init() {
  332. main_node = ASTBase::Make<ASTProgram>(ASTNode{});
  333. program = std::get_if<ASTProgram>(main_node->GetInnerData());
  334. false_condition = MakeExpr<ExprBoolean>(false);
  335. }
  336. void ASTManager::DeclareLabel(u32 address) {
  337. const auto pair = labels_map.emplace(address, labels_count);
  338. if (pair.second) {
  339. labels_count++;
  340. labels.resize(labels_count);
  341. }
  342. }
  343. void ASTManager::InsertLabel(u32 address) {
  344. const u32 index = labels_map[address];
  345. const ASTNode label = ASTBase::Make<ASTLabel>(main_node, index);
  346. labels[index] = label;
  347. program->nodes.PushBack(label);
  348. }
  349. void ASTManager::InsertGoto(Expr condition, u32 address) {
  350. const u32 index = labels_map[address];
  351. const ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, std::move(condition), index);
  352. gotos.push_back(goto_node);
  353. program->nodes.PushBack(goto_node);
  354. }
  355. void ASTManager::InsertBlock(u32 start_address, u32 end_address) {
  356. ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address);
  357. program->nodes.PushBack(std::move(block));
  358. }
  359. void ASTManager::InsertReturn(Expr condition, bool kills) {
  360. ASTNode node = ASTBase::Make<ASTReturn>(main_node, std::move(condition), kills);
  361. program->nodes.PushBack(std::move(node));
  362. }
  363. // The decompile algorithm is based on
  364. // "Taming control flow: A structured approach to eliminating goto statements"
  365. // by AM Erosa, LJ Hendren 1994. In general, the idea is to get gotos to be
  366. // on the same structured level as the label which they jump to. This is done,
  367. // through outward/inward movements and lifting. Once they are at the same
  368. // level, you can enclose them in an "if" structure or a "do-while" structure.
  369. void ASTManager::Decompile() {
  370. auto it = gotos.begin();
  371. while (it != gotos.end()) {
  372. const ASTNode goto_node = *it;
  373. const auto label_index = goto_node->GetGotoLabel();
  374. if (!label_index) {
  375. return;
  376. }
  377. const ASTNode label = labels[*label_index];
  378. if (!full_decompile) {
  379. // We only decompile backward jumps
  380. if (!IsBackwardsJump(goto_node, label)) {
  381. it++;
  382. continue;
  383. }
  384. }
  385. if (IndirectlyRelated(goto_node, label)) {
  386. while (!DirectlyRelated(goto_node, label)) {
  387. MoveOutward(goto_node);
  388. }
  389. }
  390. if (DirectlyRelated(goto_node, label)) {
  391. u32 goto_level = goto_node->GetLevel();
  392. const u32 label_level = label->GetLevel();
  393. while (label_level < goto_level) {
  394. MoveOutward(goto_node);
  395. goto_level--;
  396. }
  397. // TODO(Blinkhawk): Implement Lifting and Inward Movements
  398. }
  399. if (label->GetParent() == goto_node->GetParent()) {
  400. bool is_loop = false;
  401. ASTNode current = goto_node->GetPrevious();
  402. while (current) {
  403. if (current == label) {
  404. is_loop = true;
  405. break;
  406. }
  407. current = current->GetPrevious();
  408. }
  409. if (is_loop) {
  410. EncloseDoWhile(goto_node, label);
  411. } else {
  412. EncloseIfThen(goto_node, label);
  413. }
  414. it = gotos.erase(it);
  415. continue;
  416. }
  417. it++;
  418. }
  419. if (full_decompile) {
  420. for (const ASTNode& label : labels) {
  421. auto& manager = label->GetManager();
  422. manager.Remove(label);
  423. }
  424. labels.clear();
  425. } else {
  426. auto label_it = labels.begin();
  427. while (label_it != labels.end()) {
  428. bool can_remove = true;
  429. ASTNode label = *label_it;
  430. for (const ASTNode& goto_node : gotos) {
  431. const auto label_index = goto_node->GetGotoLabel();
  432. if (!label_index) {
  433. return;
  434. }
  435. ASTNode& glabel = labels[*label_index];
  436. if (glabel == label) {
  437. can_remove = false;
  438. break;
  439. }
  440. }
  441. if (can_remove) {
  442. label->MarkLabelUnused();
  443. }
  444. }
  445. }
  446. }
  447. bool ASTManager::IsBackwardsJump(ASTNode goto_node, ASTNode label_node) const {
  448. u32 goto_level = goto_node->GetLevel();
  449. u32 label_level = label_node->GetLevel();
  450. while (goto_level > label_level) {
  451. goto_level--;
  452. goto_node = goto_node->GetParent();
  453. }
  454. while (label_level > goto_level) {
  455. label_level--;
  456. label_node = label_node->GetParent();
  457. }
  458. while (goto_node->GetParent() != label_node->GetParent()) {
  459. goto_node = goto_node->GetParent();
  460. label_node = label_node->GetParent();
  461. }
  462. ASTNode current = goto_node->GetPrevious();
  463. while (current) {
  464. if (current == label_node) {
  465. return true;
  466. }
  467. current = current->GetPrevious();
  468. }
  469. return false;
  470. }
  471. bool ASTManager::IndirectlyRelated(const ASTNode& first, const ASTNode& second) const {
  472. return !(first->GetParent() == second->GetParent() || DirectlyRelated(first, second));
  473. }
  474. bool ASTManager::DirectlyRelated(const ASTNode& first, const ASTNode& second) const {
  475. if (first->GetParent() == second->GetParent()) {
  476. return false;
  477. }
  478. const u32 first_level = first->GetLevel();
  479. const u32 second_level = second->GetLevel();
  480. u32 min_level;
  481. u32 max_level;
  482. ASTNode max;
  483. ASTNode min;
  484. if (first_level > second_level) {
  485. min_level = second_level;
  486. min = second;
  487. max_level = first_level;
  488. max = first;
  489. } else {
  490. min_level = first_level;
  491. min = first;
  492. max_level = second_level;
  493. max = second;
  494. }
  495. while (max_level > min_level) {
  496. max_level--;
  497. max = max->GetParent();
  498. }
  499. return min->GetParent() == max->GetParent();
  500. }
  501. void ASTManager::ShowCurrentState(std::string_view state) const {
  502. LOG_CRITICAL(HW_GPU, "\nState {}:\n\n{}\n", state, Print());
  503. SanityCheck();
  504. }
  505. void ASTManager::SanityCheck() const {
  506. for (const auto& label : labels) {
  507. if (!label->GetParent()) {
  508. LOG_CRITICAL(HW_GPU, "Sanity Check Failed");
  509. }
  510. }
  511. }
  512. void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) {
  513. ASTZipper& zipper = goto_node->GetManager();
  514. const ASTNode loop_start = label->GetNext();
  515. if (loop_start == goto_node) {
  516. zipper.Remove(goto_node);
  517. return;
  518. }
  519. const ASTNode parent = label->GetParent();
  520. const Expr condition = goto_node->GetGotoCondition();
  521. zipper.DetachSegment(loop_start, goto_node);
  522. const ASTNode do_while_node = ASTBase::Make<ASTDoWhile>(parent, condition);
  523. ASTZipper* sub_zipper = do_while_node->GetSubNodes();
  524. sub_zipper->Init(loop_start, do_while_node);
  525. zipper.InsertAfter(do_while_node, label);
  526. sub_zipper->Remove(goto_node);
  527. }
  528. void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) {
  529. ASTZipper& zipper = goto_node->GetManager();
  530. const ASTNode if_end = label->GetPrevious();
  531. if (if_end == goto_node) {
  532. zipper.Remove(goto_node);
  533. return;
  534. }
  535. const ASTNode prev = goto_node->GetPrevious();
  536. const Expr condition = goto_node->GetGotoCondition();
  537. bool do_else = false;
  538. if (!disable_else_derivation && prev->IsIfThen()) {
  539. const Expr if_condition = prev->GetIfCondition();
  540. do_else = ExprAreEqual(if_condition, condition);
  541. }
  542. const ASTNode parent = label->GetParent();
  543. zipper.DetachSegment(goto_node, if_end);
  544. ASTNode if_node;
  545. if (do_else) {
  546. if_node = ASTBase::Make<ASTIfElse>(parent);
  547. } else {
  548. Expr neg_condition = MakeExprNot(condition);
  549. if_node = ASTBase::Make<ASTIfThen>(parent, neg_condition);
  550. }
  551. ASTZipper* sub_zipper = if_node->GetSubNodes();
  552. sub_zipper->Init(goto_node, if_node);
  553. zipper.InsertAfter(if_node, prev);
  554. sub_zipper->Remove(goto_node);
  555. }
  556. void ASTManager::MoveOutward(ASTNode goto_node) {
  557. ASTZipper& zipper = goto_node->GetManager();
  558. const ASTNode parent = goto_node->GetParent();
  559. ASTZipper& zipper2 = parent->GetManager();
  560. const ASTNode grandpa = parent->GetParent();
  561. const bool is_loop = parent->IsLoop();
  562. const bool is_else = parent->IsIfElse();
  563. const bool is_if = parent->IsIfThen();
  564. const ASTNode prev = goto_node->GetPrevious();
  565. const ASTNode post = goto_node->GetNext();
  566. const Expr condition = goto_node->GetGotoCondition();
  567. zipper.DetachSingle(goto_node);
  568. if (is_loop) {
  569. const u32 var_index = NewVariable();
  570. const Expr var_condition = MakeExpr<ExprVar>(var_index);
  571. const ASTNode var_node = ASTBase::Make<ASTVarSet>(parent, var_index, condition);
  572. const ASTNode var_node_init = ASTBase::Make<ASTVarSet>(parent, var_index, false_condition);
  573. zipper2.InsertBefore(var_node_init, parent);
  574. zipper.InsertAfter(var_node, prev);
  575. goto_node->SetGotoCondition(var_condition);
  576. const ASTNode break_node = ASTBase::Make<ASTBreak>(parent, var_condition);
  577. zipper.InsertAfter(break_node, var_node);
  578. } else if (is_if || is_else) {
  579. const u32 var_index = NewVariable();
  580. const Expr var_condition = MakeExpr<ExprVar>(var_index);
  581. const ASTNode var_node = ASTBase::Make<ASTVarSet>(parent, var_index, condition);
  582. const ASTNode var_node_init = ASTBase::Make<ASTVarSet>(parent, var_index, false_condition);
  583. if (is_if) {
  584. zipper2.InsertBefore(var_node_init, parent);
  585. } else {
  586. zipper2.InsertBefore(var_node_init, parent->GetPrevious());
  587. }
  588. zipper.InsertAfter(var_node, prev);
  589. goto_node->SetGotoCondition(var_condition);
  590. if (post) {
  591. zipper.DetachTail(post);
  592. const ASTNode if_node = ASTBase::Make<ASTIfThen>(parent, MakeExprNot(var_condition));
  593. ASTZipper* sub_zipper = if_node->GetSubNodes();
  594. sub_zipper->Init(post, if_node);
  595. zipper.InsertAfter(if_node, var_node);
  596. }
  597. } else {
  598. UNREACHABLE();
  599. }
  600. const ASTNode next = parent->GetNext();
  601. if (is_if && next && next->IsIfElse()) {
  602. zipper2.InsertAfter(goto_node, next);
  603. goto_node->SetParent(grandpa);
  604. return;
  605. }
  606. zipper2.InsertAfter(goto_node, parent);
  607. goto_node->SetParent(grandpa);
  608. }
  609. class ASTClearer {
  610. public:
  611. ASTClearer() = default;
  612. void operator()(const ASTProgram& ast) {
  613. ASTNode current = ast.nodes.GetFirst();
  614. while (current) {
  615. Visit(current);
  616. current = current->GetNext();
  617. }
  618. }
  619. void operator()(const ASTIfThen& ast) {
  620. ASTNode current = ast.nodes.GetFirst();
  621. while (current) {
  622. Visit(current);
  623. current = current->GetNext();
  624. }
  625. }
  626. void operator()(const ASTIfElse& ast) {
  627. ASTNode current = ast.nodes.GetFirst();
  628. while (current) {
  629. Visit(current);
  630. current = current->GetNext();
  631. }
  632. }
  633. void operator()([[maybe_unused]] const ASTBlockEncoded& ast) {}
  634. void operator()(ASTBlockDecoded& ast) {
  635. ast.nodes.clear();
  636. }
  637. void operator()([[maybe_unused]] const ASTVarSet& ast) {}
  638. void operator()([[maybe_unused]] const ASTLabel& ast) {}
  639. void operator()([[maybe_unused]] const ASTGoto& ast) {}
  640. void operator()(const ASTDoWhile& ast) {
  641. ASTNode current = ast.nodes.GetFirst();
  642. while (current) {
  643. Visit(current);
  644. current = current->GetNext();
  645. }
  646. }
  647. void operator()([[maybe_unused]] const ASTReturn& ast) {}
  648. void operator()([[maybe_unused]] const ASTBreak& ast) {}
  649. void Visit(const ASTNode& node) {
  650. std::visit(*this, *node->GetInnerData());
  651. node->Clear();
  652. }
  653. };
  654. void ASTManager::Clear() {
  655. if (!main_node) {
  656. return;
  657. }
  658. ASTClearer clearer{};
  659. clearer.Visit(main_node);
  660. main_node.reset();
  661. program = nullptr;
  662. labels_map.clear();
  663. labels.clear();
  664. gotos.clear();
  665. }
  666. } // namespace VideoCommon::Shader