diff options
| author | Meng Zhuo <mengzhuo1203@gmail.com> | 2024-09-12 20:15:56 +0800 |
|---|---|---|
| committer | Meng Zhuo <mengzhuo@iscas.ac.cn> | 2025-02-19 17:54:34 -0800 |
| commit | cdc95607940b2acb66cb184dec08d4cc8a469042 (patch) | |
| tree | ba916b940165a00c7b47299369328213bcd10652 /src/cmd/internal | |
| parent | 58083b57d4f8047d2749196a09b366926e8698da (diff) | |
| download | go-cdc95607940b2acb66cb184dec08d4cc8a469042.tar.xz | |
all: implement plugin build mode for riscv64
Change-Id: I8d7bbeebbf4a46f2fd8d630b1edbaf79b8ffccc5
Reviewed-on: https://go-review.googlesource.com/c/go/+/420114
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Joel Sing <joel@sing.id.au>
TryBot-Bypass: Joel Sing <joel@sing.id.au>
Diffstat (limited to 'src/cmd/internal')
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 3a4ab556f7..c41d99c0c7 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -157,6 +157,127 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { p.From.Offset = 0 } } + + if ctxt.Flag_dynlink { + rewriteToUseGot(ctxt, p, newprog) + } +} + +// Rewrite p, if necessary, to access global data via the global offset table. +func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { + if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO { + // ADUFFxxx $offset + // becomes + // MOV runtime.duffxxx@GOT, REG_TMP + // ADD $offset, REG_TMP + // CALL REG_TMP + var sym *obj.LSym + if p.As == obj.ADUFFCOPY { + sym = ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal) + } else { + sym = ctxt.LookupABI("runtime.duffzero", obj.ABIInternal) + } + offset := p.To.Offset + p.As = AMOV + p.From.Type = obj.TYPE_MEM + p.From.Name = obj.NAME_GOTREF + p.From.Sym = sym + p.To.Type = obj.TYPE_REG + p.To.Reg = REG_TMP + p.To.Name = obj.NAME_NONE + p.To.Offset = 0 + p.To.Sym = nil + + p1 := obj.Appendp(p, newprog) + p1.As = AADD + p1.From.Type = obj.TYPE_CONST + p1.From.Offset = offset + p1.To.Type = obj.TYPE_REG + p1.To.Reg = REG_TMP + + p2 := obj.Appendp(p1, newprog) + p2.As = obj.ACALL + p2.To.Type = obj.TYPE_REG + p2.To.Reg = REG_TMP + } + + // We only care about global data: NAME_EXTERN means a global + // symbol in the Go sense and p.Sym.Local is true for a few internally + // defined symbols. + if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { + // MOV $sym, Rx becomes MOV sym@GOT, Rx + // MOV $sym+<off>, Rx becomes MOV sym@GOT, Rx; ADD <off>, Rx + if p.As != AMOV { + ctxt.Diag("don't know how to handle TYPE_ADDR in %v with -dynlink", p) + } + if p.To.Type != obj.TYPE_REG { + ctxt.Diag("don't know how to handle LD instruction to non-register in %v with -dynlink", p) + } + p.From.Type = obj.TYPE_MEM + p.From.Name = obj.NAME_GOTREF + if p.From.Offset != 0 { + q := obj.Appendp(p, newprog) + q.As = AADD + q.From.Type = obj.TYPE_CONST + q.From.Offset = p.From.Offset + q.To = p.To + p.From.Offset = 0 + } + + } + + if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN { + ctxt.Diag("don't know how to handle %v with -dynlink", p) + } + + var source *obj.Addr + // MOVx sym, Ry becomes MOV sym@GOT, X31; MOVx (X31), Ry + // MOVx Ry, sym becomes MOV sym@GOT, X31; MOV Ry, (X31) + // An addition may be inserted between the two MOVs if there is an offset. + if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { + if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { + ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) + } + source = &p.From + } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { + source = &p.To + } else { + return + } + if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP { + return + } + if source.Sym.Type == objabi.STLSBSS { + return + } + if source.Type != obj.TYPE_MEM { + ctxt.Diag("don't know how to handle %v with -dynlink", p) + } + p1 := obj.Appendp(p, newprog) + p1.As = AMOV + p1.From.Type = obj.TYPE_MEM + p1.From.Sym = source.Sym + p1.From.Name = obj.NAME_GOTREF + p1.To.Type = obj.TYPE_REG + p1.To.Reg = REG_TMP + + p2 := obj.Appendp(p1, newprog) + p2.As = p.As + p2.From = p.From + p2.To = p.To + if p.From.Name == obj.NAME_EXTERN { + p2.From.Reg = REG_TMP + p2.From.Name = obj.NAME_NONE + p2.From.Sym = nil + } else if p.To.Name == obj.NAME_EXTERN { + p2.To.Reg = REG_TMP + p2.To.Name = obj.NAME_NONE + p2.To.Sym = nil + } else { + return + } + obj.Nopout(p) + } // addrToReg extracts the register from an Addr, handling special Addr.Names. |
