You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
4.7 KiB
C

/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
#pragma once
#ifndef __clang__
#error "Unsupported compiler, please use clang"
#endif
#include <gay/_null.h>
#ifdef __cplusplus
#if defined(_KERNEL) && !defined(_CXX_KERNEL)
#error "C++ cannot be used in kernel code. Define _CXX_KERNEL if you know what you're doing."
#endif
/** @brief Use `__restrict` in header files, and just `restrict` in C code */
#define __restrict
#define __BEGIN_DELCS extern "C" {
#define __END_DECLS }
#else /* not __cplusplus */
#define __BEGIN_DECLS
#define __END_DECLS
#endif /* __cplusplus */
/** @brief Annotated symbol is an alias for another symbol. */
#define __alias(name) __attribute__(( alias(#name) ))
/** @brief Force a type to be aligned to a certain number of bytes. */
#define __aligned(bytes) __attribute__(( aligned(bytes) ))
/*
* gcc might try to be all cute and already predefine this for us.
* I know gcc is not supported, but i'm still putting it inside an ifdef
* just in case the clang people decide to do that as well at some point.
*/
#ifndef __always_inline
/** @brief Always try to inline a function, even with optimizations disabled. */
#define __always_inline inline __attribute__(( always_inline ))
#endif
/**
* @brief Annotated function behaves like an allocator, so the branch
* prediction optimizer will assume it's unlikely to return `NULL`.
*/
#define __malloc_like __attribute__(( malloc ))
/**
* @brief Hint that the returned pointer will be able to hold at least as much
* bytes as specified by argument number `argn` (counting from 1).
*/
#define __alloc_size(argn) __attribute__(( alloc_size(argn) ))
#define __naked __attribute(( naked ))
#define __noreturn __attribute__(( noreturn ))
/**
* @brief Hint that the returned pointer will be able to hold at least as much
* bytes as the product of the arguments `argn1` and `argn2` (counting from 1).
*/
#define __alloc_size2(argn1, argn2) __attribute__(( alloc_size(argn1, argn2) ))
/**
* @brief Tightly pack all members of a structure without any padding at the
* cost of performance. Should only be used for hardware registers and such.
*/
#define __packed __attribute__(( packed ))
#define __printflike(fmt_argn, firstva_argn) \
__attribute__(( format(printf, fmt_argn, firstva_argn) ))
/**
* @brief Function does not have any side effects or internal state.
* Subsequent calls with the same parameters always return the same result.
*/
#define __pure __attribute__(( pure ))
/**
* @brief Like `__pure`, and the function additionally does not access or
* manipulate any volatile memory except its own stack.
*/
#define __pure2 __attribute__(( const ))
/** @brief Put the annotated symbol in a specific section. */
#define __section(name) __attribute__(( section(name) ))
/** @brief Mark the symbol as used, even if it really isn't. */
#define __used __attribute__(( used ))
/** @brief Symbol may be silently redefined. */
#define __weak __attribute__(( weak ))
#ifdef __cplusplus
/**
* @brief If for whatever reason we ever get into the unfortunate situation of
* having to use C++, this annotation disables the funny name mangling feature
* so we actually have a chance of accessing the symbol from assembly. It also
* forcefully marks it as `__used` because a certain IDE doesn't have full
* assembly support even after it being in the issue tracker for 4 years and
* would therefore spit out annoying warnings about the symbol bring unused.
*/
#define __asmlink __used extern "C"
#else
/**
* @brief In non-C++ code, this isn't really required because C doesn't do name
* mangling, but we declare it `__used` because a certain IDE (*cough* CLion)
* doesn't have full assembly support and shows annoying unused warnings
*/
#define __asmlink __used
#endif
#ifndef offsetof
#define offsetof(type, member) __builtin_offsetof(type, member)
#endif
#ifndef typeof
#define typeof(expr) __typeof(expr)
#endif
/*
* These are hints for clang's branch optimizer which will try to arrange the
* code to yield the best performance when a condition is true or false.
*
* Use it sparingly and only in performance critical places because the overhead
* from rearranging and aligning the individual instructions can quickly make
* the kernel image too big.
* Also, only use it if you actually know *for sure* that a particular branch
* is *very* unlikely to be hit. Most modern CPUs have become pretty good at
* speculative execution (~~and intel even managed to make it buggy~~) and
* probably do a better job optimizing themselves at runtime than you can here.
* Finally, you don't need this when doing resource allocation failure checks,
* because those functions are annotated with __malloc_like anyway.
*/
#define __predict_true(x) __builtin_expect(x, 1)
#define __predict_false(x) __builtin_expect(x, 0)