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