summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/maxwell/control_flow.h
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-01-09 03:30:07 -0300
committerGravatar ameerj2021-07-22 21:51:21 -0400
commit2d48a7b4d0666ad16d03a22d85712617a0849046 (patch)
treedd1069afca86f66e77e3438da77421a43adf5091 /src/shader_recompiler/frontend/maxwell/control_flow.h
parentthread_worker: Fix compile time error (diff)
downloadyuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.tar.gz
yuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.tar.xz
yuzu-2d48a7b4d0666ad16d03a22d85712617a0849046.zip
shader: Initial recompiler work
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/control_flow.h')
-rw-r--r--src/shader_recompiler/frontend/maxwell/control_flow.h137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.h b/src/shader_recompiler/frontend/maxwell/control_flow.h
new file mode 100644
index 000000000..b2ab0cdc3
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/control_flow.h
@@ -0,0 +1,137 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <compare>
8#include <optional>
9#include <span>
10#include <string>
11#include <vector>
12
13#include <boost/container/small_vector.hpp>
14
15#include "shader_recompiler/environment.h"
16#include "shader_recompiler/frontend/ir/condition.h"
17#include "shader_recompiler/frontend/maxwell/instruction.h"
18#include "shader_recompiler/frontend/maxwell/location.h"
19#include "shader_recompiler/frontend/maxwell/opcode.h"
20
21namespace Shader::Maxwell::Flow {
22
23using BlockId = u32;
24using FunctionId = size_t;
25
26constexpr BlockId UNREACHABLE_BLOCK_ID{static_cast<u32>(-1)};
27
28enum class EndClass {
29 Branch,
30 Exit,
31 Return,
32 Unreachable,
33};
34
35enum class Token {
36 SSY,
37 PBK,
38 PEXIT,
39 PRET,
40 PCNT,
41 PLONGJMP,
42};
43
44struct StackEntry {
45 auto operator<=>(const StackEntry&) const noexcept = default;
46
47 Token token;
48 Location target;
49};
50
51class Stack {
52public:
53 void Push(Token token, Location target);
54 [[nodiscard]] std::pair<Location, Stack> Pop(Token token) const;
55 [[nodiscard]] std::optional<Location> Peek(Token token) const;
56 [[nodiscard]] Stack Remove(Token token) const;
57
58private:
59 boost::container::small_vector<StackEntry, 3> entries;
60};
61
62struct Block {
63 [[nodiscard]] bool Contains(Location pc) const noexcept;
64
65 Location begin;
66 Location end;
67 EndClass end_class;
68 BlockId id;
69 Stack stack;
70 IR::Condition cond;
71 BlockId branch_true;
72 BlockId branch_false;
73};
74
75struct Label {
76 Location address;
77 BlockId block_id;
78 Stack stack;
79};
80
81struct Function {
82 Function(Location start_address);
83
84 Location entrypoint;
85 BlockId current_block_id{0};
86 boost::container::small_vector<Label, 16> labels;
87 boost::container::small_vector<u32, 0x130> blocks;
88 boost::container::small_vector<Block, 0x130> blocks_data;
89};
90
91class CFG {
92 enum class AnalysisState {
93 Branch,
94 Continue,
95 };
96
97public:
98 explicit CFG(Environment& env, Location start_address);
99
100 [[nodiscard]] std::string Dot() const;
101
102 [[nodiscard]] std::span<const Function> Functions() const noexcept {
103 return std::span(functions.data(), functions.size());
104 }
105
106private:
107 void AnalyzeLabel(FunctionId function_id, Label& label);
108
109 /// Inspect already visited blocks.
110 /// Return true when the block has already been visited
111 [[nodiscard]] bool InspectVisitedBlocks(FunctionId function_id, const Label& label);
112
113 [[nodiscard]] AnalysisState AnalyzeInst(Block& block, FunctionId function_id, Location pc);
114
115 void AnalyzeCondInst(Block& block, FunctionId function_id, Location pc, EndClass insn_end_class,
116 IR::Condition cond);
117
118 /// Return true when the branch instruction is confirmed to be a branch
119 [[nodiscard]] bool AnalyzeBranch(Block& block, FunctionId function_id, Location pc,
120 Instruction inst, Opcode opcode);
121
122 void AnalyzeBRA(Block& block, FunctionId function_id, Location pc, Instruction inst,
123 bool is_absolute);
124 void AnalyzeBRX(Block& block, Location pc, Instruction inst, bool is_absolute);
125 void AnalyzeCAL(Location pc, Instruction inst, bool is_absolute);
126 AnalysisState AnalyzeEXIT(Block& block, FunctionId function_id, Location pc, Instruction inst);
127
128 /// Return the branch target block id
129 [[nodiscard]] BlockId AddLabel(const Block& block, Stack stack, Location pc,
130 FunctionId function_id);
131
132 Environment& env;
133 boost::container::small_vector<Function, 1> functions;
134 FunctionId current_function_id{0};
135};
136
137} // namespace Shader::Maxwell::Flow