From d107aa2cd1fdc596b9275a127e6c35cc5f8d32bb Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 15 Dec 2021 13:04:54 -0800 Subject: [PATCH] cmd/compile: upgrade ssa to do (int or float) -> complex Generic instantiations can produce conversions from constant literal ints or floats to complex values. We could constant literals during instantiation, but it is just as easy to upgrade the code generator to do the conversions. Fixes #50193 Change-Id: I24bdc09226c8e868f6282e0e4057ba6c3ad5c41a Reviewed-on: https://go-review.googlesource.com/c/go/+/372514 Trust: Keith Randall Run-TryBot: Keith Randall Trust: Dan Scales Reviewed-by: Dan Scales Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/cmd/compile/internal/ssagen/ssa.go | 57 +++++++++++++++----------- test/typeparam/issue50193.go | 32 +++++++++++++++ test/typeparam/issue50193.out | 6 +++ 3 files changed, 70 insertions(+), 25 deletions(-) create mode 100644 test/typeparam/issue50193.go create mode 100644 test/typeparam/issue50193.out diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 265ef1aab3..0b54925696 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -2446,6 +2446,38 @@ func (s *state) conv(n ir.Node, v *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.newValue1(op, tt, v) } + if ft.IsComplex() && tt.IsComplex() { + var op ssa.Op + if ft.Size() == tt.Size() { + switch ft.Size() { + case 8: + op = ssa.OpRound32F + case 16: + op = ssa.OpRound64F + default: + s.Fatalf("weird complex conversion %v -> %v", ft, tt) + } + } else if ft.Size() == 8 && tt.Size() == 16 { + op = ssa.OpCvt32Fto64F + } else if ft.Size() == 16 && tt.Size() == 8 { + op = ssa.OpCvt64Fto32F + } else { + s.Fatalf("weird complex conversion %v -> %v", ft, tt) + } + ftp := types.FloatForComplex(ft) + ttp := types.FloatForComplex(tt) + return s.newValue2(ssa.OpComplexMake, tt, + s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, v)), + s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, v))) + } + + if tt.IsComplex() { // and ft is not complex + // Needed for generics support - can't happen in normal Go code. + et := types.FloatForComplex(tt) + v = s.conv(n, v, ft, et) + return s.newValue2(ssa.OpComplexMake, tt, v, s.zeroVal(et)) + } + if ft.IsFloat() || tt.IsFloat() { conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}] if s.config.RegSize == 4 && Arch.LinkArch.Family != sys.MIPS && !s.softFloat { @@ -2519,31 +2551,6 @@ func (s *state) conv(n ir.Node, v *ssa.Value, ft, tt *types.Type) *ssa.Value { return nil } - if ft.IsComplex() && tt.IsComplex() { - var op ssa.Op - if ft.Size() == tt.Size() { - switch ft.Size() { - case 8: - op = ssa.OpRound32F - case 16: - op = ssa.OpRound64F - default: - s.Fatalf("weird complex conversion %v -> %v", ft, tt) - } - } else if ft.Size() == 8 && tt.Size() == 16 { - op = ssa.OpCvt32Fto64F - } else if ft.Size() == 16 && tt.Size() == 8 { - op = ssa.OpCvt64Fto32F - } else { - s.Fatalf("weird complex conversion %v -> %v", ft, tt) - } - ftp := types.FloatForComplex(ft) - ttp := types.FloatForComplex(tt) - return s.newValue2(ssa.OpComplexMake, tt, - s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, v)), - s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, v))) - } - s.Fatalf("unhandled OCONV %s -> %s", ft.Kind(), tt.Kind()) return nil } diff --git a/test/typeparam/issue50193.go b/test/typeparam/issue50193.go new file mode 100644 index 0000000000..8dc488244e --- /dev/null +++ b/test/typeparam/issue50193.go @@ -0,0 +1,32 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "constraints" + "fmt" +) + +func zero[T constraints.Complex]() T { + return T(0) +} +func pi[T constraints.Complex]() T { + return T(3.14) +} +func sqrtN1[T constraints.Complex]() T { + return T(-1i) +} + +func main() { + fmt.Println(zero[complex128]()) + fmt.Println(pi[complex128]()) + fmt.Println(sqrtN1[complex128]()) + fmt.Println(zero[complex64]()) + fmt.Println(pi[complex64]()) + fmt.Println(sqrtN1[complex64]()) +} + diff --git a/test/typeparam/issue50193.out b/test/typeparam/issue50193.out new file mode 100644 index 0000000000..68186222c7 --- /dev/null +++ b/test/typeparam/issue50193.out @@ -0,0 +1,6 @@ +(0+0i) +(3.14+0i) +(0-1i) +(0+0i) +(3.14+0i) +(0-1i) -- 2.51.0