summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/maxwell/control_flow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/control_flow.cpp')
-rw-r--r--src/shader_recompiler/frontend/maxwell/control_flow.cpp140
1 files changed, 59 insertions, 81 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.cpp b/src/shader_recompiler/frontend/maxwell/control_flow.cpp
index 847bb1986..cb8ec7eaa 100644
--- a/src/shader_recompiler/frontend/maxwell/control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/control_flow.cpp
@@ -34,41 +34,37 @@ struct Compare {
34}; 34};
35 35
36u32 BranchOffset(Location pc, Instruction inst) { 36u32 BranchOffset(Location pc, Instruction inst) {
37 return pc.Offset() + inst.branch.Offset() + 8; 37 return pc.Offset() + static_cast<u32>(inst.branch.Offset()) + 8u;
38} 38}
39 39
40void Split(Block* old_block, Block* new_block, Location pc) { 40void Split(Block* old_block, Block* new_block, Location pc) {
41 if (pc <= old_block->begin || pc >= old_block->end) { 41 if (pc <= old_block->begin || pc >= old_block->end) {
42 throw InvalidArgument("Invalid address to split={}", pc); 42 throw InvalidArgument("Invalid address to split={}", pc);
43 } 43 }
44 *new_block = Block{ 44 *new_block = Block{};
45 .begin{pc}, 45 new_block->begin = pc;
46 .end{old_block->end}, 46 new_block->end = old_block->end;
47 .end_class{old_block->end_class}, 47 new_block->end_class = old_block->end_class,
48 .cond{old_block->cond}, 48 new_block->cond = old_block->cond;
49 .stack{old_block->stack}, 49 new_block->stack = old_block->stack;
50 .branch_true{old_block->branch_true}, 50 new_block->branch_true = old_block->branch_true;
51 .branch_false{old_block->branch_false}, 51 new_block->branch_false = old_block->branch_false;
52 .function_call{old_block->function_call}, 52 new_block->function_call = old_block->function_call;
53 .return_block{old_block->return_block}, 53 new_block->return_block = old_block->return_block;
54 .branch_reg{old_block->branch_reg}, 54 new_block->branch_reg = old_block->branch_reg;
55 .branch_offset{old_block->branch_offset}, 55 new_block->branch_offset = old_block->branch_offset;
56 .indirect_branches{std::move(old_block->indirect_branches)}, 56 new_block->indirect_branches = std::move(old_block->indirect_branches);
57 }; 57
58 *old_block = Block{ 58 const Location old_begin{old_block->begin};
59 .begin{old_block->begin}, 59 Stack old_stack{std::move(old_block->stack)};
60 .end{pc}, 60 *old_block = Block{};
61 .end_class{EndClass::Branch}, 61 old_block->begin = old_begin;
62 .cond{true}, 62 old_block->end = pc;
63 .stack{std::move(old_block->stack)}, 63 old_block->end_class = EndClass::Branch;
64 .branch_true{new_block}, 64 old_block->cond = IR::Condition(true);
65 .branch_false{nullptr}, 65 old_block->stack = old_stack;
66 .function_call{}, 66 old_block->branch_true = new_block;
67 .return_block{}, 67 old_block->branch_false = nullptr;
68 .branch_reg{},
69 .branch_offset{},
70 .indirect_branches{},
71 };
72} 68}
73 69
74Token OpcodeToken(Opcode opcode) { 70Token OpcodeToken(Opcode opcode) {
@@ -141,7 +137,7 @@ std::string NameOf(const Block& block) {
141 137
142void Stack::Push(Token token, Location target) { 138void Stack::Push(Token token, Location target) {
143 entries.push_back({ 139 entries.push_back({
144 .token{token}, 140 .token = token,
145 .target{target}, 141 .target{target},
146 }); 142 });
147} 143}
@@ -177,24 +173,17 @@ bool Block::Contains(Location pc) const noexcept {
177} 173}
178 174
179Function::Function(ObjectPool<Block>& block_pool, Location start_address) 175Function::Function(ObjectPool<Block>& block_pool, Location start_address)
180 : entrypoint{start_address}, labels{{ 176 : entrypoint{start_address} {
181 .address{start_address}, 177 Label& label{labels.emplace_back()};
182 .block{block_pool.Create(Block{ 178 label.address = start_address;
183 .begin{start_address}, 179 label.block = block_pool.Create(Block{});
184 .end{start_address}, 180 label.block->begin = start_address;
185 .end_class{EndClass::Branch}, 181 label.block->end = start_address;
186 .cond{true}, 182 label.block->end_class = EndClass::Branch;
187 .stack{}, 183 label.block->cond = IR::Condition(true);
188 .branch_true{nullptr}, 184 label.block->branch_true = nullptr;
189 .branch_false{nullptr}, 185 label.block->branch_false = nullptr;
190 .function_call{}, 186}
191 .return_block{},
192 .branch_reg{},
193 .branch_offset{},
194 .indirect_branches{},
195 })},
196 .stack{},
197 }} {}
198 187
199CFG::CFG(Environment& env_, ObjectPool<Block>& block_pool_, Location start_address) 188CFG::CFG(Environment& env_, ObjectPool<Block>& block_pool_, Location start_address)
200 : env{env_}, block_pool{block_pool_}, program_start{start_address} { 189 : env{env_}, block_pool{block_pool_}, program_start{start_address} {
@@ -327,7 +316,8 @@ CFG::AnalysisState CFG::AnalyzeInst(Block* block, FunctionId function_id, Locati
327 // Insert the function into the list if it doesn't exist 316 // Insert the function into the list if it doesn't exist
328 const auto it{std::ranges::find(functions, cal_pc, &Function::entrypoint)}; 317 const auto it{std::ranges::find(functions, cal_pc, &Function::entrypoint)};
329 const bool exists{it != functions.end()}; 318 const bool exists{it != functions.end()};
330 const FunctionId call_id{exists ? std::distance(functions.begin(), it) : functions.size()}; 319 const FunctionId call_id{exists ? static_cast<size_t>(std::distance(functions.begin(), it))
320 : functions.size()};
331 if (!exists) { 321 if (!exists) {
332 functions.emplace_back(block_pool, cal_pc); 322 functions.emplace_back(block_pool, cal_pc);
333 } 323 }
@@ -362,20 +352,14 @@ void CFG::AnalyzeCondInst(Block* block, FunctionId function_id, Location pc,
362 } 352 }
363 // Create a virtual block and a conditional block 353 // Create a virtual block and a conditional block
364 Block* const conditional_block{block_pool.Create()}; 354 Block* const conditional_block{block_pool.Create()};
365 Block virtual_block{ 355 Block virtual_block{};
366 .begin{block->begin.Virtual()}, 356 virtual_block.begin = block->begin.Virtual();
367 .end{block->begin.Virtual()}, 357 virtual_block.end = block->begin.Virtual();
368 .end_class{EndClass::Branch}, 358 virtual_block.end_class = EndClass::Branch;
369 .cond{cond}, 359 virtual_block.stack = block->stack;
370 .stack{block->stack}, 360 virtual_block.cond = cond;
371 .branch_true{conditional_block}, 361 virtual_block.branch_true = conditional_block;
372 .branch_false{nullptr}, 362 virtual_block.branch_false = nullptr;
373 .function_call{},
374 .return_block{},
375 .branch_reg{},
376 .branch_offset{},
377 .indirect_branches{},
378 };
379 // Save the contents of the visited block in the conditional block 363 // Save the contents of the visited block in the conditional block
380 *conditional_block = std::move(*block); 364 *conditional_block = std::move(*block);
381 // Impersonate the visited block with a virtual block 365 // Impersonate the visited block with a virtual block
@@ -444,7 +428,7 @@ CFG::AnalysisState CFG::AnalyzeBRX(Block* block, Location pc, Instruction inst,
444 if (!is_absolute) { 428 if (!is_absolute) {
445 target += pc.Offset(); 429 target += pc.Offset();
446 } 430 }
447 target += brx_table->branch_offset; 431 target += static_cast<unsigned int>(brx_table->branch_offset);
448 target += 8; 432 target += 8;
449 targets.push_back(target); 433 targets.push_back(target);
450 } 434 }
@@ -455,8 +439,8 @@ CFG::AnalysisState CFG::AnalyzeBRX(Block* block, Location pc, Instruction inst,
455 for (const u32 target : targets) { 439 for (const u32 target : targets) {
456 Block* const branch{AddLabel(block, block->stack, target, function_id)}; 440 Block* const branch{AddLabel(block, block->stack, target, function_id)};
457 block->indirect_branches.push_back({ 441 block->indirect_branches.push_back({
458 .block{branch}, 442 .block = branch,
459 .address{target}, 443 .address = target,
460 }); 444 });
461 } 445 }
462 block->cond = IR::Condition{true}; 446 block->cond = IR::Condition{true};
@@ -523,23 +507,17 @@ Block* CFG::AddLabel(Block* block, Stack stack, Location pc, FunctionId function
523 if (label_it != function.labels.end()) { 507 if (label_it != function.labels.end()) {
524 return label_it->block; 508 return label_it->block;
525 } 509 }
526 Block* const new_block{block_pool.Create(Block{ 510 Block* const new_block{block_pool.Create()};
527 .begin{pc}, 511 new_block->begin = pc;
528 .end{pc}, 512 new_block->end = pc;
529 .end_class{EndClass::Branch}, 513 new_block->end_class = EndClass::Branch;
530 .cond{true}, 514 new_block->cond = IR::Condition(true);
531 .stack{stack}, 515 new_block->stack = stack;
532 .branch_true{nullptr}, 516 new_block->branch_true = nullptr;
533 .branch_false{nullptr}, 517 new_block->branch_false = nullptr;
534 .function_call{},
535 .return_block{},
536 .branch_reg{},
537 .branch_offset{},
538 .indirect_branches{},
539 })};
540 function.labels.push_back(Label{ 518 function.labels.push_back(Label{
541 .address{pc}, 519 .address{pc},
542 .block{new_block}, 520 .block = new_block,
543 .stack{std::move(stack)}, 521 .stack{std::move(stack)},
544 }); 522 });
545 return new_block; 523 return new_block;