]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/internal/obj/link.go
[dev.typeparams] all: merge dev.regabi (7e0a81d) into dev.typeparams
[gostls13.git] / src / cmd / internal / obj / link.go
index 977c5c3303321ae17fce0ec0c90b6162bc4b9e0e..35cb53cbf6cc83dcdccdc2a7df79e61d300929b0 100644 (file)
@@ -766,6 +766,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 {
@@ -796,6 +807,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
@@ -844,6 +856,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