diff options
Diffstat (limited to 'src/video_core/shader/ast.cpp')
| -rw-r--r-- | src/video_core/shader/ast.cpp | 139 |
1 files changed, 136 insertions, 3 deletions
diff --git a/src/video_core/shader/ast.cpp b/src/video_core/shader/ast.cpp index d521a7b52..0bf289f98 100644 --- a/src/video_core/shader/ast.cpp +++ b/src/video_core/shader/ast.cpp | |||
| @@ -363,6 +363,71 @@ std::string ASTManager::Print() { | |||
| 363 | return printer.GetResult(); | 363 | return printer.GetResult(); |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | ASTManager::ASTManager() = default; | ||
| 367 | |||
| 368 | ASTManager::~ASTManager() { | ||
| 369 | Clear(); | ||
| 370 | } | ||
| 371 | |||
| 372 | void ASTManager::Init() { | ||
| 373 | main_node = ASTBase::Make<ASTProgram>(ASTNode{}); | ||
| 374 | program = std::get_if<ASTProgram>(main_node->GetInnerData()); | ||
| 375 | true_condition = MakeExpr<ExprBoolean>(true); | ||
| 376 | } | ||
| 377 | |||
| 378 | ASTManager::ASTManager(ASTManager&& other) | ||
| 379 | : labels_map(std::move(other.labels_map)), labels_count{other.labels_count}, | ||
| 380 | gotos(std::move(other.gotos)), labels(std::move(other.labels)), variables{other.variables}, | ||
| 381 | program{other.program}, main_node{other.main_node}, true_condition{other.true_condition} { | ||
| 382 | other.main_node.reset(); | ||
| 383 | } | ||
| 384 | |||
| 385 | ASTManager& ASTManager::operator=(ASTManager&& other) { | ||
| 386 | labels_map = std::move(other.labels_map); | ||
| 387 | labels_count = other.labels_count; | ||
| 388 | gotos = std::move(other.gotos); | ||
| 389 | labels = std::move(other.labels); | ||
| 390 | variables = other.variables; | ||
| 391 | program = other.program; | ||
| 392 | main_node = other.main_node; | ||
| 393 | true_condition = other.true_condition; | ||
| 394 | |||
| 395 | other.main_node.reset(); | ||
| 396 | return *this; | ||
| 397 | } | ||
| 398 | |||
| 399 | void ASTManager::DeclareLabel(u32 address) { | ||
| 400 | const auto pair = labels_map.emplace(address, labels_count); | ||
| 401 | if (pair.second) { | ||
| 402 | labels_count++; | ||
| 403 | labels.resize(labels_count); | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | void ASTManager::InsertLabel(u32 address) { | ||
| 408 | u32 index = labels_map[address]; | ||
| 409 | ASTNode label = ASTBase::Make<ASTLabel>(main_node, index); | ||
| 410 | labels[index] = label; | ||
| 411 | program->nodes.PushBack(label); | ||
| 412 | } | ||
| 413 | |||
| 414 | void ASTManager::InsertGoto(Expr condition, u32 address) { | ||
| 415 | u32 index = labels_map[address]; | ||
| 416 | ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, condition, index); | ||
| 417 | gotos.push_back(goto_node); | ||
| 418 | program->nodes.PushBack(goto_node); | ||
| 419 | } | ||
| 420 | |||
| 421 | void ASTManager::InsertBlock(u32 start_address, u32 end_address) { | ||
| 422 | ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address); | ||
| 423 | program->nodes.PushBack(block); | ||
| 424 | } | ||
| 425 | |||
| 426 | void ASTManager::InsertReturn(Expr condition, bool kills) { | ||
| 427 | ASTNode node = ASTBase::Make<ASTReturn>(main_node, condition, kills); | ||
| 428 | program->nodes.PushBack(node); | ||
| 429 | } | ||
| 430 | |||
| 366 | void ASTManager::Decompile() { | 431 | void ASTManager::Decompile() { |
| 367 | auto it = gotos.begin(); | 432 | auto it = gotos.begin(); |
| 368 | while (it != gotos.end()) { | 433 | while (it != gotos.end()) { |
| @@ -460,7 +525,6 @@ void ASTManager::SanityCheck() { | |||
| 460 | 525 | ||
| 461 | void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) { | 526 | void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) { |
| 462 | // ShowCurrentState("Before DoWhile Enclose"); | 527 | // ShowCurrentState("Before DoWhile Enclose"); |
| 463 | enclose_count++; | ||
| 464 | ASTZipper& zipper = goto_node->GetManager(); | 528 | ASTZipper& zipper = goto_node->GetManager(); |
| 465 | ASTNode loop_start = label->GetNext(); | 529 | ASTNode loop_start = label->GetNext(); |
| 466 | if (loop_start == goto_node) { | 530 | if (loop_start == goto_node) { |
| @@ -481,7 +545,6 @@ void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) { | |||
| 481 | 545 | ||
| 482 | void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) { | 546 | void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) { |
| 483 | // ShowCurrentState("Before IfThen Enclose"); | 547 | // ShowCurrentState("Before IfThen Enclose"); |
| 484 | enclose_count++; | ||
| 485 | ASTZipper& zipper = goto_node->GetManager(); | 548 | ASTZipper& zipper = goto_node->GetManager(); |
| 486 | ASTNode if_end = label->GetPrevious(); | 549 | ASTNode if_end = label->GetPrevious(); |
| 487 | if (if_end == goto_node) { | 550 | if (if_end == goto_node) { |
| @@ -514,7 +577,6 @@ void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) { | |||
| 514 | 577 | ||
| 515 | void ASTManager::MoveOutward(ASTNode goto_node) { | 578 | void ASTManager::MoveOutward(ASTNode goto_node) { |
| 516 | // ShowCurrentState("Before MoveOutward"); | 579 | // ShowCurrentState("Before MoveOutward"); |
| 517 | outward_count++; | ||
| 518 | ASTZipper& zipper = goto_node->GetManager(); | 580 | ASTZipper& zipper = goto_node->GetManager(); |
| 519 | ASTNode parent = goto_node->GetParent(); | 581 | ASTNode parent = goto_node->GetParent(); |
| 520 | ASTZipper& zipper2 = parent->GetManager(); | 582 | ASTZipper& zipper2 = parent->GetManager(); |
| @@ -582,4 +644,75 @@ void ASTManager::MoveOutward(ASTNode goto_node) { | |||
| 582 | // ShowCurrentState("After MoveOutward"); | 644 | // ShowCurrentState("After MoveOutward"); |
| 583 | } | 645 | } |
| 584 | 646 | ||
| 647 | class ASTClearer { | ||
| 648 | public: | ||
| 649 | ASTClearer() = default; | ||
| 650 | |||
| 651 | void operator()(ASTProgram& ast) { | ||
| 652 | ASTNode current = ast.nodes.GetFirst(); | ||
| 653 | while (current) { | ||
| 654 | Visit(current); | ||
| 655 | current = current->GetNext(); | ||
| 656 | } | ||
| 657 | } | ||
| 658 | |||
| 659 | void operator()(ASTIfThen& ast) { | ||
| 660 | ASTNode current = ast.nodes.GetFirst(); | ||
| 661 | while (current) { | ||
| 662 | Visit(current); | ||
| 663 | current = current->GetNext(); | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | void operator()(ASTIfElse& ast) { | ||
| 668 | ASTNode current = ast.nodes.GetFirst(); | ||
| 669 | while (current) { | ||
| 670 | Visit(current); | ||
| 671 | current = current->GetNext(); | ||
| 672 | } | ||
| 673 | } | ||
| 674 | |||
| 675 | void operator()(ASTBlockEncoded& ast) {} | ||
| 676 | |||
| 677 | void operator()(ASTBlockDecoded& ast) { | ||
| 678 | ast.nodes.clear(); | ||
| 679 | } | ||
| 680 | |||
| 681 | void operator()(ASTVarSet& ast) {} | ||
| 682 | |||
| 683 | void operator()(ASTLabel& ast) {} | ||
| 684 | |||
| 685 | void operator()(ASTGoto& ast) {} | ||
| 686 | |||
| 687 | void operator()(ASTDoWhile& ast) { | ||
| 688 | ASTNode current = ast.nodes.GetFirst(); | ||
| 689 | while (current) { | ||
| 690 | Visit(current); | ||
| 691 | current = current->GetNext(); | ||
| 692 | } | ||
| 693 | } | ||
| 694 | |||
| 695 | void operator()(ASTReturn& ast) {} | ||
| 696 | |||
| 697 | void operator()(ASTBreak& ast) {} | ||
| 698 | |||
| 699 | void Visit(ASTNode& node) { | ||
| 700 | std::visit(*this, *node->GetInnerData()); | ||
| 701 | node->Clear(); | ||
| 702 | } | ||
| 703 | }; | ||
| 704 | |||
| 705 | void ASTManager::Clear() { | ||
| 706 | if (!main_node) { | ||
| 707 | return; | ||
| 708 | } | ||
| 709 | ASTClearer clearer{}; | ||
| 710 | clearer.Visit(main_node); | ||
| 711 | main_node.reset(); | ||
| 712 | program = nullptr; | ||
| 713 | labels_map.clear(); | ||
| 714 | labels.clear(); | ||
| 715 | gotos.clear(); | ||
| 716 | } | ||
| 717 | |||
| 585 | } // namespace VideoCommon::Shader | 718 | } // namespace VideoCommon::Shader |