summaryrefslogtreecommitdiff
path: root/src/video_core/shader/ast.h
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-06-27 18:57:47 -0400
committerGravatar FernandoS272019-10-04 18:52:48 -0400
commit4fde66e6094b57201d208b8abd3d7715341cd5db (patch)
tree627cc2bfd8a03fb05e28654885b7d752e8bcfad8 /src/video_core/shader/ast.h
parentshader_ir: Initial Decompile Setup (diff)
downloadyuzu-4fde66e6094b57201d208b8abd3d7715341cd5db.tar.gz
yuzu-4fde66e6094b57201d208b8abd3d7715341cd5db.tar.xz
yuzu-4fde66e6094b57201d208b8abd3d7715341cd5db.zip
shader_ir: Add basic goto elimination
Diffstat (limited to 'src/video_core/shader/ast.h')
-rw-r--r--src/video_core/shader/ast.h174
1 files changed, 152 insertions, 22 deletions
diff --git a/src/video_core/shader/ast.h b/src/video_core/shader/ast.h
index ca71543fb..22ac8884c 100644
--- a/src/video_core/shader/ast.h
+++ b/src/video_core/shader/ast.h
@@ -18,32 +18,71 @@ namespace VideoCommon::Shader {
18 18
19class ASTBase; 19class ASTBase;
20class ASTProgram; 20class ASTProgram;
21class ASTIf; 21class ASTIfThen;
22class ASTIfElse;
22class ASTBlockEncoded; 23class ASTBlockEncoded;
23class ASTVarSet; 24class ASTVarSet;
24class ASTGoto; 25class ASTGoto;
25class ASTLabel; 26class ASTLabel;
26class ASTDoWhile; 27class ASTDoWhile;
27class ASTReturn; 28class ASTReturn;
29class ASTBreak;
28 30
29using ASTData = std::variant<ASTProgram, ASTIf, ASTBlockEncoded, ASTVarSet, ASTGoto, ASTLabel, 31using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTVarSet, ASTGoto,
30 ASTDoWhile, ASTReturn>; 32 ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>;
31 33
32using ASTNode = std::shared_ptr<ASTBase>; 34using ASTNode = std::shared_ptr<ASTBase>;
33 35
36enum class ASTZipperType : u32 {
37 Program,
38 IfThen,
39 IfElse,
40 Loop,
41};
42
43class ASTZipper final {
44public:
45 ASTZipper();
46 ASTZipper(ASTNode first);
47
48 ASTNode GetFirst() {
49 return first;
50 }
51
52 ASTNode GetLast() {
53 return last;
54 }
55
56 void PushBack(ASTNode new_node);
57 void PushFront(ASTNode new_node);
58 void InsertAfter(ASTNode new_node, ASTNode at_node);
59 void SetParent(ASTNode new_parent);
60 void DetachTail(ASTNode node);
61 void DetachSingle(ASTNode node);
62 void DetachSegment(ASTNode start, ASTNode end);
63 void Remove(ASTNode node);
64
65 ASTNode first{};
66 ASTNode last{};
67};
68
34class ASTProgram { 69class ASTProgram {
35public: 70public:
36 ASTProgram() = default; 71 ASTProgram() : nodes{} {};
37 std::list<ASTNode> nodes; 72 ASTZipper nodes;
38}; 73};
39 74
40class ASTIf { 75class ASTIfThen {
41public: 76public:
42 ASTIf(Expr condition, std::list<ASTNode> then_nodes, std::list<ASTNode> else_nodes) 77 ASTIfThen(Expr condition, ASTZipper nodes) : condition(condition), nodes{nodes} {}
43 : condition(condition), then_nodes{then_nodes}, else_nodes{then_nodes} {}
44 Expr condition; 78 Expr condition;
45 std::list<ASTNode> then_nodes; 79 ASTZipper nodes;
46 std::list<ASTNode> else_nodes; 80};
81
82class ASTIfElse {
83public:
84 ASTIfElse(ASTZipper nodes) : nodes{nodes} {}
85 ASTZipper nodes;
47}; 86};
48 87
49class ASTBlockEncoded { 88class ASTBlockEncoded {
@@ -75,10 +114,9 @@ public:
75 114
76class ASTDoWhile { 115class ASTDoWhile {
77public: 116public:
78 ASTDoWhile(Expr condition, std::list<ASTNode> loop_nodes) 117 ASTDoWhile(Expr condition, ASTZipper nodes) : condition(condition), nodes{nodes} {}
79 : condition(condition), loop_nodes{loop_nodes} {}
80 Expr condition; 118 Expr condition;
81 std::list<ASTNode> loop_nodes; 119 ASTZipper nodes;
82}; 120};
83 121
84class ASTReturn { 122class ASTReturn {
@@ -88,6 +126,12 @@ public:
88 bool kills; 126 bool kills;
89}; 127};
90 128
129class ASTBreak {
130public:
131 ASTBreak(Expr condition) : condition{condition} {}
132 Expr condition;
133};
134
91class ASTBase { 135class ASTBase {
92public: 136public:
93 explicit ASTBase(ASTNode parent, ASTData data) : parent{parent}, data{data} {} 137 explicit ASTBase(ASTNode parent, ASTData data) : parent{parent}, data{data} {}
@@ -111,9 +155,9 @@ public:
111 155
112 u32 GetLevel() const { 156 u32 GetLevel() const {
113 u32 level = 0; 157 u32 level = 0;
114 auto next = parent; 158 auto next_parent = parent;
115 while (next) { 159 while (next_parent) {
116 next = next->GetParent(); 160 next_parent = next_parent->GetParent();
117 level++; 161 level++;
118 } 162 }
119 return level; 163 return level;
@@ -123,15 +167,83 @@ public:
123 return &data; 167 return &data;
124 } 168 }
125 169
170 ASTNode GetNext() {
171 return next;
172 }
173
174 ASTNode GetPrevious() {
175 return previous;
176 }
177
178 ASTZipper& GetManager() {
179 return *manager;
180 }
181
182 u32 GetGotoLabel() const {
183 auto inner = std::get_if<ASTGoto>(&data);
184 if (inner) {
185 return inner->label;
186 }
187 return -1;
188 }
189
190 Expr GetGotoCondition() const {
191 auto inner = std::get_if<ASTGoto>(&data);
192 if (inner) {
193 return inner->condition;
194 }
195 return nullptr;
196 }
197
198 void SetGotoCondition(Expr new_condition) {
199 auto inner = std::get_if<ASTGoto>(&data);
200 if (inner) {
201 inner->condition = new_condition;
202 }
203 }
204
205 bool IsIfThen() const {
206 return std::holds_alternative<ASTIfThen>(data);
207 }
208
209 bool IsIfElse() const {
210 return std::holds_alternative<ASTIfElse>(data);
211 }
212
213 bool IsLoop() const {
214 return std::holds_alternative<ASTDoWhile>(data);
215 }
216
217 ASTZipper* GetSubNodes() {
218 if (std::holds_alternative<ASTProgram>(data)) {
219 return &std::get_if<ASTProgram>(&data)->nodes;
220 }
221 if (std::holds_alternative<ASTIfThen>(data)) {
222 return &std::get_if<ASTIfThen>(&data)->nodes;
223 }
224 if (std::holds_alternative<ASTIfElse>(data)) {
225 return &std::get_if<ASTIfElse>(&data)->nodes;
226 }
227 if (std::holds_alternative<ASTDoWhile>(data)) {
228 return &std::get_if<ASTDoWhile>(&data)->nodes;
229 }
230 return nullptr;
231 }
232
126private: 233private:
234 friend class ASTZipper;
235
127 ASTData data; 236 ASTData data;
128 ASTNode parent; 237 ASTNode parent;
238 ASTNode next{};
239 ASTNode previous{};
240 ASTZipper* manager{};
129}; 241};
130 242
131class ASTManager final { 243class ASTManager final {
132public: 244public:
133 explicit ASTManager() { 245 explicit ASTManager() {
134 main_node = ASTBase::Make<ASTProgram>(nullptr); 246 main_node = ASTBase::Make<ASTProgram>(ASTNode{});
135 program = std::get_if<ASTProgram>(main_node->GetInnerData()); 247 program = std::get_if<ASTProgram>(main_node->GetInnerData());
136 } 248 }
137 249
@@ -147,31 +259,49 @@ public:
147 u32 index = labels_map[address]; 259 u32 index = labels_map[address];
148 ASTNode label = ASTBase::Make<ASTLabel>(main_node, index); 260 ASTNode label = ASTBase::Make<ASTLabel>(main_node, index);
149 labels[index] = label; 261 labels[index] = label;
150 program->nodes.push_back(label); 262 program->nodes.PushBack(label);
151 } 263 }
152 264
153 void InsertGoto(Expr condition, u32 address) { 265 void InsertGoto(Expr condition, u32 address) {
154 u32 index = labels_map[address]; 266 u32 index = labels_map[address];
155 ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, condition, index); 267 ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, condition, index);
156 gotos.push_back(goto_node); 268 gotos.push_back(goto_node);
157 program->nodes.push_back(goto_node); 269 program->nodes.PushBack(goto_node);
158 } 270 }
159 271
160 void InsertBlock(u32 start_address, u32 end_address) { 272 void InsertBlock(u32 start_address, u32 end_address) {
161 ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address); 273 ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address);
162 program->nodes.push_back(block); 274 program->nodes.PushBack(block);
163 } 275 }
164 276
165 void InsertReturn(Expr condition, bool kills) { 277 void InsertReturn(Expr condition, bool kills) {
166 ASTNode node = ASTBase::Make<ASTReturn>(main_node, condition, kills); 278 ASTNode node = ASTBase::Make<ASTReturn>(main_node, condition, kills);
167 program->nodes.push_back(node); 279 program->nodes.PushBack(node);
168 } 280 }
169 281
170 std::string Print(); 282 std::string Print();
171 283
172 void Decompile() {} 284 void Decompile();
285
286
173 287
174private: 288private:
289 bool IndirectlyRelated(ASTNode first, ASTNode second);
290
291 bool DirectlyRelated(ASTNode first, ASTNode second);
292
293 void EncloseDoWhile(ASTNode goto_node, ASTNode label);
294
295 void EncloseIfThen(ASTNode goto_node, ASTNode label);
296
297 void MoveOutward(ASTNode goto_node) ;
298
299 u32 NewVariable() {
300 u32 new_var = variables;
301 variables++;
302 return new_var;
303 }
304
175 std::unordered_map<u32, u32> labels_map{}; 305 std::unordered_map<u32, u32> labels_map{};
176 u32 labels_count{}; 306 u32 labels_count{};
177 std::vector<ASTNode> labels{}; 307 std::vector<ASTNode> labels{};