github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/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 #include "go-type.h" 11 12 //static Lock debuglock; 13 14 // Clang requires this function to not be inlined (see below). 15 static void go_vprintf(const char*, va_list) 16 __attribute__((noinline)); 17 18 // write to goroutine-local buffer if diverting output, 19 // or else standard error. 20 static void 21 gwrite(const void *v, intgo n) 22 { 23 G* g = runtime_g(); 24 25 if(g == nil || g->writebuf == nil) { 26 // Avoid -D_FORTIFY_SOURCE problems. 27 int rv __attribute__((unused)); 28 29 rv = runtime_write(2, v, n); 30 return; 31 } 32 33 if(g->writenbuf == 0) 34 return; 35 36 if(n > g->writenbuf) 37 n = g->writenbuf; 38 runtime_memmove(g->writebuf, v, n); 39 g->writebuf += n; 40 g->writenbuf -= n; 41 } 42 43 void 44 runtime_dump(byte *p, int32 n) 45 { 46 int32 i; 47 48 for(i=0; i<n; i++) { 49 runtime_printpointer((byte*)(uintptr)(p[i]>>4)); 50 runtime_printpointer((byte*)(uintptr)(p[i]&0xf)); 51 if((i&15) == 15) 52 runtime_prints("\n"); 53 else 54 runtime_prints(" "); 55 } 56 if(n & 15) 57 runtime_prints("\n"); 58 } 59 60 void 61 runtime_prints(const char *s) 62 { 63 gwrite(s, runtime_findnull((const byte*)s)); 64 } 65 66 #if defined (__clang__) && (defined (__i386__) || defined (__x86_64__)) 67 // LLVM's code generator does not currently support split stacks for vararg 68 // functions, so we disable the feature for this function under Clang. This 69 // appears to be OK as long as: 70 // - this function only calls non-inlined, internal-linkage (hence no dynamic 71 // loader) functions compiled with split stacks (i.e. go_vprintf), which can 72 // allocate more stack space as required; 73 // - this function itself does not occupy more than BACKOFF bytes of stack space 74 // (see libgcc/config/i386/morestack.S). 75 // These conditions are currently known to be satisfied by Clang on x86-32 and 76 // x86-64. Note that signal handlers receive slightly less stack space than they 77 // would normally do if they happen to be called while this function is being 78 // run. If this turns out to be a problem we could consider increasing BACKOFF. 79 80 void 81 runtime_printf(const char *s, ...) 82 __attribute__((no_split_stack)); 83 84 int32 85 runtime_snprintf(byte *buf, int32 n, const char *s, ...) 86 __attribute__((no_split_stack)); 87 88 #endif 89 90 void 91 runtime_printf(const char *s, ...) 92 { 93 va_list va; 94 95 va_start(va, s); 96 go_vprintf(s, va); 97 va_end(va); 98 } 99 100 int32 101 runtime_snprintf(byte *buf, int32 n, const char *s, ...) 102 { 103 G *g = runtime_g(); 104 va_list va; 105 int32 m; 106 107 g->writebuf = buf; 108 g->writenbuf = n-1; 109 va_start(va, s); 110 go_vprintf(s, va); 111 va_end(va); 112 *g->writebuf = '\0'; 113 m = g->writebuf - buf; 114 g->writenbuf = 0; 115 g->writebuf = nil; 116 return m; 117 } 118 119 // Very simple printf. Only for debugging prints. 120 // Do not add to this without checking with Rob. 121 static void 122 go_vprintf(const char *s, va_list va) 123 { 124 const char *p, *lp; 125 126 //runtime_lock(&debuglock); 127 128 lp = p = s; 129 for(; *p; p++) { 130 if(*p != '%') 131 continue; 132 if(p > lp) 133 gwrite(lp, p-lp); 134 p++; 135 switch(*p) { 136 case 'a': 137 runtime_printslice(va_arg(va, Slice)); 138 break; 139 case 'c': 140 runtime_printbyte(va_arg(va, int32)); 141 break; 142 case 'd': 143 runtime_printint(va_arg(va, int32)); 144 break; 145 case 'D': 146 runtime_printint(va_arg(va, int64)); 147 break; 148 case 'e': 149 runtime_printeface(va_arg(va, Eface)); 150 break; 151 case 'f': 152 runtime_printfloat(va_arg(va, float64)); 153 break; 154 case 'C': 155 runtime_printcomplex(va_arg(va, complex double)); 156 break; 157 case 'i': 158 runtime_printiface(va_arg(va, Iface)); 159 break; 160 case 'p': 161 runtime_printpointer(va_arg(va, void*)); 162 break; 163 case 's': 164 runtime_prints(va_arg(va, char*)); 165 break; 166 case 'S': 167 runtime_printstring(va_arg(va, String)); 168 break; 169 case 't': 170 runtime_printbool(va_arg(va, int)); 171 break; 172 case 'U': 173 runtime_printuint(va_arg(va, uint64)); 174 break; 175 case 'x': 176 runtime_printhex(va_arg(va, uint32)); 177 break; 178 case 'X': 179 runtime_printhex(va_arg(va, uint64)); 180 break; 181 } 182 lp = p+1; 183 } 184 if(p > lp) 185 gwrite(lp, p-lp); 186 187 //runtime_unlock(&debuglock); 188 } 189 190 void 191 runtime_printpc(void *p __attribute__ ((unused))) 192 { 193 runtime_prints("PC="); 194 runtime_printhex((uint64)(uintptr)runtime_getcallerpc(p)); 195 } 196 197 void 198 runtime_printbool(_Bool v) 199 { 200 if(v) { 201 gwrite("true", 4); 202 return; 203 } 204 gwrite("false", 5); 205 } 206 207 void 208 runtime_printbyte(int8 c) 209 { 210 gwrite(&c, 1); 211 } 212 213 void 214 runtime_printfloat(double v) 215 { 216 byte buf[20]; 217 int32 e, s, i, n; 218 float64 h; 219 220 if(ISNAN(v)) { 221 gwrite("NaN", 3); 222 return; 223 } 224 if(isinf(v)) { 225 if(signbit(v)) { 226 gwrite("-Inf", 4); 227 } else { 228 gwrite("+Inf", 4); 229 } 230 return; 231 } 232 233 n = 7; // digits printed 234 e = 0; // exp 235 s = 0; // sign 236 if(v == 0) { 237 if(isinf(1/v) && 1/v < 0) 238 s = 1; 239 } else { 240 // sign 241 if(v < 0) { 242 v = -v; 243 s = 1; 244 } 245 246 // normalize 247 while(v >= 10) { 248 e++; 249 v /= 10; 250 } 251 while(v < 1) { 252 e--; 253 v *= 10; 254 } 255 256 // round 257 h = 5; 258 for(i=0; i<n; i++) 259 h /= 10; 260 261 v += h; 262 if(v >= 10) { 263 e++; 264 v /= 10; 265 } 266 } 267 268 // format +d.dddd+edd 269 buf[0] = '+'; 270 if(s) 271 buf[0] = '-'; 272 for(i=0; i<n; i++) { 273 s = v; 274 buf[i+2] = s+'0'; 275 v -= s; 276 v *= 10.; 277 } 278 buf[1] = buf[2]; 279 buf[2] = '.'; 280 281 buf[n+2] = 'e'; 282 buf[n+3] = '+'; 283 if(e < 0) { 284 e = -e; 285 buf[n+3] = '-'; 286 } 287 288 buf[n+4] = (e/100) + '0'; 289 buf[n+5] = (e/10)%10 + '0'; 290 buf[n+6] = (e%10) + '0'; 291 gwrite(buf, n+7); 292 } 293 294 void 295 runtime_printcomplex(complex double v) 296 { 297 gwrite("(", 1); 298 runtime_printfloat(creal(v)); 299 runtime_printfloat(cimag(v)); 300 gwrite("i)", 2); 301 } 302 303 void 304 runtime_printuint(uint64 v) 305 { 306 byte buf[100]; 307 int32 i; 308 309 for(i=nelem(buf)-1; i>0; i--) { 310 buf[i] = v%10 + '0'; 311 if(v < 10) 312 break; 313 v = v/10; 314 } 315 gwrite(buf+i, nelem(buf)-i); 316 } 317 318 void 319 runtime_printint(int64 v) 320 { 321 if(v < 0) { 322 gwrite("-", 1); 323 v = -v; 324 } 325 runtime_printuint(v); 326 } 327 328 void 329 runtime_printhex(uint64 v) 330 { 331 static const char *dig = "0123456789abcdef"; 332 byte buf[100]; 333 int32 i; 334 335 i=nelem(buf); 336 for(; v>0; v/=16) 337 buf[--i] = dig[v%16]; 338 if(i == nelem(buf)) 339 buf[--i] = '0'; 340 buf[--i] = 'x'; 341 buf[--i] = '0'; 342 gwrite(buf+i, nelem(buf)-i); 343 } 344 345 void 346 runtime_printpointer(void *p) 347 { 348 runtime_printhex((uintptr)p); 349 } 350 351 void 352 runtime_printstring(String v) 353 { 354 // if(v.len > runtime_maxstring) { 355 // gwrite("[string too long]", 17); 356 // return; 357 // } 358 if(v.len > 0) 359 gwrite(v.str, v.len); 360 } 361 362 void 363 __go_print_space(void) 364 { 365 gwrite(" ", 1); 366 } 367 368 void 369 __go_print_nl(void) 370 { 371 gwrite("\n", 1); 372 }