From 94ce893ab4ee9e31f354ef33f826fb7976bb726e Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Fri, 31 Aug 2018 21:25:32 +0200 Subject: [PATCH] Copy printfloat() from original runtime I've tried writing my own, but I couldn't make it correct in all cases. So just copy the one from upstream for now, hopefully to be replaced at some point. TODO: add a printfloat32() implementation, now it just casts to float64. This will be useful for embedded systems that sometimes have float32 but not float64. --- compiler.go | 4 +++ src/runtime/print.go | 86 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/compiler.go b/compiler.go index c11d8e7f..aa237392 100644 --- a/compiler.go +++ b/compiler.go @@ -1303,6 +1303,10 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string) c.builder.CreateCall(fn, []llvm.Value{value}, "") } else if typ.Kind() == types.Bool { c.builder.CreateCall(c.mod.NamedFunction("runtime.printbool"), []llvm.Value{value}, "") + } else if typ.Kind() == types.Float32 { + c.builder.CreateCall(c.mod.NamedFunction("runtime.printfloat32"), []llvm.Value{value}, "") + } else if typ.Kind() == types.Float64 { + c.builder.CreateCall(c.mod.NamedFunction("runtime.printfloat64"), []llvm.Value{value}, "") } else { return llvm.Value{}, errors.New("unknown basic arg type: " + typ.String()) } diff --git a/src/runtime/print.go b/src/runtime/print.go index 206ffb51..54d98afd 100644 --- a/src/runtime/print.go +++ b/src/runtime/print.go @@ -86,6 +86,92 @@ func printint64(n int64) { printuint64(uint64(n)) } +func printfloat32(v float32) { + // TODO: write an implementation like printfloat64, as some systems have + // 32-bit floats but only software emulation for 64-bit floats. + printfloat64(float64(v)) +} + +// printfloat64() was copied from the relevant source in the original Go +// implementation. It is copyright by the Go authors, licensed under the same +// BSD 3-clause license. See https://golang.org/LICENSE for details. +// +// Source: +// https://github.com/golang/go/blob/master/src/runtime/print.go +func printfloat64(v float64) { + switch { + case v != v: + printstring("NaN") + return + case v+v == v && v > 0: + printstring("+Inf") + return + case v+v == v && v < 0: + printstring("-Inf") + return + } + + const n = 7 // digits printed + var buf [n + 7]byte + buf[0] = '+' + e := 0 // exp + if v == 0 { + if 1/v < 0 { + buf[0] = '-' + } + } else { + if v < 0 { + v = -v + buf[0] = '-' + } + + // normalize + for v >= 10 { + e++ + v /= 10 + } + for v < 1 { + e-- + v *= 10 + } + + // round + h := 5.0 + for i := 0; i < n; i++ { + h /= 10 + } + v += h + if v >= 10 { + e++ + v /= 10 + } + } + + // format +d.dddd+edd + for i := 0; i < n; i++ { + s := int(v) + buf[i+2] = byte(s + '0') + v -= float64(s) + v *= 10 + } + buf[1] = buf[2] + buf[2] = '.' + + buf[n+2] = 'e' + buf[n+3] = '+' + if e < 0 { + e = -e + buf[n+3] = '-' + } + + buf[n+4] = byte(e/100) + '0' + buf[n+5] = byte(e/10)%10 + '0' + buf[n+6] = byte(e%10) + '0' + for _, c := range buf { + putchar(c) + } +} + func printspace() { putchar(' ') }