Handle TOC offsets by giving them to the linker.
An offset > 2^15 would exceed the range of an addi immediate on ppc64le. Thus, rather than add the offset after loading the TOC reference, have different tocloader functions for each (symbol, offset) pair. In this case, the linker can handle large offsets by changing the value of foo+offset@toc@ha accordingly. Change-Id: Iac1481bccaf55fb0c2b080eedebaf11befdae465 Reviewed-on: https://boringssl-review.googlesource.com/16784 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
parent
733f46e84f
commit
cd334a54ca
@ -479,13 +479,27 @@ func establishTOC(w stringWriter) {
|
||||
}
|
||||
|
||||
// loadTOCFuncName returns the name of a synthesized function that sets r3 to
|
||||
// the value of “symbol”.
|
||||
func loadTOCFuncName(symbol string) string {
|
||||
return ".Lbcm_loadtoc_" + strings.Replace(symbol, ".", "_dot_", -1)
|
||||
// the value of “symbol+offset”.
|
||||
func loadTOCFuncName(symbol, offset string) string {
|
||||
ret := ".Lbcm_loadtoc_" + strings.Replace(symbol, ".", "_dot_", -1)
|
||||
switch {
|
||||
case len(offset) == 0:
|
||||
break
|
||||
case offset[0] == '+':
|
||||
ret += "__plus_" + offset[1:]
|
||||
case offset[0] == '-':
|
||||
ret += "__minus_" + offset[1:]
|
||||
default:
|
||||
// parseMemRef will prepend a plus to bare offsets.
|
||||
panic("bad offset: " + offset)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (d *delocation) loadFromTOC(w stringWriter, symbol, dest string) wrapperFunc {
|
||||
d.tocLoaders[symbol] = struct{}{}
|
||||
func (d *delocation) loadFromTOC(w stringWriter, symbol, offset, dest string) wrapperFunc {
|
||||
d.tocLoaders[symbol + "\x00" + offset] = struct{}{}
|
||||
|
||||
return func(k func()) {
|
||||
w.WriteString("\taddi 1, 1, -288\n") // Clear the red zone.
|
||||
w.WriteString("\tmflr " + dest + "\n") // Stash the link register.
|
||||
@ -497,7 +511,7 @@ func (d *delocation) loadFromTOC(w stringWriter, symbol, dest string) wrapperFun
|
||||
|
||||
// Because loadTOCFuncName returns a “.L” name, we don't need a
|
||||
// nop after this call.
|
||||
w.WriteString("\tbl " + loadTOCFuncName(symbol) + "\n")
|
||||
w.WriteString("\tbl " + loadTOCFuncName(symbol, offset) + "\n")
|
||||
|
||||
// Cycle registers around. We need r3 -> destReg, -8(1) ->
|
||||
// lr and, optionally, -16(1) -> r3.
|
||||
@ -672,26 +686,20 @@ Args:
|
||||
// destination register is the first argument.
|
||||
destReg := args[0]
|
||||
|
||||
wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, destReg))
|
||||
wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, offset, destReg))
|
||||
switch instructionName {
|
||||
case "addi":
|
||||
// The original instruction was:
|
||||
// addi destReg, tocHaReg, offset+symbol@toc@l
|
||||
//
|
||||
// All that is left is adding the offset, if any.
|
||||
instructionName = ""
|
||||
if len(offset) != 0 {
|
||||
wrappers = append(wrappers, func(k func()) {
|
||||
d.output.WriteString("\taddi " + destReg + ", " + destReg + ", " + offset + "\n")
|
||||
})
|
||||
}
|
||||
|
||||
case "ld", "lhz", "lwz":
|
||||
// The original instruction was:
|
||||
// l?? destReg, offset+symbol@toc@l(tocHaReg)
|
||||
//
|
||||
// We transform that into the
|
||||
// equivalent dereference of destReg:
|
||||
// l?? destReg, offset(destReg)
|
||||
// l?? destReg, 0(destReg)
|
||||
origInstructionName := instructionName
|
||||
instructionName = ""
|
||||
|
||||
@ -702,11 +710,7 @@ Args:
|
||||
}
|
||||
|
||||
wrappers = append(wrappers, func(k func()) {
|
||||
fixedOffset := offset
|
||||
if len(fixedOffset) == 0 {
|
||||
fixedOffset = "0"
|
||||
}
|
||||
d.output.WriteString("\t" + origInstructionName + " " + destReg + ", " + fixedOffset + "(" + destReg + ")\n")
|
||||
d.output.WriteString("\t" + origInstructionName + " " + destReg + ", 0(" + destReg + ")\n")
|
||||
})
|
||||
default:
|
||||
return nil, fmt.Errorf("can't process TOC argument to %q", instructionName)
|
||||
@ -1212,14 +1216,18 @@ func transform(w stringWriter, inputs []inputFile) error {
|
||||
|
||||
if d.processor == ppc64le {
|
||||
loadTOCNames := sortedSet(d.tocLoaders)
|
||||
for _, symbol := range loadTOCNames {
|
||||
funcName := loadTOCFuncName(symbol)
|
||||
for _, symbolAndOffset := range loadTOCNames {
|
||||
parts := strings.SplitN(symbolAndOffset, "\x00", 2)
|
||||
symbol, offset := parts[0], parts[1]
|
||||
|
||||
funcName := loadTOCFuncName(symbol, offset)
|
||||
ref := symbol + offset
|
||||
|
||||
w.WriteString(".type " + funcName[2:] + ", @function\n")
|
||||
w.WriteString(funcName[2:] + ":\n")
|
||||
w.WriteString(funcName + ":\n")
|
||||
w.WriteString("\taddis 3, 2, " + symbol + "@toc@ha\n")
|
||||
w.WriteString("\taddi 3, 3, " + symbol + "@toc@l\n")
|
||||
w.WriteString("\taddis 3, 2, " + ref + "@toc@ha\n")
|
||||
w.WriteString("\taddi 3, 3, " + ref + "@toc@l\n")
|
||||
w.WriteString("\tblr\n")
|
||||
}
|
||||
|
||||
|
@ -12,3 +12,6 @@ foo:
|
||||
|
||||
addis 5, 2, 5+foo@toc@ha
|
||||
ld 5, 10+foo@toc@l(5)
|
||||
|
||||
addis 4, 2, foo-10@toc@ha
|
||||
addi 4, 4, foo-10@toc@l
|
||||
|
@ -9,26 +9,24 @@ foo:
|
||||
addi 1, 1, -288
|
||||
mflr 3
|
||||
std 3, -8(1)
|
||||
bl .Lbcm_loadtoc__dot_Lfoo_local_target
|
||||
bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10
|
||||
std 3, -24(1)
|
||||
ld 3, -8(1)
|
||||
mtlr 3
|
||||
ld 3, -24(1)
|
||||
addi 1, 1, 288
|
||||
addi 3, 3, +10
|
||||
|
||||
# WAS addis 3, 2, 15+foo@toc@ha
|
||||
# WAS addi 3, 3, 20+foo@toc@l
|
||||
addi 1, 1, -288
|
||||
mflr 3
|
||||
std 3, -8(1)
|
||||
bl .Lbcm_loadtoc__dot_Lfoo_local_target
|
||||
bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_20
|
||||
std 3, -24(1)
|
||||
ld 3, -8(1)
|
||||
mtlr 3
|
||||
ld 3, -24(1)
|
||||
addi 1, 1, 288
|
||||
addi 3, 3, +20
|
||||
|
||||
# WAS addis 4, 2, foo@toc@ha
|
||||
# WAS addi 4, 4, foo@toc@l
|
||||
@ -50,14 +48,28 @@ foo:
|
||||
mflr 5
|
||||
std 5, -8(1)
|
||||
std 3, -16(1)
|
||||
bl .Lbcm_loadtoc__dot_Lfoo_local_target
|
||||
bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10
|
||||
std 3, -24(1)
|
||||
ld 3, -8(1)
|
||||
mtlr 3
|
||||
ld 5, -24(1)
|
||||
ld 3, -16(1)
|
||||
addi 1, 1, 288
|
||||
ld 5, +10(5)
|
||||
ld 5, 0(5)
|
||||
|
||||
# WAS addis 4, 2, foo-10@toc@ha
|
||||
# WAS addi 4, 4, foo-10@toc@l
|
||||
addi 1, 1, -288
|
||||
mflr 4
|
||||
std 4, -8(1)
|
||||
std 3, -16(1)
|
||||
bl .Lbcm_loadtoc__dot_Lfoo_local_target__minus_10
|
||||
std 3, -24(1)
|
||||
ld 3, -8(1)
|
||||
mtlr 3
|
||||
ld 4, -24(1)
|
||||
ld 3, -16(1)
|
||||
addi 1, 1, 288
|
||||
.text
|
||||
BORINGSSL_bcm_text_end:
|
||||
.type bcm_loadtoc__dot_Lfoo_local_target, @function
|
||||
@ -66,6 +78,24 @@ bcm_loadtoc__dot_Lfoo_local_target:
|
||||
addis 3, 2, .Lfoo_local_target@toc@ha
|
||||
addi 3, 3, .Lfoo_local_target@toc@l
|
||||
blr
|
||||
.type bcm_loadtoc__dot_Lfoo_local_target__plus_10, @function
|
||||
bcm_loadtoc__dot_Lfoo_local_target__plus_10:
|
||||
.Lbcm_loadtoc__dot_Lfoo_local_target__plus_10:
|
||||
addis 3, 2, .Lfoo_local_target+10@toc@ha
|
||||
addi 3, 3, .Lfoo_local_target+10@toc@l
|
||||
blr
|
||||
.type bcm_loadtoc__dot_Lfoo_local_target__plus_20, @function
|
||||
bcm_loadtoc__dot_Lfoo_local_target__plus_20:
|
||||
.Lbcm_loadtoc__dot_Lfoo_local_target__plus_20:
|
||||
addis 3, 2, .Lfoo_local_target+20@toc@ha
|
||||
addi 3, 3, .Lfoo_local_target+20@toc@l
|
||||
blr
|
||||
.type bcm_loadtoc__dot_Lfoo_local_target__minus_10, @function
|
||||
bcm_loadtoc__dot_Lfoo_local_target__minus_10:
|
||||
.Lbcm_loadtoc__dot_Lfoo_local_target__minus_10:
|
||||
addis 3, 2, .Lfoo_local_target-10@toc@ha
|
||||
addi 3, 3, .Lfoo_local_target-10@toc@l
|
||||
blr
|
||||
.LBORINGSSL_external_toc:
|
||||
.quad .TOC.-.LBORINGSSL_external_toc
|
||||
.type BORINGSSL_bcm_text_hash, @object
|
||||
|
Loading…
Reference in New Issue
Block a user