diff --git a/config.h.meson b/config.h.meson index 0cb6789..69a4724 100644 --- a/config.h.meson +++ b/config.h.meson @@ -1,6 +1,19 @@ #mesondefine VERSION #mesondefine _GNU_SOURCE #mesondefine VIRGL_RENDERER_UNSTABLE_APIS +#mesondefine HAVE___BUILTIN_EXPECT +#mesondefine HAVE___BUILTIN_TYPES_COMPATIBLE_P +#mesondefine HAVE___BUILTIN_UNREACHABLE +#mesondefine HAVE_FUNC_ATTRIBUTE_CONST +#mesondefine HAVE_FUNC_ATTRIBUTE_FLATTEN +#mesondefine HAVE_FUNC_ATTRIBUTE_FORMAT +#mesondefine HAVE_FUNC_ATTRIBUTE_MALLOC +#mesondefine HAVE_FUNC_ATTRIBUTE_NORETURN +#mesondefine HAVE_FUNC_ATTRIBUTE_PACKED +#mesondefine HAVE_FUNC_ATTRIBUTE_PURE +#mesondefine HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL +#mesondefine HAVE_FUNC_ATTRIBUTE_UNUSED +#mesondefine HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT #mesondefine HAVE_FUNC_ATTRIBUTE_WEAK #mesondefine HAVE_TIMESPEC_GET #mesondefine HAVE_SYS_UIO_H diff --git a/meson.build b/meson.build index b410d39..f8c1ef3 100644 --- a/meson.build +++ b/meson.build @@ -126,8 +126,15 @@ if cc.has_header('sys/select.h') conf_data.set('HAVE_SYS_SELECT_H', 1) endif +foreach b : ['expect', 'types_compatible_p', 'unreachable'] + if cc.has_function(b) + conf_data.set('HAVE___BUILTIN_@0@'.format(b.to_upper()), 1) + endif +endforeach + supported_function_attributes = cc.get_supported_function_attributes([ - 'weak' + 'const', 'flatten', 'format', 'malloc', 'noreturn', 'packed', 'pure', + 'returns_nonnull', 'unused', 'warn_unused_result', 'weak', ]) foreach a : supported_function_attributes conf_data.set('HAVE_FUNC_ATTRIBUTE_@0@'.format(a.to_upper()), 1) diff --git a/src/gallium/auxiliary/os/os_misc.h b/src/gallium/auxiliary/os/os_misc.h index a89256e..cbb5cbd 100644 --- a/src/gallium/auxiliary/os/os_misc.h +++ b/src/gallium/auxiliary/os/os_misc.h @@ -43,18 +43,6 @@ # include /* getpid() */ #endif -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#ifdef NDEBUG -#define MAYBE_UNUSED __attribute__((unused)) -#else -#define MAYBE_UNUSED -#endif -#else -#define UNUSED -#define MAYBE_UNUSED -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 9a12ae1..1b9c51a 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -821,8 +821,9 @@ util_bswap16(uint16_t n) /** * Clamp X to [MIN, MAX]. * This is a macro to allow float, int, uint, etc. types. + * We arbitrarily turn NaN into MIN. */ -#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) +#define CLAMP( X, MIN, MAX ) ( (X)>(MIN) ? ((X)>(MAX) ? (MAX) : (X)) : (MIN) ) #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) #define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) diff --git a/src/gallium/auxiliary/util/u_surface.c b/src/gallium/auxiliary/util/u_surface.c index ca27481..3836c4c 100644 --- a/src/gallium/auxiliary/util/u_surface.c +++ b/src/gallium/auxiliary/util/u_surface.c @@ -254,7 +254,7 @@ util_resource_copy_region(struct pipe_context *pipe, struct pipe_transfer *src_trans, *dst_trans; uint8_t *dst_map; const uint8_t *src_map; - MAYBE_UNUSED enum pipe_format src_format; + ASSERTED enum pipe_format src_format; enum pipe_format dst_format; struct pipe_box dst_box; diff --git a/src/gallium/meson.build b/src/gallium/meson.build index 8cc533d..e839640 100644 --- a/src/gallium/meson.build +++ b/src/gallium/meson.build @@ -28,7 +28,6 @@ sources_libgallium = [ 'include/pipe/p_format.h', 'include/pipe/p_shader_tokens.h', 'include/pipe/p_screen.h', - 'include/pipe/p_compiler.h', 'include/pipe/p_video_enums.h', 'auxiliary/util/u_format.h', 'auxiliary/util/u_memory.h', diff --git a/src/gallium/include/pipe/p_compiler.h b/src/mesa/pipe/p_compiler.h similarity index 61% rename from src/gallium/include/pipe/p_compiler.h rename to src/mesa/pipe/p_compiler.h index 8156dd3..0ba459b 100644 --- a/src/gallium/include/pipe/p_compiler.h +++ b/src/mesa/pipe/p_compiler.h @@ -29,14 +29,18 @@ #define P_COMPILER_H +#include "c99_compat.h" /* inline, __func__, etc. */ #include "p_config.h" +#include "util/macros.h" + #include #include #include #include #include +/* (virglrenderer) To get uint typedef with musl */ #include @@ -46,6 +50,8 @@ #if defined(_MSC_VER) +#include + /* Avoid 'expression is always true' warning */ #pragma warning(disable: 4296) @@ -56,9 +62,6 @@ * Alternative stdint.h and stdbool.h headers are supplied in include/c99 for * systems that lack it. */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif #include #include @@ -92,17 +95,6 @@ typedef unsigned char boolean; #endif #endif -/* Function visibility */ -#ifndef PUBLIC -# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) -# define PUBLIC __attribute__((visibility("default"))) -# elif defined(_MSC_VER) -# define PUBLIC __declspec(dllexport) -# else -# define PUBLIC -# endif -#endif - /* XXX: Use standard `__func__` instead */ #ifndef __FUNCTION__ @@ -130,7 +122,7 @@ typedef unsigned char boolean; /* Macros for data alignment. */ -#if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) || defined(__SUNPRO_CC) +#if defined(__GNUC__) /* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Type-Attributes.html */ #define PIPE_ALIGN_TYPE(_alignment, _type) _type __attribute__((aligned(_alignment))) @@ -138,7 +130,7 @@ typedef unsigned char boolean; /* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Variable-Attributes.html */ #define PIPE_ALIGN_VAR(_alignment) __attribute__((aligned(_alignment))) -#if (__GNUC__ > 4 || (__GNUC__ == 4 &&__GNUC_MINOR__>1)) && !defined(PIPE_ARCH_X86_64) +#if defined(__GNUC__) && defined(PIPE_ARCH_X86) #define PIPE_ALIGN_STACK __attribute__((force_align_arg_pointer)) #else #define PIPE_ALIGN_STACK @@ -172,14 +164,8 @@ typedef unsigned char boolean; #elif defined(_MSC_VER) -void _ReadWriteBarrier(void); -#pragma intrinsic(_ReadWriteBarrier) #define PIPE_READ_WRITE_BARRIER() _ReadWriteBarrier() -#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) - -#define PIPE_READ_WRITE_BARRIER() __machine_rw_barrier() - #else #warning "Unsupported compiler" @@ -187,61 +173,6 @@ void _ReadWriteBarrier(void); #endif - -/* You should use these macros to mark if blocks where the if condition - * is either likely to be true, or unlikely to be true. - * - * This will inform human readers of this fact, and will also inform - * the compiler, who will in turn inform the CPU. - * - * CPUs often start executing code inside the if or the else blocks - * without knowing whether the condition is true or not, and will have - * to throw the work away if they find out later they executed the - * wrong part of the if. - * - * If these macros are used, the CPU is more likely to correctly predict - * the right path, and will avoid speculatively executing the wrong branch, - * thus not throwing away work, resulting in better performance. - * - * In light of this, it is also a good idea to mark as "likely" a path - * which is not necessarily always more likely, but that will benefit much - * more from performance improvements since it is already much faster than - * the other path, or viceversa with "unlikely". - * - * Example usage: - * if(unlikely(do_we_need_a_software_fallback())) - * do_software_fallback(); - * else - * render_with_gpu(); - * - * The macros follow the Linux kernel convention, and more examples can - * be found there. - * - * Note that profile guided optimization can offer better results, but - * needs an appropriate coverage suite and does not inform human readers. - */ -#ifndef likely -# if defined(__GNUC__) -# define likely(x) __builtin_expect(!!(x), 1) -# define unlikely(x) __builtin_expect(!!(x), 0) -# else -# define likely(x) (x) -# define unlikely(x) (x) -# endif -#endif - - -/** - * Static (compile-time) assertion. - * Basically, use COND to dimension an array. If COND is false/zero the - * array size will be -1 and we'll get a compilation error. - */ -#define STATIC_ASSERT(COND) \ - do { \ - (void) sizeof(char [1 - 2*!(COND)]); \ - } while (0) - - #if defined(__cplusplus) } #endif diff --git a/src/mesa/util/macros.h b/src/mesa/util/macros.h new file mode 100644 index 0000000..e179479 --- /dev/null +++ b/src/mesa/util/macros.h @@ -0,0 +1,480 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UTIL_MACROS_H +#define UTIL_MACROS_H + +#include +#include + +#include "c99_compat.h" +#include "c11_compat.h" + +#include + +/* Compute the size of an array */ +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +/* For compatibility with Clang's __has_builtin() */ +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + +/** + * __builtin_expect macros + */ +#if !defined(HAVE___BUILTIN_EXPECT) +# define __builtin_expect(x, y) (x) +#endif + +#ifndef likely +# ifdef HAVE___BUILTIN_EXPECT +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +# else +# define likely(x) (x) +# define unlikely(x) (x) +# endif +#endif + +/** + * __builtin_types_compatible_p compat + */ +#if defined(__cplusplus) || !defined(HAVE___BUILTIN_TYPES_COMPATIBLE_P) +# define __builtin_types_compatible_p(type1, type2) (1) +#endif + +/** + * Static (compile-time) assertion. + */ +#if defined(_MSC_VER) + /* MSVC doesn't like VLA's, but it also dislikes zero length arrays + * (which gcc is happy with), so we have to define STATIC_ASSERT() + * slightly differently. + */ +# define STATIC_ASSERT(COND) do { \ + (void) sizeof(char [(COND) != 0]); \ + } while (0) +#elif defined(__GNUC__) + /* This version of STATIC_ASSERT() relies on VLAs. If COND is + * false/zero, the array size will be -1 and we'll get a compile + * error + */ +# define STATIC_ASSERT(COND) do { \ + (void) sizeof(char [1 - 2*!(COND)]); \ + } while (0) +#else +# define STATIC_ASSERT(COND) do { } while (0) +#endif + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + */ +#ifndef __GNUC__ + /* a grown-up compiler is required for the extra type checking: */ +# define container_of(ptr, type, member) \ + (type*)((uint8_t *)ptr - offsetof(type, member)) +#else +# define __same_type(a, b) \ + __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) +# define container_of(ptr, type, member) ({ \ + uint8_t *__mptr = (uint8_t *)(ptr); \ + STATIC_ASSERT(__same_type(*(ptr), ((type *)0)->member) || \ + __same_type(*(ptr), void) || \ + !"pointer type mismatch in container_of()"); \ + ((type *)(__mptr - offsetof(type, member))); \ + }) +#endif + +/** + * Unreachable macro. Useful for suppressing "control reaches end of non-void + * function" warnings. + */ +#if defined(HAVE___BUILTIN_UNREACHABLE) || __has_builtin(__builtin_unreachable) +#define unreachable(str) \ +do { \ + assert(!str); \ + __builtin_unreachable(); \ +} while (0) +#elif defined (_MSC_VER) +#define unreachable(str) \ +do { \ + assert(!str); \ + __assume(0); \ +} while (0) +#else +#define unreachable(str) assert(!str) +#endif + +/** + * Assume macro. Useful for expressing our assumptions to the compiler, + * typically for purposes of silencing warnings. + */ +#if __has_builtin(__builtin_assume) +#define assume(expr) \ +do { \ + assert(expr); \ + __builtin_assume(expr); \ +} while (0) +#elif defined HAVE___BUILTIN_UNREACHABLE +#define assume(expr) ((expr) ? ((void) 0) \ + : (assert(!"assumption failed"), \ + __builtin_unreachable())) +#elif defined (_MSC_VER) +#define assume(expr) __assume(expr) +#else +#define assume(expr) assert(expr) +#endif + +/* Attribute const is used for functions that have no effects other than their + * return value, and only rely on the argument values to compute the return + * value. As a result, calls to it can be CSEed. Note that using memory + * pointed to by the arguments is not allowed for const functions. + */ +#ifdef HAVE_FUNC_ATTRIBUTE_CONST +#define ATTRIBUTE_CONST __attribute__((__const__)) +#else +#define ATTRIBUTE_CONST +#endif + +#ifdef HAVE_FUNC_ATTRIBUTE_FLATTEN +#define FLATTEN __attribute__((__flatten__)) +#else +#define FLATTEN +#endif + +#ifdef HAVE_FUNC_ATTRIBUTE_FORMAT +#if defined (__MINGW_PRINTF_FORMAT) +# define PRINTFLIKE(f, a) __attribute__ ((format(__MINGW_PRINTF_FORMAT, f, a))) +#else +# define PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a))) +#endif +#else +#define PRINTFLIKE(f, a) +#endif + +#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC +#define MALLOCLIKE __attribute__((__malloc__)) +#else +#define MALLOCLIKE +#endif + +/* Forced function inlining */ +/* Note: Clang also sets __GNUC__ (see other cases below) */ +#ifndef ALWAYS_INLINE +# if defined(__GNUC__) +# define ALWAYS_INLINE inline __attribute__((always_inline)) +# elif defined(_MSC_VER) +# define ALWAYS_INLINE __forceinline +# else +# define ALWAYS_INLINE inline +# endif +#endif + +/* Used to optionally mark structures with misaligned elements or size as + * packed, to trade off performance for space. + */ +#ifdef HAVE_FUNC_ATTRIBUTE_PACKED +#define PACKED __attribute__((__packed__)) +#else +#define PACKED +#endif + +/* Attribute pure is used for functions that have no effects other than their + * return value. As a result, calls to it can be dead code eliminated. + */ +#ifdef HAVE_FUNC_ATTRIBUTE_PURE +#define ATTRIBUTE_PURE __attribute__((__pure__)) +#else +#define ATTRIBUTE_PURE +#endif + +#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL +#define ATTRIBUTE_RETURNS_NONNULL __attribute__((__returns_nonnull__)) +#else +#define ATTRIBUTE_RETURNS_NONNULL +#endif + +#ifndef NORETURN +# ifdef _MSC_VER +# define NORETURN __declspec(noreturn) +# elif defined HAVE_FUNC_ATTRIBUTE_NORETURN +# define NORETURN __attribute__((__noreturn__)) +# else +# define NORETURN +# endif +#endif + +#ifdef _MSC_VER +#define ALIGN16 __declspec(align(16)) +#else +#define ALIGN16 __attribute__((aligned(16))) +#endif + +#ifdef __cplusplus +/** + * Macro function that evaluates to true if T is a trivially + * destructible type -- that is, if its (non-virtual) destructor + * performs no action and all member variables and base classes are + * trivially destructible themselves. + */ +# if (defined(__clang__) && defined(__has_feature)) +# if __has_feature(has_trivial_destructor) +# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) +# endif +# elif defined(__GNUC__) +# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))) +# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) +# endif +# elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) +# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) +# endif +# ifndef HAS_TRIVIAL_DESTRUCTOR + /* It's always safe (if inefficient) to assume that a + * destructor is non-trivial. + */ +# define HAS_TRIVIAL_DESTRUCTOR(T) (false) +# endif +#endif + +/** + * PUBLIC/USED macros + * + * If we build the library with gcc's -fvisibility=hidden flag, we'll + * use the PUBLIC macro to mark functions that are to be exported. + * + * We also need to define a USED attribute, so the optimizer doesn't + * inline a static function that we later use in an alias. - ajax + */ +#ifndef PUBLIC +# if defined(_WIN32) +# define PUBLIC __declspec(dllexport) +# define USED +# elif defined(__GNUC__) +# define PUBLIC __attribute__((visibility("default"))) +# define USED __attribute__((used)) +# else +# define PUBLIC +# define USED +# endif +#endif + +/** + * UNUSED marks variables (or sometimes functions) that have to be defined, + * but are sometimes (or always) unused beyond that. A common case is for + * a function parameter to be used in some build configurations but not others. + * Another case is fallback vfuncs that don't do anything with their params. + * + * Note that this should not be used for identifiers used in `assert()`; + * see ASSERTED below. + */ +#ifdef HAVE_FUNC_ATTRIBUTE_UNUSED +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + +/** + * Use ASSERTED to indicate that an identifier is unused outside of an `assert()`, + * so that assert-free builds don't get "unused variable" warnings. + */ +#ifdef NDEBUG +#define ASSERTED UNUSED +#else +#define ASSERTED +#endif + +#ifdef HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT +#define MUST_CHECK __attribute__((warn_unused_result)) +#else +#define MUST_CHECK +#endif + +#if defined(__GNUC__) +#define ATTRIBUTE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define ATTRIBUTE_NOINLINE +#endif + +/* Use as: enum name { X, Y } ENUM_PACKED; */ +#if defined(__GNUC__) +#define ENUM_PACKED __attribute__((packed)) +#else +#define ENUM_PACKED +#endif + + +/** + * Check that STRUCT::FIELD can hold MAXVAL. We use a lot of bitfields + * in Mesa/gallium. We have to be sure they're of sufficient size to + * hold the largest expected value. + * Note that with MSVC, enums are signed and enum bitfields need one extra + * high bit (always zero) to ensure the max value is handled correctly. + * This macro will detect that with MSVC, but not GCC. + */ +#define ASSERT_BITFIELD_SIZE(STRUCT, FIELD, MAXVAL) \ + do { \ + ASSERTED STRUCT s; \ + s.FIELD = (MAXVAL); \ + assert((int) s.FIELD == (MAXVAL) && "Insufficient bitfield size!"); \ + } while (0) + + +/** Compute ceiling of integer quotient of A divided by B. */ +#define DIV_ROUND_UP( A, B ) ( ((A) + (B) - 1) / (B) ) + +/** Clamp X to [MIN,MAX]. Turn NaN into MIN, arbitrarily. */ +#define CLAMP( X, MIN, MAX ) ( (X)>(MIN) ? ((X)>(MAX) ? (MAX) : (X)) : (MIN) ) + +/* Syntax sugar occuring frequently in graphics code */ +#define SATURATE( X ) CLAMP(X, 0.0f, 1.0f) + +/** Minimum of two values: */ +#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) + +/** Maximum of two values: */ +#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) + +/** Minimum and maximum of three values: */ +#define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C)) +#define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) + +/** Align a value to a power of two */ +#define ALIGN_POT(x, pot_align) (((x) + (pot_align) - 1) & ~((pot_align) - 1)) + +/** + * Macro for declaring an explicit conversion operator. Defaults to an + * implicit conversion if C++11 is not supported. + */ +#if __cplusplus >= 201103L +#define EXPLICIT_CONVERSION explicit +#elif defined(__cplusplus) +#define EXPLICIT_CONVERSION +#endif + +/** Set a single bit */ +#define BITFIELD_BIT(b) (1u << (b)) +/** Set all bits up to excluding bit b */ +#define BITFIELD_MASK(b) \ + ((b) == 32 ? (~0u) : BITFIELD_BIT((b) % 32) - 1) +/** Set count bits starting from bit b */ +#define BITFIELD_RANGE(b, count) \ + (BITFIELD_MASK((b) + (count)) & ~BITFIELD_MASK(b)) + +/** Set a single bit */ +#define BITFIELD64_BIT(b) (1ull << (b)) +/** Set all bits up to excluding bit b */ +#define BITFIELD64_MASK(b) \ + ((b) == 64 ? (~0ull) : BITFIELD64_BIT(b) - 1) +/** Set count bits starting from bit b */ +#define BITFIELD64_RANGE(b, count) \ + (BITFIELD64_MASK((b) + (count)) & ~BITFIELD64_MASK(b)) + +static inline int64_t +u_intN_max(unsigned bit_size) +{ + assert(bit_size <= 64 && bit_size > 0); + return INT64_MAX >> (64 - bit_size); +} + +static inline int64_t +u_intN_min(unsigned bit_size) +{ + /* On 2's compliment platforms, which is every platform Mesa is likely to + * every worry about, stdint.h generally calculated INT##_MIN in this + * manner. + */ + return (-u_intN_max(bit_size)) - 1; +} + +static inline uint64_t +u_uintN_max(unsigned bit_size) +{ + assert(bit_size <= 64 && bit_size > 0); + return UINT64_MAX >> (64 - bit_size); +} + +/* TODO: In future we should try to move this to u_debug.h once header + * dependencies are reorganised to allow this. + */ +enum pipe_debug_type +{ + PIPE_DEBUG_TYPE_OUT_OF_MEMORY = 1, + PIPE_DEBUG_TYPE_ERROR, + PIPE_DEBUG_TYPE_SHADER_INFO, + PIPE_DEBUG_TYPE_PERF_INFO, + PIPE_DEBUG_TYPE_INFO, + PIPE_DEBUG_TYPE_FALLBACK, + PIPE_DEBUG_TYPE_CONFORMANCE, +}; + +#if !defined(alignof) && !defined(__cplusplus) +#if __STDC_VERSION__ >= 201112L +#define alignof(t) _Alignof(t) +#elif defined(_MSC_VER) +#define alignof(t) __alignof(t) +#else +#define alignof(t) __alignof__(t) +#endif +#endif + +/* Macros for static type-safety checking. + * + * https://clang.llvm.org/docs/ThreadSafetyAnalysis.html + */ + +#if __has_attribute(capability) +typedef int __attribute__((capability("mutex"))) lock_cap_t; + +#define guarded_by(l) __attribute__((guarded_by(l))) +#define acquire_cap(l) __attribute((acquire_capability(l), no_thread_safety_analysis)) +#define release_cap(l) __attribute((release_capability(l), no_thread_safety_analysis)) +#define assert_cap(l) __attribute((assert_capability(l), no_thread_safety_analysis)) +#define requires_cap(l) __attribute((requires_capability(l))) +#define disable_thread_safety_analysis __attribute((no_thread_safety_analysis)) + +#else + +typedef int lock_cap_t; + +#define guarded_by(l) +#define acquire_cap(l) +#define release_cap(l) +#define assert_cap(l) +#define requires_cap(l) +#define disable_thread_safety_analysis + +#endif + +#endif /* UTIL_MACROS_H */ diff --git a/src/vrend_blitter.c b/src/vrend_blitter.c index 3469632..df8d930 100644 --- a/src/vrend_blitter.c +++ b/src/vrend_blitter.c @@ -699,7 +699,7 @@ static void vrend_set_vertex_param(GLuint prog_id) } /* implement blitting using OpenGL. */ -void vrend_renderer_blit_gl(MAYBE_UNUSED struct vrend_context *ctx, +void vrend_renderer_blit_gl(ASSERTED struct vrend_context *ctx, struct vrend_resource *src_res, struct vrend_resource *dst_res, GLenum blit_views[2], diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 477e2e4..915f148 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -1028,7 +1028,7 @@ static void __report_core_warn(const char *fname, struct vrend_context *ctx, #define GLES_WARN_TIMESTAMP 16 #define GLES_WARN_IMPLICIT_MSAA_SURFACE 17 -MAYBE_UNUSED +ASSERTED static const char *vrend_gles_warn_strings[] = { [GLES_WARN_NONE] = "None", [GLES_WARN_STIPPLE] = "Stipple", @@ -1049,17 +1049,17 @@ static const char *vrend_gles_warn_strings[] = { [GLES_WARN_IMPLICIT_MSAA_SURFACE] = "Implicit MSAA Surface", }; -static void __report_gles_warn(MAYBE_UNUSED const char *fname, - MAYBE_UNUSED struct vrend_context *ctx, - MAYBE_UNUSED enum virgl_ctx_errors error) +static void __report_gles_warn(ASSERTED const char *fname, + ASSERTED struct vrend_context *ctx, + ASSERTED enum virgl_ctx_errors error) { VREND_DEBUG(dbg_gles, ctx, "%s: GLES violation - %s\n", fname, vrend_gles_warn_strings[error]); } #define report_gles_warn(ctx, error) __report_gles_warn(__func__, ctx, error) -static void __report_gles_missing_func(MAYBE_UNUSED const char *fname, - MAYBE_UNUSED struct vrend_context *ctx, - MAYBE_UNUSED const char *missf) +static void __report_gles_missing_func(ASSERTED const char *fname, + ASSERTED struct vrend_context *ctx, + ASSERTED const char *missf) { VREND_DEBUG(dbg_gles, ctx, "%s: GLES function %s is missing\n", fname, missf); } @@ -1324,7 +1324,7 @@ static void vrend_stencil_test_enable(struct vrend_sub_context *sub_ctx, bool st } } -MAYBE_UNUSED +ASSERTED static void dump_stream_out(struct pipe_stream_output_info *so) { unsigned i; @@ -1372,7 +1372,7 @@ static char *get_skip_str(int *skip_val) return start_skip; } -static void set_stream_out_varyings(MAYBE_UNUSED struct vrend_sub_context *sub_ctx, +static void set_stream_out_varyings(ASSERTED struct vrend_sub_context *sub_ctx, int prog_id, struct vrend_shader_info *sinfo) { @@ -2394,9 +2394,9 @@ static void vrend_framebuffer_texture_2d(struct vrend_resource *res, } static -void debug_texture(MAYBE_UNUSED const char *f, const struct vrend_resource *gt) +void debug_texture(ASSERTED const char *f, const struct vrend_resource *gt) { - MAYBE_UNUSED const struct pipe_resource *pr = >->base; + ASSERTED const struct pipe_resource *pr = >->base; #define PRINT_TARGET(X) case X: vrend_printf( #X); break VREND_DEBUG_EXT(dbg_tex, NULL, vrend_printf("%s: ", f); @@ -9282,7 +9282,7 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx, intermediate_copy = (struct vrend_resource *)CALLOC_STRUCT(vrend_texture); vrend_renderer_resource_copy_args(&args, intermediate_copy); /* this is PIPE_MASK_ZS and bgra fixup is not needed */ - MAYBE_UNUSED int r = vrend_resource_alloc_texture(intermediate_copy, args.format, NULL); + ASSERTED int r = vrend_resource_alloc_texture(intermediate_copy, args.format, NULL); assert(!r); glGenFramebuffers(1, &intermediate_fbo); @@ -10155,7 +10155,7 @@ static int vrender_get_glsl_version(void) { int major_local = 0, minor_local = 0; const GLubyte *version_str; - MAYBE_UNUSED int c; + ASSERTED int c; version_str = glGetString(GL_SHADING_LANGUAGE_VERSION); if (vrend_state.use_gles) { diff --git a/src/vrend_shader.c b/src/vrend_shader.c index c9c0228..fd00fb8 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -7109,7 +7109,7 @@ static bool allocate_strbuffers(struct vrend_glsl_strbufs* glsl_strbufs) return true; } -static void set_strbuffers(MAYBE_UNUSED const struct vrend_context *rctx, const struct vrend_glsl_strbufs* glsl_strbufs, +static void set_strbuffers(ASSERTED const struct vrend_context *rctx, const struct vrend_glsl_strbufs* glsl_strbufs, struct vrend_strarray *shader) { strarray_addstrbuf(shader, &glsl_strbufs->glsl_ver_ext); @@ -7117,7 +7117,7 @@ static void set_strbuffers(MAYBE_UNUSED const struct vrend_context *rctx, const strarray_addstrbuf(shader, &glsl_strbufs->glsl_main); } -static bool vrend_patch_vertex_shader_interpolants(MAYBE_UNUSED const struct vrend_context *rctx, +static bool vrend_patch_vertex_shader_interpolants(ASSERTED const struct vrend_context *rctx, const struct vrend_shader_cfg *cfg, struct vrend_strarray *prog_strings, const struct vrend_shader_info *vs_info, @@ -7303,7 +7303,7 @@ static void require_gpu_shader5_and_msinterp(struct vrend_strarray *program) strbuf_append(&program->strings[SHADER_STRING_VER_EXT], gpu_shader5_and_msinterp_string); } -static bool vrend_patch_vertex_shader_interpolants(MAYBE_UNUSED const struct vrend_context *rctx, +static bool vrend_patch_vertex_shader_interpolants(ASSERTED const struct vrend_context *rctx, const struct vrend_shader_cfg *cfg, struct vrend_strarray *prog_strings, const struct vrend_shader_info *vs_info,