Merge branch 'master' of https://github.com/dolphin-emu/dolphin into dolphin-emu-master

This commit is contained in:
Nayla Hanegan 2024-10-23 14:29:49 -04:00
commit 4bd7d38a77
1243 changed files with 15939 additions and 15402 deletions

View file

@ -28,6 +28,7 @@
#endif
#include <fmt/format.h>
#include <fmt/ranges.h>
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
@ -332,5 +333,5 @@ std::string CPUInfo::Summarize()
if (bSHA2)
sum.push_back("SHA2");
return JoinStrings(sum, ",");
return fmt::to_string(fmt::join(sum, ","));
}

View file

@ -75,6 +75,8 @@ add_library(common
Hash.cpp
Hash.h
HookableEvent.h
HostDisassembler.cpp
HostDisassembler.h
HttpRequest.cpp
HttpRequest.h
Image.cpp
@ -180,6 +182,11 @@ PRIVATE
${VTUNE_LIBRARIES}
)
if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_64") OR
(NOT DEFINED CMAKE_ANDROID_ARCH_ABI AND _M_X86_64))
target_link_libraries(common PRIVATE bdisasm)
endif()
if (APPLE)
target_link_libraries(common
PRIVATE
@ -330,6 +337,28 @@ if(OPROFILE_FOUND)
target_link_libraries(common PRIVATE OProfile::OProfile)
endif()
if(ENABLE_LLVM)
find_package(LLVM CONFIG)
if(LLVM_FOUND)
message(STATUS "LLVM found, enabling LLVM support in disassembler")
target_compile_definitions(common PRIVATE HAVE_LLVM)
# Minimal documentation about LLVM's CMake functions is available here:
# https://releases.llvm.org/16.0.0/docs/CMake.html#embedding-llvm-in-your-project
# https://groups.google.com/g/llvm-dev/c/YeEVe7HTasQ?pli=1
#
# However, you have to read the source code in any case.
# Look for LLVM-Config.cmake in your (Unix) system:
# $ find /usr -name LLVM-Config\\.cmake 2>/dev/null
llvm_expand_pseudo_components(LLVM_EXPAND_COMPONENTS
AllTargetsInfos AllTargetsDisassemblers AllTargetsCodeGens
)
llvm_config(common USE_SHARED
mcdisassembler target ${LLVM_EXPAND_COMPONENTS}
)
target_include_directories(common PRIVATE ${LLVM_INCLUDE_DIRS})
endif()
endif()
if(UNIX)
# Posix networking code needs to be fixed for Windows
add_executable(traversal_server TraversalServer.cpp)

View file

@ -20,7 +20,6 @@ struct ConfigChangedCallbackID
size_t id = -1;
bool operator==(const ConfigChangedCallbackID&) const = default;
bool operator!=(const ConfigChangedCallbackID&) const = default;
};
using ConfigChangedCallback = std::function<void()>;

View file

@ -15,11 +15,6 @@ bool Location::operator==(const Location& other) const
strcasecmp(key.c_str(), other.key.c_str()) == 0;
}
bool Location::operator!=(const Location& other) const
{
return !(*this == other);
}
bool Location::operator<(const Location& other) const
{
if (system != other.system)

View file

@ -28,7 +28,6 @@ struct Location
std::string key;
bool operator==(const Location& other) const;
bool operator!=(const Location& other) const;
bool operator<(const Location& other) const;
};

View file

@ -252,8 +252,8 @@ Signature Sign(const u8* key, const u8* hash)
bn_mul(s.data.data(), minv, kk, ec_N, 30);
Signature signature;
std::copy(r.data.cbegin(), r.data.cend(), signature.begin());
std::copy(s.data.cbegin(), s.data.cend(), signature.begin() + 30);
std::ranges::copy(r.data, signature.begin());
std::ranges::copy(s.data, signature.begin() + 30);
return signature;
}

View file

@ -97,7 +97,7 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
// Remove duplicates (occurring because caller gave e.g. duplicate or overlapping directories -
// not because std::filesystem returns duplicates). Also note that this pathname-based uniqueness
// isn't as thorough as std::filesystem::equivalent.
std::sort(result.begin(), result.end());
std::ranges::sort(result);
result.erase(std::unique(result.begin(), result.end()), result.end());
// Dolphin expects to be able to use "/" (DIR_SEP) everywhere.
@ -107,7 +107,7 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
if constexpr (os_separator != DIR_SEP_CHR)
{
for (auto& path : result)
std::replace(path.begin(), path.end(), '\\', DIR_SEP_CHR);
std::ranges::replace(path, '\\', DIR_SEP_CHR);
}
return result;

View file

@ -446,7 +446,7 @@ FSTEntry ScanDirectoryTree(std::string directory, bool recursive)
// about with directory separators (for host paths - emulated paths may require it) and instead
// use fs::path to interact with them.
auto wpath = path.wstring();
std::replace(wpath.begin(), wpath.end(), L'\\', L'/');
std::ranges::replace(wpath, L'\\', L'/');
return WStringToUTF8(wpath);
#else
return PathToString(path);

View file

@ -0,0 +1,158 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Common/HostDisassembler.h"
#include <span>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <fmt/ranges.h>
#if defined(HAVE_LLVM)
#include <llvm-c/Disassembler.h>
#include <llvm-c/Target.h>
#elif defined(_M_X86_64)
#include <disasm.h> // Bochs
#endif
#if defined(HAVE_LLVM)
class HostDisassemblerLLVM final : public HostDisassembler
{
public:
explicit HostDisassemblerLLVM(const char* host_disasm, const char* cpu = "",
std::size_t inst_size = 0);
~HostDisassemblerLLVM();
private:
LLVMDisasmContextRef m_llvm_context;
std::size_t m_instruction_size;
std::size_t Disassemble(const u8* begin, const u8* end, std::ostream& stream) override;
};
HostDisassemblerLLVM::HostDisassemblerLLVM(const char* host_disasm, const char* cpu,
std::size_t inst_size)
: m_instruction_size(inst_size)
{
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();
m_llvm_context = LLVMCreateDisasmCPU(host_disasm, cpu, nullptr, 0, nullptr, nullptr);
// Couldn't create llvm context
if (!m_llvm_context)
return;
LLVMSetDisasmOptions(m_llvm_context, LLVMDisassembler_Option_AsmPrinterVariant |
LLVMDisassembler_Option_PrintLatency);
}
HostDisassemblerLLVM::~HostDisassemblerLLVM()
{
if (m_llvm_context)
LLVMDisasmDispose(m_llvm_context);
}
std::size_t HostDisassemblerLLVM::Disassemble(const u8* begin, const u8* end, std::ostream& stream)
{
std::size_t instruction_count = 0;
if (!m_llvm_context)
return instruction_count;
while (begin < end)
{
char inst_disasm[256];
const auto inst_size =
LLVMDisasmInstruction(m_llvm_context, const_cast<u8*>(begin), static_cast<u64>(end - begin),
reinterpret_cast<u64>(begin), inst_disasm, sizeof(inst_disasm));
if (inst_size == 0)
{
if (m_instruction_size != 0)
{
// If we are on an architecture that has a fixed instruction
// size, we can continue onward past this bad instruction.
fmt::println(stream, "{}\tInvalid inst: {:02x}", fmt::ptr(begin),
fmt::join(std::span{begin, m_instruction_size}, ""));
begin += m_instruction_size;
}
else
{
// We can't continue if we are on an architecture that has flexible
// instruction sizes. Dump the rest of the block instead.
fmt::println(stream, "{}\tInvalid inst: {:02x}", fmt::ptr(begin),
fmt::join(std::span{begin, end}, ""));
break;
}
}
else
{
fmt::println(stream, "{}{}", fmt::ptr(begin), inst_disasm);
begin += inst_size;
}
++instruction_count;
}
return instruction_count;
}
#elif defined(_M_X86_64)
class HostDisassemblerBochs final : public HostDisassembler
{
public:
explicit HostDisassemblerBochs();
~HostDisassemblerBochs() = default;
private:
disassembler m_disasm;
std::size_t Disassemble(const u8* begin, const u8* end, std::ostream& stream) override;
};
HostDisassemblerBochs::HostDisassemblerBochs()
{
m_disasm.set_syntax_intel();
}
std::size_t HostDisassemblerBochs::Disassemble(const u8* begin, const u8* end, std::ostream& stream)
{
std::size_t instruction_count = 0;
while (begin < end)
{
char inst_disasm[256];
const auto inst_size =
m_disasm.disasm64(0, reinterpret_cast<bx_address>(begin), begin, inst_disasm);
fmt::println(stream, "{}\t{}", fmt::ptr(begin), inst_disasm);
begin += inst_size;
++instruction_count;
}
return instruction_count;
}
#endif
std::unique_ptr<HostDisassembler> HostDisassembler::Factory(Platform arch)
{
switch (arch)
{
#if defined(HAVE_LLVM)
case Platform::x86_64:
return std::make_unique<HostDisassemblerLLVM>("x86_64-none-unknown");
case Platform::aarch64:
return std::make_unique<HostDisassemblerLLVM>("aarch64-none-unknown", "cortex-a57", 4);
#elif defined(_M_X86_64)
case Platform::x86_64:
return std::make_unique<HostDisassemblerBochs>();
#else
case Platform{}: // warning C4065: "switch statement contains 'default' but no 'case' labels"
#endif
default:
return std::make_unique<HostDisassembler>();
}
}
std::size_t HostDisassembler::Disassemble(const u8* begin, const u8* end, std::ostream& stream)
{
fmt::println(stream, "{}\t{:02x}", fmt::ptr(begin), fmt::join(std::span{begin, end}, ""));
return 0;
}

View file

@ -0,0 +1,26 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <cstddef>
#include <iosfwd>
#include <memory>
#include "Common/CommonTypes.h"
class HostDisassembler
{
public:
enum class Platform
{
x86_64,
aarch64,
};
virtual ~HostDisassembler() = default;
static std::unique_ptr<HostDisassembler> Factory(Platform arch);
virtual std::size_t Disassemble(const u8* begin, const u8* end, std::ostream& stream);
};

View file

@ -85,7 +85,7 @@ bool IniFile::Section::Delete(std::string_view key)
return false;
values.erase(it);
keys_order.erase(std::find(keys_order.begin(), keys_order.end(), key));
keys_order.erase(std::ranges::find(keys_order, key));
return true;
}
@ -130,7 +130,7 @@ const IniFile::Section* IniFile::GetSection(std::string_view section_name) const
{
for (const Section& sect : sections)
{
if (CaseInsensitiveStringCompare::IsEqual(sect.name, section_name))
if (CaseInsensitiveEquals(sect.name, section_name))
return &sect;
}
@ -141,7 +141,7 @@ IniFile::Section* IniFile::GetSection(std::string_view section_name)
{
for (Section& sect : sections)
{
if (CaseInsensitiveStringCompare::IsEqual(sect.name, section_name))
if (CaseInsensitiveEquals(sect.name, section_name))
return &sect;
}

View file

@ -15,29 +15,6 @@
namespace Common
{
struct CaseInsensitiveStringCompare
{
// Allow heterogenous lookup.
using is_transparent = void;
bool operator()(std::string_view a, std::string_view b) const
{
return std::lexicographical_compare(
a.begin(), a.end(), b.begin(), b.end(),
[](char lhs, char rhs) { return Common::ToLower(lhs) < Common::ToLower(rhs); });
}
static bool IsEqual(std::string_view a, std::string_view b)
{
if (a.size() != b.size())
return false;
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char lhs, char rhs) {
return Common::ToLower(lhs) == Common::ToLower(rhs);
});
}
};
class IniFile
{
public:
@ -86,7 +63,7 @@ public:
bool GetLines(std::vector<std::string>* lines, const bool remove_comments = true) const;
bool operator<(const Section& other) const { return name < other.name; }
using SectionMap = std::map<std::string, std::string, CaseInsensitiveStringCompare>;
using SectionMap = std::map<std::string, std::string, CaseInsensitiveLess>;
const std::string& GetName() const { return name; }
const SectionMap& GetValues() const { return values; }

View file

@ -8,6 +8,7 @@
#include <vector>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
@ -141,7 +142,7 @@ std::string EscapePath(const std::string& path)
for (const std::string& split_string : split_strings)
escaped_split_strings.push_back(EscapeFileName(split_string));
return JoinStrings(escaped_split_strings, "/");
return fmt::to_string(fmt::join(escaped_split_strings, "/"));
}
std::string UnescapeFileName(const std::string& filename)

View file

@ -36,10 +36,10 @@ MACAddress GenerateMacAddress(const MACConsumer type)
switch (type)
{
case MACConsumer::BBA:
std::copy(oui_bba.begin(), oui_bba.end(), mac.begin());
std::ranges::copy(oui_bba, mac.begin());
break;
case MACConsumer::IOS:
std::copy(oui_ios.begin(), oui_ios.end(), mac.begin());
std::ranges::copy(oui_ios, mac.begin());
break;
}

View file

@ -22,6 +22,7 @@
#include <vector>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include "Common/CommonFuncs.h"
#include "Common/CommonPaths.h"
@ -233,8 +234,8 @@ std::string_view StripQuotes(std::string_view s)
// Turns "\n\rhello" into " hello".
void ReplaceBreaksWithSpaces(std::string& str)
{
std::replace(str.begin(), str.end(), '\r', ' ');
std::replace(str.begin(), str.end(), '\n', ' ');
std::ranges::replace(str, '\r', ' ');
std::ranges::replace(str, '\n', ' ');
}
void TruncateToCString(std::string* s)
@ -367,21 +368,6 @@ std::vector<std::string> SplitString(const std::string& str, const char delim)
return output;
}
std::string JoinStrings(const std::vector<std::string>& strings, const std::string& delimiter)
{
// Check if we can return early, just for speed
if (strings.empty())
return "";
std::ostringstream res;
std::copy(strings.begin(), strings.end(),
std::ostream_iterator<std::string>(res, delimiter.c_str()));
// Drop the trailing delimiter.
std::string joined = res.str();
return joined.substr(0, joined.length() - delimiter.length());
}
std::string TabsToSpaces(int tab_size, std::string str)
{
const std::string spaces(tab_size, ' ');
@ -417,8 +403,7 @@ void StringPopBackIf(std::string* s, char c)
size_t StringUTF8CodePointCount(std::string_view str)
{
return str.size() -
std::count_if(str.begin(), str.end(), [](char c) -> bool { return (c & 0xC0) == 0x80; });
return str.size() - std::ranges::count_if(str, [](char c) -> bool { return (c & 0xC0) == 0x80; });
}
#ifdef _WIN32
@ -670,20 +655,24 @@ std::string GetEscapedHtml(std::string html)
void ToLower(std::string* str)
{
std::transform(str->begin(), str->end(), str->begin(), [](char c) { return Common::ToLower(c); });
std::ranges::transform(*str, str->begin(), static_cast<char (&)(char)>(Common::ToLower));
}
void ToUpper(std::string* str)
{
std::transform(str->begin(), str->end(), str->begin(), [](char c) { return Common::ToUpper(c); });
std::ranges::transform(*str, str->begin(), static_cast<char (&)(char)>(Common::ToUpper));
}
bool CaseInsensitiveEquals(std::string_view a, std::string_view b)
{
if (a.size() != b.size())
return false;
return std::equal(a.begin(), a.end(), b.begin(),
[](char ca, char cb) { return Common::ToLower(ca) == Common::ToLower(cb); });
return std::ranges::equal(
a, b, [](char ca, char cb) { return Common::ToLower(ca) == Common::ToLower(cb); });
}
bool CaseInsensitiveLess::operator()(std::string_view a, std::string_view b) const
{
return std::ranges::lexicographical_compare(
a, b, [](char ca, char cb) { return Common::ToLower(ca) < Common::ToLower(cb); });
}
std::string BytesToHexString(std::span<const u8> bytes)

View file

@ -200,7 +200,6 @@ std::from_chars_result FromChars(std::string_view sv, T& value,
std::string TabsToSpaces(int tab_size, std::string str);
std::vector<std::string> SplitString(const std::string& str, char delim);
std::string JoinStrings(const std::vector<std::string>& strings, const std::string& delimiter);
// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe"
// This requires forward slashes to be used for the path separators, even on Windows.
@ -314,5 +313,13 @@ std::string GetEscapedHtml(std::string html);
void ToLower(std::string* str);
void ToUpper(std::string* str);
bool CaseInsensitiveEquals(std::string_view a, std::string_view b);
// 'std::less'-like comparison function object type for case-insensitive strings.
struct CaseInsensitiveLess
{
using is_transparent = void; // Allow heterogenous lookup.
bool operator()(std::string_view a, std::string_view b) const;
};
std::string BytesToHexString(std::span<const u8> bytes);
} // namespace Common

View file

@ -14,6 +14,7 @@
#include <thread>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include "Common/CommonTypes.h"
#include "Common/Intrinsics.h"
@ -275,5 +276,5 @@ std::string CPUInfo::Summarize()
if (bSHA2)
sum.push_back("SHA2");
return JoinStrings(sum, ",");
return fmt::to_string(fmt::join(sum, ","));
}

View file

@ -122,7 +122,6 @@ struct OpArg
return std::tie(scale, offsetOrBaseReg, indexReg, offset, operandReg) ==
std::tie(b.scale, b.offsetOrBaseReg, b.indexReg, b.offset, b.operandReg);
}
constexpr bool operator!=(const OpArg& b) const { return !operator==(b); }
u64 Imm64() const
{
DEBUG_ASSERT(scale == SCALE_IMM64);