...

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

View as plain text