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