hppa: Fix g++.dg/modules/bad-mapper-1.C on hpux
[official-gcc.git] / libgo / runtime / print.c
blobf0269e8d20b5211302c733fbbae47f173da74a9b
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"
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");
40 // Clang requires this function to not be inlined (see below).
41 static void go_vprintf(const char*, va_list)
42 __attribute__((noinline));
44 static void
45 runtime_prints(const char *s)
47 Slice sl;
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);
56 static void
57 runtime_printbyte(int8 c)
59 Slice sl;
61 sl.__values = &c;
62 sl.__count = 1;
63 sl.__capacity = 1;
64 gwrite(sl);
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.
81 void
82 runtime_printf(const char *s, ...)
83 __attribute__((no_split_stack));
85 int32
86 runtime_snprintf(byte *buf, int32 n, const char *s, ...)
87 __attribute__((no_split_stack));
89 #endif
91 void
92 runtime_printf(const char *s, ...)
94 va_list va;
96 va_start(va, s);
97 go_vprintf(s, va);
98 va_end(va);
101 int32
102 runtime_snprintf(byte *buf, int32 n, const char *s, ...)
104 G *g = runtime_g();
105 va_list va;
106 int32 m;
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;
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)
127 const char *p, *lp;
128 Slice sl;
130 runtime_printlock();
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);
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;
191 lp = p+1;
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);
201 runtime_printunlock();