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 itable *types.Type // distinguished *byte
15
16var 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
36var 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
47var 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
68var 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.
78func initUniverse() {
79	lexinit()
80	typeinit()
81	lexinit1()
82}
83
84// lexinit initializes known symbols and the basic types.
85func 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
161func 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
369func 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
383func 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.
443func 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}
466