Skip to content

Commit cc4957a

Browse files
XiaodongLoonggopherbot
authored andcommitted
cmd/link: support linker for linux/loong64
The basic arch-specific hooks are implemented, which are used for internal and external linker. Contributors to the loong64 port are: Weining Lu <[email protected]> Lei Wang <[email protected]> Lingqin Gong <[email protected]> Xiaolin Zhao <[email protected]> Meidan Li <[email protected]> Xiaojuan Zhai <[email protected]> Qiyuan Pu <[email protected]> Guoqi Chen <[email protected]> This port has been updated to Go 1.15.6: https://github.com/loongson/go Updates #46229 Change-Id: I4680eb0635dd0fa3d6ea8348a2488da9c7e33d3b Reviewed-on: https://go-review.googlesource.com/c/go/+/349514 Reviewed-by: Cherry Mui <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]>
1 parent 770e0e5 commit cc4957a

File tree

12 files changed

+351
-4
lines changed

12 files changed

+351
-4
lines changed

src/cmd/link/internal/ld/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) {
199199

200200
// Internally linking cgo is incomplete on some architectures.
201201
// https://golang.org/issue/14449
202-
if iscgo && ctxt.Arch.InFamily(sys.MIPS64, sys.MIPS, sys.RISCV64) {
202+
if iscgo && ctxt.Arch.InFamily(sys.Loong64, sys.MIPS64, sys.MIPS, sys.RISCV64) {
203203
return true, buildcfg.GOARCH + " does not support internal cgo"
204204
}
205205
if iscgo && (buildcfg.GOOS == "android" || buildcfg.GOOS == "dragonfly") {

src/cmd/link/internal/ld/elf.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ we write section and prog headers.
208208
func Elfinit(ctxt *Link) {
209209
ctxt.IsELF = true
210210

211-
if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) {
211+
if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) {
212212
elfRelType = ".rela"
213213
} else {
214214
elfRelType = ".rel"
@@ -223,10 +223,13 @@ func Elfinit(ctxt *Link) {
223223
ehdr.Flags = 2 /* Version 2 ABI */
224224
}
225225
fallthrough
226-
case sys.AMD64, sys.ARM64, sys.MIPS64, sys.RISCV64:
226+
case sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.RISCV64:
227227
if ctxt.Arch.Family == sys.MIPS64 {
228228
ehdr.Flags = 0x20000004 /* MIPS 3 CPIC */
229229
}
230+
if ctxt.Arch.Family == sys.Loong64 {
231+
ehdr.Flags = 0x3 /* LoongArch lp64d */
232+
}
230233
if ctxt.Arch.Family == sys.RISCV64 {
231234
ehdr.Flags = 0x4 /* RISCV Float ABI Double */
232235
}
@@ -1655,6 +1658,8 @@ func asmbElf(ctxt *Link) {
16551658
Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family)
16561659
case sys.MIPS, sys.MIPS64:
16571660
eh.Machine = uint16(elf.EM_MIPS)
1661+
case sys.Loong64:
1662+
eh.Machine = uint16(elf.EM_LOONGARCH)
16581663
case sys.ARM:
16591664
eh.Machine = uint16(elf.EM_ARM)
16601665
case sys.AMD64:

src/cmd/link/internal/ld/lib.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,8 @@ func hostlinkArchArgs(arch *sys.Arch) []string {
18991899
if buildcfg.GOOS == "darwin" {
19001900
return []string{"-arch", "arm64"}
19011901
}
1902+
case sys.Loong64:
1903+
return []string{"-mabi=lp64d"}
19021904
case sys.MIPS64:
19031905
return []string{"-mabi=64"}
19041906
case sys.MIPS:

src/cmd/link/internal/ld/pcln.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func computeDeferReturn(ctxt *Link, deferReturnSym, s loader.Sym) uint32 {
132132
switch target.Arch.Family {
133133
case sys.AMD64, sys.I386:
134134
deferreturn--
135-
case sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64:
135+
case sys.ARM, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64:
136136
// no change
137137
case sys.S390X:
138138
deferreturn -= 2

src/cmd/link/internal/ld/target.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ func (t *Target) IsMIPS64() bool {
112112
return t.Arch.Family == sys.MIPS64
113113
}
114114

115+
func (t *Target) IsLOONG64() bool {
116+
return t.Arch.Family == sys.Loong64
117+
}
118+
115119
func (t *Target) IsPPC64() bool {
116120
return t.Arch.Family == sys.PPC64
117121
}

src/cmd/link/internal/loadelf/ldelf.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader,
346346
if mach != elf.EM_MIPS || class != elf.ELFCLASS64 {
347347
return errorf("elf object but not mips64")
348348
}
349+
case sys.Loong64:
350+
if mach != elf.EM_LOONGARCH || class != elf.ELFCLASS64 {
351+
return errorf("elf object but not loong64")
352+
}
349353

350354
case sys.ARM:
351355
if e != binary.LittleEndian || mach != elf.EM_ARM || class != elf.ELFCLASS32 {
@@ -956,6 +960,7 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
956960
ARM = uint32(sys.ARM)
957961
ARM64 = uint32(sys.ARM64)
958962
I386 = uint32(sys.I386)
963+
LOONG64 = uint32(sys.Loong64)
959964
MIPS = uint32(sys.MIPS)
960965
MIPS64 = uint32(sys.MIPS64)
961966
PPC64 = uint32(sys.PPC64)
@@ -991,6 +996,15 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
991996
MIPS64 | uint32(elf.R_MIPS_GOT_DISP)<<16:
992997
return 4, 4, nil
993998

999+
case LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_PCREL)<<16,
1000+
LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_GPREL)<<16,
1001+
LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_ABSOLUTE)<<16,
1002+
LOONG64 | uint32(elf.R_LARCH_MARK_LA)<<16,
1003+
LOONG64 | uint32(elf.R_LARCH_SOP_POP_32_S_0_10_10_16_S2)<<16,
1004+
LOONG64 | uint32(elf.R_LARCH_64)<<16,
1005+
LOONG64 | uint32(elf.R_LARCH_MARK_PCREL)<<16:
1006+
return 4, 4, nil
1007+
9941008
case S390X | uint32(elf.R_390_8)<<16:
9951009
return 1, 1, nil
9961010

src/cmd/link/internal/loong64/asm.go

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package loong64
6+
7+
import (
8+
"cmd/internal/objabi"
9+
"cmd/internal/sys"
10+
"cmd/link/internal/ld"
11+
"cmd/link/internal/loader"
12+
"cmd/link/internal/sym"
13+
"debug/elf"
14+
"log"
15+
)
16+
17+
func gentext(ctxt *ld.Link, ldr *loader.Loader) {}
18+
19+
func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
20+
log.Fatalf("adddynrel not implemented")
21+
return false
22+
}
23+
24+
func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
25+
// loong64 ELF relocation (endian neutral)
26+
// offset uint64
27+
// symreloc uint64 // The high 32-bit is the symbol, the low 32-bit is the relocation type.
28+
// addend int64
29+
30+
elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
31+
switch r.Type {
32+
default:
33+
return false
34+
case objabi.R_ADDR, objabi.R_DWARFSECREF:
35+
switch r.Size {
36+
case 4:
37+
out.Write64(uint64(sectoff))
38+
out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32)
39+
out.Write64(uint64(r.Xadd))
40+
case 8:
41+
out.Write64(uint64(sectoff))
42+
out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32)
43+
out.Write64(uint64(r.Xadd))
44+
default:
45+
return false
46+
}
47+
case objabi.R_ADDRLOONG64TLS:
48+
out.Write64(uint64(sectoff))
49+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_TLS_TPREL) | uint64(elfsym)<<32)
50+
out.Write64(uint64(r.Xadd))
51+
52+
out.Write64(uint64(sectoff))
53+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
54+
out.Write64(uint64(0xfff))
55+
56+
out.Write64(uint64(sectoff))
57+
out.Write64(uint64(elf.R_LARCH_SOP_AND))
58+
out.Write64(uint64(0x0))
59+
60+
out.Write64(uint64(sectoff))
61+
out.Write64(uint64(elf.R_LARCH_SOP_POP_32_U_10_12))
62+
out.Write64(uint64(0x0))
63+
64+
case objabi.R_ADDRLOONG64TLSU:
65+
out.Write64(uint64(sectoff))
66+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_TLS_TPREL) | uint64(elfsym)<<32)
67+
out.Write64(uint64(r.Xadd))
68+
69+
out.Write64(uint64(sectoff))
70+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
71+
out.Write64(uint64(0xc))
72+
73+
out.Write64(uint64(sectoff))
74+
out.Write64(uint64(elf.R_LARCH_SOP_SR))
75+
out.Write64(uint64(0x0))
76+
77+
out.Write64(uint64(sectoff))
78+
out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_5_20) | uint64(0)<<32)
79+
out.Write64(uint64(0x0))
80+
81+
case objabi.R_CALLLOONG64:
82+
out.Write64(uint64(sectoff))
83+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PLT_PCREL) | uint64(elfsym)<<32)
84+
out.Write64(uint64(r.Xadd))
85+
86+
out.Write64(uint64(sectoff))
87+
out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_0_10_10_16_S2))
88+
out.Write64(uint64(0x0))
89+
// The pcaddu12i + addi.d instructions is used to obtain address of a symbol on Loong64.
90+
// The low 12-bit of the symbol address need to be added. The addi.d instruction have
91+
// signed 12-bit immediate operand. The 0x800 (addr+U12 <=> addr+0x800+S12) is introduced
92+
// to do sign extending from 12 bits. The 0x804 is 0x800 + 4, 4 is instruction bit
93+
// width on Loong64 and is used to correct the PC of the addi.d instruction.
94+
case objabi.R_ADDRLOONG64:
95+
out.Write64(uint64(sectoff))
96+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32)
97+
out.Write64(uint64(r.Xadd + 0x4))
98+
99+
out.Write64(uint64(sectoff))
100+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32)
101+
out.Write64(uint64(r.Xadd + 0x804))
102+
103+
out.Write64(uint64(sectoff))
104+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
105+
out.Write64(uint64(0xc))
106+
107+
out.Write64(uint64(sectoff))
108+
out.Write64(uint64(elf.R_LARCH_SOP_SR))
109+
out.Write64(uint64(0x0))
110+
111+
out.Write64(uint64(sectoff))
112+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
113+
out.Write64(uint64(0xc))
114+
115+
out.Write64(uint64(sectoff))
116+
out.Write64(uint64(elf.R_LARCH_SOP_SL))
117+
out.Write64(uint64(0x0))
118+
119+
out.Write64(uint64(sectoff))
120+
out.Write64(uint64(elf.R_LARCH_SOP_SUB))
121+
out.Write64(uint64(0x0))
122+
123+
out.Write64(uint64(sectoff))
124+
out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_10_12))
125+
out.Write64(uint64(0x0))
126+
127+
case objabi.R_ADDRLOONG64U:
128+
out.Write64(uint64(sectoff))
129+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_PCREL) | uint64(elfsym)<<32)
130+
out.Write64(uint64(r.Xadd + 0x800))
131+
132+
out.Write64(uint64(sectoff))
133+
out.Write64(uint64(elf.R_LARCH_SOP_PUSH_ABSOLUTE))
134+
out.Write64(uint64(0xc))
135+
136+
out.Write64(uint64(sectoff))
137+
out.Write64(uint64(elf.R_LARCH_SOP_SR))
138+
out.Write64(uint64(0x0))
139+
140+
out.Write64(uint64(sectoff))
141+
out.Write64(uint64(elf.R_LARCH_SOP_POP_32_S_5_20) | uint64(0)<<32)
142+
out.Write64(uint64(0x0))
143+
}
144+
145+
return true
146+
}
147+
148+
func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
149+
return
150+
}
151+
152+
func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
153+
return false
154+
}
155+
156+
func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
157+
rs := r.Sym()
158+
if target.IsExternal() {
159+
nExtReloc := 0
160+
switch r.Type() {
161+
default:
162+
return val, 0, false
163+
case objabi.R_ADDRLOONG64,
164+
objabi.R_ADDRLOONG64U:
165+
// set up addend for eventual relocation via outer symbol.
166+
rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
167+
rst := ldr.SymType(rs)
168+
if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
169+
ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
170+
}
171+
nExtReloc = 8 // need 8 ELF relocations. see elfreloc1
172+
if r.Type() == objabi.R_ADDRLOONG64U {
173+
nExtReloc = 4
174+
}
175+
return val, nExtReloc, true
176+
case objabi.R_ADDRLOONG64TLS,
177+
objabi.R_ADDRLOONG64TLSU,
178+
objabi.R_CALLLOONG64,
179+
objabi.R_JMPLOONG64:
180+
nExtReloc = 4
181+
if r.Type() == objabi.R_CALLLOONG64 || r.Type() == objabi.R_JMPLOONG64 {
182+
nExtReloc = 2
183+
}
184+
return val, nExtReloc, true
185+
}
186+
}
187+
188+
const isOk = true
189+
const noExtReloc = 0
190+
191+
switch r.Type() {
192+
case objabi.R_CONST:
193+
return r.Add(), noExtReloc, isOk
194+
case objabi.R_GOTOFF:
195+
return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk
196+
case objabi.R_ADDRLOONG64,
197+
objabi.R_ADDRLOONG64U:
198+
pc := ldr.SymValue(s) + int64(r.Off())
199+
t := ldr.SymAddr(rs) + r.Add() - pc
200+
if r.Type() == objabi.R_ADDRLOONG64 {
201+
return int64(val&0xffc003ff | (((t + 4 - ((t + 4 + 1<<11) >> 12 << 12)) << 10) & 0x3ffc00)), noExtReloc, isOk
202+
}
203+
return int64(val&0xfe00001f | (((t + 1<<11) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk
204+
case objabi.R_ADDRLOONG64TLS,
205+
objabi.R_ADDRLOONG64TLSU:
206+
t := ldr.SymAddr(rs) + r.Add()
207+
if r.Type() == objabi.R_ADDRLOONG64TLS {
208+
return int64(val&0xffc003ff | ((t & 0xfff) << 10)), noExtReloc, isOk
209+
}
210+
return int64(val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk
211+
case objabi.R_CALLLOONG64,
212+
objabi.R_JMPLOONG64:
213+
pc := ldr.SymValue(s) + int64(r.Off())
214+
t := ldr.SymAddr(rs) + r.Add() - pc
215+
return int64(val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16)), noExtReloc, isOk
216+
}
217+
218+
return val, 0, false
219+
}
220+
221+
func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
222+
return -1
223+
}
224+
225+
func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
226+
switch r.Type() {
227+
case objabi.R_ADDRLOONG64,
228+
objabi.R_ADDRLOONG64U:
229+
return ld.ExtrelocViaOuterSym(ldr, r, s), true
230+
231+
case objabi.R_ADDRLOONG64TLS,
232+
objabi.R_ADDRLOONG64TLSU,
233+
objabi.R_CONST,
234+
objabi.R_GOTOFF,
235+
objabi.R_CALLLOONG64,
236+
objabi.R_JMPLOONG64:
237+
return ld.ExtrelocSimple(ldr, r), true
238+
}
239+
return loader.ExtReloc{}, false
240+
}

src/cmd/link/internal/loong64/l.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package loong64
6+
7+
const (
8+
maxAlign = 32 // max data alignment
9+
minAlign = 1 // min data alignment
10+
funcAlign = 8
11+
)
12+
13+
/* Used by ../../internal/ld/dwarf.go */
14+
const (
15+
dwarfRegSP = 3
16+
dwarfRegLR = 1
17+
)

0 commit comments

Comments
 (0)