From 227931aa9f2c1b84de31946c32fc83a5f9e484d4 Mon Sep 17 00:00:00 2001 From: Spartan322 Date: Fri, 3 Nov 2023 18:39:26 -0400 Subject: [PATCH] Add GCC support Add MSVC support --- include/lauf/config.h | 57 +++++++++++++++++++++++----- include/lauf/runtime/builtin.h | 4 ++ src/lauf/asm/builder.cpp | 12 +++--- src/lauf/asm/builder.hpp | 5 +-- src/lauf/backend/qbe.hpp | 39 ++++++++++++------- src/lauf/frontend/text.cpp | 7 ++-- src/lauf/lib/bits.cpp | 7 ++-- src/lauf/lib/debug.cpp | 21 ++++++++++- src/lauf/lib/fiber.cpp | 9 ++--- src/lauf/lib/int.cpp | 3 +- src/lauf/lib/memory.cpp | 8 +++- src/lauf/runtime/memory.cpp | 4 +- src/lauf/runtime/memory.hpp | 7 ++-- src/lauf/runtime/process.cpp | 22 ++++++----- src/lauf/runtime/stack.hpp | 8 ++-- src/lauf/runtime/stacktrace.cpp | 4 +- src/lauf/support/arena.hpp | 7 ++-- src/lauf/support/array.hpp | 17 ++++----- src/lauf/vm_execute.cpp | 66 ++++++++++++++++++--------------- 19 files changed, 198 insertions(+), 109 deletions(-) diff --git a/include/lauf/config.h b/include/lauf/config.h index a978416..c1bc0e7 100644 --- a/include/lauf/config.h +++ b/include/lauf/config.h @@ -36,22 +36,61 @@ typedef uint64_t lauf_uint; # error "lauf assumes 8 bit bytes" #endif -#if !defined(__clang__) +/* #if !defined(__clang__) # error "lauf currently requires clang" -#endif +#endif */ //=== optimizations ===// -#define LAUF_LIKELY(Cond) __builtin_expect((Cond), 1) -#define LAUF_UNLIKELY(Cond) __builtin_expect((Cond), 0) -#define LAUF_TAIL_CALL [[clang::musttail]] -#define LAUF_NOINLINE [[gnu::noinline]] -#define LAUF_FORCE_INLINE [[gnu::always_inline]] -#define LAUF_UNREACHABLE __builtin_unreachable() +#define LAUF_LIKELY(Cond) Cond /*__builtin_expect((Cond), 1)*/ +#define LAUF_UNLIKELY(Cond) Cond /*__builtin_expect((Cond), 0)*/ +#if defined(__clang__) +# define LAUF_TAIL_CALL [[clang::musttail]] +#elif defined(__GNUC__) || defined(__GNUG__) +# define LAUF_TAIL_CALL +#endif +#if defined(_MSC_VER) +# define LAUF_NOINLINE __declspec(noinline) +# define LAUF_FORCE_INLINE __forceinline +# define LAUF_UNREACHABLE __assume(0) +#else +# define LAUF_NOINLINE [[gnu::noinline]] +# define LAUF_FORCE_INLINE [[gnu::always_inline]] inline +# define LAUF_UNREACHABLE __builtin_unreachable() +#endif //=== configurations ===// #ifndef LAUF_CONFIG_DISPATCH_JUMP_TABLE # define LAUF_CONFIG_DISPATCH_JUMP_TABLE 1 #endif -#endif // LAUF_CONFIG_H_INCLUDED +#if !defined(__clang__) && (defined(__GNUC__) || defined(__GNUG__)) +# define LAUF_IGNORE_BITFIELD_WARNING(...) \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wconversion\""); \ + __VA_ARGS__; \ + _Pragma("GCC diagnostic pop"); +#else +# define LAUF_IGNORE_BITFIELD_WARNING(...) __VA_ARGS__ +#endif +#if !defined(__clang__) && (defined(__GNUC__) || defined(__GNUG__)) +# define LAUF_IGNORE_CONV_WARNING(...) \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wconversion\""); \ + __VA_ARGS__; \ + _Pragma("GCC diagnostic pop"); +#else +# define LAUF_IGNORE_CONV_WARNING(...) __VA_ARGS__ +#endif + +#if !defined(__clang__) && (defined(__GNUC__) || defined(__GNUG__)) +# define LAUF_IGNORE_SIGN_WARNING(...) \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wsign-conversion\""); \ + __VA_ARGS__; \ + _Pragma("GCC diagnostic pop"); +#else +# define LAUF_IGNORE_SIGN_WARNING(...) __VA_ARGS__ +#endif + +#endif // LAUF_CONFIG_H_INCLUDED diff --git a/include/lauf/runtime/builtin.h b/include/lauf/runtime/builtin.h index 957c623..510a318 100644 --- a/include/lauf/runtime/builtin.h +++ b/include/lauf/runtime/builtin.h @@ -8,7 +8,11 @@ LAUF_HEADER_START +#if defined(__clang__) #define LAUF_RUNTIME_BUILTIN_IMPL __attribute__((section("text.lauf_builtin"), aligned(8))) +#else +#define LAUF_RUNTIME_BUILTIN_IMPL +#endif typedef union lauf_asm_inst lauf_asm_inst; typedef struct lauf_asm_type lauf_asm_type; diff --git a/src/lauf/asm/builder.cpp b/src/lauf/asm/builder.cpp index e244cdc..a403514 100644 --- a/src/lauf/asm/builder.cpp +++ b/src/lauf/asm/builder.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: BSL-1.0 #include +#include #include #include @@ -372,7 +373,7 @@ LAUF_NOINLINE lauf_asm_inst* emit_body(lauf_asm_inst* ip, lauf_asm_builder* b, assert(insts[dest->offset].op() == lauf::asm_op::block); auto dest_offset = dest->offset + 1; - jump->jump.offset = std::int32_t(dest_offset - cur_offset); + LAUF_IGNORE_BITFIELD_WARNING(jump->jump.offset = std::int32_t(dest_offset - cur_offset)); } return ip; @@ -437,7 +438,7 @@ void emit_debug_location(lauf_asm_builder* b) for (auto loc : block.debug_locations) { // We also have the initial block instruction that affects the inst_idx. - loc.inst_idx += block.offset + 1; + LAUF_IGNORE_CONV_WARNING(loc.inst_idx += block.offset + 1); cont.push_back(arena, loc); } } @@ -541,7 +542,7 @@ lauf_asm_local* lauf_asm_build_local(lauf_asm_builder* b, lauf_asm_layout layout // The offset is the current size, we don't need to worry about alignment. offset = std::uint16_t(b->local_allocation_size + sizeof(lauf_runtime_stack_frame)); - b->local_allocation_size += layout.size; + LAUF_IGNORE_CONV_WARNING(b->local_allocation_size += layout.size); } else { @@ -553,7 +554,7 @@ lauf_asm_local* lauf_asm_build_local(lauf_asm_builder* b, lauf_asm_layout layout // for a pointer. // Since `layout.alignment` is a multiple of it (as a power of two bigger than it), and // size a multiple of alignment, `layout.alignment + layout.size` is as well. - b->local_allocation_size += layout.alignment + layout.size; + LAUF_IGNORE_CONV_WARNING(b->local_allocation_size += layout.alignment + layout.size); // Since we don't know the exact alignment offset, we can't compute it statically. offset = UINT16_MAX; } @@ -1006,7 +1007,7 @@ void lauf_asm_inst_global_addr(lauf_asm_builder* b, const lauf_asm_global* globa b->cur->insts.push_back(*b, LAUF_BUILD_INST_VALUE(global_addr, global->allocation_idx)); b->cur->vstack.push_constant(*b, [&] { lauf_runtime_value result; - result.as_address.allocation = global->allocation_idx; + LAUF_IGNORE_BITFIELD_WARNING(result.as_address.allocation = global->allocation_idx); result.as_address.offset = 0; result.as_address.generation = 0; // Always true for globals. return result; @@ -1381,4 +1382,3 @@ void lauf_asm_inst_store_field(lauf_asm_builder* b, lauf_asm_type type, size_t f lauf_asm_inst_call_builtin(b, builtin); } } - diff --git a/src/lauf/asm/builder.hpp b/src/lauf/asm/builder.hpp index 946e739..46f547e 100644 --- a/src/lauf/asm/builder.hpp +++ b/src/lauf/asm/builder.hpp @@ -282,7 +282,7 @@ struct lauf_asm_builder : lauf::intrinsic_arena #define LAUF_BUILD_INST_OFFSET(Name, Offset) \ [&](const char* context, std::ptrdiff_t offset) { \ lauf_asm_inst result; \ - result.Name = {lauf::asm_op::Name, std::int32_t(offset)}; \ + LAUF_IGNORE_BITFIELD_WARNING(result.Name = {lauf::asm_op::Name, std::int32_t(offset)}); \ if (result.Name.offset != offset) \ b->error(context, "offset too big"); \ return result; \ @@ -315,7 +315,7 @@ struct lauf_asm_builder : lauf::intrinsic_arena #define LAUF_BUILD_INST_VALUE(Name, Value) \ [&](const char* context, std::size_t value) { \ lauf_asm_inst result; \ - result.Name = {lauf::asm_op::Name, std::uint32_t(value)}; \ + LAUF_IGNORE_BITFIELD_WARNING(result.Name = {lauf::asm_op::Name, std::uint32_t(value)}); \ if (value != result.Name.value) \ b->error(context, "invalid value"); \ return result; \ @@ -331,4 +331,3 @@ struct lauf_asm_builder : lauf::intrinsic_arena }(LAUF_BUILD_ASSERT_CONTEXT, Index) #endif // SRC_LAUF_ASM_BUILDER_HPP_INCLUDED - diff --git a/src/lauf/backend/qbe.hpp b/src/lauf/backend/qbe.hpp index 0ea3f8b..31a06b4 100644 --- a/src/lauf/backend/qbe.hpp +++ b/src/lauf/backend/qbe.hpp @@ -5,12 +5,15 @@ #define SRC_LAUF_BACKEND_QBE_HPP_INCLUDED #include +#include #include #include #include +#include #include #include +#include #include namespace lauf @@ -80,6 +83,12 @@ enum class qbe_cc class qbe_writer { + template + constexpr std::underlying_type_t to_underlying(Enum e) noexcept + { + return static_cast>(e); + } + public: qbe_writer() : _writer(lauf_create_string_writer()) {} @@ -90,7 +99,7 @@ class qbe_writer { for (auto& [str, id] : _literals) { - out->format("data $lit_%u = {", static_cast(id)); + out->format("data $lit_%u = {", to_underlying(id)); for (auto c : str) out->format("b %d, ", c); out->write("}\n"); @@ -123,7 +132,7 @@ class qbe_writer //=== data ===// void begin_data(qbe_data id, std::size_t alignment) { - _writer->format("data $data_%u = align %zu\n", static_cast(id), alignment); + _writer->format("data $data_%u = align %zu\n", to_underlying(id), alignment); _writer->write("{\n"); } @@ -157,8 +166,8 @@ class qbe_writer else if (std::holds_alternative(ty)) _writer->format("function %s $%s(", type_name(std::get(ty)), name); else - _writer->format("function :tuple_%u $%s(", - static_cast(std::get(ty)), name); + _writer->format("function :tuple_%u $%s(", to_underlying(std::get(ty)), + name); } void param(qbe_type ty, std::size_t idx) @@ -175,7 +184,7 @@ class qbe_writer void block(qbe_block id) { - _writer->format("@block_%zu\n", static_cast(id)); + _writer->format("@block_%zu\n", to_underlying(id)); } void end_function() @@ -188,15 +197,14 @@ class qbe_writer //=== instructions ===// void jmp(qbe_block block) { - _writer->format(" jmp @block_%zu\n", static_cast(block)); + _writer->format(" jmp @block_%zu\n", to_underlying(block)); } void jnz(qbe_reg reg, qbe_block block1, qbe_block block2) { _writer->write(" jnz "); write_reg(reg); - _writer->format(", @block_%zu, @block_%zu\n", static_cast(block1), - static_cast(block2)); + _writer->format(", @block_%zu, @block_%zu\n", to_underlying(block1), to_underlying(block2)); } void ret() @@ -348,7 +356,7 @@ class qbe_writer else { write_reg(dest); - _writer->format(" =:tuple_%u call ", static_cast(std::get(ty))); + _writer->format(" =:tuple_%u call ", to_underlying(std::get(ty))); } write_value(fn); @@ -380,7 +388,7 @@ class qbe_writer if (a == qbe_alloc::return_) _writer->write("%return"); else - _writer->format("%%a%u", static_cast(a)); + _writer->format("%%a%u", to_underlying(a)); } void write_reg(qbe_reg reg) @@ -390,7 +398,7 @@ class qbe_writer else if (reg == qbe_reg::tmp2) _writer->write("%tmp2"); else - _writer->format("%%r%u", static_cast(reg)); + _writer->format("%%r%u", to_underlying(reg)); } void write_value(const qbe_value& value) @@ -402,9 +410,9 @@ class qbe_writer else if (std::holds_alternative(value)) _writer->format("%" PRIuMAX, std::get(value)); else if (std::holds_alternative(value)) - _writer->format("$data_%u", static_cast(std::get(value))); + _writer->format("$data_%u", to_underlying(std::get(value))); else if (std::holds_alternative(value)) - _writer->format("$lit_%u", static_cast(std::get(value))); + _writer->format("$lit_%u", to_underlying(std::get(value))); else _writer->format("$%s", std::get(value)); } @@ -425,6 +433,8 @@ class qbe_writer return "b"; case qbe_type::halfword: return "h"; + default: + LAUF_UNREACHABLE; } } @@ -452,6 +462,8 @@ class qbe_writer return "uge"; case qbe_cc::ugt: return "ugt"; + default: + LAUF_UNREACHABLE; } } @@ -462,4 +474,3 @@ class qbe_writer } // namespace lauf #endif // SRC_LAUF_BACKEND_QBE_HPP_INCLUDED - diff --git a/src/lauf/frontend/text.cpp b/src/lauf/frontend/text.cpp index c8c1f3c..36b2560 100644 --- a/src/lauf/frontend/text.cpp +++ b/src/lauf/frontend/text.cpp @@ -670,8 +670,10 @@ struct location static constexpr auto rule = dsl::position; static constexpr auto value = callback([](parse_state& state, auto pos) { auto loc = lexy::get_input_location(state.input->buffer, pos, state.anchor); - lauf_asm_build_debug_location(state.builder, {0, std::uint16_t(loc.line_nr()), - std::uint16_t(loc.column_nr()), false, 0}); + LAUF_IGNORE_BITFIELD_WARNING( + lauf_asm_build_debug_location(state.builder, + {0, std::uint16_t(loc.line_nr()), + std::uint16_t(loc.column_nr()), false, 0})); state.anchor = loc.anchor(); }); }; @@ -846,4 +848,3 @@ lauf_asm_module* lauf_frontend_text(lauf_reader* reader, lauf_frontend_text_opti return state.mod; } - diff --git a/src/lauf/lib/bits.cpp b/src/lauf/lib/bits.cpp index 08e7f11..5198fd3 100644 --- a/src/lauf/lib/bits.cpp +++ b/src/lauf/lib/bits.cpp @@ -51,7 +51,7 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_bits_shl, 2, 1, panic_flags, "shl", &lauf_lib_bits auto n = vstack_ptr[0].as_uint; ++vstack_ptr; - if (LAUF_UNLIKELY(n >= sizeof(lauf_uint) * CHAR_BIT)) + if (LAUF_UNLIKELY(n >= sizeof(lauf_uint) * CHAR_BIT)) [[unlikely]] return lauf_runtime_panic(process, "shift amount too big"); vstack_ptr[0].as_uint = x << n; @@ -64,7 +64,7 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_bits_ushr, 2, 1, panic_flags, "ushr", &lauf_lib_bi auto n = vstack_ptr[0].as_uint; ++vstack_ptr; - if (LAUF_UNLIKELY(n >= sizeof(lauf_uint) * CHAR_BIT)) + if (LAUF_UNLIKELY(n >= sizeof(lauf_uint) * CHAR_BIT)) [[unlikely]] return lauf_runtime_panic(process, "shift amount too big"); vstack_ptr[0].as_uint = x >> n; @@ -77,7 +77,7 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_bits_sshr, 2, 1, panic_flags, "sshr", &lauf_lib_bi auto n = vstack_ptr[0].as_uint; ++vstack_ptr; - if (LAUF_UNLIKELY(n >= sizeof(lauf_sint) * CHAR_BIT)) + if (LAUF_UNLIKELY(n >= sizeof(lauf_sint) * CHAR_BIT)) [[unlikely]] return lauf_runtime_panic(process, "shift amount too big"); static_assert(-1 >> 1 == -1, "compiler does not implement arithmetic right shift"); @@ -86,4 +86,3 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_bits_sshr, 2, 1, panic_flags, "sshr", &lauf_lib_bi } const lauf_runtime_builtin_library lauf_lib_bits = {"lauf.bits", &lauf_lib_bits_sshr, nullptr}; - diff --git a/src/lauf/lib/debug.cpp b/src/lauf/lib/debug.cpp index 84148fa..6b9bb8e 100644 --- a/src/lauf/lib/debug.cpp +++ b/src/lauf/lib/debug.cpp @@ -140,7 +140,27 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_debug_break, 0, 0, LAUF_RUNTIME_BUILTIN_NO_PROCESS | LAUF_RUNTIME_BUILTIN_NO_PANIC, "break", &lauf_lib_debug_print_all_cstacks) { +#if __has_builtin(__builtin_debugtrap) __builtin_debugtrap(); +#elif __has_builtin(__debugbreak) + __debugbreak(); +#elif defined(_MSC_VER) + __debugbreak(); +#elif defined(__ARMCC_VERSION) + __breakpoint(42) +#elif defined(__i386__) || defined(__x86_64__) + __asm__ __volatile__("int3"); +#elif defined(__thumb__) + __asm__ __volatile__(".inst 0xde01"); +#elif defined(__aarch64__) + __asm__ __volatile__(".inst 0xd4200000"); +#elif defined(__arm__) + __asm__ __volatile__(".inst 0xe7f001f0"); +#elif defined(__clang__) + __builtin_debugtrap(); +#elif defined(__STDC_HOSTED__) && (__STDC_HOSTED__ == 0) && defined(__GNUC__) + __builtin_trap(); +#endif LAUF_RUNTIME_BUILTIN_DISPATCH; } @@ -157,4 +177,3 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_debug_read, 0, 1, } const lauf_runtime_builtin_library lauf_lib_debug = {"lauf.debug", &lauf_lib_debug_read, nullptr}; - diff --git a/src/lauf/lib/fiber.cpp b/src/lauf/lib/fiber.cpp index 5fed8bc..a87df06 100644 --- a/src/lauf/lib/fiber.cpp +++ b/src/lauf/lib/fiber.cpp @@ -13,7 +13,7 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_fiber_create, 1, 1, LAUF_RUNTIME_BUILTIN_DEFAULT, auto address = vstack_ptr[0].as_function_address; auto fn = lauf_runtime_get_function_ptr_any(process, address); - if (LAUF_UNLIKELY(fn == nullptr)) + if (LAUF_UNLIKELY(fn == nullptr)) [[unlikely]] return lauf_runtime_panic(process, "invalid function address"); auto fiber = lauf_runtime_create_fiber(process, fn); @@ -29,10 +29,10 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_fiber_destroy, 1, 0, LAUF_RUNTIME_BUILTIN_DEFAULT, ++vstack_ptr; auto fiber = lauf_runtime_get_fiber_ptr(process, handle); - if (LAUF_UNLIKELY(fiber == nullptr)) + if (LAUF_UNLIKELY(fiber == nullptr)) [[unlikely]] return lauf_runtime_panic(process, "invalid fiber handle"); - if (LAUF_UNLIKELY(!lauf_runtime_destroy_fiber(process, fiber))) + if (LAUF_UNLIKELY(!lauf_runtime_destroy_fiber(process, fiber))) [[unlikely]] return false; LAUF_RUNTIME_BUILTIN_DISPATCH; @@ -69,7 +69,7 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_fiber_done, 1, 1, LAUF_RUNTIME_BUILTIN_DEFAULT, "d { auto handle = vstack_ptr[0].as_address; auto fiber = lauf_runtime_get_fiber_ptr(process, handle); - if (LAUF_UNLIKELY(fiber == nullptr)) + if (LAUF_UNLIKELY(fiber == nullptr)) [[unlikely]] return lauf_runtime_panic(process, "invalid fiber handle"); auto status = lauf_runtime_get_fiber_status(fiber); @@ -79,4 +79,3 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_fiber_done, 1, 1, LAUF_RUNTIME_BUILTIN_DEFAULT, "d } const lauf_runtime_builtin_library lauf_lib_fiber = {"lauf.fiber", &lauf_lib_fiber_done, nullptr}; - diff --git a/src/lauf/lib/int.cpp b/src/lauf/lib/int.cpp index b3a18e0..5854963 100644 --- a/src/lauf/lib/int.cpp +++ b/src/lauf/lib/int.cpp @@ -22,6 +22,8 @@ return Name##_sat; \ case LAUF_LIB_INT_OVERFLOW_PANIC: \ return Name##_panic; \ + default: \ + LAUF_UNREACHABLE; \ } \ } @@ -670,4 +672,3 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_int_u64_overflow, 1, 2, no_panic_flags, "u64_overf const lauf_runtime_builtin_library lauf_lib_int = {"lauf.int", &lauf_lib_int_u64_overflow, &lauf_lib_int_u64}; - diff --git a/src/lauf/lib/memory.cpp b/src/lauf/lib/memory.cpp index 0be9942..4ced865 100644 --- a/src/lauf/lib/memory.cpp +++ b/src/lauf/lib/memory.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2022-2023 Jonathan Müller and lauf contributors // SPDX-License-Identifier: BSL-1.0 +#include #include #include @@ -96,7 +97,7 @@ std::uint32_t addr_offset(lauf_runtime_address addr, lauf_sint offset) { lauf_sint result; auto overflow = __builtin_add_overflow(lauf_sint(addr.offset), offset, &result); - if (LAUF_UNLIKELY(overflow || result < 0 || result > UINT32_MAX)) + if (LAUF_UNLIKELY(overflow || result < 0 || result > UINT32_MAX)) [[unlikely]] result = UINT32_MAX; return std::uint32_t(result); @@ -209,6 +210,8 @@ lauf_runtime_builtin lauf_lib_memory_addr_add(lauf_lib_memory_addr_overflow over return addr_add_panic; case LAUF_LIB_MEMORY_ADDR_OVERFLOW_PANIC_STRICT: return addr_add_panic_strict; + default: + LAUF_UNREACHABLE; } } @@ -222,6 +225,8 @@ lauf_runtime_builtin lauf_lib_memory_addr_sub(lauf_lib_memory_addr_overflow over return addr_sub_panic; case LAUF_LIB_MEMORY_ADDR_OVERFLOW_PANIC_STRICT: return addr_sub_panic_strict; + default: + LAUF_UNREACHABLE; } } @@ -296,4 +301,3 @@ LAUF_RUNTIME_BUILTIN(lauf_lib_memory_cmp, 3, 1, LAUF_RUNTIME_BUILTIN_DEFAULT, "c } const lauf_runtime_builtin_library lauf_lib_memory = {"lauf.memory", &lauf_lib_memory_cmp, nullptr}; - diff --git a/src/lauf/runtime/memory.cpp b/src/lauf/runtime/memory.cpp index 25ff719..279cb24 100644 --- a/src/lauf/runtime/memory.cpp +++ b/src/lauf/runtime/memory.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2022-2023 Jonathan Müller and lauf contributors // SPDX-License-Identifier: BSL-1.0 +#include #include #include @@ -126,7 +127,7 @@ bool lauf_runtime_get_address(lauf_runtime_process* p, lauf_runtime_address* all lauf_runtime_address lauf_runtime_get_global_address(lauf_runtime_process*, const lauf_asm_global* global) { - return {global->allocation_idx, 0, 0}; + LAUF_IGNORE_BITFIELD_WARNING(return {global->allocation_idx, 0, 0}); } const char* lauf_runtime_get_cstr(lauf_runtime_process* p, lauf_runtime_address addr) @@ -527,4 +528,3 @@ bool lauf_runtime_undeclare_weak(lauf_runtime_process* p, lauf_runtime_address a alloc->is_gc_weak = false; return true; } - diff --git a/src/lauf/runtime/memory.hpp b/src/lauf/runtime/memory.hpp index 9412d8c..e646917 100644 --- a/src/lauf/runtime/memory.hpp +++ b/src/lauf/runtime/memory.hpp @@ -40,6 +40,8 @@ constexpr bool is_const(allocation_source source) case allocation_source::local_memory: case allocation_source::heap_memory: return false; + default: + LAUF_UNREACHABLE; } } @@ -203,13 +205,13 @@ class memory { auto index = _allocations.size(); _allocations.push_back(allocator, alloc); - return {std::uint32_t(index), alloc.generation, 0}; + LAUF_IGNORE_BITFIELD_WARNING(return {std::uint32_t(index), alloc.generation, 0}); } lauf_runtime_address new_allocation_unchecked(allocation alloc) { auto index = _allocations.size(); _allocations.push_back_unchecked(alloc); - return {std::uint32_t(index), alloc.generation, 0}; + LAUF_IGNORE_BITFIELD_WARNING(return {std::uint32_t(index), alloc.generation, 0}); } allocation& operator[](std::size_t index) @@ -277,4 +279,3 @@ class memory } // namespace lauf #endif // LAUF_RUNTIME_MEMORY_HPP_INCLUDED - diff --git a/src/lauf/runtime/process.cpp b/src/lauf/runtime/process.cpp index 7002e43..7e0a3d3 100644 --- a/src/lauf/runtime/process.cpp +++ b/src/lauf/runtime/process.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2022-2023 Jonathan Müller and lauf contributors // SPDX-License-Identifier: BSL-1.0 +#include #include #include @@ -90,7 +91,8 @@ LAUF_NOINLINE void lauf_runtime_process::do_cleanup(lauf_runtime_process* proces // We don't know the full size. vm->heap_allocator.free_alloc(vm->heap_allocator.user_data, alloc.ptr, 0); else - ; // We don't know the starting address of the allocation. + { // We don't know the starting address of the allocation. + } } else if (alloc.source == lauf::allocation_source::fiber_memory) { @@ -155,6 +157,8 @@ lauf_runtime_fiber_status lauf_runtime_get_fiber_status(const lauf_runtime_fiber return LAUF_RUNTIME_FIBER_SUSPENDED; case lauf_runtime_fiber::running: return LAUF_RUNTIME_FIBER_RUNNING; + default: + LAUF_UNREACHABLE; } } @@ -212,7 +216,7 @@ bool lauf_runtime_resume(lauf_runtime_process* process, lauf_runtime_fiber* fibe fiber->resume_by(nullptr); process->cur_fiber = fiber; - if (LAUF_UNLIKELY(fiber->expected_argument_count != input_count)) + if (LAUF_UNLIKELY(fiber->expected_argument_count != input_count)) [[unlikely]] return lauf_runtime_panic(process, "mismatched signature for fiber resume"); // We can't call fiber->transfer_arguments() as the order is different. @@ -225,7 +229,7 @@ bool lauf_runtime_resume(lauf_runtime_process* process, lauf_runtime_fiber* fibe auto success = lauf::execute(fiber->suspension_point.ip + 1, fiber->suspension_point.vstack_ptr, fiber->suspension_point.frame_ptr, process); - if (LAUF_LIKELY(success)) + if (LAUF_LIKELY(success)) [[likely]] { // fiber could have changed, so reset back to the current fiber. fiber = process->cur_fiber; @@ -234,7 +238,7 @@ bool lauf_runtime_resume(lauf_runtime_process* process, lauf_runtime_fiber* fibe { // Copy the final arguments. auto actual_output_count = fiber->root_function()->sig.output_count; - if (LAUF_UNLIKELY(actual_output_count != output_count)) + if (LAUF_UNLIKELY(actual_output_count != output_count)) [[unlikely]] return lauf_runtime_panic(process, "mismatched signature for fiber resume"); auto vstack_ptr = fiber->vstack.base() - actual_output_count; @@ -254,7 +258,7 @@ bool lauf_runtime_resume(lauf_runtime_process* process, lauf_runtime_fiber* fibe auto actual_output_count = fiber->suspension_point.ip->fiber_suspend.input_count; if (actual_output_count > 0) { - if (LAUF_UNLIKELY(actual_output_count != output_count)) + if (LAUF_UNLIKELY(actual_output_count != output_count)) [[unlikely]] return lauf_runtime_panic(process, "mismatched signature for fiber resume"); auto& vstack_ptr = fiber->suspension_point.vstack_ptr; @@ -277,6 +281,7 @@ bool lauf_runtime_resume_until_completion(lauf_runtime_process* process, lauf_ru // Resume the fiber at least once. if (LAUF_LIKELY(lauf_runtime_resume(process, fiber, input, input_count, output, output_count))) + [[likely]] { success = true; @@ -284,7 +289,7 @@ bool lauf_runtime_resume_until_completion(lauf_runtime_process* process, lauf_ru while (process->cur_fiber->status != lauf_runtime_fiber::done) { if (LAUF_UNLIKELY(!lauf_runtime_resume(process, process->cur_fiber, nullptr, 0, output, - output_count))) + output_count))) [[unlikely]] { success = false; break; @@ -302,7 +307,7 @@ bool lauf_runtime_resume_until_completion(lauf_runtime_process* process, lauf_ru bool lauf_runtime_destroy_fiber(lauf_runtime_process* process, lauf_runtime_fiber* fiber) { if (LAUF_UNLIKELY(fiber->status != lauf_runtime_fiber::done - && fiber->status != lauf_runtime_fiber::ready)) + && fiber->status != lauf_runtime_fiber::ready)) [[unlikely]] { assert(fiber->status == lauf_runtime_fiber::suspended); // The fiber is being canceled, which means we need to manually mark its local memory as @@ -323,7 +328,7 @@ bool lauf_runtime_destroy_fiber(lauf_runtime_process* process, lauf_runtime_fibe auto& alloc = process->memory[index]; assert(alloc.source == lauf::allocation_source::local_memory); assert(alloc.status != lauf::allocation_status::freed); - if (LAUF_UNLIKELY(alloc.split != lauf::allocation_split::unsplit)) + if (LAUF_UNLIKELY(alloc.split != lauf::allocation_split::unsplit)) [[unlikely]] return lauf_runtime_panic(process, "cannot free split allocation"); alloc.status = lauf::allocation_status::freed; @@ -386,4 +391,3 @@ bool lauf_runtime_increment_step(lauf_runtime_process* process) return true; } - diff --git a/src/lauf/runtime/stack.hpp b/src/lauf/runtime/stack.hpp index 93e165f..e808ae9 100644 --- a/src/lauf/runtime/stack.hpp +++ b/src/lauf/runtime/stack.hpp @@ -117,7 +117,8 @@ class cstack { auto cur = _first; for (_first = nullptr; cur != nullptr; cur = chunk::deallocate(alloc, cur)) - {} + { + } } void* base() @@ -133,9 +134,9 @@ class cstack if (auto cur_chunk = chunk::chunk_of(frame_ptr); LAUF_UNLIKELY(frame_ptr->next_offset + callee->max_cstack_size - > cur_chunk->remaining_space(next_frame))) + > cur_chunk->remaining_space(next_frame))) [[unlikely]] { - if (LAUF_UNLIKELY(cur_chunk->next == nullptr)) + if (LAUF_UNLIKELY(cur_chunk->next == nullptr)) [[unlikely]] return nullptr; cur_chunk = cur_chunk->next; @@ -222,4 +223,3 @@ class vstack } // namespace lauf #endif // SRC_LAUF_RUNTIME_STACK_HPP_INCLUDED - diff --git a/src/lauf/runtime/stacktrace.cpp b/src/lauf/runtime/stacktrace.cpp index e15ca9f..4143b90 100644 --- a/src/lauf/runtime/stacktrace.cpp +++ b/src/lauf/runtime/stacktrace.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2022-2023 Jonathan Müller and lauf contributors // SPDX-License-Identifier: BSL-1.0 +#include #include #include @@ -28,6 +29,8 @@ lauf_runtime_stacktrace* lauf_runtime_get_stacktrace(lauf_runtime_process* p return new lauf_runtime_stacktrace{p->regs.frame_ptr, p->regs.ip}; case lauf_runtime_fiber::done: return nullptr; + default: + LAUF_UNREACHABLE; } } @@ -60,4 +63,3 @@ void lauf_runtime_destroy_stacktrace(lauf_runtime_stacktrace* st) { delete st; } - diff --git a/src/lauf/support/arena.hpp b/src/lauf/support/arena.hpp index c1151fa..9a56ea9 100644 --- a/src/lauf/support/arena.hpp +++ b/src/lauf/support/arena.hpp @@ -67,7 +67,7 @@ class arena_base void* allocate(std::size_t size, std::size_t alignment) { - if (LAUF_UNLIKELY(size > block_size)) + if (LAUF_UNLIKELY(size > block_size)) [[unlikely]] { auto memory = ::operator new(size, std::align_val_t(alignment)); _extern_allocs @@ -77,9 +77,9 @@ class arena_base auto offset = align_offset(_cur_pos, alignment); auto remaining = std::size_t(_cur_block->end() - _cur_pos); - if (LAUF_UNLIKELY(offset + size > remaining)) + if (LAUF_UNLIKELY(offset + size > remaining)) [[unlikely]] { - if (LAUF_UNLIKELY(_cur_block->next == nullptr)) + if (LAUF_UNLIKELY(_cur_block->next == nullptr)) [[unlikely]] _cur_block->next = block::allocate(); _cur_block = _cur_block->next; @@ -241,4 +241,3 @@ struct arena : intrinsic_arena } // namespace lauf #endif // SRC_LAUF_SUPPORT_ARENA_HPP_INCLUDED - diff --git a/src/lauf/support/array.hpp b/src/lauf/support/array.hpp index 22db323..d9e9dc9 100644 --- a/src/lauf/support/array.hpp +++ b/src/lauf/support/array.hpp @@ -186,7 +186,7 @@ class array if (!_is_heap && arena.try_expand(_ptr, _capacity, new_capacity)) { - _capacity = new_capacity; + LAUF_IGNORE_BITFIELD_WARNING(_capacity = new_capacity); } else { @@ -195,9 +195,9 @@ class array if (_is_heap) ::operator delete(_ptr); - _ptr = static_cast(new_memory); - _capacity = new_capacity; - _is_heap = true; + _ptr = static_cast(new_memory); + LAUF_IGNORE_BITFIELD_WARNING(_capacity = new_capacity); + _is_heap = true; } } @@ -228,7 +228,7 @@ class array } else { - _capacity = extended_page_size / sizeof(T); + LAUF_IGNORE_BITFIELD_WARNING(_capacity = extended_page_size / sizeof(T)); } } } @@ -241,7 +241,7 @@ class array template void push_back(Allocator& alloc, const T& obj) { - if (LAUF_UNLIKELY(_size + 1 > _capacity)) + if (LAUF_UNLIKELY(_size + 1 > _capacity)) [[unlikely]] reserve(alloc, _size + 1); push_back_unchecked(obj); @@ -293,8 +293,8 @@ class array } void set_pages(page_block block) { - _ptr = static_cast(block.ptr); - _capacity = block.size / sizeof(T); + _ptr = static_cast(block.ptr); + LAUF_IGNORE_BITFIELD_WARNING(_capacity = block.size / sizeof(T)); } T* _ptr; @@ -305,4 +305,3 @@ class array } // namespace lauf #endif // SRC_LAUF_SUPPORT_ARRAY_HPP_INCLUDED - diff --git a/src/lauf/vm_execute.cpp b/src/lauf/vm_execute.cpp index 92b7e34..3741b96 100644 --- a/src/lauf/vm_execute.cpp +++ b/src/lauf/vm_execute.cpp @@ -1,6 +1,7 @@ // Copyright(C) 2022-2023 Jonathan Müller and lauf contributors // SPDX-License-Identifier: BSL-1.0 +#include #include #include @@ -73,6 +74,7 @@ LAUF_NOINLINE bool allocate_more_vstack_space(const lauf_asm_inst* ip, { process->cur_fiber->vstack.grow(process->vm->page_allocator, vstack_ptr); if (LAUF_UNLIKELY(process->cur_fiber->vstack.capacity() > process->vm->max_vstack_size)) + [[unlikely]] LAUF_DO_PANIC("vstack overflow"); LAUF_VM_DISPATCH; @@ -85,6 +87,7 @@ LAUF_NOINLINE bool allocate_more_cstack_space(const lauf_asm_inst* ip, { process->cur_fiber->cstack.grow(process->vm->page_allocator, frame_ptr); if (LAUF_UNLIKELY(process->cur_fiber->cstack.capacity() > process->vm->max_cstack_size)) + [[unlikely]] LAUF_DO_PANIC("cstack overflow"); LAUF_VM_DISPATCH; @@ -94,12 +97,12 @@ LAUF_NOINLINE bool allocate_more_cstack_space(const lauf_asm_inst* ip, { \ /* Check that we have enough space left on the vstack. */ \ if (auto remaining = vstack_ptr - process->cur_fiber->vstack.limit(); \ - LAUF_UNLIKELY(remaining < (Callee)->max_vstack_size)) \ + LAUF_UNLIKELY(remaining < (Callee)->max_vstack_size)) [[unlikely]] \ LAUF_TAIL_CALL return allocate_more_vstack_space(ip, vstack_ptr, frame_ptr, process); \ \ /* Create a new stack frame. */ \ auto new_frame = process->cur_fiber->cstack.new_call_frame(frame_ptr, (Callee), ip); \ - if (LAUF_UNLIKELY(new_frame == nullptr)) \ + if (LAUF_UNLIKELY(new_frame == nullptr)) [[unlikely]] \ LAUF_TAIL_CALL return allocate_more_cstack_space(ip, vstack_ptr, frame_ptr, process); \ \ /* And start executing the function. */ \ @@ -120,7 +123,7 @@ LAUF_NOINLINE bool call_undefined_function(const lauf_asm_inst* ip, lauf_runtime return extra == nullptr ? nullptr : extra->find_definition(callee); }(); - if (LAUF_UNLIKELY(definition == nullptr)) + if (LAUF_UNLIKELY(definition == nullptr)) [[unlikely]] { LAUF_DO_PANIC("calling undefined function"); } @@ -174,6 +177,7 @@ LAUF_FORCE_INLINE std::size_t get_global_allocation_idx(lauf_runtime_stack_frame std::size_t base_idx) { if (auto cur_mod = frame_ptr->function->module; LAUF_LIKELY(cur_mod == process->program._mod)) + [[likely]] { return base_idx; } @@ -215,7 +219,7 @@ LAUF_VM_EXECUTE(return_free) auto index = frame_ptr->first_local_alloc + i; auto& alloc = process->memory[index]; - if (LAUF_UNLIKELY(alloc.split != lauf::allocation_split::unsplit)) + if (LAUF_UNLIKELY(alloc.split != lauf::allocation_split::unsplit)) [[unlikely]] LAUF_DO_PANIC("cannot free split allocation"); alloc.status = lauf::allocation_status::freed; @@ -263,7 +267,7 @@ LAUF_VM_EXECUTE(panic) LAUF_VM_EXECUTE(panic_if) { auto condition = vstack_ptr[1].as_uint; - if (LAUF_UNLIKELY(condition != 0)) + if (LAUF_UNLIKELY(condition != 0)) [[unlikely]] LAUF_TAIL_CALL return execute_panic(ip, vstack_ptr, frame_ptr, process); vstack_ptr += 2; @@ -273,7 +277,7 @@ LAUF_VM_EXECUTE(panic_if) LAUF_VM_EXECUTE(exit) { - if (LAUF_UNLIKELY(process == nullptr)) + if (LAUF_UNLIKELY(process == nullptr)) [[unlikely]] // During constant folding, we don't have a process, so check first. // We also don't have fibers, so just return. return true; @@ -294,7 +298,7 @@ LAUF_VM_EXECUTE(exit) { // Transfer values from our vstack. if (auto argument_count = std::uint8_t(cur_fiber->vstack.base() - vstack_ptr); - LAUF_UNLIKELY(!new_fiber->transfer_arguments(argument_count, vstack_ptr))) + LAUF_UNLIKELY(!new_fiber->transfer_arguments(argument_count, vstack_ptr))) [[unlikely]] LAUF_DO_PANIC("mismatched signature for fiber resume"); // Switch to parent fiber. @@ -340,7 +344,7 @@ LAUF_VM_EXECUTE(call) = lauf::uncompress_pointer_offset(frame_ptr->function, ip->call.offset); // Call an extern implementation if necessary. - if (LAUF_UNLIKELY(callee->insts == nullptr)) + if (LAUF_UNLIKELY(callee->insts == nullptr)) [[unlikely]] LAUF_TAIL_CALL return call_undefined_function(ip, vstack_ptr, frame_ptr, process); LAUF_DO_CALL(callee); @@ -353,7 +357,7 @@ LAUF_VM_EXECUTE(call_indirect) auto callee = lauf_runtime_get_function_ptr(process, ptr, {ip->call_indirect.input_count, ip->call_indirect.output_count}); - if (LAUF_UNLIKELY(callee == nullptr)) + if (LAUF_UNLIKELY(callee == nullptr)) [[unlikely]] LAUF_DO_PANIC("invalid function address"); LAUF_DO_CALL(callee); @@ -370,12 +374,12 @@ LAUF_VM_EXECUTE(fiber_resume) auto fiber = lauf::get_fiber(process, handle); if (LAUF_UNLIKELY(fiber == nullptr || (fiber->status != lauf_runtime_fiber::suspended - && fiber->status != lauf_runtime_fiber::ready))) + && fiber->status != lauf_runtime_fiber::ready))) [[unlikely]] LAUF_DO_PANIC("invalid fiber handle"); // Transfer values from our vstack. if (auto argument_count = ip->fiber_resume.input_count; - LAUF_UNLIKELY(!fiber->transfer_arguments(argument_count, vstack_ptr))) + LAUF_UNLIKELY(!fiber->transfer_arguments(argument_count, vstack_ptr))) [[unlikely]] LAUF_DO_PANIC("mismatched signature for fiber resume"); // Remove handle from stack. ++vstack_ptr; @@ -399,12 +403,12 @@ LAUF_VM_EXECUTE(fiber_transfer) auto fiber = lauf::get_fiber(process, handle); if (LAUF_UNLIKELY(fiber == nullptr || (fiber->status != lauf_runtime_fiber::suspended - && fiber->status != lauf_runtime_fiber::ready))) + && fiber->status != lauf_runtime_fiber::ready))) [[unlikely]] LAUF_DO_PANIC("invalid fiber handle"); // Transfer values from our vstack. if (auto argument_count = ip->fiber_resume.input_count; - LAUF_UNLIKELY(!fiber->transfer_arguments(argument_count, vstack_ptr))) + LAUF_UNLIKELY(!fiber->transfer_arguments(argument_count, vstack_ptr))) [[unlikely]] LAUF_DO_PANIC("mismatched signature for fiber resume"); // Remove handle from stack. ++vstack_ptr; @@ -427,7 +431,7 @@ LAUF_VM_EXECUTE(fiber_suspend) assert(process->cur_fiber->status == lauf_runtime_fiber::running); auto cur_fiber = process->cur_fiber; - if (LAUF_UNLIKELY(!cur_fiber->has_parent())) + if (LAUF_UNLIKELY(!cur_fiber->has_parent())) [[unlikely]] { // We're suspending the main fiber, so return instead. cur_fiber->suspend({ip, vstack_ptr, frame_ptr}, ip->fiber_suspend.output_count); @@ -437,12 +441,12 @@ LAUF_VM_EXECUTE(fiber_suspend) else { auto new_fiber = lauf::get_fiber(process, cur_fiber->parent); - if (LAUF_UNLIKELY(new_fiber == nullptr)) + if (LAUF_UNLIKELY(new_fiber == nullptr)) [[unlikely]] LAUF_DO_PANIC("cannot suspend to destroyed parent"); // Transfer values from our vstack. if (auto argument_count = ip->fiber_suspend.input_count; - LAUF_UNLIKELY(!new_fiber->transfer_arguments(argument_count, vstack_ptr))) + LAUF_UNLIKELY(!new_fiber->transfer_arguments(argument_count, vstack_ptr))) [[unlikely]] LAUF_DO_PANIC("mismatched signature for fiber resume"); // We resume the parent but without setting its parent (asymmetric). @@ -498,8 +502,9 @@ LAUF_VM_EXECUTE(global_addr) { --vstack_ptr; - vstack_ptr[0].as_address.allocation - = get_global_allocation_idx(frame_ptr, process, ip->global_addr.value); + LAUF_IGNORE_BITFIELD_WARNING( + vstack_ptr[0].as_address.allocation + = get_global_allocation_idx(frame_ptr, process, ip->global_addr.value)); vstack_ptr[0].as_address.offset = 0; vstack_ptr[0].as_address.generation = 0; // Always true for globals. @@ -526,7 +531,8 @@ LAUF_VM_EXECUTE(local_addr) auto allocation_idx = frame_ptr->first_local_alloc + ip->local_addr.index; --vstack_ptr; - vstack_ptr[0].as_address.allocation = std::uint32_t(allocation_idx); + LAUF_IGNORE_BITFIELD_WARNING(vstack_ptr[0].as_address.allocation + = std::uint32_t(allocation_idx)); vstack_ptr[0].as_address.offset = 0; vstack_ptr[0].as_address.generation = frame_ptr->local_generation; @@ -650,7 +656,7 @@ LAUF_VM_EXECUTE(select) auto idx = vstack_ptr[0].as_uint; ++vstack_ptr; - if (LAUF_UNLIKELY(idx > ip->select.idx)) + if (LAUF_UNLIKELY(idx > ip->select.idx)) [[unlikely]] LAUF_DO_PANIC("invalid select index"); auto value = vstack_ptr[idx]; @@ -665,12 +671,12 @@ LAUF_VM_EXECUTE(select) LAUF_VM_EXECUTE(setup_local_alloc) { // If necessary, grow the allocation array - this will then tail call back here. - if (LAUF_UNLIKELY(process->memory.needs_to_grow(ip->setup_local_alloc.value))) + if (LAUF_UNLIKELY(process->memory.needs_to_grow(ip->setup_local_alloc.value))) [[unlikely]] LAUF_TAIL_CALL return grow_allocation_array(ip, vstack_ptr, frame_ptr, process); // Setup the necessary metadata. - frame_ptr->first_local_alloc = process->memory.next_index(); - frame_ptr->local_generation = process->memory.cur_generation(); + LAUF_IGNORE_BITFIELD_WARNING(frame_ptr->first_local_alloc = process->memory.next_index()); + LAUF_IGNORE_BITFIELD_WARNING(frame_ptr->local_generation = process->memory.cur_generation()); ++ip; LAUF_VM_DISPATCH; @@ -697,7 +703,8 @@ LAUF_VM_EXECUTE(local_alloc_aligned) memory += lauf::align_offset(memory, ip->local_alloc_aligned.alignment()); // However, to increment the offset we need both alignment and size, as that was the offset // computation assumed in the builder. - frame_ptr->next_offset += ip->local_alloc_aligned.alignment() + ip->local_alloc.size; + LAUF_IGNORE_BITFIELD_WARNING(frame_ptr->next_offset + += ip->local_alloc_aligned.alignment() + ip->local_alloc.size); process->memory.new_allocation_unchecked( lauf::make_local_alloc(memory, ip->local_alloc.size, frame_ptr->local_generation)); @@ -718,13 +725,13 @@ LAUF_VM_EXECUTE(deref_const) auto address = vstack_ptr[0].as_address; auto alloc = process->memory.try_get(address); - if (LAUF_UNLIKELY(alloc == nullptr)) + if (LAUF_UNLIKELY(alloc == nullptr)) [[unlikely]] goto panic; { auto ptr = lauf::checked_offset(*alloc, address, {ip->deref_const.size, ip->deref_const.alignment()}); - if (LAUF_UNLIKELY(ptr == nullptr)) + if (LAUF_UNLIKELY(ptr == nullptr)) [[unlikely]] goto panic; vstack_ptr[0].as_native_ptr = const_cast(ptr); @@ -743,12 +750,13 @@ LAUF_VM_EXECUTE(deref_mut) auto alloc = process->memory.try_get(address); if (LAUF_UNLIKELY(alloc == nullptr) || LAUF_UNLIKELY(lauf::is_const(alloc->source))) + [[unlikely]] goto panic; { auto ptr = lauf::checked_offset(*alloc, address, {ip->deref_mut.size, ip->deref_mut.alignment()}); - if (LAUF_UNLIKELY(ptr == nullptr)) + if (LAUF_UNLIKELY(ptr == nullptr)) [[unlikely]] goto panic; vstack_ptr[0].as_native_ptr = const_cast(ptr); @@ -766,7 +774,8 @@ LAUF_VM_EXECUTE(array_element) auto address = vstack_ptr[1].as_address; auto index = vstack_ptr[0].as_sint; - address.offset += lauf_sint(ip->array_element.value) * index; + LAUF_IGNORE_BITFIELD_WARNING( + LAUF_IGNORE_SIGN_WARNING(address.offset += lauf_sint(ip->array_element.value) * index)); ++vstack_ptr; vstack_ptr[0].as_address = address; @@ -830,4 +839,3 @@ LAUF_VM_EXECUTE(store_global_value) ++ip; LAUF_VM_DISPATCH; } -