Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/compile/internal/typecheck/universe.go

Documentation: cmd/compile/internal/typecheck

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package typecheck
     6  
     7  import (
     8  	"go/constant"
     9  
    10  	"cmd/compile/internal/base"
    11  	"cmd/compile/internal/ir"
    12  	"cmd/compile/internal/types"
    13  	"cmd/internal/src"
    14  )
    15  
    16  var (
    17  	okfor [ir.OEND][]bool
    18  	iscmp [ir.OEND]bool
    19  )
    20  
    21  var (
    22  	okforeq    [types.NTYPE]bool
    23  	okforadd   [types.NTYPE]bool
    24  	okforand   [types.NTYPE]bool
    25  	okfornone  [types.NTYPE]bool
    26  	okforbool  [types.NTYPE]bool
    27  	okforcap   [types.NTYPE]bool
    28  	okforlen   [types.NTYPE]bool
    29  	okforarith [types.NTYPE]bool
    30  )
    31  
    32  var basicTypes = [...]struct {
    33  	name  string
    34  	etype types.Kind
    35  }{
    36  	{"int8", types.TINT8},
    37  	{"int16", types.TINT16},
    38  	{"int32", types.TINT32},
    39  	{"int64", types.TINT64},
    40  	{"uint8", types.TUINT8},
    41  	{"uint16", types.TUINT16},
    42  	{"uint32", types.TUINT32},
    43  	{"uint64", types.TUINT64},
    44  	{"float32", types.TFLOAT32},
    45  	{"float64", types.TFLOAT64},
    46  	{"complex64", types.TCOMPLEX64},
    47  	{"complex128", types.TCOMPLEX128},
    48  	{"bool", types.TBOOL},
    49  	{"string", types.TSTRING},
    50  }
    51  
    52  var typedefs = [...]struct {
    53  	name     string
    54  	etype    types.Kind
    55  	sameas32 types.Kind
    56  	sameas64 types.Kind
    57  }{
    58  	{"int", types.TINT, types.TINT32, types.TINT64},
    59  	{"uint", types.TUINT, types.TUINT32, types.TUINT64},
    60  	{"uintptr", types.TUINTPTR, types.TUINT32, types.TUINT64},
    61  }
    62  
    63  var builtinFuncs = [...]struct {
    64  	name string
    65  	op   ir.Op
    66  }{
    67  	{"append", ir.OAPPEND},
    68  	{"cap", ir.OCAP},
    69  	{"close", ir.OCLOSE},
    70  	{"complex", ir.OCOMPLEX},
    71  	{"copy", ir.OCOPY},
    72  	{"delete", ir.ODELETE},
    73  	{"imag", ir.OIMAG},
    74  	{"len", ir.OLEN},
    75  	{"make", ir.OMAKE},
    76  	{"new", ir.ONEW},
    77  	{"panic", ir.OPANIC},
    78  	{"print", ir.OPRINT},
    79  	{"println", ir.OPRINTN},
    80  	{"real", ir.OREAL},
    81  	{"recover", ir.ORECOVER},
    82  }
    83  
    84  var unsafeFuncs = [...]struct {
    85  	name string
    86  	op   ir.Op
    87  }{
    88  	{"Add", ir.OUNSAFEADD},
    89  	{"Alignof", ir.OALIGNOF},
    90  	{"Offsetof", ir.OOFFSETOF},
    91  	{"Sizeof", ir.OSIZEOF},
    92  	{"Slice", ir.OUNSAFESLICE},
    93  }
    94  
    95  // InitUniverse initializes the universe block.
    96  func InitUniverse() {
    97  	if types.PtrSize == 0 {
    98  		base.Fatalf("typeinit before betypeinit")
    99  	}
   100  
   101  	types.SlicePtrOffset = 0
   102  	types.SliceLenOffset = types.Rnd(types.SlicePtrOffset+int64(types.PtrSize), int64(types.PtrSize))
   103  	types.SliceCapOffset = types.Rnd(types.SliceLenOffset+int64(types.PtrSize), int64(types.PtrSize))
   104  	types.SliceSize = types.Rnd(types.SliceCapOffset+int64(types.PtrSize), int64(types.PtrSize))
   105  
   106  	// string is same as slice wo the cap
   107  	types.StringSize = types.Rnd(types.SliceLenOffset+int64(types.PtrSize), int64(types.PtrSize))
   108  
   109  	for et := types.Kind(0); et < types.NTYPE; et++ {
   110  		types.SimType[et] = et
   111  	}
   112  
   113  	types.Types[types.TANY] = types.New(types.TANY)
   114  	types.Types[types.TINTER] = types.NewInterface(types.LocalPkg, nil)
   115  
   116  	defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type {
   117  		sym := pkg.Lookup(name)
   118  		n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, sym)
   119  		t := types.NewBasic(kind, n)
   120  		n.SetType(t)
   121  		sym.Def = n
   122  		if kind != types.TANY {
   123  			types.CalcSize(t)
   124  		}
   125  		return t
   126  	}
   127  
   128  	for _, s := range &basicTypes {
   129  		types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name)
   130  	}
   131  
   132  	for _, s := range &typedefs {
   133  		sameas := s.sameas32
   134  		if types.PtrSize == 8 {
   135  			sameas = s.sameas64
   136  		}
   137  		types.SimType[s.etype] = sameas
   138  
   139  		types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name)
   140  	}
   141  
   142  	// We create separate byte and rune types for better error messages
   143  	// rather than just creating type alias *types.Sym's for the uint8 and
   144  	// int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false.
   145  	// TODO(gri) Should we get rid of this special case (at the cost
   146  	// of less informative error messages involving bytes and runes)?
   147  	// (Alternatively, we could introduce an OTALIAS node representing
   148  	// type aliases, albeit at the cost of having to deal with it everywhere).
   149  	types.ByteType = defBasic(types.TUINT8, types.BuiltinPkg, "byte")
   150  	types.RuneType = defBasic(types.TINT32, types.BuiltinPkg, "rune")
   151  
   152  	// error type
   153  	s := types.BuiltinPkg.Lookup("error")
   154  	n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, s)
   155  	types.ErrorType = types.NewNamed(n)
   156  	types.ErrorType.SetUnderlying(makeErrorInterface())
   157  	n.SetType(types.ErrorType)
   158  	s.Def = n
   159  	types.CalcSize(types.ErrorType)
   160  
   161  	types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, ir.Pkgs.Unsafe, "Pointer")
   162  
   163  	// simple aliases
   164  	types.SimType[types.TMAP] = types.TPTR
   165  	types.SimType[types.TCHAN] = types.TPTR
   166  	types.SimType[types.TFUNC] = types.TPTR
   167  	types.SimType[types.TUNSAFEPTR] = types.TPTR
   168  
   169  	for _, s := range &builtinFuncs {
   170  		s2 := types.BuiltinPkg.Lookup(s.name)
   171  		def := NewName(s2)
   172  		def.BuiltinOp = s.op
   173  		s2.Def = def
   174  	}
   175  
   176  	for _, s := range &unsafeFuncs {
   177  		s2 := ir.Pkgs.Unsafe.Lookup(s.name)
   178  		def := NewName(s2)
   179  		def.BuiltinOp = s.op
   180  		s2.Def = def
   181  	}
   182  
   183  	s = types.BuiltinPkg.Lookup("true")
   184  	s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(true))
   185  
   186  	s = types.BuiltinPkg.Lookup("false")
   187  	s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(false))
   188  
   189  	s = Lookup("_")
   190  	types.BlankSym = s
   191  	s.Block = -100
   192  	s.Def = NewName(s)
   193  	types.Types[types.TBLANK] = types.New(types.TBLANK)
   194  	ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
   195  	ir.BlankNode = ir.AsNode(s.Def)
   196  	ir.BlankNode.SetTypecheck(1)
   197  
   198  	s = types.BuiltinPkg.Lookup("_")
   199  	s.Block = -100
   200  	s.Def = NewName(s)
   201  	types.Types[types.TBLANK] = types.New(types.TBLANK)
   202  	ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
   203  
   204  	types.Types[types.TNIL] = types.New(types.TNIL)
   205  	s = types.BuiltinPkg.Lookup("nil")
   206  	nnil := NodNil()
   207  	nnil.(*ir.NilExpr).SetSym(s)
   208  	s.Def = nnil
   209  
   210  	s = types.BuiltinPkg.Lookup("iota")
   211  	s.Def = ir.NewIota(base.Pos, s)
   212  
   213  	for et := types.TINT8; et <= types.TUINT64; et++ {
   214  		types.IsInt[et] = true
   215  	}
   216  	types.IsInt[types.TINT] = true
   217  	types.IsInt[types.TUINT] = true
   218  	types.IsInt[types.TUINTPTR] = true
   219  
   220  	types.IsFloat[types.TFLOAT32] = true
   221  	types.IsFloat[types.TFLOAT64] = true
   222  
   223  	types.IsComplex[types.TCOMPLEX64] = true
   224  	types.IsComplex[types.TCOMPLEX128] = true
   225  
   226  	// initialize okfor
   227  	for et := types.Kind(0); et < types.NTYPE; et++ {
   228  		if types.IsInt[et] || et == types.TIDEAL {
   229  			okforeq[et] = true
   230  			types.IsOrdered[et] = true
   231  			okforarith[et] = true
   232  			okforadd[et] = true
   233  			okforand[et] = true
   234  			ir.OKForConst[et] = true
   235  			types.IsSimple[et] = true
   236  		}
   237  
   238  		if types.IsFloat[et] {
   239  			okforeq[et] = true
   240  			types.IsOrdered[et] = true
   241  			okforadd[et] = true
   242  			okforarith[et] = true
   243  			ir.OKForConst[et] = true
   244  			types.IsSimple[et] = true
   245  		}
   246  
   247  		if types.IsComplex[et] {
   248  			okforeq[et] = true
   249  			okforadd[et] = true
   250  			okforarith[et] = true
   251  			ir.OKForConst[et] = true
   252  			types.IsSimple[et] = true
   253  		}
   254  	}
   255  
   256  	types.IsSimple[types.TBOOL] = true
   257  
   258  	okforadd[types.TSTRING] = true
   259  
   260  	okforbool[types.TBOOL] = true
   261  
   262  	okforcap[types.TARRAY] = true
   263  	okforcap[types.TCHAN] = true
   264  	okforcap[types.TSLICE] = true
   265  
   266  	ir.OKForConst[types.TBOOL] = true
   267  	ir.OKForConst[types.TSTRING] = true
   268  
   269  	okforlen[types.TARRAY] = true
   270  	okforlen[types.TCHAN] = true
   271  	okforlen[types.TMAP] = true
   272  	okforlen[types.TSLICE] = true
   273  	okforlen[types.TSTRING] = true
   274  
   275  	okforeq[types.TPTR] = true
   276  	okforeq[types.TUNSAFEPTR] = true
   277  	okforeq[types.TINTER] = true
   278  	okforeq[types.TCHAN] = true
   279  	okforeq[types.TSTRING] = true
   280  	okforeq[types.TBOOL] = true
   281  	okforeq[types.TMAP] = true    // nil only; refined in typecheck
   282  	okforeq[types.TFUNC] = true   // nil only; refined in typecheck
   283  	okforeq[types.TSLICE] = true  // nil only; refined in typecheck
   284  	okforeq[types.TARRAY] = true  // only if element type is comparable; refined in typecheck
   285  	okforeq[types.TSTRUCT] = true // only if all struct fields are comparable; refined in typecheck
   286  
   287  	types.IsOrdered[types.TSTRING] = true
   288  
   289  	for i := range okfor {
   290  		okfor[i] = okfornone[:]
   291  	}
   292  
   293  	// binary
   294  	okfor[ir.OADD] = okforadd[:]
   295  	okfor[ir.OAND] = okforand[:]
   296  	okfor[ir.OANDAND] = okforbool[:]
   297  	okfor[ir.OANDNOT] = okforand[:]
   298  	okfor[ir.ODIV] = okforarith[:]
   299  	okfor[ir.OEQ] = okforeq[:]
   300  	okfor[ir.OGE] = types.IsOrdered[:]
   301  	okfor[ir.OGT] = types.IsOrdered[:]
   302  	okfor[ir.OLE] = types.IsOrdered[:]
   303  	okfor[ir.OLT] = types.IsOrdered[:]
   304  	okfor[ir.OMOD] = okforand[:]
   305  	okfor[ir.OMUL] = okforarith[:]
   306  	okfor[ir.ONE] = okforeq[:]
   307  	okfor[ir.OOR] = okforand[:]
   308  	okfor[ir.OOROR] = okforbool[:]
   309  	okfor[ir.OSUB] = okforarith[:]
   310  	okfor[ir.OXOR] = okforand[:]
   311  	okfor[ir.OLSH] = okforand[:]
   312  	okfor[ir.ORSH] = okforand[:]
   313  
   314  	// unary
   315  	okfor[ir.OBITNOT] = okforand[:]
   316  	okfor[ir.ONEG] = okforarith[:]
   317  	okfor[ir.ONOT] = okforbool[:]
   318  	okfor[ir.OPLUS] = okforarith[:]
   319  
   320  	// special
   321  	okfor[ir.OCAP] = okforcap[:]
   322  	okfor[ir.OLEN] = okforlen[:]
   323  
   324  	// comparison
   325  	iscmp[ir.OLT] = true
   326  	iscmp[ir.OGT] = true
   327  	iscmp[ir.OGE] = true
   328  	iscmp[ir.OLE] = true
   329  	iscmp[ir.OEQ] = true
   330  	iscmp[ir.ONE] = true
   331  }
   332  
   333  func makeErrorInterface() *types.Type {
   334  	sig := types.NewSignature(types.NoPkg, fakeRecvField(), nil, nil, []*types.Field{
   335  		types.NewField(src.NoXPos, nil, types.Types[types.TSTRING]),
   336  	})
   337  	method := types.NewField(src.NoXPos, Lookup("Error"), sig)
   338  	return types.NewInterface(types.NoPkg, []*types.Field{method})
   339  }
   340  
   341  // DeclareUniverse makes the universe block visible within the current package.
   342  func DeclareUniverse() {
   343  	// Operationally, this is similar to a dot import of builtinpkg, except
   344  	// that we silently skip symbols that are already declared in the
   345  	// package block rather than emitting a redeclared symbol error.
   346  
   347  	for _, s := range types.BuiltinPkg.Syms {
   348  		if s.Def == nil {
   349  			continue
   350  		}
   351  		s1 := Lookup(s.Name)
   352  		if s1.Def != nil {
   353  			continue
   354  		}
   355  
   356  		s1.Def = s.Def
   357  		s1.Block = s.Block
   358  	}
   359  }
   360  

View as plain text