diff options
Diffstat (limited to 'src/video_core/shader/ast.h')
| -rw-r--r-- | src/video_core/shader/ast.h | 398 |
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 | |||
| 18 | namespace VideoCommon::Shader { | ||
| 19 | |||
| 20 | class ASTBase; | ||
| 21 | class ASTBlockDecoded; | ||
| 22 | class ASTBlockEncoded; | ||
| 23 | class ASTBreak; | ||
| 24 | class ASTDoWhile; | ||
| 25 | class ASTGoto; | ||
| 26 | class ASTIfElse; | ||
| 27 | class ASTIfThen; | ||
| 28 | class ASTLabel; | ||
| 29 | class ASTProgram; | ||
| 30 | class ASTReturn; | ||
| 31 | class ASTVarSet; | ||
| 32 | |||
| 33 | using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded, | ||
| 34 | ASTVarSet, ASTGoto, ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>; | ||
| 35 | |||
| 36 | using ASTNode = std::shared_ptr<ASTBase>; | ||
| 37 | |||
| 38 | enum class ASTZipperType : u32 { | ||
| 39 | Program, | ||
| 40 | IfThen, | ||
| 41 | IfElse, | ||
| 42 | Loop, | ||
| 43 | }; | ||
| 44 | |||
| 45 | class ASTZipper final { | ||
| 46 | public: | ||
| 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 | |||
| 72 | class ASTProgram { | ||
| 73 | public: | ||
| 74 | ASTZipper nodes{}; | ||
| 75 | }; | ||
| 76 | |||
| 77 | class ASTIfThen { | ||
| 78 | public: | ||
| 79 | explicit ASTIfThen(Expr condition_) : condition{std::move(condition_)} {} | ||
| 80 | Expr condition; | ||
| 81 | ASTZipper nodes{}; | ||
| 82 | }; | ||
| 83 | |||
| 84 | class ASTIfElse { | ||
| 85 | public: | ||
| 86 | ASTZipper nodes{}; | ||
| 87 | }; | ||
| 88 | |||
| 89 | class ASTBlockEncoded { | ||
| 90 | public: | ||
| 91 | explicit ASTBlockEncoded(u32 start_, u32 _) : start{start_}, end{_} {} | ||
| 92 | u32 start; | ||
| 93 | u32 end; | ||
| 94 | }; | ||
| 95 | |||
| 96 | class ASTBlockDecoded { | ||
| 97 | public: | ||
| 98 | explicit ASTBlockDecoded(NodeBlock&& new_nodes_) : nodes(std::move(new_nodes_)) {} | ||
| 99 | NodeBlock nodes; | ||
| 100 | }; | ||
| 101 | |||
| 102 | class ASTVarSet { | ||
| 103 | public: | ||
| 104 | explicit ASTVarSet(u32 index_, Expr condition_) | ||
| 105 | : index{index_}, condition{std::move(condition_)} {} | ||
| 106 | |||
| 107 | u32 index; | ||
| 108 | Expr condition; | ||
| 109 | }; | ||
| 110 | |||
| 111 | class ASTLabel { | ||
| 112 | public: | ||
| 113 | explicit ASTLabel(u32 index_) : index{index_} {} | ||
| 114 | u32 index; | ||
| 115 | bool unused{}; | ||
| 116 | }; | ||
| 117 | |||
| 118 | class ASTGoto { | ||
| 119 | public: | ||
| 120 | explicit ASTGoto(Expr condition_, u32 label_) | ||
| 121 | : condition{std::move(condition_)}, label{label_} {} | ||
| 122 | |||
| 123 | Expr condition; | ||
| 124 | u32 label; | ||
| 125 | }; | ||
| 126 | |||
| 127 | class ASTDoWhile { | ||
| 128 | public: | ||
| 129 | explicit ASTDoWhile(Expr condition_) : condition{std::move(condition_)} {} | ||
| 130 | Expr condition; | ||
| 131 | ASTZipper nodes{}; | ||
| 132 | }; | ||
| 133 | |||
| 134 | class ASTReturn { | ||
| 135 | public: | ||
| 136 | explicit ASTReturn(Expr condition_, bool kills_) | ||
| 137 | : condition{std::move(condition_)}, kills{kills_} {} | ||
| 138 | |||
| 139 | Expr condition; | ||
| 140 | bool kills; | ||
| 141 | }; | ||
| 142 | |||
| 143 | class ASTBreak { | ||
| 144 | public: | ||
| 145 | explicit ASTBreak(Expr condition_) : condition{std::move(condition_)} {} | ||
| 146 | Expr condition; | ||
| 147 | }; | ||
| 148 | |||
| 149 | class ASTBase { | ||
| 150 | public: | ||
| 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 | |||
| 296 | private: | ||
| 297 | friend class ASTZipper; | ||
| 298 | |||
| 299 | ASTData data; | ||
| 300 | ASTNode parent; | ||
| 301 | ASTNode next; | ||
| 302 | ASTNode previous; | ||
| 303 | ASTZipper* manager{}; | ||
| 304 | }; | ||
| 305 | |||
| 306 | class ASTManager final { | ||
| 307 | public: | ||
| 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 | |||
| 369 | private: | ||
| 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 | ||