operand: fix integer float data (#393)

Issue #387 pointed out that integer float data is printed incorrectly, such
that it is not parsed correctly by the Go assembler. Specifically, integer
values need the decimal point, otherwise they will be treated as integers. For
example, 1 must be represented as `$(1.)` or `$(1.0)` to be parsed correctly.

This PR fixes that problem and adds a regression test.  The root of the
problem was that the formatting verb `%#v` does not have the right behavior
for integers. We fix it by deferring to custom `String()` function for the
float operand types.

Fixes #387
Closes #388
This commit is contained in:
Michael McLoughlin
2023-06-11 16:12:59 -07:00
committed by GitHub
parent 9bef88dadc
commit 0d789c8353
9 changed files with 172 additions and 4 deletions

View File

@@ -0,0 +1,53 @@
//go:build ignore
// +build ignore
package main
import (
. "github.com/mmcloughlin/avo/build"
. "github.com/mmcloughlin/avo/operand"
)
// Float32 generates a function which indexes into an array of single-precision
// integer float values.
func Float32() {
f32 := GLOBL("f32", RODATA|NOPTR)
for i := 0; i < 10; i++ {
DATA(4*i, F32(i))
}
TEXT("Float32", NOSPLIT, "func(i int) float32")
Doc("Float32 indexes into an array of single-precision integral floats.")
i := Load(Param("i"), GP64())
ptr := Mem{Base: GP64()}
LEAQ(f32, ptr.Base)
x := XMM()
MOVSS(ptr.Idx(i, 4), x)
Store(x, ReturnIndex(0))
RET()
}
// Float64 generates a function which indexes into an array of double-precision
// integer float values.
func Float64() {
f64 := GLOBL("f64", RODATA|NOPTR)
for i := 0; i < 10; i++ {
DATA(8*i, F64(i))
}
TEXT("Float64", NOSPLIT, "func(i int) float64")
Doc("Float64 indexes into an array of double-precision integral floats.")
i := Load(Param("i"), GP64())
ptr := Mem{Base: GP64()}
LEAQ(f64, ptr.Base)
x := XMM()
MOVSD(ptr.Idx(i, 8), x)
Store(x, ReturnIndex(0))
RET()
}
func main() {
Float32()
Float64()
Generate()
}

View File

@@ -0,0 +1,3 @@
// Package issue387 tests representation of floating point data with integer
// values.
package issue387

View File

@@ -0,0 +1,45 @@
// Code generated by command: go run asm.go -out issue387.s -stubs stub.go. DO NOT EDIT.
#include "textflag.h"
DATA f32<>+0(SB)/4, $(0.0)
DATA f32<>+4(SB)/4, $(1.0)
DATA f32<>+8(SB)/4, $(2.0)
DATA f32<>+12(SB)/4, $(3.0)
DATA f32<>+16(SB)/4, $(4.0)
DATA f32<>+20(SB)/4, $(5.0)
DATA f32<>+24(SB)/4, $(6.0)
DATA f32<>+28(SB)/4, $(7.0)
DATA f32<>+32(SB)/4, $(8.0)
DATA f32<>+36(SB)/4, $(9.0)
GLOBL f32<>(SB), RODATA|NOPTR, $40
// func Float32(i int) float32
// Requires: SSE
TEXT ·Float32(SB), NOSPLIT, $0-12
MOVQ i+0(FP), AX
LEAQ f32<>+0(SB), CX
MOVSS (CX)(AX*4), X0
MOVSS X0, ret+8(FP)
RET
DATA f64<>+0(SB)/8, $(0.0)
DATA f64<>+8(SB)/8, $(1.0)
DATA f64<>+16(SB)/8, $(2.0)
DATA f64<>+24(SB)/8, $(3.0)
DATA f64<>+32(SB)/8, $(4.0)
DATA f64<>+40(SB)/8, $(5.0)
DATA f64<>+48(SB)/8, $(6.0)
DATA f64<>+56(SB)/8, $(7.0)
DATA f64<>+64(SB)/8, $(8.0)
DATA f64<>+72(SB)/8, $(9.0)
GLOBL f64<>(SB), RODATA|NOPTR, $80
// func Float64(i int) float64
// Requires: SSE2
TEXT ·Float64(SB), NOSPLIT, $0-16
MOVQ i+0(FP), AX
LEAQ f64<>+0(SB), CX
MOVSD (CX)(AX*8), X0
MOVSD X0, ret+8(FP)
RET

View File

@@ -0,0 +1,27 @@
package issue387
import (
"testing"
)
//go:generate go run asm.go -out issue387.s -stubs stub.go
func TestFloat32(t *testing.T) {
for i := 0; i < 10; i++ {
got := Float32(i)
expect := float32(i)
if got != expect {
t.Fatalf("Float32(%d) = %#v; expect %#v", i, got, expect)
}
}
}
func TestFloat64(t *testing.T) {
for i := 0; i < 10; i++ {
got := Float64(i)
expect := float64(i)
if got != expect {
t.Fatalf("Float64(%d) = %#v; expect %#v", i, got, expect)
}
}
}

View File

@@ -0,0 +1,9 @@
// Code generated by command: go run asm.go -out issue387.s -stubs stub.go. DO NOT EDIT.
package issue387
// Float32 indexes into an array of single-precision integral floats.
func Float32(i int) float32
// Float64 indexes into an array of double-precision integral floats.
func Float64(i int) float64