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
5package typecheck
6
7import (
8	"go/constant"
9
10	"cmd/compile/internal/ir"
11	"cmd/compile/internal/types"
12	"cmd/internal/src"
13)
14
15var (
16	okfor [ir.OEND][]bool
17)
18
19var (
20	okforeq    [types.NTYPE]bool
21	okforadd   [types.NTYPE]bool
22	okforand   [types.NTYPE]bool
23	okfornone  [types.NTYPE]bool
24	okforbool  [types.NTYPE]bool
25	okforcap   [types.NTYPE]bool
26	okforlen   [types.NTYPE]bool
27	okforarith [types.NTYPE]bool
28)
29
30var builtinFuncs = [...]struct {
31	name string
32	op   ir.Op
33}{
34	{"append", ir.OAPPEND},
35	{"cap", ir.OCAP},
36	{"clear", ir.OCLEAR},
37	{"close", ir.OCLOSE},
38	{"complex", ir.OCOMPLEX},
39	{"copy", ir.OCOPY},
40	{"delete", ir.ODELETE},
41	{"imag", ir.OIMAG},
42	{"len", ir.OLEN},
43	{"make", ir.OMAKE},
44	{"max", ir.OMAX},
45	{"min", ir.OMIN},
46	{"new", ir.ONEW},
47	{"panic", ir.OPANIC},
48	{"print", ir.OPRINT},
49	{"println", ir.OPRINTLN},
50	{"real", ir.OREAL},
51	{"recover", ir.ORECOVER},
52}
53
54var unsafeFuncs = [...]struct {
55	name string
56	op   ir.Op
57}{
58	{"Add", ir.OUNSAFEADD},
59	{"Slice", ir.OUNSAFESLICE},
60	{"SliceData", ir.OUNSAFESLICEDATA},
61	{"String", ir.OUNSAFESTRING},
62	{"StringData", ir.OUNSAFESTRINGDATA},
63}
64
65// InitUniverse initializes the universe block.
66func InitUniverse() {
67	types.InitTypes(func(sym *types.Sym, typ *types.Type) types.Object {
68		n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, sym)
69		n.SetType(typ)
70		n.SetTypecheck(1)
71		sym.Def = n
72		return n
73	})
74
75	for _, s := range &builtinFuncs {
76		ir.NewBuiltin(types.BuiltinPkg.Lookup(s.name), s.op)
77	}
78
79	for _, s := range &unsafeFuncs {
80		ir.NewBuiltin(types.UnsafePkg.Lookup(s.name), s.op)
81	}
82
83	s := types.BuiltinPkg.Lookup("true")
84	s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(true))
85
86	s = types.BuiltinPkg.Lookup("false")
87	s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(false))
88
89	s = Lookup("_")
90	types.BlankSym = s
91	ir.BlankNode = ir.NewNameAt(src.NoXPos, s, types.Types[types.TBLANK])
92	s.Def = ir.BlankNode
93
94	s = types.BuiltinPkg.Lookup("_")
95	s.Def = ir.NewNameAt(src.NoXPos, s, types.Types[types.TBLANK])
96
97	s = types.BuiltinPkg.Lookup("nil")
98	s.Def = NodNil()
99
100	// initialize okfor
101	for et := types.Kind(0); et < types.NTYPE; et++ {
102		if types.IsInt[et] || et == types.TIDEAL {
103			okforeq[et] = true
104			types.IsOrdered[et] = true
105			okforarith[et] = true
106			okforadd[et] = true
107			okforand[et] = true
108			ir.OKForConst[et] = true
109			types.IsSimple[et] = true
110		}
111
112		if types.IsFloat[et] {
113			okforeq[et] = true
114			types.IsOrdered[et] = true
115			okforadd[et] = true
116			okforarith[et] = true
117			ir.OKForConst[et] = true
118			types.IsSimple[et] = true
119		}
120
121		if types.IsComplex[et] {
122			okforeq[et] = true
123			okforadd[et] = true
124			okforarith[et] = true
125			ir.OKForConst[et] = true
126			types.IsSimple[et] = true
127		}
128	}
129
130	types.IsSimple[types.TBOOL] = true
131
132	okforadd[types.TSTRING] = true
133
134	okforbool[types.TBOOL] = true
135
136	okforcap[types.TARRAY] = true
137	okforcap[types.TCHAN] = true
138	okforcap[types.TSLICE] = true
139
140	ir.OKForConst[types.TBOOL] = true
141	ir.OKForConst[types.TSTRING] = true
142
143	okforlen[types.TARRAY] = true
144	okforlen[types.TCHAN] = true
145	okforlen[types.TMAP] = true
146	okforlen[types.TSLICE] = true
147	okforlen[types.TSTRING] = true
148
149	okforeq[types.TPTR] = true
150	okforeq[types.TUNSAFEPTR] = true
151	okforeq[types.TINTER] = true
152	okforeq[types.TCHAN] = true
153	okforeq[types.TSTRING] = true
154	okforeq[types.TBOOL] = true
155	okforeq[types.TMAP] = true    // nil only; refined in typecheck
156	okforeq[types.TFUNC] = true   // nil only; refined in typecheck
157	okforeq[types.TSLICE] = true  // nil only; refined in typecheck
158	okforeq[types.TARRAY] = true  // only if element type is comparable; refined in typecheck
159	okforeq[types.TSTRUCT] = true // only if all struct fields are comparable; refined in typecheck
160
161	types.IsOrdered[types.TSTRING] = true
162
163	for i := range okfor {
164		okfor[i] = okfornone[:]
165	}
166
167	// binary
168	okfor[ir.OADD] = okforadd[:]
169	okfor[ir.OAND] = okforand[:]
170	okfor[ir.OANDAND] = okforbool[:]
171	okfor[ir.OANDNOT] = okforand[:]
172	okfor[ir.ODIV] = okforarith[:]
173	okfor[ir.OEQ] = okforeq[:]
174	okfor[ir.OGE] = types.IsOrdered[:]
175	okfor[ir.OGT] = types.IsOrdered[:]
176	okfor[ir.OLE] = types.IsOrdered[:]
177	okfor[ir.OLT] = types.IsOrdered[:]
178	okfor[ir.OMOD] = okforand[:]
179	okfor[ir.OMUL] = okforarith[:]
180	okfor[ir.ONE] = okforeq[:]
181	okfor[ir.OOR] = okforand[:]
182	okfor[ir.OOROR] = okforbool[:]
183	okfor[ir.OSUB] = okforarith[:]
184	okfor[ir.OXOR] = okforand[:]
185	okfor[ir.OLSH] = okforand[:]
186	okfor[ir.ORSH] = okforand[:]
187
188	// unary
189	okfor[ir.OBITNOT] = okforand[:]
190	okfor[ir.ONEG] = okforarith[:]
191	okfor[ir.ONOT] = okforbool[:]
192	okfor[ir.OPLUS] = okforarith[:]
193
194	// special
195	okfor[ir.OCAP] = okforcap[:]
196	okfor[ir.OLEN] = okforlen[:]
197}
198