aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/link.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj/link.go')
-rw-r--r--src/cmd/internal/obj/link.go137
1 files changed, 105 insertions, 32 deletions
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 8c8ff587ff..a48db3bdc8 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -39,6 +39,7 @@ import (
"cmd/internal/sys"
"fmt"
"sync"
+ "sync/atomic"
)
// An Addr is an argument to an instruction.
@@ -250,6 +251,12 @@ func (a *Addr) SetTarget(t *Prog) {
a.Val = t
}
+func (a *Addr) SetConst(v int64) {
+ a.Sym = nil
+ a.Type = TYPE_CONST
+ a.Offset = v
+}
+
// Prog describes a single machine instruction.
//
// The general instruction form is:
@@ -447,6 +454,7 @@ type FuncInfo struct {
Locals int32
Align int32
FuncID objabi.FuncID
+ FuncFlag objabi.FuncFlag
Text *Prog
Autot map[*LSym]struct{}
Pcln Pcln
@@ -612,10 +620,6 @@ const (
// target of an inline during compilation
AttrWasInlined
- // TopFrame means that this function is an entry point and unwinders should not
- // keep unwinding beyond this frame.
- AttrTopFrame
-
// Indexed indicates this symbol has been assigned with an index (when using the
// new object file format).
AttrIndexed
@@ -629,6 +633,10 @@ const (
// ContentAddressable indicates this is a content-addressable symbol.
AttrContentAddressable
+ // ABI wrapper is set for compiler-generated text symbols that
+ // convert between ABI0 and ABIInternal calling conventions.
+ AttrABIWrapper
+
// attrABIBase is the value at which the ABI is encoded in
// Attribute. This must be last; all bits after this are
// assumed to be an ABI value.
@@ -637,36 +645,51 @@ const (
attrABIBase
)
-func (a Attribute) DuplicateOK() bool { return a&AttrDuplicateOK != 0 }
-func (a Attribute) MakeTypelink() bool { return a&AttrMakeTypelink != 0 }
-func (a Attribute) CFunc() bool { return a&AttrCFunc != 0 }
-func (a Attribute) NoSplit() bool { return a&AttrNoSplit != 0 }
-func (a Attribute) Leaf() bool { return a&AttrLeaf != 0 }
-func (a Attribute) OnList() bool { return a&AttrOnList != 0 }
-func (a Attribute) ReflectMethod() bool { return a&AttrReflectMethod != 0 }
-func (a Attribute) Local() bool { return a&AttrLocal != 0 }
-func (a Attribute) Wrapper() bool { return a&AttrWrapper != 0 }
-func (a Attribute) NeedCtxt() bool { return a&AttrNeedCtxt != 0 }
-func (a Attribute) NoFrame() bool { return a&AttrNoFrame != 0 }
-func (a Attribute) Static() bool { return a&AttrStatic != 0 }
-func (a Attribute) WasInlined() bool { return a&AttrWasInlined != 0 }
-func (a Attribute) TopFrame() bool { return a&AttrTopFrame != 0 }
-func (a Attribute) Indexed() bool { return a&AttrIndexed != 0 }
-func (a Attribute) UsedInIface() bool { return a&AttrUsedInIface != 0 }
-func (a Attribute) ContentAddressable() bool { return a&AttrContentAddressable != 0 }
+func (a *Attribute) load() Attribute { return Attribute(atomic.LoadUint32((*uint32)(a))) }
+
+func (a *Attribute) DuplicateOK() bool { return a.load()&AttrDuplicateOK != 0 }
+func (a *Attribute) MakeTypelink() bool { return a.load()&AttrMakeTypelink != 0 }
+func (a *Attribute) CFunc() bool { return a.load()&AttrCFunc != 0 }
+func (a *Attribute) NoSplit() bool { return a.load()&AttrNoSplit != 0 }
+func (a *Attribute) Leaf() bool { return a.load()&AttrLeaf != 0 }
+func (a *Attribute) OnList() bool { return a.load()&AttrOnList != 0 }
+func (a *Attribute) ReflectMethod() bool { return a.load()&AttrReflectMethod != 0 }
+func (a *Attribute) Local() bool { return a.load()&AttrLocal != 0 }
+func (a *Attribute) Wrapper() bool { return a.load()&AttrWrapper != 0 }
+func (a *Attribute) NeedCtxt() bool { return a.load()&AttrNeedCtxt != 0 }
+func (a *Attribute) NoFrame() bool { return a.load()&AttrNoFrame != 0 }
+func (a *Attribute) Static() bool { return a.load()&AttrStatic != 0 }
+func (a *Attribute) WasInlined() bool { return a.load()&AttrWasInlined != 0 }
+func (a *Attribute) Indexed() bool { return a.load()&AttrIndexed != 0 }
+func (a *Attribute) UsedInIface() bool { return a.load()&AttrUsedInIface != 0 }
+func (a *Attribute) ContentAddressable() bool { return a.load()&AttrContentAddressable != 0 }
+func (a *Attribute) ABIWrapper() bool { return a.load()&AttrABIWrapper != 0 }
func (a *Attribute) Set(flag Attribute, value bool) {
- if value {
- *a |= flag
- } else {
- *a &^= flag
+ for {
+ v0 := a.load()
+ v := v0
+ if value {
+ v |= flag
+ } else {
+ v &^= flag
+ }
+ if atomic.CompareAndSwapUint32((*uint32)(a), uint32(v0), uint32(v)) {
+ break
+ }
}
}
-func (a Attribute) ABI() ABI { return ABI(a / attrABIBase) }
+func (a *Attribute) ABI() ABI { return ABI(a.load() / attrABIBase) }
func (a *Attribute) SetABI(abi ABI) {
const mask = 1 // Only one ABI bit for now.
- *a = (*a &^ (mask * attrABIBase)) | Attribute(abi)*attrABIBase
+ for {
+ v0 := a.load()
+ v := (v0 &^ (mask * attrABIBase)) | Attribute(abi)*attrABIBase
+ if atomic.CompareAndSwapUint32((*uint32)(a), uint32(v0), uint32(v)) {
+ break
+ }
+ }
}
var textAttrStrings = [...]struct {
@@ -686,13 +709,13 @@ var textAttrStrings = [...]struct {
{bit: AttrNoFrame, s: "NOFRAME"},
{bit: AttrStatic, s: "STATIC"},
{bit: AttrWasInlined, s: ""},
- {bit: AttrTopFrame, s: "TOPFRAME"},
{bit: AttrIndexed, s: ""},
{bit: AttrContentAddressable, s: ""},
+ {bit: AttrABIWrapper, s: "ABIWRAPPER"},
}
-// TextAttrString formats a for printing in as part of a TEXT prog.
-func (a Attribute) TextAttrString() string {
+// String formats a for printing in as part of a TEXT prog.
+func (a Attribute) String() string {
var s string
for _, x := range textAttrStrings {
if a&x.bit != 0 {
@@ -718,13 +741,25 @@ func (a Attribute) TextAttrString() string {
return s
}
+// TextAttrString formats the symbol attributes for printing in as part of a TEXT prog.
+func (s *LSym) TextAttrString() string {
+ attr := s.Attribute.String()
+ if s.Func().FuncFlag&objabi.FuncFlag_TOPFRAME != 0 {
+ if attr != "" {
+ attr += "|"
+ }
+ attr += "TOPFRAME"
+ }
+ return attr
+}
+
func (s *LSym) String() string {
return s.Name
}
// The compiler needs *LSym to be assignable to cmd/compile/internal/ssa.Sym.
-func (s *LSym) CanBeAnSSASym() {
-}
+func (*LSym) CanBeAnSSASym() {}
+func (*LSym) CanBeAnSSAAux() {}
type Pcln struct {
// Aux symbols for pcln
@@ -754,6 +789,17 @@ type Auto struct {
Gotype *LSym
}
+// RegArg provides spill/fill information for a register-resident argument
+// to a function. These need spilling/filling in the safepoint/stackgrowth case.
+// At the time of fill/spill, the offset must be adjusted by the architecture-dependent
+// adjustment to hardware SP that occurs in a call instruction. E.g., for AMD64,
+// at Offset+8 because the return address was pushed.
+type RegArg struct {
+ Addr Addr
+ Reg int16
+ Spill, Unspill As
+}
+
// Link holds the context for writing object code from a compiler
// to be linker input or for reading that input into the linker.
type Link struct {
@@ -784,6 +830,7 @@ type Link struct {
DebugInfo func(fn *LSym, info *LSym, curfn interface{}) ([]dwarf.Scope, dwarf.InlCalls) // if non-nil, curfn is a *gc.Node
GenAbstractFunc func(fn *LSym)
Errors int
+ RegArgs []RegArg
InParallel bool // parallel backend phase in effect
UseBASEntries bool // use Base Address Selection Entries in location lists and PC ranges
@@ -832,6 +879,32 @@ func (ctxt *Link) Logf(format string, args ...interface{}) {
ctxt.Bso.Flush()
}
+func (ctxt *Link) SpillRegisterArgs(last *Prog, pa ProgAlloc) *Prog {
+ // Spill register args.
+ for _, ra := range ctxt.RegArgs {
+ spill := Appendp(last, pa)
+ spill.As = ra.Spill
+ spill.From.Type = TYPE_REG
+ spill.From.Reg = ra.Reg
+ spill.To = ra.Addr
+ last = spill
+ }
+ return last
+}
+
+func (ctxt *Link) UnspillRegisterArgs(last *Prog, pa ProgAlloc) *Prog {
+ // Unspill any spilled register args
+ for _, ra := range ctxt.RegArgs {
+ unspill := Appendp(last, pa)
+ unspill.As = ra.Unspill
+ unspill.From = ra.Addr
+ unspill.To.Type = TYPE_REG
+ unspill.To.Reg = ra.Reg
+ last = unspill
+ }
+ return last
+}
+
// The smallest possible offset from the hardware stack pointer to a local
// variable on the stack. Architectures that use a link register save its value
// on the stack in the function prologue and so always have a pointer between