X-Git-Url: https://ginac.de/CLN/cln.git//cln.git?a=blobdiff_plain;ds=sidebyside;f=include%2Fcln%2Fmodules.h;h=26fc291c01cf8e2c69be92ab81531d495e27b799;hb=a8369235e23acbacbad414dc1675be8c279e27a2;hp=913e4439ff58df098cc74e9b999ebb74009496e1;hpb=850abfde7f0d985ba01526c346bcd0d733562943;p=cln.git diff --git a/include/cln/modules.h b/include/cln/modules.h index 913e443..26fc291 100644 --- a/include/cln/modules.h +++ b/include/cln/modules.h @@ -7,7 +7,7 @@ // specified in C++. AIX 4 has a linker which apparently does order // the modules according to dependencies, so that low-level modules // will be initialized earlier than the high-level modules which depend -// on them. I have a patch for GNU ld that does the same thing. +// on them. I (Bruno) have a patch for GNU ld that does the same thing. // // But for now, I take a half-automatic approach to the correct module // ordering problem: PROVIDE/REQUIRE, as in Common Lisp. @@ -63,12 +63,12 @@ #define ASM_UNDERSCORE_PREFIX "" #endif // Globalize a label defined in the same translation unit. - // See macro ASM_GLOBALIZE_LABEL in the egcs sources. - #if defined(__i386__) || defined(__m68k__) || defined(__mips__) || defined(__mips64__) || defined(__alpha__) || defined(__rs6000__) + // See macro ASM_GLOBALIZE_LABEL in the gcc sources. + #if defined(__i386__) || defined(__m68k__) || defined(__mips__) || defined(__mips64__) || defined(__alpha__) || defined(__rs6000__) || defined(__x86_64__) || defined(__s390__) // Some m68k systems use "xdef" or "global" or ".global"... #define CL_GLOBALIZE_LABEL(label) __asm__("\t.globl " label); #endif - #if defined(__sparc__) || defined(__sparc64__) || defined(__arm__) + #if defined(__sparc__) || defined(__sparc64__) || defined(__arm__) || defined(__ia64__) // Some arm systems use "EXPORT" or ".globl"... #define CL_GLOBALIZE_LABEL(label) __asm__("\t.global " label); #endif @@ -95,9 +95,13 @@ #define CL_GLOBALIZE_CTORDTOR_LABEL(label) #endif // Output a label inside a function. - // See macro ASM_OUTPUT_LABEL in the egcs sources. + // See macro ASM_OUTPUT_LABEL in the gcc sources. #if defined(__hppa__) - #define CL_OUTPUT_LABEL(label) ASM_VOLATILE ("\n" label) + // Some hppa (Linux) systems want `label:', HPUX used to use just `label'. + // I tried to find out, but was unable to find the assembler on my HPUX-11 + // boxen so decided to potentially ditch the support (no joke). Please + // send an email if you can explain to me what's going on! (-rbk. 07/2001) + #define CL_OUTPUT_LABEL(label) ASM_VOLATILE ("\n" label ":") #else #define CL_OUTPUT_LABEL(label) ASM_VOLATILE ("\n" label ":") #endif @@ -113,7 +117,7 @@ // except that the latter inhibits inlining of the function containing it // in gcc-2.95. For new CPUs, look for "jump" and "indirect_jump" in gcc's // machine description. - #if defined(__i386__) + #if defined(__i386__) || defined(__x86_64__) #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %*%0" : : "rm" ((void*)(addr))) #endif #if defined(__m68k__) @@ -145,53 +149,97 @@ #if defined(__convex__) #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp (%0)" : : "r" ((void*)(addr))) #endif - #define CL_PROVIDE(module) \ - extern "C" void cl_module__##module##__firstglobalfun () {} \ - extern "C" void cl_module__##module##__ctorend (void); \ - extern "C" void cl_module__##module##__dtorend (void); \ - CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ - CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__dtorend) \ - CL_GLOBALIZE_CTORDTOR_LABEL( \ - ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun") \ - CL_GLOBALIZE_CTORDTOR_LABEL( \ - ASM_UNDERSCORE_PREFIX CL_GLOBAL_DESTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun") \ - static int cl_module__##module##__counter; \ - struct cl_module__##module##__controller { \ - inline cl_module__##module##__controller () \ - { if (cl_module__##module##__counter++) \ - { CL_JUMP_TO(cl_module__##module##__ctorend); } \ - } \ - inline ~cl_module__##module##__controller () \ - { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__dtorend"); } \ - }; \ - static cl_module__##module##__controller cl_module__##module##__ctordummy; - #define CL_PROVIDE_END(module) \ - struct cl_module__##module##__destroyer { \ - inline cl_module__##module##__destroyer () \ - { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__ctorend"); } \ - inline ~cl_module__##module##__destroyer () \ - { if (--cl_module__##module##__counter) \ - { CL_JUMP_TO(cl_module__##module##__dtorend); } \ - } \ - }; \ - static cl_module__##module##__destroyer cl_module__##module##__dtordummy; - #define CL_REQUIRE(module) \ - extern "C" void cl_module__##module##__ctor (void) \ - __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun"); \ - extern "C" void cl_module__##module##__dtor (void) \ - __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_DESTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun"); \ - struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ - inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ - { cl_module__##module##__ctor (); } \ - inline ~_CL_REQUIRE_CLASSNAME(module,__LINE__) () \ - { cl_module__##module##__dtor (); } \ - }; \ - static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ - _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); + #if defined(__ia64__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("br " #addr) + #endif + #if defined(__s390__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("br %0" : : "a" ((void*)(addr))) + #endif + #ifdef CL_GLOBAL_DESTRUCTOR_PREFIX + #define CL_PROVIDE(module) \ + extern "C" void cl_module__##module##__firstglobalfun () {} \ + extern "C" void cl_module__##module##__ctorend (void); \ + extern "C" void cl_module__##module##__dtorend (void); \ + CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ + CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__dtorend) \ + CL_GLOBALIZE_CTORDTOR_LABEL( \ + ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun") \ + CL_GLOBALIZE_CTORDTOR_LABEL( \ + ASM_UNDERSCORE_PREFIX CL_GLOBAL_DESTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun") \ + static int cl_module__##module##__counter; \ + struct cl_module__##module##__controller { \ + inline cl_module__##module##__controller () \ + { if (cl_module__##module##__counter++) \ + { CL_JUMP_TO(cl_module__##module##__ctorend); } \ + } \ + inline ~cl_module__##module##__controller () \ + { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__dtorend"); } \ + }; \ + static cl_module__##module##__controller cl_module__##module##__ctordummy; + #define CL_PROVIDE_END(module) \ + struct cl_module__##module##__destroyer { \ + inline cl_module__##module##__destroyer () \ + { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__ctorend"); } \ + inline ~cl_module__##module##__destroyer () \ + { if (--cl_module__##module##__counter) \ + { CL_JUMP_TO(cl_module__##module##__dtorend); } \ + } \ + }; \ + static cl_module__##module##__destroyer cl_module__##module##__dtordummy; + #define CL_REQUIRE(module) \ + extern "C" void cl_module__##module##__ctor (void) \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun"); \ + extern "C" void cl_module__##module##__dtor (void) \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_DESTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun"); \ + struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ + inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ + { cl_module__##module##__ctor (); } \ + inline ~_CL_REQUIRE_CLASSNAME(module,__LINE__) () \ + { cl_module__##module##__dtor (); } \ + }; \ + static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ + _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); + #else + // gcc-3.0 -fuse-cxa-atexit doesn't have a single per-module destructor + // function anymore. Instead, for each object's static constructor it + // executes, it pushes the corresponding object's destructor onto a list. + // Thus we need to hack the constructors only. + #define CL_PROVIDE(module) \ + extern "C" void cl_module__##module##__firstglobalfun () {} \ + extern "C" void cl_module__##module##__ctorend (void); \ + CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ + CL_GLOBALIZE_CTORDTOR_LABEL( \ + ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun") \ + static int cl_module__##module##__counter; \ + struct cl_module__##module##__controller { \ + inline cl_module__##module##__controller () \ + { if (cl_module__##module##__counter++) \ + { CL_JUMP_TO(cl_module__##module##__ctorend); } \ + } \ + }; \ + static cl_module__##module##__controller cl_module__##module##__ctordummy; + #define CL_PROVIDE_END(module) \ + struct cl_module__##module##__destroyer { \ + inline cl_module__##module##__destroyer () \ + { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__ctorend"); } \ + }; \ + static cl_module__##module##__destroyer cl_module__##module##__dtordummy; + #define CL_REQUIRE(module) \ + extern "C" void cl_module__##module##__ctor (void) \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun"); \ + struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ + inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ + { cl_module__##module##__ctor (); } \ + }; \ + static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ + _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); + #endif #define _CL_REQUIRE_CLASSNAME(module,line) __CL_REQUIRE_CLASSNAME(module,line) #define __CL_REQUIRE_CLASSNAME(module,line) cl_module__##module##__##line #else @@ -200,4 +248,32 @@ #define CL_REQUIRE(module) #endif +// Concatenation of macroexpanded tokens. +// Equivalent to CL_CONCAT in src/base/cl_macros.h which we do not want +// to expose, however. +#define CL_CONCATENATE_(xxx,yyy) xxx##yyy +#define CL_CONCATENATE(xxx,yyy) CL_CONCATENATE_(xxx,yyy) + +// Sometimes a link time dependency is needed, but without requirements +// on initialization order. +// +// CL_FORCE_LINK(dummy,external_variable) +// forces a link time reference to the external_variable. +#include +#if 0 +// This definition does not work. It gets optimized away by g++ 3.1. +#define CL_FORCE_LINK(dummy,external_variable) \ + static const void* const dummy[] = { &dummy, &external_variable }; +#else +#define CL_FORCE_LINK(dummy,external_variable) \ + static const \ + struct dummy { \ + inline dummy () { \ + if ((void*) &external_variable == (void*) this) \ + abort(); \ + } \ + } \ + CL_CONCATENATE(dummy,_instance); +#endif + #endif /* _CL_MODULES_H */