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 OrigConst(pos src.XPos, typ *types.Type, val constant.Value, op ir.Op, raw string) ir.Node {
47 orig := ir.NewRawOrigExpr(pos, op, raw)
48 return ir.NewConstExpr(val, typed(typ, orig))
49 }
50
51
52
53 func FixValue(typ *types.Type, val constant.Value) constant.Value {
54 assert(typ.Kind() != types.TFORW)
55 switch {
56 case typ.IsInteger():
57 val = constant.ToInt(val)
58 case typ.IsFloat():
59 val = constant.ToFloat(val)
60 case typ.IsComplex():
61 val = constant.ToComplex(val)
62 }
63 if !typ.IsUntyped() {
64 val = typecheck.DefaultLit(ir.NewBasicLit(src.NoXPos, val), typ).Val()
65 }
66 if !typ.IsTypeParam() {
67 ir.AssertValidTypeForConst(typ, val)
68 }
69 return val
70 }
71
72 func Nil(pos src.XPos, typ *types.Type) ir.Node {
73 return typed(typ, ir.NewNilExpr(pos))
74 }
75
76
77
78 func Addr(pos src.XPos, x ir.Node) *ir.AddrExpr {
79 n := typecheck.NodAddrAt(pos, x)
80 typed(types.NewPtr(x.Type()), n)
81 return n
82 }
83
84 func Assert(pos src.XPos, x ir.Node, typ *types.Type) ir.Node {
85 return typed(typ, ir.NewTypeAssertExpr(pos, x, nil))
86 }
87
88 func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) *ir.BinaryExpr {
89 switch op {
90 case ir.OADD:
91 n := ir.NewBinaryExpr(pos, op, x, y)
92 typed(typ, n)
93 return n
94 default:
95 n := ir.NewBinaryExpr(pos, op, x, y)
96 typed(x.Type(), n)
97 return n
98 }
99 }
100
101 func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) *ir.BinaryExpr {
102 n := ir.NewBinaryExpr(pos, op, x, y)
103 typed(typ, n)
104 return n
105 }
106
107 func Deref(pos src.XPos, typ *types.Type, x ir.Node) *ir.StarExpr {
108 n := ir.NewStarExpr(pos, x)
109 typed(typ, n)
110 return n
111 }
112
113 func DotField(pos src.XPos, x ir.Node, index int) *ir.SelectorExpr {
114 op, typ := ir.ODOT, x.Type()
115 if typ.IsPtr() {
116 op, typ = ir.ODOTPTR, typ.Elem()
117 }
118 if !typ.IsStruct() {
119 base.FatalfAt(pos, "DotField of non-struct: %L", x)
120 }
121
122
123 types.CalcSize(typ)
124
125 field := typ.Field(index)
126 return dot(pos, field.Type, op, x, field)
127 }
128
129 func DotMethod(pos src.XPos, x ir.Node, index int) *ir.SelectorExpr {
130 method := method(x.Type(), index)
131
132
133 typ := typecheck.NewMethodType(method.Type, nil)
134 return dot(pos, typ, ir.OMETHVALUE, x, method)
135 }
136
137
138
139
140
141
142 func MethodExpr(pos src.XPos, recv ir.Node, embed *types.Type, index int) *ir.SelectorExpr {
143 method := method(embed, index)
144 typ := typecheck.NewMethodType(method.Type, recv.Type())
145
146
147
148
149
150
151
152 if recv.Sym() == nil {
153 typecheck.NeedRuntimeType(recv.Type())
154 }
155 return dot(pos, typ, ir.OMETHEXPR, recv, method)
156 }
157
158 func dot(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node, selection *types.Field) *ir.SelectorExpr {
159 n := ir.NewSelectorExpr(pos, op, x, selection.Sym)
160 n.Selection = selection
161 typed(typ, n)
162 return n
163 }
164
165
166 func method(typ *types.Type, index int) *types.Field {
167 if typ.IsInterface() {
168 return typ.AllMethods().Index(index)
169 }
170 return types.ReceiverBaseType(typ).Methods().Index(index)
171 }
172
173 func Index(pos src.XPos, typ *types.Type, x, index ir.Node) *ir.IndexExpr {
174 n := ir.NewIndexExpr(pos, x, index)
175 typed(typ, n)
176 return n
177 }
178
179 func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) *ir.SliceExpr {
180 op := ir.OSLICE
181 if max != nil {
182 op = ir.OSLICE3
183 }
184 n := ir.NewSliceExpr(pos, op, x, low, high, max)
185 typed(typ, n)
186 return n
187 }
188
189 func Unary(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node) ir.Node {
190 switch op {
191 case ir.OADDR:
192 return Addr(pos, x)
193 case ir.ODEREF:
194 return Deref(pos, typ, x)
195 }
196
197 if op == ir.ORECV {
198 if typ.IsFuncArgStruct() && typ.NumFields() == 2 {
199
200
201
202 assert(typ.Field(1).Type.Kind() == types.TBOOL)
203 typ = typ.Field(0).Type
204 }
205 }
206 return typed(typ, ir.NewUnaryExpr(pos, op, x))
207 }
208
209
210
211 var one = constant.MakeInt64(1)
212
213 func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt {
214 assert(x.Type() != nil)
215 bl := ir.NewBasicLit(pos, one)
216 if x.Type().HasTParam() {
217
218
219
220
221 typed(x.Type(), bl)
222 } else {
223 bl = typecheck.DefaultLit(bl, x.Type())
224 }
225 return ir.NewAssignOpStmt(pos, op, x, bl)
226 }
227
View as plain text