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