From c767d73227704ba4e22e366e89d1885f52d4b6cc Mon Sep 17 00:00:00 2001
From: Matthew Dempsky <mdempsky@google.com>
Date: Fri, 13 Nov 2020 18:33:19 -0800
Subject: [PATCH] [dev.regabi] cmd/compile: remove CTRUNE

Since CL 255217, we've been able to rely on types.UntypedRune to
identify untyped rune literals, rather than needing Mpint.Rune /
CTRUNE. This makes way for switching to using go/constant, which
doesn't have a separate notion of rune constants distinct from integer
constants.

Passes toolstash-check.

Change-Id: I319861f4758aeea17345c101b167cb307e706a0e
Reviewed-on: https://go-review.googlesource.com/c/go/+/272652
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
---
 src/cmd/compile/internal/gc/const.go     | 86 +++++++++---------------
 src/cmd/compile/internal/gc/fmt.go       | 55 ++++++++-------
 src/cmd/compile/internal/gc/iimport.go   |  1 -
 src/cmd/compile/internal/gc/mpint.go     |  5 +-
 src/cmd/compile/internal/gc/noder.go     |  4 +-
 src/cmd/compile/internal/gc/typecheck.go |  2 +-
 src/cmd/compile/internal/gc/walk.go      |  5 +-
 7 files changed, 71 insertions(+), 87 deletions(-)

diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go
index 4e7318cfc6d..326f44a2feb 100644
--- a/src/cmd/compile/internal/gc/const.go
+++ b/src/cmd/compile/internal/gc/const.go
@@ -19,7 +19,6 @@ const (
 	CTxxx Ctype = iota
 
 	CTINT
-	CTRUNE
 	CTFLT
 	CTCPLX
 	CTSTR
@@ -29,7 +28,7 @@ const (
 type Val struct {
 	// U contains one of:
 	// bool     bool when Ctype() == CTBOOL
-	// *Mpint   int when Ctype() == CTINT, rune when Ctype() == CTRUNE
+	// *Mpint   int when Ctype() == CTINT
 	// *Mpflt   float when Ctype() == CTFLT
 	// *Mpcplx  pair of floats when Ctype() == CTCPLX
 	// string   string when Ctype() == CTSTR
@@ -37,7 +36,7 @@ type Val struct {
 }
 
 func (v Val) Ctype() Ctype {
-	switch x := v.U.(type) {
+	switch v.U.(type) {
 	default:
 		Fatalf("unexpected Ctype for %T", v.U)
 		panic("unreachable")
@@ -46,9 +45,6 @@ func (v Val) Ctype() Ctype {
 	case bool:
 		return CTBOOL
 	case *Mpint:
-		if x.Rune {
-			return CTRUNE
-		}
 		return CTINT
 	case *Mpflt:
 		return CTFLT
@@ -384,7 +380,7 @@ func convertVal(v Val, t *types.Type, explicit bool) Val {
 			return v
 		}
 
-	case CTINT, CTRUNE:
+	case CTINT:
 		if explicit && t.IsString() {
 			return tostr(v)
 		}
@@ -449,11 +445,6 @@ func toflt(v Val) Val {
 func toint(v Val) Val {
 	switch u := v.U.(type) {
 	case *Mpint:
-		if u.Rune {
-			i := new(Mpint)
-			i.Set(u)
-			v.U = i
-		}
 
 	case *Mpflt:
 		i := new(Mpint)
@@ -560,11 +551,7 @@ func consttype(n *Node) Ctype {
 }
 
 func Isconst(n *Node, ct Ctype) bool {
-	t := consttype(n)
-
-	// If the caller is asking for CTINT, allow CTRUNE too.
-	// Makes life easier for back ends.
-	return t == ct || (ct == CTINT && t == CTRUNE)
+	return consttype(n) == ct
 }
 
 // evconst rewrites constant expressions into OLITERAL nodes.
@@ -710,7 +697,7 @@ func compareOp(x Val, op Op, y Val) bool {
 			return x != y
 		}
 
-	case CTINT, CTRUNE:
+	case CTINT:
 		x, y := x.U.(*Mpint), y.U.(*Mpint)
 		return cmpZero(x.Cmp(y), op)
 
@@ -784,11 +771,10 @@ Outer:
 			return Val{U: x || y}
 		}
 
-	case CTINT, CTRUNE:
+	case CTINT:
 		x, y := x.U.(*Mpint), y.U.(*Mpint)
 
 		u := new(Mpint)
-		u.Rune = x.Rune || y.Rune
 		u.Set(x)
 		switch op {
 		case OADD:
@@ -879,16 +865,15 @@ func unaryOp(op Op, x Val, t *types.Type) Val {
 	switch op {
 	case OPLUS:
 		switch x.Ctype() {
-		case CTINT, CTRUNE, CTFLT, CTCPLX:
+		case CTINT, CTFLT, CTCPLX:
 			return x
 		}
 
 	case ONEG:
 		switch x.Ctype() {
-		case CTINT, CTRUNE:
+		case CTINT:
 			x := x.U.(*Mpint)
 			u := new(Mpint)
-			u.Rune = x.Rune
 			u.Set(x)
 			u.Neg()
 			return Val{U: u}
@@ -912,11 +897,10 @@ func unaryOp(op Op, x Val, t *types.Type) Val {
 
 	case OBITNOT:
 		switch x.Ctype() {
-		case CTINT, CTRUNE:
+		case CTINT:
 			x := x.U.(*Mpint)
 
 			u := new(Mpint)
-			u.Rune = x.Rune
 			if t.IsSigned() || t.IsUntyped() {
 				// Signed values change sign.
 				u.SetInt64(-1)
@@ -937,14 +921,11 @@ func unaryOp(op Op, x Val, t *types.Type) Val {
 }
 
 func shiftOp(x Val, op Op, y Val) Val {
-	if x.Ctype() != CTRUNE {
-		x = toint(x)
-	}
+	x = toint(x)
 	y = toint(y)
 
 	u := new(Mpint)
 	u.Set(x.U.(*Mpint))
-	u.Rune = x.U.(*Mpint).Rune
 	switch op {
 	case OLSH:
 		u.Lsh(y.U.(*Mpint))
@@ -1010,7 +991,7 @@ func represents(t *types.Type, v Val) bool {
 	}
 
 	vt := idealType(v.Ctype())
-	return t == vt
+	return t == vt || (t == types.UntypedRune && vt == types.UntypedInt)
 }
 
 func setboolconst(n *Node, v bool) {
@@ -1039,8 +1020,6 @@ func idealType(ct Ctype) *types.Type {
 		return types.UntypedBool
 	case CTINT:
 		return types.UntypedInt
-	case CTRUNE:
-		return types.UntypedRune
 	case CTFLT:
 		return types.UntypedFloat
 	case CTCPLX:
@@ -1091,31 +1070,30 @@ func defaultlit2(l *Node, r *Node, force bool) (*Node, *Node) {
 	return l, r
 }
 
-func ctype(t *types.Type) Ctype {
-	switch t {
-	case types.UntypedBool:
-		return CTBOOL
-	case types.UntypedString:
-		return CTSTR
-	case types.UntypedInt:
-		return CTINT
-	case types.UntypedRune:
-		return CTRUNE
-	case types.UntypedFloat:
-		return CTFLT
-	case types.UntypedComplex:
-		return CTCPLX
+func mixUntyped(t1, t2 *types.Type) *types.Type {
+	if t1 == t2 {
+		return t1
+	}
+
+	rank := func(t *types.Type) int {
+		switch t {
+		case types.UntypedInt:
+			return 0
+		case types.UntypedRune:
+			return 1
+		case types.UntypedFloat:
+			return 2
+		case types.UntypedComplex:
+			return 3
+		}
+		Fatalf("bad type %v", t)
+		panic("unreachable")
 	}
-	Fatalf("bad type %v", t)
-	panic("unreachable")
-}
 
-func mixUntyped(t1, t2 *types.Type) *types.Type {
-	t := t1
-	if ctype(t2) > ctype(t1) {
-		t = t2
+	if rank(t2) > rank(t1) {
+		return t2
 	}
-	return t
+	return t1
 }
 
 func defaultType(t *types.Type) *types.Type {
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index 9b57d131b1f..740fdab9774 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -526,28 +526,12 @@ func (v Val) Format(s fmt.State, verb rune) {
 func (v Val) vconv(s fmt.State, flag FmtFlag) {
 	switch u := v.U.(type) {
 	case *Mpint:
-		if !u.Rune {
-			if flag&FmtSharp != 0 {
-				fmt.Fprint(s, u.String())
-				return
-			}
-			fmt.Fprint(s, u.GoString())
+		if flag&FmtSharp != 0 {
+			fmt.Fprint(s, u.String())
 			return
 		}
-
-		switch x := u.Int64(); {
-		case ' ' <= x && x < utf8.RuneSelf && x != '\\' && x != '\'':
-			fmt.Fprintf(s, "'%c'", int(x))
-
-		case 0 <= x && x < 1<<16:
-			fmt.Fprintf(s, "'\\u%04x'", uint(int(x)))
-
-		case 0 <= x && x <= utf8.MaxRune:
-			fmt.Fprintf(s, "'\\U%08x'", uint64(x))
-
-		default:
-			fmt.Fprintf(s, "('\\x00' + %v)", u)
-		}
+		fmt.Fprint(s, u.GoString())
+		return
 
 	case *Mpflt:
 		if flag&FmtSharp != 0 {
@@ -1336,19 +1320,40 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
 			}
 		}
 
+		needUnparen := false
 		if n.Type != nil && !n.Type.IsUntyped() {
 			// Need parens when type begins with what might
 			// be misinterpreted as a unary operator: * or <-.
 			if n.Type.IsPtr() || (n.Type.IsChan() && n.Type.ChanDir() == types.Crecv) {
-				mode.Fprintf(s, "(%v)(%v)", n.Type, n.Val())
-				return
+				mode.Fprintf(s, "(%v)(", n.Type)
 			} else {
-				mode.Fprintf(s, "%v(%v)", n.Type, n.Val())
-				return
+				mode.Fprintf(s, "%v(", n.Type)
 			}
+			needUnparen = true
 		}
 
-		mode.Fprintf(s, "%v", n.Val())
+		if n.Type == types.UntypedRune {
+			u := n.Val().U.(*Mpint)
+			switch x := u.Int64(); {
+			case ' ' <= x && x < utf8.RuneSelf && x != '\\' && x != '\'':
+				fmt.Fprintf(s, "'%c'", int(x))
+
+			case 0 <= x && x < 1<<16:
+				fmt.Fprintf(s, "'\\u%04x'", uint(int(x)))
+
+			case 0 <= x && x <= utf8.MaxRune:
+				fmt.Fprintf(s, "'\\U%08x'", uint64(x))
+
+			default:
+				fmt.Fprintf(s, "('\\x00' + %v)", u)
+			}
+		} else {
+			mode.Fprintf(s, "%v", n.Val())
+		}
+
+		if needUnparen {
+			mode.Fprintf(s, ")")
+		}
 
 	// Special case: name used as local variable in export.
 	// _ becomes ~b%d internally; print as _ for export
diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go
index ac565a6632c..fc6b7ecb9ff 100644
--- a/src/cmd/compile/internal/gc/iimport.go
+++ b/src/cmd/compile/internal/gc/iimport.go
@@ -363,7 +363,6 @@ func (p *importReader) value(typ *types.Type) (v Val) {
 		v.U = p.string()
 	case CTINT:
 		x := new(Mpint)
-		x.Rune = typ == types.UntypedRune
 		p.mpint(&x.Val, typ)
 		v.U = x
 	case CTFLT:
diff --git a/src/cmd/compile/internal/gc/mpint.go b/src/cmd/compile/internal/gc/mpint.go
index 79eb60e65d2..199b2659d15 100644
--- a/src/cmd/compile/internal/gc/mpint.go
+++ b/src/cmd/compile/internal/gc/mpint.go
@@ -13,9 +13,8 @@ import (
 
 // Mpint represents an integer constant.
 type Mpint struct {
-	Val  big.Int
-	Ovf  bool // set if Val overflowed compiler limit (sticky)
-	Rune bool // set if syntax indicates default type rune
+	Val big.Int
+	Ovf bool // set if Val overflowed compiler limit (sticky)
 }
 
 func (a *Mpint) SetOverflow() {
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index 27bc9b5629e..303b04cd46e 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -656,6 +656,9 @@ func (p *noder) expr(expr syntax.Expr) *Node {
 		return p.mkname(expr)
 	case *syntax.BasicLit:
 		n := nodlit(p.basicLit(expr))
+		if expr.Kind == syntax.RuneLit {
+			n.Type = types.UntypedRune
+		}
 		n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error
 		return n
 	case *syntax.CompositeLit:
@@ -1428,7 +1431,6 @@ func (p *noder) basicLit(lit *syntax.BasicLit) Val {
 
 	case syntax.RuneLit:
 		x := new(Mpint)
-		x.Rune = true
 		if !lit.Bad {
 			u, _ := strconv.Unquote(s)
 			var r rune
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 443a3f7827d..3fb59c8debf 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -3724,7 +3724,7 @@ func checkmake(t *types.Type, arg string, np **Node) bool {
 	// Do range checks for constants before defaultlit
 	// to avoid redundant "constant NNN overflows int" errors.
 	switch consttype(n) {
-	case CTINT, CTRUNE, CTFLT, CTCPLX:
+	case CTINT, CTFLT, CTCPLX:
 		v := toint(n.Val()).U.(*Mpint)
 		if v.CmpInt64(0) < 0 {
 			yyerror("negative %s argument in make(%v)", arg, t)
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index ac43a8e1bea..e7351d1792a 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1931,10 +1931,11 @@ func walkprint(nn *Node, init *Nodes) *Node {
 	calls := []*Node{mkcall("printlock", nil, init)}
 	for i, n := range nn.List.Slice() {
 		if n.Op == OLITERAL {
-			switch n.Val().Ctype() {
-			case CTRUNE:
+			if n.Type == types.UntypedRune {
 				n = defaultlit(n, types.Runetype)
+			}
 
+			switch n.Val().Ctype() {
 			case CTINT:
 				n = defaultlit(n, types.Types[TINT64])
 
-- 
GitLab