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