=head1 LIBECB - e-C-Builtins =head2 ABOUT LIBECB Libecb is currently a simple header file that doesn't require any configuration to use or include in your project. It's part of the e-suite of libraries, other members of which include libev and libeio. Its homepage can be found here: http://software.schmorp.de/pkg/libecb It mainly provides a number of wrappers around GCC built-ins, together with replacement functions for other compilers. In addition to this, 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 aren't. More might come. =head2 ABOUT THE HEADER At the moment, all you have to do is copy F somewhere where your compiler can find it and include it: #include The header should work fine for both C and C++ compilation, and gives you all of F in addition to the ECB symbols. There are currently no object files to link to - future versions might come with an (optional) object code library to link against, to reduce code size or gain access to additional features. It also currently includes everything from F. =head2 ABOUT THIS MANUAL / CONVENTIONS This manual mainly describes each (public) function available after including the F header. The header might define other symbols than these, but these are not part of the public API, and not supported in any way. When the manual mentions a "function" then this could be defined either as as inline function, a macro, or an external symbol. When functions use a concrete standard type, such as C or C, then the corresponding function works only with that type. If only a generic name is used (C, C, C and so on), then the corresponding function relies on C to implement the correct types, and 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 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_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 =item ecb_attribute ((attrs...)) 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. Example: use the C attribute on a function. ecb_attribute((__deprecated__)) void do_not_use_me_anymore (void); =item ecb_unused Marks a function or a variable as "unused", which simply suppresses a warning by GCC when it detects it as unused. This is useful when you e.g. declare a variable but do not always use it: { int var ecb_unused; #ifdef SOMECONDITION var = ...; return var; #else return 0; #endif } =item ecb_noinline Prevent 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. =item ecb_noreturn Marks a function as "not returning, ever". Some typical functions that don't return are C or C (which really works hard to not return), and now you can make your own: ecb_noreturn void my_abort (const char *errline) { puts (errline); abort (); } 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 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. Such a function can be optimised much more aggressively by the compiler - for example, multiple calls with the same arguments can be optimised into a single call, which wouldn't be possible if the compiler would have to expect any side effects. It is best suited for functions in the sense of mathematical functions, 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 decide on rounding. See C for a slightly less restrictive class of functions. =item ecb_pure Similar to C, declares a function that has no side effects. Unlike C, the function is allowed to examine global variables and any other memory areas (such as the ones passed to it via pointers). While these functions cannot be optimised as aggressively as C functions, they can still be optimised away in many occasions, and the compiler has more freedom in moving calls to them around. Typical examples for such functions would be C or C. A function that calculates the MD5 sum of some input and updates some MD5 state passed as argument would I be pure, however, as it would modify some memory area that is not the return value. =item ecb_hot This declares a function as "hot" with regards to the cache - the function is used so often, that it is very beneficial to keep it in the cache if possible. The compiler reacts by trying to place hot functions near to each other in memory. 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. =item ecb_cold The opposite of C - declares a function as "cold" with regards to the cache, or in other words, this function is not called often, or not at speed-critical times, and keeping it in the cache might be a waste of said cache. In addition to placing cold functions together (or at least away from hot 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. Good examples for such functions would be error reporting functions, or functions only called in exceptional or rare cases. =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 - 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. Marking them as artificial will instruct the debugger about just this, leading to happier debugging and thus happier lives. Example: in some kind of smart-pointer class, mark the pointer accessor as artificial, so that the whole class acts more like a pointer and less like some C++ abstraction monster. template struct my_smart_ptr { T *value; ecb_artificial operator T *() { return value; } }; =back =head2 OPTIMISATION HINTS =over 4 =item bool ecb_is_constant(expr) Returns true iff the expression can be deduced to be a compile-time constant, and false otherwise. For example, when you have a C function that returns a 16 bit random number, and you have a function that maps this to a range from 0..n-1, then you could use this inline function in a header file: ecb_inline uint32_t rndm (uint32_t n) { return (n * (uint32_t)rndm16 ()) >> 16; } However, for powers of two, you could use a normal mask, but that is only worth it if, at compile time, you can detect this case. This is the case when the passed number is a constant and also a power of two (C): ecb_inline uint32_t rndm (uint32_t n) { return is_constant (n) && !(n & (n - 1)) ? rndm16 () & (num - 1) : (n * (uint32_t)rndm16 ()) >> 16; } =item bool 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. =item bool ecb_likely (cond) =item bool ecb_unlikely (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 other conditional statement, it will not change the program: /* these two do the same thing */ if (some_condition) ...; if (ecb_likely (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). For example, when you check for a null pointer and expect this to be a rare, exceptional, case, then use C: void my_free (void *ptr) { if (ecb_unlikely (ptr == 0)) return; } Consequent use of these functions to mark away exceptional cases or to tell the compiler what the hot path through a function is can increase performance considerably. 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 you expect that most checks will turn out to be false: /* make sure we have "size" extra room in our buffer */ ecb_inline void reserve (int size) { if (ecb_unlikely (current + size > end)) real_reserve_method (size); /* presumably noinline */ } =item bool ecb_assume (cond) Try to tell the compiler that some condition is true, even if it's not obvious. 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 description could be written thus (only C was added): ecb_inline void reserve (int size) { if (ecb_unlikely (current + size > end)) real_reserve_method (size); /* presumably noinline */ ecb_assume (current + size <= end); } If you then call this function twice, like this: reserve (10); reserve (1); Then the compiler I be able to optimise out the second call completely, as it knows that C<< current + 1 > end >> is false and the call will never be executed. =item bool 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. =item bool 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 C<0> means that there will only be one access later, C<3> means that the data will likely be accessed very often, and values in between mean something... in between. The memory pointed to by the address does not need to be accessible (it could be a null pointer for example), but C and C must be compile-time constants. 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. int sum = 0; for (i = 0; i < N; ++i) { sum += arr [i] ecb_prefetch (arr + i + 128, 0, 0); } It's hard to predict how far to prefetch, and most CPUs that can prefetch are often good enough to predict this kind of behaviour themselves. It gets more interesting with linked lists, especially when you do some fair processing on each list element: for (node *n = start; n; n = n->next) { ecb_prefetch (n->next, 0, 0); ... do medium amount of work with *n } After processing the node, (part of) the next node might already be in cache. =back =head2 BIT FIDDLING / BITSTUFFS =over 4 =item bool ecb_big_endian () =item bool ecb_little_endian () These two functions return true if the byte order is big endian (most-significant byte first) or little endian (least-significant byte first) respectively. =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: ecb_ctz32 (3) = 0 ecb_ctz32 (6) = 1 =item int ecb_popcount32 (uint32_t x) Returns the number of bits set to 1 in C. For example: ecb_popcount32 (7) = 3 ecb_popcount32 (255) = 8 =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 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 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 =over 4 =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 - ISO C guarantees very little when negative numbers are used with C<%>. 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. =back =head2 UTILITY =over 4 =item element_count = ecb_array_length (name) [MACRO] Returns the number of elements in the array C. For example: int primes[] = { 2, 3, 5, 7, 11 }; int sum = 0; for (i = 0; i < ecb_array_length (primes); i++) sum += primes [i]; =back