/libgo/runtime/print.c

https://gitlab.com/4144/gcc · C · 203 lines · 163 code · 19 blank · 21 comment · 8 complexity · fc1c7199fb443d3e4b49335b42e25886 MD5 · raw file

  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. #include <complex.h>
  5. #include <math.h>
  6. #include <stdarg.h>
  7. #include "runtime.h"
  8. #include "array.h"
  9. #include "go-type.h"
  10. extern void runtime_printlock(void)
  11. __asm__(GOSYM_PREFIX "runtime.printlock");
  12. extern void runtime_printunlock(void)
  13. __asm__(GOSYM_PREFIX "runtime.printunlock");
  14. extern void gwrite(Slice)
  15. __asm__(GOSYM_PREFIX "runtime.gwrite");
  16. extern void runtime_printint(int64)
  17. __asm__(GOSYM_PREFIX "runtime.printint");
  18. extern void runtime_printuint(uint64)
  19. __asm__(GOSYM_PREFIX "runtime.printuint");
  20. extern void runtime_printhex(uint64)
  21. __asm__(GOSYM_PREFIX "runtime.printhex");
  22. extern void runtime_printfloat(float64)
  23. __asm__(GOSYM_PREFIX "runtime.printfloat");
  24. extern void runtime_printcomplex(complex double)
  25. __asm__(GOSYM_PREFIX "runtime.printcomplex");
  26. extern void runtime_printbool(_Bool)
  27. __asm__(GOSYM_PREFIX "runtime.printbool");
  28. extern void runtime_printstring(String)
  29. __asm__(GOSYM_PREFIX "runtime.printstring");
  30. extern void runtime_printpointer(void *)
  31. __asm__(GOSYM_PREFIX "runtime.printpointer");
  32. extern void runtime_printslice(Slice)
  33. __asm__(GOSYM_PREFIX "runtime.printslice");
  34. extern void runtime_printeface(Eface)
  35. __asm__(GOSYM_PREFIX "runtime.printeface");
  36. extern void runtime_printiface(Iface)
  37. __asm__(GOSYM_PREFIX "runtime.printiface");
  38. // Clang requires this function to not be inlined (see below).
  39. static void go_vprintf(const char*, va_list)
  40. __attribute__((noinline));
  41. static void
  42. runtime_prints(const char *s)
  43. {
  44. Slice sl;
  45. // Use memcpy to avoid const-cast warning.
  46. memcpy(&sl.__values, &s, sizeof(char*));
  47. sl.__count = runtime_findnull((const byte*)s);
  48. sl.__capacity = sl.__count;
  49. gwrite(sl);
  50. }
  51. static void
  52. runtime_printbyte(int8 c)
  53. {
  54. Slice sl;
  55. sl.__values = &c;
  56. sl.__count = 1;
  57. sl.__capacity = 1;
  58. gwrite(sl);
  59. }
  60. #if defined (__clang__) && (defined (__i386__) || defined (__x86_64__))
  61. // LLVM's code generator does not currently support split stacks for vararg
  62. // functions, so we disable the feature for this function under Clang. This
  63. // appears to be OK as long as:
  64. // - this function only calls non-inlined, internal-linkage (hence no dynamic
  65. // loader) functions compiled with split stacks (i.e. go_vprintf), which can
  66. // allocate more stack space as required;
  67. // - this function itself does not occupy more than BACKOFF bytes of stack space
  68. // (see libgcc/config/i386/morestack.S).
  69. // These conditions are currently known to be satisfied by Clang on x86-32 and
  70. // x86-64. Note that signal handlers receive slightly less stack space than they
  71. // would normally do if they happen to be called while this function is being
  72. // run. If this turns out to be a problem we could consider increasing BACKOFF.
  73. void
  74. runtime_printf(const char *s, ...)
  75. __attribute__((no_split_stack));
  76. int32
  77. runtime_snprintf(byte *buf, int32 n, const char *s, ...)
  78. __attribute__((no_split_stack));
  79. #endif
  80. void
  81. runtime_printf(const char *s, ...)
  82. {
  83. va_list va;
  84. va_start(va, s);
  85. go_vprintf(s, va);
  86. va_end(va);
  87. }
  88. int32
  89. runtime_snprintf(byte *buf, int32 n, const char *s, ...)
  90. {
  91. G *g = runtime_g();
  92. va_list va;
  93. int32 m;
  94. g->writebuf.__values = buf;
  95. g->writebuf.__count = 0;
  96. g->writebuf.__capacity = n-1;
  97. va_start(va, s);
  98. go_vprintf(s, va);
  99. va_end(va);
  100. m = g->writebuf.__count;
  101. ((byte*)g->writebuf.__values)[m] = '\0';
  102. g->writebuf.__values = nil;
  103. g->writebuf.__count = 0;
  104. g->writebuf.__capacity = 0;
  105. return m;
  106. }
  107. // Very simple printf. Only for debugging prints.
  108. // Do not add to this without checking with Rob.
  109. static void
  110. go_vprintf(const char *s, va_list va)
  111. {
  112. const char *p, *lp;
  113. Slice sl;
  114. runtime_printlock();
  115. lp = p = s;
  116. for(; *p; p++) {
  117. if(*p != '%')
  118. continue;
  119. if(p > lp) {
  120. // Use memcpy to avoid const-cast warning.
  121. memcpy(&sl.__values, &lp, sizeof(char*));
  122. sl.__count = p - lp;
  123. sl.__capacity = p - lp;
  124. gwrite(sl);
  125. }
  126. p++;
  127. switch(*p) {
  128. case 'a':
  129. runtime_printslice(va_arg(va, Slice));
  130. break;
  131. case 'c':
  132. runtime_printbyte(va_arg(va, int32));
  133. break;
  134. case 'd':
  135. runtime_printint(va_arg(va, int32));
  136. break;
  137. case 'D':
  138. runtime_printint(va_arg(va, int64));
  139. break;
  140. case 'e':
  141. runtime_printeface(va_arg(va, Eface));
  142. break;
  143. case 'f':
  144. runtime_printfloat(va_arg(va, float64));
  145. break;
  146. case 'C':
  147. runtime_printcomplex(va_arg(va, complex double));
  148. break;
  149. case 'i':
  150. runtime_printiface(va_arg(va, Iface));
  151. break;
  152. case 'p':
  153. runtime_printpointer(va_arg(va, void*));
  154. break;
  155. case 's':
  156. runtime_prints(va_arg(va, char*));
  157. break;
  158. case 'S':
  159. runtime_printstring(va_arg(va, String));
  160. break;
  161. case 't':
  162. runtime_printbool(va_arg(va, int));
  163. break;
  164. case 'U':
  165. runtime_printuint(va_arg(va, uint64));
  166. break;
  167. case 'x':
  168. runtime_printhex(va_arg(va, uint32));
  169. break;
  170. case 'X':
  171. runtime_printhex(va_arg(va, uint64));
  172. break;
  173. }
  174. lp = p+1;
  175. }
  176. if(p > lp) {
  177. // Use memcpy to avoid const-cast warning.
  178. memcpy(&sl.__values, &lp, sizeof(char*));
  179. sl.__count = p - lp;
  180. sl.__capacity = p - lp;
  181. gwrite(sl);
  182. }
  183. runtime_printunlock();
  184. }