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