"bytes"
"cmd/compile/internal/base"
"cmd/compile/internal/types"
+ "cmd/internal/obj"
"cmd/internal/src"
"fmt"
"go/constant"
return n
}
-// A NameOffsetExpr refers to an offset within a variable.
+// A NameOffsetExpr refers to an offset within a global variable.
// It is like a SelectorExpr but without the field name.
type NameOffsetExpr struct {
miniExpr
- Name_ *Name
+ Linksym *obj.LSym
Offset_ int64
}
+func NewLinksymOffsetExpr(pos src.XPos, lsym *obj.LSym, offset int64, typ *types.Type) *NameOffsetExpr {
+ n := &NameOffsetExpr{Linksym: lsym, Offset_: offset}
+ n.typ = typ
+ n.op = ONAMEOFFSET
+ return n
+}
+
func NewNameOffsetExpr(pos src.XPos, name *Name, offset int64, typ *types.Type) *NameOffsetExpr {
if name == nil || IsBlank(name) || !(name.Op() == ONAME && name.Class == PEXTERN) {
base.FatalfAt(pos, "cannot take offset of nil, blank name or non-global variable: %v", name)
}
- n := &NameOffsetExpr{Name_: name, Offset_: offset}
- n.typ = typ
- n.op = ONAMEOFFSET
- return n
+ return NewLinksymOffsetExpr(pos, name.Linksym(), offset, typ)
}
// A SelectorExpr is a selector expression X.Sel.
case ONAMEOFFSET:
n := n.(*NameOffsetExpr)
- fmt.Fprintf(s, "(%v)(%v@%d)", n.Type(), n.Name_, n.Offset_)
+ fmt.Fprintf(s, "(%v)(%s@%d)", n.Type(), n.Linksym.Name, n.Offset_)
case OTYPE:
if n.Type() == nil && n.Sym() != nil {
if doNodes(n.init, do) {
return true
}
- if n.Name_ != nil && do(n.Name_) {
- return true
- }
return false
}
func (n *NameOffsetExpr) editChildren(edit func(Node) Node) {
editNodes(n.init, edit)
- if n.Name_ != nil {
- n.Name_ = edit(n.Name_).(*Name)
- }
}
func (n *NilExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
if s.canSSA(n) {
return s.variable(n, n.Type())
}
- addr := s.addr(n)
- return s.load(n.Type(), addr)
+ return s.load(n.Type(), s.addr(n))
case ir.ONAMEOFFSET:
n := n.(*ir.NameOffsetExpr)
- if s.canSSAName(n.Name_) && TypeOK(n.Type()) {
- return s.variable(n, n.Type())
- }
- addr := s.addr(n)
- return s.load(n.Type(), addr)
+ return s.load(n.Type(), s.addr(n))
case ir.ONIL:
n := n.(*ir.NilExpr)
t := n.Type()
}
t := types.NewPtr(n.Type())
- var offset int64
+ linksymOffset := func(lsym *obj.LSym, offset int64) *ssa.Value {
+ v := s.entryNewValue1A(ssa.OpAddr, t, lsym, s.sb)
+ // TODO: Make OpAddr use AuxInt as well as Aux.
+ if offset != 0 {
+ v = s.entryNewValue1I(ssa.OpOffPtr, v.Type, offset, v)
+ }
+ return v
+ }
switch n.Op() {
case ir.ONAMEOFFSET:
no := n.(*ir.NameOffsetExpr)
- offset = no.Offset_
- n = no.Name_
- fallthrough
+ return linksymOffset(no.Linksym, no.Offset_)
case ir.ONAME:
n := n.(*ir.Name)
if n.Heapaddr != nil {
switch n.Class {
case ir.PEXTERN:
// global variable
- v := s.entryNewValue1A(ssa.OpAddr, t, n.Linksym(), s.sb)
- // TODO: Make OpAddr use AuxInt as well as Aux.
- if offset != 0 {
- v = s.entryNewValue1I(ssa.OpOffPtr, v.Type, offset, v)
- }
- return v
+ return linksymOffset(n.Linksym(), 0)
case ir.PPARAM:
// parameter slot
v := s.decladdrs[n]