summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/ir/basic_block.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/ir/basic_block.cpp')
-rw-r--r--src/shader_recompiler/frontend/ir/basic_block.cpp51
1 files changed, 37 insertions, 14 deletions
diff --git a/src/shader_recompiler/frontend/ir/basic_block.cpp b/src/shader_recompiler/frontend/ir/basic_block.cpp
index 0406726ad..e795618fc 100644
--- a/src/shader_recompiler/frontend/ir/basic_block.cpp
+++ b/src/shader_recompiler/frontend/ir/basic_block.cpp
@@ -37,6 +37,10 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op,
37 return result_it; 37 return result_it;
38} 38}
39 39
40void Block::AddImmediatePredecessor(IR::Block* immediate_predecessor) {
41 imm_predecessors.push_back(immediate_predecessor);
42}
43
40u32 Block::LocationBegin() const noexcept { 44u32 Block::LocationBegin() const noexcept {
41 return location_begin; 45 return location_begin;
42} 46}
@@ -53,6 +57,18 @@ const Block::InstructionList& Block::Instructions() const noexcept {
53 return instructions; 57 return instructions;
54} 58}
55 59
60std::span<IR::Block* const> Block::ImmediatePredecessors() const noexcept {
61 return imm_predecessors;
62}
63
64static std::string BlockToIndex(const std::map<const Block*, size_t>& block_to_index,
65 Block* block) {
66 if (const auto it{block_to_index.find(block)}; it != block_to_index.end()) {
67 return fmt::format("{{Block ${}}}", it->second);
68 }
69 return fmt::format("$<unknown block {:016x}>", reinterpret_cast<u64>(block));
70}
71
56static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_index, 72static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_index,
57 const std::map<const Inst*, size_t>& inst_to_index, 73 const std::map<const Inst*, size_t>& inst_to_index,
58 const Value& arg) { 74 const Value& arg) {
@@ -60,10 +76,7 @@ static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_ind
60 return "<null>"; 76 return "<null>";
61 } 77 }
62 if (arg.IsLabel()) { 78 if (arg.IsLabel()) {
63 if (const auto it{block_to_index.find(arg.Label())}; it != block_to_index.end()) { 79 return BlockToIndex(block_to_index, arg.Label());
64 return fmt::format("{{Block ${}}}", it->second);
65 }
66 return fmt::format("$<unknown block {:016x}>", reinterpret_cast<u64>(arg.Label()));
67 } 80 }
68 if (!arg.IsImmediate()) { 81 if (!arg.IsImmediate()) {
69 if (const auto it{inst_to_index.find(arg.Inst())}; it != inst_to_index.end()) { 82 if (const auto it{inst_to_index.find(arg.Inst())}; it != inst_to_index.end()) {
@@ -115,16 +128,26 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
115 } else { 128 } else {
116 ret += fmt::format(" {}", op); // '%00000 = ' -> 1 + 5 + 3 = 9 spaces 129 ret += fmt::format(" {}", op); // '%00000 = ' -> 1 + 5 + 3 = 9 spaces
117 } 130 }
118 const size_t arg_count{NumArgsOf(op)}; 131 if (op == Opcode::Phi) {
119 for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) { 132 size_t val_index{0};
120 const Value arg{inst.Arg(arg_index)}; 133 for (const auto& [phi_block, phi_val] : inst.PhiOperands()) {
121 ret += arg_index != 0 ? ", " : " "; 134 ret += val_index != 0 ? ", " : " ";
122 ret += ArgToIndex(block_to_index, inst_to_index, arg); 135 ret += fmt::format("[ {}, {} ]", ArgToIndex(block_to_index, inst_to_index, phi_val),
123 136 BlockToIndex(block_to_index, phi_block));
124 const Type actual_type{arg.Type()}; 137 ++val_index;
125 const Type expected_type{ArgTypeOf(op, arg_index)}; 138 }
126 if (!AreTypesCompatible(actual_type, expected_type)) { 139 } else {
127 ret += fmt::format("<type error: {} != {}>", actual_type, expected_type); 140 const size_t arg_count{NumArgsOf(op)};
141 for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) {
142 const Value arg{inst.Arg(arg_index)};
143 ret += arg_index != 0 ? ", " : " ";
144 ret += ArgToIndex(block_to_index, inst_to_index, arg);
145
146 const Type actual_type{arg.Type()};
147 const Type expected_type{ArgTypeOf(op, arg_index)};
148 if (!AreTypesCompatible(actual_type, expected_type)) {
149 ret += fmt::format("<type error: {} != {}>", actual_type, expected_type);
150 }
128 } 151 }
129 } 152 }
130 if (TypeOf(op) != Type::Void) { 153 if (TypeOf(op) != Type::Void) {