}
nl := origConst(s[i], constant.MakeString(strings.Join(strs, "")))
- nl.SetOrig(nl) // it's bigger than just s[i]
+ nl.(ir.OrigNode).SetOrig(nl) // it's bigger than just s[i]
newList = append(newList, nl)
i = i2 - 1
} else {
orig := n
n = ir.NodAt(orig.Pos(), ir.OLITERAL, nil, nil)
- n.SetOrig(orig)
+ n.(ir.OrigNode).SetOrig(orig)
n.SetType(orig.Type())
n.SetVal(v)
return n
// temp will add it to the function declaration list automatically.
heapaddr := temp(types.NewPtr(n.Type()))
heapaddr.SetSym(lookup("&" + n.Sym().Name))
- heapaddr.Orig().SetSym(heapaddr.Sym())
+ ir.Orig(heapaddr).SetSym(heapaddr.Sym())
heapaddr.SetPos(n.Pos())
// Unset AutoTemp to persist the &foo variable name through SSA to
dowidth(t)
- return n.Orig()
+ return ir.Orig(n)
}
func temp(t *types.Type) ir.Node {
if !n.Type().HasNil() {
base.Fatalf("unexpected type for nil: %v", n.Type())
}
- if n.Orig() != nil && n.Orig() != n {
- w.expr(n.Orig())
+ if orig := ir.Orig(n); orig != nil && orig != n {
+ w.expr(orig)
break
}
w.op(ir.OLITERAL)
case ir.Node:
if n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT {
a.Name = obj.NAME_PARAM
- a.Sym = n.Orig().Sym().Linksym()
+ a.Sym = ir.Orig(n).Sym().Linksym()
a.Offset += n.Offset()
break
}
r.SetType(t)
r.SetTypecheck(1)
r.SetImplicit(true)
- r.SetOrig(n.Orig())
+ r.(ir.OrigNode).SetOrig(ir.Orig(n))
return r
}
checklvalue(n.Left(), "take the address of")
r := outervalue(n.Left())
if r.Op() == ir.ONAME {
- if r.Orig() != r {
+ if ir.Orig(r) != r {
base.Fatalf("found non-orig name node %v", r) // TODO(mdempsky): What does this mean?
}
r.Name().SetAddrtaken(true)
// Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...).
// Save n as n.Orig for fmt.go.
- if n.Orig() == n {
- n.SetOrig(ir.SepCopy(n))
+ if ir.Orig(n) == n {
+ n.(ir.OrigNode).SetOrig(ir.SepCopy(n))
}
as := ir.Nod(ir.OAS2, nil, nil)
ir.ONEW,
ir.OREAL,
ir.OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof
- if n.Left().Orig() != nil && n.Left().Orig().Op() == ir.OCONV {
+ if orig := ir.Orig(n.Left()); orig.Op() == ir.OCONV {
break
}
base.ErrorfAt(n.Pos(), "%s discards result of %v", what, n.Left())
}
// Save original node (including n.Right)
- n.SetOrig(ir.Copy(n))
+ n.(ir.OrigNode).SetOrig(ir.Copy(n))
setlineno(n.Right())
case OLITERAL: // this is a bit of a mess
if mode == FErr {
- if n.Orig() != nil && n.Orig() != n {
- exprFmt(n.Orig(), s, prec, mode)
+ if orig := Orig(n); orig != nil && orig != n {
+ exprFmt(orig, s, prec, mode)
return
}
if n.Sym() != nil {
// We almost always want the original.
// TODO(gri) Why the special case for OLITERAL?
- if n.Op() != OLITERAL && n.Orig() != nil {
- n = n.Orig()
+ if n.Op() != OLITERAL && Orig(n) != nil {
+ n = Orig(n)
}
if flag&FmtLong != 0 && t != nil {
// Abstract graph structure, for generic traversals.
Op() Op
SetOp(x Op)
- Orig() Node
- SetOrig(x Node)
SubOp() Op
SetSubOp(x Op)
Left() Node
return ©
}
+// A Node may implement the Orig and SetOrig method to
+// maintain a pointer to the "unrewritten" form of a Node.
+// If a Node does not implement OrigNode, it is its own Orig.
+//
+// Note that both SepCopy and Copy have definitions compatible
+// with a Node that does not implement OrigNode: such a Node
+// is its own Orig, and in that case, that's what both want to return
+// anyway (SepCopy unconditionally, and Copy only when the input
+// is its own Orig as well, but if the output does not implement
+// OrigNode, then neither does the input, making the condition true).
+type OrigNode interface {
+ Node
+ Orig() Node
+ SetOrig(Node)
+}
+
+func Orig(n Node) Node {
+ if n, ok := n.(OrigNode); ok {
+ o := n.Orig()
+ if o == nil {
+ Dump("Orig nil", n)
+ base.Fatalf("Orig returned nil")
+ }
+ return o
+ }
+ return n
+}
+
// sepcopy returns a separate shallow copy of n, with the copy's
// Orig pointing to itself.
func SepCopy(n Node) Node {
n = n.RawCopy()
- n.SetOrig(n)
+ if n, ok := n.(OrigNode); ok {
+ n.SetOrig(n)
+ }
return n
}
// messages; see issues #26855, #27765).
func Copy(n Node) Node {
copy := n.RawCopy()
- if n.Orig() == n {
- copy.SetOrig(copy)
+ if n, ok := n.(OrigNode); ok && n.Orig() == n {
+ copy.(OrigNode).SetOrig(copy)
}
return copy
}
func IsNil(n Node) bool {
// Check n.Orig because constant propagation may produce typed nil constants,
// which don't exist in the Go spec.
- return n.Orig().Op() == ONIL
+ return Orig(n).Op() == ONIL
}
func IsBlank(n Node) bool {
}
func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
- var n Node
+ var n *node
switch op {
case ODCLFUNC:
var x struct {