var knownFormats = map[string]string{
"*bytes.Buffer %s": "",
"*cmd/compile/internal/gc.EscLocation %v": "",
+ "*cmd/compile/internal/ir.Name %v": "",
"*cmd/compile/internal/ir.node %v": "",
"*cmd/compile/internal/ssa.Block %s": "",
"*cmd/compile/internal/ssa.Block %v": "",
hashel := hashfor(t.Elem())
n := ir.Nod(ir.ORANGE, nil, ir.Nod(ir.ODEREF, np, nil))
- ni := NewName(lookup("i"))
+ ni := ir.Node(NewName(lookup("i")))
ni.SetType(types.Types[types.TINT])
n.PtrList().Set1(ni)
n.SetColas(true)
// NOTE(rsc): This comment may be stale.
// It's possible the ordering has changed and this is
// now the common case. I'm not sure.
- if n.Name().Param.Stackcopy != nil {
- n.Name().Param.Stackcopy.SetOffset(o)
+ if n.Name().Stackcopy != nil {
+ n.Name().Stackcopy.SetOffset(o)
n.SetOffset(0)
} else {
n.SetOffset(o)
}
*path = append(*path, t)
- if p := ir.AsNode(t.Nod).Name().Param; p != nil && findTypeLoop(p.Ntype.Type(), path) {
- return true
+ if n := ir.AsNode(t.Nod); n != nil {
+ if name := n.Name(); name != nil && name.Ntype != nil && findTypeLoop(name.Ntype.Type(), path) {
+ return true
+ }
}
*path = (*path)[:len(*path)-1]
} else {
fn := dcl.Func()
fn.SetIsHiddenClosure(Curfn != nil)
fn.Nname = newfuncnamel(p.pos(expr), ir.BlankNode.Sym(), fn) // filled in by typecheckclosure
- fn.Nname.Name().Param.Ntype = xtype
+ fn.Nname.Name().Ntype = xtype
fn.Nname.Name().Defn = dcl
clo := p.nod(expr, ir.OCLOSURE, nil, nil)
for _, v := range fn.ClosureVars.Slice() {
// Unlink from v1; see comment in syntax.go type Param for these fields.
v1 := v.Name().Defn
- v1.Name().Param.Innermost = v.Name().Param.Outer
+ v1.Name().Innermost = v.Name().Outer
// If the closure usage of v is not dense,
// we need to make it dense; now that we're out
// obtains f3's v, creating it if necessary (as it is in the example).
//
// capturevars will decide whether to use v directly or &v.
- v.Name().Param.Outer = oldname(v.Sym())
+ v.Name().Outer = oldname(v.Sym()).(*ir.Name)
}
return clo
// so that the outer frame also grabs them and knows they escape.
dowidth(v.Type())
- outer := v.Name().Param.Outer
+ var outer ir.Node
+ outer = v.Name().Outer
outermost := v.Name().Defn
// out parameters will be assigned to implicitly upon return.
// (accesses will implicitly deref &v).
addr := NewName(lookup("&" + v.Sym().Name))
addr.SetType(types.NewPtr(v.Type()))
- v.Name().Param.Heapaddr = addr
+ v.Name().Heapaddr = addr
v = addr
}
addr.Name().SetUsed(true)
addr.Name().Curfn = dcl
fn.Dcl = append(fn.Dcl, addr)
- v.Name().Param.Heapaddr = addr
+ v.Name().Heapaddr = addr
if v.Name().Byval() {
cv = ir.Nod(ir.OADDR, cv, nil)
}
"cmd/internal/obj"
"cmd/internal/src"
"fmt"
- "go/constant"
"strings"
)
return
}
- if n.Name() == nil {
- // named OLITERAL needs Name; most OLITERALs don't.
- n.SetName(new(ir.Name))
- }
-
s := n.Sym()
// kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
for _, v := range vl {
v.SetOp(ir.ONAME)
declare(v, dclcontext)
- v.Name().Param.Ntype = t
+ v.Name().Ntype = t
v.Name().Defn = as2
if Curfn != nil {
init = append(init, ir.Nod(ir.ODCL, v, nil))
v.SetOp(ir.ONAME)
declare(v, dclcontext)
- v.Name().Param.Ntype = t
+ v.Name().Ntype = t
if e != nil || Curfn != nil || ir.IsBlank(v) {
if Curfn != nil {
if s == nil {
base.Fatalf("newnoname nil")
}
- n := ir.Nod(ir.ONONAME, nil, nil)
- n.SetSym(s)
- n.SetOffset(0)
+ n := ir.NewNameAt(base.Pos, s)
+ n.SetOp(ir.ONONAME)
return n
}
// this generates a new name node for a name
// being declared.
-func dclname(s *types.Sym) ir.Node {
+func dclname(s *types.Sym) *ir.Name {
n := NewName(s)
n.SetOp(ir.ONONAME) // caller will correct it
return n
// are parsing x := 5 inside the closure, until we get to
// the := it looks like a reference to the outer x so we'll
// make x a closure variable unnecessarily.
- c := n.Name().Param.Innermost
+ c := n.Name().Innermost
if c == nil || c.Name().Curfn != Curfn {
// Do not have a closure var for the active closure yet; make one.
c = NewName(s)
// Link into list of active closure variables.
// Popped from list in func funcLit.
- c.Name().Param.Outer = n.Name().Param.Innermost
- n.Name().Param.Innermost = c
+ c.Name().Outer = n.Name().Innermost
+ n.Name().Innermost = c
Curfn.Func().ClosureVars.Append(c)
}
types.Markdcl()
- if n.Func().Nname != nil && n.Func().Nname.Name().Param.Ntype != nil {
- funcargs(n.Func().Nname.Name().Param.Ntype)
+ if n.Func().Nname != nil && n.Func().Nname.Name().Ntype != nil {
+ funcargs(n.Func().Nname.Name().Ntype)
} else {
funcargs2(n.Type())
}
}
n.SetRight(ir.NewNameAt(n.Pos(), n.Sym()))
- n.Right().Name().Param.Ntype = n.Left()
+ n.Right().Name().Ntype = n.Left()
n.Right().SetIsDDD(n.IsDDD())
declare(n.Right(), ctxt)
checkembeddedtype(n.Type())
f.Embedded = 1
}
- if n.HasVal() {
- f.Note = constant.StringVal(n.Val())
+ if n.Opt() != nil {
+ f.Note = n.Opt().(string)
}
base.Pos = lno
base.Fatalf("interfacefield: oops %v\n", n)
}
- if n.HasVal() {
+ if n.Opt() != nil {
base.Errorf("interface method cannot have annotation")
}
fn := ir.Nod(ir.ODCLFUNC, nil, nil)
fn.Func().Nname = newfuncnamel(base.Pos, sym, fn.Func())
fn.Func().Nname.Name().Defn = fn
- fn.Func().Nname.Name().Param.Ntype = tfn
+ fn.Func().Nname.Name().Ntype = tfn
setNodeNameFunc(fn.Func().Nname)
funchdr(fn)
- fn.Func().Nname.Name().Param.Ntype = typecheck(fn.Func().Nname.Name().Param.Ntype, ctxType)
+ fn.Func().Nname.Name().Ntype = typecheck(fn.Func().Nname.Name().Ntype, ctxType)
return fn
}
numLocalEmbed++
v = ir.NewNameAt(v.Pos(), lookupN("embed.", numLocalEmbed))
v.Sym().Def = v
- v.Name().Param.Ntype = typ
+ v.Name().Ntype = typ
v.SetClass(ir.PEXTERN)
externdcl = append(externdcl, v)
exprs = []ir.Node{v}
}
- v.Name().Param.SetEmbedFiles(list)
+ v.Name().SetEmbedFiles(list)
embedlist = append(embedlist, v)
return exprs
}
// initEmbed emits the init data for a //go:embed variable,
// which is either a string, a []byte, or an embed.FS.
func initEmbed(v ir.Node) {
- files := v.Name().Param.EmbedFiles()
+ files := v.Name().EmbedFiles()
switch kind := embedKind(v.Type()); kind {
case embedUnknown:
base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type())
stackcopy.SetType(n.Type())
stackcopy.SetOffset(n.Offset())
stackcopy.SetClass(n.Class())
- stackcopy.Name().Param.Heapaddr = heapaddr
+ stackcopy.Name().Heapaddr = heapaddr
if n.Class() == ir.PPARAMOUT {
// Make sure the pointer to the heap copy is kept live throughout the function.
// The function could panic at any point, and then a defer could recover.
// See issue 16095.
heapaddr.Name().SetIsOutputParamHeapAddr(true)
}
- n.Name().Param.Stackcopy = stackcopy
+ n.Name().Stackcopy = stackcopy
// Substitute the stackcopy into the function variable list so that
// liveness and other analyses use the underlying stack slot
// Modify n in place so that uses of n now mean indirection of the heapaddr.
n.SetClass(ir.PAUTOHEAP)
n.SetOffset(0)
- n.Name().Param.Heapaddr = heapaddr
+ n.Name().Heapaddr = heapaddr
n.SetEsc(EscHeap)
if base.Flag.LowerM != 0 {
base.WarnfAt(n.Pos(), "moved to heap: %v", n)
// isParamStackCopy reports whether this is the on-stack copy of a
// function parameter that moved to the heap.
func isParamStackCopy(n ir.Node) bool {
- return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Param.Heapaddr != nil
+ return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Heapaddr != nil
}
// isParamHeapCopy reports whether this is the on-heap copy of
// a function parameter that moved to the heap.
func isParamHeapCopy(n ir.Node) bool {
- return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Param.Stackcopy != nil
+ return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy != nil
}
// autotmpname returns the name for an autotmp variable numbered n.
}
// make a new Node off the books
-func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) ir.Node {
+func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) *ir.Name {
if curfn == nil {
base.Fatalf("no curfn for tempAt")
}
dowidth(t)
- return ir.Orig(n)
+ return n
}
-func temp(t *types.Type) ir.Node {
+func temp(t *types.Type) *ir.Name {
return tempAt(base.Pos, Curfn, t)
}
// PPARAM/PPARAMOUT, because we only want to include vargen in
// non-param names.
var v int32
- if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name().Param.Stackcopy == nil) {
+ if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy == nil) {
v = n.Name().Vargen
}
continue
}
- o := v.Name().Param.Outer
+ o := v.Name().Outer
// make sure the outer param matches the inlining location
// NB: if we enabled inlining of functions containing OCLOSURE or refined
// the reassigned check via some sort of copy propagation this would most
timings.Start("fe", "typecheck", "top1")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
- if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Param.Alias()) {
+ if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Alias()) {
xtop[i] = typecheck(n, ctxStmt)
}
}
timings.Start("fe", "typecheck", "top2")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
- if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Param.Alias() {
+ if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Alias() {
xtop[i] = typecheck(n, ctxStmt)
}
}
n.SetOp(ir.OLITERAL)
declare(n, dclcontext)
- n.Name().Param.Ntype = typ
+ n.Name().Ntype = typ
n.Name().Defn = v
n.SetIota(cs.iota)
// decl.Type may be nil but in that case we got a syntax error during parsing
typ := p.typeExprOrNil(decl.Type)
- param := n.Name().Param
- param.Ntype = typ
- param.SetAlias(decl.Alias)
+ n.Ntype = typ
+ n.SetAlias(decl.Alias)
if pragma, ok := decl.Pragma.(*Pragma); ok {
if !decl.Alias {
- param.SetPragma(pragma.Flag & TypePragmas)
+ n.SetPragma(pragma.Flag & TypePragmas)
pragma.Flag &^= TypePragmas
}
p.checkUnused(pragma)
}
nod := p.nod(decl, ir.ODCLTYPE, n, nil)
- if param.Alias() && !langSupported(1, 9, ir.LocalPkg) {
+ if n.Alias() && !langSupported(1, 9, ir.LocalPkg) {
base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
}
return nod
return nodes
}
-func (p *noder) declName(name *syntax.Name) ir.Node {
+func (p *noder) declName(name *syntax.Name) *ir.Name {
n := dclname(p.name(name))
n.SetPos(p.pos(name))
return n
f.Func().Nname = newfuncnamel(p.pos(fun.Name), name, f.Func())
f.Func().Nname.Name().Defn = f
- f.Func().Nname.Name().Param.Ntype = t
+ f.Func().Nname.Name().Ntype = t
if pragma, ok := fun.Pragma.(*Pragma); ok {
f.Func().Pragma = pragma.Flag & FuncPragmas
n = p.nodSym(field, ir.ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name))
}
if i < len(expr.TagList) && expr.TagList[i] != nil {
- n.SetVal(p.basicLit(expr.TagList[i]))
+ n.SetOpt(constant.StringVal(p.basicLit(expr.TagList[i])))
}
l = append(l, n)
}
// misleading location for the param (we want pointer-to-heap
// and not stack).
// TODO(thanm): generate a better location expression
- stackcopy := n.Name().Param.Stackcopy
+ stackcopy := n.Name().Stackcopy
if stackcopy != nil && (stackcopy.Class() == ir.PPARAM || stackcopy.Class() == ir.PPARAMOUT) {
abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
isReturnValue = (stackcopy.Class() == ir.PPARAMOUT)
// Just to be paranoid. Heap addresses are PAUTOs.
base.Fatalf("variable %v both output param and heap output param", n)
}
- if n.Name().Param.Heapaddr != nil {
+ if n.Name().Heapaddr != nil {
// If this variable moved to the heap, then
// its stack copy is not live.
continue
}
// newname returns a new ONAME Node associated with symbol s.
-func NewName(s *types.Sym) ir.Node {
+func NewName(s *types.Sym) *ir.Name {
n := ir.NewNameAt(base.Pos, s)
n.Name().Curfn = Curfn
return n
// are substituted.
cycle := cycleFor(n)
for _, n1 := range cycle {
- if n1.Name() != nil && !n1.Name().Param.Alias() {
+ if n1.Name() != nil && !n1.Name().Alias() {
// Cycle is ok. But if n is an alias type and doesn't
// have a type yet, we have a recursive type declaration
// with aliases that we can't handle properly yet.
// Report an error rather than crashing later.
- if n.Name() != nil && n.Name().Param.Alias() && n.Type() == nil {
+ if n.Name() != nil && n.Name().Alias() && n.Type() == nil {
base.Pos = n.Pos()
base.Fatalf("cannot handle alias type declaration (issue #25838): %v", n)
}
}
n.SetOp(ir.OMETHEXPR)
- if n.Name() == nil {
- n.SetName(new(ir.Name))
- }
n.SetRight(NewName(n.Sym()))
n.SetSym(methodSym(t, n.Sym()))
n.SetType(methodfunc(m.Type, n.Left().Type()))
// so that the conversion below happens).
n.SetLeft(resolve(n.Left()))
- if n.Left().Name() == nil || n.Left().Name().Defn != n || n.Left().Name().Param.Ntype != nil {
+ if n.Left().Name() == nil || n.Left().Name().Defn != n || n.Left().Name().Ntype != nil {
n.SetLeft(typecheck(n.Left(), ctxExpr|ctxAssign))
}
}
}
- if n.Left().Name() != nil && n.Left().Name().Defn == n && n.Left().Name().Param.Ntype == nil {
+ if n.Left().Name() != nil && n.Left().Name().Defn == n && n.Left().Name().Ntype == nil {
n.SetRight(defaultlit(n.Right(), nil))
n.Left().SetType(n.Right().Type())
}
n1 = resolve(n1)
ls[i1] = n1
- if n1.Name() == nil || n1.Name().Defn != n || n1.Name().Param.Ntype != nil {
+ if n1.Name() == nil || n1.Name().Defn != n || n1.Name().Ntype != nil {
ls[i1] = typecheck(ls[i1], ctxExpr|ctxAssign)
}
}
if nl.Type() != nil && nr.Type() != nil {
rs[il] = assignconv(nr, nl.Type(), "assignment")
}
- if nl.Name() != nil && nl.Name().Defn == n && nl.Name().Param.Ntype == nil {
+ if nl.Name() != nil && nl.Name().Defn == n && nl.Name().Ntype == nil {
rs[il] = defaultlit(rs[il], nil)
nl.SetType(rs[il].Type())
}
if f.Type != nil && l.Type() != nil {
checkassignto(f.Type, l)
}
- if l.Name() != nil && l.Name().Defn == n && l.Name().Param.Ntype == nil {
+ if l.Name() != nil && l.Name().Defn == n && l.Name().Ntype == nil {
l.SetType(f.Type)
}
}
if l.Type() != nil && !l.Type().IsBoolean() {
checkassignto(types.Types[types.TBOOL], l)
}
- if l.Name() != nil && l.Name().Defn == n && l.Name().Param.Ntype == nil {
+ if l.Name() != nil && l.Name().Defn == n && l.Name().Ntype == nil {
l.SetType(types.Types[types.TBOOL])
}
goto out
}
// Propagate go:notinheap pragma from the Name to the Type.
- if n.Name() != nil && n.Name().Param != nil && n.Name().Param.Pragma()&ir.NotInHeap != 0 {
+ if n.Name() != nil && n.Name().Pragma()&ir.NotInHeap != 0 {
t.SetNotInHeap(true)
}
}
n.SetTypecheck(1)
- n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
- t := n.Name().Param.Ntype.Type()
+ n.Name().Ntype = typecheck(n.Name().Ntype, ctxType)
+ t := n.Name().Ntype.Type()
if t == nil {
n.SetDiag(true)
n.SetType(nil)
base.Fatalf("typecheckdef %v", n.Op())
case ir.OLITERAL:
- if n.Name().Param.Ntype != nil {
- n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
- n.SetType(n.Name().Param.Ntype.Type())
- n.Name().Param.Ntype = nil
+ if n.Name().Ntype != nil {
+ n.Name().Ntype = typecheck(n.Name().Ntype, ctxType)
+ n.SetType(n.Name().Ntype.Type())
+ n.Name().Ntype = nil
if n.Type() == nil {
n.SetDiag(true)
goto ret
}
case ir.ONAME:
- if n.Name().Param.Ntype != nil {
- n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
- n.SetType(n.Name().Param.Ntype.Type())
+ if n.Name().Ntype != nil {
+ n.Name().Ntype = typecheck(n.Name().Ntype, ctxType)
+ n.SetType(n.Name().Ntype.Type())
if n.Type() == nil {
n.SetDiag(true)
goto ret
n.Name().Defn = typecheck(n.Name().Defn, ctxStmt) // fills in n.Type
case ir.OTYPE:
- if p := n.Name().Param; p.Alias() {
+ n := n.(*ir.Name)
+ if n.Alias() {
// Type alias declaration: Simply use the rhs type - no need
// to create a new type.
// If we have a syntax error, p.Ntype may be nil.
- if p.Ntype != nil {
- p.Ntype = typecheck(p.Ntype, ctxType)
- n.SetType(p.Ntype.Type())
+ if n.Ntype != nil {
+ n.Ntype = typecheck(n.Ntype, ctxType)
+ n.SetType(n.Ntype.Type())
if n.Type() == nil {
n.SetDiag(true)
goto ret
}
// For package-level type aliases, set n.Sym.Def so we can identify
// it as a type alias during export. See also #31959.
- if n.Name().Curfn == nil {
- n.Sym().Def = p.Ntype
+ if n.Curfn == nil {
+ n.Sym().Def = n.Ntype
}
}
break
types.Types[etype] = t
}
s2.Def = typenod(t)
- ir.AsNode(s2.Def).SetName(new(ir.Name))
}
for _, s := range &builtinFuncs {
s := ir.BuiltinPkg.Lookup("true")
s.Def = nodbool(true)
ir.AsNode(s.Def).SetSym(lookup("true"))
- ir.AsNode(s.Def).SetName(new(ir.Name))
ir.AsNode(s.Def).SetType(types.UntypedBool)
s = ir.BuiltinPkg.Lookup("false")
s.Def = nodbool(false)
ir.AsNode(s.Def).SetSym(lookup("false"))
- ir.AsNode(s.Def).SetName(new(ir.Name))
ir.AsNode(s.Def).SetType(types.UntypedBool)
s = lookup("_")
s = ir.BuiltinPkg.Lookup("nil")
s.Def = nodnil()
ir.AsNode(s.Def).SetSym(s)
- ir.AsNode(s.Def).SetName(new(ir.Name))
s = ir.BuiltinPkg.Lookup("iota")
s.Def = ir.Nod(ir.OIOTA, nil, nil)
ir.AsNode(s.Def).SetSym(s)
- ir.AsNode(s.Def).SetName(new(ir.Name))
}
func typeinit() {
types.Types[types.TUNSAFEPTR] = t
t.Sym = unsafepkg.Lookup("Pointer")
t.Sym.Def = typenod(t)
- ir.AsNode(t.Sym.Def).SetName(new(ir.Name))
dowidth(types.Types[types.TUNSAFEPTR])
for et := types.TINT8; et <= types.TUINT64; et++ {
types.Bytetype = types.New(types.TUINT8)
types.Bytetype.Sym = s
s.Def = typenod(types.Bytetype)
- ir.AsNode(s.Def).SetName(new(ir.Name))
dowidth(types.Bytetype)
// rune alias
types.Runetype = types.New(types.TINT32)
types.Runetype.Sym = s
s.Def = typenod(types.Runetype)
- ir.AsNode(s.Def).SetName(new(ir.Name))
dowidth(types.Runetype)
// backend-dependent builtin types (e.g. int).
t.Sym = s1
types.Types[s.etype] = t
s1.Def = typenod(t)
- ir.AsNode(s1.Def).SetName(new(ir.Name))
s1.Origpkg = ir.BuiltinPkg
dowidth(t)
if prealloc[v] == nil {
prealloc[v] = callnew(v.Type())
}
- nn := ir.Nod(ir.OAS, v.Name().Param.Heapaddr, prealloc[v])
+ nn := ir.Nod(ir.OAS, v.Name().Heapaddr, prealloc[v])
nn.SetColas(true)
nn = typecheck(nn, ctxStmt)
return walkstmt(nn)
}
if cl == ir.PPARAMOUT {
if isParamStackCopy(ln) {
- ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Param.Heapaddr, nil), ctxExpr), nil)
+ ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Heapaddr, nil), ctxExpr), nil)
}
rl = append(rl, ln)
}
for i, nl := range lhs.FieldSlice() {
nname := ir.AsNode(nl.Nname)
if isParamHeapCopy(nname) {
- nname = nname.Name().Param.Stackcopy
+ nname = nname.Name().Stackcopy
}
a := ir.Nod(ir.OAS, nname, rhs[i])
res[i] = convas(a, n.PtrInit())
}
if n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP {
- nn := ir.Nod(ir.ODEREF, n.Name().Param.Heapaddr, nil)
+ nn := ir.Nod(ir.ODEREF, n.Name().Heapaddr, nil)
nn = typecheck(nn, ctxExpr)
nn = walkexpr(nn, init)
nn.Left().MarkNonNil()
if n.Type().Elem().Width >= maxImplicitStackVarSize {
base.Fatalf("large ONEW with EscNone: %v", n)
}
- r := temp(n.Type().Elem())
+ r := ir.Node(temp(n.Type().Elem()))
r = ir.Nod(ir.OAS, r, nil) // zero temp
r = typecheck(r, ctxStmt)
init.Append(r)
// Any assignment to an lvalue that might cause a function call must be
// deferred until all the returned values have been read.
if fncall(l, r.Type) {
- tmp := temp(r.Type)
+ tmp := ir.Node(temp(r.Type))
tmp = typecheck(tmp, ctxExpr)
a := ir.Nod(ir.OAS, l, tmp)
a = convas(a, &mm)
return n
}
- q := temp(n.Type())
+ q := ir.Node(temp(n.Type()))
q = ir.Nod(ir.OAS, q, n)
q = typecheck(q, ctxStmt)
*early = append(*early, q)
continue
}
- if stackcopy := v.Name().Param.Stackcopy; stackcopy != nil {
+ if stackcopy := v.Name().Stackcopy; stackcopy != nil {
nn = append(nn, walkstmt(ir.Nod(ir.ODCL, v, nil)))
if stackcopy.Class() == ir.PPARAM {
nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, v, stackcopy), ctxStmt)))
func zeroResults() {
for _, f := range Curfn.Type().Results().Fields().Slice() {
v := ir.AsNode(f.Nname)
- if v != nil && v.Name().Param.Heapaddr != nil {
+ if v != nil && v.Name().Heapaddr != nil {
// The local which points to the return value is the
// thing that needs zeroing. This is already handled
// by a Needzero annotation in plive.go:livenessepilogue.
// I don't think the zeroing below matters.
// The stack return value will never be marked as live anywhere in the function.
// It is not written to until deferreturn returns.
- v = v.Name().Param.Stackcopy
+ v = v.Name().Stackcopy
}
// Zero the stack location containing f.
Curfn.Func().Enter.Append(ir.NodAt(Curfn.Pos(), ir.OAS, v, nil))
if v == nil {
continue
}
- if stackcopy := v.Name().Param.Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT {
+ if stackcopy := v.Name().Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT {
nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, stackcopy, v), ctxStmt)))
}
}
fn := syslook("memmove")
fn = substArgTypes(fn, nl.Type().Elem(), nl.Type().Elem())
- nwid := temp(types.Types[types.TUINTPTR])
+ nwid := ir.Node(temp(types.Types[types.TUINTPTR]))
setwid := ir.Nod(ir.OAS, nwid, conv(nlen, types.Types[types.TUINTPTR]))
ne.PtrBody().Append(setwid)
nwid = ir.Nod(ir.OMUL, nwid, nodintconst(nl.Type().Elem().Width))
--- /dev/null
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ir
+
+import (
+ "cmd/compile/internal/types"
+)
+
+// A miniStmt is a miniNode with extra fields common to expressions.
+// TODO(rsc): Once we are sure about the contents, compact the bools
+// into a bit field and leave extra bits available for implementations
+// embedding miniExpr. Right now there are ~60 unused bits sitting here.
+type miniExpr struct {
+ miniNode
+ typ *types.Type
+ init Nodes // TODO(rsc): Don't require every Node to have an init
+ opt interface{} // TODO(rsc): Don't require every Node to have an opt?
+ flags bitset8
+}
+
+const (
+ miniExprHasCall = 1 << iota
+ miniExprImplicit
+ miniExprNonNil
+ miniExprTransient
+ miniExprBounded
+)
+
+func (n *miniExpr) Type() *types.Type { return n.typ }
+func (n *miniExpr) SetType(x *types.Type) { n.typ = x }
+func (n *miniExpr) Opt() interface{} { return n.opt }
+func (n *miniExpr) SetOpt(x interface{}) { n.opt = x }
+func (n *miniExpr) HasCall() bool { return n.flags&miniExprHasCall != 0 }
+func (n *miniExpr) SetHasCall(b bool) { n.flags.set(miniExprHasCall, b) }
+func (n *miniExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
+func (n *miniExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
+func (n *miniExpr) NonNil() bool { return n.flags&miniExprNonNil != 0 }
+func (n *miniExpr) MarkNonNil() { n.flags |= miniExprNonNil }
+func (n *miniExpr) Transient() bool { return n.flags&miniExprTransient != 0 }
+func (n *miniExpr) SetTransient(b bool) { n.flags.set(miniExprTransient, b) }
+func (n *miniExpr) Bounded() bool { return n.flags&miniExprBounded != 0 }
+func (n *miniExpr) SetBounded(b bool) { n.flags.set(miniExprBounded, b) }
+func (n *miniExpr) Init() Nodes { return n.init }
+func (n *miniExpr) PtrInit() *Nodes { return &n.init }
+func (n *miniExpr) SetInit(x Nodes) { n.init = x }
} else {
mode.Fprintf(s, "%v%j", n.Op(), n)
}
- if recur && n.Type() == nil && n.Name() != nil && n.Name().Param != nil && n.Name().Param.Ntype != nil {
+ if recur && n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
indent(s)
- mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Param.Ntype)
+ mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Ntype)
}
case OASOP:
case OTYPE:
mode.Fprintf(s, "%v %v%j type=%v", n.Op(), n.Sym(), n, n.Type())
- if recur && n.Type() == nil && n.Name() != nil && n.Name().Param != nil && n.Name().Param.Ntype != nil {
+ if recur && n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
indent(s)
- mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Param.Ntype)
+ mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Ntype)
}
}
func (n *miniNode) Func() *Func { return nil }
func (n *miniNode) SetFunc(*Func) { panic(n.no("SetFunc")) }
func (n *miniNode) Name() *Name { return nil }
-func (n *miniNode) SetName(*Name) { panic(n.no("SetName")) }
func (n *miniNode) Sym() *types.Sym { return nil }
func (n *miniNode) SetSym(*types.Sym) { panic(n.no("SetSym")) }
func (n *miniNode) Offset() int64 { return types.BADWIDTH }
func (n *miniNode) ResetAux() { panic(n.no("ResetAux")) }
func (n *miniNode) HasBreak() bool { panic(n.no("HasBreak")) }
func (n *miniNode) SetHasBreak(bool) { panic(n.no("SetHasBreak")) }
-func (n *miniNode) HasVal() bool { return false }
func (n *miniNode) Val() constant.Value { panic(n.no("Val")) }
func (n *miniNode) SetVal(v constant.Value) { panic(n.no("SetVal")) }
func (n *miniNode) Int64Val() int64 { panic(n.no("Int64Val")) }
// Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
type Name struct {
+ miniExpr
+ subOp Op // uint8
+ class Class // uint8
+ flags bitset16
+ pragma PragmaFlag // int16
+ sym *types.Sym
+ typ *types.Type
+ fn *Func
+ offset int64
+ val constant.Value
+ orig Node
+ embedFiles *[]string // list of embedded files, for ONAME var
+
PkgName *PkgName // real package for import . names
// For a local variable (not param) or extern, the initializing assignment (OAS or OAS2).
// For a closure var, the ONAME node of the outer captured variable
Defn Node
// The ODCLFUNC node (for a static function/method or a closure) in which
// local variable or param is declared.
- Curfn Node
- Param *Param // additional fields for ONAME, OTYPE
- Decldepth int32 // declaration loop depth, increased for every loop or label
+ Curfn Node
// Unique number for ONAME nodes within a function. Function outputs
// (results) are numbered starting at one, followed by function inputs
// (parameters), and then local variables. Vargen is used to distinguish
// local variables/params with the same name.
- Vargen int32
- flags bitset16
-}
+ Vargen int32
+ Decldepth int32 // declaration loop depth, increased for every loop or label
-type Param struct {
Ntype Node
- Heapaddr Node // temp holding heap address of param
+ Heapaddr *Name // temp holding heap address of param
// ONAME PAUTOHEAP
- Stackcopy Node // the PPARAM/PPARAMOUT on-stack slot (moved func params only)
+ Stackcopy *Name // the PPARAM/PPARAMOUT on-stack slot (moved func params only)
// ONAME closure linkage
// Consider:
//
// Because of the sharding of pieces of the node, x.Defn means x.Name.Defn
// and x.Innermost/Outer means x.Name.Param.Innermost/Outer.
- Innermost Node
- Outer Node
-
- // OTYPE & ONAME //go:embed info,
- // sharing storage to reduce gc.Param size.
- // Extra is nil, or else *Extra is a *paramType or an *embedFileList.
- Extra *interface{}
+ Innermost *Name
+ Outer *Name
}
// NewNameAt returns a new ONAME Node associated with symbol s at position pos.
// The caller is responsible for setting n.Name.Curfn.
-func NewNameAt(pos src.XPos, s *types.Sym) Node {
- if s == nil {
- base.Fatalf("newnamel nil")
+func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
+ if sym == nil {
+ base.Fatalf("NewNameAt nil")
}
+ return newNameAt(pos, sym)
+}
- var x struct {
- n node
- m Name
- p Param
- }
- n := &x.n
- n.SetName(&x.m)
- n.Name().Param = &x.p
-
- n.SetOp(ONAME)
- n.SetPos(pos)
- n.SetOrig(n)
-
- n.SetSym(s)
+// newNameAt is like NewNameAt but allows sym == nil.
+func newNameAt(pos src.XPos, sym *types.Sym) *Name {
+ n := new(Name)
+ n.op = ONAME
+ n.pos = pos
+ n.orig = n
+ n.sym = sym
return n
}
-type paramType struct {
- flag PragmaFlag
- alias bool
+func (n *Name) String() string { return fmt.Sprint(n) }
+func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *Name) RawCopy() Node { c := *n; return &c }
+func (n *Name) Name() *Name { return n }
+func (n *Name) Sym() *types.Sym { return n.sym }
+func (n *Name) SetSym(x *types.Sym) { n.sym = x }
+func (n *Name) Orig() Node { return n.orig }
+func (n *Name) SetOrig(x Node) { n.orig = x }
+func (n *Name) SubOp() Op { return n.subOp }
+func (n *Name) SetSubOp(x Op) { n.subOp = x }
+func (n *Name) Class() Class { return n.class }
+func (n *Name) SetClass(x Class) { n.class = x }
+func (n *Name) Func() *Func { return n.fn }
+func (n *Name) SetFunc(x *Func) { n.fn = x }
+func (n *Name) Offset() int64 { return n.offset }
+func (n *Name) SetOffset(x int64) { n.offset = x }
+func (n *Name) Iota() int64 { return n.offset }
+func (n *Name) SetIota(x int64) { n.offset = x }
+
+func (n *Name) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OLITERAL, ONONAME, ONAME, OTYPE, OIOTA:
+ n.op = op
+ }
}
// Pragma returns the PragmaFlag for p, which must be for an OTYPE.
-func (p *Param) Pragma() PragmaFlag {
- if p.Extra == nil {
- return 0
- }
- return (*p.Extra).(*paramType).flag
-}
+func (n *Name) Pragma() PragmaFlag { return n.pragma }
// SetPragma sets the PragmaFlag for p, which must be for an OTYPE.
-func (p *Param) SetPragma(flag PragmaFlag) {
- if p.Extra == nil {
- if flag == 0 {
- return
- }
- p.Extra = new(interface{})
- *p.Extra = ¶mType{flag: flag}
- return
- }
- (*p.Extra).(*paramType).flag = flag
-}
+func (n *Name) SetPragma(flag PragmaFlag) { n.pragma = flag }
// Alias reports whether p, which must be for an OTYPE, is a type alias.
-func (p *Param) Alias() bool {
- if p.Extra == nil {
- return false
- }
- t, ok := (*p.Extra).(*paramType)
- if !ok {
- return false
- }
- return t.alias
-}
+func (n *Name) Alias() bool { return n.flags&nameAlias != 0 }
// SetAlias sets whether p, which must be for an OTYPE, is a type alias.
-func (p *Param) SetAlias(alias bool) {
- if p.Extra == nil {
- if !alias {
- return
- }
- p.Extra = new(interface{})
- *p.Extra = ¶mType{alias: alias}
- return
- }
- (*p.Extra).(*paramType).alias = alias
-}
-
-type embedFileList []string
+func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) }
// EmbedFiles returns the list of embedded files for p,
// which must be for an ONAME var.
-func (p *Param) EmbedFiles() []string {
- if p.Extra == nil {
+func (n *Name) EmbedFiles() []string {
+ if n.embedFiles == nil {
return nil
}
- return *(*p.Extra).(*embedFileList)
+ return *n.embedFiles
}
// SetEmbedFiles sets the list of embedded files for p,
// which must be for an ONAME var.
-func (p *Param) SetEmbedFiles(list []string) {
- if p.Extra == nil {
- if len(list) == 0 {
- return
- }
- f := embedFileList(list)
- p.Extra = new(interface{})
- *p.Extra = &f
+func (n *Name) SetEmbedFiles(list []string) {
+ if n.embedFiles == nil && list == nil {
return
}
- *(*p.Extra).(*embedFileList) = list
+ if n.embedFiles == nil {
+ n.embedFiles = new([]string)
+ }
+ *n.embedFiles = list
}
const (
nameInlLocal // PAUTO created by inliner, derived from callee local
nameOpenDeferSlot // if temporary var storing info for open-coded defers
nameLibfuzzerExtraCounter // if PEXTERN should be assigned to __libfuzzer_extra_counters section
+ nameIsDDD // is function argument a ...
+ nameAlias // is type name an alias
)
func (n *Name) Captured() bool { return n.flags&nameCaptured != 0 }
func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 }
func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 }
func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 }
+func (n *Name) IsDDD() bool { return n.flags&nameIsDDD != 0 }
func (n *Name) SetCaptured(b bool) { n.flags.set(nameCaptured, b) }
-func (n *Name) SetReadonly(b bool) { n.flags.set(nameReadonly, b) }
+func (n *Name) setReadonly(b bool) { n.flags.set(nameReadonly, b) }
func (n *Name) SetByval(b bool) { n.flags.set(nameByval, b) }
func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) }
func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) }
func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) }
func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) }
func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) }
+func (n *Name) SetIsDDD(b bool) { n.flags.set(nameIsDDD, b) }
// MarkReadonly indicates that n is an ONAME with readonly contents.
-func (n *node) MarkReadonly() {
+func (n *Name) MarkReadonly() {
if n.Op() != ONAME {
base.Fatalf("Node.MarkReadonly %v", n.Op())
}
- n.Name().SetReadonly(true)
+ n.Name().setReadonly(true)
// Mark the linksym as readonly immediately
// so that the SSA backend can use this information.
// It will be overridden later during dumpglobls.
}
// Val returns the constant.Value for the node.
-func (n *node) Val() constant.Value {
- if !n.HasVal() {
+func (n *Name) Val() constant.Value {
+ if n.val == nil {
return constant.MakeUnknown()
}
- return *n.e.(*constant.Value)
+ return n.val
}
// SetVal sets the constant.Value for the node,
// which must not have been used with SetOpt.
-func (n *node) SetVal(v constant.Value) {
- if n.hasOpt() {
- base.Flag.LowerH = 1
- Dump("have Opt", n)
- base.Fatalf("have Opt")
- }
- if n.Op() == OLITERAL {
- AssertValidTypeForConst(n.Type(), v)
+func (n *Name) SetVal(v constant.Value) {
+ if n.op != OLITERAL {
+ panic(n.no("SetVal"))
}
- n.setHasVal(true)
- n.e = &v
+ AssertValidTypeForConst(n.Type(), v)
+ n.val = v
}
// Int64Val returns n as an int64.
// n must be an integer or rune constant.
-func (n *node) Int64Val() int64 {
+func (n *Name) Int64Val() int64 {
if !IsConst(n, constant.Int) {
base.Fatalf("Int64Val(%v)", n)
}
}
// CanInt64 reports whether it is safe to call Int64Val() on n.
-func (n *node) CanInt64() bool {
+func (n *Name) CanInt64() bool {
if !IsConst(n, constant.Int) {
return false
}
// Uint64Val returns n as an uint64.
// n must be an integer or rune constant.
-func (n *node) Uint64Val() uint64 {
+func (n *Name) Uint64Val() uint64 {
if !IsConst(n, constant.Int) {
base.Fatalf("Uint64Val(%v)", n)
}
// BoolVal returns n as a bool.
// n must be a boolean constant.
-func (n *node) BoolVal() bool {
+func (n *Name) BoolVal() bool {
if !IsConst(n, constant.Bool) {
base.Fatalf("BoolVal(%v)", n)
}
// StringVal returns the value of a literal string Node as a string.
// n must be a string constant.
-func (n *node) StringVal() string {
+func (n *Name) StringVal() string {
if !IsConst(n, constant.String) {
base.Fatalf("StringVal(%v)", n)
}
Func() *Func
SetFunc(x *Func)
Name() *Name
- SetName(x *Name)
Sym() *types.Sym
SetSym(x *types.Sym)
Offset() int64
SetHasBreak(x bool)
MarkReadonly()
Val() constant.Value
- HasVal() bool
SetVal(v constant.Value)
Int64Val() int64
Uint64Val() uint64
// func
fn *Func
- // ONAME, OTYPE, OPACK, OLABEL, some OLITERAL
- name *Name
-
- sym *types.Sym // various
- e interface{} // Opt or Val, see methods below
+ sym *types.Sym // various
+ opt interface{}
// Various. Usually an offset into a struct. For example:
// - ONAME nodes that refer to local variables use it to identify their stack frame position.
func (n *node) SetType(x *types.Type) { n.typ = x }
func (n *node) Func() *Func { return n.fn }
func (n *node) SetFunc(x *Func) { n.fn = x }
-func (n *node) Name() *Name { return n.name }
-func (n *node) SetName(x *Name) { n.name = x }
+func (n *node) Name() *Name { return nil }
func (n *node) Sym() *types.Sym { return n.sym }
func (n *node) SetSym(x *types.Sym) { n.sym = x }
func (n *node) Pos() src.XPos { return n.pos }
func (n *node) Rlist() Nodes { return n.rlist }
func (n *node) SetRlist(x Nodes) { n.rlist = x }
func (n *node) PtrRlist() *Nodes { return &n.rlist }
+func (n *node) MarkReadonly() { panic("node.MarkReadOnly") }
+func (n *node) Val() constant.Value { panic("node.Val") }
+func (n *node) SetVal(constant.Value) { panic("node.SetVal") }
+func (n *node) Int64Val() int64 { panic("node.Int64Val") }
+func (n *node) CanInt64() bool { return false }
+func (n *node) Uint64Val() uint64 { panic("node.Uint64Val") }
+func (n *node) BoolVal() bool { panic("node.BoolVal") }
+func (n *node) StringVal() string { panic("node.StringVal") }
func (n *node) SetOp(op Op) {
if !okForNod[op] {
_, nodeBounded // bounds check unnecessary
_, nodeHasCall // expression contains a function call
_, nodeLikely // if statement condition likely
- _, nodeHasVal // node.E contains a Val
- _, nodeHasOpt // node.E contains an Opt
_, nodeEmbedded // ODCLFIELD embedded type
)
func (n *node) Bounded() bool { return n.flags&nodeBounded != 0 }
func (n *node) HasCall() bool { return n.flags&nodeHasCall != 0 }
func (n *node) Likely() bool { return n.flags&nodeLikely != 0 }
-func (n *node) HasVal() bool { return n.flags&nodeHasVal != 0 }
-func (n *node) hasOpt() bool { return n.flags&nodeHasOpt != 0 }
func (n *node) Embedded() bool { return n.flags&nodeEmbedded != 0 }
func (n *node) SetClass(b Class) { n.flags.set3(nodeClass, uint8(b)) }
func (n *node) SetTransient(b bool) { n.flags.set(nodeTransient, b) }
func (n *node) SetHasCall(b bool) { n.flags.set(nodeHasCall, b) }
func (n *node) SetLikely(b bool) { n.flags.set(nodeLikely, b) }
-func (n *node) setHasVal(b bool) { n.flags.set(nodeHasVal, b) }
-func (n *node) setHasOpt(b bool) { n.flags.set(nodeHasOpt, b) }
func (n *node) SetEmbedded(b bool) { n.flags.set(nodeEmbedded, b) }
// MarkNonNil marks a pointer n as being guaranteed non-nil,
// Opt returns the optimizer data for the node.
func (n *node) Opt() interface{} {
- if !n.hasOpt() {
- return nil
- }
- return n.e
+ return n.opt
}
// SetOpt sets the optimizer data for the node, which must not have been used with SetVal.
// SetOpt(nil) is ignored for Vals to simplify call sites that are clearing Opts.
func (n *node) SetOpt(x interface{}) {
- if x == nil {
- if n.hasOpt() {
- n.setHasOpt(false)
- n.e = nil
- }
- return
- }
- if n.HasVal() {
- base.Flag.LowerH = 1
- Dump("have Val", n)
- base.Fatalf("have Val")
- }
- n.setHasOpt(true)
- n.e = x
+ n.opt = x
}
func (n *node) Iota() int64 {
return NewEmptyStmt(pos)
case OBREAK, OCONTINUE, OFALL, OGOTO:
return NewBranchStmt(pos, op, nil)
+ case OLITERAL, OTYPE, OIOTA:
+ n := newNameAt(pos, nil)
+ n.SetOp(op)
+ return n
case OLABEL:
return NewLabelStmt(pos, nil)
default:
OINDEXMAP: true,
OINLCALL: true,
OINLMARK: true,
- OIOTA: true,
OITAB: true,
OKEY: true,
OLABEL: true,
OLE: true,
OLEN: true,
- OLITERAL: true,
OLSH: true,
OLT: true,
OMAKE: true,
OMETHEXPR: true,
OMOD: true,
OMUL: true,
- ONAME: true,
ONE: true,
ONEG: true,
ONEW: true,
ONEWOBJ: true,
ONIL: true,
- ONONAME: true,
ONOT: true,
OOFFSETOF: true,
OOR: true,
OTINTER: true,
OTMAP: true,
OTSTRUCT: true,
- OTYPE: true,
+ OTYPE: true, // TODO: Remove once setTypeNode is gone.
OTYPESW: true,
OVARDEF: true,
OVARKILL: true,
_64bit uintptr // size on 64bit platforms
}{
{Func{}, 152, 280},
- {Name{}, 36, 64},
- {Param{}, 44, 88},
- {node{}, 88, 152},
+ {Name{}, 132, 232},
+ {node{}, 84, 144},
}
for _, tt := range tests {