cmd/5l etc: restore comments lost during C -> Go conversion
It appears that c2go dropped comments inside struct { ... } and enum { ... }.
Restore them.
Identified missing comments by checking for comments present
in the C code but not the Go code, made a list, and then reapplied
with some mechanical help.
Missing comment finder: http://play.golang.org/p/g6qNUAo1Y0
Change-Id: I323ab45c7ef9d51e28eab3b699eb14bee1eef66b
Reviewed-on: https://go-review.googlesource.com/6899
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/src/cmd/internal/gc/esc.go b/src/cmd/internal/gc/esc.go
index 169dec6..8b5430b 100644
--- a/src/cmd/internal/gc/esc.go
+++ b/src/cmd/internal/gc/esc.go
@@ -206,15 +206,27 @@
)
type EscState struct {
- theSink Node
+ // Fake node that all
+ // - return values and output variables
+ // - parameters on imported functions not marked 'safe'
+ // - assignments to global variables
+ // flow to.
+ theSink Node
+
+ // If an analyzed function is recorded to return
+ // pieces obtained via indirection from a parameter,
+ // and later there is a call f(x) to that function,
+ // we create a link funcParam <- x to record that fact.
+ // The funcParam node is handled specially in escflood.
funcParam Node
- dsts *NodeList
- loopdepth int
- pdepth int
- dstcount int
- edgecount int
- noesc *NodeList
- recursive bool
+
+ dsts *NodeList // all dst nodes
+ loopdepth int // for detecting nested loop scopes
+ pdepth int // for debug printing in recursions.
+ dstcount int // diagnostic
+ edgecount int // diagnostic
+ noesc *NodeList // list of possible non-escaping nodes, for printing
+ recursive bool // recursive function or group of mutually recursive functions.
}
var tags [16]*string
@@ -530,7 +542,10 @@
// However, without this special case b will escape, because we assign to OIND/ODOTPTR.
case OAS,
OASOP:
- if (n.Left.Op == OIND || n.Left.Op == ODOTPTR) && n.Left.Left.Op == ONAME && (n.Right.Op == OSLICE || n.Right.Op == OSLICE3 || n.Right.Op == OSLICESTR) && (n.Right.Left.Op == OIND || n.Right.Left.Op == ODOTPTR) && n.Right.Left.Left.Op == ONAME && n.Left.Left == n.Right.Left.Left { // dst is ONAME dereference // src is slice operation // slice is applied to ONAME dereference // dst and src reference the same base ONAME
+ if (n.Left.Op == OIND || n.Left.Op == ODOTPTR) && n.Left.Left.Op == ONAME && // dst is ONAME dereference
+ (n.Right.Op == OSLICE || n.Right.Op == OSLICE3 || n.Right.Op == OSLICESTR) && // src is slice operation
+ (n.Right.Left.Op == OIND || n.Right.Left.Op == ODOTPTR) && n.Right.Left.Left.Op == ONAME && // slice is applied to ONAME dereference
+ n.Left.Left == n.Right.Left.Left { // dst and src reference the same base ONAME
// Here we also assume that the statement will not contain calls,
// that is, that order will move any calls to init.
@@ -578,13 +593,12 @@
if e.loopdepth == 1 { // top level
break
}
+ // arguments leak out of scope
+ // TODO: leak to a dummy node instead
fallthrough
- // go f(x) - f and x escape
- // arguments leak out of scope
- // TODO: leak to a dummy node instead
- // fallthrough
case OPROC:
+ // go f(x) - f and x escape
escassign(e, &e.theSink, n.Left.Left)
escassign(e, &e.theSink, n.Left.Right) // ODDDARG for call
@@ -899,14 +913,15 @@
OSLICEARR,
OSLICE3ARR,
OSLICESTR:
+ // Conversions, field access, slice all preserve the input value.
escassign(e, dst, src.Left)
- // Append returns first argument.
case OAPPEND:
+ // Append returns first argument.
escassign(e, dst, src.List.N)
- // Index of array preserves input value.
case OINDEX:
+ // Index of array preserves input value.
if Isfixedarray(src.Left.Type) {
escassign(e, dst, src.Left)
}
diff --git a/src/cmd/internal/gc/go.go b/src/cmd/internal/gc/go.go
index 95c3c7c..f05ba27 100644
--- a/src/cmd/internal/gc/go.go
+++ b/src/cmd/internal/gc/go.go
@@ -32,6 +32,8 @@
)
const (
+ // These values are known by runtime.
+ // The MEMx and NOEQx values must run in parallel. See algtype.
AMEM = iota
AMEM0
AMEM8
@@ -58,9 +60,9 @@
)
const (
- Mpscale = 29
- Mpprec = 16
- Mpnorm = Mpprec - 1
+ Mpscale = 29 // safely smaller than bits in a long
+ Mpprec = 16 // Mpscale*Mpprec is max number of bits
+ Mpnorm = Mpprec - 1 // significant words in a normalized float
Mpbase = 1 << Mpscale
Mpsign = Mpbase >> 1
Mpmask = Mpbase - 1
@@ -86,42 +88,44 @@
type Val struct {
Ctype int16
U struct {
- Reg int16
- Bval int16
- Xval *Mpint
- Fval *Mpflt
- Cval *Mpcplx
- Sval string
+ Reg int16 // OREGISTER
+ Bval int16 // bool value CTBOOL
+ Xval *Mpint // int CTINT, rune CTRUNE
+ Fval *Mpflt // float CTFLT
+ Cval *Mpcplx // float CTCPLX
+ Sval string // string CTSTR
}
}
type Pkg struct {
- Name string
- Path string
+ Name string // package name
+ Path string // string literal used in import statement
Pathsym *Sym
- Prefix string
- Imported uint8
- Exported int8
- Direct int8
- Safe bool
+ Prefix string // escaped path for use in symbol table
+ Imported uint8 // export data of this package was parsed
+ Exported int8 // import line written in export data
+ Direct int8 // imported directly
+ Safe bool // whether the package is marked as safe
Syms map[string]*Sym
}
type Sym struct {
- Lexical uint16
- Flags uint8
- Sym uint8
- Link *Sym
- Uniqgen uint32
- Importdef *Pkg
- Linkname string
+ Lexical uint16
+ Flags uint8
+ Sym uint8 // huffman encoding in object file
+ Link *Sym
+ Uniqgen uint32
+ Importdef *Pkg // where imported definition was found
+ Linkname string // link name
+
+ // saved and restored by dcopy
Pkg *Pkg
- Name string
- Def *Node
- Label *Label
- Block int32
- Lastlineno int32
- Origpkg *Pkg
+ Name string // variable name
+ Def *Node // definition: ONAME OTYPE OPACK or OLITERAL
+ Label *Label // corresponding label (ephemeral)
+ Block int32 // blocknumber to catch redeclaration
+ Lastlineno int32 // last declaration for diagnostic
+ Origpkg *Pkg // original package for . import
Lsym *obj.LSym
}
@@ -130,63 +134,83 @@
Nointerface bool
Noalg uint8
Chan uint8
- Trecur uint8
+ Trecur uint8 // to detect loops
Printed uint8
- Embedded uint8
+ Embedded uint8 // TFIELD embedded type
Siggen uint8
- Funarg uint8
+ Funarg uint8 // on TSTRUCT and TFIELD
Copyany uint8
- Local uint8
+ Local uint8 // created in this file
Deferwidth uint8
- Broke uint8
- Isddd uint8
+ Broke uint8 // broken type definition.
+ Isddd uint8 // TFIELD is ... argument
Align uint8
- Haspointers uint8
- Nod *Node
- Orig *Type
- Lineno int
- Thistuple int
- Outtuple int
- Intuple int
- Outnamed uint8
- Method *Type
- Xmethod *Type
- Sym *Sym
- Vargen int32
- Nname *Node
- Argwid int64
- Type *Type
- Width int64
- Down *Type
- Outer *Type
- Note *string
- Bound int64
- Bucket *Type
- Hmap *Type
- Hiter *Type
- Map *Type
- Maplineno int32
- Embedlineno int32
- Copyto *NodeList
- Lastfn *Node
+ Haspointers uint8 // 0 unknown, 1 no, 2 yes
+
+ Nod *Node // canonical OTYPE node
+ Orig *Type // original type (type literal or predefined type)
+ Lineno int
+
+ // TFUNC
+ Thistuple int
+ Outtuple int
+ Intuple int
+ Outnamed uint8
+
+ Method *Type
+ Xmethod *Type
+
+ Sym *Sym
+ Vargen int32 // unique name for OTYPE/ONAME
+
+ Nname *Node
+ Argwid int64
+
+ // most nodes
+ Type *Type // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx
+ Width int64 // offset in TFIELD, width in all others
+
+ // TFIELD
+ Down *Type // next struct field, also key type in TMAP
+ Outer *Type // outer struct
+ Note *string // literal string annotation
+
+ // TARRAY
+ Bound int64 // negative is dynamic array
+
+ // TMAP
+ Bucket *Type // internal type representing a hash bucket
+ Hmap *Type // internal type representing a Hmap (map header object)
+ Hiter *Type // internal type representing hash iterator state
+ Map *Type // link from the above 3 internal types back to the map type.
+
+ Maplineno int32 // first use of TFORW as map key
+ Embedlineno int32 // first use of TFORW as embedded type
+
+ // for TFORW, where to copy the eventual value to
+ Copyto *NodeList
+
+ Lastfn *Node // for usefield
}
type Label struct {
- Used uint8
- Sym *Sym
- Def *Node
- Use *NodeList
- Link *Label
- Gotopc *obj.Prog
- Labelpc *obj.Prog
- Breakpc *obj.Prog
- Continpc *obj.Prog
+ Used uint8
+ Sym *Sym
+ Def *Node
+ Use *NodeList
+ Link *Label
+
+ // for use during gen
+ Gotopc *obj.Prog // pointer to unresolved gotos
+ Labelpc *obj.Prog // pointer to code
+ Breakpc *obj.Prog // pointer to code
+ Continpc *obj.Prog // pointer to code
}
type InitEntry struct {
- Xoffset int64
- Key *Node
- Expr *Node
+ Xoffset int64 // struct, array only
+ Key *Node // map only
+ Expr *Node // bytes of run-time computed expressions
}
type InitPlan struct {
@@ -205,14 +229,14 @@
EscNever
EscBits = 3
EscMask = (1 << EscBits) - 1
- EscContentEscapes = 1 << EscBits
+ EscContentEscapes = 1 << EscBits // value obtained by indirect of parameter escapes to some returned result
EscReturnBits = EscBits + 1
)
const (
- SymExport = 1 << 0
+ SymExport = 1 << 0 // to be exported
SymPackage = 1 << 1
- SymExported = 1 << 2
+ SymExported = 1 << 2 // already written out by export
SymUniq = 1 << 3
SymSiggen = 1 << 4
SymAsm = 1 << 5
@@ -231,6 +255,7 @@
const (
Txxx = iota
+
TINT8
TUINT8
TINT16
@@ -242,13 +267,18 @@
TINT
TUINT
TUINTPTR
+
TCOMPLEX64
TCOMPLEX128
+
TFLOAT32
TFLOAT64
+
TBOOL
+
TPTR32
TPTR64
+
TFUNC
TARRAY
T_old_DARRAY
@@ -261,17 +291,23 @@
TANY
TSTRING
TUNSAFEPTR
+
+ // pseudo-types for literals
TIDEAL
TNIL
TBLANK
+
+ // pseudo-type for frame layout
TFUNCARGS
TCHANARGS
TINTERMETH
+
NTYPE
)
const (
CTxxx = iota
+
CTINT
CTRUNE
CTFLT
@@ -282,6 +318,8 @@
)
const (
+ /* types of channel */
+ /* must match ../../pkg/nreflect/type.go:/Chandir */
Cxxx = 0
Crecv = 1 << 0
Csend = 1 << 1
@@ -290,29 +328,31 @@
// declaration context
const (
- Pxxx = iota
- PEXTERN
- PAUTO
- PPARAM
- PPARAMOUT
- PPARAMREF
- PFUNC
- PDISCARD
- PHEAP = 1 << 7
+ Pxxx = iota
+ PEXTERN // global variable
+ PAUTO // local variables
+ PPARAM // input arguments
+ PPARAMOUT // output results
+ PPARAMREF // closure variable reference
+ PFUNC // global function
+
+ PDISCARD // discard during parse of duplicate import
+
+ PHEAP = 1 << 7 // an extra bit to identify an escaped variable
)
const (
- Etop = 1 << 1
- Erv = 1 << 2
+ Etop = 1 << 1 // evaluated at statement level
+ Erv = 1 << 2 // evaluated in value context
Etype = 1 << 3
- Ecall = 1 << 4
- Efnstruct = 1 << 5
- Eiota = 1 << 6
- Easgn = 1 << 7
- Eindir = 1 << 8
- Eaddr = 1 << 9
- Eproc = 1 << 10
- Ecomplit = 1 << 11
+ Ecall = 1 << 4 // call-only expressions are ok
+ Efnstruct = 1 << 5 // multivalue function returns are ok
+ Eiota = 1 << 6 // iota is ok
+ Easgn = 1 << 7 // assigning to expression
+ Eindir = 1 << 8 // indirecting through expression
+ Eaddr = 1 << 9 // taking address of expression
+ Eproc = 1 << 10 // inside a go statement
+ Ecomplit = 1 << 11 // type in composite literal
)
const (
@@ -364,8 +404,8 @@
eofnl int
last int
peekc int
- peekc1 int
- cp string
+ peekc1 int // second peekc for ...
+ cp string // used for content when bin==nil
importsafe bool
}
@@ -383,14 +423,18 @@
* smagic and umagic
*/
type Magic struct {
- W int
- S int
- Bad int
- Sd int64
- Sm int64
- Ud uint64
- Um uint64
- Ua int
+ W int // input for both - width
+ S int // output for both - shift
+ Bad int // output for both - unexpected failure
+
+ // magic multiplier for signed literal divisors
+ Sd int64 // input - literal divisor
+ Sm int64 // output - multiplier
+
+ // magic multiplier for unsigned literal divisors
+ Ud uint64 // input - literal divisor
+ Um uint64 // output - multiplier
+ Ua int // output - adder
}
/*
@@ -670,67 +714,94 @@
var zerosize int64
type Flow struct {
- Prog *obj.Prog
- P1 *Flow
- P2 *Flow
+ Prog *obj.Prog // actual instruction
+ P1 *Flow // predecessors of this instruction: p1,
+ P2 *Flow // and then p2 linked though p2link.
P2link *Flow
- S1 *Flow
+ S1 *Flow // successors of this instruction (at most two: s1 and s2).
S2 *Flow
- Link *Flow
- Active int32
- Id int32
- Rpo int32
- Loop uint16
- Refset uint8
- Data interface{}
+ Link *Flow // next instruction in function code
+
+ Active int32 // usable by client
+
+ Id int32 // sequence number in flow graph
+ Rpo int32 // reverse post ordering
+ Loop uint16 // x5 for every loop
+ Refset uint8 // diagnostic generated
+
+ Data interface{} // for use by client
}
type Graph struct {
Start *Flow
Num int
- Rpo []*Flow
+
+ // After calling flowrpo, rpo lists the flow nodes in reverse postorder,
+ // and each non-dead Flow node f has g->rpo[f->rpo] == f.
+ Rpo []*Flow
}
/*
* interface to back end
*/
type ProgInfo struct {
- Flags uint32
- Reguse uint64
- Regset uint64
- Regindex uint64
+ Flags uint32 // the bits below
+ Reguse uint64 // registers implicitly used by this instruction
+ Regset uint64 // registers implicitly set by this instruction
+ Regindex uint64 // registers used by addressing mode
}
const (
- Pseudo = 1 << 1
- OK = 1 << 2
- SizeB = 1 << 3
- SizeW = 1 << 4
- SizeL = 1 << 5
- SizeQ = 1 << 6
- SizeF = 1 << 7
- SizeD = 1 << 8
- LeftAddr = 1 << 9
- LeftRead = 1 << 10
- LeftWrite = 1 << 11
+ // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
+ Pseudo = 1 << 1
+
+ // There's nothing to say about the instruction,
+ // but it's still okay to see.
+ OK = 1 << 2
+
+ // Size of right-side write, or right-side read if no write.
+ SizeB = 1 << 3
+ SizeW = 1 << 4
+ SizeL = 1 << 5
+ SizeQ = 1 << 6
+ SizeF = 1 << 7
+ SizeD = 1 << 8
+
+ // Left side (Prog.from): address taken, read, write.
+ LeftAddr = 1 << 9
+ LeftRead = 1 << 10
+ LeftWrite = 1 << 11
+
+ // Register in middle (Prog.reg); only ever read. (arm, ppc64)
RegRead = 1 << 12
CanRegRead = 1 << 13
+
+ // Right side (Prog.to): address taken, read, write.
RightAddr = 1 << 14
RightRead = 1 << 15
RightWrite = 1 << 16
- Move = 1 << 17
- Conv = 1 << 18
- Cjmp = 1 << 19
- Break = 1 << 20
- Call = 1 << 21
- Jump = 1 << 22
- Skip = 1 << 23
- SetCarry = 1 << 24
- UseCarry = 1 << 25
- KillCarry = 1 << 26
- ShiftCX = 1 << 27
- ImulAXDX = 1 << 28
- PostInc = 1 << 29
+
+ // Instruction kinds
+ Move = 1 << 17 // straight move
+ Conv = 1 << 18 // size conversion
+ Cjmp = 1 << 19 // conditional jump
+ Break = 1 << 20 // breaks control flow (no fallthrough)
+ Call = 1 << 21 // function call
+ Jump = 1 << 22 // jump
+ Skip = 1 << 23 // data instruction
+
+ // Set, use, or kill of carry bit.
+ // Kill means we never look at the carry bit after this kind of instruction.
+ SetCarry = 1 << 24
+ UseCarry = 1 << 25
+ KillCarry = 1 << 26
+
+ // Special cases for register use. (amd64, 386)
+ ShiftCX = 1 << 27 // possible shift by CX
+ ImulAXDX = 1 << 28 // possible multiply into DX:AX
+
+ // Instruction updates whichever of from/to is type D_OREG. (ppc64)
+ PostInc = 1 << 29
)
type Arch struct {
diff --git a/src/cmd/internal/gc/gsubr.go b/src/cmd/internal/gc/gsubr.go
index 48a24a6..cee5099 100644
--- a/src/cmd/internal/gc/gsubr.go
+++ b/src/cmd/internal/gc/gsubr.go
@@ -167,6 +167,7 @@
Clearp(Pc)
}
+// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
func fixautoused(p *obj.Prog) {
for lp := &p; ; {
p = *lp
@@ -258,6 +259,7 @@
return false
}
+// Sweep the prog list to mark any used nodes.
func markautoused(p *obj.Prog) {
for ; p != nil; p = p.Link {
if p.As == obj.ATYPE || p.As == obj.AVARDEF || p.As == obj.AVARKILL {
diff --git a/src/cmd/internal/gc/order.go b/src/cmd/internal/gc/order.go
index 3f16d75..f7e9d4b 100644
--- a/src/cmd/internal/gc/order.go
+++ b/src/cmd/internal/gc/order.go
@@ -41,9 +41,9 @@
// Order holds state during the ordering process.
type Order struct {
- out *NodeList
- temp *NodeList
- free *NodeList
+ out *NodeList // list of generated statements
+ temp *NodeList // head of stack of temporary variables
+ free *NodeList // free list of NodeList* structs (for use in temp)
}
// Order rewrites fn->nbody to apply the ordering constraints
diff --git a/src/cmd/internal/gc/plive.go b/src/cmd/internal/gc/plive.go
index 100b82b..97e870b 100644
--- a/src/cmd/internal/gc/plive.go
+++ b/src/cmd/internal/gc/plive.go
@@ -2,6 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Garbage collector liveness bitmap generation.
+
+// The command line flag -live causes this code to print debug information.
+// The levels are:
+//
+// -live (aka -live=1): print liveness lists as code warnings at safe points
+// -live=2: print an assembly listing with liveness annotations
+// -live=3: print information during each computation phase (much chattier)
+//
+// Each level includes the earlier output as well.
+
package gc
import (
@@ -34,28 +45,49 @@
// ...
// }
type BasicBlock struct {
- pred []*BasicBlock
- succ []*BasicBlock
- first *obj.Prog
- last *obj.Prog
- rpo int
- mark int
- lastbitmapindex int
- uevar Bvec
- varkill Bvec
- livein Bvec
- liveout Bvec
- avarinit Bvec
- avarinitany Bvec
- avarinitall Bvec
+ pred []*BasicBlock // predecessors; if none, probably start of CFG
+ succ []*BasicBlock // successors; if none, probably ends in return statement
+ first *obj.Prog // first instruction in block
+ last *obj.Prog // last instruction in block
+ rpo int // reverse post-order number (also index in cfg)
+ mark int // mark bit for traversals
+ lastbitmapindex int // for livenessepilogue
+
+ // Summary sets of block effects.
+
+ // Computed during livenessprologue using only the content of
+ // individual blocks:
+ //
+ // uevar: upward exposed variables (used before set in block)
+ // varkill: killed variables (set in block)
+ // avarinit: addrtaken variables set or used (proof of initialization)
+ uevar Bvec
+ varkill Bvec
+ avarinit Bvec
+
+ // Computed during livenesssolve using control flow information:
+ //
+ // livein: variables live at block entry
+ // liveout: variables live at block exit
+ // avarinitany: addrtaken variables possibly initialized at block exit
+ // (initialized in block or at exit from any predecessor block)
+ // avarinitall: addrtaken variables certainly initialized at block exit
+ // (initialized in block or at exit from all predecessor blocks)
+ livein Bvec
+ liveout Bvec
+ avarinitany Bvec
+ avarinitall Bvec
}
// A collection of global state used by liveness analysis.
type Liveness struct {
- fn *Node
- ptxt *obj.Prog
- vars []*Node
- cfg []*BasicBlock
+ fn *Node
+ ptxt *obj.Prog
+ vars []*Node
+ cfg []*BasicBlock
+
+ // An array with a bit vector for each safe point tracking live pointers
+ // in the arguments and locals area, indexed by bb.rpo.
argslivepointers []Bvec
livepointers []Bvec
}
diff --git a/src/cmd/internal/gc/popt.go b/src/cmd/internal/gc/popt.go
index c56dc8e..813f24a 100644
--- a/src/cmd/internal/gc/popt.go
+++ b/src/cmd/internal/gc/popt.go
@@ -79,16 +79,25 @@
)
type Reg struct {
- set Bits
- use1 Bits
- use2 Bits
+ set Bits // regopt variables written by this instruction.
+ use1 Bits // regopt variables read by prog->from.
+ use2 Bits // regopt variables read by prog->to.
+
+ // refahead/refbehind are the regopt variables whose current
+ // value may be used in the following/preceding instructions
+ // up to a CALL (or the value is clobbered).
refbehind Bits
refahead Bits
+
+ // calahead/calbehind are similar, but for variables in
+ // instructions that are reachable after hitting at least one
+ // CALL.
calbehind Bits
calahead Bits
- regdiff Bits
- act Bits
- regu uint64
+
+ regdiff Bits
+ act Bits
+ regu uint64 // register used bitmap
}
type Rgn struct {
@@ -639,14 +648,14 @@
type TempVar struct {
node *Node
- def *Flow
- use *Flow
- freelink *TempVar
- merge *TempVar
- start int64
- end int64
- addr uint8
- removed uint8
+ def *Flow // definition of temp var
+ use *Flow // use list, chained through Flow.data
+ freelink *TempVar // next free temp in Type.opt list
+ merge *TempVar // merge var with this one
+ start int64 // smallest Prog.pc in live range
+ end int64 // largest Prog.pc in live range
+ addr uint8 // address taken - no accurate end
+ removed uint8 // removed from program
}
type startcmp []*TempVar
diff --git a/src/cmd/internal/gc/range.go b/src/cmd/internal/gc/range.go
index 3de70ba..8dbb002 100644
--- a/src/cmd/internal/gc/range.go
+++ b/src/cmd/internal/gc/range.go
@@ -135,6 +135,13 @@
}
func walkrange(n *Node) {
+ // variable name conventions:
+ // ohv1, hv1, hv2: hidden (old) val 1, 2
+ // ha, hit: hidden aggregate, iterator
+ // hn, hp: hidden len, pointer
+ // hb: hidden bool
+ // a, v1, v2: not hidden aggregate, val 1, 2
+
t := n.Type
a := n.Right
diff --git a/src/cmd/internal/gc/syntax.go b/src/cmd/internal/gc/syntax.go
index d2b735a..7584af2 100644
--- a/src/cmd/internal/gc/syntax.go
+++ b/src/cmd/internal/gc/syntax.go
@@ -11,31 +11,34 @@
// node with Op=ONAME for a given instance of a variable x.
// The same is true for Op=OTYPE and Op=OLITERAL.
type Node struct {
- Left *Node
- Right *Node
- Ntest *Node
- Nincr *Node
- Ninit *NodeList
- Nbody *NodeList
- Nelse *NodeList
- List *NodeList
- Rlist *NodeList
+ // Tree structure.
+ // Generic recursive walks should follow these fields.
+ Left *Node
+ Right *Node
+ Ntest *Node
+ Nincr *Node
+ Ninit *NodeList
+ Nbody *NodeList
+ Nelse *NodeList
+ List *NodeList
+ Rlist *NodeList
+
Op uint8
Nointerface bool
- Ullman uint8
- Addable uint8
- Trecur uint8
- Etype uint8
- Bounded bool
- Class uint8
- Method uint8
- Embedded uint8
- Colas uint8
- Diag uint8
- Noescape bool
- Nosplit bool
- Builtin uint8
- Nowritebarrier bool
+ Ullman uint8 // sethi/ullman number
+ Addable uint8 // type of addressability - 0 is not addressable
+ Trecur uint8 // to detect loops
+ Etype uint8 // op for OASOP, etype for OTYPE, exclam for export
+ Bounded bool // bounds check unnecessary
+ Class uint8 // PPARAM, PAUTO, PEXTERN, etc
+ Method uint8 // OCALLMETH name
+ Embedded uint8 // ODCLFIELD embedded type
+ Colas uint8 // OAS resulting from :=
+ Diag uint8 // already printed error about this
+ Noescape bool // func arguments do not escape
+ Nosplit bool // func should not execute on separate stack
+ Builtin uint8 // built-in name, like len or close
+ Nowritebarrier bool // emit compiler error instead of write barrier
Walkdef uint8
Typecheck uint8
Local uint8
@@ -45,219 +48,255 @@
Isddd uint8
Readonly uint8
Implicit uint8
- Addrtaken uint8
- Assigned uint8
- Captured uint8
- Byval uint8
- Dupok uint8
- Wrapper uint8
- Reslice uint8
- Likely int8
- Hasbreak uint8
- Needzero bool
- Needctxt bool
- Esc uint
+ Addrtaken uint8 // address taken, even if not moved to heap
+ Assigned uint8 // is the variable ever assigned to
+ Captured uint8 // is the variable captured by a closure
+ Byval uint8 // is the variable captured by value or by reference
+ Dupok uint8 // duplicate definitions ok (for func)
+ Wrapper uint8 // is method wrapper (for func)
+ Reslice uint8 // this is a reslice x = x[0:y] or x = append(x, ...)
+ Likely int8 // likeliness of if statement
+ Hasbreak uint8 // has break statement
+ Needzero bool // if it contains pointers, needs to be zeroed on function entry
+ Needctxt bool // function uses context register (has closure variables)
+ Esc uint // EscXXX
Funcdepth int
- Type *Type
- Orig *Node
- Nname *Node
- Shortname *Node
- Enter *NodeList
- Exit *NodeList
- Cvars *NodeList
- Dcl *NodeList
- Inl *NodeList
- Inldcl *NodeList
- Closgen int
- Outerfunc *Node
- Val Val
- Ntype *Node
- Defn *Node
- Pack *Node
- Curfn *Node
- Paramfld *Type
- Decldepth int
- Heapaddr *Node
- Outerexpr *Node
- Stackparam *Node
- Alloc *Node
- Outer *Node
- Closure *Node
- Top int
- Inlvar *Node
- Pkg *Pkg
- Initplan *InitPlan
- Escflowsrc *NodeList
- Escretval *NodeList
- Escloopdepth int
- Sym *Sym
- InlCost int32
- Vargen int32
- Lineno int32
- Endlineno int32
- Xoffset int64
- Stkdelta int64
- Ostk int32
- Iota int32
- Walkgen uint32
- Esclevel int32
- Opt interface{}
+
+ // most nodes
+ Type *Type
+ Orig *Node // original form, for printing, and tracking copies of ONAMEs
+
+ // func
+ Nname *Node
+ Shortname *Node
+ Enter *NodeList
+ Exit *NodeList
+ Cvars *NodeList // closure params
+ Dcl *NodeList // autodcl for this func/closure
+ Inl *NodeList // copy of the body for use in inlining
+ Inldcl *NodeList // copy of dcl for use in inlining
+ Closgen int
+ Outerfunc *Node
+
+ // OLITERAL/OREGISTER
+ Val Val
+
+ // ONAME
+ Ntype *Node
+ Defn *Node // ONAME: initializing assignment; OLABEL: labeled statement
+ Pack *Node // real package for import . names
+ Curfn *Node // function for local variables
+ Paramfld *Type // TFIELD for this PPARAM; also for ODOT, curfn
+ Decldepth int // declaration loop depth, increased for every loop or label
+
+ // ONAME func param with PHEAP
+ Heapaddr *Node // temp holding heap address of param
+ Outerexpr *Node // expression copied into closure for variable
+ Stackparam *Node // OPARAM node referring to stack copy of param
+ Alloc *Node // allocation call
+
+ // ONAME closure param with PPARAMREF
+ Outer *Node // outer PPARAMREF in nested closure
+ Closure *Node // ONAME/PHEAP <-> ONAME/PPARAMREF
+ Top int // top context (Ecall, Eproc, etc)
+
+ // ONAME substitute while inlining
+ Inlvar *Node
+
+ // OPACK
+ Pkg *Pkg
+
+ // OARRAYLIT, OMAPLIT, OSTRUCTLIT.
+ Initplan *InitPlan
+
+ // Escape analysis.
+ Escflowsrc *NodeList // flow(this, src)
+ Escretval *NodeList // on OCALLxxx, list of dummy return values
+ Escloopdepth int // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
+
+ Sym *Sym // various
+ InlCost int32 // unique name for OTYPE/ONAME
+ Vargen int32
+ Lineno int32
+ Endlineno int32
+ Xoffset int64
+ Stkdelta int64 // offset added by stack frame compaction phase.
+ Ostk int32
+ Iota int32
+ Walkgen uint32
+ Esclevel int32
+ Opt interface{} // for optimization passes
}
// Node ops.
const (
OXXX = iota
- ONAME
- ONONAME
- OTYPE
- OPACK
- OLITERAL
- OADD
- OSUB
- OOR
- OXOR
- OADDSTR
- OADDR
- OANDAND
- OAPPEND
- OARRAYBYTESTR
- OARRAYBYTESTRTMP
- OARRAYRUNESTR
- OSTRARRAYBYTE
- OSTRARRAYBYTETMP
- OSTRARRAYRUNE
- OAS
- OAS2
- OAS2FUNC
- OAS2RECV
- OAS2MAPR
- OAS2DOTTYPE
- OASOP
- OCALL
- OCALLFUNC
- OCALLMETH
- OCALLINTER
- OCALLPART
- OCAP
- OCLOSE
- OCLOSURE
- OCMPIFACE
- OCMPSTR
- OCOMPLIT
- OMAPLIT
- OSTRUCTLIT
- OARRAYLIT
- OPTRLIT
- OCONV
- OCONVIFACE
- OCONVNOP
- OCOPY
- ODCL
- ODCLFUNC
- ODCLFIELD
- ODCLCONST
- ODCLTYPE
- ODELETE
- ODOT
- ODOTPTR
- ODOTMETH
- ODOTINTER
- OXDOT
- ODOTTYPE
- ODOTTYPE2
- OEQ
- ONE
- OLT
- OLE
- OGE
- OGT
- OIND
- OINDEX
- OINDEXMAP
- OKEY
- OPARAM
- OLEN
- OMAKE
- OMAKECHAN
- OMAKEMAP
- OMAKESLICE
- OMUL
- ODIV
- OMOD
- OLSH
- ORSH
- OAND
- OANDNOT
- ONEW
- ONOT
- OCOM
- OPLUS
- OMINUS
- OOROR
- OPANIC
- OPRINT
- OPRINTN
- OPAREN
- OSEND
- OSLICE
- OSLICEARR
- OSLICESTR
- OSLICE3
- OSLICE3ARR
- ORECOVER
- ORECV
- ORUNESTR
- OSELRECV
- OSELRECV2
- OIOTA
- OREAL
- OIMAG
- OCOMPLEX
- OBLOCK
- OBREAK
- OCASE
- OXCASE
- OCONTINUE
- ODEFER
- OEMPTY
- OFALL
- OXFALL
- OFOR
- OGOTO
- OIF
- OLABEL
- OPROC
- ORANGE
- ORETURN
- OSELECT
- OSWITCH
- OTYPESW
- OTCHAN
- OTMAP
- OTSTRUCT
- OTINTER
- OTFUNC
- OTARRAY
- ODDD
- ODDDARG
- OINLCALL
- OEFACE
- OITAB
- OSPTR
- OCLOSUREVAR
- OCFUNC
- OCHECKNIL
- OVARKILL
- OREGISTER
- OINDREG
- OCMP
- ODEC
- OINC
- OEXTEND
- OHMUL
- OLROT
- ORROTC
- ORETJMP
+
+ // names
+ ONAME // var, const or func name
+ ONONAME // unnamed arg or return value: f(int, string) (int, error) { etc }
+ OTYPE // type name
+ OPACK // import
+ OLITERAL // literal
+
+ // expressions
+ OADD // x + y
+ OSUB // x - y
+ OOR // x | y
+ OXOR // x ^ y
+ OADDSTR // s + "foo"
+ OADDR // &x
+ OANDAND // b0 && b1
+ OAPPEND // append
+ OARRAYBYTESTR // string(bytes)
+ OARRAYBYTESTRTMP // string(bytes) ephemeral
+ OARRAYRUNESTR // string(runes)
+ OSTRARRAYBYTE // []byte(s)
+ OSTRARRAYBYTETMP // []byte(s) ephemeral
+ OSTRARRAYRUNE // []rune(s)
+ OAS // x = y or x := y
+ OAS2 // x, y, z = xx, yy, zz
+ OAS2FUNC // x, y = f()
+ OAS2RECV // x, ok = <-c
+ OAS2MAPR // x, ok = m["foo"]
+ OAS2DOTTYPE // x, ok = I.(int)
+ OASOP // x += y
+ OCALL // function call, method call or type conversion, possibly preceded by defer or go.
+ OCALLFUNC // f()
+ OCALLMETH // t.Method()
+ OCALLINTER // err.Error()
+ OCALLPART // t.Method (without ())
+ OCAP // cap
+ OCLOSE // close
+ OCLOSURE // f = func() { etc }
+ OCMPIFACE // err1 == err2
+ OCMPSTR // s1 == s2
+ OCOMPLIT // composite literal, typechecking may convert to a more specific OXXXLIT.
+ OMAPLIT // M{"foo":3, "bar":4}
+ OSTRUCTLIT // T{x:3, y:4}
+ OARRAYLIT // [2]int{3, 4}
+ OPTRLIT // &T{x:3, y:4}
+ OCONV // var i int; var u uint; i = int(u)
+ OCONVIFACE // I(t)
+ OCONVNOP // type Int int; var i int; var j Int; i = int(j)
+ OCOPY // copy
+ ODCL // var x int
+ ODCLFUNC // func f() or func (r) f()
+ ODCLFIELD // struct field, interface field, or func/method argument/return value.
+ ODCLCONST // const pi = 3.14
+ ODCLTYPE // type Int int
+ ODELETE // delete
+ ODOT // t.x
+ ODOTPTR // p.x that is implicitly (*p).x
+ ODOTMETH // t.Method
+ ODOTINTER // err.Error
+ OXDOT // t.x, typechecking may convert to a more specific ODOTXXX.
+ ODOTTYPE // e = err.(MyErr)
+ ODOTTYPE2 // e, ok = err.(MyErr)
+ OEQ // x == y
+ ONE // x != y
+ OLT // x < y
+ OLE // x <= y
+ OGE // x >= y
+ OGT // x > y
+ OIND // *p
+ OINDEX // a[i]
+ OINDEXMAP // m[s]
+ OKEY // The x:3 in t{x:3, y:4}, the 1:2 in a[1:2], the 2:20 in [3]int{2:20}, etc.
+ OPARAM // The on-stack copy of a parameter or return value that escapes.
+ OLEN // len
+ OMAKE // make, typechecking may convert to a more specific OMAKEXXX.
+ OMAKECHAN // make(chan int)
+ OMAKEMAP // make(map[string]int)
+ OMAKESLICE // make([]int, 0)
+ OMUL // *
+ ODIV // x / y
+ OMOD // x % y
+ OLSH // x << u
+ ORSH // x >> u
+ OAND // x & y
+ OANDNOT // x &^ y
+ ONEW // new
+ ONOT // !b
+ OCOM // ^x
+ OPLUS // +x
+ OMINUS // -y
+ OOROR // b1 || b2
+ OPANIC // panic
+ OPRINT // print
+ OPRINTN // println
+ OPAREN // (x)
+ OSEND // c <- x
+ OSLICE // v[1:2], typechecking may convert to a more specific OSLICEXXX.
+ OSLICEARR // a[1:2]
+ OSLICESTR // s[1:2]
+ OSLICE3 // v[1:2:3], typechecking may convert to OSLICE3ARR.
+ OSLICE3ARR // a[1:2:3]
+ ORECOVER // recover
+ ORECV // <-c
+ ORUNESTR // string(i)
+ OSELRECV // case x = <-c:
+ OSELRECV2 // case x, ok = <-c:
+ OIOTA // iota
+ OREAL // real
+ OIMAG // imag
+ OCOMPLEX // complex
+
+ // statements
+ OBLOCK // block of code
+ OBREAK // break
+ OCASE // case, after being verified by swt.c's casebody.
+ OXCASE // case, before verification.
+ OCONTINUE // continue
+ ODEFER // defer
+ OEMPTY // no-op
+ OFALL // fallthrough, after being verified by swt.c's casebody.
+ OXFALL // fallthrough, before verification.
+ OFOR // for
+ OGOTO // goto
+ OIF // if
+ OLABEL // label:
+ OPROC // go
+ ORANGE // range
+ ORETURN // return
+ OSELECT // select
+ OSWITCH // switch x
+ OTYPESW // switch err.(type)
+
+ // types
+ OTCHAN // chan int
+ OTMAP // map[string]int
+ OTSTRUCT // struct{}
+ OTINTER // interface{}
+ OTFUNC // func()
+ OTARRAY // []int, [8]int, [N]int or [...]int
+
+ // misc
+ ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}.
+ ODDDARG // func f(args ...int), introduced by escape analysis.
+ OINLCALL // intermediary representation of an inlined call.
+ OEFACE // itable and data words of an empty-interface value.
+ OITAB // itable word of an interface value.
+ OSPTR // base pointer of a slice or string.
+ OCLOSUREVAR // variable reference at beginning of closure function
+ OCFUNC // reference to c function pointer (not go func value)
+ OCHECKNIL // emit code to ensure pointer/interface not nil
+ OVARKILL // variable is dead
+
+ // thearch-specific registers
+ OREGISTER // a register, such as AX.
+ OINDREG // offset plus indirect of a register, such as 8(SP).
+
+ // 386/amd64-specific opcodes
+ OCMP // compare: ACMP.
+ ODEC // decrement: ADEC.
+ OINC // increment: AINC.
+ OEXTEND // extend: ACWD/ACDQ/ACQO.
+ OHMUL // high mul: AMUL/AIMUL for unsigned/signed (OMUL uses AIMUL for both).
+ OLROT // left rotate: AROL.
+ ORROTC // right rotate-carry: ARCR.
+ ORETJMP // return to other function
+
OEND
)
diff --git a/src/cmd/internal/gc/typecheck.go b/src/cmd/internal/gc/typecheck.go
index 845aac6..5ae418c 100644
--- a/src/cmd/internal/gc/typecheck.go
+++ b/src/cmd/internal/gc/typecheck.go
@@ -490,7 +490,7 @@
case OIND:
ntop := Erv | Etype
- if top&Eaddr == 0 {
+ if top&Eaddr == 0 { // The *x in &*x is not an indirect.
ntop |= Eindir
}
ntop |= top & Ecomplit
diff --git a/src/cmd/internal/gc/walk.go b/src/cmd/internal/gc/walk.go
index 842deab..a96ce07 100644
--- a/src/cmd/internal/gc/walk.go
+++ b/src/cmd/internal/gc/walk.go
@@ -2950,10 +2950,9 @@
nif.Ntest = Nod(OGT, nt, Nodintconst(0))
// instantiate growslice(Type*, []any, int) []any
- fn := syslook("growslice", 1)
-
- argtype(fn, s.Type.Type)
- argtype(fn, s.Type.Type)
+ fn := syslook("growslice", 1) // growslice(<type>, old []T, n int64) (ret []T)
+ argtype(fn, s.Type.Type) // 1 old []any
+ argtype(fn, s.Type.Type) // 2 ret []any
// s = growslice(T, s, n)
nif.Nbody = list1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt)))
@@ -3774,8 +3773,8 @@
// by a constant
w := int(nl.Type.Width * 8)
- s := 0
- pow := powtwo(nr)
+ s := 0 // 1 if nr is negative.
+ pow := powtwo(nr) // if >= 0, nr is 1<<pow
if pow >= 1000 {
// negative power of 2
s = 1