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 }