yuzu/src/common/CMakeLists.txt
Morph 334567d33b common: Introduce macro-based BitField
The current BitField implementation requires the use of the union, which makes it both non-constexpr (due to accessing inactive union members), and prevents the usage of smaller types and enums, reducing its flexibility.

Furthermore, BitField is not trivially copyable (and by extension, not trivial).

Moreover, it is not well documented that BitField performs automatic sign extension on signed integers, as a recent PR made an assumption that these signed integers were zero extended.

These considerations resulted in this new BitField implementation, which uses macros to generate functions for accessing / setting bitfield values.

2 macros are provided:

`YUZU_RO_BITFIELD` for read-only BitFields, which generates a member function that directly returns the specified type.

`YUZU_BITFIELD`, which generates a member function that returns a `BitFieldHelper` class which allows setting the value using `operator=` or `Set()`, and performs implicit conversion to the specified type.

Types:

The following type tags are added:

Automatic type deduction:
AutoUInt, AutoSignExtSInt, AutoZeroExtSInt, AutoFloat

Automatic type deduction selects the smallest type that contains at least the specified NumBits bits.
However, in testing, MSVC is pretty bad at optimizing smaller-than-32-bit accesses, so it may be advisable to specify 32 bit types in performance sensitive code.

Signed Integers:
SignExtSInt<>, ZeroExtSInt<>

The new SignExtSInt and ZeroExtSInt are mandatory type tags for signed integers to explicitly specify whether to sign extend (preserving the sign and value) or zero extend the bitfield value.

These changes have sacrificed compatibility with `_be` types. This is a worthwhile sacrifice as we do not have usages of these types in BitField.

Example usage:

```cpp
struct MyTestStruct {
    u32 raw;

    YUZU_RO_BITFIELD(0, 3, AutoUInt, field0);
    YUZU_BITFIELD(3, 4, AutoSignExtSInt, field1);
    YUZU_BITFIELD(7, 5, ZeroExtSInt<s16>, field2);
    YUZU_RO_BITFIELD(12, 1, bool, flag0);
};

MyTestStruct s{0x1234567};
s.field1() = -1;
s.field2() = -2;
fmt::print("field0={}, field1={}, field2={}, flag0={}", s.field0(), s.field1(), s.field2(), s.flag0());
```
2023-07-24 17:37:07 -04:00

216 lines
4.7 KiB
CMake

# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
if (DEFINED ENV{AZURECIREPO})
set(BUILD_REPOSITORY $ENV{AZURECIREPO})
endif()
if (DEFINED ENV{TITLEBARFORMATIDLE})
set(TITLE_BAR_FORMAT_IDLE $ENV{TITLEBARFORMATIDLE})
endif ()
if (DEFINED ENV{TITLEBARFORMATRUNNING})
set(TITLE_BAR_FORMAT_RUNNING $ENV{TITLEBARFORMATRUNNING})
endif ()
if (DEFINED ENV{DISPLAYVERSION})
set(DISPLAY_VERSION $ENV{DISPLAYVERSION})
endif ()
include(GenerateSCMRev)
add_library(common STATIC
address_space.cpp
address_space.h
algorithm.h
alignment.h
announce_multiplayer_room.h
assert.cpp
assert.h
atomic_helpers.h
atomic_ops.h
detached_tasks.cpp
detached_tasks.h
bit_cast.h
bit_field.h
bit_set.h
bit_util.h
cityhash.cpp
cityhash.h
common_funcs.h
common_precompiled_headers.h
common_types.h
concepts.h
container_hash.h
demangle.cpp
demangle.h
div_ceil.h
dynamic_library.cpp
dynamic_library.h
elf.h
error.cpp
error.h
expected.h
fiber.cpp
fiber.h
fixed_point.h
fs/file.cpp
fs/file.h
fs/fs.cpp
fs/fs.h
fs/fs_paths.h
fs/fs_types.h
fs/fs_util.cpp
fs/fs_util.h
fs/path_util.cpp
fs/path_util.h
hash.h
hex_util.cpp
hex_util.h
host_memory.cpp
host_memory.h
input.h
intrusive_red_black_tree.h
literals.h
logging/backend.cpp
logging/backend.h
logging/filter.cpp
logging/filter.h
logging/formatter.h
logging/log.h
logging/log_entry.h
logging/text_formatter.cpp
logging/text_formatter.h
logging/types.h
lz4_compression.cpp
lz4_compression.h
make_unique_for_overwrite.h
math_util.h
memory_detect.cpp
memory_detect.h
microprofile.cpp
microprofile.h
microprofileui.h
multi_level_page_table.cpp
multi_level_page_table.h
new_bit_field.h
nvidia_flags.cpp
nvidia_flags.h
overflow.h
page_table.cpp
page_table.h
param_package.cpp
param_package.h
parent_of_member.h
point.h
precompiled_headers.h
quaternion.h
range_map.h
reader_writer_queue.h
ring_buffer.h
${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp
scm_rev.h
scope_exit.h
scratch_buffer.h
settings.cpp
settings.h
settings_input.cpp
settings_input.h
socket_types.h
spin_lock.cpp
spin_lock.h
steady_clock.cpp
steady_clock.h
stream.cpp
stream.h
string_util.cpp
string_util.h
swap.h
telemetry.cpp
telemetry.h
thread.cpp
thread.h
thread_queue_list.h
thread_worker.h
threadsafe_queue.h
time_zone.cpp
time_zone.h
tiny_mt.h
tree.h
typed_address.h
uint128.h
unique_function.h
uuid.cpp
uuid.h
vector_math.h
virtual_buffer.cpp
virtual_buffer.h
wall_clock.cpp
wall_clock.h
zstd_compression.cpp
zstd_compression.h
)
if (WIN32)
target_sources(common PRIVATE
windows/timer_resolution.cpp
windows/timer_resolution.h
)
target_link_libraries(common PRIVATE ntdll)
endif()
if(ANDROID)
target_sources(common
PRIVATE
fs/fs_android.cpp
fs/fs_android.h
)
endif()
if(ARCHITECTURE_x86_64)
target_sources(common
PRIVATE
x64/cpu_detect.cpp
x64/cpu_detect.h
x64/cpu_wait.cpp
x64/cpu_wait.h
x64/native_clock.cpp
x64/native_clock.h
x64/rdtsc.cpp
x64/rdtsc.h
x64/xbyak_abi.h
x64/xbyak_util.h
)
target_link_libraries(common PRIVATE xbyak::xbyak)
endif()
if (MSVC)
target_compile_definitions(common PRIVATE
# The standard library doesn't provide any replacement for codecvt yet
# so we can disable this deprecation warning for the time being.
_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
)
target_compile_options(common PRIVATE
/W4
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
)
else()
target_compile_options(common PRIVATE
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>
)
endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile Threads::Threads)
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
if (ANDROID)
# For ASharedMemory_create
target_link_libraries(common PRIVATE android)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(common PRIVATE precompiled_headers.h)
endif()