SPU: More UB fixes

This commit is contained in:
Elad 2026-05-14 13:21:23 +03:00 committed by GitHub
parent c860aa2107
commit 53d76db753
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 20 additions and 16 deletions

View File

@ -1222,7 +1222,7 @@ void spu_cache::initialize(bool build_existing_cache)
} }
// Initialize global cache instance // Initialize global cache instance
if (g_cfg.core.spu_cache && cache) if (g_cfg.core.spu_cache && !spu_precompilation_enabled && cache)
{ {
g_fxo->get<spu_cache>() = std::move(cache); g_fxo->get<spu_cache>() = std::move(cache);
} }
@ -1282,8 +1282,8 @@ spu_runtime::spu_runtime()
fs::remove_all(m_cache_path + "llvm/", false); fs::remove_all(m_cache_path + "llvm/", false);
} }
fs::file(m_cache_path + "spu.log", fs::rewrite); fs::write_file(m_cache_path + "spu.log", fs::rewrite);
fs::file(m_cache_path + "spu-ir.log", fs::rewrite); fs::write_file(m_cache_path + "spu-ir.log", fs::rewrite);
} }
} }
@ -3215,10 +3215,13 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
jt_abs.clear(); jt_abs.clear();
} }
// If this fails, this is a TODO to compare them in another way
ensure(jt_abs.size() != jt_rel.size()); ensure(jt_abs.size() != jt_rel.size());
} }
if (jt_abs.size() >= jt_rel.size()) const bool abs_domainates = jt_abs.size() > jt_rel.size();
if (abs_domainates)
{ {
const u32 new_size = (start - lsa) / 4 + ::size32(jt_abs); const u32 new_size = (start - lsa) / 4 + ::size32(jt_abs);
@ -3236,8 +3239,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
m_targets.emplace(pos, std::move(jt_abs)); m_targets.emplace(pos, std::move(jt_abs));
} }
else
if (jt_rel.size() >= jt_abs.size())
{ {
const u32 new_size = (start - lsa) / 4 + ::size32(jt_rel); const u32 new_size = (start - lsa) / 4 + ::size32(jt_rel);
@ -8766,6 +8768,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
void spu_recompiler_base::dump(const spu_program& result, std::string& out, u32 block_min, u32 block_max) void spu_recompiler_base::dump(const spu_program& result, std::string& out, u32 block_min, u32 block_max)
{ {
block_max = std::min<u32>(block_max, SPU_LS_SIZE);
SPUDisAsm dis_asm(cpu_disasm_mode::dump, reinterpret_cast<const u8*>(result.data.data()), result.lower_bound); SPUDisAsm dis_asm(cpu_disasm_mode::dump, reinterpret_cast<const u8*>(result.data.data()), result.lower_bound);
std::string hash; std::string hash;

View File

@ -2637,7 +2637,7 @@ public:
for (u32 iteration_emit = 0; is_reduced_loop; m_pos += 4) for (u32 iteration_emit = 0; is_reduced_loop; m_pos += 4)
{ {
if (m_pos != baddr && m_block_info[m_pos / 4] && m_reduced_loop_info->loop_end < m_pos) if (m_pos != baddr && m_pos != SPU_LS_SIZE && m_block_info[m_pos / 4] && m_reduced_loop_info->loop_end < m_pos)
{ {
fmt::throw_exception("LLVM: Reduced Loop Pattern: Exit(1) too early at 0x%x", m_pos); fmt::throw_exception("LLVM: Reduced Loop Pattern: Exit(1) too early at 0x%x", m_pos);
} }
@ -3217,7 +3217,7 @@ public:
for (u32 target : m_bbs[cur].targets) for (u32 target : m_bbs[cur].targets)
{ {
if (!m_block_info[target / 4]) if (target == SPU_LS_SIZE || !m_block_info[target / 4])
{ {
continue; continue;
} }
@ -9066,7 +9066,7 @@ public:
for (u32 target : tfound->second) for (u32 target : tfound->second)
{ {
if (m_block_info[target / 4]) if (target != SPU_LS_SIZE && m_block_info[target / 4])
{ {
targets.emplace(target, nullptr); targets.emplace(target, nullptr);
} }

View File

@ -714,14 +714,14 @@ protected:
u64 m_hash_start; u64 m_hash_start;
// Bit indicating start of the block // Bit indicating start of the block
std::bitset<0x10000> m_block_info; std::bitset<SPU_LS_SIZE / 4> m_block_info;
// GPR modified by the instruction (-1 = not set) // GPR modified by the instruction (-1 = not set)
std::array<u8, 0x10000> m_regmod; std::array<u8, SPU_LS_SIZE / 4> m_regmod;
std::bitset<0x10000> m_use_ra; std::bitset<SPU_LS_SIZE / 4> m_use_ra;
std::bitset<0x10000> m_use_rb; std::bitset<SPU_LS_SIZE / 4> m_use_rb;
std::bitset<0x10000> m_use_rc; std::bitset<SPU_LS_SIZE / 4> m_use_rc;
// List of possible targets for the instruction (entry shouldn't exist for simple instructions) // List of possible targets for the instruction (entry shouldn't exist for simple instructions)
std::unordered_map<u32, std::vector<u32>, value_hash<u32, 2>> m_targets; std::unordered_map<u32, std::vector<u32>, value_hash<u32, 2>> m_targets;
@ -730,10 +730,10 @@ protected:
std::unordered_map<u32, std::vector<u32>, value_hash<u32, 2>> m_preds; std::unordered_map<u32, std::vector<u32>, value_hash<u32, 2>> m_preds;
// List of function entry points and return points (set after BRSL, BRASL, BISL, BISLED) // List of function entry points and return points (set after BRSL, BRASL, BISL, BISLED)
std::bitset<0x10000> m_entry_info; std::bitset<SPU_LS_SIZE / 4> m_entry_info;
// Set after return points and disjoint chunks // Set after return points and disjoint chunks
std::bitset<0x10000> m_ret_info; std::bitset<SPU_LS_SIZE / 4> m_ret_info;
// Basic block information // Basic block information
struct block_info struct block_info