From 5fe23ccc3efb7f059580f01c2255624500ed1c7e Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 24 Jul 2021 10:08:02 +0200 Subject: [PATCH] DiscIO: Fix broken workaround for MSVC ARM64 ICE The workaround added in 30f9f31 caused a regression where Dolphin incorrectly replaced runs of one byte with runs of another byte when writing WIA and RVZ files. ReuseID::operator< was always returning false unless the ReuseIDs being compared had different partition keys, which caused std::map to treat all ReuseIDs with the same partition key as equal. --- Source/Core/DiscIO/WIABlob.h | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Source/Core/DiscIO/WIABlob.h b/Source/Core/DiscIO/WIABlob.h index 1714226ab311..cb27b5d71170 100644 --- a/Source/Core/DiscIO/WIABlob.h +++ b/Source/Core/DiscIO/WIABlob.h @@ -240,22 +240,26 @@ class WIARVZFileReader : public BlobReader struct ReuseID { - // This is a workaround for an ICE in Visual Studio 16.10.0 when making an ARM64 Release build. - // Once the ICE has been fixed upstream, we can move partition_key inside the tie. -#define COMPARE_TIED(op) \ - (partition_key op other.partition_key) && \ - std::tie(data_size, encrypted, value) \ - op std::tie(other.data_size, other.encrypted, other.value) - - bool operator==(const ReuseID& other) const { return COMPARE_TIED(==); } - bool operator<(const ReuseID& other) const { return COMPARE_TIED(<); } - bool operator>(const ReuseID& other) const { return COMPARE_TIED(>); } + // This code is a workaround for an ICE in Visual Studio 16.10.0 when making an ARM64 Release + // build. Once a fixed version of Visual Studio is released, we can use std::tie instead. +#define COMPARE_REUSE_ID_INNER(op, f, next) ((f != other.f) ? (f op other.f) : (next)) +#define COMPARE_REUSE_ID(op, equal_result) \ + COMPARE_REUSE_ID_INNER( \ + op, partition_key, \ + COMPARE_REUSE_ID_INNER( \ + op, data_size, \ + COMPARE_REUSE_ID_INNER(op, encrypted, COMPARE_REUSE_ID_INNER(op, value, equal_result)))) + + bool operator==(const ReuseID& other) const { return COMPARE_REUSE_ID(==, true); } + bool operator<(const ReuseID& other) const { return COMPARE_REUSE_ID(<, false); } + bool operator>(const ReuseID& other) const { return COMPARE_REUSE_ID(>, false); } bool operator!=(const ReuseID& other) const { return !operator==(other); } bool operator>=(const ReuseID& other) const { return !operator<(other); } bool operator<=(const ReuseID& other) const { return !operator>(other); } -#undef COMPARE_TIED +#undef COMPARE_REUSE_ID_INNER +#undef COMPARE_REUSE_ID WiiKey partition_key; u64 data_size;