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
gwrite(const void * v,intgo n)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
runtime_dump(byte * p,int32 n)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
runtime_prints(const char * s)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
runtime_printf(const char * s,...)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
runtime_snprintf(byte * buf,int32 n,const char * s,...)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
go_vprintf(const char * s,va_list va)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
runtime_printpc(void * p)191 runtime_printpc(void *p __attribute__ ((unused)))
192 {
193 	runtime_prints("PC=");
194 	runtime_printhex((uint64)(uintptr)runtime_getcallerpc(p));
195 }
196 
197 void
runtime_printbool(_Bool v)198 runtime_printbool(_Bool v)
199 {
200 	if(v) {
201 		gwrite("true", 4);
202 		return;
203 	}
204 	gwrite("false", 5);
205 }
206 
207 void
runtime_printbyte(int8 c)208 runtime_printbyte(int8 c)
209 {
210 	gwrite(&c, 1);
211 }
212 
213 void
runtime_printfloat(double v)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
runtime_printcomplex(complex double v)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
runtime_printuint(uint64 v)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
runtime_printint(int64 v)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
runtime_printhex(uint64 v)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
runtime_printpointer(void * p)346 runtime_printpointer(void *p)
347 {
348 	runtime_printhex((uintptr)p);
349 }
350 
351 void
runtime_printstring(String v)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
__go_print_space(void)363 __go_print_space(void)
364 {
365 	gwrite(" ", 1);
366 }
367 
368 void
__go_print_nl(void)369 __go_print_nl(void)
370 {
371 	gwrite("\n", 1);
372 }
373