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