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/typecheck"
13 "cmd/compile/internal/types"
14 "cmd/internal/src"
15 )
16
17
18
19
20
21
22 type ImplicitNode interface {
23 ir.Node
24 SetImplicit(x bool)
25 }
26
27
28 func Implicit(n ImplicitNode) ImplicitNode {
29 n.SetImplicit(true)
30 return n
31 }
32
33
34 func typed(typ *types.Type, n ir.Node) ir.Node {
35 n.SetType(typ)
36 n.SetTypecheck(1)
37 return n
38 }
39
40
41
42 func Const(pos src.XPos, typ *types.Type, val constant.Value) ir.Node {
43 return typed(typ, ir.NewBasicLit(pos, val))
44 }
45
46 func Nil(pos src.XPos, typ *types.Type) ir.Node {
47 return typed(typ, ir.NewNilExpr(pos))
48 }
49
50
51
52 func Addr(pos src.XPos, x ir.Node) *ir.AddrExpr {
53 n := typecheck.NodAddrAt(pos, x)
54 switch x.Op() {
55 case ir.OARRAYLIT, ir.OMAPLIT, ir.OSLICELIT, ir.OSTRUCTLIT:
56 n.SetOp(ir.OPTRLIT)
57 }
58 typed(types.NewPtr(x.Type()), n)
59 return n
60 }
61
62 func Assert(pos src.XPos, x ir.Node, typ *types.Type) ir.Node {
63 return typed(typ, ir.NewTypeAssertExpr(pos, x, nil))
64 }
65
66 func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) ir.Node {
67 switch op {
68 case ir.OANDAND, ir.OOROR:
69 return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y))
70 case ir.OADD:
71 n := ir.NewBinaryExpr(pos, op, x, y)
72 if x.Type().HasTParam() || y.Type().HasTParam() {
73
74
75
76 n.SetType(typ)
77 n.SetTypecheck(3)
78 return n
79 }
80 typed(typ, n)
81 return transformAdd(n)
82 default:
83 return typed(x.Type(), ir.NewBinaryExpr(pos, op, x, y))
84 }
85 }
86
87 func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node {
88 n := ir.NewCallExpr(pos, ir.OCALL, fun, args)
89 n.IsDDD = dots
90
91
92 n.Use = ir.CallUseExpr
93
94 if fun.Op() == ir.OTYPE {
95
96 if fun.Type().HasTParam() || args[0].Type().HasTParam() {
97
98
99 return typed(typ, n)
100 }
101 typed(typ, n)
102 return transformConvCall(n)
103 }
104
105 if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 {
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 switch fun.BuiltinOp {
121 case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OLEN, ir.OCAP, ir.OAPPEND:
122 hasTParam := false
123 for _, arg := range args {
124 if arg.Type().HasTParam() {
125 hasTParam = true
126 break
127 }
128 }
129 if hasTParam {
130 return typed(typ, n)
131 }
132 }
133
134 typed(typ, n)
135 return transformBuiltin(n)
136 }
137
138
139 switch fun := fun.(type) {
140 case *ir.ClosureExpr:
141 fun.Func.SetClosureCalled(true)
142 case *ir.SelectorExpr:
143 if fun.Op() == ir.OCALLPART {
144 op := ir.ODOTMETH
145 if fun.X.Type().IsInterface() {
146 op = ir.ODOTINTER
147 }
148 fun.SetOp(op)
149
150
151 fun.SetType(fun.Selection.Type)
152 }
153 }
154
155 if fun.Type().HasTParam() {
156
157
158
159
160
161 return typed(typ, n)
162 }
163
164 if fun.Op() == ir.OXDOT {
165 if !fun.(*ir.SelectorExpr).X.Type().HasTParam() {
166 base.FatalfAt(pos, "Expecting type param receiver in %v", fun)
167 }
168
169
170
171 typed(typ, n)
172 return n
173 }
174 if fun.Op() != ir.OFUNCINST {
175
176
177 typed(typ, n)
178 transformCall(n)
179 return n
180 }
181
182
183 typed(typ, n)
184 return n
185 }
186
187 func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node {
188 n := ir.NewBinaryExpr(pos, op, x, y)
189 if x.Type().HasTParam() || y.Type().HasTParam() {
190
191
192 n.SetType(typ)
193 n.SetTypecheck(3)
194 return n
195 }
196 typed(typ, n)
197 transformCompare(n)
198 return n
199 }
200
201 func Deref(pos src.XPos, typ *types.Type, x ir.Node) *ir.StarExpr {
202 n := ir.NewStarExpr(pos, x)
203 typed(typ, n)
204 return n
205 }
206
207 func DotField(pos src.XPos, x ir.Node, index int) *ir.SelectorExpr {
208 op, typ := ir.ODOT, x.Type()
209 if typ.IsPtr() {
210 op, typ = ir.ODOTPTR, typ.Elem()
211 }
212 if !typ.IsStruct() {
213 base.FatalfAt(pos, "DotField of non-struct: %L", x)
214 }
215
216
217 types.CalcSize(typ)
218
219 field := typ.Field(index)
220 return dot(pos, field.Type, op, x, field)
221 }
222
223 func DotMethod(pos src.XPos, x ir.Node, index int) *ir.SelectorExpr {
224 method := method(x.Type(), index)
225
226
227 typ := typecheck.NewMethodType(method.Type, nil)
228 return dot(pos, typ, ir.OCALLPART, x, method)
229 }
230
231
232
233
234
235
236 func MethodExpr(pos src.XPos, recv ir.Node, embed *types.Type, index int) *ir.SelectorExpr {
237 method := method(embed, index)
238 typ := typecheck.NewMethodType(method.Type, recv.Type())
239
240
241
242
243
244
245
246 if recv.Sym() == nil {
247 typecheck.NeedRuntimeType(recv.Type())
248 }
249 return dot(pos, typ, ir.OMETHEXPR, recv, method)
250 }
251
252 func dot(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node, selection *types.Field) *ir.SelectorExpr {
253 n := ir.NewSelectorExpr(pos, op, x, selection.Sym)
254 n.Selection = selection
255 typed(typ, n)
256 return n
257 }
258
259
260 func method(typ *types.Type, index int) *types.Field {
261 if typ.IsInterface() {
262 return typ.AllMethods().Index(index)
263 }
264 return types.ReceiverBaseType(typ).Methods().Index(index)
265 }
266
267 func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node {
268 n := ir.NewIndexExpr(pos, x, index)
269 if x.Type().HasTParam() {
270
271 n.SetType(typ)
272 n.SetTypecheck(3)
273 return n
274 }
275 typed(typ, n)
276
277 transformIndex(n)
278 return n
279 }
280
281 func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) ir.Node {
282 op := ir.OSLICE
283 if max != nil {
284 op = ir.OSLICE3
285 }
286 n := ir.NewSliceExpr(pos, op, x, low, high, max)
287 if x.Type().HasTParam() {
288
289 n.SetType(typ)
290 n.SetTypecheck(3)
291 return n
292 }
293 typed(typ, n)
294 transformSlice(n)
295 return n
296 }
297
298 func Unary(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node) ir.Node {
299 switch op {
300 case ir.OADDR:
301 return Addr(pos, x)
302 case ir.ODEREF:
303 return Deref(pos, typ, x)
304 }
305
306 if op == ir.ORECV {
307 if typ.IsFuncArgStruct() && typ.NumFields() == 2 {
308
309
310
311 assert(typ.Field(1).Type.Kind() == types.TBOOL)
312 typ = typ.Field(0).Type
313 }
314 }
315 return typed(typ, ir.NewUnaryExpr(pos, op, x))
316 }
317
318
319
320 var one = constant.MakeInt64(1)
321
322 func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt {
323 assert(x.Type() != nil)
324 return ir.NewAssignOpStmt(pos, op, x, typecheck.DefaultLit(ir.NewBasicLit(pos, one), x.Type()))
325 }
326
View as plain text