aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
authorJoel Sing <joel@sing.id.au>2022-09-16 02:29:12 +1000
committerJoel Sing <joel@sing.id.au>2023-08-03 16:15:14 +0000
commit9ff01162295c815c252dec812f6ce983aa90a62b (patch)
tree5d0f0eb023841479264959471b96fb7a59dee431 /src/cmd/internal/obj
parentb7c826d2c4576dbe04a79ab7d0dfa03c722c0ab9 (diff)
downloadgo-9ff01162295c815c252dec812f6ce983aa90a62b.tar.xz
cmd/asm,cmd/internal/obj/riscv,cmd/link: improve TLS handling on riscv64
The existing Thread Local Storage (TLS) implementation for riscv64 uses initial-exec (IE) mode, however a MOV of a TLS symbol currently loads the thread pointer offset and not the actual address or memory location. Rework TLS on riscv64 to generate the full instruction sequence needed to load from or store to a TLS symbol. Additionally, provide support for both initial-exec (IE) and local-exec (LE) TLS - in many cases we can use LE, which is slightly more efficient and easier to support in the linker. Change-Id: I1b43f8888b3b6b10354bbb79d604771e64d92645 Reviewed-on: https://go-review.googlesource.com/c/go/+/431103 Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: M Zhuo <mzh@golangcn.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Joel Sing <joel@sing.id.au>
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/riscv/obj.go63
1 files changed, 59 insertions, 4 deletions
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 43fa7351bf..2e55fac812 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -1827,6 +1827,53 @@ func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
return []*instruction{insLUI, insADD, ins}
}
+func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
+ insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
+
+ var inss []*instruction
+ if p.Ctxt.Flag_shared {
+ // TLS initial-exec mode - load TLS offset from GOT, add the thread pointer
+ // register, then load from or store to the resulting memory location.
+ insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
+ insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
+ inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
+ } else {
+ // TLS local-exec mode - load upper TLS offset, add the lower TLS offset,
+ // add the thread pointer register, then load from or store to the resulting
+ // memory location. Note that this differs from the suggested three
+ // instruction sequence, as the Go linker does not currently have an
+ // easy way to handle relocation across 12 bytes of machine code.
+ insLUI := &instruction{as: ALUI, rd: REG_TMP}
+ insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
+ inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
+ }
+ return inss
+}
+
+func instructionsForTLSLoad(p *obj.Prog) []*instruction {
+ if p.From.Sym.Type != objabi.STLSBSS {
+ p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
+ return nil
+ }
+
+ ins := instructionForProg(p)
+ ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
+
+ return instructionsForTLS(p, ins)
+}
+
+func instructionsForTLSStore(p *obj.Prog) []*instruction {
+ if p.To.Sym.Type != objabi.STLSBSS {
+ p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
+ return nil
+ }
+
+ ins := instructionForProg(p)
+ ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
+
+ return instructionsForTLS(p, ins)
+}
+
// instructionsForMOV returns the machine instructions for an *obj.Prog that
// uses a MOV pseudo-instruction.
func instructionsForMOV(p *obj.Prog) []*instruction {
@@ -1939,6 +1986,10 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
case obj.NAME_EXTERN, obj.NAME_STATIC:
+ if p.From.Sym.Type == objabi.STLSBSS {
+ return instructionsForTLSLoad(p)
+ }
+
// Note that the values for $off_hi and $off_lo are currently
// zero and will be assigned during relocation.
//
@@ -1966,6 +2017,10 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
case obj.NAME_EXTERN, obj.NAME_STATIC:
+ if p.To.Sym.Type == objabi.STLSBSS {
+ return instructionsForTLSStore(p)
+ }
+
// Note that the values for $off_hi and $off_lo are currently
// zero and will be assigned during relocation.
//
@@ -2244,10 +2299,10 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
break
}
if addr.Sym.Type == objabi.STLSBSS {
- if rt == objabi.R_RISCV_PCREL_ITYPE {
- rt = objabi.R_RISCV_TLS_IE_ITYPE
- } else if rt == objabi.R_RISCV_PCREL_STYPE {
- rt = objabi.R_RISCV_TLS_IE_STYPE
+ if ctxt.Flag_shared {
+ rt = objabi.R_RISCV_TLS_IE
+ } else {
+ rt = objabi.R_RISCV_TLS_LE
}
}