|
5 | 5 | package noder
|
6 | 6 |
|
7 | 7 | import (
|
8 |
| - "go/constant" |
9 |
| - |
10 |
| - "cmd/compile/internal/base" |
11 |
| - "cmd/compile/internal/ir" |
12 | 8 | "cmd/compile/internal/syntax"
|
13 |
| - "cmd/compile/internal/typecheck" |
14 |
| - "cmd/compile/internal/types" |
15 | 9 | "cmd/compile/internal/types2"
|
16 | 10 | )
|
17 | 11 |
|
18 |
| -// TODO(mdempsky): Skip blank declarations? Probably only safe |
19 |
| -// for declarations without pragmas. |
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 // already handled in irgen.generate |
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 |
| - // Get the imported package's path, as resolved already by types2 |
45 |
| - // and gcimporter. This is the same path as would be computed by |
46 |
| - // parseImportPath. |
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 | 12 | // pkgNameOf returns the PkgName associated with the given ImportDecl.
|
56 | 13 | func pkgNameOf(info *types2.Info, decl *syntax.ImportDecl) *types2.PkgName {
|
57 | 14 | if name := decl.LocalPkgName; name != nil {
|
58 | 15 | return info.Defs[name].(*types2.PkgName)
|
59 | 16 | }
|
60 | 17 | return info.Implicits[decl].(*types2.PkgName)
|
61 | 18 | }
|
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 |
| - // For untyped numeric constants, make sure the value |
70 |
| - // representation matches what the rest of the |
71 |
| - // compiler (really just iexport) expects. |
72 |
| - // TODO(mdempsky): Revisit after #43891 is resolved. |
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 |
| - // Set g.curDecl to the function name, as context for the type params declared |
91 |
| - // during types2-to-types1 translation if this is a generic function. |
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 |
| - // This is a method, so set g.curDecl to recvTypeName.methName instead. |
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 |
| - // Propagate //go:nointerface from Func.Pragma to Field.Nointerface. |
112 |
| - // This is a bit roundabout, but this is the earliest point where we've |
113 |
| - // processed the function's pragma flags, and we've also already created |
114 |
| - // the Fields to represent the receiver's method set. |
115 |
| - if recv := fn.Type().Recv(); recv != nil { |
116 |
| - typ := types.ReceiverBaseType(recv.Type) |
117 |
| - if orig := typ.OrigType(); orig != nil { |
118 |
| - // For a generic method, we mark the methods on the |
119 |
| - // base generic type, since those are the methods |
120 |
| - // that will be stenciled. |
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 { |
129 |
| - if fn.Pragma&ir.Noescape != 0 { |
130 |
| - base.ErrorfAt(fn.Pos(), "can only use //go:noescape with external func implementations") |
131 |
| - } |
132 |
| - if (fn.Pragma&ir.UintptrKeepAlive != 0 && fn.Pragma&ir.UintptrEscapes == 0) && fn.Pragma&ir.Nosplit == 0 { |
133 |
| - // Stack growth can't handle uintptr arguments that may |
134 |
| - // be pointers (as we don't know which are pointers |
135 |
| - // when creating the stack map). Thus uintptrkeepalive |
136 |
| - // functions (and all transitive callees) must be |
137 |
| - // nosplit. |
138 |
| - // |
139 |
| - // N.B. uintptrescapes implies uintptrkeepalive but it |
140 |
| - // is OK since the arguments must escape to the heap. |
141 |
| - // |
142 |
| - // TODO(prattmic): Add recursive nosplit check of callees. |
143 |
| - // TODO(prattmic): Functions with no body (i.e., |
144 |
| - // assembly) must also be nosplit, but we can't check |
145 |
| - // that here. |
146 |
| - base.ErrorfAt(fn.Pos(), "go:uintptrkeepalive requires go:nosplit") |
147 |
| - } |
148 |
| - } |
149 |
| - |
150 |
| - if decl.Name.Value == "init" && decl.Recv == nil { |
151 |
| - g.target.Inits = append(g.target.Inits, fn) |
152 |
| - } |
153 |
| - |
154 |
| - saveHaveEmbed := g.haveEmbed |
155 |
| - saveCurDecl := g.curDecl |
156 |
| - g.curDecl = "" |
157 |
| - g.later(func() { |
158 |
| - defer func(b bool, s string) { |
159 |
| - // Revert haveEmbed and curDecl back to what they were before |
160 |
| - // the "later" function. |
161 |
| - g.haveEmbed = b |
162 |
| - g.curDecl = s |
163 |
| - }(g.haveEmbed, g.curDecl) |
164 |
| - |
165 |
| - // Set haveEmbed and curDecl to what they were for this funcDecl. |
166 |
| - g.haveEmbed = saveHaveEmbed |
167 |
| - g.curDecl = saveCurDecl |
168 |
| - if fn.Type().HasTParam() { |
169 |
| - g.topFuncIsGeneric = true |
170 |
| - } |
171 |
| - g.funcBody(fn, decl.Recv, decl.Type, decl.Body) |
172 |
| - g.topFuncIsGeneric = false |
173 |
| - if fn.Type().HasTParam() && fn.Body != nil { |
174 |
| - // Set pointers to the dcls/body of a generic function/method in |
175 |
| - // the Inl struct, so it is marked for export, is available for |
176 |
| - // stenciling, and works with Inline_Flood(). |
177 |
| - fn.Inl = &ir.Inline{ |
178 |
| - Cost: 1, |
179 |
| - Dcl: fn.Dcl, |
180 |
| - Body: fn.Body, |
181 |
| - } |
182 |
| - } |
183 |
| - |
184 |
| - out.Append(fn) |
185 |
| - }) |
186 |
| -} |
187 |
| - |
188 |
| -func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { |
189 |
| - // Set the position for any error messages we might print (e.g. too large types). |
190 |
| - base.Pos = g.pos(decl) |
191 |
| - assert(ir.CurFunc != nil || g.curDecl == "") |
192 |
| - // Set g.curDecl to the type name, as context for the type params declared |
193 |
| - // during types2-to-types1 translation if this is a generic type. |
194 |
| - saveCurDecl := g.curDecl |
195 |
| - g.curDecl = decl.Name.Value |
196 |
| - if decl.Alias { |
197 |
| - name, _ := g.def(decl.Name) |
198 |
| - g.pragmaFlags(decl.Pragma, 0) |
199 |
| - assert(name.Alias()) // should be set by irgen.obj |
200 |
| - |
201 |
| - out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name)) |
202 |
| - g.curDecl = "" |
203 |
| - return |
204 |
| - } |
205 |
| - |
206 |
| - // Prevent size calculations until we set the underlying type. |
207 |
| - types.DeferCheckSize() |
208 |
| - |
209 |
| - name, obj := g.def(decl.Name) |
210 |
| - ntyp, otyp := name.Type(), obj.Type() |
211 |
| - if ir.CurFunc != nil { |
212 |
| - ntyp.SetVargen() |
213 |
| - } |
214 |
| - |
215 |
| - pragmas := g.pragmaFlags(decl.Pragma, 0) |
216 |
| - name.SetPragma(pragmas) // TODO(mdempsky): Is this still needed? |
217 |
| - |
218 |
| - ntyp.SetUnderlying(g.typeExpr(decl.Type)) |
219 |
| - |
220 |
| - tparams := otyp.(*types2.Named).TypeParams() |
221 |
| - if n := tparams.Len(); n > 0 { |
222 |
| - rparams := make([]*types.Type, n) |
223 |
| - for i := range rparams { |
224 |
| - rparams[i] = g.typ(tparams.At(i)) |
225 |
| - } |
226 |
| - // This will set hasTParam flag if any rparams are not concrete types. |
227 |
| - ntyp.SetRParams(rparams) |
228 |
| - } |
229 |
| - types.ResumeCheckSize() |
230 |
| - |
231 |
| - g.curDecl = saveCurDecl |
232 |
| - if otyp, ok := otyp.(*types2.Named); ok && otyp.NumMethods() != 0 { |
233 |
| - methods := make([]*types.Field, otyp.NumMethods()) |
234 |
| - for i := range methods { |
235 |
| - m := otyp.Method(i) |
236 |
| - // Set g.curDecl to recvTypeName.methName, as context for the |
237 |
| - // method-specific type params in the receiver. |
238 |
| - g.curDecl = decl.Name.Value + "." + m.Name() |
239 |
| - meth := g.obj(m) |
240 |
| - methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type()) |
241 |
| - methods[i].Nname = meth |
242 |
| - g.curDecl = "" |
243 |
| - } |
244 |
| - ntyp.Methods().Set(methods) |
245 |
| - } |
246 |
| - |
247 |
| - out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name)) |
248 |
| -} |
249 |
| - |
250 |
| -func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) { |
251 |
| - pos := g.pos(decl) |
252 |
| - // Set the position for any error messages we might print (e.g. too large types). |
253 |
| - base.Pos = pos |
254 |
| - names := make([]*ir.Name, len(decl.NameList)) |
255 |
| - for i, name := range decl.NameList { |
256 |
| - names[i], _ = g.def(name) |
257 |
| - } |
258 |
| - |
259 |
| - if decl.Pragma != nil { |
260 |
| - pragma := decl.Pragma.(*pragmas) |
261 |
| - varEmbed(g.makeXPos, names[0], decl, pragma, g.haveEmbed) |
262 |
| - g.reportUnused(pragma) |
263 |
| - } |
264 |
| - |
265 |
| - haveEmbed := g.haveEmbed |
266 |
| - do := func() { |
267 |
| - defer func(b bool) { g.haveEmbed = b }(g.haveEmbed) |
268 |
| - |
269 |
| - g.haveEmbed = haveEmbed |
270 |
| - values := g.exprList(decl.Values) |
271 |
| - |
272 |
| - var as2 *ir.AssignListStmt |
273 |
| - if len(values) != 0 && len(names) != len(values) { |
274 |
| - as2 = ir.NewAssignListStmt(pos, ir.OAS2, make([]ir.Node, len(names)), values) |
275 |
| - } |
276 |
| - |
277 |
| - for i, name := range names { |
278 |
| - if ir.CurFunc != nil { |
279 |
| - out.Append(ir.NewDecl(pos, ir.ODCL, name)) |
280 |
| - } |
281 |
| - if as2 != nil { |
282 |
| - as2.Lhs[i] = name |
283 |
| - name.Defn = as2 |
284 |
| - } else { |
285 |
| - as := ir.NewAssignStmt(pos, name, nil) |
286 |
| - if len(values) != 0 { |
287 |
| - as.Y = values[i] |
288 |
| - name.Defn = as |
289 |
| - } else if ir.CurFunc == nil { |
290 |
| - name.Defn = as |
291 |
| - } |
292 |
| - if !g.delayTransform() { |
293 |
| - lhs := []ir.Node{as.X} |
294 |
| - rhs := []ir.Node{} |
295 |
| - if as.Y != nil { |
296 |
| - rhs = []ir.Node{as.Y} |
297 |
| - } |
298 |
| - transformAssign(as, lhs, rhs) |
299 |
| - as.X = lhs[0] |
300 |
| - if as.Y != nil { |
301 |
| - as.Y = rhs[0] |
302 |
| - } |
303 |
| - } |
304 |
| - as.SetTypecheck(1) |
305 |
| - out.Append(as) |
306 |
| - } |
307 |
| - } |
308 |
| - if as2 != nil { |
309 |
| - if !g.delayTransform() { |
310 |
| - transformAssign(as2, as2.Lhs, as2.Rhs) |
311 |
| - } |
312 |
| - as2.SetTypecheck(1) |
313 |
| - out.Append(as2) |
314 |
| - } |
315 |
| - } |
316 |
| - |
317 |
| - // If we're within a function, we need to process the assignment |
318 |
| - // part of the variable declaration right away. Otherwise, we leave |
319 |
| - // it to be handled after all top-level declarations are processed. |
320 |
| - if ir.CurFunc != nil { |
321 |
| - do() |
322 |
| - } else { |
323 |
| - g.later(do) |
324 |
| - } |
325 |
| -} |
326 |
| - |
327 |
| -// pragmaFlags returns any specified pragma flags included in allowed, |
328 |
| -// and reports errors about any other, unexpected pragmas. |
329 |
| -func (g *irgen) pragmaFlags(pragma syntax.Pragma, allowed ir.PragmaFlag) ir.PragmaFlag { |
330 |
| - if pragma == nil { |
331 |
| - return 0 |
332 |
| - } |
333 |
| - p := pragma.(*pragmas) |
334 |
| - present := p.Flag & allowed |
335 |
| - p.Flag &^= allowed |
336 |
| - g.reportUnused(p) |
337 |
| - return present |
338 |
| -} |
339 |
| - |
340 |
| -// reportUnused reports errors about any unused pragmas. |
341 |
| -func (g *irgen) reportUnused(pragma *pragmas) { |
342 |
| - for _, pos := range pragma.Pos { |
343 |
| - if pos.Flag&pragma.Flag != 0 { |
344 |
| - base.ErrorfAt(g.makeXPos(pos.Pos), "misplaced compiler directive") |
345 |
| - } |
346 |
| - } |
347 |
| - if len(pragma.Embeds) > 0 { |
348 |
| - for _, e := range pragma.Embeds { |
349 |
| - base.ErrorfAt(g.makeXPos(e.Pos), "misplaced go:embed directive") |
350 |
| - } |
351 |
| - } |
352 |
| -} |
0 commit comments