github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/cmd/compile/internal/gc/universe.go (about)

     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  // TODO(gri) This file should probably become part of package types.
     6  
     7  package gc
     8  
     9  import "cmd/compile/internal/types"
    10  
    11  // builtinpkg is a fake package that declares the universe block.
    12  var builtinpkg *types.Pkg
    13  
    14  var itable *types.Type // distinguished *byte
    15  
    16  var basicTypes = [...]struct {
    17  	name  string
    18  	etype types.EType
    19  }{
    20  	{"int8", TINT8},
    21  	{"int16", TINT16},
    22  	{"int32", TINT32},
    23  	{"int64", TINT64},
    24  	{"uint8", TUINT8},
    25  	{"uint16", TUINT16},
    26  	{"uint32", TUINT32},
    27  	{"uint64", TUINT64},
    28  	{"float32", TFLOAT32},
    29  	{"float64", TFLOAT64},
    30  	{"complex64", TCOMPLEX64},
    31  	{"complex128", TCOMPLEX128},
    32  	{"bool", TBOOL},
    33  	{"string", TSTRING},
    34  }
    35  
    36  var typedefs = [...]struct {
    37  	name     string
    38  	etype    types.EType
    39  	width    *int
    40  	sameas32 types.EType
    41  	sameas64 types.EType
    42  }{
    43  	{"int", TINT, &Widthint, TINT32, TINT64},
    44  	{"uint", TUINT, &Widthint, TUINT32, TUINT64},
    45  	{"uintptr", TUINTPTR, &Widthptr, TUINT32, TUINT64},
    46  }
    47  
    48  var builtinFuncs = [...]struct {
    49  	name string
    50  	op   Op
    51  }{
    52  	{"append", OAPPEND},
    53  	{"cap", OCAP},
    54  	{"close", OCLOSE},
    55  	{"complex", OCOMPLEX},
    56  	{"copy", OCOPY},
    57  	{"delete", ODELETE},
    58  	{"imag", OIMAG},
    59  	{"len", OLEN},
    60  	{"make", OMAKE},
    61  	{"new", ONEW},
    62  	{"panic", OPANIC},
    63  	{"print", OPRINT},
    64  	{"println", OPRINTN},
    65  	{"real", OREAL},
    66  	{"recover", ORECOVER},
    67  }
    68  
    69  var unsafeFuncs = [...]struct {
    70  	name string
    71  	op   Op
    72  }{
    73  	{"Alignof", OALIGNOF},
    74  	{"Offsetof", OOFFSETOF},
    75  	{"Sizeof", OSIZEOF},
    76  }
    77  
    78  // initUniverse initializes the universe block.
    79  func initUniverse() {
    80  	lexinit()
    81  	typeinit()
    82  	lexinit1()
    83  }
    84  
    85  // lexinit initializes known symbols and the basic types.
    86  func lexinit() {
    87  	for _, s := range basicTypes {
    88  		etype := s.etype
    89  		if int(etype) >= len(types.Types) {
    90  			Fatalf("lexinit: %s bad etype", s.name)
    91  		}
    92  		s2 := builtinpkg.Lookup(s.name)
    93  		t := types.Types[etype]
    94  		if t == nil {
    95  			t = types.New(etype)
    96  			t.Sym = s2
    97  			if etype != TANY && etype != TSTRING {
    98  				dowidth(t)
    99  			}
   100  			types.Types[etype] = t
   101  		}
   102  		s2.Def = asTypesNode(typenod(t))
   103  		asNode(s2.Def).Name = new(Name)
   104  	}
   105  
   106  	for _, s := range builtinFuncs {
   107  		// TODO(marvin): Fix Node.EType type union.
   108  		s2 := builtinpkg.Lookup(s.name)
   109  		s2.Def = asTypesNode(newname(s2))
   110  		asNode(s2.Def).Etype = types.EType(s.op)
   111  	}
   112  
   113  	for _, s := range unsafeFuncs {
   114  		s2 := unsafepkg.Lookup(s.name)
   115  		s2.Def = asTypesNode(newname(s2))
   116  		asNode(s2.Def).Etype = types.EType(s.op)
   117  	}
   118  
   119  	types.Idealstring = types.New(TSTRING)
   120  	types.Idealbool = types.New(TBOOL)
   121  	types.Types[TANY] = types.New(TANY)
   122  
   123  	s := builtinpkg.Lookup("true")
   124  	s.Def = asTypesNode(nodbool(true))
   125  	asNode(s.Def).Sym = lookup("true")
   126  	asNode(s.Def).Name = new(Name)
   127  	asNode(s.Def).Type = types.Idealbool
   128  
   129  	s = builtinpkg.Lookup("false")
   130  	s.Def = asTypesNode(nodbool(false))
   131  	asNode(s.Def).Sym = lookup("false")
   132  	asNode(s.Def).Name = new(Name)
   133  	asNode(s.Def).Type = types.Idealbool
   134  
   135  	s = lookup("_")
   136  	s.Block = -100
   137  	s.Def = asTypesNode(newname(s))
   138  	types.Types[TBLANK] = types.New(TBLANK)
   139  	asNode(s.Def).Type = types.Types[TBLANK]
   140  	nblank = asNode(s.Def)
   141  
   142  	s = builtinpkg.Lookup("_")
   143  	s.Block = -100
   144  	s.Def = asTypesNode(newname(s))
   145  	types.Types[TBLANK] = types.New(TBLANK)
   146  	asNode(s.Def).Type = types.Types[TBLANK]
   147  
   148  	types.Types[TNIL] = types.New(TNIL)
   149  	s = builtinpkg.Lookup("nil")
   150  	var v Val
   151  	v.U = new(NilVal)
   152  	s.Def = asTypesNode(nodlit(v))
   153  	asNode(s.Def).Sym = s
   154  	asNode(s.Def).Name = new(Name)
   155  
   156  	s = builtinpkg.Lookup("iota")
   157  	s.Def = asTypesNode(nod(OIOTA, nil, nil))
   158  	asNode(s.Def).Sym = s
   159  	asNode(s.Def).Name = new(Name)
   160  }
   161  
   162  func typeinit() {
   163  	if Widthptr == 0 {
   164  		Fatalf("typeinit before betypeinit")
   165  	}
   166  
   167  	for et := types.EType(0); et < NTYPE; et++ {
   168  		simtype[et] = et
   169  	}
   170  
   171  	types.Types[TPTR32] = types.New(TPTR32)
   172  	dowidth(types.Types[TPTR32])
   173  
   174  	types.Types[TPTR64] = types.New(TPTR64)
   175  	dowidth(types.Types[TPTR64])
   176  
   177  	t := types.New(TUNSAFEPTR)
   178  	types.Types[TUNSAFEPTR] = t
   179  	t.Sym = unsafepkg.Lookup("Pointer")
   180  	t.Sym.Def = asTypesNode(typenod(t))
   181  	asNode(t.Sym.Def).Name = new(Name)
   182  	dowidth(types.Types[TUNSAFEPTR])
   183  
   184  	types.Tptr = TPTR32
   185  	if Widthptr == 8 {
   186  		types.Tptr = TPTR64
   187  	}
   188  
   189  	for et := TINT8; et <= TUINT64; et++ {
   190  		isInt[et] = true
   191  	}
   192  	isInt[TINT] = true
   193  	isInt[TUINT] = true
   194  	isInt[TUINTPTR] = true
   195  
   196  	isFloat[TFLOAT32] = true
   197  	isFloat[TFLOAT64] = true
   198  
   199  	isComplex[TCOMPLEX64] = true
   200  	isComplex[TCOMPLEX128] = true
   201  
   202  	isforw[TFORW] = true
   203  
   204  	// initialize okfor
   205  	for et := types.EType(0); et < NTYPE; et++ {
   206  		if isInt[et] || et == TIDEAL {
   207  			okforeq[et] = true
   208  			okforcmp[et] = true
   209  			okforarith[et] = true
   210  			okforadd[et] = true
   211  			okforand[et] = true
   212  			okforconst[et] = true
   213  			issimple[et] = true
   214  			minintval[et] = new(Mpint)
   215  			maxintval[et] = new(Mpint)
   216  		}
   217  
   218  		if isFloat[et] {
   219  			okforeq[et] = true
   220  			okforcmp[et] = true
   221  			okforadd[et] = true
   222  			okforarith[et] = true
   223  			okforconst[et] = true
   224  			issimple[et] = true
   225  			minfltval[et] = newMpflt()
   226  			maxfltval[et] = newMpflt()
   227  		}
   228  
   229  		if isComplex[et] {
   230  			okforeq[et] = true
   231  			okforadd[et] = true
   232  			okforarith[et] = true
   233  			okforconst[et] = true
   234  			issimple[et] = true
   235  		}
   236  	}
   237  
   238  	issimple[TBOOL] = true
   239  
   240  	okforadd[TSTRING] = true
   241  
   242  	okforbool[TBOOL] = true
   243  
   244  	okforcap[TARRAY] = true
   245  	okforcap[TCHAN] = true
   246  	okforcap[TSLICE] = true
   247  
   248  	okforconst[TBOOL] = true
   249  	okforconst[TSTRING] = true
   250  
   251  	okforlen[TARRAY] = true
   252  	okforlen[TCHAN] = true
   253  	okforlen[TMAP] = true
   254  	okforlen[TSLICE] = true
   255  	okforlen[TSTRING] = true
   256  
   257  	okforeq[TPTR32] = true
   258  	okforeq[TPTR64] = true
   259  	okforeq[TUNSAFEPTR] = true
   260  	okforeq[TINTER] = true
   261  	okforeq[TCHAN] = true
   262  	okforeq[TSTRING] = true
   263  	okforeq[TBOOL] = true
   264  	okforeq[TMAP] = true    // nil only; refined in typecheck
   265  	okforeq[TFUNC] = true   // nil only; refined in typecheck
   266  	okforeq[TSLICE] = true  // nil only; refined in typecheck
   267  	okforeq[TARRAY] = true  // only if element type is comparable; refined in typecheck
   268  	okforeq[TSTRUCT] = true // only if all struct fields are comparable; refined in typecheck
   269  
   270  	okforcmp[TSTRING] = true
   271  
   272  	var i int
   273  	for i = 0; i < len(okfor); i++ {
   274  		okfor[i] = okfornone[:]
   275  	}
   276  
   277  	// binary
   278  	okfor[OADD] = okforadd[:]
   279  
   280  	okfor[OAND] = okforand[:]
   281  	okfor[OANDAND] = okforbool[:]
   282  	okfor[OANDNOT] = okforand[:]
   283  	okfor[ODIV] = okforarith[:]
   284  	okfor[OEQ] = okforeq[:]
   285  	okfor[OGE] = okforcmp[:]
   286  	okfor[OGT] = okforcmp[:]
   287  	okfor[OLE] = okforcmp[:]
   288  	okfor[OLT] = okforcmp[:]
   289  	okfor[OMOD] = okforand[:]
   290  	okfor[OMUL] = okforarith[:]
   291  	okfor[ONE] = okforeq[:]
   292  	okfor[OOR] = okforand[:]
   293  	okfor[OOROR] = okforbool[:]
   294  	okfor[OSUB] = okforarith[:]
   295  	okfor[OXOR] = okforand[:]
   296  	okfor[OLSH] = okforand[:]
   297  	okfor[ORSH] = okforand[:]
   298  
   299  	// unary
   300  	okfor[OCOM] = okforand[:]
   301  
   302  	okfor[OMINUS] = okforarith[:]
   303  	okfor[ONOT] = okforbool[:]
   304  	okfor[OPLUS] = okforarith[:]
   305  
   306  	// special
   307  	okfor[OCAP] = okforcap[:]
   308  
   309  	okfor[OLEN] = okforlen[:]
   310  
   311  	// comparison
   312  	iscmp[OLT] = true
   313  
   314  	iscmp[OGT] = true
   315  	iscmp[OGE] = true
   316  	iscmp[OLE] = true
   317  	iscmp[OEQ] = true
   318  	iscmp[ONE] = true
   319  
   320  	maxintval[TINT8].SetString("0x7f")
   321  	minintval[TINT8].SetString("-0x80")
   322  	maxintval[TINT16].SetString("0x7fff")
   323  	minintval[TINT16].SetString("-0x8000")
   324  	maxintval[TINT32].SetString("0x7fffffff")
   325  	minintval[TINT32].SetString("-0x80000000")
   326  	maxintval[TINT64].SetString("0x7fffffffffffffff")
   327  	minintval[TINT64].SetString("-0x8000000000000000")
   328  
   329  	maxintval[TUINT8].SetString("0xff")
   330  	maxintval[TUINT16].SetString("0xffff")
   331  	maxintval[TUINT32].SetString("0xffffffff")
   332  	maxintval[TUINT64].SetString("0xffffffffffffffff")
   333  
   334  	// f is valid float if min < f < max.  (min and max are not themselves valid.)
   335  	maxfltval[TFLOAT32].SetString("33554431p103") // 2^24-1 p (127-23) + 1/2 ulp
   336  	minfltval[TFLOAT32].SetString("-33554431p103")
   337  	maxfltval[TFLOAT64].SetString("18014398509481983p970") // 2^53-1 p (1023-52) + 1/2 ulp
   338  	minfltval[TFLOAT64].SetString("-18014398509481983p970")
   339  
   340  	maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32]
   341  	minfltval[TCOMPLEX64] = minfltval[TFLOAT32]
   342  	maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64]
   343  	minfltval[TCOMPLEX128] = minfltval[TFLOAT64]
   344  
   345  	// for walk to use in error messages
   346  	types.Types[TFUNC] = functype(nil, nil, nil)
   347  
   348  	// types used in front end
   349  	// types.Types[TNIL] got set early in lexinit
   350  	types.Types[TIDEAL] = types.New(TIDEAL)
   351  
   352  	types.Types[TINTER] = types.New(TINTER)
   353  
   354  	// simple aliases
   355  	simtype[TMAP] = types.Tptr
   356  
   357  	simtype[TCHAN] = types.Tptr
   358  	simtype[TFUNC] = types.Tptr
   359  	simtype[TUNSAFEPTR] = types.Tptr
   360  
   361  	array_array = int(Rnd(0, int64(Widthptr)))
   362  	array_nel = int(Rnd(int64(array_array)+int64(Widthptr), int64(Widthint)))
   363  	array_cap = int(Rnd(int64(array_nel)+int64(Widthint), int64(Widthint)))
   364  	sizeof_Array = int(Rnd(int64(array_cap)+int64(Widthint), int64(Widthptr)))
   365  
   366  	// string is same as slice wo the cap
   367  	sizeof_String = int(Rnd(int64(array_nel)+int64(Widthint), int64(Widthptr)))
   368  
   369  	dowidth(types.Types[TSTRING])
   370  	dowidth(types.Idealstring)
   371  
   372  	itable = types.NewPtr(types.Types[TUINT8])
   373  }
   374  
   375  func makeErrorInterface() *types.Type {
   376  	field := types.NewField()
   377  	field.Type = types.Types[TSTRING]
   378  	f := functypefield(fakethisfield(), nil, []*types.Field{field})
   379  
   380  	field = types.NewField()
   381  	field.Sym = lookup("Error")
   382  	field.Type = f
   383  
   384  	t := types.New(TINTER)
   385  	t.SetInterface([]*types.Field{field})
   386  	return t
   387  }
   388  
   389  func lexinit1() {
   390  	// error type
   391  	s := builtinpkg.Lookup("error")
   392  	types.Errortype = makeErrorInterface()
   393  	types.Errortype.Sym = s
   394  	// TODO: If we can prove that it's safe to set errortype.Orig here
   395  	// than we don't need the special errortype/errorInterface case in
   396  	// bexport.go. See also issue #15920.
   397  	// errortype.Orig = makeErrorInterface()
   398  	s.Def = asTypesNode(typenod(types.Errortype))
   399  
   400  	// We create separate byte and rune types for better error messages
   401  	// rather than just creating type alias *types.Sym's for the uint8 and
   402  	// int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false.
   403  	// TODO(gri) Should we get rid of this special case (at the cost
   404  	// of less informative error messages involving bytes and runes)?
   405  	// (Alternatively, we could introduce an OTALIAS node representing
   406  	// type aliases, albeit at the cost of having to deal with it everywhere).
   407  
   408  	// byte alias
   409  	s = builtinpkg.Lookup("byte")
   410  	types.Bytetype = types.New(TUINT8)
   411  	types.Bytetype.Sym = s
   412  	s.Def = asTypesNode(typenod(types.Bytetype))
   413  	asNode(s.Def).Name = new(Name)
   414  
   415  	// rune alias
   416  	s = builtinpkg.Lookup("rune")
   417  	types.Runetype = types.New(TINT32)
   418  	types.Runetype.Sym = s
   419  	s.Def = asTypesNode(typenod(types.Runetype))
   420  	asNode(s.Def).Name = new(Name)
   421  
   422  	// backend-dependent builtin types (e.g. int).
   423  	for _, s := range typedefs {
   424  		s1 := builtinpkg.Lookup(s.name)
   425  
   426  		sameas := s.sameas32
   427  		if *s.width == 8 {
   428  			sameas = s.sameas64
   429  		}
   430  
   431  		simtype[s.etype] = sameas
   432  		minfltval[s.etype] = minfltval[sameas]
   433  		maxfltval[s.etype] = maxfltval[sameas]
   434  		minintval[s.etype] = minintval[sameas]
   435  		maxintval[s.etype] = maxintval[sameas]
   436  
   437  		t := types.New(s.etype)
   438  		t.Sym = s1
   439  		types.Types[s.etype] = t
   440  		s1.Def = asTypesNode(typenod(t))
   441  		asNode(s1.Def).Name = new(Name)
   442  		s1.Origpkg = builtinpkg
   443  
   444  		dowidth(t)
   445  	}
   446  }
   447  
   448  // finishUniverse makes the universe block visible within the current package.
   449  func finishUniverse() {
   450  	// Operationally, this is similar to a dot import of builtinpkg, except
   451  	// that we silently skip symbols that are already declared in the
   452  	// package block rather than emitting a redeclared symbol error.
   453  
   454  	for _, s := range builtinpkg.Syms {
   455  		if s.Def == nil {
   456  			continue
   457  		}
   458  		s1 := lookup(s.Name)
   459  		if s1.Def != nil {
   460  			continue
   461  		}
   462  
   463  		s1.Def = s.Def
   464  		s1.Block = s.Block
   465  	}
   466  
   467  	nodfp = newname(lookup(".fp"))
   468  	nodfp.Type = types.Types[TINT32]
   469  	nodfp.Class = PPARAM
   470  	nodfp.SetUsed(true)
   471  }