From 4bcc138bc6a4791163c9f2604a9fa44ed4ec8421 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 2 Aug 2022 17:39:11 -0400 Subject: [PATCH] cmd/compile, cmd/link: enable Duff's device on darwin/arm64 Duff's device was disabled on darwin/arm64 because the darwin linker couldn't handle a branch relocation with non-zero addend. This is no longer the case now. The darwin linker can handle it just fine. So enable it. Fixes #54189. Change-Id: Ida7ebafe6eb01db1af5bb8ae60a62491da5eabdf Reviewed-on: https://go-review.googlesource.com/c/go/+/420894 Reviewed-by: Eric Fang Reviewed-by: Than McIntosh Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot --- src/cmd/compile/internal/arm64/ggen.go | 5 +--- src/cmd/compile/internal/ssa/config.go | 1 - src/cmd/link/internal/arm64/asm.go | 34 +++++++++++--------------- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/arm64/ggen.go b/src/cmd/compile/internal/arm64/ggen.go index 89be496461..a681adcb7f 100644 --- a/src/cmd/compile/internal/arm64/ggen.go +++ b/src/cmd/compile/internal/arm64/ggen.go @@ -10,11 +10,8 @@ import ( "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/obj/arm64" - "internal/buildcfg" ) -var darwin = buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" - func padframe(frame int64) int64 { // arm64 requires that the frame size (not counting saved FP&LR) // be 16 bytes aligned. If not, pad it. @@ -32,7 +29,7 @@ func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog for i := int64(0); i < cnt; i += int64(types.PtrSize) { p = pp.Append(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGZERO, 0, obj.TYPE_MEM, arm64.REGSP, 8+off+i) } - } else if cnt <= int64(128*types.PtrSize) && !darwin { // darwin ld64 cannot handle BR26 reloc with non-zero addend + } else if cnt <= int64(128*types.PtrSize) { if cnt%(2*int64(types.PtrSize)) != 0 { p = pp.Append(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGZERO, 0, obj.TYPE_MEM, arm64.REGSP, 8+off) off += int64(types.PtrSize) diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 79b6849e4e..d7a413268b 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -230,7 +230,6 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat boo c.FPReg = framepointerRegARM64 c.LinkReg = linkRegARM64 c.hasGReg = true - c.noDuffDevice = buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" // darwin linker cannot handle BR26 reloc with non-zero addend case "ppc64": c.BigEndian = true fallthrough diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index 9937683a13..42f0e77865 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -539,7 +539,8 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sy v |= ld.MACHO_ARM64_RELOC_UNSIGNED << 28 case objabi.R_CALLARM64: if xadd != 0 { - ldr.Errorf(s, "ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", ldr.SymName(rs), xadd) + out.Write32(uint32(sectoff)) + out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff)) } v |= 1 << 24 // pc-relative bit @@ -719,15 +720,22 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade } return val, nExtReloc, isOk - case objabi.R_CALLARM64, - objabi.R_ARM64_TLS_LE, - objabi.R_ARM64_TLS_IE: + + case objabi.R_CALLARM64: nExtReloc = 1 - if rt == objabi.R_ARM64_TLS_IE { - nExtReloc = 2 // need two ELF relocations. see elfreloc1 + if target.IsDarwin() && r.Add() != 0 { + nExtReloc = 2 // need another relocation for addend } return val, nExtReloc, isOk + case objabi.R_ARM64_TLS_LE: + nExtReloc = 1 + return val, nExtReloc, isOk + + case objabi.R_ARM64_TLS_IE: + nExtReloc = 2 // need two ELF relocations. see elfreloc1 + return val, nExtReloc, isOk + case objabi.R_ADDR: if target.IsWindows() && r.Add() != 0 { if r.Siz() == 8 { @@ -946,20 +954,6 @@ func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sy case objabi.R_ARM64_GOTPCREL, objabi.R_ADDRARM64: rr := ld.ExtrelocViaOuterSym(ldr, r, s) - - // Note: ld64 currently has a bug that any non-zero addend for BR26 relocation - // will make the linking fail because it thinks the code is not PIC even though - // the BR26 relocation should be fully resolved at link time. - // That is the reason why the next if block is disabled. When the bug in ld64 - // is fixed, we can enable this block and also enable duff's device in cmd/7g. - if false && target.IsDarwin() { - // Mach-O wants the addend to be encoded in the instruction - // Note that although Mach-O supports ARM64_RELOC_ADDEND, it - // can only encode 24-bit of signed addend, but the instructions - // supports 33-bit of signed addend, so we always encode the - // addend in place. - rr.Xadd = 0 - } return rr, true case objabi.R_CALLARM64, objabi.R_ARM64_TLS_LE, -- 2.50.0