[dev.typeparams] cmd/compile: add and use ir.RawOrigExpr

This CL adds ir.RawOrigExpr, which can be used to represent arbitrary
constant expressions without needing to build and carry around an
entire IR representation of the original expression. It also allows
distinguishing how the constant was originally written by the
user (e.g., "0xff" vs "255").

This CL then also updates irgen to make use of this functionality for
expressions that were constant folded by types2.

Change-Id: I41e04e228e715ae2735c357b75633a2d08ee7021
Reviewed-on: https://go-review.googlesource.com/c/go/+/323210
Trust: Matthew Dempsky <mdempsky@google.com>
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
Matthew Dempsky 2021-05-27 02:50:17 -07:00
parent de5d1aca5e
commit ea522bc546
6 changed files with 107 additions and 7 deletions

View file

@ -5,6 +5,8 @@
package noder
import (
"fmt"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/syntax"
@ -15,6 +17,8 @@ import (
)
func (g *irgen) expr(expr syntax.Expr) ir.Node {
expr = unparen(expr) // skip parens; unneeded after parse+typecheck
if expr == nil {
return nil
}
@ -67,7 +71,9 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node {
// Constant expression.
if tv.Value != nil {
return Const(g.pos(expr), g.typ(typ), tv.Value)
typ := g.typ(typ)
value := FixValue(typ, tv.Value)
return OrigConst(g.pos(expr), typ, value, constExprOp(expr), syntax.String(expr))
}
n := g.expr0(typ, expr)
@ -161,9 +167,6 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
typed(g.typ(typ), n)
return n
case *syntax.ParenExpr:
return g.expr(expr.X) // skip parens; unneeded after parse+typecheck
case *syntax.SelectorExpr:
// Qualified identifier.
if name, ok := expr.X.(*syntax.Name); ok {
@ -317,13 +320,17 @@ func getTargs(selinfo *types2.Selection) []types2.Type {
}
func (g *irgen) exprList(expr syntax.Expr) []ir.Node {
return g.exprs(unpackListExpr(expr))
}
func unpackListExpr(expr syntax.Expr) []syntax.Expr {
switch expr := expr.(type) {
case nil:
return nil
case *syntax.ListExpr:
return g.exprs(expr.ElemList)
return expr.ElemList
default:
return []ir.Node{g.expr(expr)}
return []syntax.Expr{expr}
}
}
@ -402,3 +409,35 @@ func (g *irgen) typeExpr(typ syntax.Expr) *types.Type {
}
return n.Type()
}
// constExprOp returns an ir.Op that represents the outermost
// operation of the given constant expression. It's intended for use
// with ir.RawOrigExpr.
func constExprOp(expr syntax.Expr) ir.Op {
switch expr := expr.(type) {
default:
panic(fmt.Sprintf("%s: unexpected expression: %T", expr.Pos(), expr))
case *syntax.BasicLit:
return ir.OLITERAL
case *syntax.Name, *syntax.SelectorExpr:
return ir.ONAME
case *syntax.CallExpr:
return ir.OCALL
case *syntax.Operation:
if expr.Y == nil {
return unOps[expr.Op]
}
return binOps[expr.Op]
}
}
func unparen(expr syntax.Expr) syntax.Expr {
for {
paren, ok := expr.(*syntax.ParenExpr)
if !ok {
return expr
}
expr = paren.X
}
}