mirror of
https://github.com/golang/go.git
synced 2025-05-23 16:31:27 +00:00
internal/sys: add LR and fixed frame size to sys.Arch
Storing this information in the Arch eliminates some code duplication between the compiler and linker. This information is entirely determined by the Arch, so the current approach of attaching it to an entire Ctxt is a little silly. This will also make it easier to use this information from tests. The next CL will be a rote refactoring to eliminate the Ctxt.FixedFrameSize methods. Change-Id: I315c524fa66a0ea99f63ae5a2a6fdc367d843bad Reviewed-on: https://go-review.googlesource.com/c/go/+/400818 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
caa46312ee
commit
8af7fac5a1
@ -989,16 +989,7 @@ func (fi *FuncInfo) UnspillRegisterArgs(last *Prog, pa ProgAlloc) *Prog {
|
|||||||
// on the stack in the function prologue and so always have a pointer between
|
// on the stack in the function prologue and so always have a pointer between
|
||||||
// the hardware stack pointer and the local variable area.
|
// the hardware stack pointer and the local variable area.
|
||||||
func (ctxt *Link) FixedFrameSize() int64 {
|
func (ctxt *Link) FixedFrameSize() int64 {
|
||||||
switch ctxt.Arch.Family {
|
return ctxt.Arch.FixedFrameSize
|
||||||
case sys.AMD64, sys.I386, sys.Wasm:
|
|
||||||
return 0
|
|
||||||
case sys.PPC64:
|
|
||||||
// PIC code on ppc64le requires 32 bytes of stack, and it's easier to
|
|
||||||
// just use that much stack always on ppc64x.
|
|
||||||
return int64(4 * ctxt.Arch.PtrSize)
|
|
||||||
default:
|
|
||||||
return int64(ctxt.Arch.PtrSize)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinkArch is the definition of a single architecture.
|
// LinkArch is the definition of a single architecture.
|
||||||
|
@ -56,6 +56,18 @@ type Arch struct {
|
|||||||
// CanJumpTable reports whether the backend can handle
|
// CanJumpTable reports whether the backend can handle
|
||||||
// compiling a jump table.
|
// compiling a jump table.
|
||||||
CanJumpTable bool
|
CanJumpTable bool
|
||||||
|
|
||||||
|
// HasLR indicates that this architecture uses a link register
|
||||||
|
// for calls.
|
||||||
|
HasLR bool
|
||||||
|
|
||||||
|
// FixedFrameSize is 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 the hardware stack pointer and the local
|
||||||
|
// variable area.
|
||||||
|
FixedFrameSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// InFamily reports whether a is a member of any of the specified
|
// InFamily reports whether a is a member of any of the specified
|
||||||
@ -70,103 +82,121 @@ func (a *Arch) InFamily(xs ...ArchFamily) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var Arch386 = &Arch{
|
var Arch386 = &Arch{
|
||||||
Name: "386",
|
Name: "386",
|
||||||
Family: I386,
|
Family: I386,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 4,
|
PtrSize: 4,
|
||||||
RegSize: 4,
|
RegSize: 4,
|
||||||
MinLC: 1,
|
MinLC: 1,
|
||||||
Alignment: 1,
|
Alignment: 1,
|
||||||
CanMergeLoads: true,
|
CanMergeLoads: true,
|
||||||
|
HasLR: false,
|
||||||
|
FixedFrameSize: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchAMD64 = &Arch{
|
var ArchAMD64 = &Arch{
|
||||||
Name: "amd64",
|
Name: "amd64",
|
||||||
Family: AMD64,
|
Family: AMD64,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 1,
|
MinLC: 1,
|
||||||
Alignment: 1,
|
Alignment: 1,
|
||||||
CanMergeLoads: true,
|
CanMergeLoads: true,
|
||||||
CanJumpTable: true,
|
CanJumpTable: true,
|
||||||
|
HasLR: false,
|
||||||
|
FixedFrameSize: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchARM = &Arch{
|
var ArchARM = &Arch{
|
||||||
Name: "arm",
|
Name: "arm",
|
||||||
Family: ARM,
|
Family: ARM,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 4,
|
PtrSize: 4,
|
||||||
RegSize: 4,
|
RegSize: 4,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 4, // TODO: just for arm5?
|
Alignment: 4, // TODO: just for arm5?
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 4, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchARM64 = &Arch{
|
var ArchARM64 = &Arch{
|
||||||
Name: "arm64",
|
Name: "arm64",
|
||||||
Family: ARM64,
|
Family: ARM64,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 1,
|
Alignment: 1,
|
||||||
CanMergeLoads: true,
|
CanMergeLoads: true,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 8, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchLoong64 = &Arch{
|
var ArchLoong64 = &Arch{
|
||||||
Name: "loong64",
|
Name: "loong64",
|
||||||
Family: Loong64,
|
Family: Loong64,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 8, // Unaligned accesses are not guaranteed to be fast
|
Alignment: 8, // Unaligned accesses are not guaranteed to be fast
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 8, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchMIPS = &Arch{
|
var ArchMIPS = &Arch{
|
||||||
Name: "mips",
|
Name: "mips",
|
||||||
Family: MIPS,
|
Family: MIPS,
|
||||||
ByteOrder: binary.BigEndian,
|
ByteOrder: binary.BigEndian,
|
||||||
PtrSize: 4,
|
PtrSize: 4,
|
||||||
RegSize: 4,
|
RegSize: 4,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 4,
|
Alignment: 4,
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 4, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchMIPSLE = &Arch{
|
var ArchMIPSLE = &Arch{
|
||||||
Name: "mipsle",
|
Name: "mipsle",
|
||||||
Family: MIPS,
|
Family: MIPS,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 4,
|
PtrSize: 4,
|
||||||
RegSize: 4,
|
RegSize: 4,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 4,
|
Alignment: 4,
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 4, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchMIPS64 = &Arch{
|
var ArchMIPS64 = &Arch{
|
||||||
Name: "mips64",
|
Name: "mips64",
|
||||||
Family: MIPS64,
|
Family: MIPS64,
|
||||||
ByteOrder: binary.BigEndian,
|
ByteOrder: binary.BigEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 8,
|
Alignment: 8,
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 8, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchMIPS64LE = &Arch{
|
var ArchMIPS64LE = &Arch{
|
||||||
Name: "mips64le",
|
Name: "mips64le",
|
||||||
Family: MIPS64,
|
Family: MIPS64,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 8,
|
Alignment: 8,
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 8, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchPPC64 = &Arch{
|
var ArchPPC64 = &Arch{
|
||||||
@ -178,50 +208,62 @@ var ArchPPC64 = &Arch{
|
|||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 1,
|
Alignment: 1,
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: true,
|
||||||
|
// PIC code on ppc64le requires 32 bytes of stack, and it's
|
||||||
|
// easier to just use that much stack always.
|
||||||
|
FixedFrameSize: 4 * 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchPPC64LE = &Arch{
|
var ArchPPC64LE = &Arch{
|
||||||
Name: "ppc64le",
|
Name: "ppc64le",
|
||||||
Family: PPC64,
|
Family: PPC64,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 1,
|
Alignment: 1,
|
||||||
CanMergeLoads: true,
|
CanMergeLoads: true,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 4 * 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchRISCV64 = &Arch{
|
var ArchRISCV64 = &Arch{
|
||||||
Name: "riscv64",
|
Name: "riscv64",
|
||||||
Family: RISCV64,
|
Family: RISCV64,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 4,
|
MinLC: 4,
|
||||||
Alignment: 8, // riscv unaligned loads work, but are really slow (trap + simulated by OS)
|
Alignment: 8, // riscv unaligned loads work, but are really slow (trap + simulated by OS)
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 8, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchS390X = &Arch{
|
var ArchS390X = &Arch{
|
||||||
Name: "s390x",
|
Name: "s390x",
|
||||||
Family: S390X,
|
Family: S390X,
|
||||||
ByteOrder: binary.BigEndian,
|
ByteOrder: binary.BigEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 2,
|
MinLC: 2,
|
||||||
Alignment: 1,
|
Alignment: 1,
|
||||||
CanMergeLoads: true,
|
CanMergeLoads: true,
|
||||||
|
HasLR: true,
|
||||||
|
FixedFrameSize: 8, // LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var ArchWasm = &Arch{
|
var ArchWasm = &Arch{
|
||||||
Name: "wasm",
|
Name: "wasm",
|
||||||
Family: Wasm,
|
Family: Wasm,
|
||||||
ByteOrder: binary.LittleEndian,
|
ByteOrder: binary.LittleEndian,
|
||||||
PtrSize: 8,
|
PtrSize: 8,
|
||||||
RegSize: 8,
|
RegSize: 8,
|
||||||
MinLC: 1,
|
MinLC: 1,
|
||||||
Alignment: 1,
|
Alignment: 1,
|
||||||
CanMergeLoads: false,
|
CanMergeLoads: false,
|
||||||
|
HasLR: false,
|
||||||
|
FixedFrameSize: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var Archs = [...]*Arch{
|
var Archs = [...]*Arch{
|
||||||
|
@ -1360,7 +1360,7 @@ func (d *dwctxt) writeframes(fs loader.Sym) dwarfSecInfo {
|
|||||||
fsu := d.ldr.MakeSymbolUpdater(fs)
|
fsu := d.ldr.MakeSymbolUpdater(fs)
|
||||||
fsu.SetType(sym.SDWARFSECT)
|
fsu.SetType(sym.SDWARFSECT)
|
||||||
isdw64 := isDwarf64(d.linkctxt)
|
isdw64 := isDwarf64(d.linkctxt)
|
||||||
haslr := haslinkregister(d.linkctxt)
|
haslr := d.linkctxt.Arch.HasLR
|
||||||
|
|
||||||
// Length field is 4 bytes on Dwarf32 and 12 bytes on Dwarf64
|
// Length field is 4 bytes on Dwarf32 and 12 bytes on Dwarf64
|
||||||
lengthFieldSize := int64(4)
|
lengthFieldSize := int64(4)
|
||||||
|
@ -2349,12 +2349,8 @@ type chain struct {
|
|||||||
limit int // limit on entry to sym
|
limit int // limit on entry to sym
|
||||||
}
|
}
|
||||||
|
|
||||||
func haslinkregister(ctxt *Link) bool {
|
|
||||||
return ctxt.FixedFrameSize() != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func callsize(ctxt *Link) int {
|
func callsize(ctxt *Link) int {
|
||||||
if haslinkregister(ctxt) {
|
if ctxt.Arch.HasLR {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return ctxt.Arch.RegSize
|
return ctxt.Arch.RegSize
|
||||||
@ -2554,7 +2550,7 @@ func (sc *stkChk) print(ch *chain, limit int) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sc.print(ch.up, ch.limit+callsize(ctxt))
|
sc.print(ch.up, ch.limit+callsize(ctxt))
|
||||||
if !haslinkregister(ctxt) {
|
if !ctxt.Arch.HasLR {
|
||||||
fmt.Printf("\t%d\ton entry to %s\n", ch.limit, name)
|
fmt.Printf("\t%d\ton entry to %s\n", ch.limit, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ package ld
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"cmd/internal/objabi"
|
"cmd/internal/objabi"
|
||||||
"cmd/internal/sys"
|
|
||||||
"cmd/link/internal/loader"
|
"cmd/link/internal/loader"
|
||||||
"cmd/link/internal/sym"
|
"cmd/link/internal/sym"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
@ -108,16 +107,7 @@ type cgodata struct {
|
|||||||
// on the stack in the function prologue and so always have a pointer between
|
// on the stack in the function prologue and so always have a pointer between
|
||||||
// the hardware stack pointer and the local variable area.
|
// the hardware stack pointer and the local variable area.
|
||||||
func (ctxt *Link) FixedFrameSize() int64 {
|
func (ctxt *Link) FixedFrameSize() int64 {
|
||||||
switch ctxt.Arch.Family {
|
return ctxt.Arch.FixedFrameSize
|
||||||
case sys.AMD64, sys.I386:
|
|
||||||
return 0
|
|
||||||
case sys.PPC64:
|
|
||||||
// PIC code on ppc64le requires 32 bytes of stack, and it's easier to
|
|
||||||
// just use that much stack always on ppc64x.
|
|
||||||
return int64(4 * ctxt.Arch.PtrSize)
|
|
||||||
default:
|
|
||||||
return int64(ctxt.Arch.PtrSize)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctxt *Link) Logf(format string, args ...interface{}) {
|
func (ctxt *Link) Logf(format string, args ...interface{}) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user