Software APIs
Data Structures | Macros
macros.h File Reference

(5015f26)

Generic preprocessor macros that don't really fit anywhere else. More...

#include <assert.h>
#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Data Structures

struct  OtSignConversionUnsupportedType
 

Macros

#define ARRAYSIZE(array)   (sizeof(array) / sizeof(array[0]))
 Computes the number of elements in the given array. More...
 
#define OT_FALLTHROUGH_INTENDED   __attribute__((fallthrough))
 An annotation that a switch/case fallthrough is the intended behavior.
 
#define OT_ALWAYS_INLINE   __attribute__((always_inline)) inline
 A directive to force the compiler to inline a function.
 
#define OT_RESTRICT   __restrict__
 The restrict keyword is C specific, so we provide a C++-portable wrapper that uses the GCC name. More...
 
#define OT_STRINGIFY(a)   OT_STRINGIFY_(a)
 An argument stringification macro.
 
#define OT_STRINGIFY_(a)   #a
 
#define OT_VA_ARGS_COUNT(dummy, ...)
 A variable-argument macro that expands to the number of arguments passed into it, between 0 and 31 arguments. More...
 
#define OT_SHIFT_N_VARIABLE_ARGS_(...)   OT_GET_NTH_VARIABLE_ARG_(__VA_ARGS__)
 
#define OT_GET_NTH_VARIABLE_ARG_(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, n, ...)   n
 
#define OT_CAT(a, ...)   OT_PRIMITIVE_CAT(a, __VA_ARGS__)
 An argument concatenation macro. More...
 
#define OT_PRIMITIVE_CAT(a, ...)   a##__VA_ARGS__
 
#define OT_GET_ARG(n, ...)   OT_CAT(OT_CAT(OT_GET_ARG_, n), _)(__VA_ARGS__)
 A macro which gets the nth arg from a VA_LIST
 
#define OT_GET_LAST_ARG(...)   OT_GET_ARG(OT_VA_ARGS_COUNT(__VA_ARGS__), ##__VA_ARGS__)
 A macro which gets the last arg from a VA_LIST More...
 
#define OT_GET_ARG_0_(x0, ...)   x0
 The following collection of OT_GET_ARG macros are used to construct the generic "get nth arg" macro.
 
#define OT_GET_ARG_1_(x1, x0, ...)   x0
 
#define OT_GET_ARG_2_(x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_3_(x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_4_(x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_5_(x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_6_(x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_7_(x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_8_(x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_9_(x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_10_(x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_11_(x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_12_(x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_13_(x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_14_(x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_15_(x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_16_(x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_17_(x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_18_(x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_19_(x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_20_(x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_21_(x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_22_(x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_23_(x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_24_(x24, x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_25_(x25, x24, x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_26_(x26, x25, x24, x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_27_(x27, x26, x25, x24, x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_28_(x28, x27, x26, x25, x24, x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_29_(x29, x28, x27, x26, x25, x24, x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_30_(x30, x29, x28, x27, x26, x25, x24, x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_GET_ARG_31_(x31, x30, x29, x28, x27, x26, x25, x24, x23, x22, x21, x20, x19, x18, x17, x16, x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, ...)   x0
 
#define OT_ASSERT_MEMBER_OFFSET(type, member, offset)
 A macro that expands to an assertion for the offset of a struct member. More...
 
#define OT_ASSERT_MEMBER_SIZE(type, member, size)
 A macro that expands to an assertion for the size of a struct member. More...
 
#define OT_ASSERT_SIZE(type, size)   static_assert(sizeof(type) == UINT32_C(size), "Unexpected size for " #type)
 A macro that expands to an assertion for the size of a type. More...
 
#define OT_ASSERT_ENUM_VALUE(var, expected_value)   static_assert(var == expected_value, "Unexpected value for " #var)
 A macro that expands to an assertion for an expected enum value. More...
 
#define OT_WARN_UNUSED_RESULT   __attribute__((warn_unused_result))
 A macro representing the OpenTitan execution platform. More...
 
#define OT_WEAK   __attribute__((weak))
 Attribute for weak functions that can be overridden, e.g., ISRs.
 
#define OT_NAKED   __attribute__((naked))
 Attribute to construct functions without prologue/epilogue sequences. More...
 
#define OT_SECTION(name)   __attribute__((section(name)))
 Attribute to place symbols into particular sections. More...
 
#define OT_SET_BSS_SECTION(name, ...)
 Pragma meant to place symbols into a NOBITS section with a specified name. More...
 
#define OT_SET_BSS_SECTION_(section)   _Pragma(#section)
 
#define OT_NOINLINE   __attribute__((noinline))
 Attribute to suppress the inlining of a function at its call sites. More...
 
#define OT_FRAME_ADDR()   __builtin_frame_address(0)
 Returns the address of the current function stack frame. More...
 
#define OT_UNREACHABLE()   __builtin_unreachable()
 Hints to the compiler that some point is not reachable. More...
 
#define OT_ALIAS(name)   __attribute__((alias(name)))
 Attribute for weak alias that can be overridden, e.g., Mock overrides in DIFs.
 
#define OT_ADDRESSABLE_LABEL(kName_)
 Defines a local symbol named kName_ whose address resolves to the program counter value an inline assembly block at this location would see. More...
 
#define OT_DISCARD(expr_)
 Evaluates and discards expr_. More...
 
#define OT_USED   __attribute__((used))
 An attribute used for static variables indicating that they should be retained in the object file, even if they are seemingly unreferenced.
 
#define OT_BUILD_FOR_STATIC_ANALYZER   0
 OT_BUILD_FOR_STATIC_ANALYZER indicates whether we are compiling for the purpose of static analysis. More...
 
#define OT_ALIGN_MEM(x)   (uint32_t)(4 + (((uintptr_t)(x)-1) & ~3u))
 This macro is used to align an offset to point to a 32b value.
 
#define OT_SIGNED(value)
 This macro converts a given unsigned integer value to its signed counterpart. More...
 
#define OT_UNSIGNED(value)
 This macro converts a given signed integer value to its unsigned counterpart. More...
 
#define ATOMIC_WAIT_FOR_INTERRUPT(_volatile_condition)
 

Detailed Description

Generic preprocessor macros that don't really fit anywhere else.

Definition in file macros.h.


Data Structure Documentation

◆ OtSignConversionUnsupportedType

struct OtSignConversionUnsupportedType

Definition at line 473 of file macros.h.

Data Fields
char err

Macro Definition Documentation

◆ ARRAYSIZE

#define ARRAYSIZE (   array)    (sizeof(array) / sizeof(array[0]))

Computes the number of elements in the given array.

Note that this can only determine the length of fixed-size arrays. Due to limitations of C, it will incorrectly compute the size of an array passed as a function argument, because those automatically decay into pointers. This function can only be used correctly with:

  • Arrays declared as stack variables.
  • Arrays declared at global scope.
  • Arrays that are members of a struct or union.
Parameters
arrayThe array expression to measure.
Returns
The number of elements in the array, as a size_t.

Definition at line 45 of file macros.h.

◆ ATOMIC_WAIT_FOR_INTERRUPT

#define ATOMIC_WAIT_FOR_INTERRUPT (   _volatile_condition)
Value:
while (true) { \
irq_global_ctrl(false); \
if ((_volatile_condition)) { \
break; \
} \
wait_for_interrupt(); \
irq_global_ctrl(true); \
} \
irq_global_ctrl(true)

Definition at line 528 of file macros.h.

◆ OT_ADDRESSABLE_LABEL

#define OT_ADDRESSABLE_LABEL (   kName_)
Value:
extern const char kName_[]; \
asm volatile(".local " #kName_ "; " #kName_ ":;"); \
/* Force this to be at function scope. It could go at global scope, but it \
* would give a garbage value dependent on the whims of the linker. */ \
do { \
} while (false)

Defines a local symbol named kName_ whose address resolves to the program counter value an inline assembly block at this location would see.

The primary intention of this macro is to allow for peripheral tests to be written that want to assert that a specific program counter reported by the hardware corresponds to actual code that executed.

For example, suppose that we're waiting for an interrupt to fire, and want to verify that it fired in a specific region. We have two volatile globals: irq_happened, which the ISR sets before returning, and irq_pc, which the ISR sets to whatever PC the hardware reports it came from. The code below tests that the reported PC matches expectations.

OT_ADDRESSABLE_LABEL(kIrqWaitStart);
enable_interrupts();
while(!irq_happened) {
}
OT_ADDRESSABLE_LABEL(kIrqWaitEnd);
CHECK(irq_pc >= &kIrqWaitStart && irq_pc < &IrqWaitEnd);

Note that this only works if all functions called between the two labels are actually inlined; if the interrupt fires inside of one of those two functions, it will appear to not have the right PC, even though it is logically inside the pair of labels.

Volatile Semantics

This has the same semantics as a volatile inline assembly block: it may be reordered with respect to all operations except other volatile operations (i.e. volatile assembly and volatile read/write, such as MMIO). For example, in the following code, kBefore and kAfter can wind up having the same address:

x += 5;

Because it can be reordered and the compiler is free to emit whatever instructions it likes, comparing a program counter value obtained from the hardware with a symbol emitted by this macro is brittle (and, ultimately, futile). Instead, it should be used in pairs to create a range of addresses that a value can be checked for being within.

For this primitive to work correctly there must be something that counts as a volatile operation between the two labels. These include:

  • Direct reads or writes to MMIO registers or CSRs.
  • A volatile assembly block with at least one instruction.
  • Any DIF or driver call that may touch an MMIO register or a CSR.
  • LOGging, printfing, or CHECKing.
  • wait_for_interrupt().
  • barrier32(), but NOT launder32().

This macro should not be used on the host side. It will compile, but will probably not provide any meaningful values. In the future, it may start producing a garbage value on the host side.

Symbol Access

The symbol reference kName_ will only be scoped to the current block in a function, but it can be redeclared in the same file with

extern const char kName_[];

if needed elsewhere (although this should be avoided for readability's sake). The name of the constant is global to the current .c file only.

Example Uses

Definition at line 432 of file macros.h.

◆ OT_ASSERT_ENUM_VALUE

#define OT_ASSERT_ENUM_VALUE (   var,
  expected_value 
)    static_assert(var == expected_value, "Unexpected value for " #var)

A macro that expands to an assertion for an expected enum value.

Parameters
varAn enum entry.
expected_valueExpected enum value.

Definition at line 244 of file macros.h.

◆ OT_ASSERT_MEMBER_OFFSET

#define OT_ASSERT_MEMBER_OFFSET (   type,
  member,
  offset 
)
Value:
static_assert(offsetof(type, member) == UINT32_C(offset), \
"Unexpected offset for " #type "." #member)

A macro that expands to an assertion for the offset of a struct member.

Parameters
typeA struct type.
memberA member of the struct.
offsetExpected offset of the member.

Definition at line 214 of file macros.h.

◆ OT_ASSERT_MEMBER_SIZE

#define OT_ASSERT_MEMBER_SIZE (   type,
  member,
  size 
)
Value:
static_assert(sizeof(((type){0}).member) == UINT32_C(size), \
"Unexpected size for " #type)

A macro that expands to an assertion for the size of a struct member.

Parameters
typeA struct type.
memberA member of the struct.
sizeExpected size of the type.

Definition at line 225 of file macros.h.

◆ OT_ASSERT_SIZE

#define OT_ASSERT_SIZE (   type,
  size 
)    static_assert(sizeof(type) == UINT32_C(size), "Unexpected size for " #type)

A macro that expands to an assertion for the size of a type.

Parameters
typeA type.
sizeExpected size of the type.

Definition at line 235 of file macros.h.

◆ OT_BUILD_FOR_STATIC_ANALYZER

#define OT_BUILD_FOR_STATIC_ANALYZER   0

OT_BUILD_FOR_STATIC_ANALYZER indicates whether we are compiling for the purpose of static analysis.

Currently, this macro only detects Clang-Analyzer, which is used as a backend by Clang-Tidy.

Definition at line 462 of file macros.h.

◆ OT_CAT

#define OT_CAT (   a,
  ... 
)    OT_PRIMITIVE_CAT(a, __VA_ARGS__)

An argument concatenation macro.

Because the ## operator inhibits expansion, we use a level of indirection to create a macro which concatenates without inhibition.

Definition at line 103 of file macros.h.

◆ OT_DISCARD

#define OT_DISCARD (   expr_)
Value:
if (expr_) { \
}

Evaluates and discards expr_.

This is needed because ‘(void)expr;` does not work for gcc.

Definition at line 444 of file macros.h.

◆ OT_FRAME_ADDR

#define OT_FRAME_ADDR ( )    __builtin_frame_address(0)

Returns the address of the current function stack frame.

See https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html.

Definition at line 333 of file macros.h.

◆ OT_GET_LAST_ARG

#define OT_GET_LAST_ARG (   ...)    OT_GET_ARG(OT_VA_ARGS_COUNT(__VA_ARGS__), ##__VA_ARGS__)

A macro which gets the last arg from a VA_LIST

Note: we leave out the dummy argument because we want count to give us the number of args minus one so that the created OT_GET_ARG_n token will contain the correct integer.

Definition at line 118 of file macros.h.

◆ OT_NAKED

#define OT_NAKED   __attribute__((naked))

Attribute to construct functions without prologue/epilogue sequences.

Only basic asm statements can be safely included in naked functions.

See https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html #RISC-V-Function-Attributes

Definition at line 291 of file macros.h.

◆ OT_NOINLINE

#define OT_NOINLINE   __attribute__((noinline))

Attribute to suppress the inlining of a function at its call sites.

See https://clang.llvm.org/docs/AttributeReference.html#noinline.

Definition at line 326 of file macros.h.

◆ OT_RESTRICT

#define OT_RESTRICT   __restrict__

The restrict keyword is C specific, so we provide a C++-portable wrapper that uses the GCC name.

It only needs to be used in headers; .c files can use restrict directly.

Definition at line 63 of file macros.h.

◆ OT_SECTION

#define OT_SECTION (   name)    __attribute__((section(name)))

Attribute to place symbols into particular sections.

See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html #Common-Function-Attributes

Definition at line 299 of file macros.h.

◆ OT_SET_BSS_SECTION

#define OT_SET_BSS_SECTION (   name,
  ... 
)
Value:
OT_SET_BSS_SECTION_(clang section bss = name) \
__VA_ARGS__ \
_Pragma("clang section bss = \"\"")

Pragma meant to place symbols into a NOBITS section with a specified name.

This should only be used for zero-initialized globals (including implicitly zero-initialized ones, when the initializer is missing). The pragma won't affect variables that do not go into the bss section.

Example:

OT_SET_BSS_SECTION(".foo", uint32_t x; // emitted in section .foo instead of .bss uint32_t y = 42; // emitted in regular .data section (but don't do this) )

Definition at line 315 of file macros.h.

◆ OT_SIGNED

#define OT_SIGNED (   value)
Value:
_Generic((value), \
uint8_t: (int8_t)(value), \
uint16_t: (int16_t)(value), \
uint32_t: (int32_t)(value), \
uint64_t: (int64_t)(value), \
default: (struct OtSignConversionUnsupportedType){.err = 1})

This macro converts a given unsigned integer value to its signed counterpart.

Definition at line 480 of file macros.h.

◆ OT_UNREACHABLE

#define OT_UNREACHABLE ( )    __builtin_unreachable()

Hints to the compiler that some point is not reachable.

One use case could be a function that never returns.

Please not that if the control flow reaches the point of the __builtin_unreachable, the program is undefined.

See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.

Definition at line 345 of file macros.h.

◆ OT_UNSIGNED

#define OT_UNSIGNED (   value)
Value:
_Generic((value), \
int8_t: (uint8_t)(value), \
int16_t: (uint16_t)(value), \
int32_t: (uint32_t)(value), \
int64_t: (uint64_t)(value), \
default: (struct OtSignConversionUnsupportedType){.err = 1})

This macro converts a given signed integer value to its unsigned counterpart.

Definition at line 491 of file macros.h.

◆ OT_VA_ARGS_COUNT

#define OT_VA_ARGS_COUNT (   dummy,
  ... 
)
Value:
OT_SHIFT_N_VARIABLE_ARGS_(dummy, ##__VA_ARGS__, 31, 30, 29, 28, 27, 26, 25, \
24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, \
12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

A variable-argument macro that expands to the number of arguments passed into it, between 0 and 31 arguments.

This macro is based off of a well-known preprocessor trick. This StackOverflow post expains the trick in detail: https://stackoverflow.com/questions/2308243/macro-returning-the-number-of-arguments-it-is-given-in-c TODO #2026: a dummy token is required for this to work correctly.

Parameters
dummya dummy token that is required to be passed for the calculation to work correctly.
...the variable args list.

Definition at line 84 of file macros.h.

◆ OT_WARN_UNUSED_RESULT

#define OT_WARN_UNUSED_RESULT   __attribute__((warn_unused_result))

A macro representing the OpenTitan execution platform.

A macro indicating whether software should assume reduced hardware support (for the top_englishbreakafst toplevel). Attribute for functions which return errors that must be acknowledged.

This attribute must be used to mark all DIFs which return an error value of some kind, to ensure that callers do not accidentally drop the error on the ground.

Normally, the standard way to drop such a value on the ground explicitly is with the syntax (void)expr;, in analogy with the behavior of C++'s [[nodiscard]] attribute. However, GCC does not implement this, so the idiom if (expr) {} should be used instead, for the time being. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509.

Definition at line 276 of file macros.h.