2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2009 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 gc
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
import (
|
2015-05-21 13:28:10 -04:00
|
|
|
"cmd/compile/internal/big"
|
2015-03-02 16:03:26 -05:00
|
|
|
"cmd/internal/obj"
|
|
|
|
"strings"
|
|
|
|
)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-18 18:56:47 +10:00
|
|
|
// IntLiteral returns the Node's literal value as an interger.
|
|
|
|
func (n *Node) IntLiteral() (x int64, ok bool) {
|
|
|
|
switch {
|
|
|
|
case n == nil:
|
|
|
|
return
|
|
|
|
case Isconst(n, CTINT):
|
|
|
|
return n.Int(), true
|
|
|
|
case Isconst(n, CTBOOL):
|
|
|
|
return int64(obj.Bool2int(n.Bool())), true
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-04-22 20:08:03 -07:00
|
|
|
// Int returns n as an int.
|
|
|
|
// n must be an integer constant.
|
|
|
|
func (n *Node) Int() int64 {
|
|
|
|
if !Isconst(n, CTINT) {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("Int(%v)", n)
|
2015-04-22 20:08:03 -07:00
|
|
|
}
|
2015-05-27 00:47:05 -04:00
|
|
|
return Mpgetfix(n.Val().U.(*Mpint))
|
2015-04-22 20:08:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetInt sets n's value to i.
|
|
|
|
// n must be an integer constant.
|
|
|
|
func (n *Node) SetInt(i int64) {
|
|
|
|
if !Isconst(n, CTINT) {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("SetInt(%v)", n)
|
2015-04-22 20:08:03 -07:00
|
|
|
}
|
2015-05-27 00:47:05 -04:00
|
|
|
Mpmovecfix(n.Val().U.(*Mpint), i)
|
2015-04-22 20:08:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetBigInt sets n's value to x.
|
|
|
|
// n must be an integer constant.
|
|
|
|
func (n *Node) SetBigInt(x *big.Int) {
|
|
|
|
if !Isconst(n, CTINT) {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("SetBigInt(%v)", n)
|
2015-04-22 20:08:03 -07:00
|
|
|
}
|
2015-05-27 00:47:05 -04:00
|
|
|
n.Val().U.(*Mpint).Val.Set(x)
|
2015-04-22 20:08:03 -07:00
|
|
|
}
|
|
|
|
|
2015-05-07 18:43:03 -07:00
|
|
|
// Bool returns n as an bool.
|
|
|
|
// n must be an boolean constant.
|
|
|
|
func (n *Node) Bool() bool {
|
|
|
|
if !Isconst(n, CTBOOL) {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("Int(%v)", n)
|
2015-05-07 18:43:03 -07:00
|
|
|
}
|
2015-05-27 00:47:05 -04:00
|
|
|
return n.Val().U.(bool)
|
2015-05-07 18:43:03 -07:00
|
|
|
}
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// truncate float literal fv to 32-bit or 64-bit precision
|
|
|
|
// according to type; return truncated value.
|
2015-02-13 14:40:36 -05:00
|
|
|
func truncfltlit(oldv *Mpflt, t *Type) *Mpflt {
|
|
|
|
if t == nil {
|
|
|
|
return oldv
|
|
|
|
}
|
|
|
|
|
2015-03-02 14:22:05 -05:00
|
|
|
var v Val
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = oldv
|
2015-02-13 14:40:36 -05:00
|
|
|
overflow(v, t)
|
|
|
|
|
2015-03-20 16:59:08 -07:00
|
|
|
fv := newMpflt()
|
|
|
|
mpmovefltflt(fv, oldv)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// convert large precision literal floating
|
|
|
|
// into limited precision (float64 or float32)
|
|
|
|
switch t.Etype {
|
|
|
|
case TFLOAT64:
|
2015-02-23 16:07:24 -05:00
|
|
|
d := mpgetflt(fv)
|
2015-02-13 14:40:36 -05:00
|
|
|
Mpmovecflt(fv, d)
|
|
|
|
|
|
|
|
case TFLOAT32:
|
2015-02-23 16:07:24 -05:00
|
|
|
d := mpgetflt32(fv)
|
2015-02-13 14:40:36 -05:00
|
|
|
Mpmovecflt(fv, d)
|
|
|
|
}
|
|
|
|
|
|
|
|
return fv
|
|
|
|
}
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// convert n, if literal, to type t.
|
|
|
|
// implicit conversion.
|
2015-02-13 14:40:36 -05:00
|
|
|
func Convlit(np **Node, t *Type) {
|
2015-02-17 22:13:49 -05:00
|
|
|
convlit1(np, t, false)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// convert n, if literal, to type t.
|
|
|
|
// return a new node if necessary
|
|
|
|
//(if n is a named constant, can't edit n->type directly).
|
2015-02-17 22:13:49 -05:00
|
|
|
func convlit1(np **Node, t *Type, explicit bool) {
|
2015-02-23 16:07:24 -05:00
|
|
|
n := *np
|
2015-02-17 22:13:49 -05:00
|
|
|
if n == nil || t == nil || n.Type == nil || isideal(t) || n.Type == t {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if !explicit && !isideal(n.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if n.Op == OLITERAL {
|
2015-02-23 16:07:24 -05:00
|
|
|
nn := Nod(OXXX, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
*nn = *n
|
|
|
|
n = nn
|
|
|
|
*np = n
|
|
|
|
}
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
default:
|
|
|
|
if n.Type == idealbool {
|
|
|
|
if t.Etype == TBOOL {
|
|
|
|
n.Type = t
|
|
|
|
} else {
|
|
|
|
n.Type = Types[TBOOL]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if n.Type.Etype == TIDEAL {
|
|
|
|
Convlit(&n.Left, t)
|
|
|
|
Convlit(&n.Right, t)
|
|
|
|
n.Type = t
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
// target is invalid type for a constant? leave alone.
|
|
|
|
case OLITERAL:
|
2015-03-01 07:54:01 +00:00
|
|
|
if !okforconst[t.Etype] && n.Type.Etype != TNIL {
|
2015-02-13 14:40:36 -05:00
|
|
|
defaultlit(&n, nil)
|
|
|
|
*np = n
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OLSH, ORSH:
|
2015-02-17 22:13:49 -05:00
|
|
|
convlit1(&n.Left, t, explicit && isideal(n.Left.Type))
|
2015-02-13 14:40:36 -05:00
|
|
|
t = n.Left.Type
|
2015-05-27 00:47:05 -04:00
|
|
|
if t != nil && t.Etype == TIDEAL && n.Val().Ctype() != CTINT {
|
|
|
|
n.SetVal(toint(n.Val()))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-01 07:54:01 +00:00
|
|
|
if t != nil && !Isint[t.Etype] {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("invalid operation: %v (shift of type %v)", n, t)
|
2015-02-13 14:40:36 -05:00
|
|
|
t = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Type = t
|
|
|
|
return
|
|
|
|
|
|
|
|
case OCOMPLEX:
|
|
|
|
if n.Type.Etype == TIDEAL {
|
|
|
|
switch t.Etype {
|
|
|
|
// If trying to convert to non-complex type,
|
|
|
|
// leave as complex128 and let typechecker complain.
|
|
|
|
default:
|
|
|
|
t = Types[TCOMPLEX128]
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
//fallthrough
|
|
|
|
case TCOMPLEX128:
|
|
|
|
n.Type = t
|
|
|
|
|
|
|
|
Convlit(&n.Left, Types[TFLOAT64])
|
|
|
|
Convlit(&n.Right, Types[TFLOAT64])
|
|
|
|
|
|
|
|
case TCOMPLEX64:
|
|
|
|
n.Type = t
|
|
|
|
Convlit(&n.Left, Types[TFLOAT32])
|
|
|
|
Convlit(&n.Right, Types[TFLOAT32])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// avoided repeated calculations, errors
|
|
|
|
if Eqtype(n.Type, t) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
ct := consttype(n)
|
2016-02-29 20:07:09 -08:00
|
|
|
var et EType
|
2015-02-13 14:40:36 -05:00
|
|
|
if ct < 0 {
|
|
|
|
goto bad
|
|
|
|
}
|
|
|
|
|
2016-02-29 20:07:09 -08:00
|
|
|
et = t.Etype
|
2015-02-13 14:40:36 -05:00
|
|
|
if et == TINTER {
|
|
|
|
if ct == CTNIL && n.Type == Types[TNIL] {
|
|
|
|
n.Type = t
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultlit(np, nil)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ct {
|
|
|
|
default:
|
|
|
|
goto bad
|
|
|
|
|
|
|
|
case CTNIL:
|
|
|
|
switch et {
|
|
|
|
default:
|
|
|
|
n.Type = nil
|
|
|
|
goto bad
|
|
|
|
|
|
|
|
// let normal conversion code handle it
|
|
|
|
case TSTRING:
|
|
|
|
return
|
|
|
|
|
|
|
|
case TARRAY:
|
2015-02-17 22:13:49 -05:00
|
|
|
if !Isslice(t) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto bad
|
|
|
|
}
|
|
|
|
|
|
|
|
case TPTR32,
|
|
|
|
TPTR64,
|
|
|
|
TINTER,
|
|
|
|
TMAP,
|
|
|
|
TCHAN,
|
|
|
|
TFUNC,
|
|
|
|
TUNSAFEPTR:
|
|
|
|
break
|
|
|
|
|
|
|
|
// A nil literal may be converted to uintptr
|
|
|
|
// if it is an unsafe.Pointer
|
|
|
|
case TUINTPTR:
|
|
|
|
if n.Type.Etype == TUNSAFEPTR {
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(Val{new(Mpint)})
|
|
|
|
Mpmovecfix(n.Val().U.(*Mpint), 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
|
|
|
goto bad
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTSTR, CTBOOL:
|
2016-02-29 20:07:09 -08:00
|
|
|
if et != n.Type.Etype {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto bad
|
|
|
|
}
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTINT, CTRUNE, CTFLT, CTCPLX:
|
2015-05-01 19:50:27 -07:00
|
|
|
if n.Type.Etype == TUNSAFEPTR && t.Etype != TUINTPTR {
|
|
|
|
goto bad
|
|
|
|
}
|
2015-10-26 16:00:59 -07:00
|
|
|
ct := n.Val().Ctype()
|
2015-03-01 07:54:01 +00:00
|
|
|
if Isint[et] {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch ct {
|
|
|
|
default:
|
|
|
|
goto bad
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTCPLX, CTFLT, CTRUNE:
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(toint(n.Val()))
|
2015-02-13 14:40:36 -05:00
|
|
|
fallthrough
|
|
|
|
|
|
|
|
case CTINT:
|
2015-05-27 00:47:05 -04:00
|
|
|
overflow(n.Val(), t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-01 07:54:01 +00:00
|
|
|
} else if Isfloat[et] {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch ct {
|
|
|
|
default:
|
|
|
|
goto bad
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTCPLX, CTINT, CTRUNE:
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(toflt(n.Val()))
|
2015-02-13 14:40:36 -05:00
|
|
|
fallthrough
|
|
|
|
|
|
|
|
case CTFLT:
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(Val{truncfltlit(n.Val().U.(*Mpflt), t)})
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-01 07:54:01 +00:00
|
|
|
} else if Iscomplex[et] {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch ct {
|
|
|
|
default:
|
|
|
|
goto bad
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTFLT, CTINT, CTRUNE:
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(tocplx(n.Val()))
|
2015-11-04 15:47:48 -05:00
|
|
|
fallthrough
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTCPLX:
|
2015-05-27 00:47:05 -04:00
|
|
|
overflow(n.Val(), t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
} else if et == TSTRING && (ct == CTINT || ct == CTRUNE) && explicit {
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(tostr(n.Val()))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
|
|
|
goto bad
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Type = t
|
|
|
|
return
|
|
|
|
|
|
|
|
bad:
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Diag == 0 {
|
2015-09-07 10:37:26 +10:00
|
|
|
if !t.Broke {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("cannot convert %v to type %v", n, t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
n.Diag = 1
|
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if isideal(n.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
defaultlit(&n, nil)
|
|
|
|
*np = n
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func copyval(v Val) Val {
|
2015-05-26 22:50:45 -04:00
|
|
|
switch v.Ctype() {
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTINT, CTRUNE:
|
2015-02-23 16:07:24 -05:00
|
|
|
i := new(Mpint)
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmovefixfix(i, v.U.(*Mpint))
|
2015-05-26 22:50:45 -04:00
|
|
|
i.Rune = v.U.(*Mpint).Rune
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = i
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTFLT:
|
2015-03-20 16:59:08 -07:00
|
|
|
f := newMpflt()
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmovefltflt(f, v.U.(*Mpflt))
|
|
|
|
v.U = f
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTCPLX:
|
2015-02-23 16:07:24 -05:00
|
|
|
c := new(Mpcplx)
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmovefltflt(&c.Real, &v.U.(*Mpcplx).Real)
|
|
|
|
mpmovefltflt(&c.Imag, &v.U.(*Mpcplx).Imag)
|
|
|
|
v.U = c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func tocplx(v Val) Val {
|
2015-05-26 22:50:45 -04:00
|
|
|
switch v.Ctype() {
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTINT, CTRUNE:
|
2015-02-23 16:07:24 -05:00
|
|
|
c := new(Mpcplx)
|
2015-05-14 17:57:42 -07:00
|
|
|
Mpmovefixflt(&c.Real, v.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
Mpmovecflt(&c.Imag, 0.0)
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = c
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTFLT:
|
2015-02-23 16:07:24 -05:00
|
|
|
c := new(Mpcplx)
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmovefltflt(&c.Real, v.U.(*Mpflt))
|
2015-02-13 14:40:36 -05:00
|
|
|
Mpmovecflt(&c.Imag, 0.0)
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func toflt(v Val) Val {
|
2015-05-26 22:50:45 -04:00
|
|
|
switch v.Ctype() {
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTINT, CTRUNE:
|
2015-03-20 16:59:08 -07:00
|
|
|
f := newMpflt()
|
2015-05-14 17:57:42 -07:00
|
|
|
Mpmovefixflt(f, v.U.(*Mpint))
|
|
|
|
v.U = f
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTCPLX:
|
2015-03-20 16:59:08 -07:00
|
|
|
f := newMpflt()
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmovefltflt(f, &v.U.(*Mpcplx).Real)
|
|
|
|
if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) != 0 {
|
|
|
|
Yyerror("constant %v%vi truncated to real", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp|obj.FmtSign))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = f
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func toint(v Val) Val {
|
2015-05-26 22:50:45 -04:00
|
|
|
switch v.Ctype() {
|
2015-02-13 14:40:36 -05:00
|
|
|
case CTRUNE:
|
2015-05-26 22:50:45 -04:00
|
|
|
i := new(Mpint)
|
|
|
|
mpmovefixfix(i, v.U.(*Mpint))
|
|
|
|
v.U = i
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTFLT:
|
2015-02-23 16:07:24 -05:00
|
|
|
i := new(Mpint)
|
2015-12-03 15:51:03 -08:00
|
|
|
if f := v.U.(*Mpflt); mpmovefltfix(i, f) < 0 {
|
|
|
|
msg := "constant %v truncated to integer"
|
|
|
|
// provide better error message if mpmovefltfix failed because f was too large
|
|
|
|
if f.Val.IsInt() {
|
|
|
|
msg = "constant %v overflows integer"
|
|
|
|
}
|
|
|
|
Yyerror(msg, Fconv(f, obj.FmtSharp))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = i
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTCPLX:
|
2015-02-23 16:07:24 -05:00
|
|
|
i := new(Mpint)
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpmovefltfix(i, &v.U.(*Mpcplx).Real) < 0 {
|
|
|
|
Yyerror("constant %v%vi truncated to integer", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp|obj.FmtSign))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) != 0 {
|
|
|
|
Yyerror("constant %v%vi truncated to real", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp|obj.FmtSign))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = i
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func doesoverflow(v Val, t *Type) bool {
|
2015-05-26 22:50:45 -04:00
|
|
|
switch v.Ctype() {
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTINT, CTRUNE:
|
2015-03-01 07:54:01 +00:00
|
|
|
if !Isint[t.Etype] {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("overflow: %v integer constant", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-14 17:57:42 -07:00
|
|
|
if Mpcmpfixfix(v.U.(*Mpint), Minintval[t.Etype]) < 0 || Mpcmpfixfix(v.U.(*Mpint), Maxintval[t.Etype]) > 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case CTFLT:
|
2015-03-01 07:54:01 +00:00
|
|
|
if !Isfloat[t.Etype] {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("overflow: %v floating-point constant", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(v.U.(*Mpflt), minfltval[t.Etype]) <= 0 || mpcmpfltflt(v.U.(*Mpflt), maxfltval[t.Etype]) >= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case CTCPLX:
|
2015-03-01 07:54:01 +00:00
|
|
|
if !Iscomplex[t.Etype] {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("overflow: %v complex constant", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(&v.U.(*Mpcplx).Real, minfltval[t.Etype]) <= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Real, maxfltval[t.Etype]) >= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, minfltval[t.Etype]) <= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, maxfltval[t.Etype]) >= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func overflow(v Val, t *Type) {
|
|
|
|
// v has already been converted
|
|
|
|
// to appropriate form for t.
|
|
|
|
if t == nil || t.Etype == TIDEAL {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-05-01 19:50:27 -07:00
|
|
|
// Only uintptrs may be converted to unsafe.Pointer, which cannot overflow.
|
|
|
|
if t.Etype == TUNSAFEPTR {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-09-15 11:16:58 -07:00
|
|
|
if doesoverflow(v, t) {
|
|
|
|
Yyerror("constant %s overflows %v", Vconv(v, 0), t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func tostr(v Val) Val {
|
2015-05-26 22:50:45 -04:00
|
|
|
switch v.Ctype() {
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTINT, CTRUNE:
|
2015-05-14 17:57:42 -07:00
|
|
|
if Mpcmpfixfix(v.U.(*Mpint), Minintval[TINT]) < 0 || Mpcmpfixfix(v.U.(*Mpint), Maxintval[TINT]) > 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("overflow in int -> string")
|
|
|
|
}
|
2015-05-14 17:57:42 -07:00
|
|
|
r := uint(Mpgetfix(v.U.(*Mpint)))
|
2015-02-13 14:40:36 -05:00
|
|
|
v = Val{}
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = string(r)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTFLT:
|
|
|
|
Yyerror("no float -> string")
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
case CTNIL:
|
|
|
|
v = Val{}
|
2015-05-14 17:57:42 -07:00
|
|
|
v.U = ""
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2015-10-26 16:00:59 -07:00
|
|
|
func consttype(n *Node) Ctype {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil || n.Op != OLITERAL {
|
|
|
|
return -1
|
|
|
|
}
|
2015-10-26 16:00:59 -07:00
|
|
|
return n.Val().Ctype()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-10-26 16:00:59 -07:00
|
|
|
func Isconst(n *Node, ct Ctype) bool {
|
2015-02-23 16:07:24 -05:00
|
|
|
t := consttype(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// If the caller is asking for CTINT, allow CTRUNE too.
|
|
|
|
// Makes life easier for back ends.
|
2015-02-17 22:13:49 -05:00
|
|
|
return t == ct || (ct == CTINT && t == CTRUNE)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func saveorig(n *Node) *Node {
|
|
|
|
if n == n.Orig {
|
|
|
|
// duplicate node for n->orig.
|
2015-02-23 16:07:24 -05:00
|
|
|
n1 := Nod(OLITERAL, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
n.Orig = n1
|
|
|
|
*n1 = *n
|
|
|
|
}
|
|
|
|
|
|
|
|
return n.Orig
|
|
|
|
}
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// if n is constant, rewrite as OLITERAL node.
|
2015-02-13 14:40:36 -05:00
|
|
|
func evconst(n *Node) {
|
|
|
|
// pick off just the opcodes that can be
|
|
|
|
// constant evaluated.
|
|
|
|
switch n.Op {
|
|
|
|
default:
|
|
|
|
return
|
|
|
|
|
|
|
|
case OADD,
|
|
|
|
OAND,
|
|
|
|
OANDAND,
|
|
|
|
OANDNOT,
|
|
|
|
OARRAYBYTESTR,
|
|
|
|
OCOM,
|
|
|
|
ODIV,
|
|
|
|
OEQ,
|
|
|
|
OGE,
|
|
|
|
OGT,
|
|
|
|
OLE,
|
|
|
|
OLSH,
|
|
|
|
OLT,
|
|
|
|
OMINUS,
|
|
|
|
OMOD,
|
|
|
|
OMUL,
|
|
|
|
ONE,
|
|
|
|
ONOT,
|
|
|
|
OOR,
|
|
|
|
OOROR,
|
|
|
|
OPLUS,
|
|
|
|
ORSH,
|
|
|
|
OSUB,
|
|
|
|
OXOR:
|
|
|
|
break
|
|
|
|
|
|
|
|
case OCONV:
|
|
|
|
if n.Type == nil {
|
|
|
|
return
|
|
|
|
}
|
2015-03-01 07:54:01 +00:00
|
|
|
if !okforconst[n.Type.Etype] && n.Type.Etype != TNIL {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// merge adjacent constants in the argument list.
|
|
|
|
case OADDSTR:
|
2015-02-23 16:07:24 -05:00
|
|
|
var nr *Node
|
|
|
|
var nl *Node
|
|
|
|
var l2 *NodeList
|
|
|
|
for l1 := n.List; l1 != nil; l1 = l1.Next {
|
2015-02-17 22:13:49 -05:00
|
|
|
if Isconst(l1.N, CTSTR) && l1.Next != nil && Isconst(l1.Next.N, CTSTR) {
|
2015-02-13 14:40:36 -05:00
|
|
|
// merge from l1 up to but not including l2
|
2015-03-02 16:03:26 -05:00
|
|
|
var strs []string
|
2015-02-13 14:40:36 -05:00
|
|
|
l2 = l1
|
2015-02-17 22:13:49 -05:00
|
|
|
for l2 != nil && Isconst(l2.N, CTSTR) {
|
2015-02-13 14:40:36 -05:00
|
|
|
nr = l2.N
|
2015-05-27 00:47:05 -04:00
|
|
|
strs = append(strs, nr.Val().U.(string))
|
2015-02-13 14:40:36 -05:00
|
|
|
l2 = l2.Next
|
|
|
|
}
|
|
|
|
|
|
|
|
nl = Nod(OXXX, nil, nil)
|
|
|
|
*nl = *l1.N
|
|
|
|
nl.Orig = nl
|
2015-05-27 00:47:05 -04:00
|
|
|
nl.SetVal(Val{strings.Join(strs, "")})
|
2015-02-13 14:40:36 -05:00
|
|
|
l1.N = nl
|
|
|
|
l1.Next = l2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// fix list end pointer.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l2 := n.List; l2 != nil; l2 = l2.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
n.List.End = l2
|
|
|
|
}
|
|
|
|
|
|
|
|
// collapse single-constant list to single constant.
|
2015-02-17 22:13:49 -05:00
|
|
|
if count(n.List) == 1 && Isconst(n.List.N, CTSTR) {
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Op = OLITERAL
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(n.List.N.Val())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
nl := n.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
if nl == nil || nl.Type == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if consttype(nl) < 0 {
|
|
|
|
return
|
|
|
|
}
|
2016-02-29 20:07:09 -08:00
|
|
|
wl := nl.Type.Etype
|
2015-03-01 07:54:01 +00:00
|
|
|
if Isint[wl] || Isfloat[wl] || Iscomplex[wl] {
|
2015-02-13 14:40:36 -05:00
|
|
|
wl = TIDEAL
|
|
|
|
}
|
|
|
|
|
2015-10-26 16:00:59 -07:00
|
|
|
// avoid constant conversions in switches below
|
|
|
|
const (
|
2015-09-24 23:21:18 +02:00
|
|
|
CTINT_ = uint32(CTINT)
|
|
|
|
CTRUNE_ = uint32(CTRUNE)
|
|
|
|
CTFLT_ = uint32(CTFLT)
|
|
|
|
CTCPLX_ = uint32(CTCPLX)
|
|
|
|
CTSTR_ = uint32(CTSTR)
|
|
|
|
CTBOOL_ = uint32(CTBOOL)
|
|
|
|
CTNIL_ = uint32(CTNIL)
|
|
|
|
OCONV_ = uint32(OCONV) << 16
|
|
|
|
OARRAYBYTESTR_ = uint32(OARRAYBYTESTR) << 16
|
|
|
|
OPLUS_ = uint32(OPLUS) << 16
|
|
|
|
OMINUS_ = uint32(OMINUS) << 16
|
|
|
|
OCOM_ = uint32(OCOM) << 16
|
|
|
|
ONOT_ = uint32(ONOT) << 16
|
|
|
|
OLSH_ = uint32(OLSH) << 16
|
|
|
|
ORSH_ = uint32(ORSH) << 16
|
|
|
|
OADD_ = uint32(OADD) << 16
|
|
|
|
OSUB_ = uint32(OSUB) << 16
|
|
|
|
OMUL_ = uint32(OMUL) << 16
|
|
|
|
ODIV_ = uint32(ODIV) << 16
|
|
|
|
OMOD_ = uint32(OMOD) << 16
|
|
|
|
OOR_ = uint32(OOR) << 16
|
|
|
|
OAND_ = uint32(OAND) << 16
|
|
|
|
OANDNOT_ = uint32(OANDNOT) << 16
|
|
|
|
OXOR_ = uint32(OXOR) << 16
|
|
|
|
OEQ_ = uint32(OEQ) << 16
|
|
|
|
ONE_ = uint32(ONE) << 16
|
|
|
|
OLT_ = uint32(OLT) << 16
|
|
|
|
OLE_ = uint32(OLE) << 16
|
|
|
|
OGE_ = uint32(OGE) << 16
|
|
|
|
OGT_ = uint32(OGT) << 16
|
|
|
|
OOROR_ = uint32(OOROR) << 16
|
|
|
|
OANDAND_ = uint32(OANDAND) << 16
|
2015-10-26 16:00:59 -07:00
|
|
|
)
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
nr := n.Right
|
|
|
|
var rv Val
|
|
|
|
var lno int
|
2016-02-29 20:07:09 -08:00
|
|
|
var wr EType
|
2015-02-23 16:07:24 -05:00
|
|
|
var v Val
|
|
|
|
var norig *Node
|
2016-01-07 03:06:49 -08:00
|
|
|
var nn *Node
|
2015-02-13 14:40:36 -05:00
|
|
|
if nr == nil {
|
2015-03-02 12:35:15 -05:00
|
|
|
// copy numeric value to avoid modifying
|
|
|
|
// nl, in case someone still refers to it (e.g. iota).
|
2015-05-27 00:47:05 -04:00
|
|
|
v = nl.Val()
|
2015-03-02 12:35:15 -05:00
|
|
|
|
|
|
|
if wl == TIDEAL {
|
|
|
|
v = copyval(v)
|
|
|
|
}
|
|
|
|
|
2015-05-26 22:50:45 -04:00
|
|
|
switch uint32(n.Op)<<16 | uint32(v.Ctype()) {
|
2015-03-02 12:35:15 -05:00
|
|
|
default:
|
|
|
|
if n.Diag == 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("illegal constant expression %v %v", Oconv(int(n.Op), 0), nl.Type)
|
2015-03-02 12:35:15 -05:00
|
|
|
n.Diag = 1
|
|
|
|
}
|
|
|
|
return
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OCONV_ | CTNIL_,
|
|
|
|
OARRAYBYTESTR_ | CTNIL_:
|
2015-03-02 12:35:15 -05:00
|
|
|
if n.Type.Etype == TSTRING {
|
|
|
|
v = tostr(v)
|
|
|
|
nl.Type = n.Type
|
|
|
|
break
|
|
|
|
}
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
// fall through
|
2015-09-24 23:21:18 +02:00
|
|
|
case OCONV_ | CTINT_,
|
|
|
|
OCONV_ | CTRUNE_,
|
|
|
|
OCONV_ | CTFLT_,
|
2016-01-05 12:26:55 -08:00
|
|
|
OCONV_ | CTSTR_,
|
|
|
|
OCONV_ | CTBOOL_:
|
2015-03-02 12:35:15 -05:00
|
|
|
convlit1(&nl, n.Type, true)
|
|
|
|
|
2015-05-27 00:47:05 -04:00
|
|
|
v = nl.Val()
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OPLUS_ | CTINT_,
|
|
|
|
OPLUS_ | CTRUNE_:
|
2015-03-02 12:35:15 -05:00
|
|
|
break
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OMINUS_ | CTINT_,
|
|
|
|
OMINUS_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpnegfix(v.U.(*Mpint))
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OCOM_ | CTINT_,
|
|
|
|
OCOM_ | CTRUNE_:
|
2016-02-29 20:07:09 -08:00
|
|
|
var et EType = Txxx
|
2015-03-02 12:35:15 -05:00
|
|
|
if nl.Type != nil {
|
2016-02-29 20:07:09 -08:00
|
|
|
et = nl.Type.Etype
|
2015-03-02 12:35:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// calculate the mask in b
|
|
|
|
// result will be (a ^ mask)
|
|
|
|
var b Mpint
|
|
|
|
switch et {
|
|
|
|
// signed guys change sign
|
|
|
|
default:
|
|
|
|
Mpmovecfix(&b, -1)
|
|
|
|
|
|
|
|
// unsigned guys invert their bits
|
|
|
|
case TUINT8,
|
|
|
|
TUINT16,
|
|
|
|
TUINT32,
|
|
|
|
TUINT64,
|
|
|
|
TUINT,
|
|
|
|
TUINTPTR:
|
|
|
|
mpmovefixfix(&b, Maxintval[et])
|
|
|
|
}
|
|
|
|
|
2015-05-14 17:57:42 -07:00
|
|
|
mpxorfixfix(v.U.(*Mpint), &b)
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OPLUS_ | CTFLT_:
|
2015-03-02 12:35:15 -05:00
|
|
|
break
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OMINUS_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpnegflt(v.U.(*Mpflt))
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OPLUS_ | CTCPLX_:
|
2015-03-02 12:35:15 -05:00
|
|
|
break
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OMINUS_ | CTCPLX_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpnegflt(&v.U.(*Mpcplx).Real)
|
|
|
|
mpnegflt(&v.U.(*Mpcplx).Imag)
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ONOT_ | CTBOOL_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if !v.U.(bool) {
|
2015-03-02 12:35:15 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
}
|
|
|
|
goto ret
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
if nr.Type == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if consttype(nr) < 0 {
|
|
|
|
return
|
|
|
|
}
|
2016-02-29 20:07:09 -08:00
|
|
|
wr = nr.Type.Etype
|
2015-03-01 07:54:01 +00:00
|
|
|
if Isint[wr] || Isfloat[wr] || Iscomplex[wr] {
|
2015-02-13 14:40:36 -05:00
|
|
|
wr = TIDEAL
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for compatible general types (numeric, string, etc)
|
|
|
|
if wl != wr {
|
|
|
|
goto illegal
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for compatible types.
|
|
|
|
switch n.Op {
|
|
|
|
// ideal const mixes with anything but otherwise must match.
|
|
|
|
default:
|
|
|
|
if nl.Type.Etype != TIDEAL {
|
|
|
|
defaultlit(&nr, nl.Type)
|
|
|
|
n.Right = nr
|
|
|
|
}
|
|
|
|
|
|
|
|
if nr.Type.Etype != TIDEAL {
|
|
|
|
defaultlit(&nl, nr.Type)
|
|
|
|
n.Left = nl
|
|
|
|
}
|
|
|
|
|
|
|
|
if nl.Type.Etype != nr.Type.Etype {
|
|
|
|
goto illegal
|
|
|
|
}
|
|
|
|
|
|
|
|
// right must be unsigned.
|
|
|
|
// left can be ideal.
|
2015-04-01 09:38:44 -07:00
|
|
|
case OLSH, ORSH:
|
2015-02-13 14:40:36 -05:00
|
|
|
defaultlit(&nr, Types[TUINT])
|
|
|
|
|
|
|
|
n.Right = nr
|
2015-03-01 07:54:01 +00:00
|
|
|
if nr.Type != nil && (Issigned[nr.Type.Etype] || !Isint[nr.Type.Etype]) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto illegal
|
|
|
|
}
|
2015-05-27 00:47:05 -04:00
|
|
|
if nl.Val().Ctype() != CTRUNE {
|
|
|
|
nl.SetVal(toint(nl.Val()))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-27 00:47:05 -04:00
|
|
|
nr.SetVal(toint(nr.Val()))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// copy numeric value to avoid modifying
|
|
|
|
// n->left, in case someone still refers to it (e.g. iota).
|
2015-05-27 00:47:05 -04:00
|
|
|
v = nl.Val()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
if wl == TIDEAL {
|
|
|
|
v = copyval(v)
|
|
|
|
}
|
|
|
|
|
2015-05-27 00:47:05 -04:00
|
|
|
rv = nr.Val()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// convert to common ideal
|
2015-05-26 22:50:45 -04:00
|
|
|
if v.Ctype() == CTCPLX || rv.Ctype() == CTCPLX {
|
2015-02-13 14:40:36 -05:00
|
|
|
v = tocplx(v)
|
|
|
|
rv = tocplx(rv)
|
|
|
|
}
|
|
|
|
|
2015-05-26 22:50:45 -04:00
|
|
|
if v.Ctype() == CTFLT || rv.Ctype() == CTFLT {
|
2015-02-13 14:40:36 -05:00
|
|
|
v = toflt(v)
|
|
|
|
rv = toflt(rv)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rune and int turns into rune.
|
2015-05-26 22:50:45 -04:00
|
|
|
if v.Ctype() == CTRUNE && rv.Ctype() == CTINT {
|
|
|
|
i := new(Mpint)
|
|
|
|
mpmovefixfix(i, rv.U.(*Mpint))
|
|
|
|
i.Rune = true
|
|
|
|
rv.U = i
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-26 22:50:45 -04:00
|
|
|
if v.Ctype() == CTINT && rv.Ctype() == CTRUNE {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Op == OLSH || n.Op == ORSH {
|
2015-05-26 22:50:45 -04:00
|
|
|
i := new(Mpint)
|
|
|
|
mpmovefixfix(i, rv.U.(*Mpint))
|
|
|
|
rv.U = i
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-05-26 22:50:45 -04:00
|
|
|
i := new(Mpint)
|
|
|
|
mpmovefixfix(i, v.U.(*Mpint))
|
|
|
|
i.Rune = true
|
|
|
|
v.U = i
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 22:50:45 -04:00
|
|
|
if v.Ctype() != rv.Ctype() {
|
2015-02-13 14:40:36 -05:00
|
|
|
// Use of undefined name as constant?
|
2015-05-26 22:50:45 -04:00
|
|
|
if (v.Ctype() == 0 || rv.Ctype() == 0) && nerrors > 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("constant type mismatch %v(%d) %v(%d)", nl.Type, v.Ctype(), nr.Type, rv.Ctype())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// run op
|
2015-05-26 22:50:45 -04:00
|
|
|
switch uint32(n.Op)<<16 | uint32(v.Ctype()) {
|
2015-02-13 14:40:36 -05:00
|
|
|
default:
|
|
|
|
goto illegal
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OADD_ | CTINT_,
|
|
|
|
OADD_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpaddfixfix(v.U.(*Mpint), rv.U.(*Mpint), 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OSUB_ | CTINT_,
|
|
|
|
OSUB_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpsubfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OMUL_ | CTINT_,
|
|
|
|
OMUL_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmulfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ODIV_ | CTINT_,
|
|
|
|
ODIV_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("division by zero")
|
2015-05-14 17:57:42 -07:00
|
|
|
mpsetovf(v.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2015-05-14 17:57:42 -07:00
|
|
|
mpdivfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OMOD_ | CTINT_,
|
|
|
|
OMOD_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("division by zero")
|
2015-05-14 17:57:42 -07:00
|
|
|
mpsetovf(v.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmodfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OLSH_ | CTINT_,
|
|
|
|
OLSH_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mplshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ORSH_ | CTINT_,
|
|
|
|
ORSH_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mprshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OOR_ | CTINT_,
|
|
|
|
OOR_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mporfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OAND_ | CTINT_,
|
|
|
|
OAND_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpandfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OANDNOT_ | CTINT_,
|
|
|
|
OANDNOT_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpandnotfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OXOR_ | CTINT_,
|
|
|
|
OXOR_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpxorfixfix(v.U.(*Mpint), rv.U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OADD_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpaddfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OSUB_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpsubfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OMUL_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmulfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ODIV_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltc(rv.U.(*Mpflt), 0) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("division by zero")
|
2015-05-14 17:57:42 -07:00
|
|
|
Mpmovecflt(v.U.(*Mpflt), 1.0)
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2015-05-14 17:57:42 -07:00
|
|
|
mpdivfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// The default case above would print 'ideal % ideal',
|
|
|
|
// which is not quite an ideal error.
|
2015-09-24 23:21:18 +02:00
|
|
|
case OMOD_ | CTFLT_:
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Diag == 0 {
|
2015-02-23 14:02:27 -05:00
|
|
|
Yyerror("illegal constant expression: floating-point %% operation")
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Diag = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OADD_ | CTCPLX_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpaddfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
|
|
|
|
mpaddfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OSUB_ | CTCPLX_:
|
2015-05-14 17:57:42 -07:00
|
|
|
mpsubfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
|
|
|
|
mpsubfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OMUL_ | CTCPLX_:
|
2015-05-14 17:57:42 -07:00
|
|
|
cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ODIV_ | CTCPLX_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltc(&rv.U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&rv.U.(*Mpcplx).Imag, 0) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("complex division by zero")
|
2015-05-14 17:57:42 -07:00
|
|
|
Mpmovecflt(&rv.U.(*Mpcplx).Real, 1.0)
|
|
|
|
Mpmovecflt(&rv.U.(*Mpcplx).Imag, 0.0)
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2015-05-14 17:57:42 -07:00
|
|
|
cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OEQ_ | CTNIL_:
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ONE_ | CTNIL_:
|
2015-02-13 14:40:36 -05:00
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OEQ_ | CTINT_,
|
|
|
|
OEQ_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ONE_ | CTINT_,
|
|
|
|
ONE_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OLT_ | CTINT_,
|
|
|
|
OLT_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) < 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OLE_ | CTINT_,
|
|
|
|
OLE_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) <= 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OGE_ | CTINT_,
|
|
|
|
OGE_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) >= 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OGT_ | CTINT_,
|
|
|
|
OGT_ | CTRUNE_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) > 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OEQ_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ONE_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OLT_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) < 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OLE_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) <= 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OGE_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) >= 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OGT_ | CTFLT_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) > 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OEQ_ | CTCPLX_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) == 0 && mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ONE_ | CTCPLX_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) != 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OEQ_ | CTSTR_:
|
2015-09-17 21:01:29 +02:00
|
|
|
if strlit(nl) == strlit(nr) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ONE_ | CTSTR_:
|
2015-09-17 21:01:29 +02:00
|
|
|
if strlit(nl) != strlit(nr) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OLT_ | CTSTR_:
|
2015-09-17 21:01:29 +02:00
|
|
|
if strlit(nl) < strlit(nr) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OLE_ | CTSTR_:
|
2015-09-17 21:01:29 +02:00
|
|
|
if strlit(nl) <= strlit(nr) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OGE_ | CTSTR_:
|
2015-09-17 21:01:29 +02:00
|
|
|
if strlit(nl) >= strlit(nr) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OGT_ | CTSTR_:
|
2015-09-17 21:01:29 +02:00
|
|
|
if strlit(nl) > strlit(nr) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OOROR_ | CTBOOL_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if v.U.(bool) || rv.U.(bool) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OANDAND_ | CTBOOL_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if v.U.(bool) && rv.U.(bool) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case OEQ_ | CTBOOL_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if v.U.(bool) == rv.U.(bool) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
case ONE_ | CTBOOL_:
|
2015-05-14 17:57:42 -07:00
|
|
|
if v.U.(bool) != rv.U.(bool) {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto settrue
|
|
|
|
}
|
|
|
|
goto setfalse
|
|
|
|
}
|
|
|
|
|
|
|
|
goto ret
|
|
|
|
|
|
|
|
ret:
|
|
|
|
norig = saveorig(n)
|
|
|
|
*n = *nl
|
|
|
|
|
|
|
|
// restore value of n->orig.
|
|
|
|
n.Orig = norig
|
|
|
|
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(v)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// check range.
|
|
|
|
lno = int(setlineno(n))
|
|
|
|
|
|
|
|
overflow(v, n.Type)
|
|
|
|
lineno = int32(lno)
|
|
|
|
|
|
|
|
// truncate precision for non-ideal float.
|
2015-05-26 22:50:45 -04:00
|
|
|
if v.Ctype() == CTFLT && n.Type.Etype != TIDEAL {
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(Val{truncfltlit(v.U.(*Mpflt), n.Type)})
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
return
|
|
|
|
|
|
|
|
settrue:
|
2016-01-07 03:06:49 -08:00
|
|
|
nn = Nodbool(true)
|
|
|
|
nn.Orig = saveorig(n)
|
|
|
|
if !iscmp[n.Op] {
|
|
|
|
nn.Type = nl.Type
|
|
|
|
}
|
|
|
|
*n = *nn
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
setfalse:
|
2016-01-07 03:06:49 -08:00
|
|
|
nn = Nodbool(false)
|
|
|
|
nn.Orig = saveorig(n)
|
|
|
|
if !iscmp[n.Op] {
|
|
|
|
nn.Type = nl.Type
|
|
|
|
}
|
|
|
|
*n = *nn
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
illegal:
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Diag == 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("illegal constant expression: %v %v %v", nl.Type, Oconv(int(n.Op), 0), nr.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Diag = 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func nodlit(v Val) *Node {
|
2015-02-23 16:07:24 -05:00
|
|
|
n := Nod(OLITERAL, nil, nil)
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(v)
|
2015-05-26 22:50:45 -04:00
|
|
|
switch v.Ctype() {
|
2015-02-13 14:40:36 -05:00
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("nodlit ctype %d", v.Ctype())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTSTR:
|
|
|
|
n.Type = idealstring
|
|
|
|
|
|
|
|
case CTBOOL:
|
|
|
|
n.Type = idealbool
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTINT, CTRUNE, CTFLT, CTCPLX:
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Type = Types[TIDEAL]
|
|
|
|
|
|
|
|
case CTNIL:
|
|
|
|
n.Type = Types[TNIL]
|
|
|
|
}
|
|
|
|
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func nodcplxlit(r Val, i Val) *Node {
|
|
|
|
r = toflt(r)
|
|
|
|
i = toflt(i)
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
c := new(Mpcplx)
|
|
|
|
n := Nod(OLITERAL, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Type = Types[TIDEAL]
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(Val{c})
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-05-26 22:50:45 -04:00
|
|
|
if r.Ctype() != CTFLT || i.Ctype() != CTFLT {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("nodcplxlit ctype %d/%d", r.Ctype(), i.Ctype())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-05-14 17:57:42 -07:00
|
|
|
mpmovefltflt(&c.Real, r.U.(*Mpflt))
|
|
|
|
mpmovefltflt(&c.Imag, i.U.(*Mpflt))
|
2015-02-13 14:40:36 -05:00
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
// idealkind returns a constant kind like consttype
|
|
|
|
// but for an arbitrary "ideal" (untyped constant) expression.
|
2015-10-26 16:00:59 -07:00
|
|
|
func idealkind(n *Node) Ctype {
|
2015-02-17 22:13:49 -05:00
|
|
|
if n == nil || !isideal(n.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
return CTxxx
|
|
|
|
}
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
default:
|
|
|
|
return CTxxx
|
|
|
|
|
|
|
|
case OLITERAL:
|
2015-10-26 16:00:59 -07:00
|
|
|
return n.Val().Ctype()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// numeric kinds.
|
|
|
|
case OADD,
|
|
|
|
OAND,
|
|
|
|
OANDNOT,
|
|
|
|
OCOM,
|
|
|
|
ODIV,
|
|
|
|
OMINUS,
|
|
|
|
OMOD,
|
|
|
|
OMUL,
|
|
|
|
OSUB,
|
|
|
|
OXOR,
|
|
|
|
OOR,
|
|
|
|
OPLUS:
|
2015-02-23 16:07:24 -05:00
|
|
|
k1 := idealkind(n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
k2 := idealkind(n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
if k1 > k2 {
|
|
|
|
return k1
|
|
|
|
} else {
|
|
|
|
return k2
|
|
|
|
}
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OREAL, OIMAG:
|
2015-02-13 14:40:36 -05:00
|
|
|
return CTFLT
|
|
|
|
|
|
|
|
case OCOMPLEX:
|
|
|
|
return CTCPLX
|
|
|
|
|
|
|
|
case OADDSTR:
|
|
|
|
return CTSTR
|
|
|
|
|
|
|
|
case OANDAND,
|
|
|
|
OEQ,
|
|
|
|
OGE,
|
|
|
|
OGT,
|
|
|
|
OLE,
|
|
|
|
OLT,
|
|
|
|
ONE,
|
|
|
|
ONOT,
|
|
|
|
OOROR,
|
|
|
|
OCMPSTR,
|
|
|
|
OCMPIFACE:
|
|
|
|
return CTBOOL
|
|
|
|
|
|
|
|
// shifts (beware!).
|
2015-04-01 09:38:44 -07:00
|
|
|
case OLSH, ORSH:
|
2015-02-13 14:40:36 -05:00
|
|
|
return idealkind(n.Left)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func defaultlit(np **Node, t *Type) {
|
2015-02-23 16:07:24 -05:00
|
|
|
n := *np
|
2015-02-17 22:13:49 -05:00
|
|
|
if n == nil || !isideal(n.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if n.Op == OLITERAL {
|
2015-02-23 16:07:24 -05:00
|
|
|
nn := Nod(OXXX, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
*nn = *n
|
|
|
|
n = nn
|
|
|
|
*np = n
|
|
|
|
}
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
lno := int(setlineno(n))
|
|
|
|
ctype := idealkind(n)
|
|
|
|
var t1 *Type
|
2015-02-13 14:40:36 -05:00
|
|
|
switch ctype {
|
|
|
|
default:
|
|
|
|
if t != nil {
|
|
|
|
Convlit(np, t)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-05-27 00:47:05 -04:00
|
|
|
if n.Val().Ctype() == CTNIL {
|
2015-02-13 14:40:36 -05:00
|
|
|
lineno = int32(lno)
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Diag == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("use of untyped nil")
|
|
|
|
n.Diag = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Type = nil
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2015-05-27 00:47:05 -04:00
|
|
|
if n.Val().Ctype() == CTSTR {
|
2015-02-23 16:07:24 -05:00
|
|
|
t1 := Types[TSTRING]
|
2015-02-13 14:40:36 -05:00
|
|
|
Convlit(np, t1)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("defaultlit: unknown literal: %v", n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTxxx:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("defaultlit: idealkind is CTxxx: %v", Nconv(n, obj.FmtSign))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTBOOL:
|
2015-02-23 16:07:24 -05:00
|
|
|
t1 := Types[TBOOL]
|
2015-02-13 14:40:36 -05:00
|
|
|
if t != nil && t.Etype == TBOOL {
|
|
|
|
t1 = t
|
|
|
|
}
|
|
|
|
Convlit(np, t1)
|
|
|
|
|
|
|
|
case CTINT:
|
|
|
|
t1 = Types[TINT]
|
|
|
|
goto num
|
|
|
|
|
|
|
|
case CTRUNE:
|
|
|
|
t1 = runetype
|
|
|
|
goto num
|
|
|
|
|
|
|
|
case CTFLT:
|
|
|
|
t1 = Types[TFLOAT64]
|
|
|
|
goto num
|
|
|
|
|
|
|
|
case CTCPLX:
|
|
|
|
t1 = Types[TCOMPLEX128]
|
|
|
|
goto num
|
|
|
|
}
|
|
|
|
|
|
|
|
lineno = int32(lno)
|
|
|
|
return
|
|
|
|
|
|
|
|
num:
|
2015-11-17 16:34:06 -05:00
|
|
|
// Note: n.Val().Ctype() can be CTxxx (not a constant) here
|
|
|
|
// in the case of an untyped non-constant value, like 1<<i.
|
|
|
|
v1 := n.Val()
|
2015-02-13 14:40:36 -05:00
|
|
|
if t != nil {
|
2015-03-01 07:54:01 +00:00
|
|
|
if Isint[t.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
t1 = t
|
2015-11-17 16:34:06 -05:00
|
|
|
v1 = toint(n.Val())
|
2015-03-01 07:54:01 +00:00
|
|
|
} else if Isfloat[t.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
t1 = t
|
2015-11-17 16:34:06 -05:00
|
|
|
v1 = toflt(n.Val())
|
2015-03-01 07:54:01 +00:00
|
|
|
} else if Iscomplex[t.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
t1 = t
|
2015-11-17 16:34:06 -05:00
|
|
|
v1 = tocplx(n.Val())
|
|
|
|
}
|
|
|
|
if n.Val().Ctype() != CTxxx {
|
|
|
|
n.SetVal(v1)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 16:34:06 -05:00
|
|
|
if n.Val().Ctype() != CTxxx {
|
|
|
|
overflow(n.Val(), t1)
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
Convlit(np, t1)
|
|
|
|
lineno = int32(lno)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// defaultlit on both nodes simultaneously;
|
|
|
|
// if they're both ideal going in they better
|
|
|
|
// get the same type going out.
|
|
|
|
// force means must assign concrete (non-ideal) type.
|
2016-03-01 00:15:27 -08:00
|
|
|
func defaultlit2(lp **Node, rp **Node, force bool) {
|
2015-02-23 16:07:24 -05:00
|
|
|
l := *lp
|
|
|
|
r := *rp
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.Type == nil || r.Type == nil {
|
|
|
|
return
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if !isideal(l.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
Convlit(rp, l.Type)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if !isideal(r.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
Convlit(lp, r.Type)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-03-01 00:15:27 -08:00
|
|
|
if !force {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
2016-03-01 00:15:27 -08:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.Type.Etype == TBOOL {
|
|
|
|
Convlit(lp, Types[TBOOL])
|
|
|
|
Convlit(rp, Types[TBOOL])
|
|
|
|
}
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
lkind := idealkind(l)
|
|
|
|
rkind := idealkind(r)
|
2015-02-13 14:40:36 -05:00
|
|
|
if lkind == CTCPLX || rkind == CTCPLX {
|
|
|
|
Convlit(lp, Types[TCOMPLEX128])
|
|
|
|
Convlit(rp, Types[TCOMPLEX128])
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if lkind == CTFLT || rkind == CTFLT {
|
|
|
|
Convlit(lp, Types[TFLOAT64])
|
|
|
|
Convlit(rp, Types[TFLOAT64])
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if lkind == CTRUNE || rkind == CTRUNE {
|
|
|
|
Convlit(lp, runetype)
|
|
|
|
Convlit(rp, runetype)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
Convlit(lp, Types[TINT])
|
|
|
|
Convlit(rp, Types[TINT])
|
|
|
|
}
|
|
|
|
|
2015-09-17 21:01:29 +02:00
|
|
|
// strlit returns the value of a literal string Node as a string.
|
|
|
|
func strlit(n *Node) string {
|
|
|
|
return n.Val().U.(string)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func Smallintconst(n *Node) bool {
|
|
|
|
if n.Op == OLITERAL && Isconst(n, CTINT) && n.Type != nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch Simtype[n.Type.Etype] {
|
|
|
|
case TINT8,
|
|
|
|
TUINT8,
|
|
|
|
TINT16,
|
|
|
|
TUINT16,
|
|
|
|
TINT32,
|
|
|
|
TUINT32,
|
|
|
|
TBOOL,
|
|
|
|
TPTR32:
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case TIDEAL, TINT64, TUINT64, TPTR64:
|
2015-05-27 00:47:05 -04:00
|
|
|
if Mpcmpfixfix(n.Val().U.(*Mpint), Minintval[TINT32]) < 0 || Mpcmpfixfix(n.Val().U.(*Mpint), Maxintval[TINT32]) > 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func nonnegconst(n *Node) int {
|
|
|
|
if n.Op == OLITERAL && n.Type != nil {
|
|
|
|
switch Simtype[n.Type.Etype] {
|
|
|
|
// check negative and 2^31
|
|
|
|
case TINT8,
|
|
|
|
TUINT8,
|
|
|
|
TINT16,
|
|
|
|
TUINT16,
|
|
|
|
TINT32,
|
|
|
|
TUINT32,
|
|
|
|
TINT64,
|
|
|
|
TUINT64,
|
|
|
|
TIDEAL:
|
2015-05-27 00:47:05 -04:00
|
|
|
if Mpcmpfixfix(n.Val().U.(*Mpint), Minintval[TUINT32]) < 0 || Mpcmpfixfix(n.Val().U.(*Mpint), Maxintval[TINT32]) > 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
2015-05-27 00:47:05 -04:00
|
|
|
return int(Mpgetfix(n.Val().U.(*Mpint)))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// convert x to type et and back to int64
|
|
|
|
// for sign extension and truncation.
|
2015-09-24 23:21:18 +02:00
|
|
|
func iconv(x int64, et EType) int64 {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch et {
|
|
|
|
case TINT8:
|
|
|
|
x = int64(int8(x))
|
|
|
|
|
|
|
|
case TUINT8:
|
|
|
|
x = int64(uint8(x))
|
|
|
|
|
|
|
|
case TINT16:
|
|
|
|
x = int64(int16(x))
|
|
|
|
|
|
|
|
case TUINT16:
|
|
|
|
x = int64(uint64(x))
|
|
|
|
|
|
|
|
case TINT32:
|
|
|
|
x = int64(int32(x))
|
|
|
|
|
|
|
|
case TUINT32:
|
|
|
|
x = int64(uint32(x))
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case TINT64, TUINT64:
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
return x
|
|
|
|
}
|
|
|
|
|
2015-05-07 18:43:03 -07:00
|
|
|
// Convconst converts constant node n to type t and
|
|
|
|
// places the result in con.
|
|
|
|
func (n *Node) Convconst(con *Node, t *Type) {
|
2015-02-23 16:07:24 -05:00
|
|
|
tt := Simsimtype(t)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// copy the constant for conversion
|
|
|
|
Nodconst(con, Types[TINT8], 0)
|
|
|
|
|
|
|
|
con.Type = t
|
2015-05-27 00:47:05 -04:00
|
|
|
con.SetVal(n.Val())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-01 07:54:01 +00:00
|
|
|
if Isint[tt] {
|
2015-05-27 00:47:05 -04:00
|
|
|
con.SetVal(Val{new(Mpint)})
|
2015-02-23 16:07:24 -05:00
|
|
|
var i int64
|
2015-05-27 00:47:05 -04:00
|
|
|
switch n.Val().Ctype() {
|
2015-02-13 14:40:36 -05:00
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("convconst ctype=%d %v", n.Val().Ctype(), Tconv(t, obj.FmtLong))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case CTINT, CTRUNE:
|
2015-05-27 00:47:05 -04:00
|
|
|
i = Mpgetfix(n.Val().U.(*Mpint))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTBOOL:
|
2015-05-27 00:47:05 -04:00
|
|
|
i = int64(obj.Bool2int(n.Val().U.(bool)))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case CTNIL:
|
|
|
|
i = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
i = iconv(i, tt)
|
2015-05-27 00:47:05 -04:00
|
|
|
Mpmovecfix(con.Val().U.(*Mpint), i)
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-03-01 07:54:01 +00:00
|
|
|
if Isfloat[tt] {
|
2015-05-27 00:47:05 -04:00
|
|
|
con.SetVal(toflt(con.Val()))
|
|
|
|
if con.Val().Ctype() != CTFLT {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("convconst ctype=%d %v", con.Val().Ctype(), t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
if tt == TFLOAT32 {
|
2015-05-27 00:47:05 -04:00
|
|
|
con.SetVal(Val{truncfltlit(con.Val().U.(*Mpflt), t)})
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-03-01 07:54:01 +00:00
|
|
|
if Iscomplex[tt] {
|
2015-05-27 00:47:05 -04:00
|
|
|
con.SetVal(tocplx(con.Val()))
|
2015-02-13 14:40:36 -05:00
|
|
|
if tt == TCOMPLEX64 {
|
2015-05-27 00:47:05 -04:00
|
|
|
con.Val().U.(*Mpcplx).Real = *truncfltlit(&con.Val().U.(*Mpcplx).Real, Types[TFLOAT32])
|
|
|
|
con.Val().U.(*Mpcplx).Imag = *truncfltlit(&con.Val().U.(*Mpcplx).Imag, Types[TFLOAT32])
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("convconst %v constant", Tconv(t, obj.FmtLong))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// complex multiply v *= rv
|
|
|
|
// (a, b) * (c, d) = (a*c - b*d, b*c + a*d)
|
|
|
|
func cmplxmpy(v *Mpcplx, rv *Mpcplx) {
|
|
|
|
var ac Mpflt
|
|
|
|
var bd Mpflt
|
|
|
|
var bc Mpflt
|
|
|
|
var ad Mpflt
|
|
|
|
|
|
|
|
mpmovefltflt(&ac, &v.Real)
|
|
|
|
mpmulfltflt(&ac, &rv.Real) // ac
|
|
|
|
|
|
|
|
mpmovefltflt(&bd, &v.Imag)
|
|
|
|
|
|
|
|
mpmulfltflt(&bd, &rv.Imag) // bd
|
|
|
|
|
|
|
|
mpmovefltflt(&bc, &v.Imag)
|
|
|
|
|
|
|
|
mpmulfltflt(&bc, &rv.Real) // bc
|
|
|
|
|
|
|
|
mpmovefltflt(&ad, &v.Real)
|
|
|
|
|
|
|
|
mpmulfltflt(&ad, &rv.Imag) // ad
|
|
|
|
|
|
|
|
mpmovefltflt(&v.Real, &ac)
|
|
|
|
|
|
|
|
mpsubfltflt(&v.Real, &bd) // ac-bd
|
|
|
|
|
|
|
|
mpmovefltflt(&v.Imag, &bc)
|
|
|
|
|
|
|
|
mpaddfltflt(&v.Imag, &ad) // bc+ad
|
|
|
|
}
|
|
|
|
|
|
|
|
// complex divide v /= rv
|
|
|
|
// (a, b) / (c, d) = ((a*c + b*d), (b*c - a*d))/(c*c + d*d)
|
|
|
|
func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
|
|
|
|
var ac Mpflt
|
|
|
|
var bd Mpflt
|
|
|
|
var bc Mpflt
|
|
|
|
var ad Mpflt
|
|
|
|
var cc_plus_dd Mpflt
|
|
|
|
|
|
|
|
mpmovefltflt(&cc_plus_dd, &rv.Real)
|
|
|
|
mpmulfltflt(&cc_plus_dd, &rv.Real) // cc
|
|
|
|
|
|
|
|
mpmovefltflt(&ac, &rv.Imag)
|
|
|
|
|
|
|
|
mpmulfltflt(&ac, &rv.Imag) // dd
|
|
|
|
|
|
|
|
mpaddfltflt(&cc_plus_dd, &ac) // cc+dd
|
|
|
|
|
|
|
|
mpmovefltflt(&ac, &v.Real)
|
|
|
|
|
|
|
|
mpmulfltflt(&ac, &rv.Real) // ac
|
|
|
|
|
|
|
|
mpmovefltflt(&bd, &v.Imag)
|
|
|
|
|
|
|
|
mpmulfltflt(&bd, &rv.Imag) // bd
|
|
|
|
|
|
|
|
mpmovefltflt(&bc, &v.Imag)
|
|
|
|
|
|
|
|
mpmulfltflt(&bc, &rv.Real) // bc
|
|
|
|
|
|
|
|
mpmovefltflt(&ad, &v.Real)
|
|
|
|
|
|
|
|
mpmulfltflt(&ad, &rv.Imag) // ad
|
|
|
|
|
|
|
|
mpmovefltflt(&v.Real, &ac)
|
|
|
|
|
|
|
|
mpaddfltflt(&v.Real, &bd) // ac+bd
|
|
|
|
mpdivfltflt(&v.Real, &cc_plus_dd) // (ac+bd)/(cc+dd)
|
|
|
|
|
|
|
|
mpmovefltflt(&v.Imag, &bc)
|
|
|
|
|
|
|
|
mpsubfltflt(&v.Imag, &ad) // bc-ad
|
|
|
|
mpdivfltflt(&v.Imag, &cc_plus_dd) // (bc+ad)/(cc+dd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is n a Go language constant (as opposed to a compile-time constant)?
|
|
|
|
// Expressions derived from nil, like string([]byte(nil)), while they
|
|
|
|
// may be known at compile time, are not Go language constants.
|
|
|
|
// Only called for expressions known to evaluated to compile-time
|
|
|
|
// constants.
|
2015-02-17 22:13:49 -05:00
|
|
|
func isgoconst(n *Node) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Orig != nil {
|
|
|
|
n = n.Orig
|
|
|
|
}
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
case OADD,
|
|
|
|
OADDSTR,
|
|
|
|
OAND,
|
|
|
|
OANDAND,
|
|
|
|
OANDNOT,
|
|
|
|
OCOM,
|
|
|
|
ODIV,
|
|
|
|
OEQ,
|
|
|
|
OGE,
|
|
|
|
OGT,
|
|
|
|
OLE,
|
|
|
|
OLSH,
|
|
|
|
OLT,
|
|
|
|
OMINUS,
|
|
|
|
OMOD,
|
|
|
|
OMUL,
|
|
|
|
ONE,
|
|
|
|
ONOT,
|
|
|
|
OOR,
|
|
|
|
OOROR,
|
|
|
|
OPLUS,
|
|
|
|
ORSH,
|
|
|
|
OSUB,
|
|
|
|
OXOR,
|
|
|
|
OIOTA,
|
|
|
|
OCOMPLEX,
|
|
|
|
OREAL,
|
|
|
|
OIMAG:
|
2015-02-17 22:13:49 -05:00
|
|
|
if isgoconst(n.Left) && (n.Right == nil || isgoconst(n.Right)) {
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case OCONV:
|
2015-03-01 07:54:01 +00:00
|
|
|
if okforconst[n.Type.Etype] && isgoconst(n.Left) {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OLEN, OCAP:
|
2015-02-23 16:07:24 -05:00
|
|
|
l := n.Left
|
2015-02-17 22:13:49 -05:00
|
|
|
if isgoconst(l) {
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Special case: len/cap is constant when applied to array or
|
|
|
|
// pointer to array when the expression does not contain
|
|
|
|
// function calls or channel receive operations.
|
2015-02-23 16:07:24 -05:00
|
|
|
t := l.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-01 07:54:01 +00:00
|
|
|
if t != nil && Isptr[t.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
t = t.Type
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if Isfixedarray(t) && !hascallchan(l) {
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case OLITERAL:
|
2015-05-27 00:47:05 -04:00
|
|
|
if n.Val().Ctype() != CTNIL {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case ONAME:
|
2015-02-23 16:07:24 -05:00
|
|
|
l := n.Sym.Def
|
2015-05-27 00:47:05 -04:00
|
|
|
if l != nil && l.Op == OLITERAL && n.Val().Ctype() != CTNIL {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case ONONAME:
|
|
|
|
if n.Sym.Def != nil && n.Sym.Def.Op == OIOTA {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Only constant calls are unsafe.Alignof, Offsetof, and Sizeof.
|
|
|
|
case OCALL:
|
2015-02-23 16:07:24 -05:00
|
|
|
l := n.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
for l.Op == OPAREN {
|
|
|
|
l = l.Left
|
|
|
|
}
|
|
|
|
if l.Op != ONAME || l.Sym.Pkg != unsafepkg {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if l.Sym.Name == "Alignof" || l.Sym.Name == "Offsetof" || l.Sym.Name == "Sizeof" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//dump("nonconst", n);
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func hascallchan(n *Node) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
switch n.Op {
|
|
|
|
case OAPPEND,
|
|
|
|
OCALL,
|
|
|
|
OCALLFUNC,
|
|
|
|
OCALLINTER,
|
|
|
|
OCALLMETH,
|
|
|
|
OCAP,
|
|
|
|
OCLOSE,
|
|
|
|
OCOMPLEX,
|
|
|
|
OCOPY,
|
|
|
|
ODELETE,
|
|
|
|
OIMAG,
|
|
|
|
OLEN,
|
|
|
|
OMAKE,
|
|
|
|
ONEW,
|
|
|
|
OPANIC,
|
|
|
|
OPRINT,
|
|
|
|
OPRINTN,
|
|
|
|
OREAL,
|
|
|
|
ORECOVER,
|
|
|
|
ORECV:
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if hascallchan(n.Left) || hascallchan(n.Right) {
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := n.List; l != nil; l = l.Next {
|
2015-02-17 22:13:49 -05:00
|
|
|
if hascallchan(l.N) {
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := n.Rlist; l != nil; l = l.Next {
|
2015-02-17 22:13:49 -05:00
|
|
|
if hascallchan(l.N) {
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|