diff options
Diffstat (limited to 'vendor/honnef.co/go/tools/ssa/ssa.go')
-rw-r--r-- | vendor/honnef.co/go/tools/ssa/ssa.go | 1745 |
1 files changed, 1745 insertions, 0 deletions
diff --git a/vendor/honnef.co/go/tools/ssa/ssa.go b/vendor/honnef.co/go/tools/ssa/ssa.go new file mode 100644 index 0000000..aeddd65 --- /dev/null +++ b/vendor/honnef.co/go/tools/ssa/ssa.go | |||
@@ -0,0 +1,1745 @@ | |||
1 | // Copyright 2013 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 | |||
5 | package ssa | ||
6 | |||
7 | // This package defines a high-level intermediate representation for | ||
8 | // Go programs using static single-assignment (SSA) form. | ||
9 | |||
10 | import ( | ||
11 | "fmt" | ||
12 | "go/ast" | ||
13 | "go/constant" | ||
14 | "go/token" | ||
15 | "go/types" | ||
16 | "sync" | ||
17 | |||
18 | "golang.org/x/tools/go/types/typeutil" | ||
19 | ) | ||
20 | |||
21 | // A Program is a partial or complete Go program converted to SSA form. | ||
22 | type Program struct { | ||
23 | Fset *token.FileSet // position information for the files of this Program | ||
24 | imported map[string]*Package // all importable Packages, keyed by import path | ||
25 | packages map[*types.Package]*Package // all loaded Packages, keyed by object | ||
26 | mode BuilderMode // set of mode bits for SSA construction | ||
27 | MethodSets typeutil.MethodSetCache // cache of type-checker's method-sets | ||
28 | |||
29 | methodsMu sync.Mutex // guards the following maps: | ||
30 | methodSets typeutil.Map // maps type to its concrete methodSet | ||
31 | runtimeTypes typeutil.Map // types for which rtypes are needed | ||
32 | canon typeutil.Map // type canonicalization map | ||
33 | bounds map[*types.Func]*Function // bounds for curried x.Method closures | ||
34 | thunks map[selectionKey]*Function // thunks for T.Method expressions | ||
35 | } | ||
36 | |||
37 | // A Package is a single analyzed Go package containing Members for | ||
38 | // all package-level functions, variables, constants and types it | ||
39 | // declares. These may be accessed directly via Members, or via the | ||
40 | // type-specific accessor methods Func, Type, Var and Const. | ||
41 | // | ||
42 | // Members also contains entries for "init" (the synthetic package | ||
43 | // initializer) and "init#%d", the nth declared init function, | ||
44 | // and unspecified other things too. | ||
45 | // | ||
46 | type Package struct { | ||
47 | Prog *Program // the owning program | ||
48 | Pkg *types.Package // the corresponding go/types.Package | ||
49 | Members map[string]Member // all package members keyed by name (incl. init and init#%d) | ||
50 | values map[types.Object]Value // package members (incl. types and methods), keyed by object | ||
51 | init *Function // Func("init"); the package's init function | ||
52 | debug bool // include full debug info in this package | ||
53 | |||
54 | // The following fields are set transiently, then cleared | ||
55 | // after building. | ||
56 | buildOnce sync.Once // ensures package building occurs once | ||
57 | ninit int32 // number of init functions | ||
58 | info *types.Info // package type information | ||
59 | files []*ast.File // package ASTs | ||
60 | } | ||
61 | |||
62 | // A Member is a member of a Go package, implemented by *NamedConst, | ||
63 | // *Global, *Function, or *Type; they are created by package-level | ||
64 | // const, var, func and type declarations respectively. | ||
65 | // | ||
66 | type Member interface { | ||
67 | Name() string // declared name of the package member | ||
68 | String() string // package-qualified name of the package member | ||
69 | RelString(*types.Package) string // like String, but relative refs are unqualified | ||
70 | Object() types.Object // typechecker's object for this member, if any | ||
71 | Pos() token.Pos // position of member's declaration, if known | ||
72 | Type() types.Type // type of the package member | ||
73 | Token() token.Token // token.{VAR,FUNC,CONST,TYPE} | ||
74 | Package() *Package // the containing package | ||
75 | } | ||
76 | |||
77 | // A Type is a Member of a Package representing a package-level named type. | ||
78 | type Type struct { | ||
79 | object *types.TypeName | ||
80 | pkg *Package | ||
81 | } | ||
82 | |||
83 | // A NamedConst is a Member of a Package representing a package-level | ||
84 | // named constant. | ||
85 | // | ||
86 | // Pos() returns the position of the declaring ast.ValueSpec.Names[*] | ||
87 | // identifier. | ||
88 | // | ||
89 | // NB: a NamedConst is not a Value; it contains a constant Value, which | ||
90 | // it augments with the name and position of its 'const' declaration. | ||
91 | // | ||
92 | type NamedConst struct { | ||
93 | object *types.Const | ||
94 | Value *Const | ||
95 | pkg *Package | ||
96 | } | ||
97 | |||
98 | // A Value is an SSA value that can be referenced by an instruction. | ||
99 | type Value interface { | ||
100 | // Name returns the name of this value, and determines how | ||
101 | // this Value appears when used as an operand of an | ||
102 | // Instruction. | ||
103 | // | ||
104 | // This is the same as the source name for Parameters, | ||
105 | // Builtins, Functions, FreeVars, Globals. | ||
106 | // For constants, it is a representation of the constant's value | ||
107 | // and type. For all other Values this is the name of the | ||
108 | // virtual register defined by the instruction. | ||
109 | // | ||
110 | // The name of an SSA Value is not semantically significant, | ||
111 | // and may not even be unique within a function. | ||
112 | Name() string | ||
113 | |||
114 | // If this value is an Instruction, String returns its | ||
115 | // disassembled form; otherwise it returns unspecified | ||
116 | // human-readable information about the Value, such as its | ||
117 | // kind, name and type. | ||
118 | String() string | ||
119 | |||
120 | // Type returns the type of this value. Many instructions | ||
121 | // (e.g. IndexAddr) change their behaviour depending on the | ||
122 | // types of their operands. | ||
123 | Type() types.Type | ||
124 | |||
125 | // Parent returns the function to which this Value belongs. | ||
126 | // It returns nil for named Functions, Builtin, Const and Global. | ||
127 | Parent() *Function | ||
128 | |||
129 | // Referrers returns the list of instructions that have this | ||
130 | // value as one of their operands; it may contain duplicates | ||
131 | // if an instruction has a repeated operand. | ||
132 | // | ||
133 | // Referrers actually returns a pointer through which the | ||
134 | // caller may perform mutations to the object's state. | ||
135 | // | ||
136 | // Referrers is currently only defined if Parent()!=nil, | ||
137 | // i.e. for the function-local values FreeVar, Parameter, | ||
138 | // Functions (iff anonymous) and all value-defining instructions. | ||
139 | // It returns nil for named Functions, Builtin, Const and Global. | ||
140 | // | ||
141 | // Instruction.Operands contains the inverse of this relation. | ||
142 | Referrers() *[]Instruction | ||
143 | |||
144 | // Pos returns the location of the AST token most closely | ||
145 | // associated with the operation that gave rise to this value, | ||
146 | // or token.NoPos if it was not explicit in the source. | ||
147 | // | ||
148 | // For each ast.Node type, a particular token is designated as | ||
149 | // the closest location for the expression, e.g. the Lparen | ||
150 | // for an *ast.CallExpr. This permits a compact but | ||
151 | // approximate mapping from Values to source positions for use | ||
152 | // in diagnostic messages, for example. | ||
153 | // | ||
154 | // (Do not use this position to determine which Value | ||
155 | // corresponds to an ast.Expr; use Function.ValueForExpr | ||
156 | // instead. NB: it requires that the function was built with | ||
157 | // debug information.) | ||
158 | Pos() token.Pos | ||
159 | } | ||
160 | |||
161 | // An Instruction is an SSA instruction that computes a new Value or | ||
162 | // has some effect. | ||
163 | // | ||
164 | // An Instruction that defines a value (e.g. BinOp) also implements | ||
165 | // the Value interface; an Instruction that only has an effect (e.g. Store) | ||
166 | // does not. | ||
167 | // | ||
168 | type Instruction interface { | ||
169 | // String returns the disassembled form of this value. | ||
170 | // | ||
171 | // Examples of Instructions that are Values: | ||
172 | // "x + y" (BinOp) | ||
173 | // "len([])" (Call) | ||
174 | // Note that the name of the Value is not printed. | ||
175 | // | ||
176 | // Examples of Instructions that are not Values: | ||
177 | // "return x" (Return) | ||
178 | // "*y = x" (Store) | ||
179 | // | ||
180 | // (The separation Value.Name() from Value.String() is useful | ||
181 | // for some analyses which distinguish the operation from the | ||
182 | // value it defines, e.g., 'y = local int' is both an allocation | ||
183 | // of memory 'local int' and a definition of a pointer y.) | ||
184 | String() string | ||
185 | |||
186 | // Parent returns the function to which this instruction | ||
187 | // belongs. | ||
188 | Parent() *Function | ||
189 | |||
190 | // Block returns the basic block to which this instruction | ||
191 | // belongs. | ||
192 | Block() *BasicBlock | ||
193 | |||
194 | // setBlock sets the basic block to which this instruction belongs. | ||
195 | setBlock(*BasicBlock) | ||
196 | |||
197 | // Operands returns the operands of this instruction: the | ||
198 | // set of Values it references. | ||
199 | // | ||
200 | // Specifically, it appends their addresses to rands, a | ||
201 | // user-provided slice, and returns the resulting slice, | ||
202 | // permitting avoidance of memory allocation. | ||
203 | // | ||
204 | // The operands are appended in undefined order, but the order | ||
205 | // is consistent for a given Instruction; the addresses are | ||
206 | // always non-nil but may point to a nil Value. Clients may | ||
207 | // store through the pointers, e.g. to effect a value | ||
208 | // renaming. | ||
209 | // | ||
210 | // Value.Referrers is a subset of the inverse of this | ||
211 | // relation. (Referrers are not tracked for all types of | ||
212 | // Values.) | ||
213 | Operands(rands []*Value) []*Value | ||
214 | |||
215 | // Pos returns the location of the AST token most closely | ||
216 | // associated with the operation that gave rise to this | ||
217 | // instruction, or token.NoPos if it was not explicit in the | ||
218 | // source. | ||
219 | // | ||
220 | // For each ast.Node type, a particular token is designated as | ||
221 | // the closest location for the expression, e.g. the Go token | ||
222 | // for an *ast.GoStmt. This permits a compact but approximate | ||
223 | // mapping from Instructions to source positions for use in | ||
224 | // diagnostic messages, for example. | ||
225 | // | ||
226 | // (Do not use this position to determine which Instruction | ||
227 | // corresponds to an ast.Expr; see the notes for Value.Pos. | ||
228 | // This position may be used to determine which non-Value | ||
229 | // Instruction corresponds to some ast.Stmts, but not all: If | ||
230 | // and Jump instructions have no Pos(), for example.) | ||
231 | Pos() token.Pos | ||
232 | } | ||
233 | |||
234 | // A Node is a node in the SSA value graph. Every concrete type that | ||
235 | // implements Node is also either a Value, an Instruction, or both. | ||
236 | // | ||
237 | // Node contains the methods common to Value and Instruction, plus the | ||
238 | // Operands and Referrers methods generalized to return nil for | ||
239 | // non-Instructions and non-Values, respectively. | ||
240 | // | ||
241 | // Node is provided to simplify SSA graph algorithms. Clients should | ||
242 | // use the more specific and informative Value or Instruction | ||
243 | // interfaces where appropriate. | ||
244 | // | ||
245 | type Node interface { | ||
246 | // Common methods: | ||
247 | String() string | ||
248 | Pos() token.Pos | ||
249 | Parent() *Function | ||
250 | |||
251 | // Partial methods: | ||
252 | Operands(rands []*Value) []*Value // nil for non-Instructions | ||
253 | Referrers() *[]Instruction // nil for non-Values | ||
254 | } | ||
255 | |||
256 | // Function represents the parameters, results, and code of a function | ||
257 | // or method. | ||
258 | // | ||
259 | // If Blocks is nil, this indicates an external function for which no | ||
260 | // Go source code is available. In this case, FreeVars and Locals | ||
261 | // are nil too. Clients performing whole-program analysis must | ||
262 | // handle external functions specially. | ||
263 | // | ||
264 | // Blocks contains the function's control-flow graph (CFG). | ||
265 | // Blocks[0] is the function entry point; block order is not otherwise | ||
266 | // semantically significant, though it may affect the readability of | ||
267 | // the disassembly. | ||
268 | // To iterate over the blocks in dominance order, use DomPreorder(). | ||
269 | // | ||
270 | // Recover is an optional second entry point to which control resumes | ||
271 | // after a recovered panic. The Recover block may contain only a return | ||
272 | // statement, preceded by a load of the function's named return | ||
273 | // parameters, if any. | ||
274 | // | ||
275 | // A nested function (Parent()!=nil) that refers to one or more | ||
276 | // lexically enclosing local variables ("free variables") has FreeVars. | ||
277 | // Such functions cannot be called directly but require a | ||
278 | // value created by MakeClosure which, via its Bindings, supplies | ||
279 | // values for these parameters. | ||
280 | // | ||
281 | // If the function is a method (Signature.Recv() != nil) then the first | ||
282 | // element of Params is the receiver parameter. | ||
283 | // | ||
284 | // A Go package may declare many functions called "init". | ||
285 | // For each one, Object().Name() returns "init" but Name() returns | ||
286 | // "init#1", etc, in declaration order. | ||
287 | // | ||
288 | // Pos() returns the declaring ast.FuncLit.Type.Func or the position | ||
289 | // of the ast.FuncDecl.Name, if the function was explicit in the | ||
290 | // source. Synthetic wrappers, for which Synthetic != "", may share | ||
291 | // the same position as the function they wrap. | ||
292 | // Syntax.Pos() always returns the position of the declaring "func" token. | ||
293 | // | ||
294 | // Type() returns the function's Signature. | ||
295 | // | ||
296 | type Function struct { | ||
297 | name string | ||
298 | object types.Object // a declared *types.Func or one of its wrappers | ||
299 | method *types.Selection // info about provenance of synthetic methods | ||
300 | Signature *types.Signature | ||
301 | pos token.Pos | ||
302 | |||
303 | Synthetic string // provenance of synthetic function; "" for true source functions | ||
304 | syntax ast.Node // *ast.Func{Decl,Lit}; replaced with simple ast.Node after build, unless debug mode | ||
305 | parent *Function // enclosing function if anon; nil if global | ||
306 | Pkg *Package // enclosing package; nil for shared funcs (wrappers and error.Error) | ||
307 | Prog *Program // enclosing program | ||
308 | Params []*Parameter // function parameters; for methods, includes receiver | ||
309 | FreeVars []*FreeVar // free variables whose values must be supplied by closure | ||
310 | Locals []*Alloc // local variables of this function | ||
311 | Blocks []*BasicBlock // basic blocks of the function; nil => external | ||
312 | Recover *BasicBlock // optional; control transfers here after recovered panic | ||
313 | AnonFuncs []*Function // anonymous functions directly beneath this one | ||
314 | referrers []Instruction // referring instructions (iff Parent() != nil) | ||
315 | |||
316 | // The following fields are set transiently during building, | ||
317 | // then cleared. | ||
318 | currentBlock *BasicBlock // where to emit code | ||
319 | objects map[types.Object]Value // addresses of local variables | ||
320 | namedResults []*Alloc // tuple of named results | ||
321 | targets *targets // linked stack of branch targets | ||
322 | lblocks map[*ast.Object]*lblock // labelled blocks | ||
323 | } | ||
324 | |||
325 | // BasicBlock represents an SSA basic block. | ||
326 | // | ||
327 | // The final element of Instrs is always an explicit transfer of | ||
328 | // control (If, Jump, Return, or Panic). | ||
329 | // | ||
330 | // A block may contain no Instructions only if it is unreachable, | ||
331 | // i.e., Preds is nil. Empty blocks are typically pruned. | ||
332 | // | ||
333 | // BasicBlocks and their Preds/Succs relation form a (possibly cyclic) | ||
334 | // graph independent of the SSA Value graph: the control-flow graph or | ||
335 | // CFG. It is illegal for multiple edges to exist between the same | ||
336 | // pair of blocks. | ||
337 | // | ||
338 | // Each BasicBlock is also a node in the dominator tree of the CFG. | ||
339 | // The tree may be navigated using Idom()/Dominees() and queried using | ||
340 | // Dominates(). | ||
341 | // | ||
342 | // The order of Preds and Succs is significant (to Phi and If | ||
343 | // instructions, respectively). | ||
344 | // | ||
345 | type BasicBlock struct { | ||
346 | Index int // index of this block within Parent().Blocks | ||
347 | Comment string // optional label; no semantic significance | ||
348 | parent *Function // parent function | ||
349 | Instrs []Instruction // instructions in order | ||
350 | Preds, Succs []*BasicBlock // predecessors and successors | ||
351 | succs2 [2]*BasicBlock // initial space for Succs | ||
352 | dom domInfo // dominator tree info | ||
353 | gaps int // number of nil Instrs (transient) | ||
354 | rundefers int // number of rundefers (transient) | ||
355 | } | ||
356 | |||
357 | // Pure values ---------------------------------------- | ||
358 | |||
359 | // A FreeVar represents a free variable of the function to which it | ||
360 | // belongs. | ||
361 | // | ||
362 | // FreeVars are used to implement anonymous functions, whose free | ||
363 | // variables are lexically captured in a closure formed by | ||
364 | // MakeClosure. The value of such a free var is an Alloc or another | ||
365 | // FreeVar and is considered a potentially escaping heap address, with | ||
366 | // pointer type. | ||
367 | // | ||
368 | // FreeVars are also used to implement bound method closures. Such a | ||
369 | // free var represents the receiver value and may be of any type that | ||
370 | // has concrete methods. | ||
371 | // | ||
372 | // Pos() returns the position of the value that was captured, which | ||
373 | // belongs to an enclosing function. | ||
374 | // | ||
375 | type FreeVar struct { | ||
376 | name string | ||
377 | typ types.Type | ||
378 | pos token.Pos | ||
379 | parent *Function | ||
380 | referrers []Instruction | ||
381 | |||
382 | // Transiently needed during building. | ||
383 | outer Value // the Value captured from the enclosing context. | ||
384 | } | ||
385 | |||
386 | // A Parameter represents an input parameter of a function. | ||
387 | // | ||
388 | type Parameter struct { | ||
389 | name string | ||
390 | object types.Object // a *types.Var; nil for non-source locals | ||
391 | typ types.Type | ||
392 | pos token.Pos | ||
393 | parent *Function | ||
394 | referrers []Instruction | ||
395 | } | ||
396 | |||
397 | // A Const represents the value of a constant expression. | ||
398 | // | ||
399 | // The underlying type of a constant may be any boolean, numeric, or | ||
400 | // string type. In addition, a Const may represent the nil value of | ||
401 | // any reference type---interface, map, channel, pointer, slice, or | ||
402 | // function---but not "untyped nil". | ||
403 | // | ||
404 | // All source-level constant expressions are represented by a Const | ||
405 | // of the same type and value. | ||
406 | // | ||
407 | // Value holds the exact value of the constant, independent of its | ||
408 | // Type(), using the same representation as package go/constant uses for | ||
409 | // constants, or nil for a typed nil value. | ||
410 | // | ||
411 | // Pos() returns token.NoPos. | ||
412 | // | ||
413 | // Example printed form: | ||
414 | // 42:int | ||
415 | // "hello":untyped string | ||
416 | // 3+4i:MyComplex | ||
417 | // | ||
418 | type Const struct { | ||
419 | typ types.Type | ||
420 | Value constant.Value | ||
421 | } | ||
422 | |||
423 | // A Global is a named Value holding the address of a package-level | ||
424 | // variable. | ||
425 | // | ||
426 | // Pos() returns the position of the ast.ValueSpec.Names[*] | ||
427 | // identifier. | ||
428 | // | ||
429 | type Global struct { | ||
430 | name string | ||
431 | object types.Object // a *types.Var; may be nil for synthetics e.g. init$guard | ||
432 | typ types.Type | ||
433 | pos token.Pos | ||
434 | |||
435 | Pkg *Package | ||
436 | } | ||
437 | |||
438 | // A Builtin represents a specific use of a built-in function, e.g. len. | ||
439 | // | ||
440 | // Builtins are immutable values. Builtins do not have addresses. | ||
441 | // Builtins can only appear in CallCommon.Func. | ||
442 | // | ||
443 | // Name() indicates the function: one of the built-in functions from the | ||
444 | // Go spec (excluding "make" and "new") or one of these ssa-defined | ||
445 | // intrinsics: | ||
446 | // | ||
447 | // // wrapnilchk returns ptr if non-nil, panics otherwise. | ||
448 | // // (For use in indirection wrappers.) | ||
449 | // func ssa:wrapnilchk(ptr *T, recvType, methodName string) *T | ||
450 | // | ||
451 | // Object() returns a *types.Builtin for built-ins defined by the spec, | ||
452 | // nil for others. | ||
453 | // | ||
454 | // Type() returns a *types.Signature representing the effective | ||
455 | // signature of the built-in for this call. | ||
456 | // | ||
457 | type Builtin struct { | ||
458 | name string | ||
459 | sig *types.Signature | ||
460 | } | ||
461 | |||
462 | // Value-defining instructions ---------------------------------------- | ||
463 | |||
464 | // The Alloc instruction reserves space for a variable of the given type, | ||
465 | // zero-initializes it, and yields its address. | ||
466 | // | ||
467 | // Alloc values are always addresses, and have pointer types, so the | ||
468 | // type of the allocated variable is actually | ||
469 | // Type().Underlying().(*types.Pointer).Elem(). | ||
470 | // | ||
471 | // If Heap is false, Alloc allocates space in the function's | ||
472 | // activation record (frame); we refer to an Alloc(Heap=false) as a | ||
473 | // "local" alloc. Each local Alloc returns the same address each time | ||
474 | // it is executed within the same activation; the space is | ||
475 | // re-initialized to zero. | ||
476 | // | ||
477 | // If Heap is true, Alloc allocates space in the heap; we | ||
478 | // refer to an Alloc(Heap=true) as a "new" alloc. Each new Alloc | ||
479 | // returns a different address each time it is executed. | ||
480 | // | ||
481 | // When Alloc is applied to a channel, map or slice type, it returns | ||
482 | // the address of an uninitialized (nil) reference of that kind; store | ||
483 | // the result of MakeSlice, MakeMap or MakeChan in that location to | ||
484 | // instantiate these types. | ||
485 | // | ||
486 | // Pos() returns the ast.CompositeLit.Lbrace for a composite literal, | ||
487 | // or the ast.CallExpr.Rparen for a call to new() or for a call that | ||
488 | // allocates a varargs slice. | ||
489 | // | ||
490 | // Example printed form: | ||
491 | // t0 = local int | ||
492 | // t1 = new int | ||
493 | // | ||
494 | type Alloc struct { | ||
495 | register | ||
496 | Comment string | ||
497 | Heap bool | ||
498 | index int // dense numbering; for lifting | ||
499 | } | ||
500 | |||
501 | var _ Instruction = (*Sigma)(nil) | ||
502 | var _ Value = (*Sigma)(nil) | ||
503 | |||
504 | type Sigma struct { | ||
505 | register | ||
506 | X Value | ||
507 | Branch bool | ||
508 | } | ||
509 | |||
510 | func (p *Sigma) Value() Value { | ||
511 | v := p.X | ||
512 | for { | ||
513 | sigma, ok := v.(*Sigma) | ||
514 | if !ok { | ||
515 | break | ||
516 | } | ||
517 | v = sigma | ||
518 | } | ||
519 | return v | ||
520 | } | ||
521 | |||
522 | func (p *Sigma) String() string { | ||
523 | return fmt.Sprintf("σ [%s.%t]", relName(p.X, p), p.Branch) | ||
524 | } | ||
525 | |||
526 | // The Phi instruction represents an SSA φ-node, which combines values | ||
527 | // that differ across incoming control-flow edges and yields a new | ||
528 | // value. Within a block, all φ-nodes must appear before all non-φ | ||
529 | // nodes. | ||
530 | // | ||
531 | // Pos() returns the position of the && or || for short-circuit | ||
532 | // control-flow joins, or that of the *Alloc for φ-nodes inserted | ||
533 | // during SSA renaming. | ||
534 | // | ||
535 | // Example printed form: | ||
536 | // t2 = phi [0: t0, 1: t1] | ||
537 | // | ||
538 | type Phi struct { | ||
539 | register | ||
540 | Comment string // a hint as to its purpose | ||
541 | Edges []Value // Edges[i] is value for Block().Preds[i] | ||
542 | } | ||
543 | |||
544 | // The Call instruction represents a function or method call. | ||
545 | // | ||
546 | // The Call instruction yields the function result if there is exactly | ||
547 | // one. Otherwise it returns a tuple, the components of which are | ||
548 | // accessed via Extract. | ||
549 | // | ||
550 | // See CallCommon for generic function call documentation. | ||
551 | // | ||
552 | // Pos() returns the ast.CallExpr.Lparen, if explicit in the source. | ||
553 | // | ||
554 | // Example printed form: | ||
555 | // t2 = println(t0, t1) | ||
556 | // t4 = t3() | ||
557 | // t7 = invoke t5.Println(...t6) | ||
558 | // | ||
559 | type Call struct { | ||
560 | register | ||
561 | Call CallCommon | ||
562 | } | ||
563 | |||
564 | // The BinOp instruction yields the result of binary operation X Op Y. | ||
565 | // | ||
566 | // Pos() returns the ast.BinaryExpr.OpPos, if explicit in the source. | ||
567 | // | ||
568 | // Example printed form: | ||
569 | // t1 = t0 + 1:int | ||
570 | // | ||
571 | type BinOp struct { | ||
572 | register | ||
573 | // One of: | ||
574 | // ADD SUB MUL QUO REM + - * / % | ||
575 | // AND OR XOR SHL SHR AND_NOT & | ^ << >> &^ | ||
576 | // EQL NEQ LSS LEQ GTR GEQ == != < <= < >= | ||
577 | Op token.Token | ||
578 | X, Y Value | ||
579 | } | ||
580 | |||
581 | // The UnOp instruction yields the result of Op X. | ||
582 | // ARROW is channel receive. | ||
583 | // MUL is pointer indirection (load). | ||
584 | // XOR is bitwise complement. | ||
585 | // SUB is negation. | ||
586 | // NOT is logical negation. | ||
587 | // | ||
588 | // If CommaOk and Op=ARROW, the result is a 2-tuple of the value above | ||
589 | // and a boolean indicating the success of the receive. The | ||
590 | // components of the tuple are accessed using Extract. | ||
591 | // | ||
592 | // Pos() returns the ast.UnaryExpr.OpPos, if explicit in the source. | ||
593 | // For receive operations (ARROW) implicit in ranging over a channel, | ||
594 | // Pos() returns the ast.RangeStmt.For. | ||
595 | // For implicit memory loads (STAR), Pos() returns the position of the | ||
596 | // most closely associated source-level construct; the details are not | ||
597 | // specified. | ||
598 | // | ||
599 | // Example printed form: | ||
600 | // t0 = *x | ||
601 | // t2 = <-t1,ok | ||
602 | // | ||
603 | type UnOp struct { | ||
604 | register | ||
605 | Op token.Token // One of: NOT SUB ARROW MUL XOR ! - <- * ^ | ||
606 | X Value | ||
607 | CommaOk bool | ||
608 | } | ||
609 | |||
610 | // The ChangeType instruction applies to X a value-preserving type | ||
611 | // change to Type(). | ||
612 | // | ||
613 | // Type changes are permitted: | ||
614 | // - between a named type and its underlying type. | ||
615 | // - between two named types of the same underlying type. | ||
616 | // - between (possibly named) pointers to identical base types. | ||
617 | // - from a bidirectional channel to a read- or write-channel, | ||
618 | // optionally adding/removing a name. | ||
619 | // | ||
620 | // This operation cannot fail dynamically. | ||
621 | // | ||
622 | // Pos() returns the ast.CallExpr.Lparen, if the instruction arose | ||
623 | // from an explicit conversion in the source. | ||
624 | // | ||
625 | // Example printed form: | ||
626 | // t1 = changetype *int <- IntPtr (t0) | ||
627 | // | ||
628 | type ChangeType struct { | ||
629 | register | ||
630 | X Value | ||
631 | } | ||
632 | |||
633 | // The Convert instruction yields the conversion of value X to type | ||
634 | // Type(). One or both of those types is basic (but possibly named). | ||
635 | // | ||
636 | // A conversion may change the value and representation of its operand. | ||
637 | // Conversions are permitted: | ||
638 | // - between real numeric types. | ||
639 | // - between complex numeric types. | ||
640 | // - between string and []byte or []rune. | ||
641 | // - between pointers and unsafe.Pointer. | ||
642 | // - between unsafe.Pointer and uintptr. | ||
643 | // - from (Unicode) integer to (UTF-8) string. | ||
644 | // A conversion may imply a type name change also. | ||
645 | // | ||
646 | // This operation cannot fail dynamically. | ||
647 | // | ||
648 | // Conversions of untyped string/number/bool constants to a specific | ||
649 | // representation are eliminated during SSA construction. | ||
650 | // | ||
651 | // Pos() returns the ast.CallExpr.Lparen, if the instruction arose | ||
652 | // from an explicit conversion in the source. | ||
653 | // | ||
654 | // Example printed form: | ||
655 | // t1 = convert []byte <- string (t0) | ||
656 | // | ||
657 | type Convert struct { | ||
658 | register | ||
659 | X Value | ||
660 | } | ||
661 | |||
662 | // ChangeInterface constructs a value of one interface type from a | ||
663 | // value of another interface type known to be assignable to it. | ||
664 | // This operation cannot fail. | ||
665 | // | ||
666 | // Pos() returns the ast.CallExpr.Lparen if the instruction arose from | ||
667 | // an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the | ||
668 | // instruction arose from an explicit e.(T) operation; or token.NoPos | ||
669 | // otherwise. | ||
670 | // | ||
671 | // Example printed form: | ||
672 | // t1 = change interface interface{} <- I (t0) | ||
673 | // | ||
674 | type ChangeInterface struct { | ||
675 | register | ||
676 | X Value | ||
677 | } | ||
678 | |||
679 | // MakeInterface constructs an instance of an interface type from a | ||
680 | // value of a concrete type. | ||
681 | // | ||
682 | // Use Program.MethodSets.MethodSet(X.Type()) to find the method-set | ||
683 | // of X, and Program.MethodValue(m) to find the implementation of a method. | ||
684 | // | ||
685 | // To construct the zero value of an interface type T, use: | ||
686 | // NewConst(constant.MakeNil(), T, pos) | ||
687 | // | ||
688 | // Pos() returns the ast.CallExpr.Lparen, if the instruction arose | ||
689 | // from an explicit conversion in the source. | ||
690 | // | ||
691 | // Example printed form: | ||
692 | // t1 = make interface{} <- int (42:int) | ||
693 | // t2 = make Stringer <- t0 | ||
694 | // | ||
695 | type MakeInterface struct { | ||
696 | register | ||
697 | X Value | ||
698 | } | ||
699 | |||
700 | // The MakeClosure instruction yields a closure value whose code is | ||
701 | // Fn and whose free variables' values are supplied by Bindings. | ||
702 | // | ||
703 | // Type() returns a (possibly named) *types.Signature. | ||
704 | // | ||
705 | // Pos() returns the ast.FuncLit.Type.Func for a function literal | ||
706 | // closure or the ast.SelectorExpr.Sel for a bound method closure. | ||
707 | // | ||
708 | // Example printed form: | ||
709 | // t0 = make closure anon@1.2 [x y z] | ||
710 | // t1 = make closure bound$(main.I).add [i] | ||
711 | // | ||
712 | type MakeClosure struct { | ||
713 | register | ||
714 | Fn Value // always a *Function | ||
715 | Bindings []Value // values for each free variable in Fn.FreeVars | ||
716 | } | ||
717 | |||
718 | // The MakeMap instruction creates a new hash-table-based map object | ||
719 | // and yields a value of kind map. | ||
720 | // | ||
721 | // Type() returns a (possibly named) *types.Map. | ||
722 | // | ||
723 | // Pos() returns the ast.CallExpr.Lparen, if created by make(map), or | ||
724 | // the ast.CompositeLit.Lbrack if created by a literal. | ||
725 | // | ||
726 | // Example printed form: | ||
727 | // t1 = make map[string]int t0 | ||
728 | // t1 = make StringIntMap t0 | ||
729 | // | ||
730 | type MakeMap struct { | ||
731 | register | ||
732 | Reserve Value // initial space reservation; nil => default | ||
733 | } | ||
734 | |||
735 | // The MakeChan instruction creates a new channel object and yields a | ||
736 | // value of kind chan. | ||
737 | // | ||
738 | // Type() returns a (possibly named) *types.Chan. | ||
739 | // | ||
740 | // Pos() returns the ast.CallExpr.Lparen for the make(chan) that | ||
741 | // created it. | ||
742 | // | ||
743 | // Example printed form: | ||
744 | // t0 = make chan int 0 | ||
745 | // t0 = make IntChan 0 | ||
746 | // | ||
747 | type MakeChan struct { | ||
748 | register | ||
749 | Size Value // int; size of buffer; zero => synchronous. | ||
750 | } | ||
751 | |||
752 | // The MakeSlice instruction yields a slice of length Len backed by a | ||
753 | // newly allocated array of length Cap. | ||
754 | // | ||
755 | // Both Len and Cap must be non-nil Values of integer type. | ||
756 | // | ||
757 | // (Alloc(types.Array) followed by Slice will not suffice because | ||
758 | // Alloc can only create arrays of constant length.) | ||
759 | // | ||
760 | // Type() returns a (possibly named) *types.Slice. | ||
761 | // | ||
762 | // Pos() returns the ast.CallExpr.Lparen for the make([]T) that | ||
763 | // created it. | ||
764 | // | ||
765 | // Example printed form: | ||
766 | // t1 = make []string 1:int t0 | ||
767 | // t1 = make StringSlice 1:int t0 | ||
768 | // | ||
769 | type MakeSlice struct { | ||
770 | register | ||
771 | Len Value | ||
772 | Cap Value | ||
773 | } | ||
774 | |||
775 | // The Slice instruction yields a slice of an existing string, slice | ||
776 | // or *array X between optional integer bounds Low and High. | ||
777 | // | ||
778 | // Dynamically, this instruction panics if X evaluates to a nil *array | ||
779 | // pointer. | ||
780 | // | ||
781 | // Type() returns string if the type of X was string, otherwise a | ||
782 | // *types.Slice with the same element type as X. | ||
783 | // | ||
784 | // Pos() returns the ast.SliceExpr.Lbrack if created by a x[:] slice | ||
785 | // operation, the ast.CompositeLit.Lbrace if created by a literal, or | ||
786 | // NoPos if not explicit in the source (e.g. a variadic argument slice). | ||
787 | // | ||
788 | // Example printed form: | ||
789 | // t1 = slice t0[1:] | ||
790 | // | ||
791 | type Slice struct { | ||
792 | register | ||
793 | X Value // slice, string, or *array | ||
794 | Low, High, Max Value // each may be nil | ||
795 | } | ||
796 | |||
797 | // The FieldAddr instruction yields the address of Field of *struct X. | ||
798 | // | ||
799 | // The field is identified by its index within the field list of the | ||
800 | // struct type of X. | ||
801 | // | ||
802 | // Dynamically, this instruction panics if X evaluates to a nil | ||
803 | // pointer. | ||
804 | // | ||
805 | // Type() returns a (possibly named) *types.Pointer. | ||
806 | // | ||
807 | // Pos() returns the position of the ast.SelectorExpr.Sel for the | ||
808 | // field, if explicit in the source. | ||
809 | // | ||
810 | // Example printed form: | ||
811 | // t1 = &t0.name [#1] | ||
812 | // | ||
813 | type FieldAddr struct { | ||
814 | register | ||
815 | X Value // *struct | ||
816 | Field int // field is X.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Struct).Field(Field) | ||
817 | } | ||
818 | |||
819 | // The Field instruction yields the Field of struct X. | ||
820 | // | ||
821 | // The field is identified by its index within the field list of the | ||
822 | // struct type of X; by using numeric indices we avoid ambiguity of | ||
823 | // package-local identifiers and permit compact representations. | ||
824 | // | ||
825 | // Pos() returns the position of the ast.SelectorExpr.Sel for the | ||
826 | // field, if explicit in the source. | ||
827 | // | ||
828 | // Example printed form: | ||
829 | // t1 = t0.name [#1] | ||
830 | // | ||
831 | type Field struct { | ||
832 | register | ||
833 | X Value // struct | ||
834 | Field int // index into X.Type().(*types.Struct).Fields | ||
835 | } | ||
836 | |||
837 | // The IndexAddr instruction yields the address of the element at | ||
838 | // index Index of collection X. Index is an integer expression. | ||
839 | // | ||
840 | // The elements of maps and strings are not addressable; use Lookup or | ||
841 | // MapUpdate instead. | ||
842 | // | ||
843 | // Dynamically, this instruction panics if X evaluates to a nil *array | ||
844 | // pointer. | ||
845 | // | ||
846 | // Type() returns a (possibly named) *types.Pointer. | ||
847 | // | ||
848 | // Pos() returns the ast.IndexExpr.Lbrack for the index operation, if | ||
849 | // explicit in the source. | ||
850 | // | ||
851 | // Example printed form: | ||
852 | // t2 = &t0[t1] | ||
853 | // | ||
854 | type IndexAddr struct { | ||
855 | register | ||
856 | X Value // slice or *array, | ||
857 | Index Value // numeric index | ||
858 | } | ||
859 | |||
860 | // The Index instruction yields element Index of array X. | ||
861 | // | ||
862 | // Pos() returns the ast.IndexExpr.Lbrack for the index operation, if | ||
863 | // explicit in the source. | ||
864 | // | ||
865 | // Example printed form: | ||
866 | // t2 = t0[t1] | ||
867 | // | ||
868 | type Index struct { | ||
869 | register | ||
870 | X Value // array | ||
871 | Index Value // integer index | ||
872 | } | ||
873 | |||
874 | // The Lookup instruction yields element Index of collection X, a map | ||
875 | // or string. Index is an integer expression if X is a string or the | ||
876 | // appropriate key type if X is a map. | ||
877 | // | ||
878 | // If CommaOk, the result is a 2-tuple of the value above and a | ||
879 | // boolean indicating the result of a map membership test for the key. | ||
880 | // The components of the tuple are accessed using Extract. | ||
881 | // | ||
882 | // Pos() returns the ast.IndexExpr.Lbrack, if explicit in the source. | ||
883 | // | ||
884 | // Example printed form: | ||
885 | // t2 = t0[t1] | ||
886 | // t5 = t3[t4],ok | ||
887 | // | ||
888 | type Lookup struct { | ||
889 | register | ||
890 | X Value // string or map | ||
891 | Index Value // numeric or key-typed index | ||
892 | CommaOk bool // return a value,ok pair | ||
893 | } | ||
894 | |||
895 | // SelectState is a helper for Select. | ||
896 | // It represents one goal state and its corresponding communication. | ||
897 | // | ||
898 | type SelectState struct { | ||
899 | Dir types.ChanDir // direction of case (SendOnly or RecvOnly) | ||
900 | Chan Value // channel to use (for send or receive) | ||
901 | Send Value // value to send (for send) | ||
902 | Pos token.Pos // position of token.ARROW | ||
903 | DebugNode ast.Node // ast.SendStmt or ast.UnaryExpr(<-) [debug mode] | ||
904 | } | ||
905 | |||
906 | // The Select instruction tests whether (or blocks until) one | ||
907 | // of the specified sent or received states is entered. | ||
908 | // | ||
909 | // Let n be the number of States for which Dir==RECV and T_i (0<=i<n) | ||
910 | // be the element type of each such state's Chan. | ||
911 | // Select returns an n+2-tuple | ||
912 | // (index int, recvOk bool, r_0 T_0, ... r_n-1 T_n-1) | ||
913 | // The tuple's components, described below, must be accessed via the | ||
914 | // Extract instruction. | ||
915 | // | ||
916 | // If Blocking, select waits until exactly one state holds, i.e. a | ||
917 | // channel becomes ready for the designated operation of sending or | ||
918 | // receiving; select chooses one among the ready states | ||
919 | // pseudorandomly, performs the send or receive operation, and sets | ||
920 | // 'index' to the index of the chosen channel. | ||
921 | // | ||
922 | // If !Blocking, select doesn't block if no states hold; instead it | ||
923 | // returns immediately with index equal to -1. | ||
924 | // | ||
925 | // If the chosen channel was used for a receive, the r_i component is | ||
926 | // set to the received value, where i is the index of that state among | ||
927 | // all n receive states; otherwise r_i has the zero value of type T_i. | ||
928 | // Note that the receive index i is not the same as the state | ||
929 | // index index. | ||
930 | // | ||
931 | // The second component of the triple, recvOk, is a boolean whose value | ||
932 | // is true iff the selected operation was a receive and the receive | ||
933 | // successfully yielded a value. | ||
934 | // | ||
935 | // Pos() returns the ast.SelectStmt.Select. | ||
936 | // | ||
937 | // Example printed form: | ||
938 | // t3 = select nonblocking [<-t0, t1<-t2] | ||
939 | // t4 = select blocking [] | ||
940 | // | ||
941 | type Select struct { | ||
942 | register | ||
943 | States []*SelectState | ||
944 | Blocking bool | ||
945 | } | ||
946 | |||
947 | // The Range instruction yields an iterator over the domain and range | ||
948 | // of X, which must be a string or map. | ||
949 | // | ||
950 | // Elements are accessed via Next. | ||
951 | // | ||
952 | // Type() returns an opaque and degenerate "rangeIter" type. | ||
953 | // | ||
954 | // Pos() returns the ast.RangeStmt.For. | ||
955 | // | ||
956 | // Example printed form: | ||
957 | // t0 = range "hello":string | ||
958 | // | ||
959 | type Range struct { | ||
960 | register | ||
961 | X Value // string or map | ||
962 | } | ||
963 | |||
964 | // The Next instruction reads and advances the (map or string) | ||
965 | // iterator Iter and returns a 3-tuple value (ok, k, v). If the | ||
966 | // iterator is not exhausted, ok is true and k and v are the next | ||
967 | // elements of the domain and range, respectively. Otherwise ok is | ||
968 | // false and k and v are undefined. | ||
969 | // | ||
970 | // Components of the tuple are accessed using Extract. | ||
971 | // | ||
972 | // The IsString field distinguishes iterators over strings from those | ||
973 | // over maps, as the Type() alone is insufficient: consider | ||
974 | // map[int]rune. | ||
975 | // | ||
976 | // Type() returns a *types.Tuple for the triple (ok, k, v). | ||
977 | // The types of k and/or v may be types.Invalid. | ||
978 | // | ||
979 | // Example printed form: | ||
980 | // t1 = next t0 | ||
981 | // | ||
982 | type Next struct { | ||
983 | register | ||
984 | Iter Value | ||
985 | IsString bool // true => string iterator; false => map iterator. | ||
986 | } | ||
987 | |||
988 | // The TypeAssert instruction tests whether interface value X has type | ||
989 | // AssertedType. | ||
990 | // | ||
991 | // If !CommaOk, on success it returns v, the result of the conversion | ||
992 | // (defined below); on failure it panics. | ||
993 | // | ||
994 | // If CommaOk: on success it returns a pair (v, true) where v is the | ||
995 | // result of the conversion; on failure it returns (z, false) where z | ||
996 | // is AssertedType's zero value. The components of the pair must be | ||
997 | // accessed using the Extract instruction. | ||
998 | // | ||
999 | // If AssertedType is a concrete type, TypeAssert checks whether the | ||
1000 | // dynamic type in interface X is equal to it, and if so, the result | ||
1001 | // of the conversion is a copy of the value in the interface. | ||
1002 | // | ||
1003 | // If AssertedType is an interface, TypeAssert checks whether the | ||
1004 | // dynamic type of the interface is assignable to it, and if so, the | ||
1005 | // result of the conversion is a copy of the interface value X. | ||
1006 | // If AssertedType is a superinterface of X.Type(), the operation will | ||
1007 | // fail iff the operand is nil. (Contrast with ChangeInterface, which | ||
1008 | // performs no nil-check.) | ||
1009 | // | ||
1010 | // Type() reflects the actual type of the result, possibly a | ||
1011 | // 2-types.Tuple; AssertedType is the asserted type. | ||
1012 | // | ||
1013 | // Pos() returns the ast.CallExpr.Lparen if the instruction arose from | ||
1014 | // an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the | ||
1015 | // instruction arose from an explicit e.(T) operation; or the | ||
1016 | // ast.CaseClause.Case if the instruction arose from a case of a | ||
1017 | // type-switch statement. | ||
1018 | // | ||
1019 | // Example printed form: | ||
1020 | // t1 = typeassert t0.(int) | ||
1021 | // t3 = typeassert,ok t2.(T) | ||
1022 | // | ||
1023 | type TypeAssert struct { | ||
1024 | register | ||
1025 | X Value | ||
1026 | AssertedType types.Type | ||
1027 | CommaOk bool | ||
1028 | } | ||
1029 | |||
1030 | // The Extract instruction yields component Index of Tuple. | ||
1031 | // | ||
1032 | // This is used to access the results of instructions with multiple | ||
1033 | // return values, such as Call, TypeAssert, Next, UnOp(ARROW) and | ||
1034 | // IndexExpr(Map). | ||
1035 | // | ||
1036 | // Example printed form: | ||
1037 | // t1 = extract t0 #1 | ||
1038 | // | ||
1039 | type Extract struct { | ||
1040 | register | ||
1041 | Tuple Value | ||
1042 | Index int | ||
1043 | } | ||
1044 | |||
1045 | // Instructions executed for effect. They do not yield a value. -------------------- | ||
1046 | |||
1047 | // The Jump instruction transfers control to the sole successor of its | ||
1048 | // owning block. | ||
1049 | // | ||
1050 | // A Jump must be the last instruction of its containing BasicBlock. | ||
1051 | // | ||
1052 | // Pos() returns NoPos. | ||
1053 | // | ||
1054 | // Example printed form: | ||
1055 | // jump done | ||
1056 | // | ||
1057 | type Jump struct { | ||
1058 | anInstruction | ||
1059 | } | ||
1060 | |||
1061 | // The If instruction transfers control to one of the two successors | ||
1062 | // of its owning block, depending on the boolean Cond: the first if | ||
1063 | // true, the second if false. | ||
1064 | // | ||
1065 | // An If instruction must be the last instruction of its containing | ||
1066 | // BasicBlock. | ||
1067 | // | ||
1068 | // Pos() returns NoPos. | ||
1069 | // | ||
1070 | // Example printed form: | ||
1071 | // if t0 goto done else body | ||
1072 | // | ||
1073 | type If struct { | ||
1074 | anInstruction | ||
1075 | Cond Value | ||
1076 | } | ||
1077 | |||
1078 | // The Return instruction returns values and control back to the calling | ||
1079 | // function. | ||
1080 | // | ||
1081 | // len(Results) is always equal to the number of results in the | ||
1082 | // function's signature. | ||
1083 | // | ||
1084 | // If len(Results) > 1, Return returns a tuple value with the specified | ||
1085 | // components which the caller must access using Extract instructions. | ||
1086 | // | ||
1087 | // There is no instruction to return a ready-made tuple like those | ||
1088 | // returned by a "value,ok"-mode TypeAssert, Lookup or UnOp(ARROW) or | ||
1089 | // a tail-call to a function with multiple result parameters. | ||
1090 | // | ||
1091 | // Return must be the last instruction of its containing BasicBlock. | ||
1092 | // Such a block has no successors. | ||
1093 | // | ||
1094 | // Pos() returns the ast.ReturnStmt.Return, if explicit in the source. | ||
1095 | // | ||
1096 | // Example printed form: | ||
1097 | // return | ||
1098 | // return nil:I, 2:int | ||
1099 | // | ||
1100 | type Return struct { | ||
1101 | anInstruction | ||
1102 | Results []Value | ||
1103 | pos token.Pos | ||
1104 | } | ||
1105 | |||
1106 | // The RunDefers instruction pops and invokes the entire stack of | ||
1107 | // procedure calls pushed by Defer instructions in this function. | ||
1108 | // | ||
1109 | // It is legal to encounter multiple 'rundefers' instructions in a | ||
1110 | // single control-flow path through a function; this is useful in | ||
1111 | // the combined init() function, for example. | ||
1112 | // | ||
1113 | // Pos() returns NoPos. | ||
1114 | // | ||
1115 | // Example printed form: | ||
1116 | // rundefers | ||
1117 | // | ||
1118 | type RunDefers struct { | ||
1119 | anInstruction | ||
1120 | } | ||
1121 | |||
1122 | // The Panic instruction initiates a panic with value X. | ||
1123 | // | ||
1124 | // A Panic instruction must be the last instruction of its containing | ||
1125 | // BasicBlock, which must have no successors. | ||
1126 | // | ||
1127 | // NB: 'go panic(x)' and 'defer panic(x)' do not use this instruction; | ||
1128 | // they are treated as calls to a built-in function. | ||
1129 | // | ||
1130 | // Pos() returns the ast.CallExpr.Lparen if this panic was explicit | ||
1131 | // in the source. | ||
1132 | // | ||
1133 | // Example printed form: | ||
1134 | // panic t0 | ||
1135 | // | ||
1136 | type Panic struct { | ||
1137 | anInstruction | ||
1138 | X Value // an interface{} | ||
1139 | pos token.Pos | ||
1140 | } | ||
1141 | |||
1142 | // The Go instruction creates a new goroutine and calls the specified | ||
1143 | // function within it. | ||
1144 | // | ||
1145 | // See CallCommon for generic function call documentation. | ||
1146 | // | ||
1147 | // Pos() returns the ast.GoStmt.Go. | ||
1148 | // | ||
1149 | // Example printed form: | ||
1150 | // go println(t0, t1) | ||
1151 | // go t3() | ||
1152 | // go invoke t5.Println(...t6) | ||
1153 | // | ||
1154 | type Go struct { | ||
1155 | anInstruction | ||
1156 | Call CallCommon | ||
1157 | pos token.Pos | ||
1158 | } | ||
1159 | |||
1160 | // The Defer instruction pushes the specified call onto a stack of | ||
1161 | // functions to be called by a RunDefers instruction or by a panic. | ||
1162 | // | ||
1163 | // See CallCommon for generic function call documentation. | ||
1164 | // | ||
1165 | // Pos() returns the ast.DeferStmt.Defer. | ||
1166 | // | ||
1167 | // Example printed form: | ||
1168 | // defer println(t0, t1) | ||
1169 | // defer t3() | ||
1170 | // defer invoke t5.Println(...t6) | ||
1171 | // | ||
1172 | type Defer struct { | ||
1173 | anInstruction | ||
1174 | Call CallCommon | ||
1175 | pos token.Pos | ||
1176 | } | ||
1177 | |||
1178 | // The Send instruction sends X on channel Chan. | ||
1179 | // | ||
1180 | // Pos() returns the ast.SendStmt.Arrow, if explicit in the source. | ||
1181 | // | ||
1182 | // Example printed form: | ||
1183 | // send t0 <- t1 | ||
1184 | // | ||
1185 | type Send struct { | ||
1186 | anInstruction | ||
1187 | Chan, X Value | ||
1188 | pos token.Pos | ||
1189 | } | ||
1190 | |||
1191 | // The Store instruction stores Val at address Addr. | ||
1192 | // Stores can be of arbitrary types. | ||
1193 | // | ||
1194 | // Pos() returns the position of the source-level construct most closely | ||
1195 | // associated with the memory store operation. | ||
1196 | // Since implicit memory stores are numerous and varied and depend upon | ||
1197 | // implementation choices, the details are not specified. | ||
1198 | // | ||
1199 | // Example printed form: | ||
1200 | // *x = y | ||
1201 | // | ||
1202 | type Store struct { | ||
1203 | anInstruction | ||
1204 | Addr Value | ||
1205 | Val Value | ||
1206 | pos token.Pos | ||
1207 | } | ||
1208 | |||
1209 | // The BlankStore instruction is emitted for assignments to the blank | ||
1210 | // identifier. | ||
1211 | // | ||
1212 | // BlankStore is a pseudo-instruction: it has no dynamic effect. | ||
1213 | // | ||
1214 | // Pos() returns NoPos. | ||
1215 | // | ||
1216 | // Example printed form: | ||
1217 | // _ = t0 | ||
1218 | // | ||
1219 | type BlankStore struct { | ||
1220 | anInstruction | ||
1221 | Val Value | ||
1222 | } | ||
1223 | |||
1224 | // The MapUpdate instruction updates the association of Map[Key] to | ||
1225 | // Value. | ||
1226 | // | ||
1227 | // Pos() returns the ast.KeyValueExpr.Colon or ast.IndexExpr.Lbrack, | ||
1228 | // if explicit in the source. | ||
1229 | // | ||
1230 | // Example printed form: | ||
1231 | // t0[t1] = t2 | ||
1232 | // | ||
1233 | type MapUpdate struct { | ||
1234 | anInstruction | ||
1235 | Map Value | ||
1236 | Key Value | ||
1237 | Value Value | ||
1238 | pos token.Pos | ||
1239 | } | ||
1240 | |||
1241 | // A DebugRef instruction maps a source-level expression Expr to the | ||
1242 | // SSA value X that represents the value (!IsAddr) or address (IsAddr) | ||
1243 | // of that expression. | ||
1244 | // | ||
1245 | // DebugRef is a pseudo-instruction: it has no dynamic effect. | ||
1246 | // | ||
1247 | // Pos() returns Expr.Pos(), the start position of the source-level | ||
1248 | // expression. This is not the same as the "designated" token as | ||
1249 | // documented at Value.Pos(). e.g. CallExpr.Pos() does not return the | ||
1250 | // position of the ("designated") Lparen token. | ||
1251 | // | ||
1252 | // If Expr is an *ast.Ident denoting a var or func, Object() returns | ||
1253 | // the object; though this information can be obtained from the type | ||
1254 | // checker, including it here greatly facilitates debugging. | ||
1255 | // For non-Ident expressions, Object() returns nil. | ||
1256 | // | ||
1257 | // DebugRefs are generated only for functions built with debugging | ||
1258 | // enabled; see Package.SetDebugMode() and the GlobalDebug builder | ||
1259 | // mode flag. | ||
1260 | // | ||
1261 | // DebugRefs are not emitted for ast.Idents referring to constants or | ||
1262 | // predeclared identifiers, since they are trivial and numerous. | ||
1263 | // Nor are they emitted for ast.ParenExprs. | ||
1264 | // | ||
1265 | // (By representing these as instructions, rather than out-of-band, | ||
1266 | // consistency is maintained during transformation passes by the | ||
1267 | // ordinary SSA renaming machinery.) | ||
1268 | // | ||
1269 | // Example printed form: | ||
1270 | // ; *ast.CallExpr @ 102:9 is t5 | ||
1271 | // ; var x float64 @ 109:72 is x | ||
1272 | // ; address of *ast.CompositeLit @ 216:10 is t0 | ||
1273 | // | ||
1274 | type DebugRef struct { | ||
1275 | anInstruction | ||
1276 | Expr ast.Expr // the referring expression (never *ast.ParenExpr) | ||
1277 | object types.Object // the identity of the source var/func | ||
1278 | IsAddr bool // Expr is addressable and X is the address it denotes | ||
1279 | X Value // the value or address of Expr | ||
1280 | } | ||
1281 | |||
1282 | // Embeddable mix-ins and helpers for common parts of other structs. ----------- | ||
1283 | |||
1284 | // register is a mix-in embedded by all SSA values that are also | ||
1285 | // instructions, i.e. virtual registers, and provides a uniform | ||
1286 | // implementation of most of the Value interface: Value.Name() is a | ||
1287 | // numbered register (e.g. "t0"); the other methods are field accessors. | ||
1288 | // | ||
1289 | // Temporary names are automatically assigned to each register on | ||
1290 | // completion of building a function in SSA form. | ||
1291 | // | ||
1292 | // Clients must not assume that the 'id' value (and the Name() derived | ||
1293 | // from it) is unique within a function. As always in this API, | ||
1294 | // semantics are determined only by identity; names exist only to | ||
1295 | // facilitate debugging. | ||
1296 | // | ||
1297 | type register struct { | ||
1298 | anInstruction | ||
1299 | num int // "name" of virtual register, e.g. "t0". Not guaranteed unique. | ||
1300 | typ types.Type // type of virtual register | ||
1301 | pos token.Pos // position of source expression, or NoPos | ||
1302 | referrers []Instruction | ||
1303 | } | ||
1304 | |||
1305 | // anInstruction is a mix-in embedded by all Instructions. | ||
1306 | // It provides the implementations of the Block and setBlock methods. | ||
1307 | type anInstruction struct { | ||
1308 | block *BasicBlock // the basic block of this instruction | ||
1309 | } | ||
1310 | |||
1311 | // CallCommon is contained by Go, Defer and Call to hold the | ||
1312 | // common parts of a function or method call. | ||
1313 | // | ||
1314 | // Each CallCommon exists in one of two modes, function call and | ||
1315 | // interface method invocation, or "call" and "invoke" for short. | ||
1316 | // | ||
1317 | // 1. "call" mode: when Method is nil (!IsInvoke), a CallCommon | ||
1318 | // represents an ordinary function call of the value in Value, | ||
1319 | // which may be a *Builtin, a *Function or any other value of kind | ||
1320 | // 'func'. | ||
1321 | // | ||
1322 | // Value may be one of: | ||
1323 | // (a) a *Function, indicating a statically dispatched call | ||
1324 | // to a package-level function, an anonymous function, or | ||
1325 | // a method of a named type. | ||
1326 | // (b) a *MakeClosure, indicating an immediately applied | ||
1327 | // function literal with free variables. | ||
1328 | // (c) a *Builtin, indicating a statically dispatched call | ||
1329 | // to a built-in function. | ||
1330 | // (d) any other value, indicating a dynamically dispatched | ||
1331 | // function call. | ||
1332 | // StaticCallee returns the identity of the callee in cases | ||
1333 | // (a) and (b), nil otherwise. | ||
1334 | // | ||
1335 | // Args contains the arguments to the call. If Value is a method, | ||
1336 | // Args[0] contains the receiver parameter. | ||
1337 | // | ||
1338 | // Example printed form: | ||
1339 | // t2 = println(t0, t1) | ||
1340 | // go t3() | ||
1341 | // defer t5(...t6) | ||
1342 | // | ||
1343 | // 2. "invoke" mode: when Method is non-nil (IsInvoke), a CallCommon | ||
1344 | // represents a dynamically dispatched call to an interface method. | ||
1345 | // In this mode, Value is the interface value and Method is the | ||
1346 | // interface's abstract method. Note: an abstract method may be | ||
1347 | // shared by multiple interfaces due to embedding; Value.Type() | ||
1348 | // provides the specific interface used for this call. | ||
1349 | // | ||
1350 | // Value is implicitly supplied to the concrete method implementation | ||
1351 | // as the receiver parameter; in other words, Args[0] holds not the | ||
1352 | // receiver but the first true argument. | ||
1353 | // | ||
1354 | // Example printed form: | ||
1355 | // t1 = invoke t0.String() | ||
1356 | // go invoke t3.Run(t2) | ||
1357 | // defer invoke t4.Handle(...t5) | ||
1358 | // | ||
1359 | // For all calls to variadic functions (Signature().Variadic()), | ||
1360 | // the last element of Args is a slice. | ||
1361 | // | ||
1362 | type CallCommon struct { | ||
1363 | Value Value // receiver (invoke mode) or func value (call mode) | ||
1364 | Method *types.Func // abstract method (invoke mode) | ||
1365 | Args []Value // actual parameters (in static method call, includes receiver) | ||
1366 | pos token.Pos // position of CallExpr.Lparen, iff explicit in source | ||
1367 | } | ||
1368 | |||
1369 | // IsInvoke returns true if this call has "invoke" (not "call") mode. | ||
1370 | func (c *CallCommon) IsInvoke() bool { | ||
1371 | return c.Method != nil | ||
1372 | } | ||
1373 | |||
1374 | func (c *CallCommon) Pos() token.Pos { return c.pos } | ||
1375 | |||
1376 | // Signature returns the signature of the called function. | ||
1377 | // | ||
1378 | // For an "invoke"-mode call, the signature of the interface method is | ||
1379 | // returned. | ||
1380 | // | ||
1381 | // In either "call" or "invoke" mode, if the callee is a method, its | ||
1382 | // receiver is represented by sig.Recv, not sig.Params().At(0). | ||
1383 | // | ||
1384 | func (c *CallCommon) Signature() *types.Signature { | ||
1385 | if c.Method != nil { | ||
1386 | return c.Method.Type().(*types.Signature) | ||
1387 | } | ||
1388 | return c.Value.Type().Underlying().(*types.Signature) | ||
1389 | } | ||
1390 | |||
1391 | // StaticCallee returns the callee if this is a trivially static | ||
1392 | // "call"-mode call to a function. | ||
1393 | func (c *CallCommon) StaticCallee() *Function { | ||
1394 | switch fn := c.Value.(type) { | ||
1395 | case *Function: | ||
1396 | return fn | ||
1397 | case *MakeClosure: | ||
1398 | return fn.Fn.(*Function) | ||
1399 | } | ||
1400 | return nil | ||
1401 | } | ||
1402 | |||
1403 | // Description returns a description of the mode of this call suitable | ||
1404 | // for a user interface, e.g., "static method call". | ||
1405 | func (c *CallCommon) Description() string { | ||
1406 | switch fn := c.Value.(type) { | ||
1407 | case *Builtin: | ||
1408 | return "built-in function call" | ||
1409 | case *MakeClosure: | ||
1410 | return "static function closure call" | ||
1411 | case *Function: | ||
1412 | if fn.Signature.Recv() != nil { | ||
1413 | return "static method call" | ||
1414 | } | ||
1415 | return "static function call" | ||
1416 | } | ||
1417 | if c.IsInvoke() { | ||
1418 | return "dynamic method call" // ("invoke" mode) | ||
1419 | } | ||
1420 | return "dynamic function call" | ||
1421 | } | ||
1422 | |||
1423 | // The CallInstruction interface, implemented by *Go, *Defer and *Call, | ||
1424 | // exposes the common parts of function-calling instructions, | ||
1425 | // yet provides a way back to the Value defined by *Call alone. | ||
1426 | // | ||
1427 | type CallInstruction interface { | ||
1428 | Instruction | ||
1429 | Common() *CallCommon // returns the common parts of the call | ||
1430 | Value() *Call // returns the result value of the call (*Call) or nil (*Go, *Defer) | ||
1431 | } | ||
1432 | |||
1433 | func (s *Call) Common() *CallCommon { return &s.Call } | ||
1434 | func (s *Defer) Common() *CallCommon { return &s.Call } | ||
1435 | func (s *Go) Common() *CallCommon { return &s.Call } | ||
1436 | |||
1437 | func (s *Call) Value() *Call { return s } | ||
1438 | func (s *Defer) Value() *Call { return nil } | ||
1439 | func (s *Go) Value() *Call { return nil } | ||
1440 | |||
1441 | func (v *Builtin) Type() types.Type { return v.sig } | ||
1442 | func (v *Builtin) Name() string { return v.name } | ||
1443 | func (*Builtin) Referrers() *[]Instruction { return nil } | ||
1444 | func (v *Builtin) Pos() token.Pos { return token.NoPos } | ||
1445 | func (v *Builtin) Object() types.Object { return types.Universe.Lookup(v.name) } | ||
1446 | func (v *Builtin) Parent() *Function { return nil } | ||
1447 | |||
1448 | func (v *FreeVar) Type() types.Type { return v.typ } | ||
1449 | func (v *FreeVar) Name() string { return v.name } | ||
1450 | func (v *FreeVar) Referrers() *[]Instruction { return &v.referrers } | ||
1451 | func (v *FreeVar) Pos() token.Pos { return v.pos } | ||
1452 | func (v *FreeVar) Parent() *Function { return v.parent } | ||
1453 | |||
1454 | func (v *Global) Type() types.Type { return v.typ } | ||
1455 | func (v *Global) Name() string { return v.name } | ||
1456 | func (v *Global) Parent() *Function { return nil } | ||
1457 | func (v *Global) Pos() token.Pos { return v.pos } | ||
1458 | func (v *Global) Referrers() *[]Instruction { return nil } | ||
1459 | func (v *Global) Token() token.Token { return token.VAR } | ||
1460 | func (v *Global) Object() types.Object { return v.object } | ||
1461 | func (v *Global) String() string { return v.RelString(nil) } | ||
1462 | func (v *Global) Package() *Package { return v.Pkg } | ||
1463 | func (v *Global) RelString(from *types.Package) string { return relString(v, from) } | ||
1464 | |||
1465 | func (v *Function) Name() string { return v.name } | ||
1466 | func (v *Function) Type() types.Type { return v.Signature } | ||
1467 | func (v *Function) Pos() token.Pos { return v.pos } | ||
1468 | func (v *Function) Token() token.Token { return token.FUNC } | ||
1469 | func (v *Function) Object() types.Object { return v.object } | ||
1470 | func (v *Function) String() string { return v.RelString(nil) } | ||
1471 | func (v *Function) Package() *Package { return v.Pkg } | ||
1472 | func (v *Function) Parent() *Function { return v.parent } | ||
1473 | func (v *Function) Referrers() *[]Instruction { | ||
1474 | if v.parent != nil { | ||
1475 | return &v.referrers | ||
1476 | } | ||
1477 | return nil | ||
1478 | } | ||
1479 | |||
1480 | func (v *Parameter) Type() types.Type { return v.typ } | ||
1481 | func (v *Parameter) Name() string { return v.name } | ||
1482 | func (v *Parameter) Object() types.Object { return v.object } | ||
1483 | func (v *Parameter) Referrers() *[]Instruction { return &v.referrers } | ||
1484 | func (v *Parameter) Pos() token.Pos { return v.pos } | ||
1485 | func (v *Parameter) Parent() *Function { return v.parent } | ||
1486 | |||
1487 | func (v *Alloc) Type() types.Type { return v.typ } | ||
1488 | func (v *Alloc) Referrers() *[]Instruction { return &v.referrers } | ||
1489 | func (v *Alloc) Pos() token.Pos { return v.pos } | ||
1490 | |||
1491 | func (v *register) Type() types.Type { return v.typ } | ||
1492 | func (v *register) setType(typ types.Type) { v.typ = typ } | ||
1493 | func (v *register) Name() string { return fmt.Sprintf("t%d", v.num) } | ||
1494 | func (v *register) setNum(num int) { v.num = num } | ||
1495 | func (v *register) Referrers() *[]Instruction { return &v.referrers } | ||
1496 | func (v *register) Pos() token.Pos { return v.pos } | ||
1497 | func (v *register) setPos(pos token.Pos) { v.pos = pos } | ||
1498 | |||
1499 | func (v *anInstruction) Parent() *Function { return v.block.parent } | ||
1500 | func (v *anInstruction) Block() *BasicBlock { return v.block } | ||
1501 | func (v *anInstruction) setBlock(block *BasicBlock) { v.block = block } | ||
1502 | func (v *anInstruction) Referrers() *[]Instruction { return nil } | ||
1503 | |||
1504 | func (t *Type) Name() string { return t.object.Name() } | ||
1505 | func (t *Type) Pos() token.Pos { return t.object.Pos() } | ||
1506 | func (t *Type) Type() types.Type { return t.object.Type() } | ||
1507 | func (t *Type) Token() token.Token { return token.TYPE } | ||
1508 | func (t *Type) Object() types.Object { return t.object } | ||
1509 | func (t *Type) String() string { return t.RelString(nil) } | ||
1510 | func (t *Type) Package() *Package { return t.pkg } | ||
1511 | func (t *Type) RelString(from *types.Package) string { return relString(t, from) } | ||
1512 | |||
1513 | func (c *NamedConst) Name() string { return c.object.Name() } | ||
1514 | func (c *NamedConst) Pos() token.Pos { return c.object.Pos() } | ||
1515 | func (c *NamedConst) String() string { return c.RelString(nil) } | ||
1516 | func (c *NamedConst) Type() types.Type { return c.object.Type() } | ||
1517 | func (c *NamedConst) Token() token.Token { return token.CONST } | ||
1518 | func (c *NamedConst) Object() types.Object { return c.object } | ||
1519 | func (c *NamedConst) Package() *Package { return c.pkg } | ||
1520 | func (c *NamedConst) RelString(from *types.Package) string { return relString(c, from) } | ||
1521 | |||
1522 | // Func returns the package-level function of the specified name, | ||
1523 | // or nil if not found. | ||
1524 | // | ||
1525 | func (p *Package) Func(name string) (f *Function) { | ||
1526 | f, _ = p.Members[name].(*Function) | ||
1527 | return | ||
1528 | } | ||
1529 | |||
1530 | // Var returns the package-level variable of the specified name, | ||
1531 | // or nil if not found. | ||
1532 | // | ||
1533 | func (p *Package) Var(name string) (g *Global) { | ||
1534 | g, _ = p.Members[name].(*Global) | ||
1535 | return | ||
1536 | } | ||
1537 | |||
1538 | // Const returns the package-level constant of the specified name, | ||
1539 | // or nil if not found. | ||
1540 | // | ||
1541 | func (p *Package) Const(name string) (c *NamedConst) { | ||
1542 | c, _ = p.Members[name].(*NamedConst) | ||
1543 | return | ||
1544 | } | ||
1545 | |||
1546 | // Type returns the package-level type of the specified name, | ||
1547 | // or nil if not found. | ||
1548 | // | ||
1549 | func (p *Package) Type(name string) (t *Type) { | ||
1550 | t, _ = p.Members[name].(*Type) | ||
1551 | return | ||
1552 | } | ||
1553 | |||
1554 | func (v *Call) Pos() token.Pos { return v.Call.pos } | ||
1555 | func (s *Defer) Pos() token.Pos { return s.pos } | ||
1556 | func (s *Go) Pos() token.Pos { return s.pos } | ||
1557 | func (s *MapUpdate) Pos() token.Pos { return s.pos } | ||
1558 | func (s *Panic) Pos() token.Pos { return s.pos } | ||
1559 | func (s *Return) Pos() token.Pos { return s.pos } | ||
1560 | func (s *Send) Pos() token.Pos { return s.pos } | ||
1561 | func (s *Store) Pos() token.Pos { return s.pos } | ||
1562 | func (s *BlankStore) Pos() token.Pos { return token.NoPos } | ||
1563 | func (s *If) Pos() token.Pos { return token.NoPos } | ||
1564 | func (s *Jump) Pos() token.Pos { return token.NoPos } | ||
1565 | func (s *RunDefers) Pos() token.Pos { return token.NoPos } | ||
1566 | func (s *DebugRef) Pos() token.Pos { return s.Expr.Pos() } | ||
1567 | |||
1568 | // Operands. | ||
1569 | |||
1570 | func (v *Alloc) Operands(rands []*Value) []*Value { | ||
1571 | return rands | ||
1572 | } | ||
1573 | |||
1574 | func (v *BinOp) Operands(rands []*Value) []*Value { | ||
1575 | return append(rands, &v.X, &v.Y) | ||
1576 | } | ||
1577 | |||
1578 | func (c *CallCommon) Operands(rands []*Value) []*Value { | ||
1579 | rands = append(rands, &c.Value) | ||
1580 | for i := range c.Args { | ||
1581 | rands = append(rands, &c.Args[i]) | ||
1582 | } | ||
1583 | return rands | ||
1584 | } | ||
1585 | |||
1586 | func (s *Go) Operands(rands []*Value) []*Value { | ||
1587 | return s.Call.Operands(rands) | ||
1588 | } | ||
1589 | |||
1590 | func (s *Call) Operands(rands []*Value) []*Value { | ||
1591 | return s.Call.Operands(rands) | ||
1592 | } | ||
1593 | |||
1594 | func (s *Defer) Operands(rands []*Value) []*Value { | ||
1595 | return s.Call.Operands(rands) | ||
1596 | } | ||
1597 | |||
1598 | func (v *ChangeInterface) Operands(rands []*Value) []*Value { | ||
1599 | return append(rands, &v.X) | ||
1600 | } | ||
1601 | |||
1602 | func (v *ChangeType) Operands(rands []*Value) []*Value { | ||
1603 | return append(rands, &v.X) | ||
1604 | } | ||
1605 | |||
1606 | func (v *Convert) Operands(rands []*Value) []*Value { | ||
1607 | return append(rands, &v.X) | ||
1608 | } | ||
1609 | |||
1610 | func (s *DebugRef) Operands(rands []*Value) []*Value { | ||
1611 | return append(rands, &s.X) | ||
1612 | } | ||
1613 | |||
1614 | func (v *Extract) Operands(rands []*Value) []*Value { | ||
1615 | return append(rands, &v.Tuple) | ||
1616 | } | ||
1617 | |||
1618 | func (v *Field) Operands(rands []*Value) []*Value { | ||
1619 | return append(rands, &v.X) | ||
1620 | } | ||
1621 | |||
1622 | func (v *FieldAddr) Operands(rands []*Value) []*Value { | ||
1623 | return append(rands, &v.X) | ||
1624 | } | ||
1625 | |||
1626 | func (s *If) Operands(rands []*Value) []*Value { | ||
1627 | return append(rands, &s.Cond) | ||
1628 | } | ||
1629 | |||
1630 | func (v *Index) Operands(rands []*Value) []*Value { | ||
1631 | return append(rands, &v.X, &v.Index) | ||
1632 | } | ||
1633 | |||
1634 | func (v *IndexAddr) Operands(rands []*Value) []*Value { | ||
1635 | return append(rands, &v.X, &v.Index) | ||
1636 | } | ||
1637 | |||
1638 | func (*Jump) Operands(rands []*Value) []*Value { | ||
1639 | return rands | ||
1640 | } | ||
1641 | |||
1642 | func (v *Lookup) Operands(rands []*Value) []*Value { | ||
1643 | return append(rands, &v.X, &v.Index) | ||
1644 | } | ||
1645 | |||
1646 | func (v *MakeChan) Operands(rands []*Value) []*Value { | ||
1647 | return append(rands, &v.Size) | ||
1648 | } | ||
1649 | |||
1650 | func (v *MakeClosure) Operands(rands []*Value) []*Value { | ||
1651 | rands = append(rands, &v.Fn) | ||
1652 | for i := range v.Bindings { | ||
1653 | rands = append(rands, &v.Bindings[i]) | ||
1654 | } | ||
1655 | return rands | ||
1656 | } | ||
1657 | |||
1658 | func (v *MakeInterface) Operands(rands []*Value) []*Value { | ||
1659 | return append(rands, &v.X) | ||
1660 | } | ||
1661 | |||
1662 | func (v *MakeMap) Operands(rands []*Value) []*Value { | ||
1663 | return append(rands, &v.Reserve) | ||
1664 | } | ||
1665 | |||
1666 | func (v *MakeSlice) Operands(rands []*Value) []*Value { | ||
1667 | return append(rands, &v.Len, &v.Cap) | ||
1668 | } | ||
1669 | |||
1670 | func (v *MapUpdate) Operands(rands []*Value) []*Value { | ||
1671 | return append(rands, &v.Map, &v.Key, &v.Value) | ||
1672 | } | ||
1673 | |||
1674 | func (v *Next) Operands(rands []*Value) []*Value { | ||
1675 | return append(rands, &v.Iter) | ||
1676 | } | ||
1677 | |||
1678 | func (s *Panic) Operands(rands []*Value) []*Value { | ||
1679 | return append(rands, &s.X) | ||
1680 | } | ||
1681 | |||
1682 | func (v *Sigma) Operands(rands []*Value) []*Value { | ||
1683 | return append(rands, &v.X) | ||
1684 | } | ||
1685 | |||
1686 | func (v *Phi) Operands(rands []*Value) []*Value { | ||
1687 | for i := range v.Edges { | ||
1688 | rands = append(rands, &v.Edges[i]) | ||
1689 | } | ||
1690 | return rands | ||
1691 | } | ||
1692 | |||
1693 | func (v *Range) Operands(rands []*Value) []*Value { | ||
1694 | return append(rands, &v.X) | ||
1695 | } | ||
1696 | |||
1697 | func (s *Return) Operands(rands []*Value) []*Value { | ||
1698 | for i := range s.Results { | ||
1699 | rands = append(rands, &s.Results[i]) | ||
1700 | } | ||
1701 | return rands | ||
1702 | } | ||
1703 | |||
1704 | func (*RunDefers) Operands(rands []*Value) []*Value { | ||
1705 | return rands | ||
1706 | } | ||
1707 | |||
1708 | func (v *Select) Operands(rands []*Value) []*Value { | ||
1709 | for i := range v.States { | ||
1710 | rands = append(rands, &v.States[i].Chan, &v.States[i].Send) | ||
1711 | } | ||
1712 | return rands | ||
1713 | } | ||
1714 | |||
1715 | func (s *Send) Operands(rands []*Value) []*Value { | ||
1716 | return append(rands, &s.Chan, &s.X) | ||
1717 | } | ||
1718 | |||
1719 | func (v *Slice) Operands(rands []*Value) []*Value { | ||
1720 | return append(rands, &v.X, &v.Low, &v.High, &v.Max) | ||
1721 | } | ||
1722 | |||
1723 | func (s *Store) Operands(rands []*Value) []*Value { | ||
1724 | return append(rands, &s.Addr, &s.Val) | ||
1725 | } | ||
1726 | |||
1727 | func (s *BlankStore) Operands(rands []*Value) []*Value { | ||
1728 | return append(rands, &s.Val) | ||
1729 | } | ||
1730 | |||
1731 | func (v *TypeAssert) Operands(rands []*Value) []*Value { | ||
1732 | return append(rands, &v.X) | ||
1733 | } | ||
1734 | |||
1735 | func (v *UnOp) Operands(rands []*Value) []*Value { | ||
1736 | return append(rands, &v.X) | ||
1737 | } | ||
1738 | |||
1739 | // Non-Instruction Values: | ||
1740 | func (v *Builtin) Operands(rands []*Value) []*Value { return rands } | ||
1741 | func (v *FreeVar) Operands(rands []*Value) []*Value { return rands } | ||
1742 | func (v *Const) Operands(rands []*Value) []*Value { return rands } | ||
1743 | func (v *Function) Operands(rands []*Value) []*Value { return rands } | ||
1744 | func (v *Global) Operands(rands []*Value) []*Value { return rands } | ||
1745 | func (v *Parameter) Operands(rands []*Value) []*Value { return rands } | ||