--- cvsroot/libecb/ecb.pod 2011/05/26 23:55:58 1.17 +++ cvsroot/libecb/ecb.pod 2011/06/17 18:46:19 1.33 @@ -17,8 +17,9 @@ it provides a number of other lowlevel C utilities, such as endianness detection, byte swapping or bit rotations. -Or in other words, things that should be built-in into any standard C -system, but isn't. +Or in other words, things that should be built into any standard C system, +but aren't, implemented as efficient as possible with GCC, and still +correct with other compilers. More might come. @@ -57,7 +58,21 @@ =head2 GCC ATTRIBUTES -blabla where to put, what others +A major part of libecb deals with GCC attributes. These are additional +attributes that you can 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 expected places, the safest way is to put attribute +declarations before the whole declaration: + + ecb_const int mysqrt (int a); + ecb_unused int i; + +For variables, it is often nicer to put the attribute after the name, and +avoid multiple declarations using commas: + + int i ecb_unused; =over 4 @@ -88,6 +103,21 @@ #endif } +=item ecb_inline + +This is not actually an attribute, but you use it like one. It 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 @@ -107,12 +137,12 @@ abort (); } -In this case, the compiler would probbaly be smart enough to decude it on -it's own, so this is mainly useful for declarations. +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_const -Declares that the function only depends on the values of it's arguments, +Declares that the function only depends on the values of its arguments, much like a mathematical function. It specifically does not read or write any memory any arguments might point to, global variables, or call any non-const functions. It also must not have any side effects. @@ -123,7 +153,7 @@ expect any side effects. It is best suited for functions in the sense of mathematical functions, -such as a function return the square root of its input argument. +such as a function returning the square root of its input argument. Not suited would be a function that calculates the hash of some memory area you pass in, prints some messages or looks at a global variable to @@ -156,7 +186,7 @@ The compiler reacts by trying to place hot functions near to each other in memory. -Whether a function is hot or not often depend son the whole program, +Whether a function is hot or not often depends on the whole program, and less on the function itself. C is likely more useful in practise. @@ -171,7 +201,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. @@ -243,12 +273,12 @@ 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 @@ -256,18 +286,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; } @@ -275,6 +305,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 @@ -284,7 +320,7 @@ 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 */ } @@ -297,13 +333,13 @@ 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); @@ -374,13 +410,13 @@ (most-significant byte first) or little endian (least-significant byte first) respectively. +On systems that are neither, their return values are unspecified. + =item int ecb_ctz32 (uint32_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., -floor(log2(n)). For example: +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. For example: ecb_ctz32 (3) = 0 ecb_ctz32 (6) = 1 @@ -396,16 +432,23 @@ =item uint32_t ecb_bswap32 (uint32_t x) -These two functions return the value of the 16-bit (32-bit) variable -C after reversing the order of bytes. +These two functions return the value of the 16-bit (32-bit) value C +after reversing the order of bytes (0x11223344 becomes 0x44332211). =item uint32_t ecb_rotr32 (uint32_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 shifting all the bits +=item uint64_t ecb_rotr64 (uint64_t x, unsigned int count) + +=item uint64_t ecb_rotl64 (uint64_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. +Current GCC versions understand these functions and usually compile them +to "optimal" code (e.g. a single C on x86). + =back =head2 ARITHMETIC @@ -414,13 +457,29 @@ =item x = ecb_mod (m, n) -Returns the positive remainder of the modulo operation between C and -C. Unlike the C modulo operator C<%>, this function ensures that the -return value is always positive). +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 +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 +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 +C, as the C<%> operator might give either negative results, or +change direction for negative values: + + for (m = -100; m <= 100; ++m) + int elem = myarray [ecb_mod (m, ecb_array_length (myarray))]; =back @@ -428,7 +487,7 @@ =over 4 -=item element_count = ecb_array_length (name) [MACRO] +=item element_count = ecb_array_length (name) Returns the number of elements in the array C. For example: