mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-20 08:18:59 +02:00
[cmake] enable clang-cl and WoA builds (#348)
Compilation and CMake fixes for both Windows on ARM and clang-cl, meaning Windows can now be built on both MSVC and clang on both amd64 and aarch64. Compiling on clang is *dramatically* faster so this should be useful for CI. Co-authored-by: crueter <crueter@eden-emu.dev> Co-authored-by: crueter <crueter@crueter.xyz> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/348 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
428f136a75
commit
9d2681ecc9
276 changed files with 973 additions and 1010 deletions
|
|
@ -237,7 +237,7 @@ else()
|
|||
)
|
||||
|
||||
# Get around GCC failing with intrinsics in Debug
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
if(CXX_GCC AND CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
set_property(
|
||||
SOURCE stb.cpp
|
||||
APPEND
|
||||
|
|
@ -245,7 +245,7 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if(CXX_CLANG)
|
||||
target_compile_options(common PRIVATE -fsized-deallocation
|
||||
-Werror=unreachable-code-aggressive)
|
||||
target_compile_definitions(
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ public:
|
|||
|
||||
// If we are, join with them, ensuring we stay in bounds.
|
||||
if (it != m_free_regions.end()) {
|
||||
start_address = std::min(start_address, it->lower());
|
||||
end_address = std::max(end_address, it->upper());
|
||||
start_address = (std::min)(start_address, it->lower());
|
||||
end_address = (std::max)(end_address, it->upper());
|
||||
}
|
||||
|
||||
// Free the relevant region.
|
||||
|
|
|
|||
|
|
@ -484,9 +484,9 @@ std::string GetParentPath(std::string_view path) {
|
|||
std::size_t name_index;
|
||||
|
||||
if (name_bck_index == std::string_view::npos || name_fwd_index == std::string_view::npos) {
|
||||
name_index = std::min(name_bck_index, name_fwd_index);
|
||||
name_index = (std::min)(name_bck_index, name_fwd_index);
|
||||
} else {
|
||||
name_index = std::max(name_bck_index, name_fwd_index);
|
||||
name_index = (std::max)(name_bck_index, name_fwd_index);
|
||||
}
|
||||
|
||||
return std::string(path.substr(0, name_index));
|
||||
|
|
@ -506,7 +506,7 @@ std::string_view GetPathWithoutTop(std::string_view path) {
|
|||
|
||||
const auto name_bck_index = path.find('\\');
|
||||
const auto name_fwd_index = path.find('/');
|
||||
return path.substr(std::min(name_bck_index, name_fwd_index) + 1);
|
||||
return path.substr((std::min)(name_bck_index, name_fwd_index) + 1);
|
||||
}
|
||||
|
||||
} // namespace Common::FS
|
||||
|
|
|
|||
|
|
@ -144,8 +144,7 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p
|
|||
}
|
||||
|
||||
// Clamp to end.
|
||||
next = std::min(next, end);
|
||||
|
||||
next = (std::min)(next, end);
|
||||
// Reprotect, if we need to.
|
||||
if (should_protect) {
|
||||
m_buffer.Protect(cur, next - cur, perm);
|
||||
|
|
@ -211,8 +210,8 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() {
|
|||
// Despite being worse in theory, this has proven to be better in practice than more
|
||||
// regularly dumping a smaller amount, because it significantly reduces average case
|
||||
// lock contention.
|
||||
const size_t desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2;
|
||||
const size_t evict_count = m_resident_map_count - desired_count;
|
||||
std::size_t const desired_count = (std::min)(m_resident_map_count, m_max_resident_map_count) / 2;
|
||||
std::size_t const evict_count = m_resident_map_count - desired_count;
|
||||
auto it = m_resident_mappings.begin();
|
||||
|
||||
for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) {
|
||||
|
|
|
|||
|
|
@ -199,8 +199,8 @@ public:
|
|||
std::scoped_lock lock{placeholder_mutex};
|
||||
auto [it, end] = placeholders.equal_range({virtual_offset, virtual_end});
|
||||
while (it != end) {
|
||||
const size_t offset = std::max(it->lower(), virtual_offset);
|
||||
const size_t protect_length = std::min(it->upper(), virtual_end) - offset;
|
||||
const size_t offset = (std::max)(it->lower(), virtual_offset);
|
||||
const size_t protect_length = (std::min)(it->upper(), virtual_end) - offset;
|
||||
DWORD old_flags{};
|
||||
if (!VirtualProtect(virtual_base + offset, protect_length, new_flags, &old_flags)) {
|
||||
LOG_CRITICAL(HW_Memory, "Failed to change virtual memory protect rules");
|
||||
|
|
@ -266,8 +266,8 @@ private:
|
|||
}
|
||||
const size_t placeholder_begin = it->lower();
|
||||
const size_t placeholder_end = it->upper();
|
||||
const size_t unmap_begin = std::max(virtual_offset, placeholder_begin);
|
||||
const size_t unmap_end = std::min(virtual_offset + length, placeholder_end);
|
||||
const size_t unmap_begin = (std::max)(virtual_offset, placeholder_begin);
|
||||
const size_t unmap_end = (std::min)(virtual_offset + length, placeholder_end);
|
||||
ASSERT(unmap_begin >= placeholder_begin && unmap_begin < placeholder_end);
|
||||
ASSERT(unmap_end <= placeholder_end && unmap_end > placeholder_begin);
|
||||
|
||||
|
|
@ -655,8 +655,8 @@ private:
|
|||
*virtual_offset = 0;
|
||||
*length = 0;
|
||||
} else {
|
||||
*virtual_offset = std::max(intended_start, address_space_start);
|
||||
*length = std::min(intended_end, address_space_end) - *virtual_offset;
|
||||
*virtual_offset = (std::max)(intended_start, address_space_start);
|
||||
*length = (std::min)(intended_end, address_space_end) - *virtual_offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ constexpr const char* TrimSourcePath(std::string_view source) {
|
|||
const auto rfind = [source](const std::string_view match) {
|
||||
return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size());
|
||||
};
|
||||
auto idx = std::max({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")});
|
||||
auto idx = (std::max)({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")});
|
||||
return source.data() + idx;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,10 +85,10 @@ struct Rectangle {
|
|||
}
|
||||
|
||||
[[nodiscard]] constexpr bool Intersect(const Rectangle<T>& with, Rectangle<T>* result) const {
|
||||
result->left = std::max(left, with.left);
|
||||
result->top = std::max(top, with.top);
|
||||
result->right = std::min(right, with.right);
|
||||
result->bottom = std::min(bottom, with.bottom);
|
||||
result->left = (std::max)(left, with.left);
|
||||
result->top = (std::max)(top, with.top);
|
||||
result->right = (std::min)(right, with.right);
|
||||
result->bottom = (std::min)(bottom, with.bottom);
|
||||
return !result->IsEmpty();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ template <typename T>
|
|||
inline bool CanAddWithoutOverflow(T lhs, T rhs) {
|
||||
#ifdef _MSC_VER
|
||||
if (lhs >= 0 && rhs >= 0) {
|
||||
return WrappingAdd(lhs, rhs) >= std::max(lhs, rhs);
|
||||
return WrappingAdd(lhs, rhs) >= (std::max)(lhs, rhs);
|
||||
} else if (lhs < 0 && rhs < 0) {
|
||||
return WrappingAdd(lhs, rhs) <= std::min(lhs, rhs);
|
||||
return WrappingAdd(lhs, rhs) <= (std::min)(lhs, rhs);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ private:
|
|||
|
||||
public:
|
||||
explicit RangeMap(ValueT null_value_) : null_value{null_value_} {
|
||||
container.emplace(std::numeric_limits<KeyT>::min(), null_value);
|
||||
container.emplace((std::numeric_limits<KeyT>::min)(), null_value);
|
||||
};
|
||||
~RangeMap() = default;
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ private:
|
|||
}
|
||||
const auto it_end = std::next(it);
|
||||
if (it_end == container.end()) {
|
||||
return std::numeric_limits<KeyT>::max() - address;
|
||||
return (std::numeric_limits<KeyT>::max)() - address;
|
||||
}
|
||||
return it_end->first - address;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ void OverlapRangeSet<AddressType>::Subtract(AddressType base_address, size_t siz
|
|||
|
||||
template <typename AddressType>
|
||||
void OverlapRangeSet<AddressType>::DeleteAll(AddressType base_address, size_t size) {
|
||||
m_impl->template Subtract<false>(base_address, size, std::numeric_limits<s32>::max(),
|
||||
m_impl->template Subtract<false>(base_address, size, (std::numeric_limits<s32>::max)(),
|
||||
[](AddressType, AddressType) {});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class RingBuffer {
|
|||
// T must be safely memcpy-able and have a trivial default constructor.
|
||||
static_assert(std::is_trivial_v<T>);
|
||||
// Ensure capacity is sensible.
|
||||
static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2);
|
||||
static_assert(capacity < (std::numeric_limits<std::size_t>::max)() / 2);
|
||||
static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two");
|
||||
// Ensure lock-free.
|
||||
static_assert(std::atomic_size_t::is_always_lock_free);
|
||||
|
|
@ -43,9 +43,9 @@ public:
|
|||
std::lock_guard lock(rb_mutex);
|
||||
|
||||
const std::size_t slots_free = capacity + read_index - write_index;
|
||||
const std::size_t push_count = std::min(slot_count, slots_free);
|
||||
const std::size_t push_count = (std::min)(slot_count, slots_free);
|
||||
const std::size_t pos = write_index % capacity;
|
||||
const std::size_t first_copy = std::min(capacity - pos, push_count);
|
||||
const std::size_t first_copy = (std::min)(capacity - pos, push_count);
|
||||
const std::size_t second_copy = push_count - first_copy;
|
||||
|
||||
const char* in = static_cast<const char*>(new_slots);
|
||||
|
|
@ -69,9 +69,9 @@ public:
|
|||
std::lock_guard lock(rb_mutex);
|
||||
|
||||
const std::size_t slots_filled = write_index - read_index;
|
||||
const std::size_t pop_count = std::min(slots_filled, max_slots);
|
||||
const std::size_t pop_count = (std::min)(slots_filled, max_slots);
|
||||
const std::size_t pos = read_index % capacity;
|
||||
const std::size_t first_copy = std::min(capacity - pos, pop_count);
|
||||
const std::size_t first_copy = (std::min)(capacity - pos, pop_count);
|
||||
const std::size_t second_copy = pop_count - first_copy;
|
||||
|
||||
char* out = static_cast<char*>(output);
|
||||
|
|
@ -84,7 +84,7 @@ public:
|
|||
}
|
||||
|
||||
std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) {
|
||||
std::vector<T> out(std::min(max_slots, capacity));
|
||||
std::vector<T> out((std::min)(max_slots, capacity));
|
||||
const std::size_t count = Pop(out.data(), out.size());
|
||||
out.resize(count);
|
||||
return out;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/scm_rev.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
#define GIT_REV "@GIT_REV@"
|
||||
#define GIT_BRANCH "@GIT_BRANCH@"
|
||||
#define GIT_DESC "@GIT_DESC@"
|
||||
|
|
@ -18,64 +17,21 @@
|
|||
#define TITLE_BAR_FORMAT_IDLE "@TITLE_BAR_FORMAT_IDLE@"
|
||||
#define TITLE_BAR_FORMAT_RUNNING "@TITLE_BAR_FORMAT_RUNNING@"
|
||||
#define IS_DEV_BUILD @IS_DEV_BUILD@
|
||||
#define COMPILER_ID "@CXX_COMPILER@"
|
||||
|
||||
namespace Common {
|
||||
|
||||
const char* g_scm_rev;
|
||||
const char* g_scm_branch;
|
||||
const char* g_scm_desc;
|
||||
const char g_build_name[] = BUILD_NAME;
|
||||
const char g_build_date[] = BUILD_DATE;
|
||||
const char g_build_fullname[] = BUILD_FULLNAME;
|
||||
const char g_build_version[] = BUILD_VERSION;
|
||||
const char g_build_id[] = BUILD_ID;
|
||||
const char g_title_bar_format_idle[] = TITLE_BAR_FORMAT_IDLE;
|
||||
const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING;
|
||||
const bool g_is_dev_build = IS_DEV_BUILD;
|
||||
constexpr const char g_scm_rev[] = GIT_REV;
|
||||
constexpr const char g_scm_branch[] = GIT_BRANCH;
|
||||
constexpr const char g_scm_desc[] = GIT_DESC;
|
||||
constexpr const char g_build_name[] = BUILD_NAME;
|
||||
constexpr const char g_build_date[] = BUILD_DATE;
|
||||
constexpr const char g_build_fullname[] = BUILD_FULLNAME;
|
||||
constexpr const char g_build_version[] = BUILD_VERSION;
|
||||
constexpr const char g_build_id[] = BUILD_ID;
|
||||
constexpr const char g_title_bar_format_idle[] = TITLE_BAR_FORMAT_IDLE;
|
||||
constexpr const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING;
|
||||
constexpr const bool g_is_dev_build = IS_DEV_BUILD;
|
||||
constexpr const char g_compiler_id[] = COMPILER_ID;
|
||||
|
||||
/// Anonymizes SCM data
|
||||
/// This is quite weak. But better than nothing.
|
||||
class scm_encrypt {
|
||||
std::string m_scm_rev, m_scm_branch, m_scm_desc;
|
||||
|
||||
public:
|
||||
scm_encrypt() {
|
||||
// Get a key that is easy to obtain when asking the person directly but (usually) hard to
|
||||
// guess
|
||||
std::string key;
|
||||
#ifdef __linux__
|
||||
if (!std::getline(std::ifstream("/proc/sys/kernel/hostname"), key))
|
||||
key = "linux_error_key";
|
||||
#else
|
||||
// Not a good fallback, but better than nothing I guess?
|
||||
key = g_build_date;
|
||||
#endif
|
||||
// Copy strings in place
|
||||
m_scm_rev = GIT_REV;
|
||||
m_scm_branch = GIT_BRANCH;
|
||||
m_scm_desc = GIT_DESC;
|
||||
// XOR each string with key
|
||||
auto key_it = key.begin();
|
||||
for (auto& string : {&m_scm_rev, &m_scm_branch, &m_scm_desc}) {
|
||||
for (auto& c : *string) {
|
||||
c ^= *key_it;
|
||||
if (++key_it == key.end())
|
||||
key_it = key.begin();
|
||||
}
|
||||
}
|
||||
// Make each string human-readable
|
||||
for (auto& string : {&m_scm_rev, &m_scm_branch, &m_scm_desc}) {
|
||||
const std::string original = *string;
|
||||
string->clear();
|
||||
for (const auto c : original) {
|
||||
string->append(fmt::format("{:x}", unsigned(c)));
|
||||
}
|
||||
string->pop_back();
|
||||
}
|
||||
// Set pointers
|
||||
g_scm_rev = m_scm_rev.c_str();
|
||||
g_scm_branch = m_scm_branch.c_str();
|
||||
g_scm_desc = m_scm_desc.c_str();
|
||||
}
|
||||
} scm_encrypt_instance;
|
||||
} // namespace Common
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -5,9 +8,9 @@
|
|||
|
||||
namespace Common {
|
||||
|
||||
extern const char* g_scm_rev;
|
||||
extern const char* g_scm_branch;
|
||||
extern const char* g_scm_desc;
|
||||
extern const char g_scm_rev[];
|
||||
extern const char g_scm_branch[];
|
||||
extern const char g_scm_desc[];
|
||||
extern const char g_build_name[];
|
||||
extern const char g_build_date[];
|
||||
extern const char g_build_fullname[];
|
||||
|
|
@ -17,5 +20,6 @@ extern const char g_title_bar_format_idle[];
|
|||
extern const char g_title_bar_format_running[];
|
||||
extern const char g_shader_cache_version[];
|
||||
extern const bool g_is_dev_build;
|
||||
extern const char g_compiler_id[];
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@ struct ResolutionScalingInfo {
|
|||
if (value == 0) {
|
||||
return 0;
|
||||
}
|
||||
return std::max((value * static_cast<s32>(up_scale)) >> static_cast<s32>(down_shift), 1);
|
||||
return (std::max)((value * static_cast<s32>(up_scale)) >> static_cast<s32>(down_shift), 1);
|
||||
}
|
||||
|
||||
u32 ScaleUp(u32 value) const {
|
||||
if (value == 0U) {
|
||||
return 0U;
|
||||
}
|
||||
return std::max((value * up_scale) >> down_shift, 1U);
|
||||
return (std::max)((value * up_scale) >> down_shift, 1U);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -612,8 +612,8 @@ struct Values {
|
|||
false, true, &custom_rtc_enabled};
|
||||
SwitchableSetting<s64, true> custom_rtc_offset{linkage,
|
||||
0,
|
||||
std::numeric_limits<int>::min(),
|
||||
std::numeric_limits<int>::max(),
|
||||
(std::numeric_limits<int>::min)(),
|
||||
(std::numeric_limits<int>::max)(),
|
||||
"custom_rtc_offset",
|
||||
Category::System,
|
||||
Specialization::Countable,
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ public:
|
|||
if constexpr (std::is_enum_v<Type>) {
|
||||
return EnumMetadata<Type>::Index();
|
||||
} else {
|
||||
return std::numeric_limits<u32>::max();
|
||||
return (std::numeric_limits<u32>::max)();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -237,14 +237,14 @@ public:
|
|||
|
||||
[[nodiscard]] std::string MinVal() const override final {
|
||||
if constexpr (std::is_arithmetic_v<Type> && !ranged) {
|
||||
return this->ToString(std::numeric_limits<Type>::min());
|
||||
return this->ToString((std::numeric_limits<Type>::min)());
|
||||
} else {
|
||||
return this->ToString(minimum);
|
||||
}
|
||||
}
|
||||
[[nodiscard]] std::string MaxVal() const override final {
|
||||
if constexpr (std::is_arithmetic_v<Type> && !ranged) {
|
||||
return this->ToString(std::numeric_limits<Type>::max());
|
||||
return this->ToString((std::numeric_limits<Type>::max)());
|
||||
} else {
|
||||
return this->ToString(maximum);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
namespace Common {
|
||||
|
||||
struct SlotId {
|
||||
static constexpr u32 INVALID_INDEX = std::numeric_limits<u32>::max();
|
||||
static constexpr u32 INVALID_INDEX = (std::numeric_limits<u32>::max)();
|
||||
|
||||
constexpr auto operator<=>(const SlotId&) const noexcept = default;
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
|
|||
const auto scheduling_type = SCHED_OTHER;
|
||||
s32 max_prio = sched_get_priority_max(scheduling_type);
|
||||
s32 min_prio = sched_get_priority_min(scheduling_type);
|
||||
u32 level = std::max(static_cast<u32>(new_priority) + 1, 4U);
|
||||
u32 level = (std::max)(static_cast<u32>(new_priority) + 1, 4U);
|
||||
|
||||
struct sched_param params;
|
||||
if (max_prio > min_prio) {
|
||||
|
|
@ -101,7 +101,7 @@ void SetCurrentThreadName(const char* name) {
|
|||
#elif defined(__linux__)
|
||||
// Linux limits thread names to 15 characters and will outright reject any
|
||||
// attempt to set a longer name with ERANGE.
|
||||
std::string truncated(name, std::min(strlen(name), static_cast<size_t>(15)));
|
||||
std::string truncated(name, (std::min)(strlen(name), static_cast<size_t>(15)));
|
||||
if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) {
|
||||
errno = e;
|
||||
LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg());
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ public:
|
|||
this->state.data[3] = ParamTmat;
|
||||
|
||||
{
|
||||
const int num_init_iterations = std::max(seed_count + 1, MinimumInitIterations) - 1;
|
||||
const int num_init_iterations = (std::max)(seed_count + 1, MinimumInitIterations) - 1;
|
||||
|
||||
GenerateInitialValuePlus(&this->state, 0, seed_count);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Common {
|
|||
|
||||
// This function multiplies 2 u64 values and divides it by a u64 value.
|
||||
[[nodiscard]] static inline u64 MultiplyAndDivide64(u64 a, u64 b, u64 d) {
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
u128 r{};
|
||||
r[0] = _umul128(a, b, &r[1]);
|
||||
u64 remainder;
|
||||
|
|
@ -41,7 +41,7 @@ namespace Common {
|
|||
// This function multiplies 2 u64 values and produces a u128 value;
|
||||
[[nodiscard]] static inline u128 Multiply64Into128(u64 a, u64 b) {
|
||||
u128 result;
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
result[0] = _umul128(a, b, &result[1]);
|
||||
#else
|
||||
unsigned __int128 tmp = a;
|
||||
|
|
@ -65,7 +65,7 @@ namespace Common {
|
|||
#endif
|
||||
#else
|
||||
// This one is bit more inaccurate.
|
||||
return MultiplyAndDivide64(std::numeric_limits<u64>::max(), numerator, divisor);
|
||||
return MultiplyAndDivide64((std::numeric_limits<u64>::max)(), numerator, divisor);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ constexpr auto PauseCycles = 100'000U;
|
|||
|
||||
} // Anonymous namespace
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
__forceinline static void TPAUSE() {
|
||||
static constexpr auto RequestC02State = 0U;
|
||||
_tpause(RequestC02State, FencedRDTSC() + PauseCycles);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue