mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Passes toolstash/buildall.
[git-generate]
cd src/cmd/compile/internal/ssa
rf '
ex . ../ir ../gc {
import "cmd/compile/internal/types"
var t *types.Type
t.Etype -> t.Kind()
t.Sym -> t.GetSym()
t.Orig -> t.Underlying()
}
'
cd ../types
rf '
mv EType Kind
mv IRNode Object
mv Type.Etype Type.kind
mv Type.Sym Type.sym
mv Type.Orig Type.underlying
mv Type.Cache Type.cache
mv Type.GetSym Type.Sym
mv Bytetype ByteType
mv Runetype RuneType
mv Errortype ErrorType
'
cd ../gc
sed -i 's/Bytetype/ByteType/; s/Runetype/RuneType/' mkbuiltin.go
git codereview gofmt
go install cmd/compile/internal/...
go test cmd/compile -u || go test cmd/compile
Change-Id: Ibecb2d7100d3318a49238eb4a78d70acb49eedca
Reviewed-on: https://go-review.googlesource.com/c/go/+/274437
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
362 lines
9 KiB
Go
362 lines
9 KiB
Go
// 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.
|
|
|
|
// TODO(gri) This file should probably become part of package types.
|
|
|
|
package gc
|
|
|
|
import (
|
|
"cmd/compile/internal/base"
|
|
"cmd/compile/internal/ir"
|
|
"cmd/compile/internal/types"
|
|
"cmd/internal/src"
|
|
)
|
|
|
|
var basicTypes = [...]struct {
|
|
name string
|
|
etype types.Kind
|
|
}{
|
|
{"int8", types.TINT8},
|
|
{"int16", types.TINT16},
|
|
{"int32", types.TINT32},
|
|
{"int64", types.TINT64},
|
|
{"uint8", types.TUINT8},
|
|
{"uint16", types.TUINT16},
|
|
{"uint32", types.TUINT32},
|
|
{"uint64", types.TUINT64},
|
|
{"float32", types.TFLOAT32},
|
|
{"float64", types.TFLOAT64},
|
|
{"complex64", types.TCOMPLEX64},
|
|
{"complex128", types.TCOMPLEX128},
|
|
{"bool", types.TBOOL},
|
|
{"string", types.TSTRING},
|
|
}
|
|
|
|
var typedefs = [...]struct {
|
|
name string
|
|
etype types.Kind
|
|
sameas32 types.Kind
|
|
sameas64 types.Kind
|
|
}{
|
|
{"int", types.TINT, types.TINT32, types.TINT64},
|
|
{"uint", types.TUINT, types.TUINT32, types.TUINT64},
|
|
{"uintptr", types.TUINTPTR, types.TUINT32, types.TUINT64},
|
|
}
|
|
|
|
var builtinFuncs = [...]struct {
|
|
name string
|
|
op ir.Op
|
|
}{
|
|
{"append", ir.OAPPEND},
|
|
{"cap", ir.OCAP},
|
|
{"close", ir.OCLOSE},
|
|
{"complex", ir.OCOMPLEX},
|
|
{"copy", ir.OCOPY},
|
|
{"delete", ir.ODELETE},
|
|
{"imag", ir.OIMAG},
|
|
{"len", ir.OLEN},
|
|
{"make", ir.OMAKE},
|
|
{"new", ir.ONEW},
|
|
{"panic", ir.OPANIC},
|
|
{"print", ir.OPRINT},
|
|
{"println", ir.OPRINTN},
|
|
{"real", ir.OREAL},
|
|
{"recover", ir.ORECOVER},
|
|
}
|
|
|
|
// isBuiltinFuncName reports whether name matches a builtin function
|
|
// name.
|
|
func isBuiltinFuncName(name string) bool {
|
|
for _, fn := range &builtinFuncs {
|
|
if fn.name == name {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
var unsafeFuncs = [...]struct {
|
|
name string
|
|
op ir.Op
|
|
}{
|
|
{"Alignof", ir.OALIGNOF},
|
|
{"Offsetof", ir.OOFFSETOF},
|
|
{"Sizeof", ir.OSIZEOF},
|
|
}
|
|
|
|
// initUniverse initializes the universe block.
|
|
func initUniverse() {
|
|
if Widthptr == 0 {
|
|
base.Fatalf("typeinit before betypeinit")
|
|
}
|
|
|
|
slicePtrOffset = 0
|
|
sliceLenOffset = Rnd(slicePtrOffset+int64(Widthptr), int64(Widthptr))
|
|
sliceCapOffset = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr))
|
|
sizeofSlice = Rnd(sliceCapOffset+int64(Widthptr), int64(Widthptr))
|
|
|
|
// string is same as slice wo the cap
|
|
sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr))
|
|
|
|
for et := types.Kind(0); et < types.NTYPE; et++ {
|
|
simtype[et] = et
|
|
}
|
|
|
|
types.Types[types.TANY] = types.New(types.TANY)
|
|
types.Types[types.TINTER] = types.New(types.TINTER) // empty interface
|
|
|
|
defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type {
|
|
sym := pkg.Lookup(name)
|
|
n := ir.NewNameAt(src.NoXPos, sym)
|
|
n.SetOp(ir.OTYPE)
|
|
t := types.NewBasic(kind, n)
|
|
n.SetType(t)
|
|
sym.Def = n
|
|
if kind != types.TANY {
|
|
dowidth(t)
|
|
}
|
|
return t
|
|
}
|
|
|
|
for _, s := range &basicTypes {
|
|
types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name)
|
|
}
|
|
|
|
for _, s := range &typedefs {
|
|
sameas := s.sameas32
|
|
if Widthptr == 8 {
|
|
sameas = s.sameas64
|
|
}
|
|
simtype[s.etype] = sameas
|
|
|
|
types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name)
|
|
}
|
|
|
|
// We create separate byte and rune types for better error messages
|
|
// rather than just creating type alias *types.Sym's for the uint8 and
|
|
// int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false.
|
|
// TODO(gri) Should we get rid of this special case (at the cost
|
|
// of less informative error messages involving bytes and runes)?
|
|
// (Alternatively, we could introduce an OTALIAS node representing
|
|
// type aliases, albeit at the cost of having to deal with it everywhere).
|
|
types.ByteType = defBasic(types.TUINT8, ir.BuiltinPkg, "byte")
|
|
types.RuneType = defBasic(types.TINT32, ir.BuiltinPkg, "rune")
|
|
|
|
// error type
|
|
s := ir.BuiltinPkg.Lookup("error")
|
|
n := ir.NewNameAt(src.NoXPos, s)
|
|
n.SetOp(ir.OTYPE)
|
|
types.ErrorType = types.NewNamed(n)
|
|
types.ErrorType.SetUnderlying(makeErrorInterface())
|
|
n.SetType(types.ErrorType)
|
|
s.Def = n
|
|
dowidth(types.ErrorType)
|
|
|
|
types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, unsafepkg, "Pointer")
|
|
|
|
// simple aliases
|
|
simtype[types.TMAP] = types.TPTR
|
|
simtype[types.TCHAN] = types.TPTR
|
|
simtype[types.TFUNC] = types.TPTR
|
|
simtype[types.TUNSAFEPTR] = types.TPTR
|
|
|
|
for _, s := range &builtinFuncs {
|
|
s2 := ir.BuiltinPkg.Lookup(s.name)
|
|
s2.Def = NewName(s2)
|
|
ir.AsNode(s2.Def).SetSubOp(s.op)
|
|
}
|
|
|
|
for _, s := range &unsafeFuncs {
|
|
s2 := unsafepkg.Lookup(s.name)
|
|
s2.Def = NewName(s2)
|
|
ir.AsNode(s2.Def).SetSubOp(s.op)
|
|
}
|
|
|
|
s = ir.BuiltinPkg.Lookup("true")
|
|
s.Def = nodbool(true)
|
|
ir.AsNode(s.Def).SetSym(lookup("true"))
|
|
|
|
s = ir.BuiltinPkg.Lookup("false")
|
|
s.Def = nodbool(false)
|
|
ir.AsNode(s.Def).SetSym(lookup("false"))
|
|
|
|
s = lookup("_")
|
|
s.Block = -100
|
|
s.Def = NewName(s)
|
|
types.Types[types.TBLANK] = types.New(types.TBLANK)
|
|
ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
|
|
ir.BlankNode = ir.AsNode(s.Def)
|
|
ir.BlankNode.SetTypecheck(1)
|
|
|
|
s = ir.BuiltinPkg.Lookup("_")
|
|
s.Block = -100
|
|
s.Def = NewName(s)
|
|
types.Types[types.TBLANK] = types.New(types.TBLANK)
|
|
ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
|
|
|
|
types.Types[types.TNIL] = types.New(types.TNIL)
|
|
s = ir.BuiltinPkg.Lookup("nil")
|
|
s.Def = nodnil()
|
|
ir.AsNode(s.Def).SetSym(s)
|
|
|
|
s = ir.BuiltinPkg.Lookup("iota")
|
|
s.Def = ir.Nod(ir.OIOTA, nil, nil)
|
|
ir.AsNode(s.Def).SetSym(s)
|
|
|
|
for et := types.TINT8; et <= types.TUINT64; et++ {
|
|
isInt[et] = true
|
|
}
|
|
isInt[types.TINT] = true
|
|
isInt[types.TUINT] = true
|
|
isInt[types.TUINTPTR] = true
|
|
|
|
isFloat[types.TFLOAT32] = true
|
|
isFloat[types.TFLOAT64] = true
|
|
|
|
isComplex[types.TCOMPLEX64] = true
|
|
isComplex[types.TCOMPLEX128] = true
|
|
|
|
// initialize okfor
|
|
for et := types.Kind(0); et < types.NTYPE; et++ {
|
|
if isInt[et] || et == types.TIDEAL {
|
|
okforeq[et] = true
|
|
okforcmp[et] = true
|
|
okforarith[et] = true
|
|
okforadd[et] = true
|
|
okforand[et] = true
|
|
ir.OKForConst[et] = true
|
|
issimple[et] = true
|
|
}
|
|
|
|
if isFloat[et] {
|
|
okforeq[et] = true
|
|
okforcmp[et] = true
|
|
okforadd[et] = true
|
|
okforarith[et] = true
|
|
ir.OKForConst[et] = true
|
|
issimple[et] = true
|
|
}
|
|
|
|
if isComplex[et] {
|
|
okforeq[et] = true
|
|
okforadd[et] = true
|
|
okforarith[et] = true
|
|
ir.OKForConst[et] = true
|
|
issimple[et] = true
|
|
}
|
|
}
|
|
|
|
issimple[types.TBOOL] = true
|
|
|
|
okforadd[types.TSTRING] = true
|
|
|
|
okforbool[types.TBOOL] = true
|
|
|
|
okforcap[types.TARRAY] = true
|
|
okforcap[types.TCHAN] = true
|
|
okforcap[types.TSLICE] = true
|
|
|
|
ir.OKForConst[types.TBOOL] = true
|
|
ir.OKForConst[types.TSTRING] = true
|
|
|
|
okforlen[types.TARRAY] = true
|
|
okforlen[types.TCHAN] = true
|
|
okforlen[types.TMAP] = true
|
|
okforlen[types.TSLICE] = true
|
|
okforlen[types.TSTRING] = true
|
|
|
|
okforeq[types.TPTR] = true
|
|
okforeq[types.TUNSAFEPTR] = true
|
|
okforeq[types.TINTER] = true
|
|
okforeq[types.TCHAN] = true
|
|
okforeq[types.TSTRING] = true
|
|
okforeq[types.TBOOL] = true
|
|
okforeq[types.TMAP] = true // nil only; refined in typecheck
|
|
okforeq[types.TFUNC] = true // nil only; refined in typecheck
|
|
okforeq[types.TSLICE] = true // nil only; refined in typecheck
|
|
okforeq[types.TARRAY] = true // only if element type is comparable; refined in typecheck
|
|
okforeq[types.TSTRUCT] = true // only if all struct fields are comparable; refined in typecheck
|
|
|
|
okforcmp[types.TSTRING] = true
|
|
|
|
for i := range okfor {
|
|
okfor[i] = okfornone[:]
|
|
}
|
|
|
|
// binary
|
|
okfor[ir.OADD] = okforadd[:]
|
|
okfor[ir.OAND] = okforand[:]
|
|
okfor[ir.OANDAND] = okforbool[:]
|
|
okfor[ir.OANDNOT] = okforand[:]
|
|
okfor[ir.ODIV] = okforarith[:]
|
|
okfor[ir.OEQ] = okforeq[:]
|
|
okfor[ir.OGE] = okforcmp[:]
|
|
okfor[ir.OGT] = okforcmp[:]
|
|
okfor[ir.OLE] = okforcmp[:]
|
|
okfor[ir.OLT] = okforcmp[:]
|
|
okfor[ir.OMOD] = okforand[:]
|
|
okfor[ir.OMUL] = okforarith[:]
|
|
okfor[ir.ONE] = okforeq[:]
|
|
okfor[ir.OOR] = okforand[:]
|
|
okfor[ir.OOROR] = okforbool[:]
|
|
okfor[ir.OSUB] = okforarith[:]
|
|
okfor[ir.OXOR] = okforand[:]
|
|
okfor[ir.OLSH] = okforand[:]
|
|
okfor[ir.ORSH] = okforand[:]
|
|
|
|
// unary
|
|
okfor[ir.OBITNOT] = okforand[:]
|
|
okfor[ir.ONEG] = okforarith[:]
|
|
okfor[ir.ONOT] = okforbool[:]
|
|
okfor[ir.OPLUS] = okforarith[:]
|
|
|
|
// special
|
|
okfor[ir.OCAP] = okforcap[:]
|
|
okfor[ir.OLEN] = okforlen[:]
|
|
|
|
// comparison
|
|
iscmp[ir.OLT] = true
|
|
iscmp[ir.OGT] = true
|
|
iscmp[ir.OGE] = true
|
|
iscmp[ir.OLE] = true
|
|
iscmp[ir.OEQ] = true
|
|
iscmp[ir.ONE] = true
|
|
}
|
|
|
|
func makeErrorInterface() *types.Type {
|
|
sig := functypefield(fakeRecvField(), nil, []*types.Field{
|
|
types.NewField(src.NoXPos, nil, types.Types[types.TSTRING]),
|
|
})
|
|
|
|
method := types.NewField(src.NoXPos, lookup("Error"), sig)
|
|
|
|
t := types.New(types.TINTER)
|
|
t.SetInterface([]*types.Field{method})
|
|
return t
|
|
}
|
|
|
|
// finishUniverse makes the universe block visible within the current package.
|
|
func finishUniverse() {
|
|
// Operationally, this is similar to a dot import of builtinpkg, except
|
|
// that we silently skip symbols that are already declared in the
|
|
// package block rather than emitting a redeclared symbol error.
|
|
|
|
for _, s := range ir.BuiltinPkg.Syms {
|
|
if s.Def == nil {
|
|
continue
|
|
}
|
|
s1 := lookup(s.Name)
|
|
if s1.Def != nil {
|
|
continue
|
|
}
|
|
|
|
s1.Def = s.Def
|
|
s1.Block = s.Block
|
|
}
|
|
|
|
nodfp = NewName(lookup(".fp"))
|
|
nodfp.SetType(types.Types[types.TINT32])
|
|
nodfp.SetClass(ir.PPARAM)
|
|
nodfp.Name().SetUsed(true)
|
|
}
|