diff options
author | Keith Randall <khr@golang.org> | 2021-12-15 13:04:54 -0800 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2021-12-16 00:33:58 +0000 |
commit | d107aa2cd1fdc596b9275a127e6c35cc5f8d32bb (patch) | |
tree | cea2411f97ea73d29d3eddc4c17a6e49a8319cd4 /src/cmd/compile | |
parent | 6e7c6912186b6c91fff332ef473409a8e960c519 (diff) | |
download | go-d107aa2cd1fdc596b9275a127e6c35cc5f8d32bb.tar.gz go-d107aa2cd1fdc596b9275a127e6c35cc5f8d32bb.zip |
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 <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Dan Scales <danscales@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/cmd/compile')
-rw-r--r-- | src/cmd/compile/internal/ssagen/ssa.go | 57 |
1 files changed, 32 insertions, 25 deletions
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 } |