Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions include/prism/compiler/assume.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @file compiler/assume.h
*/
#ifndef PRISM_COMPILER_ASSUME_H
#define PRISM_COMPILER_ASSUME_H

/**
* Tell the compiler that the given expression can be assumed to be true. Unlike
* assert, this emits no runtime check — it only feeds the optimizer's value
* range analysis so it can prune impossible paths. Use it to communicate an
* invariant the caller guarantees but that the compiler cannot otherwise prove.
*/
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L /* C23 or later */
#define PRISM_ASSUME(expr_) [[assume(expr_)]]
#elif defined(__clang__)
#define PRISM_ASSUME(expr_) __builtin_assume(expr_)
#elif defined(_MSC_VER)
#define PRISM_ASSUME(expr_) __assume(expr_)
#elif defined(__GNUC__)
#define PRISM_ASSUME(expr_) ((expr_) ? (void) 0 : __builtin_unreachable())
#else
#define PRISM_ASSUME(expr_) ((void) 0)
#endif

#endif
1 change: 1 addition & 0 deletions prism.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Gem::Specification.new do |spec|
"include/prism.h",
"include/prism/compiler/accel.h",
"include/prism/compiler/align.h",
"include/prism/compiler/assume.h",
"include/prism/compiler/exported.h",
"include/prism/compiler/fallthrough.h",
"include/prism/compiler/filesystem.h",
Expand Down
3 changes: 3 additions & 0 deletions templates/src/diagnostic.c.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "prism/internal/diagnostic.h"

#include "prism/compiler/assume.h"
#include "prism/compiler/inline.h"

#include "prism/internal/allocator.h"
Expand Down Expand Up @@ -446,6 +447,7 @@ pm_diagnostic_id_name(pm_diagnostic_id_t diag_id) {
static PRISM_INLINE const char *
pm_diagnostic_id_message(pm_diagnostic_id_t diag_id) {
assert(diag_id < PM_DIAGNOSTIC_ID_MAX);
PRISM_ASSUME(diag_id < PM_DIAGNOSTIC_ID_MAX);

const char *message = diagnostic_messages[diag_id].message;
assert(message);
Expand All @@ -456,6 +458,7 @@ pm_diagnostic_id_message(pm_diagnostic_id_t diag_id) {
static PRISM_INLINE uint8_t
pm_diagnostic_id_level(pm_diagnostic_id_t diag_id) {
assert(diag_id < PM_DIAGNOSTIC_ID_MAX);
PRISM_ASSUME(diag_id < PM_DIAGNOSTIC_ID_MAX);

return (uint8_t) diagnostic_messages[diag_id].level;
}
Expand Down
Loading