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  }