if need == 1 {
var strs []string
for _, c := range s {
- strs = append(strs, c.StringVal())
+ strs = append(strs, ir.StringVal(c))
}
return origConst(n, constant.MakeString(strings.Join(strs, "")))
}
var strs []string
i2 := i
for i2 < len(s) && ir.IsConst(s[i2], constant.String) {
- strs = append(strs, s[i2].StringVal())
+ strs = append(strs, ir.StringVal(s[i2]))
i2++
}
switch nl.Type().Kind() {
case types.TSTRING:
if ir.IsConst(nl, constant.String) {
- return origIntConst(n, int64(len(nl.StringVal())))
+ return origIntConst(n, int64(len(ir.StringVal(nl))))
}
case types.TARRAY:
if !hascallchan(nl) {
if doesoverflow(v, types.Types[types.TINT]) {
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
if !smallintconst(r) {
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"
}
}
n := p.expr(x)
if ir.IsConst(n, constant.String) && n.Sym() == nil {
nstr = n
- chunks = append(chunks, nstr.StringVal())
+ chunks = append(chunks, ir.StringVal(nstr))
}
for i := len(adds) - 1; i >= 0; i-- {
if ir.IsConst(r, constant.String) && r.Sym() == nil {
if nstr != nil {
// Collapse r into nstr instead of adding to n.
- chunks = append(chunks, r.StringVal())
+ chunks = append(chunks, ir.StringVal(r))
continue
}
nstr = r
- chunks = append(chunks, nstr.StringVal())
+ chunks = append(chunks, ir.StringVal(nstr))
} else {
if len(chunks) > 1 {
nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
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() {
s.WriteInt(base.Ctxt, n.Offset(), wid, i)
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:
f, _ := constant.Float64Val(u)
haslit := false
for _, n1 := range n.List().Slice() {
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 {
var t *types.Type
switch n.Op() {
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:
t = partialCallType(n)
}
case ir.OSLICELIT:
// copy slice
a := s.inittemps[r]
- slicesym(l, a, r.Right().Int64Val())
+ slicesym(l, a, ir.Int64Val(r.Right()))
return true
case ir.OARRAYLIT, ir.OSTRUCTLIT:
case ir.OSTR2BYTES:
if l.Class() == ir.PEXTERN && r.Left().Op() == ir.OLITERAL {
- sval := r.Left().StringVal()
+ sval := ir.StringVal(r.Left())
slicebytes(l, sval)
return true
}
case ir.OSLICELIT:
s.initplan(r)
// Init slice.
- bound := r.Right().Int64Val()
+ bound := ir.Int64Val(r.Right())
ta := types.NewArray(r.Type().Elem(), bound)
ta.SetNoalg(true)
a := staticname(ta)
if !top {
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.
// Very rough estimation, it takes 4 bytes of instructions
// to initialize 1 byte of result. So don't use a static
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) {
// 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)
if ctxt == inNonInitFunction {
func getlit(lit ir.Node) int {
if smallintconst(lit) {
- return int(lit.Int64Val())
+ return int(ir.Int64Val(lit))
}
return -1
}
// We're assigning a slicing operation back to its source.
// Don't write back fields we aren't changing. See issue #14855.
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 [:...]
i = nil
}
case ir.OIF:
if ir.IsConst(n.Left(), constant.Bool) {
s.stmtList(n.Left().Init())
- if n.Left().BoolVal() {
+ if ir.BoolVal(n.Left()) {
s.stmtList(n.Body())
} else {
s.stmtList(n.Rlist())
case ir.OLITERAL:
switch u := n.Val(); u.Kind() {
case constant.Int:
- i := ir.Int64Val(n.Type(), u)
+ i := ir.IntVal(n.Type(), u)
switch n.Type().Size() {
case 1:
return s.constInt8(n.Type(), int8(i))
// Replace "abc"[1] with 'b'.
// Delayed until now because "abc"[1] is not an ideal constant.
// 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())
i := s.expr(n.Right())
ptrtyp := s.f.Config.Types.BytePtr
ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
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 {
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
}
// all we need here is consistency. We respect this
// sorting below.
sort.Slice(cc, func(i, j int) bool {
- si := cc[i].lo.StringVal()
- sj := cc[j].lo.StringVal()
+ si := ir.StringVal(cc[i].lo)
+ sj := ir.StringVal(cc[j].lo)
if len(si) != len(sj) {
return len(si) < len(sj)
}
// runLen returns the string length associated with a
// 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.
var runs [][]exprClause
merged := cc[:1]
for _, c := range cc[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
} else {
merged = append(merged, c)
// Optimize "switch true { ...}" and "switch false { ... }".
if ir.IsConst(exprname, constant.Bool) && !c.lo.Type().IsInterface() {
- if exprname.BoolVal() {
+ if ir.BoolVal(exprname) {
return c.lo
} else {
return ir.NodAt(c.pos, ir.ONOT, c.lo, nil)
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())) {
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())))) {
- base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Right(), 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(ir.StringVal(n.Left())))
} else if doesoverflow(x, types.Types[types.TINT]) {
base.Errorf("invalid %s index %v (index too large)", why, n.Right())
}
l = defaultlit(l, 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")
}
- 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")
}
} 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())
return false
- } else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(l.StringVal())))) {
- base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, 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(ir.StringVal(l)))
return false
} else if doesoverflow(x, types.Types[types.TINT]) {
base.Errorf("invalid slice index %v (index too large)", r)
var l []ir.Node
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))))
i++
}
return
}
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
}
default:
n.SetLeft(deadcodeexpr(n.Left()))
if ir.IsConst(n.Left(), constant.Bool) {
var body ir.Nodes
- if n.Left().BoolVal() {
+ if ir.BoolVal(n.Left()) {
n.SetRlist(ir.Nodes{})
body = n.Body()
} else {
n.SetLeft(deadcodeexpr(n.Left()))
n.SetRight(deadcodeexpr(n.Right()))
if ir.IsConst(n.Left(), constant.Bool) {
- if n.Left().BoolVal() {
+ if ir.BoolVal(n.Left()) {
return n.Right() // true && x => x
} else {
return n.Left() // false && x => false
n.SetLeft(deadcodeexpr(n.Left()))
n.SetRight(deadcodeexpr(n.Right()))
if ir.IsConst(n.Left(), constant.Bool) {
- if n.Left().BoolVal() {
+ if ir.BoolVal(n.Left()) {
return n.Left() // true || x => true
} else {
return n.Right() // false || x => x
// The SSA backend will handle those.
switch et {
case types.TINT64:
- c := n.Right().Int64Val()
+ c := ir.Int64Val(n.Right())
if c < 0 {
c = -c
}
break opswitch
}
case types.TUINT64:
- c := n.Right().Uint64Val()
+ c := ir.Uint64Val(n.Right())
if c < 1<<16 {
break opswitch
}
base.Errorf("index out of bounds")
}
} 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) {
base.Warn("index bounds check elided")
}
case ir.OSTR2BYTES:
s := n.Left()
if ir.IsConst(s, constant.String) {
- sc := s.StringVal()
+ sc := ir.StringVal(s)
// Allocate a [n]byte of the right size.
t := types.NewArray(types.Types[types.TUINT8], int64(len(sc)))
for i := 0; i < len(s); {
var strs []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++
}
if len(strs) > 0 {
case types.TSTRING:
cs := ""
if ir.IsConst(n, constant.String) {
- cs = n.StringVal()
+ cs = ir.StringVal(n)
}
switch cs {
case " ":
sz := int64(0)
for _, n1 := range n.List().Slice() {
if n1.Op() == ir.OLITERAL {
- sz += int64(len(n1.StringVal()))
+ sz += int64(len(ir.StringVal(n1)))
}
}
func tracecmpArg(n ir.Node, t *types.Type, init *ir.Nodes) ir.Node {
// 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)
}
// Length-only checks are ok, though.
maxRewriteLen = 0
}
- if s := cs.StringVal(); len(s) <= maxRewriteLen {
+ if s := ir.StringVal(cs); len(s) <= maxRewriteLen {
if len(s) > 0 {
ncs = safeexpr(ncs, init)
}
bits := int32(8 * n.Type().Width)
if smallintconst(n) {
- v := n.Int64Val()
+ v := ir.Int64Val(n)
return 0 <= v && v < max
}
v := int64(-1)
switch {
case smallintconst(n.Left()):
- v = n.Left().Int64Val()
+ v = ir.Int64Val(n.Left())
case smallintconst(n.Right()):
- v = n.Right().Int64Val()
+ v = ir.Int64Val(n.Right())
if n.Op() == ir.OANDNOT {
v = ^v
if !sign {
case ir.OMOD:
if !sign && smallintconst(n.Right()) {
- v := n.Right().Int64Val()
+ v := ir.Int64Val(n.Right())
if 0 <= v && v <= max {
return true
}
case ir.ODIV:
if !sign && smallintconst(n.Right()) {
- v := n.Right().Int64Val()
+ v := ir.Int64Val(n.Right())
for bits > 0 && v >= 2 {
bits--
v >>= 1
case ir.ORSH:
if !sign && smallintconst(n.Right()) {
- v := n.Right().Int64Val()
+ v := ir.Int64Val(n.Right())
if v > int64(bits) {
return true
}
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"
// of a variable or function. During parsing, storage classes are
// called declaration contexts.
MarkReadonly()
Val() constant.Value
SetVal(v constant.Value)
- Int64Val() int64
- Uint64Val() uint64
- CanInt64() bool
- BoolVal() bool
- StringVal() string
// Storage for analysis passes.
Esc() uint16
case constant.String:
return constant.StringVal(v)
case constant.Int:
- return Int64Val(n.Type(), v)
+ return IntVal(n.Type(), v)
case constant.Float:
return Float64Val(v)
case constant.Complex:
// int64Val returns v converted to 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 x, ok := constant.Uint64Val(v); ok {
return int64(x)
}
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())
+}