You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
9.7 KiB

25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
  1. // Macros for correct module ordering.
  2. #ifndef _CL_MODULES_H
  3. #define _CL_MODULES_H
  4. // The order of initialization of different compilation units is not
  5. // specified in C++. AIX 4 has a linker which apparently does order
  6. // the modules according to dependencies, so that low-level modules
  7. // will be initialized earlier than the high-level modules which depend
  8. // on them. I have a patch for GNU ld that does the same thing.
  9. //
  10. // But for now, I take a half-automatic approach to the correct module
  11. // ordering problem: PROVIDE/REQUIRE, as in Common Lisp.
  12. //
  13. // CL_PROVIDE(module) must be the first code-generating entity in a module.
  14. // Inline function definitions can precede it, but global variable/function/
  15. // class definitions may not precede it.
  16. // Afterwards, any number of CL_REQUIRE(othermodule) is allowed.
  17. // At the end of the module, there must be a corresponding
  18. // CL_PROVIDE_END(module). (Sorry for this, it's really needed.)
  19. //
  20. // These macros work only with g++, and only in optimizing mode. But who
  21. // wants to use CLN with other C++ compilers anyway...
  22. // How to apply these macros:
  23. // 1. Find out about variables which need to be initialized.
  24. // On Linux/ELF, you can use a command like
  25. // $ nm -o libcln.a | grep -v ' [UTtRrW] ' | sort +1
  26. // A symbol of type "D" or "d" lies in the preinitialized DATA section,
  27. // a symbol of type "B" or "b" lies in the uninitialized BSS section.
  28. // All of them have to be checked.
  29. // - Those which contain POD (= plain old data, i.e. scalar values or
  30. // class instances without nontrivial constructors) are already fully
  31. // initialized by the linker and can be discarded from these considerations.
  32. // - Those which are static variables inside a function (you recognize
  33. // them: g++ appends a dot and a number to their name) are initialized
  34. // the first time the function is entered. They can be discarded from
  35. // our considerations as well.
  36. // 2. Find out which of these variables are publically exposed (to the user of
  37. // the library) through the library's include files, either directly or
  38. // through inline functions, or indirectly through normal function calls.
  39. // These variables can be referenced from any user module U, hence any
  40. // such module must CL_REQUIRE(M) the variable's definition module M.
  41. // Since there is no CL_REQUIRE_IF_NEEDED(M) macro (which is equivalent
  42. // to CL_REQUIRE(M) if the required module will be part of the executable
  43. // but does nothing if M is not used), we must preventively put the
  44. // CL_REQUIRE(M) into the header file. Hopefully M is either used anyway
  45. // or does not bring in too much code into the executable.
  46. // 3. Variables which are not publicly exposed but used internally by the
  47. // library can be handled by adding a CL_REQUIRE in all the library's
  48. // modules which directly or indirectly use the variable.
  49. // 4. Variables and functions which can be reasonably assumed to not be
  50. // accessed or executed during initialization need not be treated.
  51. // For example, I/O to external streams, exception handling facilities,
  52. // number theory stuff, etc.
  53. // OK, stop reading here, because it's getting obscene.
  54. #if defined(__GNUC__) && defined(__OPTIMIZE__) && !(defined(__hppa__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8)) && !defined(NO_PROVIDE_REQUIRE)
  55. #ifdef ASM_UNDERSCORE
  56. #define ASM_UNDERSCORE_PREFIX "_"
  57. #else
  58. #define ASM_UNDERSCORE_PREFIX ""
  59. #endif
  60. // Globalize a label defined in the same translation unit.
  61. // See macro ASM_GLOBALIZE_LABEL in the gcc sources.
  62. #if defined(__i386__) || defined(__m68k__) || defined(__mips__) || defined(__mips64__) || defined(__alpha__) || defined(__rs6000__)
  63. // Some m68k systems use "xdef" or "global" or ".global"...
  64. #define CL_GLOBALIZE_LABEL(label) __asm__("\t.globl " label);
  65. #endif
  66. #if defined(__sparc__) || defined(__sparc64__) || defined(__arm__) || defined(__ia64__)
  67. // Some arm systems use "EXPORT" or ".globl"...
  68. #define CL_GLOBALIZE_LABEL(label) __asm__("\t.global " label);
  69. #endif
  70. #if defined(__hppa__)
  71. #define CL_GLOBALIZE_LABEL(label) __asm__("\t.EXPORT " label ",ENTRY,PRIV_LEV=3");
  72. #endif
  73. #if defined(__m88k__)
  74. #define CL_GLOBALIZE_LABEL(label) __asm__("\tglobal " label);
  75. #endif
  76. #if defined(__convex__)
  77. #define CL_GLOBALIZE_LABEL(label) __asm__(".globl " label);
  78. #endif
  79. #ifndef CL_GLOBALIZE_LABEL
  80. #define CL_GLOBALIZE_LABEL(label)
  81. #endif
  82. #if defined(__rs6000__) || defined(_WIN32)
  83. #define CL_GLOBALIZE_JUMP_LABEL(label) CL_GLOBALIZE_LABEL(#label)
  84. #else
  85. #define CL_GLOBALIZE_JUMP_LABEL(label)
  86. #endif
  87. #ifdef CL_NEED_GLOBALIZE_CTORDTOR
  88. #define CL_GLOBALIZE_CTORDTOR_LABEL(label) CL_GLOBALIZE_LABEL(label)
  89. #else
  90. #define CL_GLOBALIZE_CTORDTOR_LABEL(label)
  91. #endif
  92. // Output a label inside a function.
  93. // See macro ASM_OUTPUT_LABEL in the gcc sources.
  94. #if defined(__hppa__)
  95. #define CL_OUTPUT_LABEL(label) ASM_VOLATILE ("\n" label)
  96. #else
  97. #define CL_OUTPUT_LABEL(label) ASM_VOLATILE ("\n" label ":")
  98. #endif
  99. // ASM_VOLATILE(string) is for asms without arguments only!!
  100. #if ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 91)) || (__GNUC__ >= 3)
  101. // avoid warning caused by the volatile keyword
  102. #define ASM_VOLATILE __asm__
  103. #else
  104. // need volatile to avoid reordering
  105. #define ASM_VOLATILE __asm__ __volatile__
  106. #endif
  107. // CL_JUMP_TO(addr) jumps to an address, like goto *(void*)(addr),
  108. // except that the latter inhibits inlining of the function containing it
  109. // in gcc-2.95. For new CPUs, look for "jump" and "indirect_jump" in gcc's
  110. // machine description.
  111. #if defined(__i386__)
  112. #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %*%0" : : "rm" ((void*)(addr)))
  113. #endif
  114. #if defined(__m68k__)
  115. #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %0@" : : "a" ((void*)(addr)))
  116. #endif
  117. #if defined(__mips__)
  118. #define CL_JUMP_TO(addr) ASM_VOLATILE("%*j %0" : : "d" ((void*)(addr)))
  119. #endif
  120. #if defined(__sparc__) || defined(__sparc64__)
  121. #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %0\n\tnop" : : "r" ((void*)(addr)))
  122. #endif
  123. #if defined(__alpha__)
  124. #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp $31,(%0),0" : : "r" ((void*)(addr)))
  125. #endif
  126. #if defined(__hppa__)
  127. //#define CL_JUMP_TO(addr) ASM_VOLATILE("bv,n 0(%0)" : : "r" ((void*)(addr)))
  128. #define CL_JUMP_TO(addr) ASM_VOLATILE("b " #addr "\n\tnop")
  129. #endif
  130. #if defined(__arm__)
  131. #define CL_JUMP_TO(addr) ASM_VOLATILE("mov pc,%0" : : "r" ((void*)(addr)))
  132. #endif
  133. #if defined(__rs6000__) || defined(__powerpc__) || defined(__ppc__)
  134. //#define CL_JUMP_TO(addr) ASM_VOLATILE("mtctr %0\n\tbctr" : : "r" ((void*)(addr)))
  135. #define CL_JUMP_TO(addr) ASM_VOLATILE("b " #addr)
  136. #endif
  137. #if defined(__m88k__)
  138. #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %0" : : "r" ((void*)(addr)))
  139. #endif
  140. #if defined(__convex__)
  141. #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp (%0)" : : "r" ((void*)(addr)))
  142. #endif
  143. #if defined(__ia64__)
  144. #define CL_JUMP_TO(addr) ASM_VOLATILE("br " #addr)
  145. #endif
  146. #define CL_PROVIDE(module) \
  147. extern "C" void cl_module__##module##__firstglobalfun () {} \
  148. extern "C" void cl_module__##module##__ctorend (void); \
  149. extern "C" void cl_module__##module##__dtorend (void); \
  150. CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \
  151. CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__dtorend) \
  152. CL_GLOBALIZE_CTORDTOR_LABEL( \
  153. ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \
  154. "cl_module__" #module "__firstglobalfun") \
  155. CL_GLOBALIZE_CTORDTOR_LABEL( \
  156. ASM_UNDERSCORE_PREFIX CL_GLOBAL_DESTRUCTOR_PREFIX \
  157. "cl_module__" #module "__firstglobalfun") \
  158. static int cl_module__##module##__counter; \
  159. struct cl_module__##module##__controller { \
  160. inline cl_module__##module##__controller () \
  161. { if (cl_module__##module##__counter++) \
  162. { CL_JUMP_TO(cl_module__##module##__ctorend); } \
  163. } \
  164. inline ~cl_module__##module##__controller () \
  165. { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__dtorend"); } \
  166. }; \
  167. static cl_module__##module##__controller cl_module__##module##__ctordummy;
  168. #define CL_PROVIDE_END(module) \
  169. struct cl_module__##module##__destroyer { \
  170. inline cl_module__##module##__destroyer () \
  171. { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__ctorend"); } \
  172. inline ~cl_module__##module##__destroyer () \
  173. { if (--cl_module__##module##__counter) \
  174. { CL_JUMP_TO(cl_module__##module##__dtorend); } \
  175. } \
  176. }; \
  177. static cl_module__##module##__destroyer cl_module__##module##__dtordummy;
  178. #define CL_REQUIRE(module) \
  179. extern "C" void cl_module__##module##__ctor (void) \
  180. __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \
  181. "cl_module__" #module "__firstglobalfun"); \
  182. extern "C" void cl_module__##module##__dtor (void) \
  183. __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_DESTRUCTOR_PREFIX \
  184. "cl_module__" #module "__firstglobalfun"); \
  185. struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \
  186. inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \
  187. { cl_module__##module##__ctor (); } \
  188. inline ~_CL_REQUIRE_CLASSNAME(module,__LINE__) () \
  189. { cl_module__##module##__dtor (); } \
  190. }; \
  191. static _CL_REQUIRE_CLASSNAME(module,__LINE__) \
  192. _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__);
  193. #define _CL_REQUIRE_CLASSNAME(module,line) __CL_REQUIRE_CLASSNAME(module,line)
  194. #define __CL_REQUIRE_CLASSNAME(module,line) cl_module__##module##__##line
  195. #else
  196. #define CL_PROVIDE(module)
  197. #define CL_PROVIDE_END(module)
  198. #define CL_REQUIRE(module)
  199. #endif
  200. #endif /* _CL_MODULES_H */