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

     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 builtinFuncs = [...]struct {
    33  	name string
    34  	op   ir.Op
    35  }{
    36  	{"append", ir.OAPPEND},
    37  	{"cap", ir.OCAP},
    38  	{"close", ir.OCLOSE},
    39  	{"complex", ir.OCOMPLEX},
    40  	{"copy", ir.OCOPY},
    41  	{"delete", ir.ODELETE},
    42  	{"imag", ir.OIMAG},
    43  	{"len", ir.OLEN},
    44  	{"make", ir.OMAKE},
    45  	{"new", ir.ONEW},
    46  	{"panic", ir.OPANIC},
    47  	{"print", ir.OPRINT},
    48  	{"println", ir.OPRINTN},
    49  	{"real", ir.OREAL},
    50  	{"recover", ir.ORECOVER},
    51  }
    52  
    53  var unsafeFuncs = [...]struct {
    54  	name string
    55  	op   ir.Op
    56  }{
    57  	{"Add", ir.OUNSAFEADD},
    58  	{"Alignof", ir.OALIGNOF},
    59  	{"Offsetof", ir.OOFFSETOF},
    60  	{"Sizeof", ir.OSIZEOF},
    61  	{"Slice", ir.OUNSAFESLICE},
    62  }
    63  
    64  // InitUniverse initializes the universe block.
    65  func InitUniverse() {
    66  	types.InitTypes(func(sym *types.Sym, typ *types.Type) types.Object {
    67  		n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, sym)
    68  		n.SetType(typ)
    69  		sym.Def = n
    70  		return n
    71  	})
    72  
    73  	for _, s := range &builtinFuncs {
    74  		s2 := types.BuiltinPkg.Lookup(s.name)
    75  		def := NewName(s2)
    76  		def.BuiltinOp = s.op
    77  		s2.Def = def
    78  	}
    79  
    80  	for _, s := range &unsafeFuncs {
    81  		s2 := types.UnsafePkg.Lookup(s.name)
    82  		def := NewName(s2)
    83  		def.BuiltinOp = s.op
    84  		s2.Def = def
    85  	}
    86  
    87  	s := types.BuiltinPkg.Lookup("true")
    88  	s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(true))
    89  
    90  	s = types.BuiltinPkg.Lookup("false")
    91  	s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(false))
    92  
    93  	s = Lookup("_")
    94  	types.BlankSym = s
    95  	s.Block = -100
    96  	s.Def = NewName(s)
    97  	ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
    98  	ir.BlankNode = ir.AsNode(s.Def)
    99  	ir.BlankNode.SetTypecheck(1)
   100  
   101  	s = types.BuiltinPkg.Lookup("_")
   102  	s.Block = -100
   103  	s.Def = NewName(s)
   104  	ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
   105  
   106  	s = types.BuiltinPkg.Lookup("nil")
   107  	nnil := NodNil()
   108  	nnil.(*ir.NilExpr).SetSym(s)
   109  	s.Def = nnil
   110  
   111  	s = types.BuiltinPkg.Lookup("iota")
   112  	s.Def = ir.NewIota(base.Pos, s)
   113  
   114  	// initialize okfor
   115  	for et := types.Kind(0); et < types.NTYPE; et++ {
   116  		if types.IsInt[et] || et == types.TIDEAL {
   117  			okforeq[et] = true
   118  			types.IsOrdered[et] = true
   119  			okforarith[et] = true
   120  			okforadd[et] = true
   121  			okforand[et] = true
   122  			ir.OKForConst[et] = true
   123  			types.IsSimple[et] = true
   124  		}
   125  
   126  		if types.IsFloat[et] {
   127  			okforeq[et] = true
   128  			types.IsOrdered[et] = true
   129  			okforadd[et] = true
   130  			okforarith[et] = true
   131  			ir.OKForConst[et] = true
   132  			types.IsSimple[et] = true
   133  		}
   134  
   135  		if types.IsComplex[et] {
   136  			okforeq[et] = true
   137  			okforadd[et] = true
   138  			okforarith[et] = true
   139  			ir.OKForConst[et] = true
   140  			types.IsSimple[et] = true
   141  		}
   142  	}
   143  
   144  	types.IsSimple[types.TBOOL] = true
   145  
   146  	okforadd[types.TSTRING] = true
   147  
   148  	okforbool[types.TBOOL] = true
   149  
   150  	okforcap[types.TARRAY] = true
   151  	okforcap[types.TCHAN] = true
   152  	okforcap[types.TSLICE] = true
   153  
   154  	ir.OKForConst[types.TBOOL] = true
   155  	ir.OKForConst[types.TSTRING] = true
   156  
   157  	okforlen[types.TARRAY] = true
   158  	okforlen[types.TCHAN] = true
   159  	okforlen[types.TMAP] = true
   160  	okforlen[types.TSLICE] = true
   161  	okforlen[types.TSTRING] = true
   162  
   163  	okforeq[types.TPTR] = true
   164  	okforeq[types.TUNSAFEPTR] = true
   165  	okforeq[types.TINTER] = true
   166  	okforeq[types.TCHAN] = true
   167  	okforeq[types.TSTRING] = true
   168  	okforeq[types.TBOOL] = true
   169  	okforeq[types.TMAP] = true    // nil only; refined in typecheck
   170  	okforeq[types.TFUNC] = true   // nil only; refined in typecheck
   171  	okforeq[types.TSLICE] = true  // nil only; refined in typecheck
   172  	okforeq[types.TARRAY] = true  // only if element type is comparable; refined in typecheck
   173  	okforeq[types.TSTRUCT] = true // only if all struct fields are comparable; refined in typecheck
   174  
   175  	types.IsOrdered[types.TSTRING] = true
   176  
   177  	for i := range okfor {
   178  		okfor[i] = okfornone[:]
   179  	}
   180  
   181  	// binary
   182  	okfor[ir.OADD] = okforadd[:]
   183  	okfor[ir.OAND] = okforand[:]
   184  	okfor[ir.OANDAND] = okforbool[:]
   185  	okfor[ir.OANDNOT] = okforand[:]
   186  	okfor[ir.ODIV] = okforarith[:]
   187  	okfor[ir.OEQ] = okforeq[:]
   188  	okfor[ir.OGE] = types.IsOrdered[:]
   189  	okfor[ir.OGT] = types.IsOrdered[:]
   190  	okfor[ir.OLE] = types.IsOrdered[:]
   191  	okfor[ir.OLT] = types.IsOrdered[:]
   192  	okfor[ir.OMOD] = okforand[:]
   193  	okfor[ir.OMUL] = okforarith[:]
   194  	okfor[ir.ONE] = okforeq[:]
   195  	okfor[ir.OOR] = okforand[:]
   196  	okfor[ir.OOROR] = okforbool[:]
   197  	okfor[ir.OSUB] = okforarith[:]
   198  	okfor[ir.OXOR] = okforand[:]
   199  	okfor[ir.OLSH] = okforand[:]
   200  	okfor[ir.ORSH] = okforand[:]
   201  
   202  	// unary
   203  	okfor[ir.OBITNOT] = okforand[:]
   204  	okfor[ir.ONEG] = okforarith[:]
   205  	okfor[ir.ONOT] = okforbool[:]
   206  	okfor[ir.OPLUS] = okforarith[:]
   207  
   208  	// special
   209  	okfor[ir.OCAP] = okforcap[:]
   210  	okfor[ir.OLEN] = okforlen[:]
   211  }
   212  
   213  // DeclareUniverse makes the universe block visible within the current package.
   214  func DeclareUniverse() {
   215  	// Operationally, this is similar to a dot import of builtinpkg, except
   216  	// that we silently skip symbols that are already declared in the
   217  	// package block rather than emitting a redeclared symbol error.
   218  
   219  	for _, s := range types.BuiltinPkg.Syms {
   220  		if s.Def == nil {
   221  			continue
   222  		}
   223  		s1 := Lookup(s.Name)
   224  		if s1.Def != nil {
   225  			continue
   226  		}
   227  
   228  		s1.Def = s.Def
   229  		s1.Block = s.Block
   230  	}
   231  }
   232  

View as plain text