Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[dev.unified] cmd/compile: extract rtype code from walk
This CL removes (almost*) all reflectdata.{TypePtr,ITabAddr} calls from package walk. This will allow us to next start adding RType/ITab fields to IR nodes directly, and have the helpers start returning them when available instead. The one survining ITabAddr call is due to ODOTTYPE{,2}, but we already have ODYNAMICDOTTYPE{,2}, which I plan to have Unified IR always use. (Longer term, once the Go 1.18 frontend is gone, we can get rid of ODOTTYPE*, and rename ODYNAMICDOTTYPE*.) Passes toolstash -cmp. Change-Id: I5e00da06a93d069abf383d7628e692dd7fd2a1c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/413356 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
- Loading branch information
Showing
9 changed files
with
225 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
// Copyright 2022 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 reflectdata | ||
|
||
import ( | ||
"cmd/compile/internal/base" | ||
"cmd/compile/internal/ir" | ||
"cmd/compile/internal/types" | ||
"cmd/internal/src" | ||
) | ||
|
||
// assertOp asserts that n is an op. | ||
func assertOp(n ir.Node, op ir.Op) { | ||
base.AssertfAt(n.Op() == op, n.Pos(), "want %v, have %v", op, n) | ||
} | ||
|
||
// assertOp2 asserts that n is an op1 or op2. | ||
func assertOp2(n ir.Node, op1, op2 ir.Op) { | ||
base.AssertfAt(n.Op() == op1 || n.Op() == op2, n.Pos(), "want %v or %v, have %v", op1, op2, n) | ||
} | ||
|
||
// kindRType asserts that typ has the given kind, and returns an | ||
// expression that yields the *runtime._type value representing typ. | ||
func kindRType(pos src.XPos, typ *types.Type, k types.Kind) ir.Node { | ||
base.AssertfAt(typ.Kind() == k, pos, "want %v type, have %v", k, typ) | ||
return TypePtrAt(pos, typ) | ||
} | ||
|
||
// mapRType asserts that typ is a map type, and returns an expression | ||
// that yields the *runtime._type value representing typ. | ||
func mapRType(pos src.XPos, typ *types.Type) ir.Node { | ||
return kindRType(pos, typ, types.TMAP) | ||
} | ||
|
||
// chanRType asserts that typ is a map type, and returns an expression | ||
// that yields the *runtime._type value representing typ. | ||
func chanRType(pos src.XPos, typ *types.Type) ir.Node { | ||
return kindRType(pos, typ, types.TCHAN) | ||
} | ||
|
||
// sliceElemRType asserts that typ is a slice type, and returns an | ||
// expression that yields the *runtime._type value representing typ's | ||
// element type. | ||
func sliceElemRType(pos src.XPos, typ *types.Type) ir.Node { | ||
base.AssertfAt(typ.IsSlice(), pos, "want slice type, have %v", typ) | ||
return TypePtrAt(pos, typ.Elem()) | ||
} | ||
|
||
// concreteRType asserts that typ is not an interface type, and | ||
// returns an expression that yields the *runtime._type value | ||
// representing typ. | ||
func concreteRType(pos src.XPos, typ *types.Type) ir.Node { | ||
base.AssertfAt(!typ.IsInterface(), pos, "want non-interface type, have %v", typ) | ||
return TypePtrAt(pos, typ) | ||
} | ||
|
||
// AppendElemRType asserts that n is an "append" operation, and | ||
// returns an expression that yields the *runtime._type value | ||
// representing the result slice type's element type. | ||
func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node { | ||
assertOp(n, ir.OAPPEND) | ||
return sliceElemRType(pos, n.Type()) | ||
} | ||
|
||
// CompareRType asserts that n is a comparison (== or !=) operation | ||
// between expressions of interface and non-interface type, and | ||
// returns an expression that yields the *runtime._type value | ||
// representing the non-interface type. | ||
func CompareRType(pos src.XPos, n *ir.BinaryExpr) ir.Node { | ||
assertOp2(n, ir.OEQ, ir.ONE) | ||
base.AssertfAt(n.X.Type().IsInterface() != n.Y.Type().IsInterface(), n.Pos(), "expect mixed interface and non-interface, have %L and %L", n.X, n.Y) | ||
typ := n.X.Type() | ||
if typ.IsInterface() { | ||
typ = n.Y.Type() | ||
} | ||
return concreteRType(pos, typ) | ||
} | ||
|
||
// ConvIfaceTypeWord asserts that n is conversion to interface type, | ||
// and returns an expression that yields the *runtime._type or | ||
// *runtime.itab value necessary for implementing the conversion. | ||
// | ||
// - *runtime._type for the destination type, for I2I conversions | ||
// - *runtime.itab, for T2I conversions | ||
// - *runtime._type for the source type, for T2E conversions | ||
func ConvIfaceTypeWord(pos src.XPos, n *ir.ConvExpr) ir.Node { | ||
assertOp(n, ir.OCONVIFACE) | ||
src, dst := n.X.Type(), n.Type() | ||
base.AssertfAt(dst.IsInterface(), n.Pos(), "want interface type, have %L", n) | ||
if dst.IsEmptyInterface() { | ||
return concreteRType(pos, src) // direct eface construction | ||
} | ||
if !src.IsInterface() { | ||
return ITabAddr(src, dst) // direct iface construction | ||
} | ||
return TypePtrAt(pos, dst) // convI2I | ||
} | ||
|
||
// ConvIfaceDataWordRType asserts that n is a conversion from | ||
// non-interface type to interface type (or OCONVIDATA operation), and | ||
// returns an expression that yields the *runtime._type for copying | ||
// the convertee value to the heap. | ||
func ConvIfaceDataWordRType(pos src.XPos, n *ir.ConvExpr) ir.Node { | ||
assertOp2(n, ir.OCONVIFACE, ir.OCONVIDATA) | ||
return concreteRType(pos, n.X.Type()) | ||
} | ||
|
||
// CopyElemRType asserts that n is a "copy" operation, and returns an | ||
// expression that yields the *runtime._type value representing the | ||
// destination slice type's element type. | ||
func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node { | ||
assertOp(n, ir.OCOPY) | ||
return sliceElemRType(pos, n.X.Type()) | ||
} | ||
|
||
// DeleteMapRType asserts that n is a "delete" operation, and returns | ||
// an expression that yields the *runtime._type value representing the | ||
// map type. | ||
func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node { | ||
assertOp(n, ir.ODELETE) | ||
return mapRType(pos, n.Args[0].Type()) | ||
} | ||
|
||
// IndexMapRType asserts that n is a map index operation, and returns | ||
// an expression that yields the *runtime._type value representing the | ||
// map type. | ||
func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node { | ||
assertOp(n, ir.OINDEXMAP) | ||
return mapRType(pos, n.X.Type()) | ||
} | ||
|
||
// MakeChanRType asserts that n is a "make" operation for a channel | ||
// type, and returns an expression that yields the *runtime._type | ||
// value representing that channel type. | ||
func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node { | ||
assertOp(n, ir.OMAKECHAN) | ||
return chanRType(pos, n.Type()) | ||
} | ||
|
||
// MakeMapRType asserts that n is a "make" operation for a map type, | ||
// and returns an expression that yields the *runtime._type value | ||
// representing that map type. | ||
func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node { | ||
assertOp(n, ir.OMAKEMAP) | ||
return mapRType(pos, n.Type()) | ||
} | ||
|
||
// MakeSliceElemRType asserts that n is a "make" operation for a slice | ||
// type, and returns an expression that yields the *runtime._type | ||
// value representing that slice type's element type. | ||
func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node { | ||
assertOp2(n, ir.OMAKESLICE, ir.OMAKESLICECOPY) | ||
return sliceElemRType(pos, n.Type()) | ||
} | ||
|
||
// RangeMapRType asserts that n is a "range" loop over a map value, | ||
// and returns an expression that yields the *runtime._type value | ||
// representing that map type. | ||
func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node { | ||
assertOp(n, ir.ORANGE) | ||
return mapRType(pos, n.X.Type()) | ||
} | ||
|
||
// UnsafeSliceElemRType asserts that n is an "unsafe.Slice" operation, | ||
// and returns an expression that yields the *runtime._type value | ||
// representing the result slice type's element type. | ||
func UnsafeSliceElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node { | ||
assertOp(n, ir.OUNSAFESLICE) | ||
return sliceElemRType(pos, n.Type()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.