print_wasm.mx raw
1 //go:build wasm
2
3 package runtime
4
5 import (
6 "unsafe"
7 )
8
9 type stringer interface {
10 String() string
11 }
12
13 //go:nobounds
14 func printstring(s string) {
15 for i := 0; i < len(s); i++ {
16 putchar(s[i])
17 }
18 }
19
20 func printuint8(n uint8) {
21 if TargetBits >= 32 {
22 printuint32(uint32(n))
23 } else {
24 prevdigits := n / 10
25 if prevdigits != 0 {
26 printuint8(prevdigits)
27 }
28 putchar(byte((n % 10) + '0'))
29 }
30 }
31
32 func printint8(n int8) {
33 if TargetBits >= 32 {
34 printint32(int32(n))
35 } else {
36 if n < 0 {
37 putchar('-')
38 n = -n
39 }
40 printuint8(uint8(n))
41 }
42 }
43
44 func printuintptr(n uintptr) {
45 switch unsafe.Sizeof(n) {
46 case 2:
47 printuint16(uint16(n))
48 case 4:
49 printuint32(uint32(n))
50 case 8:
51 printuint64(uint64(n))
52 }
53 }
54
55 func printuint16(n uint16) {
56 printuint32(uint32(n))
57 }
58
59 func printint16(n int16) {
60 printint32(int32(n))
61 }
62
63 func printuint32(n uint32) {
64 printuint64(uint64(n))
65 }
66
67 func printint32(n int32) {
68 if n < 0 {
69 putchar('-')
70 n = -n
71 }
72 printuint32(uint32(n))
73 }
74
75 //go:nobounds
76 func printuint64(n uint64) {
77 digits := [20]byte{}
78 firstdigit := 19
79 for i := 19; i >= 0; i-- {
80 digit := byte(n%10 + '0')
81 digits[i] = digit
82 if digit != '0' {
83 firstdigit = i
84 }
85 n /= 10
86 }
87 for i := firstdigit; i < 20; i++ {
88 putchar(digits[i])
89 }
90 }
91
92 func printint64(n int64) {
93 if n < 0 {
94 putchar('-')
95 n = -n
96 }
97 printuint64(uint64(n))
98 }
99
100 func printfloat32(v float32) {
101 switch {
102 case v != v:
103 printstring("NaN")
104 return
105 case v+v == v && v > 0:
106 printstring("+Inf")
107 return
108 case v+v == v && v < 0:
109 printstring("-Inf")
110 return
111 }
112
113 const n = 7
114 var buf [n + 7]byte
115 buf[0] = '+'
116 e := 0
117 if v == 0 {
118 if 1/v < 0 {
119 buf[0] = '-'
120 }
121 } else {
122 if v < 0 {
123 v = -v
124 buf[0] = '-'
125 }
126
127 for v >= 10 {
128 e++
129 v /= 10
130 }
131 for v < 1 {
132 e--
133 v *= 10
134 }
135
136 h := float32(5.0)
137 for i := 0; i < n; i++ {
138 h /= 10
139 }
140 v += h
141 if v >= 10 {
142 e++
143 v /= 10
144 }
145 }
146
147 for i := 0; i < n; i++ {
148 s := int32(v)
149 buf[i+2] = byte(s + '0')
150 v -= float32(s)
151 v *= 10
152 }
153 buf[1] = buf[2]
154 buf[2] = '.'
155
156 buf[n+2] = 'e'
157 buf[n+3] = '+'
158 if e < 0 {
159 e = -e
160 buf[n+3] = '-'
161 }
162
163 buf[n+4] = byte(e/100) + '0'
164 buf[n+5] = byte(e/10)%10 + '0'
165 buf[n+6] = byte(e%10) + '0'
166 for _, c := range buf {
167 putchar(c)
168 }
169 }
170
171 func printfloat64(v float64) {
172 switch {
173 case v != v:
174 printstring("NaN")
175 return
176 case v+v == v && v > 0:
177 printstring("+Inf")
178 return
179 case v+v == v && v < 0:
180 printstring("-Inf")
181 return
182 }
183
184 const n = 7
185 var buf [n + 7]byte
186 buf[0] = '+'
187 e := 0
188 if v == 0 {
189 if 1/v < 0 {
190 buf[0] = '-'
191 }
192 } else {
193 if v < 0 {
194 v = -v
195 buf[0] = '-'
196 }
197
198 for v >= 10 {
199 e++
200 v /= 10
201 }
202 for v < 1 {
203 e--
204 v *= 10
205 }
206
207 h := 5.0
208 for i := 0; i < n; i++ {
209 h /= 10
210 }
211 v += h
212 if v >= 10 {
213 e++
214 v /= 10
215 }
216 }
217
218 for i := 0; i < n; i++ {
219 s := int32(v)
220 buf[i+2] = byte(s + '0')
221 v -= float64(s)
222 v *= 10
223 }
224 buf[1] = buf[2]
225 buf[2] = '.'
226
227 buf[n+2] = 'e'
228 buf[n+3] = '+'
229 if e < 0 {
230 e = -e
231 buf[n+3] = '-'
232 }
233
234 buf[n+4] = byte(e/100) + '0'
235 buf[n+5] = byte(e/10)%10 + '0'
236 buf[n+6] = byte(e%10) + '0'
237 for _, c := range buf {
238 putchar(c)
239 }
240 }
241
242 func printcomplex64(c complex64) {
243 putchar('(')
244 printfloat32(real(c))
245 printfloat32(imag(c))
246 printstring("i)")
247 }
248
249 func printcomplex128(c complex128) {
250 putchar('(')
251 printfloat64(real(c))
252 printfloat64(imag(c))
253 printstring("i)")
254 }
255
256 func printspace() {
257 putchar(' ')
258 }
259
260 func printnl() {
261 if baremetal {
262 putchar('\r')
263 }
264 putchar('\n')
265 }
266
267 // printitf for WASM: int≡int32 and uint≡uint32, so only int32/uint32 cases.
268 func printitf(msg interface{}) {
269 switch msg := msg.(type) {
270 case bool:
271 printbool(msg)
272 case int8:
273 printint8(msg)
274 case int16:
275 printint16(msg)
276 case int32:
277 printint32(msg)
278 case int64:
279 printint64(msg)
280 case uint8:
281 printuint8(msg)
282 case uint16:
283 printuint16(msg)
284 case uint32:
285 printuint32(msg)
286 case uint64:
287 printuint64(msg)
288 case uintptr:
289 printuintptr(msg)
290 case float32:
291 printfloat32(msg)
292 case float64:
293 printfloat64(msg)
294 case complex64:
295 printcomplex64(msg)
296 case complex128:
297 printcomplex128(msg)
298 case string:
299 printstring(msg)
300 case error:
301 printstring(msg.Error())
302 case stringer:
303 printstring(msg.String())
304 default:
305 itf := *(*_interface)(unsafe.Pointer(&msg))
306 putchar('(')
307 printuintptr(uintptr(itf.typecode))
308 putchar(':')
309 printptr(uintptr(itf.value))
310 putchar(')')
311 }
312 }
313
314 func printmap(m *hashmap) {
315 printstring("map[")
316 if m == nil {
317 printstring("nil")
318 } else {
319 switch unsafe.Sizeof(m.count) {
320 case 8:
321 printuint64(uint64(m.count))
322 case 4:
323 printuint32(uint32(m.count))
324 case 2:
325 printuint16(uint16(m.count))
326 }
327 }
328 putchar(']')
329 }
330
331 func printptr(ptr uintptr) {
332 if ptr == 0 {
333 printstring("nil")
334 return
335 }
336 putchar('0')
337 putchar('x')
338 for i := 0; i < int32(unsafe.Sizeof(ptr))*2; i++ {
339 nibble := byte(ptr >> (unsafe.Sizeof(ptr)*8 - 4))
340 if nibble < 10 {
341 putchar(nibble + '0')
342 } else {
343 putchar(nibble - 10 + 'a')
344 }
345 ptr <<= 4
346 }
347 }
348
349 func printbool(b bool) {
350 if b {
351 printstring("true")
352 } else {
353 printstring("false")
354 }
355 }
356
357 func printslice(ptr, len_, cap_ uintptr) {
358 putchar('[')
359 printuintptr(len_)
360 putchar('/')
361 printuintptr(cap_)
362 putchar(']')
363 printptr(ptr)
364 }
365