mirror of
https://github.com/golang/go
synced 2024-11-11 20:01:37 -07:00
[dev.regabi] cmd/compile: refactoring prep for ConstExpr
The next CL adds ConstExpr, which is a more memory efficient representation for constant expressions than Name. However, currently a bunch of Val helper methods are defined on Name. This CL changes them into standalone functions that work with any Node.Val implementation. There's also an existing standalone function named Int64Val, which takes a Type argument to specify what type of integer is expected. So to avoid collisions, this CL renames it to IntVal. Passes buildall w/ toolstash -cmp. [git-generate] cd src/cmd/compile/internal/ir rf 'mv Int64Val IntVal' sed -i -E -e 's/\(n \*Name\) (CanInt64|((I|Ui)nt64|Bool|String)Val)\(/\1(n Node/' name.go cd ../gc rf ' ex { import "cmd/compile/internal/ir" var n ir.Node n.CanInt64() -> ir.CanInt64(n) n.Int64Val() -> ir.Int64Val(n) n.Uint64Val() -> ir.Uint64Val(n) n.BoolVal() -> ir.BoolVal(n) n.StringVal() -> ir.StringVal(n) } ' cd ../ir rf ' mv CanInt64 Int64Val Uint64Val BoolVal StringVal val.go rm Node.CanInt64 Node.Int64Val Node.Uint64Val Node.BoolVal Node.StringVal ' Change-Id: I003140bda1690d770fd608bdd087e6d4ff00fb1f Reviewed-on: https://go-review.googlesource.com/c/go/+/275032 Trust: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
7e81135be7
commit
beb5e05404
@ -526,7 +526,7 @@ func evalConst(n ir.Node) ir.Node {
|
|||||||
if need == 1 {
|
if need == 1 {
|
||||||
var strs []string
|
var strs []string
|
||||||
for _, c := range s {
|
for _, c := range s {
|
||||||
strs = append(strs, c.StringVal())
|
strs = append(strs, ir.StringVal(c))
|
||||||
}
|
}
|
||||||
return origConst(n, constant.MakeString(strings.Join(strs, "")))
|
return origConst(n, constant.MakeString(strings.Join(strs, "")))
|
||||||
}
|
}
|
||||||
@ -537,7 +537,7 @@ func evalConst(n ir.Node) ir.Node {
|
|||||||
var strs []string
|
var strs []string
|
||||||
i2 := i
|
i2 := i
|
||||||
for i2 < len(s) && ir.IsConst(s[i2], constant.String) {
|
for i2 < len(s) && ir.IsConst(s[i2], constant.String) {
|
||||||
strs = append(strs, s[i2].StringVal())
|
strs = append(strs, ir.StringVal(s[i2]))
|
||||||
i2++
|
i2++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,7 +558,7 @@ func evalConst(n ir.Node) ir.Node {
|
|||||||
switch nl.Type().Kind() {
|
switch nl.Type().Kind() {
|
||||||
case types.TSTRING:
|
case types.TSTRING:
|
||||||
if ir.IsConst(nl, constant.String) {
|
if ir.IsConst(nl, constant.String) {
|
||||||
return origIntConst(n, int64(len(nl.StringVal())))
|
return origIntConst(n, int64(len(ir.StringVal(nl))))
|
||||||
}
|
}
|
||||||
case types.TARRAY:
|
case types.TARRAY:
|
||||||
if !hascallchan(nl) {
|
if !hascallchan(nl) {
|
||||||
@ -780,7 +780,7 @@ func indexconst(n ir.Node) int64 {
|
|||||||
if doesoverflow(v, types.Types[types.TINT]) {
|
if doesoverflow(v, types.Types[types.TINT]) {
|
||||||
return -2
|
return -2
|
||||||
}
|
}
|
||||||
return ir.Int64Val(types.Types[types.TINT], v)
|
return ir.IntVal(types.Types[types.TINT], v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isGoConst reports whether n is a Go language constant (as opposed to a
|
// isGoConst reports whether n is a Go language constant (as opposed to a
|
||||||
|
@ -1769,7 +1769,7 @@ func heapAllocReason(n ir.Node) string {
|
|||||||
if !smallintconst(r) {
|
if !smallintconst(r) {
|
||||||
return "non-constant size"
|
return "non-constant size"
|
||||||
}
|
}
|
||||||
if t := n.Type(); t.Elem().Width != 0 && r.Int64Val() >= maxImplicitStackVarSize/t.Elem().Width {
|
if t := n.Type(); t.Elem().Width != 0 && ir.Int64Val(r) >= maxImplicitStackVarSize/t.Elem().Width {
|
||||||
return "too large for stack"
|
return "too large for stack"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -807,7 +807,7 @@ func (p *noder) sum(x syntax.Expr) ir.Node {
|
|||||||
n := p.expr(x)
|
n := p.expr(x)
|
||||||
if ir.IsConst(n, constant.String) && n.Sym() == nil {
|
if ir.IsConst(n, constant.String) && n.Sym() == nil {
|
||||||
nstr = n
|
nstr = n
|
||||||
chunks = append(chunks, nstr.StringVal())
|
chunks = append(chunks, ir.StringVal(nstr))
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := len(adds) - 1; i >= 0; i-- {
|
for i := len(adds) - 1; i >= 0; i-- {
|
||||||
@ -817,12 +817,12 @@ func (p *noder) sum(x syntax.Expr) ir.Node {
|
|||||||
if ir.IsConst(r, constant.String) && r.Sym() == nil {
|
if ir.IsConst(r, constant.String) && r.Sym() == nil {
|
||||||
if nstr != nil {
|
if nstr != nil {
|
||||||
// Collapse r into nstr instead of adding to n.
|
// Collapse r into nstr instead of adding to n.
|
||||||
chunks = append(chunks, r.StringVal())
|
chunks = append(chunks, ir.StringVal(r))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
nstr = r
|
nstr = r
|
||||||
chunks = append(chunks, nstr.StringVal())
|
chunks = append(chunks, ir.StringVal(nstr))
|
||||||
} else {
|
} else {
|
||||||
if len(chunks) > 1 {
|
if len(chunks) > 1 {
|
||||||
nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
|
nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
|
||||||
|
@ -263,7 +263,7 @@ func dumpGlobalConst(n ir.Node) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, typesymname(t), ir.Int64Val(t, v))
|
base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, typesymname(t), ir.IntVal(t, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpglobls() {
|
func dumpglobls() {
|
||||||
@ -598,7 +598,7 @@ func litsym(n, c ir.Node, wid int) {
|
|||||||
s.WriteInt(base.Ctxt, n.Offset(), wid, i)
|
s.WriteInt(base.Ctxt, n.Offset(), wid, i)
|
||||||
|
|
||||||
case constant.Int:
|
case constant.Int:
|
||||||
s.WriteInt(base.Ctxt, n.Offset(), wid, ir.Int64Val(n.Type(), u))
|
s.WriteInt(base.Ctxt, n.Offset(), wid, ir.IntVal(n.Type(), u))
|
||||||
|
|
||||||
case constant.Float:
|
case constant.Float:
|
||||||
f, _ := constant.Float64Val(u)
|
f, _ := constant.Float64Val(u)
|
||||||
|
@ -1107,7 +1107,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
|
|||||||
haslit := false
|
haslit := false
|
||||||
for _, n1 := range n.List().Slice() {
|
for _, n1 := range n.List().Slice() {
|
||||||
hasbyte = hasbyte || n1.Op() == ir.OBYTES2STR
|
hasbyte = hasbyte || n1.Op() == ir.OBYTES2STR
|
||||||
haslit = haslit || n1.Op() == ir.OLITERAL && len(n1.StringVal()) != 0
|
haslit = haslit || n1.Op() == ir.OLITERAL && len(ir.StringVal(n1)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if haslit && hasbyte {
|
if haslit && hasbyte {
|
||||||
@ -1278,7 +1278,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
|
|||||||
var t *types.Type
|
var t *types.Type
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case ir.OSLICELIT:
|
case ir.OSLICELIT:
|
||||||
t = types.NewArray(n.Type().Elem(), n.Right().Int64Val())
|
t = types.NewArray(n.Type().Elem(), ir.Int64Val(n.Right()))
|
||||||
case ir.OCALLPART:
|
case ir.OCALLPART:
|
||||||
t = partialCallType(n)
|
t = partialCallType(n)
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ func (s *InitSchedule) staticcopy(l ir.Node, r ir.Node) bool {
|
|||||||
case ir.OSLICELIT:
|
case ir.OSLICELIT:
|
||||||
// copy slice
|
// copy slice
|
||||||
a := s.inittemps[r]
|
a := s.inittemps[r]
|
||||||
slicesym(l, a, r.Right().Int64Val())
|
slicesym(l, a, ir.Int64Val(r.Right()))
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case ir.OARRAYLIT, ir.OSTRUCTLIT:
|
case ir.OARRAYLIT, ir.OSTRUCTLIT:
|
||||||
@ -213,7 +213,7 @@ func (s *InitSchedule) staticassign(l ir.Node, r ir.Node) bool {
|
|||||||
|
|
||||||
case ir.OSTR2BYTES:
|
case ir.OSTR2BYTES:
|
||||||
if l.Class() == ir.PEXTERN && r.Left().Op() == ir.OLITERAL {
|
if l.Class() == ir.PEXTERN && r.Left().Op() == ir.OLITERAL {
|
||||||
sval := r.Left().StringVal()
|
sval := ir.StringVal(r.Left())
|
||||||
slicebytes(l, sval)
|
slicebytes(l, sval)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -221,7 +221,7 @@ func (s *InitSchedule) staticassign(l ir.Node, r ir.Node) bool {
|
|||||||
case ir.OSLICELIT:
|
case ir.OSLICELIT:
|
||||||
s.initplan(r)
|
s.initplan(r)
|
||||||
// Init slice.
|
// Init slice.
|
||||||
bound := r.Right().Int64Val()
|
bound := ir.Int64Val(r.Right())
|
||||||
ta := types.NewArray(r.Type().Elem(), bound)
|
ta := types.NewArray(r.Type().Elem(), bound)
|
||||||
ta.SetNoalg(true)
|
ta.SetNoalg(true)
|
||||||
a := staticname(ta)
|
a := staticname(ta)
|
||||||
@ -418,7 +418,7 @@ func getdyn(n ir.Node, top bool) initGenType {
|
|||||||
if !top {
|
if !top {
|
||||||
return initDynamic
|
return initDynamic
|
||||||
}
|
}
|
||||||
if n.Right().Int64Val()/4 > int64(n.List().Len()) {
|
if ir.Int64Val(n.Right())/4 > int64(n.List().Len()) {
|
||||||
// <25% of entries have explicit values.
|
// <25% of entries have explicit values.
|
||||||
// Very rough estimation, it takes 4 bytes of instructions
|
// Very rough estimation, it takes 4 bytes of instructions
|
||||||
// to initialize 1 byte of result. So don't use a static
|
// to initialize 1 byte of result. So don't use a static
|
||||||
@ -594,12 +594,12 @@ func isSmallSliceLit(n ir.Node) bool {
|
|||||||
|
|
||||||
r := n.Right()
|
r := n.Right()
|
||||||
|
|
||||||
return smallintconst(r) && (n.Type().Elem().Width == 0 || r.Int64Val() <= smallArrayBytes/n.Type().Elem().Width)
|
return smallintconst(r) && (n.Type().Elem().Width == 0 || ir.Int64Val(r) <= smallArrayBytes/n.Type().Elem().Width)
|
||||||
}
|
}
|
||||||
|
|
||||||
func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) {
|
func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) {
|
||||||
// make an array type corresponding the number of elements we have
|
// make an array type corresponding the number of elements we have
|
||||||
t := types.NewArray(n.Type().Elem(), n.Right().Int64Val())
|
t := types.NewArray(n.Type().Elem(), ir.Int64Val(n.Right()))
|
||||||
dowidth(t)
|
dowidth(t)
|
||||||
|
|
||||||
if ctxt == inNonInitFunction {
|
if ctxt == inNonInitFunction {
|
||||||
@ -997,7 +997,7 @@ func oaslit(n ir.Node, init *ir.Nodes) bool {
|
|||||||
|
|
||||||
func getlit(lit ir.Node) int {
|
func getlit(lit ir.Node) int {
|
||||||
if smallintconst(lit) {
|
if smallintconst(lit) {
|
||||||
return int(lit.Int64Val())
|
return int(ir.Int64Val(lit))
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
@ -1271,7 +1271,7 @@ func (s *state) stmt(n ir.Node) {
|
|||||||
// We're assigning a slicing operation back to its source.
|
// We're assigning a slicing operation back to its source.
|
||||||
// Don't write back fields we aren't changing. See issue #14855.
|
// Don't write back fields we aren't changing. See issue #14855.
|
||||||
i, j, k := rhs.SliceBounds()
|
i, j, k := rhs.SliceBounds()
|
||||||
if i != nil && (i.Op() == ir.OLITERAL && i.Val().Kind() == constant.Int && i.Int64Val() == 0) {
|
if i != nil && (i.Op() == ir.OLITERAL && i.Val().Kind() == constant.Int && ir.Int64Val(i) == 0) {
|
||||||
// [0:...] is the same as [:...]
|
// [0:...] is the same as [:...]
|
||||||
i = nil
|
i = nil
|
||||||
}
|
}
|
||||||
@ -1301,7 +1301,7 @@ func (s *state) stmt(n ir.Node) {
|
|||||||
case ir.OIF:
|
case ir.OIF:
|
||||||
if ir.IsConst(n.Left(), constant.Bool) {
|
if ir.IsConst(n.Left(), constant.Bool) {
|
||||||
s.stmtList(n.Left().Init())
|
s.stmtList(n.Left().Init())
|
||||||
if n.Left().BoolVal() {
|
if ir.BoolVal(n.Left()) {
|
||||||
s.stmtList(n.Body())
|
s.stmtList(n.Body())
|
||||||
} else {
|
} else {
|
||||||
s.stmtList(n.Rlist())
|
s.stmtList(n.Rlist())
|
||||||
@ -2041,7 +2041,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
|
|||||||
case ir.OLITERAL:
|
case ir.OLITERAL:
|
||||||
switch u := n.Val(); u.Kind() {
|
switch u := n.Val(); u.Kind() {
|
||||||
case constant.Int:
|
case constant.Int:
|
||||||
i := ir.Int64Val(n.Type(), u)
|
i := ir.IntVal(n.Type(), u)
|
||||||
switch n.Type().Size() {
|
switch n.Type().Size() {
|
||||||
case 1:
|
case 1:
|
||||||
return s.constInt8(n.Type(), int8(i))
|
return s.constInt8(n.Type(), int8(i))
|
||||||
@ -2624,7 +2624,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
|
|||||||
// Replace "abc"[1] with 'b'.
|
// Replace "abc"[1] with 'b'.
|
||||||
// Delayed until now because "abc"[1] is not an ideal constant.
|
// Delayed until now because "abc"[1] is not an ideal constant.
|
||||||
// See test/fixedbugs/issue11370.go.
|
// See test/fixedbugs/issue11370.go.
|
||||||
return s.newValue0I(ssa.OpConst8, types.Types[types.TUINT8], int64(int8(n.Left().StringVal()[n.Right().Int64Val()])))
|
return s.newValue0I(ssa.OpConst8, types.Types[types.TUINT8], int64(int8(ir.StringVal(n.Left())[ir.Int64Val(n.Right())])))
|
||||||
}
|
}
|
||||||
a := s.expr(n.Left())
|
a := s.expr(n.Left())
|
||||||
i := s.expr(n.Right())
|
i := s.expr(n.Right())
|
||||||
@ -2633,7 +2633,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
|
|||||||
ptrtyp := s.f.Config.Types.BytePtr
|
ptrtyp := s.f.Config.Types.BytePtr
|
||||||
ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
|
ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
|
||||||
if ir.IsConst(n.Right(), constant.Int) {
|
if ir.IsConst(n.Right(), constant.Int) {
|
||||||
ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, n.Right().Int64Val(), ptr)
|
ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, ir.Int64Val(n.Right()), ptr)
|
||||||
} else {
|
} else {
|
||||||
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
|
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
|
||||||
}
|
}
|
||||||
|
@ -365,8 +365,8 @@ func (s *exprSwitch) flush() {
|
|||||||
// all we need here is consistency. We respect this
|
// all we need here is consistency. We respect this
|
||||||
// sorting below.
|
// sorting below.
|
||||||
sort.Slice(cc, func(i, j int) bool {
|
sort.Slice(cc, func(i, j int) bool {
|
||||||
si := cc[i].lo.StringVal()
|
si := ir.StringVal(cc[i].lo)
|
||||||
sj := cc[j].lo.StringVal()
|
sj := ir.StringVal(cc[j].lo)
|
||||||
if len(si) != len(sj) {
|
if len(si) != len(sj) {
|
||||||
return len(si) < len(sj)
|
return len(si) < len(sj)
|
||||||
}
|
}
|
||||||
@ -375,7 +375,7 @@ func (s *exprSwitch) flush() {
|
|||||||
|
|
||||||
// runLen returns the string length associated with a
|
// runLen returns the string length associated with a
|
||||||
// particular run of exprClauses.
|
// particular run of exprClauses.
|
||||||
runLen := func(run []exprClause) int64 { return int64(len(run[0].lo.StringVal())) }
|
runLen := func(run []exprClause) int64 { return int64(len(ir.StringVal(run[0].lo))) }
|
||||||
|
|
||||||
// Collapse runs of consecutive strings with the same length.
|
// Collapse runs of consecutive strings with the same length.
|
||||||
var runs [][]exprClause
|
var runs [][]exprClause
|
||||||
@ -411,7 +411,7 @@ func (s *exprSwitch) flush() {
|
|||||||
merged := cc[:1]
|
merged := cc[:1]
|
||||||
for _, c := range cc[1:] {
|
for _, c := range cc[1:] {
|
||||||
last := &merged[len(merged)-1]
|
last := &merged[len(merged)-1]
|
||||||
if last.jmp == c.jmp && last.hi.Int64Val()+1 == c.lo.Int64Val() {
|
if last.jmp == c.jmp && ir.Int64Val(last.hi)+1 == ir.Int64Val(c.lo) {
|
||||||
last.hi = c.lo
|
last.hi = c.lo
|
||||||
} else {
|
} else {
|
||||||
merged = append(merged, c)
|
merged = append(merged, c)
|
||||||
@ -446,7 +446,7 @@ func (c *exprClause) test(exprname ir.Node) ir.Node {
|
|||||||
|
|
||||||
// Optimize "switch true { ...}" and "switch false { ... }".
|
// Optimize "switch true { ...}" and "switch false { ... }".
|
||||||
if ir.IsConst(exprname, constant.Bool) && !c.lo.Type().IsInterface() {
|
if ir.IsConst(exprname, constant.Bool) && !c.lo.Type().IsInterface() {
|
||||||
if exprname.BoolVal() {
|
if ir.BoolVal(exprname) {
|
||||||
return c.lo
|
return c.lo
|
||||||
} else {
|
} else {
|
||||||
return ir.NodAt(c.pos, ir.ONOT, c.lo, nil)
|
return ir.NodAt(c.pos, ir.ONOT, c.lo, nil)
|
||||||
|
@ -1054,8 +1054,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
|
|||||||
base.Errorf("invalid %s index %v (index must be non-negative)", why, n.Right())
|
base.Errorf("invalid %s index %v (index must be non-negative)", why, n.Right())
|
||||||
} else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) {
|
} else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) {
|
||||||
base.Errorf("invalid array index %v (out of bounds for %d-element array)", n.Right(), t.NumElem())
|
base.Errorf("invalid array index %v (out of bounds for %d-element array)", n.Right(), t.NumElem())
|
||||||
} else if ir.IsConst(n.Left(), constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(n.Left().StringVal())))) {
|
} else if ir.IsConst(n.Left(), constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(ir.StringVal(n.Left()))))) {
|
||||||
base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Right(), len(n.Left().StringVal()))
|
base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Right(), len(ir.StringVal(n.Left())))
|
||||||
} else if doesoverflow(x, types.Types[types.TINT]) {
|
} else if doesoverflow(x, types.Types[types.TINT]) {
|
||||||
base.Errorf("invalid %s index %v (index too large)", why, n.Right())
|
base.Errorf("invalid %s index %v (index too large)", why, n.Right())
|
||||||
}
|
}
|
||||||
@ -1146,11 +1146,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
|
|||||||
l = defaultlit(l, types.Types[types.TINT])
|
l = defaultlit(l, types.Types[types.TINT])
|
||||||
c = defaultlit(c, types.Types[types.TINT])
|
c = defaultlit(c, types.Types[types.TINT])
|
||||||
|
|
||||||
if ir.IsConst(l, constant.Int) && l.Int64Val() < 0 {
|
if ir.IsConst(l, constant.Int) && ir.Int64Val(l) < 0 {
|
||||||
base.Fatalf("len for OSLICEHEADER must be non-negative")
|
base.Fatalf("len for OSLICEHEADER must be non-negative")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ir.IsConst(c, constant.Int) && c.Int64Val() < 0 {
|
if ir.IsConst(c, constant.Int) && ir.Int64Val(c) < 0 {
|
||||||
base.Fatalf("cap for OSLICEHEADER must be non-negative")
|
base.Fatalf("cap for OSLICEHEADER must be non-negative")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2173,8 +2173,8 @@ func checksliceindex(l ir.Node, r ir.Node, tp *types.Type) bool {
|
|||||||
} else if tp != nil && tp.NumElem() >= 0 && constant.Compare(x, token.GTR, constant.MakeInt64(tp.NumElem())) {
|
} else if tp != nil && tp.NumElem() >= 0 && constant.Compare(x, token.GTR, constant.MakeInt64(tp.NumElem())) {
|
||||||
base.Errorf("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
|
base.Errorf("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
|
||||||
return false
|
return false
|
||||||
} else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(l.StringVal())))) {
|
} else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(ir.StringVal(l))))) {
|
||||||
base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.StringVal()))
|
base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, len(ir.StringVal(l)))
|
||||||
return false
|
return false
|
||||||
} else if doesoverflow(x, types.Types[types.TINT]) {
|
} else if doesoverflow(x, types.Types[types.TINT]) {
|
||||||
base.Errorf("invalid slice index %v (index too large)", r)
|
base.Errorf("invalid slice index %v (index too large)", r)
|
||||||
@ -3407,7 +3407,7 @@ func stringtoruneslit(n ir.Node) ir.Node {
|
|||||||
|
|
||||||
var l []ir.Node
|
var l []ir.Node
|
||||||
i := 0
|
i := 0
|
||||||
for _, r := range n.Left().StringVal() {
|
for _, r := range ir.StringVal(n.Left()) {
|
||||||
l = append(l, ir.Nod(ir.OKEY, nodintconst(int64(i)), nodintconst(int64(r))))
|
l = append(l, ir.Nod(ir.OKEY, nodintconst(int64(i)), nodintconst(int64(r))))
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@ -3803,7 +3803,7 @@ func deadcode(fn *ir.Func) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
case ir.OFOR:
|
case ir.OFOR:
|
||||||
if !ir.IsConst(n.Left(), constant.Bool) || n.Left().BoolVal() {
|
if !ir.IsConst(n.Left(), constant.Bool) || ir.BoolVal(n.Left()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -3833,7 +3833,7 @@ func deadcodeslice(nn *ir.Nodes) {
|
|||||||
n.SetLeft(deadcodeexpr(n.Left()))
|
n.SetLeft(deadcodeexpr(n.Left()))
|
||||||
if ir.IsConst(n.Left(), constant.Bool) {
|
if ir.IsConst(n.Left(), constant.Bool) {
|
||||||
var body ir.Nodes
|
var body ir.Nodes
|
||||||
if n.Left().BoolVal() {
|
if ir.BoolVal(n.Left()) {
|
||||||
n.SetRlist(ir.Nodes{})
|
n.SetRlist(ir.Nodes{})
|
||||||
body = n.Body()
|
body = n.Body()
|
||||||
} else {
|
} else {
|
||||||
@ -3876,7 +3876,7 @@ func deadcodeexpr(n ir.Node) ir.Node {
|
|||||||
n.SetLeft(deadcodeexpr(n.Left()))
|
n.SetLeft(deadcodeexpr(n.Left()))
|
||||||
n.SetRight(deadcodeexpr(n.Right()))
|
n.SetRight(deadcodeexpr(n.Right()))
|
||||||
if ir.IsConst(n.Left(), constant.Bool) {
|
if ir.IsConst(n.Left(), constant.Bool) {
|
||||||
if n.Left().BoolVal() {
|
if ir.BoolVal(n.Left()) {
|
||||||
return n.Right() // true && x => x
|
return n.Right() // true && x => x
|
||||||
} else {
|
} else {
|
||||||
return n.Left() // false && x => false
|
return n.Left() // false && x => false
|
||||||
@ -3886,7 +3886,7 @@ func deadcodeexpr(n ir.Node) ir.Node {
|
|||||||
n.SetLeft(deadcodeexpr(n.Left()))
|
n.SetLeft(deadcodeexpr(n.Left()))
|
||||||
n.SetRight(deadcodeexpr(n.Right()))
|
n.SetRight(deadcodeexpr(n.Right()))
|
||||||
if ir.IsConst(n.Left(), constant.Bool) {
|
if ir.IsConst(n.Left(), constant.Bool) {
|
||||||
if n.Left().BoolVal() {
|
if ir.BoolVal(n.Left()) {
|
||||||
return n.Left() // true || x => true
|
return n.Left() // true || x => true
|
||||||
} else {
|
} else {
|
||||||
return n.Right() // false || x => x
|
return n.Right() // false || x => x
|
||||||
|
@ -1014,7 +1014,7 @@ opswitch:
|
|||||||
// The SSA backend will handle those.
|
// The SSA backend will handle those.
|
||||||
switch et {
|
switch et {
|
||||||
case types.TINT64:
|
case types.TINT64:
|
||||||
c := n.Right().Int64Val()
|
c := ir.Int64Val(n.Right())
|
||||||
if c < 0 {
|
if c < 0 {
|
||||||
c = -c
|
c = -c
|
||||||
}
|
}
|
||||||
@ -1022,7 +1022,7 @@ opswitch:
|
|||||||
break opswitch
|
break opswitch
|
||||||
}
|
}
|
||||||
case types.TUINT64:
|
case types.TUINT64:
|
||||||
c := n.Right().Uint64Val()
|
c := ir.Uint64Val(n.Right())
|
||||||
if c < 1<<16 {
|
if c < 1<<16 {
|
||||||
break opswitch
|
break opswitch
|
||||||
}
|
}
|
||||||
@ -1072,7 +1072,7 @@ opswitch:
|
|||||||
base.Errorf("index out of bounds")
|
base.Errorf("index out of bounds")
|
||||||
}
|
}
|
||||||
} else if ir.IsConst(n.Left(), constant.String) {
|
} else if ir.IsConst(n.Left(), constant.String) {
|
||||||
n.SetBounded(bounded(r, int64(len(n.Left().StringVal()))))
|
n.SetBounded(bounded(r, int64(len(ir.StringVal(n.Left())))))
|
||||||
if base.Flag.LowerM != 0 && n.Bounded() && !ir.IsConst(n.Right(), constant.Int) {
|
if base.Flag.LowerM != 0 && n.Bounded() && !ir.IsConst(n.Right(), constant.Int) {
|
||||||
base.Warn("index bounds check elided")
|
base.Warn("index bounds check elided")
|
||||||
}
|
}
|
||||||
@ -1507,7 +1507,7 @@ opswitch:
|
|||||||
case ir.OSTR2BYTES:
|
case ir.OSTR2BYTES:
|
||||||
s := n.Left()
|
s := n.Left()
|
||||||
if ir.IsConst(s, constant.String) {
|
if ir.IsConst(s, constant.String) {
|
||||||
sc := s.StringVal()
|
sc := ir.StringVal(s)
|
||||||
|
|
||||||
// Allocate a [n]byte of the right size.
|
// Allocate a [n]byte of the right size.
|
||||||
t := types.NewArray(types.Types[types.TUINT8], int64(len(sc)))
|
t := types.NewArray(types.Types[types.TUINT8], int64(len(sc)))
|
||||||
@ -1936,7 +1936,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
|
|||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
var strs []string
|
var strs []string
|
||||||
for i < len(s) && ir.IsConst(s[i], constant.String) {
|
for i < len(s) && ir.IsConst(s[i], constant.String) {
|
||||||
strs = append(strs, s[i].StringVal())
|
strs = append(strs, ir.StringVal(s[i]))
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if len(strs) > 0 {
|
if len(strs) > 0 {
|
||||||
@ -2016,7 +2016,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
|
|||||||
case types.TSTRING:
|
case types.TSTRING:
|
||||||
cs := ""
|
cs := ""
|
||||||
if ir.IsConst(n, constant.String) {
|
if ir.IsConst(n, constant.String) {
|
||||||
cs = n.StringVal()
|
cs = ir.StringVal(n)
|
||||||
}
|
}
|
||||||
switch cs {
|
switch cs {
|
||||||
case " ":
|
case " ":
|
||||||
@ -2673,7 +2673,7 @@ func addstr(n ir.Node, init *ir.Nodes) ir.Node {
|
|||||||
sz := int64(0)
|
sz := int64(0)
|
||||||
for _, n1 := range n.List().Slice() {
|
for _, n1 := range n.List().Slice() {
|
||||||
if n1.Op() == ir.OLITERAL {
|
if n1.Op() == ir.OLITERAL {
|
||||||
sz += int64(len(n1.StringVal()))
|
sz += int64(len(ir.StringVal(n1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3467,7 +3467,7 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node {
|
|||||||
|
|
||||||
func tracecmpArg(n ir.Node, t *types.Type, init *ir.Nodes) ir.Node {
|
func tracecmpArg(n ir.Node, t *types.Type, init *ir.Nodes) ir.Node {
|
||||||
// Ugly hack to avoid "constant -1 overflows uintptr" errors, etc.
|
// Ugly hack to avoid "constant -1 overflows uintptr" errors, etc.
|
||||||
if n.Op() == ir.OLITERAL && n.Type().IsSigned() && n.Int64Val() < 0 {
|
if n.Op() == ir.OLITERAL && n.Type().IsSigned() && ir.Int64Val(n) < 0 {
|
||||||
n = copyexpr(n, n.Type(), init)
|
n = copyexpr(n, n.Type(), init)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3537,7 +3537,7 @@ func walkcompareString(n ir.Node, init *ir.Nodes) ir.Node {
|
|||||||
// Length-only checks are ok, though.
|
// Length-only checks are ok, though.
|
||||||
maxRewriteLen = 0
|
maxRewriteLen = 0
|
||||||
}
|
}
|
||||||
if s := cs.StringVal(); len(s) <= maxRewriteLen {
|
if s := ir.StringVal(cs); len(s) <= maxRewriteLen {
|
||||||
if len(s) > 0 {
|
if len(s) > 0 {
|
||||||
ncs = safeexpr(ncs, init)
|
ncs = safeexpr(ncs, init)
|
||||||
}
|
}
|
||||||
@ -3632,7 +3632,7 @@ func bounded(n ir.Node, max int64) bool {
|
|||||||
bits := int32(8 * n.Type().Width)
|
bits := int32(8 * n.Type().Width)
|
||||||
|
|
||||||
if smallintconst(n) {
|
if smallintconst(n) {
|
||||||
v := n.Int64Val()
|
v := ir.Int64Val(n)
|
||||||
return 0 <= v && v < max
|
return 0 <= v && v < max
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3641,9 +3641,9 @@ func bounded(n ir.Node, max int64) bool {
|
|||||||
v := int64(-1)
|
v := int64(-1)
|
||||||
switch {
|
switch {
|
||||||
case smallintconst(n.Left()):
|
case smallintconst(n.Left()):
|
||||||
v = n.Left().Int64Val()
|
v = ir.Int64Val(n.Left())
|
||||||
case smallintconst(n.Right()):
|
case smallintconst(n.Right()):
|
||||||
v = n.Right().Int64Val()
|
v = ir.Int64Val(n.Right())
|
||||||
if n.Op() == ir.OANDNOT {
|
if n.Op() == ir.OANDNOT {
|
||||||
v = ^v
|
v = ^v
|
||||||
if !sign {
|
if !sign {
|
||||||
@ -3657,7 +3657,7 @@ func bounded(n ir.Node, max int64) bool {
|
|||||||
|
|
||||||
case ir.OMOD:
|
case ir.OMOD:
|
||||||
if !sign && smallintconst(n.Right()) {
|
if !sign && smallintconst(n.Right()) {
|
||||||
v := n.Right().Int64Val()
|
v := ir.Int64Val(n.Right())
|
||||||
if 0 <= v && v <= max {
|
if 0 <= v && v <= max {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -3665,7 +3665,7 @@ func bounded(n ir.Node, max int64) bool {
|
|||||||
|
|
||||||
case ir.ODIV:
|
case ir.ODIV:
|
||||||
if !sign && smallintconst(n.Right()) {
|
if !sign && smallintconst(n.Right()) {
|
||||||
v := n.Right().Int64Val()
|
v := ir.Int64Val(n.Right())
|
||||||
for bits > 0 && v >= 2 {
|
for bits > 0 && v >= 2 {
|
||||||
bits--
|
bits--
|
||||||
v >>= 1
|
v >>= 1
|
||||||
@ -3674,7 +3674,7 @@ func bounded(n ir.Node, max int64) bool {
|
|||||||
|
|
||||||
case ir.ORSH:
|
case ir.ORSH:
|
||||||
if !sign && smallintconst(n.Right()) {
|
if !sign && smallintconst(n.Right()) {
|
||||||
v := n.Right().Int64Val()
|
v := ir.Int64Val(n.Right())
|
||||||
if v > int64(bits) {
|
if v > int64(bits) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -296,62 +296,6 @@ func (n *Name) SetVal(v constant.Value) {
|
|||||||
n.val = v
|
n.val = v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64Val returns n as an int64.
|
|
||||||
// n must be an integer or rune constant.
|
|
||||||
func (n *Name) Int64Val() int64 {
|
|
||||||
if !IsConst(n, constant.Int) {
|
|
||||||
base.Fatalf("Int64Val(%v)", n)
|
|
||||||
}
|
|
||||||
x, ok := constant.Int64Val(n.Val())
|
|
||||||
if !ok {
|
|
||||||
base.Fatalf("Int64Val(%v)", n)
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanInt64 reports whether it is safe to call Int64Val() on n.
|
|
||||||
func (n *Name) CanInt64() bool {
|
|
||||||
if !IsConst(n, constant.Int) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the value inside n cannot be represented as an int64, the
|
|
||||||
// return value of Int64 is undefined
|
|
||||||
_, ok := constant.Int64Val(n.Val())
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64Val returns n as an uint64.
|
|
||||||
// n must be an integer or rune constant.
|
|
||||||
func (n *Name) Uint64Val() uint64 {
|
|
||||||
if !IsConst(n, constant.Int) {
|
|
||||||
base.Fatalf("Uint64Val(%v)", n)
|
|
||||||
}
|
|
||||||
x, ok := constant.Uint64Val(n.Val())
|
|
||||||
if !ok {
|
|
||||||
base.Fatalf("Uint64Val(%v)", n)
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolVal returns n as a bool.
|
|
||||||
// n must be a boolean constant.
|
|
||||||
func (n *Name) BoolVal() bool {
|
|
||||||
if !IsConst(n, constant.Bool) {
|
|
||||||
base.Fatalf("BoolVal(%v)", n)
|
|
||||||
}
|
|
||||||
return constant.BoolVal(n.Val())
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringVal returns the value of a literal string Node as a string.
|
|
||||||
// n must be a string constant.
|
|
||||||
func (n *Name) StringVal() string {
|
|
||||||
if !IsConst(n, constant.String) {
|
|
||||||
base.Fatalf("StringVal(%v)", n)
|
|
||||||
}
|
|
||||||
return constant.StringVal(n.Val())
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Class of a variable/function describes the "storage class"
|
// The Class of a variable/function describes the "storage class"
|
||||||
// of a variable or function. During parsing, storage classes are
|
// of a variable or function. During parsing, storage classes are
|
||||||
// called declaration contexts.
|
// called declaration contexts.
|
||||||
|
@ -87,11 +87,6 @@ type Node interface {
|
|||||||
MarkReadonly()
|
MarkReadonly()
|
||||||
Val() constant.Value
|
Val() constant.Value
|
||||||
SetVal(v constant.Value)
|
SetVal(v constant.Value)
|
||||||
Int64Val() int64
|
|
||||||
Uint64Val() uint64
|
|
||||||
CanInt64() bool
|
|
||||||
BoolVal() bool
|
|
||||||
StringVal() string
|
|
||||||
|
|
||||||
// Storage for analysis passes.
|
// Storage for analysis passes.
|
||||||
Esc() uint16
|
Esc() uint16
|
||||||
|
@ -32,7 +32,7 @@ func ConstValue(n Node) interface{} {
|
|||||||
case constant.String:
|
case constant.String:
|
||||||
return constant.StringVal(v)
|
return constant.StringVal(v)
|
||||||
case constant.Int:
|
case constant.Int:
|
||||||
return Int64Val(n.Type(), v)
|
return IntVal(n.Type(), v)
|
||||||
case constant.Float:
|
case constant.Float:
|
||||||
return Float64Val(v)
|
return Float64Val(v)
|
||||||
case constant.Complex:
|
case constant.Complex:
|
||||||
@ -42,7 +42,7 @@ func ConstValue(n Node) interface{} {
|
|||||||
|
|
||||||
// int64Val returns v converted to int64.
|
// int64Val returns v converted to int64.
|
||||||
// Note: if t is uint64, very large values will be converted to negative int64.
|
// Note: if t is uint64, very large values will be converted to negative int64.
|
||||||
func Int64Val(t *types.Type, v constant.Value) int64 {
|
func IntVal(t *types.Type, v constant.Value) int64 {
|
||||||
if t.IsUnsigned() {
|
if t.IsUnsigned() {
|
||||||
if x, ok := constant.Uint64Val(v); ok {
|
if x, ok := constant.Uint64Val(v); ok {
|
||||||
return int64(x)
|
return int64(x)
|
||||||
@ -118,3 +118,59 @@ func idealType(ct constant.Kind) *types.Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var OKForConst [types.NTYPE]bool
|
var OKForConst [types.NTYPE]bool
|
||||||
|
|
||||||
|
// CanInt64 reports whether it is safe to call Int64Val() on n.
|
||||||
|
func CanInt64(n Node) bool {
|
||||||
|
if !IsConst(n, constant.Int) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the value inside n cannot be represented as an int64, the
|
||||||
|
// return value of Int64 is undefined
|
||||||
|
_, ok := constant.Int64Val(n.Val())
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Val returns n as an int64.
|
||||||
|
// n must be an integer or rune constant.
|
||||||
|
func Int64Val(n Node) int64 {
|
||||||
|
if !IsConst(n, constant.Int) {
|
||||||
|
base.Fatalf("Int64Val(%v)", n)
|
||||||
|
}
|
||||||
|
x, ok := constant.Int64Val(n.Val())
|
||||||
|
if !ok {
|
||||||
|
base.Fatalf("Int64Val(%v)", n)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64Val returns n as an uint64.
|
||||||
|
// n must be an integer or rune constant.
|
||||||
|
func Uint64Val(n Node) uint64 {
|
||||||
|
if !IsConst(n, constant.Int) {
|
||||||
|
base.Fatalf("Uint64Val(%v)", n)
|
||||||
|
}
|
||||||
|
x, ok := constant.Uint64Val(n.Val())
|
||||||
|
if !ok {
|
||||||
|
base.Fatalf("Uint64Val(%v)", n)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolVal returns n as a bool.
|
||||||
|
// n must be a boolean constant.
|
||||||
|
func BoolVal(n Node) bool {
|
||||||
|
if !IsConst(n, constant.Bool) {
|
||||||
|
base.Fatalf("BoolVal(%v)", n)
|
||||||
|
}
|
||||||
|
return constant.BoolVal(n.Val())
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringVal returns the value of a literal string Node as a string.
|
||||||
|
// n must be a string constant.
|
||||||
|
func StringVal(n Node) string {
|
||||||
|
if !IsConst(n, constant.String) {
|
||||||
|
base.Fatalf("StringVal(%v)", n)
|
||||||
|
}
|
||||||
|
return constant.StringVal(n.Val())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user