summaryrefslogtreecommitdiff
path: root/src/video_core/shader/ast.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/shader/ast.h')
-rw-r--r--src/video_core/shader/ast.h398
1 files changed, 0 insertions, 398 deletions
diff --git a/src/video_core/shader/ast.h b/src/video_core/shader/ast.h
deleted file mode 100644
index dc49b369e..000000000
--- a/src/video_core/shader/ast.h
+++ /dev/null
@@ -1,398 +0,0 @@
1// Copyright 2019 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 <functional>
8#include <list>
9#include <memory>
10#include <optional>
11#include <string>
12#include <unordered_map>
13#include <vector>
14
15#include "video_core/shader/expr.h"
16#include "video_core/shader/node.h"
17
18namespace VideoCommon::Shader {
19
20class ASTBase;
21class ASTBlockDecoded;
22class ASTBlockEncoded;
23class ASTBreak;
24class ASTDoWhile;
25class ASTGoto;
26class ASTIfElse;
27class ASTIfThen;
28class ASTLabel;
29class ASTProgram;
30class ASTReturn;
31class ASTVarSet;
32
33using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded,
34 ASTVarSet, ASTGoto, ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>;
35
36using ASTNode = std::shared_ptr<ASTBase>;
37
38enum class ASTZipperType : u32 {
39 Program,
40 IfThen,
41 IfElse,
42 Loop,
43};
44
45class ASTZipper final {
46public:
47 explicit ASTZipper();
48
49 void Init(ASTNode first, ASTNode parent);
50
51 ASTNode GetFirst() const {
52 return first;
53 }
54
55 ASTNode GetLast() const {
56 return last;
57 }
58
59 void PushBack(ASTNode new_node);
60 void PushFront(ASTNode new_node);
61 void InsertAfter(ASTNode new_node, ASTNode at_node);
62 void InsertBefore(ASTNode new_node, ASTNode at_node);
63 void DetachTail(ASTNode node);
64 void DetachSingle(ASTNode node);
65 void DetachSegment(ASTNode start, ASTNode end);
66 void Remove(ASTNode node);
67
68 ASTNode first;
69 ASTNode last;
70};
71
72class ASTProgram {
73public:
74 ASTZipper nodes{};
75};
76
77class ASTIfThen {
78public:
79 explicit ASTIfThen(Expr condition_) : condition{std::move(condition_)} {}
80 Expr condition;
81 ASTZipper nodes{};
82};
83
84class ASTIfElse {
85public:
86 ASTZipper nodes{};
87};
88
89class ASTBlockEncoded {
90public:
91 explicit ASTBlockEncoded(u32 start_, u32 _) : start{start_}, end{_} {}
92 u32 start;
93 u32 end;
94};
95
96class ASTBlockDecoded {
97public:
98 explicit ASTBlockDecoded(NodeBlock&& new_nodes_) : nodes(std::move(new_nodes_)) {}
99 NodeBlock nodes;
100};
101
102class ASTVarSet {
103public:
104 explicit ASTVarSet(u32 index_, Expr condition_)
105 : index{index_}, condition{std::move(condition_)} {}
106
107 u32 index;
108 Expr condition;
109};
110
111class ASTLabel {
112public:
113 explicit ASTLabel(u32 index_) : index{index_} {}
114 u32 index;
115 bool unused{};
116};
117
118class ASTGoto {
119public:
120 explicit ASTGoto(Expr condition_, u32 label_)
121 : condition{std::move(condition_)}, label{label_} {}
122
123 Expr condition;
124 u32 label;
125};
126
127class ASTDoWhile {
128public:
129 explicit ASTDoWhile(Expr condition_) : condition{std::move(condition_)} {}
130 Expr condition;
131 ASTZipper nodes{};
132};
133
134class ASTReturn {
135public:
136 explicit ASTReturn(Expr condition_, bool kills_)
137 : condition{std::move(condition_)}, kills{kills_} {}
138
139 Expr condition;
140 bool kills;
141};
142
143class ASTBreak {
144public:
145 explicit ASTBreak(Expr condition_) : condition{std::move(condition_)} {}
146 Expr condition;
147};
148
149class ASTBase {
150public:
151 explicit ASTBase(ASTNode parent_, ASTData data_)
152 : data{std::move(data_)}, parent{std::move(parent_)} {}
153
154 template <class U, class... Args>
155 static ASTNode Make(ASTNode parent, Args&&... args) {
156 return std::make_shared<ASTBase>(std::move(parent),
157 ASTData(U(std::forward<Args>(args)...)));
158 }
159
160 void SetParent(ASTNode new_parent) {
161 parent = std::move(new_parent);
162 }
163
164 ASTNode& GetParent() {
165 return parent;
166 }
167
168 const ASTNode& GetParent() const {
169 return parent;
170 }
171
172 u32 GetLevel() const {
173 u32 level = 0;
174 auto next_parent = parent;
175 while (next_parent) {
176 next_parent = next_parent->GetParent();
177 level++;
178 }
179 return level;
180 }
181
182 ASTData* GetInnerData() {
183 return &data;
184 }
185
186 const ASTData* GetInnerData() const {
187 return &data;
188 }
189
190 ASTNode GetNext() const {
191 return next;
192 }
193
194 ASTNode GetPrevious() const {
195 return previous;
196 }
197
198 ASTZipper& GetManager() {
199 return *manager;
200 }
201
202 const ASTZipper& GetManager() const {
203 return *manager;
204 }
205
206 std::optional<u32> GetGotoLabel() const {
207 if (const auto* inner = std::get_if<ASTGoto>(&data)) {
208 return {inner->label};
209 }
210 return std::nullopt;
211 }
212
213 Expr GetGotoCondition() const {
214 if (const auto* inner = std::get_if<ASTGoto>(&data)) {
215 return inner->condition;
216 }
217 return nullptr;
218 }
219
220 void MarkLabelUnused() {
221 if (auto* inner = std::get_if<ASTLabel>(&data)) {
222 inner->unused = true;
223 }
224 }
225
226 bool IsLabelUnused() const {
227 if (const auto* inner = std::get_if<ASTLabel>(&data)) {
228 return inner->unused;
229 }
230 return true;
231 }
232
233 std::optional<u32> GetLabelIndex() const {
234 if (const auto* inner = std::get_if<ASTLabel>(&data)) {
235 return {inner->index};
236 }
237 return std::nullopt;
238 }
239
240 Expr GetIfCondition() const {
241 if (const auto* inner = std::get_if<ASTIfThen>(&data)) {
242 return inner->condition;
243 }
244 return nullptr;
245 }
246
247 void SetGotoCondition(Expr new_condition) {
248 if (auto* inner = std::get_if<ASTGoto>(&data)) {
249 inner->condition = std::move(new_condition);
250 }
251 }
252
253 bool IsIfThen() const {
254 return std::holds_alternative<ASTIfThen>(data);
255 }
256
257 bool IsIfElse() const {
258 return std::holds_alternative<ASTIfElse>(data);
259 }
260
261 bool IsBlockEncoded() const {
262 return std::holds_alternative<ASTBlockEncoded>(data);
263 }
264
265 void TransformBlockEncoded(NodeBlock&& nodes) {
266 data = ASTBlockDecoded(std::move(nodes));
267 }
268
269 bool IsLoop() const {
270 return std::holds_alternative<ASTDoWhile>(data);
271 }
272
273 ASTZipper* GetSubNodes() {
274 if (std::holds_alternative<ASTProgram>(data)) {
275 return &std::get_if<ASTProgram>(&data)->nodes;
276 }
277 if (std::holds_alternative<ASTIfThen>(data)) {
278 return &std::get_if<ASTIfThen>(&data)->nodes;
279 }
280 if (std::holds_alternative<ASTIfElse>(data)) {
281 return &std::get_if<ASTIfElse>(&data)->nodes;
282 }
283 if (std::holds_alternative<ASTDoWhile>(data)) {
284 return &std::get_if<ASTDoWhile>(&data)->nodes;
285 }
286 return nullptr;
287 }
288
289 void Clear() {
290 next.reset();
291 previous.reset();
292 parent.reset();
293 manager = nullptr;
294 }
295
296private:
297 friend class ASTZipper;
298
299 ASTData data;
300 ASTNode parent;
301 ASTNode next;
302 ASTNode previous;
303 ASTZipper* manager{};
304};
305
306class ASTManager final {
307public:
308 explicit ASTManager(bool do_full_decompile, bool disable_else_derivation_);
309 ~ASTManager();
310
311 ASTManager(const ASTManager& o) = delete;
312 ASTManager& operator=(const ASTManager& other) = delete;
313
314 ASTManager(ASTManager&& other) noexcept = default;
315 ASTManager& operator=(ASTManager&& other) noexcept = default;
316
317 void Init();
318
319 void DeclareLabel(u32 address);
320
321 void InsertLabel(u32 address);
322
323 void InsertGoto(Expr condition, u32 address);
324
325 void InsertBlock(u32 start_address, u32 end_address);
326
327 void InsertReturn(Expr condition, bool kills);
328
329 std::string Print() const;
330
331 void Decompile();
332
333 void ShowCurrentState(std::string_view state) const;
334
335 void SanityCheck() const;
336
337 void Clear();
338
339 bool IsFullyDecompiled() const {
340 if (full_decompile) {
341 return gotos.empty();
342 }
343
344 for (ASTNode goto_node : gotos) {
345 auto label_index = goto_node->GetGotoLabel();
346 if (!label_index) {
347 return false;
348 }
349 ASTNode glabel = labels[*label_index];
350 if (IsBackwardsJump(goto_node, glabel)) {
351 return false;
352 }
353 }
354 return true;
355 }
356
357 ASTNode GetProgram() const {
358 return main_node;
359 }
360
361 u32 GetVariables() const {
362 return variables;
363 }
364
365 const std::vector<ASTNode>& GetLabels() const {
366 return labels;
367 }
368
369private:
370 bool IsBackwardsJump(ASTNode goto_node, ASTNode label_node) const;
371
372 bool IndirectlyRelated(const ASTNode& first, const ASTNode& second) const;
373
374 bool DirectlyRelated(const ASTNode& first, const ASTNode& second) const;
375
376 void EncloseDoWhile(ASTNode goto_node, ASTNode label);
377
378 void EncloseIfThen(ASTNode goto_node, ASTNode label);
379
380 void MoveOutward(ASTNode goto_node);
381
382 u32 NewVariable() {
383 return variables++;
384 }
385
386 bool full_decompile{};
387 bool disable_else_derivation{};
388 std::unordered_map<u32, u32> labels_map{};
389 u32 labels_count{};
390 std::vector<ASTNode> labels{};
391 std::list<ASTNode> gotos{};
392 u32 variables{};
393 ASTProgram* program{};
394 ASTNode main_node{};
395 Expr false_condition{};
396};
397
398} // namespace VideoCommon::Shader