-
Notifications
You must be signed in to change notification settings - Fork 200
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compiler: header for compiler-specific wrappers.
Currently they sit in each module.
- Loading branch information
1 parent
a8e0cfb
commit 89f1301
Showing
5 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../licences/LGPL-3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#include <string.h> | ||
#include <stdio.h> | ||
#include "config.h" | ||
|
||
/** | ||
* compiler - macros for common compiler extensions | ||
* | ||
* Abstracts away some compiler hints. Currently these include: | ||
* - UNLIKELY_FUNCTION_ATTRIBUTE | ||
* For functions not called in fast paths (aka. cold functions) | ||
* - PRINTF_ATTRIBUTE | ||
* For functions which take printf-style parameters. | ||
* - IDEMPOTENT_ATTRIBUTE | ||
* For functions which return the same value for same parameters. | ||
* - NEEDED_ATTRIBUTE | ||
* For functions and variables which must be emitted even if unused. | ||
* - UNNEEDED_ATTRIBUTE | ||
* For functions and variables which need not be emitted if unused. | ||
* - IS_COMPILE_CONSTANT | ||
* For using different tradeoffs for compiletime vs runtime evaluation. | ||
* | ||
* Licence: LGPL (3 or any later version) | ||
* Author: Rusty Russell <rusty@rustcorp.com.au> | ||
* | ||
* Example: | ||
* #include <ccan/compiler/attributs.h> | ||
* #include <stdio.h> | ||
* #include <stdarg.h> | ||
* | ||
* // Example of a (slow-path) logging function. | ||
* static int log_threshold = 2; | ||
* static void UNLIKELY_FUNCTION_ATTRIBUTE PRINTF_ATTRIBUTE(2,3) | ||
* logger(int level, const char *fmt, ...) | ||
* { | ||
* va_list ap; | ||
* va_start(ap, fmt); | ||
* if (level >= log_threshold) | ||
* vfprintf(stderr, fmt, ap); | ||
* va_end(ap); | ||
* } | ||
* | ||
* int main(int argc, char *argv[]) | ||
* { | ||
* if (argc != 1) { | ||
* logger(3, "Don't want %i arguments!\n", argc-1); | ||
* return 1; | ||
* } | ||
* return 0; | ||
* } | ||
*/ | ||
int main(int argc, char *argv[]) | ||
{ | ||
/* Expect exactly one argument */ | ||
if (argc != 2) | ||
return 1; | ||
|
||
if (strcmp(argv[1], "depends") == 0) { | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
#ifndef CCAN_COMPILER_H | ||
#define CCAN_COMPILER_H | ||
#include "config.h" | ||
|
||
#if HAVE_ATTRIBUTE_COLD | ||
/** | ||
* UNLIKELY_FUNCTION_ATTRIBUTE - a function is unlikely to be called. | ||
* | ||
* Used to mark an unlikely code path and optimize appropriately. | ||
* It is usually used on logging or error routines. | ||
* | ||
* Example: | ||
* void UNLIKELY_FUNCTION_ATTRIBUTE moan(const char *reason) | ||
* { | ||
* fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno)); | ||
* } | ||
*/ | ||
#define UNLIKELY_FUNCTION_ATTRIBUTE __attribute__((cold)) | ||
#else | ||
#define UNLIKELY_FUNCTION_ATTRIBUTE | ||
#endif | ||
|
||
#if HAVE_ATTRIBUTE_PRINTF | ||
/** | ||
* PRINTF_ATTRIBUTE - a function takes printf-style arguments | ||
* nfmt: the 1-based number of the function's format argument. | ||
* narg: the 1-based number of the function's first variable argument. | ||
* | ||
* This allows the compiler to check your parameters as it does for printf(). | ||
* | ||
* Example: | ||
* void PRINTF_ATTRIBUTE(2,3) my_printf(char *prefix, char *format, ...); | ||
*/ | ||
#define PRINTF_ATTRIBUTE(nfmt, narg) \ | ||
__attribute__((format(__printf__, nfmt, narg))) | ||
#else | ||
#define PRINTF_ATTRIBUTE(nfmt, narg) | ||
#endif | ||
|
||
#if HAVE_ATTRIBUTE_CONST | ||
/** | ||
* IDEMPOTENT_ATTRIBUTE - a function's return depends only on its argument | ||
* | ||
* This allows the compiler to assume that the function will return the exact | ||
* same value for the exact same arguments. This implies that the function | ||
* must not use global variables, or dereference pointer arguments. | ||
*/ | ||
#define IDEMPOTENT_ATTRIBUTE __attribute__((const)) | ||
#else | ||
#define IDEMPOTENT_ATTRIBUTE | ||
#endif | ||
|
||
#if HAVE_ATTRIBUTE_UNUSED | ||
/** | ||
* UNNEEDED_ATTRIBUTE - a parameter/variable/function may not be needed | ||
* | ||
* This suppresses warnings about unused variables or parameters, but tells | ||
* the compiler that if it is unused it need not emit it into the source code. | ||
* | ||
* Example: | ||
* // With some config options, this is unnecessary. | ||
* static UNNEEDED_ATTRIBUTE int counter; | ||
* ... | ||
* #ifdef DEBUG | ||
* counter++; | ||
* #endif | ||
* ... | ||
* // With some config options, this is unnecessary. | ||
* static UNNEEDED_ATTRIBUTE int add_to_counter(int add) | ||
* { | ||
* counter += add; | ||
* } | ||
*/ | ||
#define UNNEEDED_ATTRIBUTE __attribute__((unused)) | ||
|
||
#if HAVE_ATTRIBUTE_USED | ||
/** | ||
* NEEDED_ATTRIBUTE - a parameter/variable/function is needed | ||
* | ||
* This suppresses warnings about unused variables or parameters, but tells | ||
* the compiler that it must exist even if it (seems) unused. | ||
* | ||
* Example: | ||
* // Even if this is unused, these are vital for debugging. | ||
* static UNNEEDED_ATTRIBUTE int counter; | ||
* static UNNEEDED_ATTRIBUTE void dump_counter(void) | ||
* { | ||
* printf("Counter is %i\n", counter); | ||
* } | ||
*/ | ||
#define NEEDED_ATTRIBUTE __attribute__((used)) | ||
#else | ||
/* Before used, unused functions and vars were always emitted. */ | ||
#define NEEDED_ATTRIBUTE __attribute__((unused)) | ||
#endif | ||
#else | ||
#define UNNEEDED_ATTRIBUTE | ||
#define NEEDED_ATTRIBUTE | ||
#endif | ||
|
||
#if HAVE_BUILTIN_CONSTANT_P | ||
/** | ||
* IS_COMPILE_CONSTANT - does the compiler know the value of this expression? | ||
* @expr: the expression to evaluate | ||
* | ||
* When an expression manipulation is complicated, it is usually better to | ||
* implement it in a function. However, if the expression being manipulated is | ||
* known at compile time, it is better to have the compiler see the entire | ||
* expression so it can simply substitute the result. | ||
* | ||
* This can be done using the IS_COMPILE_CONSTANT() macro. | ||
* | ||
* Example: | ||
* enum greek { ALPHA, BETA, GAMMA, DELTA, EPSILON }; | ||
* | ||
* // Out-of-line version. | ||
* const char *greek_name(enum greek greek); | ||
* | ||
* // Inline version. | ||
* static inline _greek_name(enum greek greek) | ||
* { | ||
* switch (greek) { | ||
* case ALPHA: return "alpha"; | ||
* case BETA: return "beta"; | ||
* case GAMMA: return "gamma"; | ||
* case DELTA: return "delta"; | ||
* case EPSILON: return "epsilon"; | ||
* default: return "**INVALID**"; | ||
* } | ||
* } | ||
* | ||
* // Use inline if compiler knows answer. Otherwise call function | ||
* // to avoid copies of the same code everywhere. | ||
* #define greek_name(g) \ | ||
* (IS_COMPILE_CONSTANT(greek) ? _greek_name(g) : greek_name(g)) | ||
*/ | ||
#define IS_COMPILE_CONSTANT(expr) __builtin_constant_p(expr) | ||
#else | ||
/* If we don't know, assume it's not. */ | ||
#define IS_COMPILE_CONSTANT(expr) 0 | ||
#endif | ||
#endif /* CCAN_COMPILER_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include <ccan/compiler/compiler.h> | ||
|
||
static void PRINTF_ATTRIBUTE(2,3) my_printf(int x, const char *fmt, ...) | ||
{ | ||
} | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
unsigned int i = 0; | ||
|
||
my_printf(1, "Not a pointer " | ||
#ifdef FAIL | ||
"%p", | ||
#if !HAVE_ATTRIBUTE_PRINTF | ||
#error "Unfortunately we don't fail if !HAVE_ATTRIBUTE_PRINTF." | ||
#endif | ||
#else | ||
"%i", | ||
#endif | ||
i); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include <ccan/compiler/compiler.h> | ||
#include <ccan/tap/tap.h> | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
plan_tests(2); | ||
|
||
ok1(!IS_COMPILE_CONSTANT(argc)); | ||
#ifdef HAVE_BUILTIN_CONSTANT_P | ||
ok1(IS_COMPILE_CONSTANT(7)); | ||
#else | ||
pass("If !HAVE_BUILTIN_CONSTANT_P, IS_COMPILE_CONSTANT always false"); | ||
#endif | ||
return exit_status(); | ||
} |