1
2
3
4
5 package noder
6
7 import (
8 "go/constant"
9
10 "cmd/compile/internal/base"
11 "cmd/compile/internal/ir"
12 "cmd/compile/internal/syntax"
13 "cmd/compile/internal/typecheck"
14 "cmd/compile/internal/types"
15 "cmd/compile/internal/types2"
16 )
17
18
19
20
21 func (g *irgen) decls(res *ir.Nodes, decls []syntax.Decl) {
22 for _, decl := range decls {
23 switch decl := decl.(type) {
24 case *syntax.ConstDecl:
25 g.constDecl(res, decl)
26 case *syntax.FuncDecl:
27 g.funcDecl(res, decl)
28 case *syntax.TypeDecl:
29 if ir.CurFunc == nil {
30 continue
31 }
32 g.typeDecl(res, decl)
33 case *syntax.VarDecl:
34 g.varDecl(res, decl)
35 default:
36 g.unhandled("declaration", decl)
37 }
38 }
39 }
40
41 func (g *irgen) importDecl(p *noder, decl *syntax.ImportDecl) {
42 g.pragmaFlags(decl.Pragma, 0)
43
44
45
46
47 switch pkgNameOf(g.info, decl).Imported().Path() {
48 case "unsafe":
49 p.importedUnsafe = true
50 case "embed":
51 p.importedEmbed = true
52 }
53 }
54
55
56 func pkgNameOf(info *types2.Info, decl *syntax.ImportDecl) *types2.PkgName {
57 if name := decl.LocalPkgName; name != nil {
58 return info.Defs[name].(*types2.PkgName)
59 }
60 return info.Implicits[decl].(*types2.PkgName)
61 }
62
63 func (g *irgen) constDecl(out *ir.Nodes, decl *syntax.ConstDecl) {
64 g.pragmaFlags(decl.Pragma, 0)
65
66 for _, name := range decl.NameList {
67 name, obj := g.def(name)
68
69
70
71
72
73 val := obj.(*types2.Const).Val()
74 switch name.Type() {
75 case types.UntypedInt, types.UntypedRune:
76 val = constant.ToInt(val)
77 case types.UntypedFloat:
78 val = constant.ToFloat(val)
79 case types.UntypedComplex:
80 val = constant.ToComplex(val)
81 }
82 name.SetVal(val)
83
84 out.Append(ir.NewDecl(g.pos(decl), ir.ODCLCONST, name))
85 }
86 }
87
88 func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
89 assert(g.curDecl == "")
90
91
92 g.curDecl = decl.Name.Value
93 obj2 := g.info.Defs[decl.Name]
94 recv := types2.AsSignature(obj2.Type()).Recv()
95 if recv != nil {
96 t2 := deref2(recv.Type())
97
98 g.curDecl = t2.(*types2.Named).Obj().Name() + "." + g.curDecl
99 }
100
101 fn := ir.NewFunc(g.pos(decl))
102 fn.Nname, _ = g.def(decl.Name)
103 fn.Nname.Func = fn
104 fn.Nname.Defn = fn
105
106 fn.Pragma = g.pragmaFlags(decl.Pragma, funcPragmas)
107 if fn.Pragma&ir.Systemstack != 0 && fn.Pragma&ir.Nosplit != 0 {
108 base.ErrorfAt(fn.Pos(), "go:nosplit and go:systemstack cannot be combined")
109 }
110 if fn.Pragma&ir.Nointerface != 0 {
111
112
113
114
115 if recv := fn.Type().Recv(); recv != nil {
116 typ := types.ReceiverBaseType(recv.Type)
117 if orig := typ.OrigType(); orig != nil {
118
119
120
121 typ = orig
122 }
123 meth := typecheck.Lookdot1(fn, typecheck.Lookup(decl.Name.Value), typ, typ.Methods(), 0)
124 meth.SetNointerface(true)
125 }
126 }
127
128 if decl.Body != nil && fn.Pragma&ir.Noescape != 0 {
129 base.ErrorfAt(fn.Pos(), "can only use //go:noescape with external func implementations")
130 }
131
132 if decl.Name.Value == "init" && decl.Recv == nil {
133 g.target.Inits = append(g.target.Inits, fn)
134 }
135
136 saveHaveEmbed := g.haveEmbed
137 saveCurDecl := g.curDecl
138 g.curDecl = ""
139 g.later(func() {
140 defer func(b bool, s string) {
141
142
143 g.haveEmbed = b
144 g.curDecl = s
145 }(g.haveEmbed, g.curDecl)
146
147
148 g.haveEmbed = saveHaveEmbed
149 g.curDecl = saveCurDecl
150 if fn.Type().HasTParam() {
151 g.topFuncIsGeneric = true
152 }
153 g.funcBody(fn, decl.Recv, decl.Type, decl.Body)
154 g.topFuncIsGeneric = false
155 if fn.Type().HasTParam() && fn.Body != nil {
156
157
158
159 fn.Inl = &ir.Inline{
160 Cost: 1,
161 Dcl: fn.Dcl,
162 Body: fn.Body,
163 }
164 }
165
166 out.Append(fn)
167 })
168 }
169
170 func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
171
172 base.Pos = g.pos(decl)
173 assert(ir.CurFunc != nil || g.curDecl == "")
174
175
176 saveCurDecl := g.curDecl
177 g.curDecl = decl.Name.Value
178 if decl.Alias {
179 name, _ := g.def(decl.Name)
180 g.pragmaFlags(decl.Pragma, 0)
181 assert(name.Alias())
182
183 out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name))
184 g.curDecl = ""
185 return
186 }
187
188
189 types.DeferCheckSize()
190
191 name, obj := g.def(decl.Name)
192 ntyp, otyp := name.Type(), obj.Type()
193 if ir.CurFunc != nil {
194 ntyp.SetVargen()
195 }
196
197 pragmas := g.pragmaFlags(decl.Pragma, typePragmas)
198 name.SetPragma(pragmas)
199
200 if pragmas&ir.NotInHeap != 0 {
201 ntyp.SetNotInHeap(true)
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 ntyp.SetUnderlying(g.typeExpr(decl.Type))
225
226 tparams := otyp.(*types2.Named).TypeParams()
227 if n := tparams.Len(); n > 0 {
228 rparams := make([]*types.Type, n)
229 for i := range rparams {
230 rparams[i] = g.typ(tparams.At(i))
231 }
232
233 ntyp.SetRParams(rparams)
234 }
235 types.ResumeCheckSize()
236
237 g.curDecl = saveCurDecl
238 if otyp, ok := otyp.(*types2.Named); ok && otyp.NumMethods() != 0 {
239 methods := make([]*types.Field, otyp.NumMethods())
240 for i := range methods {
241 m := otyp.Method(i)
242
243
244 g.curDecl = decl.Name.Value + "." + m.Name()
245 meth := g.obj(m)
246 methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type())
247 methods[i].Nname = meth
248 g.curDecl = ""
249 }
250 ntyp.Methods().Set(methods)
251 }
252
253 out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name))
254 }
255
256 func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) {
257 pos := g.pos(decl)
258
259 base.Pos = pos
260 names := make([]*ir.Name, len(decl.NameList))
261 for i, name := range decl.NameList {
262 names[i], _ = g.def(name)
263 }
264
265 if decl.Pragma != nil {
266 pragma := decl.Pragma.(*pragmas)
267 varEmbed(g.makeXPos, names[0], decl, pragma, g.haveEmbed)
268 g.reportUnused(pragma)
269 }
270
271 haveEmbed := g.haveEmbed
272 do := func() {
273 defer func(b bool) { g.haveEmbed = b }(g.haveEmbed)
274
275 g.haveEmbed = haveEmbed
276 values := g.exprList(decl.Values)
277
278 var as2 *ir.AssignListStmt
279 if len(values) != 0 && len(names) != len(values) {
280 as2 = ir.NewAssignListStmt(pos, ir.OAS2, make([]ir.Node, len(names)), values)
281 }
282
283 for i, name := range names {
284 if ir.CurFunc != nil {
285 out.Append(ir.NewDecl(pos, ir.ODCL, name))
286 }
287 if as2 != nil {
288 as2.Lhs[i] = name
289 name.Defn = as2
290 } else {
291 as := ir.NewAssignStmt(pos, name, nil)
292 if len(values) != 0 {
293 as.Y = values[i]
294 name.Defn = as
295 } else if ir.CurFunc == nil {
296 name.Defn = as
297 }
298 if !g.delayTransform() {
299 lhs := []ir.Node{as.X}
300 rhs := []ir.Node{}
301 if as.Y != nil {
302 rhs = []ir.Node{as.Y}
303 }
304 transformAssign(as, lhs, rhs)
305 as.X = lhs[0]
306 if as.Y != nil {
307 as.Y = rhs[0]
308 }
309 }
310 as.SetTypecheck(1)
311 out.Append(as)
312 }
313 }
314 if as2 != nil {
315 if !g.delayTransform() {
316 transformAssign(as2, as2.Lhs, as2.Rhs)
317 }
318 as2.SetTypecheck(1)
319 out.Append(as2)
320 }
321 }
322
323
324
325
326 if ir.CurFunc != nil {
327 do()
328 } else {
329 g.later(do)
330 }
331 }
332
333
334
335 func (g *irgen) pragmaFlags(pragma syntax.Pragma, allowed ir.PragmaFlag) ir.PragmaFlag {
336 if pragma == nil {
337 return 0
338 }
339 p := pragma.(*pragmas)
340 present := p.Flag & allowed
341 p.Flag &^= allowed
342 g.reportUnused(p)
343 return present
344 }
345
346
347 func (g *irgen) reportUnused(pragma *pragmas) {
348 for _, pos := range pragma.Pos {
349 if pos.Flag&pragma.Flag != 0 {
350 base.ErrorfAt(g.makeXPos(pos.Pos), "misplaced compiler directive")
351 }
352 }
353 if len(pragma.Embeds) > 0 {
354 for _, e := range pragma.Embeds {
355 base.ErrorfAt(g.makeXPos(e.Pos), "misplaced go:embed directive")
356 }
357 }
358 }
359
View as plain text