diff options
author | Russ Cox <rsc@golang.org> | 2020-12-23 00:41:49 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2020-12-23 06:38:26 +0000 |
commit | b9693d7627089204e6c2448f543c3512d86dae70 (patch) | |
tree | 0f869f5abb58568525f47d330e93ef36e1467bf2 /src/cmd/compile/internal/typecheck/universe.go | |
parent | dac0de3748cc816352da56f516506f80c33db4a5 (diff) | |
download | go-b9693d7627089204e6c2448f543c3512d86dae70.tar.gz go-b9693d7627089204e6c2448f543c3512d86dae70.zip |
[dev.regabi] cmd/compile: split out package typecheck [generated]
This commit splits the typechecking logic into its own package,
the first of a sequence of CLs to break package gc into more
manageable units.
[git-generate]
cd src/cmd/compile/internal/gc
rf '
# The binary import/export has to be part of typechecking,
# because we load inlined function bodies lazily, but "exporter"
# should not be. Move that out of bexport.go.
mv exporter exporter.markObject exporter.markType export.go
# Use the typechecking helpers, so that the calls left behind
# in package gc do not need access to ctxExpr etc.
ex {
import "cmd/compile/internal/ir"
# TODO(rsc): Should not be necessary.
avoid TypecheckExpr
avoid TypecheckStmt
avoid TypecheckExprs
avoid TypecheckStmts
avoid TypecheckAssignExpr
avoid TypecheckCallee
var n ir.Node
var ns []ir.Node
typecheck(n, ctxExpr) -> TypecheckExpr(n)
typecheck(n, ctxStmt) -> TypecheckStmt(n)
typecheckslice(ns, ctxExpr) -> TypecheckExprs(ns)
typecheckslice(ns, ctxStmt) -> TypecheckStmts(ns)
typecheck(n, ctxExpr|ctxAssign) -> TypecheckAssignExpr(n)
typecheck(n, ctxExpr|ctxCallee) -> TypecheckCallee(n)
}
# Move some typechecking API to typecheck.
mv syslook LookupRuntime
mv substArgTypes SubstArgTypes
mv LookupRuntime SubstArgTypes syms.go
mv conv Conv
mv convnop ConvNop
mv Conv ConvNop typecheck.go
mv colasdefn AssignDefn
mv colasname assignableName
mv Target target.go
mv initname autoexport exportsym dcl.go
mv exportsym Export
# Export API to be called from outside typecheck.
# The ones with "Typecheck" prefixes will be renamed later to drop the prefix.
mv adddot AddImplicitDots
mv assignconv AssignConv
mv expandmeth CalcMethods
mv capturevarscomplete CaptureVarsComplete
mv checkMapKeys CheckMapKeys
mv checkreturn CheckReturn
mv dclcontext DeclContext
mv dclfunc DeclFunc
mv declare Declare
mv dotImportRefs DotImportRefs
mv declImporter DeclImporter
mv variter DeclVars
mv defaultlit DefaultLit
mv evalConst EvalConst
mv expandInline ImportBody
mv finishUniverse declareUniverse
mv funcbody FinishFuncBody
mv funchdr StartFuncBody
mv indexconst IndexConst
mv initTodo InitTodoFunc
mv lookup Lookup
mv resolve Resolve
mv lookupN LookupNum
mv nodAddr NodAddr
mv nodAddrAt NodAddrAt
mv nodnil NodNil
mv origBoolConst OrigBool
mv origConst OrigConst
mv origIntConst OrigInt
mv redeclare Redeclared
mv tostruct NewStructType
mv functype NewFuncType
mv methodfunc NewMethodType
mv structargs NewFuncParams
mv temp Temp
mv tempAt TempAt
mv typecheckok TypecheckAllowed
mv typecheck _typecheck # make room for typecheck pkg
mv typecheckinl TypecheckImportedBody
mv typecheckFunc TypecheckFunc
mv iimport ReadImports
mv iexport WriteExports
mv sysfunc LookupRuntimeFunc
mv sysvar LookupRuntimeVar
# Move function constructors to typecheck.
mv mkdotargslice MakeDotArgs
mv fixVariadicCall FixVariadicCall
mv closureType ClosureType
mv partialCallType PartialCallType
mv capturevars CaptureVars
mv MakeDotArgs FixVariadicCall ClosureType PartialCallType CaptureVars typecheckclosure func.go
mv autolabel AutoLabel
mv AutoLabel syms.go
mv Dlist dlist
mv Symlink symlink
mv \
AssignDefn assignableName \
AssignConv \
CaptureVarsComplete \
DeclContext \
DeclFunc \
DeclImporter \
DeclVars \
Declare \
DotImportRefs \
Export \
InitTodoFunc \
Lookup \
LookupNum \
LookupRuntimeFunc \
LookupRuntimeVar \
NewFuncParams \
NewName \
NodAddr \
NodAddrAt \
NodNil \
Redeclared \
StartFuncBody \
FinishFuncBody \
TypecheckImportedBody \
AddImplicitDots \
CalcMethods \
CheckFuncStack \
NewFuncType \
NewMethodType \
NewStructType \
TypecheckAllowed \
Temp \
TempAt \
adddot1 \
dotlist \
addmethod \
assignconvfn \
assignop \
autotmpname \
autoexport \
bexport.go \
checkdupfields \
checkembeddedtype \
closurename \
convertop \
declare_typegen \
decldepth \
dlist \
dotpath \
expand0 \
expand1 \
expandDecl \
fakeRecvField \
fnpkg \
funcStack \
funcStackEnt \
funcarg \
funcarg2 \
funcargs \
funcargs2 \
globClosgen \
ifacelookdot \
implements \
importalias \
importconst \
importfunc \
importobj \
importsym \
importtype \
importvar \
inimport \
initname \
isptrto \
loadsys \
lookdot0 \
lookdot1 \
makepartialcall \
okfor \
okforlen \
operandType \
slist \
symlink \
tointerface \
typeSet \
typeSet.add \
typeSetEntry \
typecheckExprSwitch \
typecheckTypeSwitch \
typecheckpartialcall \
typecheckrange \
typecheckrangeExpr \
typecheckselect \
typecheckswitch \
vargen \
builtin.go \
builtin_test.go \
const.go \
func.go \
iexport.go \
iimport.go \
mapfile_mmap.go \
syms.go \
target.go \
typecheck.go \
unsafe.go \
universe.go \
cmd/compile/internal/typecheck
'
rm gen.go types.go types_acc.go
sed -i '' 's/package gc/package typecheck/' mapfile_read.go mkbuiltin.go
mv mapfile_read.go ../typecheck # not part of default build
mv mkbuiltin.go ../typecheck # package main helper
mv builtin ../typecheck
cd ../typecheck
mv dcl.go dcl1.go
mv typecheck.go typecheck1.go
mv universe.go universe1.go
rf '
# Sweep some small files into larger ones.
# "mv sym... file1.go file.go" (after the mv file1.go file.go above)
# lets us insert sym... at the top of file.go.
mv okfor okforeq universe1.go universe.go
mv DeclContext vargen dcl1.go Temp TempAt autotmpname NewMethodType dcl.go
mv InitTodoFunc inimport decldepth TypecheckAllowed typecheck1.go typecheck.go
mv inl.go closure.go func.go
mv range.go select.go swt.go stmt.go
mv Lookup loadsys LookupRuntimeFunc LookupRuntimeVar syms.go
mv unsafe.go const.go
mv TypecheckAssignExpr AssignExpr
mv TypecheckExpr Expr
mv TypecheckStmt Stmt
mv TypecheckExprs Exprs
mv TypecheckStmts Stmts
mv TypecheckCall Call
mv TypecheckCallee Callee
mv _typecheck check
mv TypecheckFunc Func
mv TypecheckFuncBody FuncBody
mv TypecheckImports AllImportedBodies
mv TypecheckImportedBody ImportedBody
mv TypecheckInit Init
mv TypecheckPackage Package
'
rm gen.go go.go init.go main.go reflect.go
Change-Id: Iea6a7aaf6407d690670ec58aeb36cc0b280f80b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/279236
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/typecheck/universe.go')
-rw-r--r-- | src/cmd/compile/internal/typecheck/universe.go | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/typecheck/universe.go b/src/cmd/compile/internal/typecheck/universe.go new file mode 100644 index 0000000000..fc8e962e28 --- /dev/null +++ b/src/cmd/compile/internal/typecheck/universe.go @@ -0,0 +1,362 @@ +// 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 typecheck + +import ( + "go/constant" + + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/types" + "cmd/internal/src" +) + +var ( + okfor [ir.OEND][]bool + iscmp [ir.OEND]bool +) + +var ( + okforeq [types.NTYPE]bool + okforadd [types.NTYPE]bool + okforand [types.NTYPE]bool + okfornone [types.NTYPE]bool + okforbool [types.NTYPE]bool + okforcap [types.NTYPE]bool + okforlen [types.NTYPE]bool + okforarith [types.NTYPE]bool +) + +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}, +} + +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 types.PtrSize == 0 { + base.Fatalf("typeinit before betypeinit") + } + + types.SlicePtrOffset = 0 + types.SliceLenOffset = types.Rnd(types.SlicePtrOffset+int64(types.PtrSize), int64(types.PtrSize)) + types.SliceCapOffset = types.Rnd(types.SliceLenOffset+int64(types.PtrSize), int64(types.PtrSize)) + types.SliceSize = types.Rnd(types.SliceCapOffset+int64(types.PtrSize), int64(types.PtrSize)) + + // string is same as slice wo the cap + types.StringSize = types.Rnd(types.SliceLenOffset+int64(types.PtrSize), int64(types.PtrSize)) + + for et := types.Kind(0); et < types.NTYPE; et++ { + types.SimType[et] = et + } + + types.Types[types.TANY] = types.New(types.TANY) + types.Types[types.TINTER] = types.NewInterface(types.LocalPkg, nil) + + defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type { + sym := pkg.Lookup(name) + n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, sym) + t := types.NewBasic(kind, n) + n.SetType(t) + sym.Def = n + if kind != types.TANY { + types.CalcSize(t) + } + return t + } + + for _, s := range &basicTypes { + types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name) + } + + for _, s := range &typedefs { + sameas := s.sameas32 + if types.PtrSize == 8 { + sameas = s.sameas64 + } + types.SimType[s.etype] = sameas + + types.Types[s.etype] = defBasic(s.etype, types.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, types.BuiltinPkg, "byte") + types.RuneType = defBasic(types.TINT32, types.BuiltinPkg, "rune") + + // error type + s := types.BuiltinPkg.Lookup("error") + n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, s) + types.ErrorType = types.NewNamed(n) + types.ErrorType.SetUnderlying(makeErrorInterface()) + n.SetType(types.ErrorType) + s.Def = n + types.CalcSize(types.ErrorType) + + types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, ir.Pkgs.Unsafe, "Pointer") + + // simple aliases + types.SimType[types.TMAP] = types.TPTR + types.SimType[types.TCHAN] = types.TPTR + types.SimType[types.TFUNC] = types.TPTR + types.SimType[types.TUNSAFEPTR] = types.TPTR + + for _, s := range &builtinFuncs { + s2 := types.BuiltinPkg.Lookup(s.name) + def := NewName(s2) + def.BuiltinOp = s.op + s2.Def = def + } + + for _, s := range &unsafeFuncs { + s2 := ir.Pkgs.Unsafe.Lookup(s.name) + def := NewName(s2) + def.BuiltinOp = s.op + s2.Def = def + } + + s = types.BuiltinPkg.Lookup("true") + s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(true)) + + s = types.BuiltinPkg.Lookup("false") + s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(false)) + + s = Lookup("_") + types.BlankSym = s + 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 = types.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 = types.BuiltinPkg.Lookup("nil") + nnil := NodNil() + nnil.(*ir.NilExpr).SetSym(s) + s.Def = nnil + + s = types.BuiltinPkg.Lookup("iota") + s.Def = ir.NewIota(base.Pos, s) + + for et := types.TINT8; et <= types.TUINT64; et++ { + types.IsInt[et] = true + } + types.IsInt[types.TINT] = true + types.IsInt[types.TUINT] = true + types.IsInt[types.TUINTPTR] = true + + types.IsFloat[types.TFLOAT32] = true + types.IsFloat[types.TFLOAT64] = true + + types.IsComplex[types.TCOMPLEX64] = true + types.IsComplex[types.TCOMPLEX128] = true + + // initialize okfor + for et := types.Kind(0); et < types.NTYPE; et++ { + if types.IsInt[et] || et == types.TIDEAL { + okforeq[et] = true + types.IsOrdered[et] = true + okforarith[et] = true + okforadd[et] = true + okforand[et] = true + ir.OKForConst[et] = true + types.IsSimple[et] = true + } + + if types.IsFloat[et] { + okforeq[et] = true + types.IsOrdered[et] = true + okforadd[et] = true + okforarith[et] = true + ir.OKForConst[et] = true + types.IsSimple[et] = true + } + + if types.IsComplex[et] { + okforeq[et] = true + okforadd[et] = true + okforarith[et] = true + ir.OKForConst[et] = true + types.IsSimple[et] = true + } + } + + types.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 + + types.IsOrdered[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] = types.IsOrdered[:] + okfor[ir.OGT] = types.IsOrdered[:] + okfor[ir.OLE] = types.IsOrdered[:] + okfor[ir.OLT] = types.IsOrdered[:] + 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 := types.NewSignature(types.NoPkg, fakeRecvField(), nil, []*types.Field{ + types.NewField(src.NoXPos, nil, types.Types[types.TSTRING]), + }) + method := types.NewField(src.NoXPos, Lookup("Error"), sig) + return types.NewInterface(types.NoPkg, []*types.Field{method}) +} + +// declareUniverse makes the universe block visible within the current package. +func declareUniverse() { + // 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 types.BuiltinPkg.Syms { + if s.Def == nil { + continue + } + s1 := Lookup(s.Name) + if s1.Def != nil { + continue + } + + s1.Def = s.Def + s1.Block = s.Block + } + + ir.RegFP = NewName(Lookup(".fp")) + ir.RegFP.SetType(types.Types[types.TINT32]) + ir.RegFP.Class_ = ir.PPARAM + ir.RegFP.SetUsed(true) +} |