--- libecb/ecb.pod 2011/05/31 21:10:37 1.24 +++ libecb/ecb.pod 2015/09/01 16:14:42 1.70 @@ -56,35 +56,169 @@ is usually implemented as a macro. Specifically, a "bool" in this manual refers to any kind of boolean value, not a specific type. -=head2 GCC ATTRIBUTES +=head2 TYPES / TYPE SUPPORT -A major part of libecb deals with GCC attributes. These are additional -attributes that you cna assign to functions, variables and sometimes even -types - much like C or C in C. - -While GCC allows declarations to show up in many surprising places, -but not in many expeted places, the safest way is to put attribute -declarations before the whole declaration: +ecb.h makes sure that the following types are defined (in the expected way): - ecb_const int mysqrt (int a); - ecb_unused int i; + int8_t uint8_t int16_t uint16_t + int32_t uint32_t int64_t uint64_t + intptr_t uintptr_t + +The macro C is defined to the size of a pointer on this +platform (currently C<4> or C<8>) and can be used in preprocessor +expressions. + +For C and C use C. + +=head2 LANGUAGE/ENVIRONMENT/COMPILER VERSIONS + +All the following symbols expand to an expression that can be tested in +preprocessor instructions as well as treated as a boolean (use C to +ensure it's either C<0> or C<1> if you need that). + +=over 4 + +=item ECB_C + +True if the implementation defines the C<__STDC__> macro to a true value, +while not claiming to be C++. + +=item ECB_C99 + +True if the implementation claims to be compliant to C99 (ISO/IEC +9899:1999) or any later version, while not claiming to be C++. + +Note that later versions (ECB_C11) remove core features again (for +example, variable length arrays). + +=item ECB_C11 + +True if the implementation claims to be compliant to C11 (ISO/IEC +9899:2011) or any later version, while not claiming to be C++. + +=item ECB_CPP + +True if the implementation defines the C<__cplusplus__> macro to a true +value, which is typically true for C++ compilers. + +=item ECB_CPP11 + +True if the implementation claims to be compliant to ISO/IEC 14882:2011 +(C++11) or any later version. + +=item ECB_GCC_VERSION (major, minor) + +Expands to a true value (suitable for testing in by the preprocessor) +if the compiler used is GNU C and the version is the given version, or +higher. + +This macro tries to return false on compilers that claim to be GCC +compatible but aren't. + +=item ECB_EXTERN_C + +Expands to C in C++, and a simple C in C. + +This can be used to declare a single external C function: + + ECB_EXTERN_C int printf (const char *format, ...); + +=item ECB_EXTERN_C_BEG / ECB_EXTERN_C_END + +These two macros can be used to wrap multiple C definitions - +they expand to nothing in C. + +They are most useful in header files: + + ECB_EXTERN_C_BEG + + int mycfun1 (int x); + int mycfun2 (int x); + + ECB_EXTERN_C_END + +=item ECB_STDFP + +If this evaluates to a true value (suitable for testing in by the +preprocessor), then C and C use IEEE 754 single/binary32 +and double/binary64 representations internally I the endianness of +both types match the endianness of C and C. + +This means you can just copy the bits of a C (or C) to an +C (or C) and get the raw IEEE 754 bit representation +without having to think about format or endianness. + +This is true for basically all modern platforms, although F might +not be able to deduce this correctly everywhere and might err on the safe +side. + +=item ECB_AMD64, ECB_AMD64_X32 + +These two macros are defined to C<1> on the x86_64/amd64 ABI and the X32 +ABI, respectively, and undefined elsewhere. + +The designers of the new X32 ABI for some inexplicable reason decided to +make it look exactly like amd64, even though it's completely incompatible +to that ABI, breaking about every piece of software that assumed that +C<__x86_64> stands for, well, the x86-64 ABI, making these macros +necessary. -For variables, it is often nicer to put the attribute after the name, and -avoid multiple declarations using commas: +=back - int i ecb_unused; +=head2 MACRO TRICKERY =over 4 -=item ecb_attribute ((attrs...)) +=item ECB_CONCAT (a, b) + +Expands any macros in C and C, then concatenates the result to form +a single token. This is mainly useful to form identifiers from components, +e.g.: + + #define S1 str + #define S2 cpy + + ECB_CONCAT (S1, S2)(dst, src); // == strcpy (dst, src); + +=item ECB_STRINGIFY (arg) + +Expands any macros in C and returns the stringified version of +it. This is mainly useful to get the contents of a macro in string form, +e.g.: + + #define SQL_LIMIT 100 + sql_exec ("select * from table limit " ECB_STRINGIFY (SQL_LIMIT)); + +=item ECB_STRINGIFY_EXPR (expr) + +Like C, but additionally evaluates C to make sure it +is a valid expression. This is useful to catch typos or cases where the +macro isn't available: + + #include -A simple wrapper that expands to C<__attribute__((attrs))> on GCC, and to -nothing on other compilers, so the effect is that only GCC sees these. + ECB_STRINGIFY (EDOM); // "33" (on my system at least) + ECB_STRINGIFY_EXPR (EDOM); // "33" -Example: use the C attribute on a function. + // now imagine we had a typo: - ecb_attribute((__deprecated__)) void - do_not_use_me_anymore (void); + ECB_STRINGIFY (EDAM); // "EDAM" + ECB_STRINGIFY_EXPR (EDAM); // error: EDAM undefined + +=back + +=head2 ATTRIBUTES + +A major part of libecb deals with additional attributes that can be +assigned to functions, variables and sometimes even types - much like +C or C in C. They are implemented using either GCC +attributes or other compiler/language specific features. Attributes +declarations must be put before the whole declaration: + + ecb_const int mysqrt (int a); + ecb_unused int i; + +=over 4 =item ecb_unused @@ -93,7 +227,7 @@ declare a variable but do not always use it: { - int var ecb_unused; + ecb_unused int var; #ifdef SOMECONDITION var = ...; @@ -103,9 +237,34 @@ #endif } +=item ecb_deprecated + +Similar to C, but marks a function, variable or type as +deprecated. This makes some compilers warn when the type is used. + +=item ecb_deprecated_message (message) + +Same as C, but if possible, the specified diagnostic is +used instead of a generic depreciation message when the object is being +used. + +=item ecb_inline + +Expands either to C or to just C, if inline +isn't supported. It should be used to declare functions that should be +inlined, for code size or speed reasons. + +Example: inline this function, it surely will reduce codesize. + + ecb_inline int + negmul (int a, int b) + { + return - (a * b); + } + =item ecb_noinline -Prevent a function from being inlined - it might be optimised away, but +Prevents a function from being inlined - it might be optimised away, but not inlined into other functions. This is useful if you know your function is rarely called and large enough for inlining not to be helpful. @@ -125,6 +284,27 @@ In this case, the compiler would probably be smart enough to deduce it on its own, so this is mainly useful for declarations. +=item ecb_restrict + +Expands to the C keyword or equivalent on compilers that support +them, and to nothing on others. Must be specified on a pointer type or +an array index to indicate that the memory doesn't alias with any other +restricted pointer in the same scope. + +Example: multiply a vector, and allow the compiler to parallelise the +loop, because it knows it doesn't overwrite input values. + + void + multiply (ecb_restrict float *src, + ecb_restrict float *dst, + int len, float factor) + { + int i; + + for (i = 0; i < len; ++i) + dst [i] = src [i] * factor; + } + =item ecb_const Declares that the function only depends on the values of its arguments, @@ -186,7 +366,7 @@ functions), this knowledge can be used in other ways, for example, the function will be optimised for size, as opposed to speed, and codepaths leading to calls to those functions can automatically be marked as if -C had been used to reach them. +C had been used to reach them. Good examples for such functions would be error reporting functions, or functions only called in exceptional or rare cases. @@ -194,7 +374,7 @@ =item ecb_artificial Declares the function as "artificial", in this case meaning that this -function is not really mean to be a function, but more like an accessor +function is not really meant to be a function, but more like an accessor - many methods in C++ classes are mere accessor functions, and having a crash reported in such a method, or single-stepping through them, is not usually so helpful, especially when it's inlined to just a few instructions. @@ -224,7 +404,7 @@ =over 4 -=item bool ecb_is_constant(expr) +=item bool ecb_is_constant (expr) Returns true iff the expression can be deduced to be a compile-time constant, and false otherwise. @@ -252,18 +432,18 @@ : (n * (uint32_t)rndm16 ()) >> 16; } -=item bool ecb_expect (expr, value) +=item ecb_expect (expr, value) Evaluates C and returns it. In addition, it tells the compiler that the C evaluates to C a lot, which can be used for static branch optimisations. -Usually, you want to use the more intuitive C and -C functions instead. +Usually, you want to use the more intuitive C and +C functions instead. -=item bool ecb_likely (cond) +=item bool ecb_expect_true (cond) -=item bool ecb_unlikely (cond) +=item bool ecb_expect_false (cond) These two functions expect a expression that is true or false and return C<1> or C<0>, respectively, so when used in the condition of an C or @@ -271,18 +451,18 @@ /* these two do the same thing */ if (some_condition) ...; - if (ecb_likely (some_condition)) ...; + if (ecb_expect_true (some_condition)) ...; -However, by using C, you tell the compiler that the condition -is likely to be true (and for C, that it is unlikely to be -true). +However, by using C, you tell the compiler that the +condition is likely to be true (and for C, that it is +unlikely to be true). For example, when you check for a null pointer and expect this to be a -rare, exceptional, case, then use C: +rare, exceptional, case, then use C: void my_free (void *ptr) { - if (ecb_unlikely (ptr == 0)) + if (ecb_expect_false (ptr == 0)) return; } @@ -290,6 +470,12 @@ tell the compiler what the hot path through a function is can increase performance considerably. +You might know these functions under the name C and C +- while these are common aliases, we find that the expect name is easier +to understand when quickly skimming code. If you wish, you can use +C instead of C and C instead of +C - these are simply aliases. + A very good example is in a function that reserves more space for some memory block (for example, inside an implementation of a string stream) - each time something is added, you have to check for a buffer overrun, but @@ -299,26 +485,27 @@ ecb_inline void reserve (int size) { - if (ecb_unlikely (current + size > end)) + if (ecb_expect_false (current + size > end)) real_reserve_method (size); /* presumably noinline */ } -=item bool ecb_assume (cond) +=item ecb_assume (cond) -Try to tell the compiler that some condition is true, even if it's not -obvious. +Tries to tell the compiler that some condition is true, even if it's not +obvious. This is not a function, but a statement: it cannot be used in +another expression. This can be used to teach the compiler about invariants or other conditions that might improve code generation, but which are impossible to deduce form the code itself. -For example, the example reservation function from the C +For example, the example reservation function from the C description could be written thus (only C was added): ecb_inline void reserve (int size) { - if (ecb_unlikely (current + size > end)) + if (ecb_expect_false (current + size > end)) real_reserve_method (size); /* presumably noinline */ ecb_assume (current + size <= end); @@ -333,13 +520,13 @@ completely, as it knows that C<< current + 1 > end >> is false and the call will never be executed. -=item bool ecb_unreachable () +=item ecb_unreachable () This function does nothing itself, except tell the compiler that it will never be executed. Apart from suppressing a warning in some cases, this -function can be used to implement C or similar functions. +function can be used to implement C or similar functionality. -=item bool ecb_prefetch (addr, rw, locality) +=item ecb_prefetch (addr, rw, locality) Tells the compiler to try to prefetch memory at the given Cess for either reading (C = 0) or writing (C = 1). A C of @@ -349,6 +536,9 @@ need to be accessible (it could be a null pointer for example), but C and C must be compile-time constants. +This is a statement, not a function: you cannot use it as part of an +expression. + An obvious way to use this is to prefetch some data far away, in a big array you loop over. This prefetches memory some 128 array elements later, in the hope that it will be ready when the CPU arrives at that location. @@ -377,7 +567,7 @@ =back -=head2 BIT FIDDLING / BITSTUFFS +=head2 BIT FIDDLING / BIT WIZARDRY =over 4 @@ -393,38 +583,175 @@ =item int ecb_ctz32 (uint32_t x) +=item int ecb_ctz64 (uint64_t x) + Returns the index of the least significant bit set in C (or equivalently the number of bits set to 0 before the least significant bit -set), starting from 0. If C is 0 the result is undefined. A common use -case is to compute the integer binary logarithm, i.e., C. For example: +set), starting from 0. If C is 0 the result is undefined. + +For smaller types than C you can safely use C. + +For example: ecb_ctz32 (3) = 0 ecb_ctz32 (6) = 1 +=item bool ecb_is_pot32 (uint32_t x) + +=item bool ecb_is_pot64 (uint32_t x) + +Returns true iff C is a power of two or C. + +For smaller types than C you can safely use C. + +=item int ecb_ld32 (uint32_t x) + +=item int ecb_ld64 (uint64_t x) + +Returns the index of the most significant bit set in C, or the number +of digits the number requires in binary (so that C<< 2**ld <= x < +2**(ld+1) >>). If C is 0 the result is undefined. A common use case is +to compute the integer binary logarithm, i.e. C, for +example to see how many bits a certain number requires to be encoded. + +This function is similar to the "count leading zero bits" function, except +that that one returns how many zero bits are "in front" of the number (in +the given data type), while C returns how many bits the number +itself requires. + +For smaller types than C you can safely use C. + =item int ecb_popcount32 (uint32_t x) -Returns the number of bits set to 1 in C. For example: +=item int ecb_popcount64 (uint64_t x) + +Returns the number of bits set to 1 in C. + +For smaller types than C you can safely use C. + +For example: ecb_popcount32 (7) = 3 ecb_popcount32 (255) = 8 +=item uint8_t ecb_bitrev8 (uint8_t x) + +=item uint16_t ecb_bitrev16 (uint16_t x) + +=item uint32_t ecb_bitrev32 (uint32_t x) + +Reverses the bits in x, i.e. the MSB becomes the LSB, MSB-1 becomes LSB+1 +and so on. + +Example: + + ecb_bitrev8 (0xa7) = 0xea + ecb_bitrev32 (0xffcc4411) = 0x882233ff + =item uint32_t ecb_bswap16 (uint32_t x) =item uint32_t ecb_bswap32 (uint32_t x) -These two functions return the value of the 16-bit (32-bit) value C -after reversing the order of bytes (0x11223344 becomes 0x44332211). +=item uint64_t ecb_bswap64 (uint64_t x) -=item uint32_t ecb_rotr32 (uint32_t x, unsigned int count) +These functions return the value of the 16-bit (32-bit, 64-bit) value +C after reversing the order of bytes (0x11223344 becomes 0x44332211 in +C). + +=item uint8_t ecb_rotl8 (uint8_t x, unsigned int count) + +=item uint16_t ecb_rotl16 (uint16_t x, unsigned int count) =item uint32_t ecb_rotl32 (uint32_t x, unsigned int count) -These two functions return the value of C after rotating all the bits -by C positions to the right or left respectively. +=item uint64_t ecb_rotl64 (uint64_t x, unsigned int count) + +=item uint8_t ecb_rotr8 (uint8_t x, unsigned int count) + +=item uint16_t ecb_rotr16 (uint16_t x, unsigned int count) + +=item uint32_t ecb_rotr32 (uint32_t x, unsigned int count) + +=item uint64_t ecb_rotr64 (uint64_t x, unsigned int count) + +These two families of functions return the value of C after rotating +all the bits by C positions to the right (C) or left +(C). Current GCC versions understand these functions and usually compile them -to "optimal" code (e.g. a single C on x86). +to "optimal" code (e.g. a single C or a combination of C on +x86). + +=back + +=head2 FLOATING POINT FIDDLING + +=over 4 + +=item ECB_INFINITY + +Evaluates to positive infinity if supported by the platform, otherwise to +a truly huge number. + +=item ECB_NAN + +Evaluates to a quiet NAN if supported by the platform, otherwise to +C. + +=item float ecb_ldexpf (float x, int exp) + +Same as C, but always available. + +=item uint32_t ecb_float_to_binary32 (float x) [-UECB_NO_LIBM] + +=item uint64_t ecb_double_to_binary64 (double x) [-UECB_NO_LIBM] + +These functions each take an argument in the native C or C +type and return the IEEE 754 bit representation of it. + +The bit representation is just as IEEE 754 defines it, i.e. the sign bit +will be the most significant bit, followed by exponent and mantissa. + +This function should work even when the native floating point format isn't +IEEE compliant, of course at a speed and code size penalty, and of course +also within reasonable limits (it tries to convert NaNs, infinities and +denormals, but will likely convert negative zero to positive zero). + +On all modern platforms (where C is true), the compiler should +be able to optimise away this function completely. + +These functions can be helpful when serialising floats to the network - you +can serialise the return value like a normal uint32_t/uint64_t. + +Another use for these functions is to manipulate floating point values +directly. + +Silly example: toggle the sign bit of a float. + + /* On gcc-4.7 on amd64, */ + /* this results in a single add instruction to toggle the bit, and 4 extra */ + /* instructions to move the float value to an integer register and back. */ + + x = ecb_binary32_to_float (ecb_float_to_binary32 (x) ^ 0x80000000U) + +=item float ecb_binary16_to_float (uint16_t x) [-UECB_NO_LIBM] + +=item float ecb_binary32_to_float (uint32_t x) [-UECB_NO_LIBM] + +=item double ecb_binary64_to_double (uint64_t x) [-UECB_NO_LIBM] + +The reverse operation of the previous function - takes the bit +representation of an IEEE binary16, binary32 or binary64 number and +converts it to the native C or C format. + +This function should work even when the native floating point format isn't +IEEE compliant, of course at a speed and code size penalty, and of course +also within reasonable limits (it tries to convert normals and denormals, +and might be lucky for infinities, and with extraordinary luck, also for +negative zero). + +On all modern platforms (where C is true), the compiler should +be able to optimise away this function completely. =back @@ -434,18 +761,21 @@ =item x = ecb_mod (m, n) -Returns the positive remainder of the modulo operation between C and -C, using floored division. Unlike the C modulo operator C<%>, this -function ensures that the return value is always positive and that the two -numbers I and I result in the same value modulo I - -the C<%> operator usually has a behaviour change at C. +Returns C modulo C, which is the same as the positive remainder +of the division operation between C and C, using floored +division. Unlike the C remainder operator C<%>, this function ensures that +the return value is always positive and that the two numbers I and +I result in the same value modulo I - in other words, +C implements the mathematical modulo operation, which is missing +in the language. C must be strictly positive (i.e. C<< >= 1 >>), while C must be negatable, that is, both C and C<-m> must be representable in its -type. +type (this typically excludes the minimum signed integer value, the same +limitation as for C and C<%> in C). Current GCC versions compile this into an efficient branchless sequence on -many systems. +almost all CPUs. For example, when you want to rotate forward through the members of an array for increasing C (which might be negative), then you should use @@ -455,6 +785,15 @@ for (m = -100; m <= 100; ++m) int elem = myarray [ecb_mod (m, ecb_array_length (myarray))]; +=item x = ecb_div_rd (val, div) + +=item x = ecb_div_ru (val, div) + +Returns C divided by C
rounded down or up, respectively. +C and C
must have integer types and C
must be strictly +positive. Note that these functions are implemented with macros in C +and with function templates in C++. + =back =head2 UTILITY @@ -473,4 +812,53 @@ =back +=head2 SYMBOLS GOVERNING COMPILATION OF ECB.H ITSELF + +These symbols need to be defined before including F the first time. + +=over 4 + +=item ECB_NO_THREADS + +If F is never used from multiple threads, then this symbol can +be defined, in which case memory fences (and similar constructs) are +completely removed, leading to more efficient code and fewer dependencies. + +Setting this symbol to a true value implies C. + +=item ECB_NO_SMP + +The weaker version of C - if F is used from +multiple threads, but never concurrently (e.g. if the system the program +runs on has only a single CPU with a single core, no hyperthreading and so +on), then this symbol can be defined, leading to more efficient code and +fewer dependencies. + +=item ECB_NO_LIBM + +When defined to C<1>, do not export any functions that might introduce +dependencies on the math library (usually called F<-lm>) - these are +marked with [-UECB_NO_LIBM]. + +=back + +=head1 UNDOCUMENTED FUNCTIONALITY + +F is full of undocumented functionality as well, some of which is +intended to be internal-use only, some of which we forgot to document, and +some of which we hide because we are not sure we will keep the interface +stable. + +While you are welcome to rummage around and use whatever you find useful +(we can't stop you), keep in mind that we will change undocumented +functionality in incompatible ways without thinking twice, while we are +considerably more conservative with documented things. + +=head1 AUTHORS + +C is designed and maintained by: + + Emanuele Giaquinta + Marc Alexander Lehmann +