Home | History | Annotate | Download | only in gc
      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 	types.Errortype.Orig = makeErrorInterface()
    389 	s.Def = asTypesNode(typenod(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 
    406 	// rune alias
    407 	s = builtinpkg.Lookup("rune")
    408 	types.Runetype = types.New(TINT32)
    409 	types.Runetype.Sym = s
    410 	s.Def = asTypesNode(typenod(types.Runetype))
    411 	asNode(s.Def).Name = new(Name)
    412 
    413 	// backend-dependent builtin types (e.g. int).
    414 	for _, s := range typedefs {
    415 		s1 := builtinpkg.Lookup(s.name)
    416 
    417 		sameas := s.sameas32
    418 		if Widthptr == 8 {
    419 			sameas = s.sameas64
    420 		}
    421 
    422 		simtype[s.etype] = sameas
    423 		minfltval[s.etype] = minfltval[sameas]
    424 		maxfltval[s.etype] = maxfltval[sameas]
    425 		minintval[s.etype] = minintval[sameas]
    426 		maxintval[s.etype] = maxintval[sameas]
    427 
    428 		t := types.New(s.etype)
    429 		t.Sym = s1
    430 		types.Types[s.etype] = t
    431 		s1.Def = asTypesNode(typenod(t))
    432 		asNode(s1.Def).Name = new(Name)
    433 		s1.Origpkg = builtinpkg
    434 
    435 		dowidth(t)
    436 	}
    437 }
    438 
    439 // finishUniverse makes the universe block visible within the current package.
    440 func finishUniverse() {
    441 	// Operationally, this is similar to a dot import of builtinpkg, except
    442 	// that we silently skip symbols that are already declared in the
    443 	// package block rather than emitting a redeclared symbol error.
    444 
    445 	for _, s := range builtinpkg.Syms {
    446 		if s.Def == nil {
    447 			continue
    448 		}
    449 		s1 := lookup(s.Name)
    450 		if s1.Def != nil {
    451 			continue
    452 		}
    453 
    454 		s1.Def = s.Def
    455 		s1.Block = s.Block
    456 	}
    457 
    458 	nodfp = newname(lookup(".fp"))
    459 	nodfp.Type = types.Types[TINT32]
    460 	nodfp.SetClass(PPARAM)
    461 	nodfp.Name.SetUsed(true)
    462 }
    463